qt - 使用gstreamer api播放音频文件时遇到问题:应用程序挂起

标签 qt audio gstreamer

我用gstreamer api用c++编写了一个简单的音频播放器应用程序。我关注了Gstreamer Hello world example。这是我的代码:

CMediaPlayer::CMediaPlayer(QString path) 
{
    gst_init(NULL, NULL);
    createElements(path);
}

createElements(QString &path)
    {
            /* Create gstreamer elements */
            m_pipeline  = gst_pipeline_new("audio-player");
            m_fileSource = gst_element_factory_make("filesrc", "file-source");
            m_audioDecoder = gst_element_factory_make("mad", "mp3-decoder");
            m_volume = gst_element_factory_make("volume", "volume-name");
            m_audioConverter = gst_element_factory_make("audioconvert", "audio-converter");
            m_sink = gst_element_factory_make("alsasink", "audio-output");


        if (!m_pipeline || !m_fileSource || !m_audioDecoder || !m_volume || !m_audioConverter || !m_sink) {
            g_printerr ("One or more elements could not be created !! \n");
            return false;
        }
        /* Set up the pipeline */
        else {
            /* set a message handler on a bus */
            GstBus *bus = gst_pipeline_get_bus (GST_PIPELINE (m_pipeline));
            gst_bus_add_watch(bus, bus_call, m_loop);
            gst_object_unref(bus);

            g_object_set (G_OBJECT (m_fileSource), "location", path.toLatin1().data(), NULL);

            /* add all elements into the pipeline */
            gst_bin_add_many (GST_BIN (m_pipeline), m_fileSource, m_audioDecoder, m_volume, m_audioConverter, m_sink, NULL);

            /* link the elements together */
            if(!gst_element_link_many (m_fileSource, m_audioDecoder, NULL)) {
                g_printerr("ERROR: Failed to link file-source and audio-decoder !! \n");
                return false;
            }
            if(!gst_element_link_many (m_audioDecoder, m_volume, NULL)) {
                g_printerr("ERROR: Failed to link audio-decoder and volume !! \n");
                return false;
            }
            if(!gst_element_link_many (m_volume, m_audioConverter, NULL)) {
                g_printerr("ERROR: Failed to link audio-decoder and audio-converter !! \n");
                return false;
            }
            if(!gst_element_link_many (m_audioConverter, m_sink, NULL)) {
                g_printerr("ERROR: Failed to link audio-converter and sink !! \n");
                return false;
            }
        }

    /* Prepare the pipeline */
    gst_element_set_state(m_pipeline, GST_STATE_READY);
    gst_element_set_state(m_pipeline, GST_STATE_PAUSED);

}

bus_call(GstBus *bus, GstMessage *msg, gpointer data) {

    CMediaPlayer *ptr = (CMediaPlayer*)(data);
    switch(GST_MESSAGE_TYPE(msg))
    {
        case GST_MESSAGE_EOS:
            // Reset the position of the stream
            gst_element_set_state (ptr->m_pipeline, GST_STATE_READY);
            gst_element_set_state (ptr->m_pipeline, GST_STATE_PAUSED);
            g_message("GST_MESSAGE_EOS \n");
            break;

        case GST_MESSAGE_ERROR:
            gchar  *debug;
            GError *error;

            gst_message_parse_error (msg, &error, &debug);
            g_free (debug);

            g_printerr ("ERROR: %s\n", error->message);
            g_error_free (error);
            break;
        default:
            g_message("default \n");
            break;
    }
    bus = bus; // prevent "unused" warning
    return TRUE;
}

slot_play() {
    m_gstReturnValue = gst_element_set_state (m_pipeline, GST_STATE_PLAYING);
    if(m_gstReturnValue == GST_STATE_CHANGE_FAILURE)
    {
        g_printerr("ERROR: Cannot play !! \n");
    }
}

slot_pause() {
    m_gstReturnValue = gst_element_set_state (m_pipeline, GST_STATE_PAUSED);
    if(m_gstReturnValue == GST_STATE_CHANGE_FAILURE)
    {
        g_printerr("ERROR: Cannot pause !! \n");
    }
}

slot_stop() {
    m_gstReturnValue = gst_element_set_state (m_pipeline, GST_STATE_READY);
    m_gstReturnValue = gst_element_set_state (m_pipeline, GST_STATE_PAUSED);
    if(m_gstReturnValue == GST_STATE_CHANGE_FAILURE)
    {
        g_printerr("ERROR: Cannot stop !! \n");
    }
}

slot_setVolume(int vol_i) {
    vol_i = (vol_i > 10) ? 10 : (vol_i < 0) ? 0 : vol_i;
    g_object_set(G_OBJECT(m_volume), "volume", (gdouble(vol_i)/10), NULL);
}

