"); //-->
上篇我们介绍了骁龙820A关于多媒体处理框架元件相关的概念和基本介绍。本篇我们将进行箱柜(Bins)和管道(pipeline)的介绍。
基础概念介绍---箱柜(Bins)
• 箱柜(Bins)是一个可以装载元件(element)的容器。
• 同时箱柜本身也是一种元件,所以你能够象操作普通元件一样的
操作一个箱柜,可以改变一个箱柜的状态来改变箱柜内部所有元
件的状态。
• 箱柜可以发送总线消息给它的子集元件 (这些消息包括:错误消息
(error messages),标签消息(tag messages),EOS消息(EOS messages))。
创建箱柜
• 你可以通过使用创建其他元件的方法来创建一个箱柜,如使用元件工厂等。当然也有一些更便利的函数来创建箱柜— (gst_bin_new()和gst_pipeline_new ())。你可以使用gst_bin_add()往箱柜中增加元件,使用gst_bin_remove()移除箱柜中的元件。当你往箱柜中增加一个元件后,箱柜会对该元件产生一个所属关系;(dereferenced); 当你销毁一个箱柜后,箱柜中的元件同样被销毁 当你将一个元件从箱柜移除后,该元件会被自动销毁(dereferenced)。
#include <gst/gst.h> int main (int argc, char *argv[]) { GstElement *bin, *pipeline, *source, *sink; /* init */ gst_init (&argc, &argv); /* create */ pipeline = gst_pipeline_new ("my_pipeline"); bin = gst_pipeline_new ("my_bin"); source = gst_element_factory_make ("fakesrc", "source"); sink = gst_element_factory_make ("fakesink", "sink"); /* set up pipeline */ gst_bin_add_many (GST_BIN (bin), source, sink, NULL); gst_bin_add (GST_BIN (pipeline), bin); gst_element_link (source, sink); [..] }
基础概念介绍---管道(pipeline)
• 管道(pipeline)是箱柜(Bin)的一个特殊的子类型,管道可以操作包含在它自身内部的所有元件。
• 管道是高级的箱柜。当你设定管道的暂停或者播放状态的时候,数据流将开始流动,并且媒体数据处理也开始处理。一旦开始,管道将在一个单独的线程中运行,直到被停止或者数据流播放完毕。
总线(Bus)
• 总线是一个简单的系统,它采用自己的线程机制将一个管道线程的消息分发到一个应用程序当中。
• 每一个管道默认包含一个总线,所以应用程序不需要再创建总线。应用程序只需要在总线上设置一个类似于对象的信号处理器的消息处理器。当主循环运行的时候,总线将会轮询这个消息处理器是否有新的消息,当消息被采集到后,总线将呼叫相应的回调函数来完成任务。
• 使用总线有两种方法,如下:
• 运行GLib/Gtk+ 主循环(你也可以自己运行默认的GLib的主循环),然后使用侦听器对总线进行侦听。使用这种方法,GLib的主循环将轮询总线上是否存在新的消息,当存在新的消息的时候,总线会马上通知你。在这种情况下,你会用到gst_bus_add_watch()gst_bus_add_signal_watch()两个函数。当使用总线时,设置消息处理器到管道的总线上可以使用gst_bus_add_watch () 来创建一个消息处理器来侦听管道。每当管道发出一个消息到总线,这个消息处理器就会被触发,消息处理器则开始检测消息信号类型从而决定哪些事件将被处理。当处理器从总线删除某个消息的时候,其返回值应为TRUE。
• 自己侦听总线消息,使用gst_bus_peek () 和/或 gst_bus_poll () 就可以实现。
消息类型(Message types)
• 应用程序至少要处理错误消息并直接的反馈给用户。
• 错误、警告和消息示:它们被各个元件用来在必要的时候告知用户现在管道的状态。错误信息表明有致命的错误并且终止数据传送。错误应该被修复,这样才能继续管道的工作。警告并不是
致命的,但是暗示有问题存在。
• 数据流结束(End-of-stream)示:当数据流结束的时候,该消息被发送。管道的状态不会改变,但是之后的媒体操作将会停止。
• 状态转换(State-changes):当状态成功的转换时发送该消息。
• 缓冲(Buffering):当缓冲网络数据流时此消息被发送。
上面我们演示了如何自动生成一个pipeline。这次我们打算用一个个element来手动搭建
一个pipeline。
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.\n"); 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.\n"); 28. gst_object_unref (pipeline); 29. return -1; 30. }
新的element的建立可以使用gst_element_factory_make()。这个API的第一个参数是要创建的element的类型,第二个参数是我们想创建的element的名字,这个名字并非是必须的,但在调试中会非常有用,如果你传入的时NULL,那么GStreamer会自动创建一个名字。
我们创建了2个elements: videotestsrc和autovideosink.
vieotestsrc是一个source element(源元件)。 这个element常用在调试中,很少用于实际的应用。
autovideosink是一个sink element(接收元件), 会在一个窗口显示收到的图像。在不同的操作系统中,会存在多个的video sink, autovideosink会自动选择一个最合适的,所以你不需要关心更多的细节,代码也会有更好的移植性。因为要统一处理时钟和一些信息, GStreamer中的所有elements都必须在使用之前包含到pipeline中。我们用gst_pipeline_new()来创建pipeline。一个pipeline就是一个特定类型的可以包含其他element的bin,而且所有可
以用在bin上的方法也都可以用在pipeline上。我们调用了gst_bin_add_many()
方法在pipeline中加入element。这个时候,这些刚增加的elements还没有互相连接起来。我们用gst_element_link()方法来把element连接起来,这个方法的第一个参数是源,第二个参数是目标,这个顺序不能搞错,因为这确定了数据的流向。记住只有在同一个bin里面的element才能连接起来,所以一定要把element在连接之前加入到pipeline中。
1. 2. /* Modify the source's properties */ 3. g_object_set (source, "pattern", 0, NULL); 4. 5. /* Start playing */ 6. ret = gst_element_set_state (pipeline, GST_STATE_PLAYING); 7. if (ret == GST_STATE_CHANGE_FAILURE) { 8. g_printerr ("Unable to set the pipeline to the playing state.\n"); 9. gst_object_unref (pipeline); 10. return -1; 11. } 12. 13. /* Wait until error or EOS */ 14. bus = gst_element_get_bus (pipeline); 15. msg = gst_bus_timed_pop_filtered (bus, GST_CLOCK_TIME_NONE, GST_MESSAGE_ERROR | GST_MESSAGE_EOS); 16. 1. /* Parse message */ 2. if (msg != NULL) { 3. GError *err; 4. gchar *debug_info; 5. 6. switch (GST_MESSAGE_TYPE (msg)) { 7. case GST_MESSAGE_ERROR: 8. gst_message_parse_error (msg, &err, &debug_info); 9. g_printerr ("Error received from element %s: %s\n", GST_OBJECT_NAME (msg- >src), err->message); 10. g_printerr ("Debugging information: %s\n", debug_info ? debug_info : "none"); 11. g_clear_error (&err); 12. g_free (debug_info); 13. break; 14. case GST_MESSAGE_EOS: 15. g_print ("End-Of-Stream reached.\n"); 16. break; 17. default: 18. /* We should not reach here because we only asked for ERRORs and EOS */ 19. g_printerr ("Unexpected message received.\n"); 20. break; 21. } 22. gst_message_unref (msg); 23. } 24. 25. /* Free resources */ 26. gst_object_unref (bus); 27. gst_element_set_state (pipeline, GST_STATE_NULL); 28. gst_object_unref (pipeline); 29. return 0; 30.}
用g_object_set()方法来设置属性。 g_object_set()方法接受一个用NULL结束的属性名称/属性值的组成的对,所以可以一次同时修改多项属性。上面的代码修改了videotests的"pattern"属性,这个属性控制了视频的输出.
关于管道和Bins的介绍及先到这里,后面我们会对Gst的pads进行详细的介绍,由此才能进入工具篇来详细介绍工具的使用。
*博客内容为网友个人发布,仅代表博主个人观点,如有侵权请联系工作人员删除。