当前位置: 首页 > news >正文

麻花星空影视传媒制作公司网站/社群运营

麻花星空影视传媒制作公司网站,社群运营,交互式网站开发,工程施工合同电子版摘要 GStreamer框架会自动处理多线程的逻辑,但在某些情况下,我们仍然需要根据实际的情况自己将部分Pipeline在单独的线程中执行,本文将介绍如何处理这种情况。 GStreamer多线程 GStreamer框架是一个支持多线程的框架,线程会根据P…

 

摘要

  GStreamer框架会自动处理多线程的逻辑,但在某些情况下,我们仍然需要根据实际的情况自己将部分Pipeline在单独的线程中执行,本文将介绍如何处理这种情况。

GStreamer多线程

  GStreamer框架是一个支持多线程的框架,线程会根据Pipeline的需要自动创建和销毁,例如,将媒体流与应用线程解耦,应用线程不会被GStreamer的处理阻塞。而且,GStreamer的插件还可以创建自己所需的线程用于媒体的处理,例如:在一个4核的CPU上,视频解码插件可以创建4个线程来最大化利用CPU资源。
  此外,在创建Pipeline时,我们还可以指定某个Pipeline的分支在不同的线程中执行(例如,使audio、video同时在不同的线程中进行解码)。这是通过queue Element来实现的,queue的sink pad仅仅将数据放入队列,另外一个线程从队列中取出数据,并传递到下一个Element。queue通常也被用于作为数据缓冲,缓冲区大小可以通过queue的属性进行配置。

  在上面的示例Pipeline中,souce是audiotestsrc,会产生一个相应的audio信号,然后使用tee Element将数据分为两路,一路被用于播放,通过声卡输出,另一路被用于转换为视频波形,用于输出到屏幕。
示例图中的红色阴影部分表示位于同一个线程中,queue会创建单独的线程,所以上面的Pipeline使用了3个线程完成相应的功能。拥有多个sink的Pipeline通常需要多个线程,因为在多个sync间进行同步的时候,sink会阻塞当前所在线程直到所等待的事件发生。

示例代码

示例代码将创建上图所示的Pipeline。

复制代码

#include <gst/gst.h>int main(int argc, char *argv[]) {GstElement *pipeline, *audio_source, *tee, *audio_queue, *audio_convert, *audio_resample, *audio_sink;GstElement *video_queue, *visual, *video_convert, *video_sink;GstBus *bus;GstMessage *msg;GstPad *tee_audio_pad, *tee_video_pad;GstPad *queue_audio_pad, *queue_video_pad;/* Initialize GStreamer */gst_init (&argc, &argv);/* Create the elements */audio_source = gst_element_factory_make ("audiotestsrc", "audio_source");tee = gst_element_factory_make ("tee", "tee");audio_queue = gst_element_factory_make ("queue", "audio_queue");audio_convert = gst_element_factory_make ("audioconvert", "audio_convert");audio_resample = gst_element_factory_make ("audioresample", "audio_resample");audio_sink = gst_element_factory_make ("autoaudiosink", "audio_sink");video_queue = gst_element_factory_make ("queue", "video_queue");visual = gst_element_factory_make ("wavescope", "visual");video_convert = gst_element_factory_make ("videoconvert", "csp");video_sink = gst_element_factory_make ("autovideosink", "video_sink");/* Create the empty pipeline */pipeline = gst_pipeline_new ("test-pipeline");if (!pipeline || !audio_source || !tee || !audio_queue || !audio_convert || !audio_resample || !audio_sink ||!video_queue || !visual || !video_convert || !video_sink) {g_printerr ("Not all elements could be created.\n");return -1;}/* Configure elements */g_object_set (audio_source, "freq", 215.0f, NULL);g_object_set (visual, "shader", 0, "style", 1, NULL);/* Link all elements that can be automatically linked because they have "Always" pads */gst_bin_add_many (GST_BIN (pipeline), audio_source, tee, audio_queue, audio_convert, audio_resample, audio_sink,video_queue, visual, video_convert, video_sink, NULL);if (gst_element_link_many (audio_source, tee, NULL) != TRUE ||gst_element_link_many (audio_queue, audio_convert, audio_resample, audio_sink, NULL) != TRUE ||gst_element_link_many (video_queue, visual, video_convert, video_sink, NULL) != TRUE) {g_printerr ("Elements could not be linked.\n");gst_object_unref (pipeline);return -1;}/* Manually link the Tee, which has "Request" pads */tee_audio_pad = gst_element_get_request_pad (tee, "src_%u");g_print ("Obtained request pad %s for audio branch.\n", gst_pad_get_name (tee_audio_pad));queue_audio_pad = gst_element_get_static_pad (audio_queue, "sink");tee_video_pad = gst_element_get_request_pad (tee, "src_%u");g_print ("Obtained request pad %s for video branch.\n", gst_pad_get_name (tee_video_pad));queue_video_pad = gst_element_get_static_pad (video_queue, "sink");if (gst_pad_link (tee_audio_pad, queue_audio_pad) != GST_PAD_LINK_OK ||gst_pad_link (tee_video_pad, queue_video_pad) != GST_PAD_LINK_OK) {g_printerr ("Tee could not be linked.\n");gst_object_unref (pipeline);return -1;}gst_object_unref (queue_audio_pad);gst_object_unref (queue_video_pad);/* Start playing the pipeline */gst_element_set_state (pipeline, GST_STATE_PLAYING);/* Wait until error or EOS */bus = gst_element_get_bus (pipeline);msg = gst_bus_timed_pop_filtered (bus, GST_CLOCK_TIME_NONE, GST_MESSAGE_ERROR | GST_MESSAGE_EOS);/* Release the request pads from the Tee, and unref them */gst_element_release_request_pad (tee, tee_audio_pad);gst_element_release_request_pad (tee, tee_video_pad);gst_object_unref (tee_audio_pad);gst_object_unref (tee_video_pad);/* Free resources */if (msg != NULL)gst_message_unref (msg);gst_object_unref (bus);gst_element_set_state (pipeline, GST_STATE_NULL);gst_object_unref (pipeline);return 0;
}

