目的
《GStreamer08——pipeline的快捷访问》展示了一个应用如何用appsrc和appsink这两个特殊的element在pipeline中手动输入/提取数据。playbin2也允许使用这两个element,但连接它们的方法有所不同。连接appsink到playbin2的方法在后面还会提到。这里我们主要讲述:
如何把appsrc连接到playbin2
如何配置appsrc
一个playbin2波形发生器
- <spanstyle="font-size:14px;">#include<gst/gst.h>
- #include<string.h>
- #defineCHUNK_SIZE1024/*Amountofbyteswearesendingineachbuffer*/
- #defineSAMPLE_RATE44100/*Samplespersecondwearesending*/
- #defineAUdio_CAPS"audio/x-raw-int,channels=1,rate=%d,signed=(boolean)true,width=16,depth=16,endianness=BYTE_ORDER"
- typedefstruct_CustomData{
- GstElement*pipeline;
- GstElement*app_source;
- guint64num_samples;
- gfloata,b,c,d;
- guintsourceid;
- GMainLoop*main_loop;
- }CustomData;
- staticgbooleanpush_data(CustomData*data){
- GstBuffer*buffer;
- GstFlowReturnret;
- inti;
- gint16*raw;
- gintnum_samples=CHUNK_SIZE/2;
- gfloatfreq;
- buffer=gst_buffer_new_and_alloc(CHUNK_SIZE);
- GST_BUFFER_TIMESTAMP(buffer)=gst_util_uint64_scale(data->num_samples,GST_SECOND,SAMPLE_RATE);
- GST_BUFFER_DURATION(buffer)=gst_util_uint64_scale(CHUNK_SIZE,SAMPLE_RATE);
- raw=(gint16*)GST_BUFFER_DATA(buffer);
- data->c+=data->d;
- data->d-=data->c/1000;
- freq=1100+11000*data->d;
- for(i=0;i<num_samples;i++){
- data->a+=data->b;
- data->b-=data->a/freq;
- raw[i]=(gint16)(5500*data->a);
- }
- data->num_samples+=num_samples;
- g_signal_emit_by_name(data->app_source,"push-buffer",buffer,&ret);
- gst_buffer_unref(buffer);
- if(ret!=GST_FLOW_OK){
- returnFALSE;
- returnTRUE;
- }
- staticvoidstart_Feed(GstElement*source,guintsize,CustomData*data){
- if(data->sourceid==0){
- g_print("StartFeeding\n");
- data->sourceid=g_idle_add((GSourceFunc)push_data,data);
- staticvoidstop_Feed(GstElement*source,CustomData*data){
- if(data->sourceid!=0){
- g_print("StopFeeding\n");
- g_source_remove(data->sourceid);
- data->sourceid=0;
- staticvoiderror_cb(GstBus*bus,GstMessage*msg,0)">GError*err;
- gchar*debug_info;
- gst_message_parse_error(msg,&err,&debug_info);
- g_printerr("Errorreceivedfromelement%s:%s\n",GST_OBJECT_NAME(msg->src),err->message);
- g_printerr("Debugginginformation:%s\n",debug_info?debug_info:"none");
- g_clear_error(&err);
- g_free(debug_info);
- g_main_loop_quit(data->main_loop);
- staticvoidsource_setup(GstElement*pipeline,GstElement*source,0)">gchar*audio_caps_text;
- GstCaps*audio_caps;
- g_print("Sourcehasbeencreated.Configuring.\n");
- data->app_source=source;
- audio_caps_text=g_strdup_printf(AUdio_CAPS,SAMPLE_RATE);
- audio_caps=gst_caps_from_string(audio_caps_text);
- g_object_set(source,"caps",audio_caps,NULL);
- g_signal_connect(source,"need-data",G_CALLBACK(start_Feed),data);
- "enough-data",G_CALLBACK(stop_Feed),data);
- gst_caps_unref(audio_caps);
- g_free(audio_caps_text);
- intmain(intargc,charchar*argv[]){
- CustomDatadata;
- GstBus*bus;
- memset(&data,0,sizeof(data));
- data.b=1;
- data.d=1;
- gst_init(&argc,&argv);
- data.pipeline=gst_parse_launch("playbin2uri=appsrc://",0)">g_signal_connect(data.pipeline,"source-setup",G_CALLBACK(source_setup),&data);
- bus=gst_element_get_bus(data.pipeline);
- gst_bus_add_signal_watch(bus);
- g_signal_connect(G_OBJECT(bus),"message::error",(GCallback)error_cb,&data);
- gst_object_unref(bus);
- gst_element_set_state(data.pipeline,GST_STATE_PLAYING);
- data.main_loop=g_main_loop_new(NULL,FALSE);
- g_main_loop_run(data.main_loop);
- gst_object_unref(data.pipeline);
- return0;
- </span>
把appsrc用作pipeline的source,仅仅把playbin2的UIR设置成appsrc://即可。
playbin2创建一个内部的appsrc element并且发送source-setup信号来通知应用进行设置。
[objc]view plaincopy
<spanstyle="font-size:14px;">g_signal_connect(data.pipeline,&data);</span>
特别地,设置appsrc的caps属性是很重要的,因为一旦这个信号的处理返回,playbin2就会根据返回值来初始化下一个element。
[objc]view plaincopy
<spanstyle="font-size:14px;">
gchar*audio_caps_text;
GstCaps*audio_caps;
g_print("Sourcehasbeencreated.Configuring.\n");
data->app_source=source;
audio_caps=gst_caps_from_string(audio_caps_text);
NULL);
gst_caps_unref(audio_caps);
g_free(audio_caps_text);
}</span>
appsrc的配置和《GStreamer08——pipeline的快捷访问》里面一样:caps设置成audio/x-raw-int,注册两个回调,这样element可以在需要/停止给它推送数据时通知应用。具体细节请参考《GStreamer08——pipeline的快捷访问》。
在这个点之后,playbin2接管处理了剩下的pipeline,应用仅仅需要生成数据即可。
至于使用appsink来从从playbin2里面提取数据,在后面的教程里面再讲述。