当我运行该应用程序时,它的行为很奇怪。有时会播放,有时则不会。这是不播放的信息:
0:01:12.000176325 31988   0x5e3000 INFO               GST_EVENT gstevent.c:1244:gst_event_new_latency: creating latency event 0:00:00.000000000
0:01:12.000953562 31988   0x5e3000 INFO                     bin gstbin.c:2502:gst_bin_do_latency_func:<audio-player> configured latency of 0:00:00.000000000
0:01:12.001444706 31988   0x5e3000 INFO              GST_STATES gstbin.c:2230:gst_bin_element_set_state:<audio-output> current PAUSED pending VOID_PENDING, desired next PLAYING
0:01:12.004258709 31988   0x5e3000 INFO              GST_STATES gstelement.c:2328:gst_element_continue_state:<audio-output> completed state change to PLAYING
0:01:12.004433239 31988   0x5e3000 INFO              GST_STATES gstelement.c:2233:_priv_gst_element_state_changed:<audio-output> notifying about state-changed PAUSED to PLAYING (VOID_PENDING pending)
0:01:12.004624124 31988   0x5e3000 INFO              GST_STATES gstbin.c:2673:gst_bin_change_state_func:<audio-player> child 'audio-output' changed state to 4(PLAYING) successfully
0:01:12.004783134 31988   0x5e3000 INFO              GST_STATES gstbin.c:2230:gst_bin_element_set_state:<audio-converter> current PAUSED pending VOID_PENDING, desired next PLAYING
0:01:12.004904644 31988   0x5e3000 INFO              GST_STATES gstelement.c:2328:gst_element_continue_state:<audio-converter> completed state change to PLAYING
0:01:12.004990634 31988   0x5e3000 INFO              GST_STATES gstelement.c:2233:_priv_gst_element_state_changed:<audio-converter> notifying about state-changed PAUSED to PLAYING (VOID_PENDING pending)
0:01:12.005134540 31988   0x5e3000 INFO              GST_STATES gstbin.c:2673:gst_bin_change_state_func:<audio-player> child 'audio-converter' changed state to 4(PLAYING) successfully
0:01:12.005267925 31988   0x5e3000 INFO              GST_STATES gstbin.c:2230:gst_bin_element_set_state:<volume-name> current PAUSED pending VOID_PENDING, desired next PLAYING
0:01:12.005386310 31988   0x5e3000 INFO              GST_STATES gstelement.c:2328:gst_element_continue_state:<volume-name> completed state change to PLAYING
0:01:12.005483653 31988   0x5e3000 INFO              GST_STATES gstelement.c:2233:_priv_gst_element_state_changed:<volume-name> notifying about state-changed PAUSED to PLAYING (VOID_PENDING pending)
0:01:12.005634851 31988   0x5e3000 INFO              GST_STATES gstbin.c:2673:gst_bin_change_state_func:<audio-player> child 'volume-name' changed state to 4(PLAYING) successfully
0:01:12.005785006 31988   0x5e3000 INFO              GST_STATES gstbin.c:2230:gst_bin_element_set_state:<mp3-decoder> current PAUSED pending VOID_PENDING, desired next PLAYING
0:01:12.005916673 31988   0x5e3000 INFO              GST_STATES gstelement.c:2328:gst_element_continue_state:<mp3-decoder> completed state change to PLAYING
0:01:12.006004329 31988   0x5e3000 INFO              GST_STATES gstelement.c:2233:_priv_gst_element_state_changed:<mp3-decoder> notifying about state-changed PAUSED to PLAYING (VOID_PENDING pending)
0:01:12.006142245 31988   0x5e3000 INFO              GST_STATES gstbin.c:2673:gst_bin_change_state_func:<audio-player> child 'mp3-decoder' changed state to 4(PLAYING) successfully
0:01:12.006259484 31988   0x5e3000 INFO              GST_STATES gstbin.c:2230:gst_bin_element_set_state:<file-source> current PAUSED pending VOID_PENDING, desired next PLAYING
0:01:12.006381567 31988   0x5e3000 INFO              GST_STATES gstelement.c:2328:gst_element_continue_state:<file-source> completed state change to PLAYING
0:01:12.006465942 31988   0x5e3000 INFO              GST_STATES gstelement.c:2233:_priv_gst_element_state_changed:<file-source> notifying about state-changed PAUSED to PLAYING (VOID_PENDING pending)
0:01:12.006599379 31988   0x5e3000 INFO              GST_STATES gstbin.c:2673:gst_bin_change_state_func:<audio-player> child 'file-source' changed state to 4(PLAYING) successfully
0:01:12.006726983 31988   0x5e3000 INFO              GST_STATES gstelement.c:2328:gst_element_continue_state:<audio-player> completed state change to PLAYING
0:01:12.006812868 31988   0x5e3000 INFO              GST_STATES gstelement.c:2233:_priv_gst_element_state_changed:<audio-player> notifying about state-changed PAUSED to PLAYING (VOID_PENDING pending)