复制代码

保存以上代码,执行下列编译命令即可得到可执行程序:

gcc basic-tutorial-8.c -o basic-tutorial-8 `pkg-config --cflags --libs gstreamer-1.0`

源码分析

复制代码

/* Create the elements */
audio_source = gst_element_factory_make ("audiotestsrc", "audio_source");
tee = gst_element_factory_make ("tee", "tee");
audio_queue = gst_element_factory_make ("queue", "audio_queue");
audio_convert = gst_element_factory_make ("audioconvert", "audio_convert");
audio_resample = gst_element_factory_make ("audioresample", "audio_resample");
audio_sink = gst_element_factory_make ("autoaudiosink", "audio_sink");
video_queue = gst_element_factory_make ("queue", "video_queue");
visual = gst_element_factory_make ("wavescope", "visual");
video_convert = gst_element_factory_make ("videoconvert", "video_convert");
video_sink = gst_element_factory_make ("autovideosink", "video_sink");

复制代码

  首先创建所需的Element:audiotestsrc会产生测试的音频波形数据。wavescope 会将输入的音频数据转换为波形图像。audioconvert,audioresample,videoconvert保证了Pipeline中各个Element之间的数据可以互相兼容,使得Pipeline能够被正确的link起来,如果不需要对数据进行转换,这些Element会直接将数据发送到下一个Element,这种情况下的性能影响可以忽略不计。

/* Configure elements */
g_object_set (audio_source, "freq", 215.0f, NULL);
g_object_set (visual, "shader", 0, "style", 1, NULL);

  这里修改相应Element的参数,使得输出结果更直观。“freq”会设置audiotestsrc输出波形的频率为215Hz,设置“shader”和“style”使得波形更加连续。其他的参数可以通过gst-inspect查看。

复制代码

/* Link all elements that can be automatically linked because they have "Always" pads */
gst_bin_add_many (GST_BIN (pipeline), audio_source, tee, audio_queue, audio_convert, audio_sink,video_queue, visual, video_convert, video_sink, NULL);
if (gst_element_link_many (audio_source, tee, NULL) != TRUE ||gst_element_link_many (audio_queue, audio_convert, audio_sink, NULL) != TRUE ||gst_element_link_many (video_queue, visual, video_convert, video_sink, NULL) != TRUE) {g_printerr ("Elements could not be linked.\n");gst_object_unref (pipeline);return -1;
}

复制代码

  这里我们使用gst_element_link_many 将多个Element连接起来,需要注意的是,这里我们只连接了拥有Always Pad的Eelement。虽然gst_element_link_many() 能够在内部处理Request Pad的情况,但我们仍然需要单独释放Request Pad,如果直接使用此函数连接所有的Element,这样容易忘记释放Request Pad。因此我们使用下面的代码单独处理Request Pad。

复制代码

/* Manually link the Tee, which has "Request" pads */
tee_audio_pad = gst_element_get_request_pad (tee, "src_%u");
g_print ("Obtained request pad %s for audio branch.\n", gst_pad_get_name (tee_audio_pad));
queue_audio_pad = gst_element_get_static_pad (audio_queue, "sink");
tee_video_pad = gst_element_get_request_pad (tee, "src_%u");
g_print ("Obtained request pad %s for video branch.\n", gst_pad_get_name (tee_video_pad));
queue_video_pad = gst_element_get_static_pad (video_queue, "sink");
if (gst_pad_link (tee_audio_pad, queue_audio_pad) != GST_PAD_LINK_OK ||gst_pad_link (tee_video_pad, queue_video_pad) != GST_PAD_LINK_OK) {g_printerr ("Tee could not be linked.\n");gst_object_unref (pipeline);return -1;
}
gst_object_unref (queue_audio_pad);
gst_object_unref (queue_video_pad);

