源代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 |
#include <gst/gst.h> #include <glib.h> /*总线消息处理回调函数*/ static gboolean bus_call (GstBus *bus, GstMessage *msg, gpointer data) { GMainLoop *loop = (GMainLoop *) data; switch (GST_MESSAGE_TYPE (msg)) { case GST_MESSAGE_EOS: g_print ("End of stream\n"); g_main_loop_quit (loop); 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); g_main_loop_quit (loop); break; } default: break; } return TRUE; } int main (int argc, char *argv[]) { GMainLoop *loop; GstElement *pipeline, *source, *parser, *decoder, *conv, *sink; GstBus *bus; guint bus_watch_id; /* Initialisation */ gst_init (&argc, &argv); loop = g_main_loop_new (NULL, FALSE); /* Check input arguments */ if (argc != 2) { g_printerr ("Usage: %s <Ogg/Vorbis filename>\n", argv[0]); return -1; } /* Create gstreamer elements */ pipeline = gst_pipeline_new ("audio-player"); source = gst_element_factory_make ("filesrc", "file-source"); parser = gst_element_factory_make ("mpegaudioparse", "mp3-parser"); decoder = gst_element_factory_make ("mpg123audiodec", "mp3-decoder"); conv = gst_element_factory_make ("audioconvert", "converter"); //sink = gst_element_factory_make ("pulsesink", "audio-output"); sink = gst_element_factory_make ("autoaudiosink", "audio-output"); if (!pipeline || !source || !parser || !decoder || !conv || !sink ) { g_printerr ("One element could not be created. Exiting.\n"); return -1; } /* Set up the pipeline */ /* we set the input filename to the source element */ g_object_set (G_OBJECT (source), "location", argv[1], NULL); /* we add a message handler */ bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline)); bus_watch_id = gst_bus_add_watch (bus, bus_call, loop); gst_object_unref (bus); /* we add all elements into the pipeline */ /* file-source | mp3-parser | mp3-decoder | converter | alsa-output */ gst_bin_add_many (GST_BIN (pipeline), source, parser, decoder, conv, sink, NULL); /* we link the elements together */ /* file-source -> mp3-parser ~> mp3-decoder -> converter -> alsa-output */ //gst_element_link (source, parser); gst_element_link_many (source, parser, decoder, conv, sink, NULL); /* note that the parser will be linked to the decoder dynamically. The reason is that Ogg may contain various streams (for example audio and video). The source pad(s) will be created at run time, by the parser when it detects the amount and nature of streams. Therefore we connect a callback function which will be executed when the "pad-added" is emitted.*/ /* Set the pipeline to "playing" state*/ g_print ("Now playing: %s\n", argv[1]); gst_element_set_state (pipeline, GST_STATE_PLAYING); /* Iterate */ g_print ("Running...\n"); g_main_loop_run (loop); /* Out of the main loop, clean up nicely */ g_print ("Returned, stopping playback\n"); gst_element_set_state (pipeline, GST_STATE_NULL); g_print ("Deleting pipeline\n"); gst_object_unref (GST_OBJECT (pipeline)); g_source_remove (bus_watch_id); g_main_loop_unref (loop); return 0; } |
与ogg格式音频不一样,mp3格式数据没有多路复用,直接解析就行,而ogg需要一个分路器来实现多路复用数据分离。
因此可直接用下面两行代码对元数据进行解析和解码
1 2 3 4 |
parser = gst_element_factory_make ("mpegaudioparse", "mp3-parser"); decoder = gst_element_factory_make ("mpg123audiodec", "mp3-decoder"); |
再用转流器输出到可用音频设备就行。
另一个需要提到的与ogg音频播放代码有差别的是:
处理mp3的管道 (pipeline) 中,各个元素直接添加到管道中进行链接即可,而不需要像处理ogg那样,监听分离器产生的pad-added事件,再调用回调函数链接分离器和解码器。
因为mp3没有多路复用,mp3解析器(mpegaudioparse)生成的元素,其pad可用性属于always pad,一直存在且只有单个,并不属于ogg格式下的dynamic pad(含有两个pad)。