根据日志,管道的状态更改为“正在播放”。但是我什么也没听到。当我尝试停止或暂停或更改音量时,应用程序挂起。

我提到了这个link。但这没有帮助。

我想念什么?我是gstreamer的新手。任何指针将非常有帮助。

最佳答案

好的,这对我来说很好,总是在播放。

#include <gst/gst.h>
#include <glib.h>

int createElements(char *path)
{

    /* Create gstreamer elements */
    GstElement *m_pipeline  = gst_pipeline_new("audio-player");
    GstElement *m_fileSource = gst_element_factory_make("filesrc", "file-source");
    GstElement *m_audioDecoder = gst_element_factory_make("mad", "mp3-decoder");
    GstElement *m_volume = gst_element_factory_make("volume", "volume-name");
    GstElement *m_audioConverter = gst_element_factory_make("audioconvert", "audio-converter");
    GstElement *m_sink = gst_element_factory_make("alsasink", "audio-output");

    if (!m_pipeline || !m_fileSource || !m_audioDecoder || !m_volume || !m_audioConverter || !m_sink) {
            g_printerr ("One or more elements could not be created !! \n");
            return 0;
    } else {
            g_object_set (G_OBJECT (m_fileSource), "location", path, NULL);

            gst_bin_add_many (GST_BIN (m_pipeline), m_fileSource, m_audioDecoder, m_volume, m_audioConverter, m_sink, NULL);

            if(!gst_element_link_many (m_fileSource, m_audioDecoder, NULL)) {
                    g_printerr("ERROR: Failed to link file-source and audio-decoder !! \n");
                    return 0;
            }
            if(!gst_element_link_many (m_audioDecoder, m_volume, NULL)) {
                    g_printerr("ERROR: Failed to link audio-decoder and volume !! \n");
                    return 0;
            }
            if(!gst_element_link_many (m_volume, m_audioConverter, NULL)) {
                    g_printerr("ERROR: Failed to link audio-decoder and audio-converter !! \n");
                    return 0;
            }
            if(!gst_element_link_many (m_audioConverter, m_sink, NULL)) {
                    g_printerr("ERROR: Failed to link audio-converter and sink !! \n");
                    return 0;
            }
    }

    gst_element_set_state(m_pipeline, GST_STATE_PAUSED);
    sleep(3);
    gst_element_set_state(m_pipeline, GST_STATE_PLAYING);
    sleep(1);
    gst_element_set_state(m_pipeline, GST_STATE_PAUSED);
    sleep(2);
    gst_element_set_state(m_pipeline, GST_STATE_PLAYING);

    return 1;
}


int main(int argc, char **argv) {
    GMainLoop *loop = g_main_loop_new (NULL, FALSE);
    gst_init(&argc, &argv);
    createElements(argv[1]);
    g_main_loop_run (loop);
    return 0;
}

更新:
添加了多个暂停/播放过渡

在Linux上编译
gcc -Wall alsa_player.c -o alsa_player $(pkg-config --cflags --libs gstreamer-1.0)

使用./alsa_player file.mp3运行

我正在使用gstreamer 1.6,但我认为此代码将对任何1.x gstreamer都能完美运行。

UPDATE2:
您也可以尝试使用gst-play命令通过指定alsasink来执行相同的任务:
gst-play-1.0 japaka.mp3 --audiosink=alsasink
使用SPACE暂停和播放。

关于qt - 使用gstreamer api播放音频文件时遇到问题:应用程序挂起,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32872056/

相关文章:

ios - 将来自麦克风的音频录制为 .wav 格式并使用 Xamarin.ios 中的 AudioUnit 进行播放

Gstreamer:在 RTP 流中暂停/恢复视频

gstreamer - 许多缓冲区被丢弃

audio - gstreamer将音频/mpeg转换为音频/x-raw

c++ - QHeaderview中的排序指示器是用什么画出来的?

c++ - Qt 事件和信号/插槽

c++ - Treeview 模型属性在委托(delegate)警告中为空

Qt Creator 调试窗口专注于 Ubuntu

android - 在 android 中读取原始音频并提取 SMPTE 时间码

java - Android:- 将录制的音频文件转换为 float 组