• 【GStreamer开发】GStreamer基础教程02——GStreamer概念


    上一个教程演示了如何自动生成一个pipeline。这次我们打算用一个个element来手动搭建一个pipeline。我们这个教程会演示:

    1. 什么是GStreamer的element以及如何建立一个element

    2. 如何在element直接建立连接

    3. 如何客制化element的行为

    4. 如何监视总线上的错误并获得相关的信息


          手动建立Hello World

    把下面的代码copy到basic-turtorial-2.c文件

    [objc] view plain copy
     在CODE上查看代码片派生到我的代码片
    1. #include <gst/gst.h>  
    2.     
    3. int main(int argc, charchar *argv[]) {  
    4.   GstElement *pipeline, *source, *sink;  
    5.   GstBus *bus;  
    6.   GstMessage *msg;  
    7.   GstStateChangeReturn ret;  
    8.     
    9.   /* Initialize GStreamer */  
    10.   gst_init (&argc, &argv);  
    11.      
    12.   /* Create the elements */  
    13.   source = gst_element_factory_make ("videotestsrc""source");  
    14.   sink = gst_element_factory_make ("autovideosink""sink");  
    15.      
    16.   /* Create the empty pipeline */  
    17.   pipeline = gst_pipeline_new ("test-pipeline");  
    18.      
    19.   if (!pipeline || !source || !sink) {  
    20.     g_printerr ("Not all elements could be created. ");  
    21.     return -1;  
    22.   }  
    23.     
    24.   /* Build the pipeline */  
    25.   gst_bin_add_many (GST_BIN (pipeline), source, sink, NULL);  
    26.   if (gst_element_link (source, sink) != TRUE) {  
    27.     g_printerr ("Elements could not be linked. ");  
    28.     gst_object_unref (pipeline);  
    29.     return -1;  
    30.   }  
    31.     
    32.   /* Modify the source's properties */  
    33.   g_object_set (source, "pattern"0NULL);  
    34.     
    35.   /* Start playing */  
    36.   ret = gst_element_set_state (pipeline, GST_STATE_PLAYING);  
    37.   if (ret == GST_STATE_CHANGE_FAILURE) {  
    38.     g_printerr ("Unable to set the pipeline to the playing state. ");  
    39.     gst_object_unref (pipeline);  
    40.     return -1;  
    41.   }  
    42.     
    43.   /* Wait until error or EOS */  
    44.   bus = gst_element_get_bus (pipeline);  
    45.   msg = gst_bus_timed_pop_filtered (bus, GST_CLOCK_TIME_NONE, GST_MESSAGE_ERROR | GST_MESSAGE_EOS);  
    46.     
    47.   /* Parse message */  
    48.   if (msg != NULL) {  
    49.     GError *err;  
    50.     gchar *debug_info;  
    51.       
    52.     switch (GST_MESSAGE_TYPE (msg)) {  
    53.       case GST_MESSAGE_ERROR:  
    54.         gst_message_parse_error (msg, &err, &debug_info);  
    55.         g_printerr ("Error received from element %s: %s ", GST_OBJECT_NAME (msg->src), err->message);  
    56.         g_printerr ("Debugging information: %s ", debug_info ? debug_info : "none");  
    57.         g_clear_error (&err);  
    58.         g_free (debug_info);  
    59.         break;  
    60.       case GST_MESSAGE_EOS:  
    61.         g_print ("End-Of-Stream reached. ");  
    62.         break;  
    63.       default:  
    64.         /* We should not reach here because we only asked for ERRORs and EOS */  
    65.         g_printerr ("Unexpected message received. ");  
    66.         break;  
    67.     }  
    68.     gst_message_unref (msg);  
    69.   }  
    70.     
    71.   /* Free resources */  
    72.   gst_object_unref (bus);  
    73.   gst_element_set_state (pipeline, GST_STATE_NULL);  
    74.   gst_object_unref (pipeline);  
    75.   return 0;  
    76. }  


          工作流程

          GStreamer的基本组成是elements,这些elements把数据从source经过filter传到sink。


          建立element

          因为上一篇教程以及介绍过了初始化这段内容,所以我们这次略过这一段。

    [objc] view plain copy
     在CODE上查看代码片派生到我的代码片
    1. /* Create the elements */  
    2. source = gst_element_factory_make ("videotestsrc""source");  
    3. sink = gst_element_factory_make ("autovideosink""sink");  

          新的element的建立可以使用gst_element_factory_make()。这个API的第一个参数是要创建的element的类型(后面第14讲会介绍一些常见的类型,第10讲会介绍如何获得可用的类型列表),第二个参数是我们想创建的element的名字,这个名字并非是必须的,但在调试中会非常有用,如果你传入的时NULL,那么GStreamer会自动创建一个名字。

          在本教程内我们创建了2个elements:videotestsrc和autovideosink.

          vieotestsrc是一个source element(生产数据),会创建一个video模式。这个element常用在调试中,很少用于实际的应用。

          autovideosink是一个sink element(消费数据),会在一个窗口显示收到的图像。在不同的操作系统中,会存在多个的video sink,autovideosink会自动选择一个最合适的,所以你不需要关心更多的细节,代码也会有更好的移植性。


          建立pipeline

    [objc] view plain copy
     在CODE上查看代码片派生到我的代码片
    1. /* Create the empty pipeline */  
    2. pipeline = gst_pipeline_new ("test-pipeline");  
          因为要统一处理时钟和一些信息,GStreamer中的所有elements都必须在使用之前包含到pipeline中。我们用gst_pipeline_new()来创建pipeline。

    [objc] view plain copy
     在CODE上查看代码片派生到我的代码片
    1. /* Build the pipeline */  
    2. gst_bin_add_many (GST_BIN (pipeline), source, sink, NULL);  
    3. if (gst_element_link (source, sink) != TRUE) {  
    4.   g_printerr ("Elements could not be linked. ");  
    5.   gst_object_unref (pipeline);  
    6.   return -1;  
    7. }  

          一个pipeline就是一个特定类型的可以包含其他element的bin,而且所以可以用在bin上的方法也都可以用在pipeline上。在这个例子中,我们调用了gst_bin_add_many()方法在pipeline中加入element。这个方法会接受一系列的element作为输入参数,最后由NULL来终止。增加单个element的方法是gst_bin_add()。

          这个时候,这些刚增加的elements还没有互相连接起来。我们用gst_element_link()方法来把element连接起来,这个方法的第一个参数是源,第二个参数是目标,这个顺序不能搞错,因为这确定了数据的流向。记住只有在同一个bin里面的element才能连接起来,所以一定要把element在连接之前加入到pipeline中。


          属性

    [objc] view plain copy
     在CODE上查看代码片派生到我的代码片
    1. /* Modify the source's properties */  
    2. g_object_set (source, "pattern"0NULL);  
          绝大部分的GStreamer elements有可以定制化的属性:只读的属性会显示element的内部状态,可写的属性会影响element的行为。我们用g_object_get()方法来获得属性,用g_object_set()方法来设置属性。

          g_object_set()方法接受一个用NULL结束的属性名称/属性值的组成的对,所以可以一次同时修改多项属性。

          上面的代码修改了videotestsrc的“pattern”属性,这个属性控制了视频的输出,大家可以试试不同的值看一下效果。

          关于一个element的名字和取值范围,使用gst-inspect工具可以查询到。


          错误检查

          在这一点上,本系列的教程内容都比较相似,和第一讲没什么不同,只是我们监测更多的错误罢了。

    [objc] view plain copy
     在CODE上查看代码片派生到我的代码片
    1. /* Start playing */  
    2. ret = gst_element_set_state (pipeline, GST_STATE_PLAYING);  
    3. if (ret == GST_STATE_CHANGE_FAILURE) {  
    4.   g_printerr ("Unable to set the pipeline to the playing state. ");  
    5.   gst_object_unref (pipeline);  
    6.   return -1;  
    7. }  
          我们调用gst_element_set_state()方法,但这次我们检查它的返回值。状态转换是一个很微妙的过程,在下一篇教程中我们会有更多的一些细节。

    [objc] view plain copy
     在CODE上查看代码片派生到我的代码片
    1. /* Wait until error or EOS */  
    2. bus = gst_element_get_bus (pipeline);  
    3. msg = gst_bus_timed_pop_filtered (bus, GST_CLOCK_TIME_NONE, GST_MESSAGE_ERROR | GST_MESSAGE_EOS);  
    4.   
    5. /* Parse message */  
    6. if (msg != NULL) {  
    7.   GError *err;  
    8.   gchar *debug_info;  
    9.     
    10.   switch (GST_MESSAGE_TYPE (msg)) {  
    11.     case GST_MESSAGE_ERROR:  
    12.       gst_message_parse_error (msg, &err, &debug_info);  
    13.       g_printerr ("Error received from element %s: %s ", GST_OBJECT_NAME (msg->src), err->message);  
    14.       g_printerr ("Debugging information: %s ", debug_info ? debug_info : "none");  
    15.       g_clear_error (&err);  
    16.       g_free (debug_info);  
    17.       break;  
    18.     case GST_MESSAGE_EOS:  
    19.       g_print ("End-Of-Stream reached. ");  
    20.       break;  
    21.     default:  
    22.       /* We should not reach here because we only asked for ERRORs and EOS */  
    23.       g_printerr ("Unexpected message received. ");  
    24.       break;  
    25.   }  
    26.   gst_message_unref (msg);  
    27. }  
          gst_bus_timed_pop_filted()会一直等到运行结束,然后返回一个GstMessage参数。我们让gst_bus_timed_pop_filtered()方法仅在收到错误或者播放结束的消息时才返回。所以我们需要检查是哪个消息并打印出来。

          GstMessage是一个非常通用的结构,它可以传递很多信息。幸好GStreamer提供了一系列的解析函数,在本教程里面,我们一旦知道message里面包含一个错误(通过使用GST_MESSAGE_TYPE宏),我们可以使用gst_message_parse_error()方法,这个方法会返回一个GLib的GError结构。


          GStreamer总线

          这里稍微介绍一下GStreamer总线。GStreamer总线本身也是一个对象,是创建来传递elements生成的GstMessage的对象。消息可以在总线上用gst_bus_timed_pop_filtered()方法抓出来,你的应用需要随时注意出错的信息和播放相关的其他问题。

          其他的代码是释放内存的,和上一篇教程是一样的。

  • 相关阅读:
    时间同步装置|电力时间同步装置|GPS时间同步装置|网络时间同步装置
    北斗时钟服务器|北斗校时器|北斗卫星校时器|北斗卫星授时系统
    网络时间服务器|网络时钟服务器|网络授时服务器|网络校时服务器|时间同步服务器
    GPS时钟产品|gps时钟设备|gps时钟系统|gps时钟服务器|gps卫星同步时钟
    GPS授时系统|GPS时间同步系统|GPS网络时间服务器|NTP时间同步服务器
    GNOME 3 + Ubuntu 11.04
    数据手册中Accuracy和Precision的准确定义
    彻底解决COM端口被占用(在使用中)问题的办法
    Linux中查看进程及杀死进程命令
    Windows 7下硬盘安装Ubuntu
  • 原文地址:https://www.cnblogs.com/huty/p/8517327.html
Copyright © 2020-2023  润新知