我使用gstreamer apis在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)
根据日志,管道状态更改为PLAYING。但我什么都听不到。当我尝试停止或暂停或更改音量时,应用程序会挂起。
我提到了link。但它没有帮助。
我错过了什么?我是gstreamer的新手。任何指针都会非常有用。
答案 0 :(得分:0)
好的,这对我很好,总是在玩..
#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;
}
<强>更新强> 添加了PAUSED / PLAYING的多个过渡
在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暂停和播放..