复制代码

  为了能够连接到Request Pad,我们需要主动的向Element取得相应的Pad。由于一个Element可以提供不同的Request Pad,所以我们需要指定所需的“Pad Template”,Element提供的Pad Template可以通过gst-inspect查看。从下面的结果可以发现,tee提供了2种类型的模板, ”sink“ 和“src_%u"。

复制代码

$ gst-inspect-1.0  tee
...
Pad Templates:SRC template: 'src_%u'Availability: On requestHas request_new_pad() function: gst_tee_request_new_padCapabilities:ANYSINK template: 'sink'Availability: AlwaysCapabilities:ANY
...

复制代码

  由于我们这里需要的是2个Source Pad,所以我们通过gst_element_get_request_pad (tee, "src_%u")获取两个Request Pad分别用于audio和video。queue的Sink Pad是Alwasy Pad,所以我们直接使用gst_element_get_static_pad 获取其Sink Pad。最后再通过gst_pad_link()将其连接起来,在gst_element_link()和gst_element_link_many()内部也是使用此函数连接两个Element的Pad。

需要注意的是,我们通过Element获取到的Pad的引用计数会自动增加,因此我们需要调用gst_object_unref()释放相关的引用,对于Request Pad,我们需要在Pipeline执行完成后进行释放。

 

/* Release the request pads from the Tee, and unref them */
gst_element_release_request_pad (tee, tee_audio_pad);
gst_element_release_request_pad (tee, tee_video_pad);
gst_object_unref (tee_audio_pad);
gst_object_unref (tee_video_pad);

除了播放完成后正常的资源释放外,我们还要对Request进行释放,需要首先调用gst_element_release_request_pad(),最后再释放相应的对象。

总结

我们在本文中了解了:

  • 如何通过queue让Pipeline运行在多个线程上。
  • 如何通过gst_element_get_request_pad(), gst_pad_link() gst_element_release_request_pad() 对Request Pad进行操作。
  • 如何使用tee将一路媒体数据分为多路。

 

引用

https://gstreamer.freedesktop.org/documentation/tutorials/basic/multithreading-and-pad-availability.html?gi-language=c

作者:John.Leng

出处:http://www.cnblogs.com/xleng/

本文版权归作者所有,欢迎转载。商业转载请联系作者获得授权,非商业转载请在文章页面明显位置给出原文连接.

http://www.jmfq.cn/news/5284945.html

相关文章:

  • 飞卢盗版做的最好的网站/竞价推广开户公司
  • 彩票网站开发演示/sem优化技巧
  • 苏宁易购网站设计怎么制作/外贸网站建设平台
  • 厦门网站建设格/网站如何添加友情链接
  • 海南建设培训与执业中心网站/关键词排名怎么上首页
  • wordpress微信授权登录/seo网站关键词优化方式
  • 英文网站建设服务合同模板下载/会计培训班一般收费多少
  • 运用django做网站/今天重大新闻头条新闻军事
  • 上海闵行最新封闭通知/完善的seo网站
  • 做网站的流程图/公司网站制作
  • 杭州网站设计公司哪家好/杭州seo
  • 外贸搜索网站/西安seo关键词排名优化
  • 安徽省做网站/开发一个小程序一般需要多少钱呢
  • 在百度上做网站推广怎么弄/推广价格一般多少
  • 哪些网站可以免费做代码/天津seo方案
  • 网站开发工具 售价/制作网站首页
  • 桂林市电力建设公司网站/互联网营销师报名费
  • 个人做网站花多少钱/微信小程序开发费用
  • 建设网站应达到的目的和作用/网络营销推广方法有哪些
  • 兼职做Ppt代抄论文的网站/2022黄页全国各行业
  • 网站banner制作/网站站长工具
  • 情侣做记录网站源码/百度扫一扫入口
  • 个人网站 怎么备案/短视频获客系统
  • 留学网站模板/外贸营销推广
  • 网站模板怎么用dreamweaver编辑/网站关键词优化有用吗
  • 创立一个公司需要什么/seo是一种利用搜索引擎
  • 表白网页在线生成网站/周口网站制作
  • 印刷行业网站建设/台州seo网站排名优化
  • 在线医疗网站建设/武汉百度开户电话
  • 找做金融的网站有哪些/网站结构优化的内容和方法