【GStreamer开发】GStreamer播放教程03——pipeline的快捷访问

前端之家收集整理的这篇文章主要介绍了【GStreamer开发】GStreamer播放教程03——pipeline的快捷访问前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

目的

GStreamer08——pipeline的快捷访问》展示了一个应用如何用appsrc和appsink这两个特殊的element在pipeline中手动输入/提取数据。playbin2也允许使用这两个element,但连接它们的方法有所不同。连接appsink到playbin2的方法在后面还会提到。这里我们主要讲述:

如何把appsrc连接到playbin2

如何配置appsrc


一个playbin2波形发生器

  1. <spanstyle="font-size:14px;">#include<gst/gst.h>
  2. @H_502_65@#include<string.h>
  3. @H_502_65@#defineCHUNK_SIZE1024/*Amountofbyteswearesendingineachbuffer*/
  4. #defineSAMPLE_RATE44100/*Samplespersecondwearesending*/
  5. @H_502_65@#defineAUdio_CAPS"audio/x-raw-int,channels=1,rate=%d,signed=(boolean)true,width=16,depth=16,endianness=BYTE_ORDER"
  6. /*Structuretocontainallourinformation,sowecanpassittocallbacks*/
  7. typedefstruct_CustomData{
  8. @H_502_65@GstElement*pipeline;
  9. GstElement*app_source;
  10. @H_502_65@
  11. guint64num_samples;/*Numberofsamplesgeneratedsofar(fortimestampgeneration)*/
  12. @H_502_65@gfloata,b,c,d;/*Forwaveformgeneration*/
  13. guintsourceid;/*TocontroltheGSource*/
  14. GMainLoop*main_loop;/*GLib'sMainLoop*/
  15. }CustomData;
  16. @H_502_65@/*ThismethodiscalledbytheidleGSourceinthemainloop,toFeedCHUNK_SIZEbytesintoappsrc. @H_502_65@*Theidehandlerisaddedtothemainloopwhenappsrcrequestsustostartsendingdata(need-datasignal)
  17. *andisremovedwhenappsrchasenoughdata(enough-datasignal).
  18. @H_502_65@*/
  19. staticgbooleanpush_data(CustomData*data){
  20. @H_502_65@GstBuffer*buffer;
  21. GstFlowReturnret;
  22. @H_502_65@inti;
  23. gint16*raw;
  24. @H_502_65@gintnum_samples=CHUNK_SIZE/2;/*Becauseeachsampleis16bits*/
  25. gfloatfreq;
  26. @H_502_65@/*Createanewemptybuffer*/ @H_502_65@buffer=gst_buffer_new_and_alloc(CHUNK_SIZE);
  27. /*Setitstimestampandduration*/
  28. GST_BUFFER_TIMESTAMP(buffer)=gst_util_uint64_scale(data->num_samples,GST_SECOND,SAMPLE_RATE);
  29. @H_502_65@GST_BUFFER_DURATION(buffer)=gst_util_uint64_scale(CHUNK_SIZE,SAMPLE_RATE);
  30. /*Generatesomepsychodelicwaveforms*/
  31. raw=(gint16*)GST_BUFFER_DATA(buffer);
  32. @H_502_65@data->c+=data->d;
  33. data->d-=data->c/1000;
  34. @H_502_65@freq=1100+11000*data->d;
  35. for(i=0;i<num_samples;i++){
  36. @H_502_65@data->a+=data->b;
  37. data->b-=data->a/freq;
  38. @H_502_65@raw[i]=(gint16)(5500*data->a);
  39. }
  40. @H_502_65@data->num_samples+=num_samples;
  41. /*Pushthebufferintotheappsrc*/
  42. g_signal_emit_by_name(data->app_source,"push-buffer",buffer,&ret);
  43. @H_502_65@/*Freethebuffernowthatwearedonewithit*/ @H_502_65@gst_buffer_unref(buffer);
  44. if(ret!=GST_FLOW_OK){
  45. /*Wegotsomeerror,stopsendingdata*/
  46. @H_502_65@returnFALSE;
  47. returnTRUE;
  48. @H_502_65@}
  49. /*Thissignalcallbacktriggerswhenappsrcneedsdata.Here,weaddanidlehandler
  50. *tothemainlooptostartpushingdataintotheappsrc*/
  51. @H_502_65@staticvoidstart_Feed(GstElement*source,guintsize,CustomData*data){
  52. if(data->sourceid==0){
  53. @H_502_65@g_print("StartFeeding\n");
  54. data->sourceid=g_idle_add((GSourceFunc)push_data,data);
  55. @H_502_65@/*Thiscallbacktriggerswhenappsrchasenoughdataandwecanstopsending. @H_502_65@*Weremovetheidlehandlerfromthemainloop*/
  56. staticvoidstop_Feed(GstElement*source,CustomData*data){
  57. @H_502_65@if(data->sourceid!=0){
  58. g_print("StopFeeding\n");
  59. @H_502_65@g_source_remove(data->sourceid);
  60. data->sourceid=0;
  61. @H_502_65@/*Thisfunctioniscalledwhenanerrormessageispostedonthebus*/ @H_502_65@staticvoiderror_cb(GstBus*bus,GstMessage*msg,0)">GError*err; @H_502_65@gchar*debug_info;
  62. /*Printerrordetailsonthescreen*/
  63. gst_message_parse_error(msg,&err,&debug_info);
  64. @H_502_65@g_printerr("Errorreceivedfromelement%s:%s\n",GST_OBJECT_NAME(msg->src),err->message);
  65. g_printerr("Debugginginformation:%s\n",debug_info?debug_info:"none");
  66. @H_502_65@g_clear_error(&err);
  67. g_free(debug_info);
  68. @H_502_65@g_main_loop_quit(data->main_loop); @H_502_65@/*Thisfunctioniscalledwhenplaybin2hascreatedtheappsrcelement,sowehave
  69. *achancetoconfigureit.*/
  70. @H_502_65@staticvoidsource_setup(GstElement*pipeline,GstElement*source,0)">gchar*audio_caps_text; @H_502_65@GstCaps*audio_caps;
  71. g_print("Sourcehasbeencreated.Configuring.\n");
  72. data->app_source=source;
  73. @H_502_65@/*Configureappsrc*/ @H_502_65@audio_caps_text=g_strdup_printf(AUdio_CAPS,SAMPLE_RATE);
  74. audio_caps=gst_caps_from_string(audio_caps_text);
  75. @H_502_65@g_object_set(source,"caps",audio_caps,NULL);
  76. g_signal_connect(source,"need-data",G_CALLBACK(start_Feed),data);
  77. "enough-data",G_CALLBACK(stop_Feed),data);
  78. gst_caps_unref(audio_caps);
  79. @H_502_65@g_free(audio_caps_text);
  80. intmain(intargc,charchar*argv[]){
  81. @H_502_65@CustomDatadata;
  82. GstBus*bus;
  83. @H_502_65@/*Initializecumstomdatastructure*/ @H_502_65@memset(&data,0,sizeof(data));
  84. data.b=1;/*Forwaveformgeneration*/
  85. @H_502_65@data.d=1;
  86. /*InitializeGStreamer*/
  87. gst_init(&argc,&argv);
  88. @H_502_65@/*Createtheplaybin2element*/ @H_502_65@data.pipeline=gst_parse_launch("playbin2uri=appsrc://",0)">g_signal_connect(data.pipeline,"source-setup",G_CALLBACK(source_setup),&data); @H_502_65@/*Instructthebustoemitsignalsforeachreceivedmessage,andconnecttotheinterestingsignals*/ @H_502_65@bus=gst_element_get_bus(data.pipeline);
  89. gst_bus_add_signal_watch(bus);
  90. @H_502_65@g_signal_connect(G_OBJECT(bus),"message::error",(GCallback)error_cb,&data);
  91. gst_object_unref(bus);
  92. @H_502_65@/*Startplayingthepipeline*/ @H_502_65@gst_element_set_state(data.pipeline,GST_STATE_PLAYING);
  93. /*CreateaGLibMainLoopandsetittorun*/
  94. data.main_loop=g_main_loop_new(NULL,FALSE);
  95. @H_502_65@g_main_loop_run(data.main_loop);
  96. /*Freeresources*/
  97. 502_65@gst_object_unref(data.pipeline);
  98. return0;
  99. @H_502_65@</span>

把appsrc用作pipeline的source,仅仅把playbin2的UIR设置成appsrc://即可。

[objc]view plaincopy
<spanstyle="font-size:14px;">/*Createtheplaybin2element*/
  • NULL);</span>
  • 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;">/*Thisfunctioniscalledwhenplaybin2hascreatedtheappsrcelement,sowehave @H_502_65@*achancetoconfigureit.*/
  • gchar*audio_caps_text;
  • GstCaps*audio_caps;
  • @H_502_65@g_print("Sourcehasbeencreated.Configuring.\n"); @H_502_65@data->app_source=source;
  • /*Configureappsrc*/
  • 502_65@audio_caps=gst_caps_from_string(audio_caps_text);
  • NULL);
  • @H_502_65@gst_caps_unref(audio_caps);
  • g_free(audio_caps_text);
  • @H_502_65@}</span>

    appsrc的配置和《GStreamer08——pipeline的快捷访问》里面一样:caps设置成audio/x-raw-int,注册两个回调,这样element可以在需要/停止给它推送数据时通知应用。具体细节请参考《GStreamer08——pipeline的快捷访问》。

    在这个点之后,playbin2接管处理了剩下的pipeline,应用仅仅需要生成数据即可。

    至于使用appsink来从从playbin2里面提取数据,在后面的教程里面再讲述。

    原文链接:https://www.f2er.com/javaschema/283321.html

    猜你在找的设计模式相关文章