本文記錄在 CentOS 6 環境下,解決 MP3 解碼專利問題(安裝 libmad、gstreamer-plugins-ugly),構建基於 filesrc → mad → autoaudiosink 管道的命令行 MP3 播放器完整流程。
CentOS 默認倉庫無 MP3 解碼器,需手動安裝第三方 RPM:
# 1. 安裝基礎開發包
yum install gstreamer-devel gstreamer-plugins-base-devel
# 2. 下載並安裝 libmad(MP3 解碼核心庫)
wget ftp://ftp.pbone.net/mirror/atrpms.net/el5-x86_64/atrpms/stable/libmad0-0.15.1b-4.el5.x86_64.rpm
wget ftp://ftp.pbone.net/mirror/atrpms.net/el5-x86_64/atrpms/stable/libmad-0.15.1b-4.el5.x86_64.rpm
wget ftp://195.220.108.108/linux/centos/6.7/os/x86_64/Packages/libid3tag-0.15.1b-11.el6.x86_64.rpm
wget ftp://ftp.pbone.net/mirror/atrpms.net/el6-x86_64/atrpms/stable/libdvdread3-0.9.7-5.el6.x86_64.rpm
wget ftp://195.220.108.108/linux/Mandriva/official/2007.0/x86_64/media/main/release/gstreamer0.10-plugins-ugly-0.10.4-1mdv2007.0.x86_64.rpm
rpm -ivh libmad0-0.15.1b-4.el5.x86_64.rpm libmad-0.15.1b-4.el5.x86_64.rpm
rpm -ivh libid3tag-0.15.1b-11.el6.x86_64.rpm libdvdread3-0.9.7-5.el6.x86_64.rpm
rpm -ivh gstreamer0.10-plugins-ugly-0.10.4-1mdv2007.0.x86_64.rpm
現代系統(GStreamer 1.x):直接 yum install gstreamer1-plugins-ugly 或 apt install gstreamer1.0-plugins-ugly 即可,無需手動找 RPM。
#include
#include
/* 總線消息回調:處理 EOS、ERROR */
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("播放結束\n");
g_main_loop_quit(loop);
break;
case GST_MESSAGE_ERROR: {
GError *err; gchar *dbg;
gst_message_parse_error(msg, &err, &dbg);
g_printerr("錯誤: %s\n", err->message);
g_error_free(err); g_free(dbg);
g_main_loop_quit(loop);
break;
}
default: break;
}
return TRUE;
}
int main(int argc, char *argv[]) {
GMainLoop *loop;
GstElement *pipeline, *source, *decoder, *sink;
GstBus *bus;
gst_init(&argc, &argv);
if (argc != 2) {
g_printerr("用法: %s \n", argv[0]);
return -1;
}
loop = g_main_loop_new(NULL, FALSE);
/* 創建元件 */
pipeline = gst_pipeline_new("audio-player");
source = gst_element_factory_make("filesrc", "file-source");
decoder = gst_element_factory_make("mad", "mad-decoder"); // MP3 解碼
sink = gst_element_factory_make("autoaudiosink", "audio-output");
if (!pipeline || !source || !decoder || !sink) {
g_printerr("元件創建失敗\n");
return -1;
}
/* 設置源文件路徑 */
g_object_set(G_OBJECT(source), "location", argv[1], NULL);
/* 總線監聽 */
bus = gst_pipeline_get_bus(GST_PIPELINE(pipeline));
gst_bus_add_watch(bus, bus_call, loop);
gst_object_unref(bus);
/* 組裝管道 */
gst_bin_add_many(GST_BIN(pipeline), source, decoder, sink, NULL);
gst_element_link_many(source, decoder, sink, NULL);
/* 啟動播放 */
gst_element_set_state(pipeline, GST_STATE_PLAYING);
g_print("正在播放: %s\n", argv[1]);
/* 進入主循環 */
g_main_loop_run(loop);
/* 清理 */
g_print("停止播放\n");
gst_element_set_state(pipeline, GST_STATE_NULL);
gst_object_unref(GST_OBJECT(pipeline));
return 0;
}
# GStreamer 0.10 (舊版)
gcc -Wall -g -o mp3 mp3.c `pkg-config --cflags --libs gstreamer-0.10`
# GStreamer 1.x (現代系統)
gcc -Wall -g -o mp3 mp3.c `pkg-config --cflags --libs gstreamer-1.0`
# 運行
./mp3 song.mp3
libmad 的 MP3 解碼器,屬於 ugly 插件組(專利風險),需額外安裝。decodebin 自動探測格式並選擇解碼器,無需硬編碼 mad:decoder = gst_element_factory_make("decodebin", "dec");pad-added 信號動態鏈接下游。g_main_loop_run() 陻塞直到 g_main_loop_quit()。gst_bus_add_watch() 在主循環上下文中回調,安全處理 EOS/ERROR/STATE_CHANGED 等。NULL → READY → PAUSED → PLAYING,每次轉換觸發元件內部資源分配/釋放/協商。| 現象 | 原因 | 解決 |
|---|---|---|
| 元件創建失敗 | 缺少 ugly 插件或 libmad | 安裝 gstreamer-plugins-ugly / libmad-devel |
| 無聲音輸出 | autoaudiosink 未檢測到音頻設備 | 指定 sink:alsasink/pulsesink/osxaudio |
| 播放卡頓 | 解碼過慢/緩衝不足 | 添加 queue 元件、啟用硬件加速 |
| 無法定位 | MP3 無 seek table / mad 不支持 | 使用 id3demux+mad 或換用 decodebin |
PAUSED↔PLAYING)、停止、音量(g_object_set(sink, "volume", 0.5, NULL))、進度查詢(GST_QUERY_POSITION)。gtkglsink/qmlglsink、顯示波形/頻譜/歌詞。gst_tag_list_get_string() 獲取標題/藝術家/專輯/封面。掌握「元件工廠創建 → 屬性設置 → 管道組裝 → 總線監聽 → 主循環驅動」這一標準範式,即可基於 GStreamer 快速構建各類音視頻播放、處理、流媒體應用。