zoukankan      html  css  js  c++  java
  • 【GStreamer开发】GStreamer播放教程03——pipeline的快捷访问

    目的

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

          如何把appsrc连接到playbin2

          如何配置appsrc


    一个playbin2波形发生器

    [objc] view plain copy
     在CODE上查看代码片派生到我的代码片
    1. <span style="font-size:14px;">#include <gst/gst.h>  
    2. #include <string.h>  
    3.     
    4. #define CHUNK_SIZE 1024   /* Amount of bytes we are sending in each buffer */  
    5. #define SAMPLE_RATE 44100 /* Samples per second we are sending */  
    6. #define AUDIO_CAPS "audio/x-raw-int,channels=1,rate=%d,signed=(boolean)true,width=16,depth=16,endianness=BYTE_ORDER"  
    7.     
    8. /* Structure to contain all our information, so we can pass it to callbacks */  
    9. typedef struct _CustomData {  
    10.   GstElement *pipeline;  
    11.   GstElement *app_source;  
    12.     
    13.   guint64 num_samples;   /* Number of samples generated so far (for timestamp generation) */  
    14.   gfloat a, b, c, d;     /* For waveform generation */  
    15.     
    16.   guint sourceid;        /* To control the GSource */  
    17.     
    18.   GMainLoop *main_loop;  /* GLib's Main Loop */  
    19. } CustomData;  
    20.     
    21. /* This method is called by the idle GSource in the mainloop, to feed CHUNK_SIZE bytes into appsrc. 
    22.  * The ide handler is added to the mainloop when appsrc requests us to start sending data (need-data signal) 
    23.  * and is removed when appsrc has enough data (enough-data signal). 
    24.  */  
    25. static gboolean push_data (CustomData *data) {  
    26.   GstBuffer *buffer;  
    27.   GstFlowReturn ret;  
    28.   int i;  
    29.   gint16 *raw;  
    30.   gint num_samples = CHUNK_SIZE / 2/* Because each sample is 16 bits */  
    31.   gfloat freq;  
    32.     
    33.   /* Create a new empty buffer */  
    34.   buffer = gst_buffer_new_and_alloc (CHUNK_SIZE);  
    35.     
    36.   /* Set its timestamp and duration */  
    37.   GST_BUFFER_TIMESTAMP (buffer) = gst_util_uint64_scale (data->num_samples, GST_SECOND, SAMPLE_RATE);  
    38.   GST_BUFFER_DURATION (buffer) = gst_util_uint64_scale (CHUNK_SIZE, GST_SECOND, SAMPLE_RATE);  
    39.     
    40.   /* Generate some psychodelic waveforms */  
    41.   raw = (gint16 *)GST_BUFFER_DATA (buffer);  
    42.   data->c += data->d;  
    43.   data->d -= data->c / 1000;  
    44.   freq = 1100 + 11000 * data->d;  
    45.   for (i = 0; i < num_samples; i++) {  
    46.     data->a += data->b;  
    47.     data->b -= data->a / freq;  
    48.     raw[i] = (gint16)(5500 * data->a);  
    49.   }  
    50.   data->num_samples += num_samples;  
    51.     
    52.   /* Push the buffer into the appsrc */  
    53.   g_signal_emit_by_name (data->app_source, "push-buffer", buffer, &ret);  
    54.     
    55.   /* Free the buffer now that we are done with it */  
    56.   gst_buffer_unref (buffer);  
    57.     
    58.   if (ret != GST_FLOW_OK) {  
    59.     /* We got some error, stop sending data */  
    60.     return FALSE;  
    61.   }  
    62.     
    63.   return TRUE;  
    64. }  
    65.     
    66. /* This signal callback triggers when appsrc needs data. Here, we add an idle handler 
    67.  * to the mainloop to start pushing data into the appsrc */  
    68. static void start_feed (GstElement *source, guint size, CustomData *data) {  
    69.   if (data->sourceid == 0) {  
    70.     g_print ("Start feeding ");  
    71.     data->sourceid = g_idle_add ((GSourceFunc) push_data, data);  
    72.   }  
    73. }  
    74.     
    75. /* This callback triggers when appsrc has enough data and we can stop sending. 
    76.  * We remove the idle handler from the mainloop */  
    77. static void stop_feed (GstElement *source, CustomData *data) {  
    78.   if (data->sourceid != 0) {  
    79.     g_print ("Stop feeding ");  
    80.     g_source_remove (data->sourceid);  
    81.     data->sourceid = 0;  
    82.   }  
    83. }  
    84.     
    85. /* This function is called when an error message is posted on the bus */  
    86. static void error_cb (GstBus *bus, GstMessage *msg, CustomData *data) {  
    87.   GError *err;  
    88.   gchar *debug_info;  
    89.     
    90.   /* Print error details on the screen */  
    91.   gst_message_parse_error (msg, &err, &debug_info);  
    92.   g_printerr ("Error received from element %s: %s ", GST_OBJECT_NAME (msg->src), err->message);  
    93.   g_printerr ("Debugging information: %s ", debug_info ? debug_info : "none");  
    94.   g_clear_error (&err);  
    95.   g_free (debug_info);  
    96.     
    97.   g_main_loop_quit (data->main_loop);  
    98. }  
    99.     
    100. /* This function is called when playbin2 has created the appsrc element, so we have 
    101.  * a chance to configure it. */  
    102. static void source_setup (GstElement *pipeline, GstElement *source, CustomData *data) {  
    103.   gchar *audio_caps_text;  
    104.   GstCaps *audio_caps;  
    105.     
    106.   g_print ("Source has been created. Configuring. ");  
    107.   data->app_source = source;  
    108.     
    109.   /* Configure appsrc */  
    110.   audio_caps_text = g_strdup_printf (AUDIO_CAPS, SAMPLE_RATE);  
    111.   audio_caps = gst_caps_from_string (audio_caps_text);  
    112.   g_object_set (source, "caps", audio_caps, NULL);  
    113.   g_signal_connect (source, "need-data", G_CALLBACK (start_feed), data);  
    114.   g_signal_connect (source, "enough-data", G_CALLBACK (stop_feed), data);  
    115.   gst_caps_unref (audio_caps);  
    116.   g_free (audio_caps_text);  
    117. }  
    118.     
    119. int main(int argc, charchar *argv[]) {  
    120.   CustomData data;  
    121.   GstBus *bus;  
    122.     
    123.   /* Initialize cumstom data structure */  
    124.   memset (&data, 0sizeof (data));  
    125.   data.b = 1/* For waveform generation */  
    126.   data.d = 1;  
    127.     
    128.   /* Initialize GStreamer */  
    129.   gst_init (&argc, &argv);  
    130.     
    131.   /* Create the playbin2 element */  
    132.   data.pipeline = gst_parse_launch ("playbin2 uri=appsrc://"NULL);  
    133.   g_signal_connect (data.pipeline"source-setup", G_CALLBACK (source_setup), &data);  
    134.     
    135.   /* Instruct the bus to emit signals for each received message, and connect to the interesting signals */  
    136.   bus = gst_element_get_bus (data.pipeline);  
    137.   gst_bus_add_signal_watch (bus);  
    138.   g_signal_connect (G_OBJECT (bus), "message::error", (GCallback)error_cb, &data);  
    139.   gst_object_unref (bus);  
    140.     
    141.   /* Start playing the pipeline */  
    142.   gst_element_set_state (data.pipeline, GST_STATE_PLAYING);  
    143.     
    144.   /* Create a GLib Main Loop and set it to run */  
    145.   data.main_loop = g_main_loop_new (NULL, FALSE);  
    146.   g_main_loop_run (data.main_loop);  
    147.     
    148.   /* Free resources */  
    149.   gst_element_set_state (data.pipeline, GST_STATE_NULL);  
    150.   gst_object_unref (data.pipeline);  
    151.   return 0;  
    152. }  
    153. </span>  

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

    [objc] view plain copy
     在CODE上查看代码片派生到我的代码片
    1. <span style="font-size:14px;">  /* Create the playbin2 element */  
    2.   data.pipeline = gst_parse_launch ("playbin2 uri=appsrc://"NULL);</span>  

          playbin2创建一个内部的appsrc element并且发送source-setup信号来通知应用进行设置。

    [objc] view plain copy
     在CODE上查看代码片派生到我的代码片
    1. <span style="font-size:14px;">  g_signal_connect (data.pipeline"source-setup", G_CALLBACK (source_setup), &data);</span>  

          特别地,设置appsrc的caps属性是很重要的,因为一旦这个信号的处理返回,playbin2就会根据返回值来初始化下一个element。

    [objc] view plain copy
     在CODE上查看代码片派生到我的代码片
    1. <span style="font-size:14px;">/* This function is called when playbin2 has created the appsrc element, so we have 
    2.  * a chance to configure it. */  
    3. static void source_setup (GstElement *pipeline, GstElement *source, CustomData *data) {  
    4.   gchar *audio_caps_text;  
    5.   GstCaps *audio_caps;  
    6.     
    7.   g_print ("Source has been created. Configuring. ");  
    8.   data->app_source = source;  
    9.     
    10.   /* Configure appsrc */  
    11.   audio_caps_text = g_strdup_printf (AUDIO_CAPS, SAMPLE_RATE);  
    12.   audio_caps = gst_caps_from_string (audio_caps_text);  
    13.   g_object_set (source, "caps", audio_caps, NULL);  
    14.   g_signal_connect (source, "need-data", G_CALLBACK (start_feed), data);  
    15.   g_signal_connect (source, "enough-data", G_CALLBACK (stop_feed), data);  
    16.   gst_caps_unref (audio_caps);  
    17.   g_free (audio_caps_text);  
    18. }</span>  

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

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

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

  • 相关阅读:
    Median Value
    237. Delete Node in a Linked List
    206. Reverse Linked List
    160. Intersection of Two Linked Lists
    83. Remove Duplicates from Sorted List
    21. Merge Two Sorted Lists
    477. Total Hamming Distance
    421. Maximum XOR of Two Numbers in an Array
    397. Integer Replacement
    318. Maximum Product of Word Lengths
  • 原文地址:https://www.cnblogs.com/huty/p/8517344.html
Copyright © 2011-2022 走看看