• 【GStreamer开发】GStreamer播放教程07——自定义playbin2的sink


    目标

          通过手动选择音频和视频的sink,playbin2可以进一步定制。这允许使用playbin2的应用在解码后可以自行做最终的渲染和显示。本教程展示了:

          如何替换playbin2选择的sink

          如何使用一个复杂的pipeline来作为sink


    介绍

          playbin2有两个属性:audio-sink和video-sink。应用只需要实例化合适的element然后通过这两个属性传给playbin2就行了。

          这个方法只能使用一个简单地element来做sink。如果遇到的情况不是简单地element而是一个复杂的pipeline呢(比如均衡器加一个音频sink),就需要用Bin来包装一下,让playbin2感觉还是一个element。

          一个Bin就是一个容器,可以容纳一部分的pipeline,但操作的时候作为一个element。例如,我们在所有教程里面用得GstPipeline就是一个不会和外面的element做交互的GstBin。在Bin里面的element通过虚拟Pad(Ghost Pads)来和外面的element交互。这也就是说,Bin上得一个pad仅仅实现把外面的element上的pad的数据传到内部的element的pad上。


          GstBin也是element的一类,所以element可以用的地方,Bin也都能用,特别是,可以作为playbin2的sink。


    一个均衡的播放器

    [objc] view plain copy
     在CODE上查看代码片派生到我的代码片
    1. #include <gst/gst.h>  
    2.     
    3. int main(int argc, charchar *argv[]) {  
    4.   GstElement *pipeline, *bin, *equalizer, *convert, *sink;  
    5.   GstPad *pad, *ghost_pad;  
    6.   GstBus *bus;  
    7.   GstMessage *msg;  
    8.     
    9.   /* Initialize GStreamer */  
    10.   gst_init (&argc, &argv);  
    11.     
    12.   /* Build the pipeline */  
    13.   pipeline = gst_parse_launch ("playbin2 uri=http://docs.gstreamer.com/media/sintel_trailer-480p.webm"NULL);  
    14.     
    15.   /* Create the elements inside the sink bin */  
    16.   equalizer = gst_element_factory_make ("equalizer-3bands""equalizer");  
    17.   convert = gst_element_factory_make ("audioconvert""convert");  
    18.   sink = gst_element_factory_make ("autoaudiosink""audio_sink");  
    19.   if (!equalizer || !convert || !sink) {  
    20.     g_printerr ("Not all elements could be created. ");  
    21.     return -1;  
    22.   }  
    23.     
    24.   /* Create the sink bin, add the elements and link them */  
    25.   bin = gst_bin_new ("audio_sink_bin");  
    26.   gst_bin_add_many (GST_BIN (bin), equalizer, convert, sink, NULL);  
    27.   gst_element_link_many (equalizer, convert, sink, NULL);  
    28.   pad = gst_element_get_static_pad (equalizer, "sink");  
    29.   ghost_pad = gst_ghost_pad_new ("sink", pad);  
    30.   gst_pad_set_active (ghost_pad, TRUE);  
    31.   gst_element_add_pad (bin, ghost_pad);  
    32.   gst_object_unref (pad);  
    33.     
    34.   /* Configure the equalizer */  
    35.   g_object_set (G_OBJECT (equalizer), "band1", (gdouble)-24.0NULL);  
    36.   g_object_set (G_OBJECT (equalizer), "band2", (gdouble)-24.0NULL);  
    37.     
    38.   /* Set playbin2's audio sink to be our sink bin */  
    39.   g_object_set (GST_OBJECT (pipeline), "audio-sink", bin, NULL);  
    40.     
    41.   /* Start playing */  
    42.   gst_element_set_state (pipeline, GST_STATE_PLAYING);  
    43.     
    44.   /* Wait until error or EOS */  
    45.   bus = gst_element_get_bus (pipeline);  
    46.   msg = gst_bus_timed_pop_filtered (bus, GST_CLOCK_TIME_NONE, GST_MESSAGE_ERROR | GST_MESSAGE_EOS);  
    47.     
    48.   /* Free resources */  
    49.   if (msg != NULL)  
    50.     gst_message_unref (msg);  
    51.   gst_object_unref (bus);  
    52.   gst_element_set_state (pipeline, GST_STATE_NULL);  
    53.   gst_object_unref (pipeline);  
    54.   return 0;  
    55. }  

    工作流程

    [objc] view plain copy
     在CODE上查看代码片派生到我的代码片
    1. /* Create the elements inside the sink bin */  
    2. equalizer = gst_element_factory_make ("equalizer-3bands""equalizer");  
    3. convert = gst_element_factory_make ("audioconvert""convert");  
    4. sink = gst_element_factory_make ("autoaudiosink""audio_sink");  
    5. if (!equalizer || !convert || !sink) {  
    6.   g_printerr ("Not all elements could be created. ");  
    7.   return -1;  
    8. }  

          生成所有的sink bin所需要的element。我们使用了一个equalizer-3bands和一个autoaudiosink,中间还用audioconvert连接起来。

    [objc] view plain copy
     在CODE上查看代码片派生到我的代码片
    1. /* Create the sink bin, add the elements and link them */  
    2. bin = gst_bin_new ("audio_sink_bin");  
    3. gst_bin_add_many (GST_BIN (bin), equalizer, convert, sink, NULL);  
    4. gst_element_link_many (equalizer, convert, sink, NULL);  

          这几句把新的element加到Bin里面然后连接起来,就和在pipeline中一样。

    [objc] view plain copy
     在CODE上查看代码片派生到我的代码片
    1. pad = gst_element_get_static_pad (equalizer, "sink");  
    2. ghost_pad = gst_ghost_pad_new ("sink", pad);  
    3. gst_pad_set_active (ghost_pad, TRUE);  
    4. gst_element_add_pad (bin, ghost_pad);  
    5. gst_object_unref (pad);  

          现在我们需要生成虚拟Pad,这也一部分在Bin里面的pipeline可以连接到外面。这个虚拟Pad会和内部的一个element的Pad连接起来,我们会用gst_element_get_static_pad()来获得这个Pad。如果是一个RequestPad而不是Always Pad的话,那么我们就用get_element_request_pad()方法,具体请参考《GStreamer基础教程07——多线程和Pad的有效性

          虚拟Pad用gst_ghost_pad_new()来创建,用gst_pad_set_active()来激活。然后用gst_element_add_pad()来加入Bin。

          最后,我们用gst_object_unref()来释放获得的均衡器的sink pad。

          在这点上,我们有一个有sink功能的Bin,可以在playbin2里面用作音频sink,我们只需要设置一下playbin2的相关属性就行了。

    [objc] view plain copy
     在CODE上查看代码片派生到我的代码片
    1. /* Set playbin2's audio sink to be our sink bin */  
    2. g_object_set (GST_OBJECT (pipeline), "audio-sink", bin, NULL);  

          这和用一个sink element设置playbin2的audio-sink属性是完全一样的。

    [objc] view plain copy
     在CODE上查看代码片派生到我的代码片
    1. /* Configure the equalizer */  
    2. g_object_set (G_OBJECT (equalizer), "band1", (gdouble)-24.0NULL);  
    3. g_object_set (G_OBJECT (equalizer), "band2", (gdouble)-24.0NULL);  

          剩下的就是均衡器的配置了。在这个例子中,两个高频波段设置了最大的衰减,这样就增强了低音修改不同的值来实际看看效果。


  • 相关阅读:
    MySql: Year, Quarter, Month, Day, Hour statistics
    PHP7.27: Cookie and Session
    css:Media Queries: How to target desktop, tablet and mobile?
    PHP7.27: object
    php7.27: export excel from mysql
    机器学习基础---逻辑回归(假设函数与线性回归不同)
    机器学习作业---线性回归
    机器学习基础---多变量线性回归
    机器学习基础---线性回归
    机器学习基础---概述
  • 原文地址:https://www.cnblogs.com/huty/p/8517336.html
Copyright © 2020-2023  润新知