GStreamer 从摄像头获取图像 转264

Stella981
• 阅读 1305

  1、这里有个简单的例子,可以看看GStreamer如何编程的。

  2、GStreamer  GstAppSink的官方Document,翻译了一下它的描述部分,点击这里

  3、GStreamer  GstAppSrc的官方Document,翻译了以下它的描述部分,点击这里

  4、GStreamer中的Padscapabilities

       Pads 允许信息进入或者离开一个element,这个Capabilities(简称Caps)就是指定哪些信息可以通过Pad来传输。例如:“RGB视频,尺寸为320*200并且每秒30帧”或者“16位的音频采样,5.1声道,每秒采样44.1k” 甚至可以是类似于mp3/h264之类的压缩格式。

  Pads支持多重Capabilities(比如,一个视频的sink可以支持RGB输出或者YUV输出),Capabilites可以指定一个范围而不必须是一个特定值(比如,一个音频sink可以支持从1~48000的采样率)。然而,数据从一个pad流向另一个pad的时候,必须是一个双方都能支持的格式。某一种数据形式是两个pad都能支持的,这样pads的Capabilities就固定下来,这个过程就被称为协商。

  作为一个应用开发者,我们通常都是用连接一个个element的方法来建立pipeline的,在这里,你需要了解使用的element的Pad的Caps。

  5、Pad模板

  Pad是由Pad模板创建的,模板里面会列出一个Pad所有可能的Capabilities。模板对于创建几个相似的Pad是很有帮助的,但也会比较早的判断出两个element是否可以连接:如果两个Pad的模板都不具备共同的子集的话,就没有必要进行更深层的协商了。

  Pad模板检查是协商流程的第一步。随着流程的逐步深入,Pad会正式初始化,也会确定他们的Capability(除非协商失败)

  6、queue

  queue element会创建一个新的线程。通常来说,有多于一个sink element时就需要使用多个线程。这是因为在同步时,sink通常是阻塞起来等待其他的sink都准备好,如果仅仅只有一个线程是如法做到这一点的。

  7、tee

  tee比较特别但很有用,tee有1个输入pad而没有输出pad,需要有申请,tee才会生成。通过这种方法,输入流可以被复制成多份。和Always Pad比起来,Request Pad因为并非一直存在,所以是不能自动连接element的。

  例子:

GStreamer 从摄像头获取图像 转264

  建立一个如上的pipeline的步骤如下:

  1)初始化GStreamer;

  2)创建上图中的所有element;

  3)创建pipeline;

  4)配置element;

  5)把element放进pipeline中,然后将可以连接起来的原件连接起来;

      (1)app source -> tee  (2)audio_queue -> audio_convert -> audio_resample -> audio_sink  (3)video_queue ->wave_scope->video_convert->video_sink

  6) 手工连接tee->audio_queue和tee->video_queue;

  7)设置pipeline状态为PLAYING;

  8)监测BUS信号即可。

  上诉过程的代码可以参考官方文档:https://gstreamer.freedesktop.org/documentation/tutorials/basic/multithreading-and-pad-availability.html

  同时也可以参考《GStreamer讲解.pdf》 P56。

  关于上面的第6步,两个参考讲解还有一点不一致,官方文档更简单,需要进一步测试才能确定这两种方式是不是都可行。

从GStreamer获取摄像头数据的代码:

1、h文件

GStreamer 从摄像头获取图像 转264 GStreamer 从摄像头获取图像 转264

 1 #ifndef GSTREAMERVIDEOENCODER_H
 2 #define GSTREAMERVIDEOENCODER_H
 3 
 4 #include <QObject>
 5 #include <QWidget>
 6 #include <gst/gst.h>
 7 #include <gst/app/gstappsink.h>
 8 #include <gst/app/gstappsrc.h>
 9 #include <glib.h>
10 #include <iostream>
11 #include <sstream>
12 #include <thread>
13 #include "../IOutputOrignalImage.h"
14 #include "../GlobalData.h"
15 
16 class GStreamerCameraExtract
17 {
18 public:
19     GStreamerCameraExtract() {}
20     ~GStreamerCameraExtract() {}
21 
22 public:
23     GstBus *bus;
24     GstElement *pipeline;
25     GstMessage *msg;
26     GstElement *v4l2_src;
27     GstAppSink* appsink;
28     GstElement *src_caps_filter;
29     GstCaps *caps_src;
30     GstCaps *caps_sink;
31     GstElement *video_convert;
32     GstElement *h264Encoder;
33     GstAppSinkCallbacks appsink_callbacks;
34     QByteArray cameraBuffer;
35     IOutputOrignalImage *callback;
36 
37 public:
38     int CreateCameraExtractPipeline();
39     void ReadLocalCameraImage();
40     void StopPipeline();
41 };
42 
43 #endif // GSTREAMERVIDEOENCODER_H

View Code

2、cpp文件

GStreamer 从摄像头获取图像 转264 GStreamer 从摄像头获取图像 转264

  1 #include "GStreamerCameraExtract.h"
  2 
  3 static GstFlowReturn appsink_new_sample_callback(GstAppSink *slt,gpointer user_data)
  4 {
  5     GStreamerCameraExtract *encoder = (GStreamerCameraExtract *)user_data;
  6 
  7     encoder->ReadLocalCameraImage();
  8 }
  9 
 10 void GStreamerCameraExtract::ReadLocalCameraImage()
 11 {
 12     gint height;
 13     gint width;
 14 
 15     GstSample * sample = gst_app_sink_pull_sample(appsink);
 16 
 17     GstBuffer * gstImageBuffer= gst_sample_get_buffer(sample);
 18     GstCaps * caps = gst_sample_get_caps(sample);
 19     const GstStructure *caps_st = gst_caps_get_structure (caps, 0);
 20 
 21     if ((gst_structure_get_int (caps_st, "width", &width) != 0) && \
 22             (gst_structure_get_int (caps_st, "height", &height) != 0) )
 23     {
 24         cameraBuffer.resize(width*height*3);
 25 
 26         gst_buffer_extract(gstImageBuffer, 0, cameraBuffer.data(), cameraBuffer.size());
 27 
 28         callback->OutputOrignalImage(&cameraBuffer);
 29     }
 30 
 31     gst_buffer_unref(gstImageBuffer);
 32     //gst_sample_unref(sample);             //一定不能添加这一句
 33 }
 34 
 35 void GStreamerCameraExtract::StopPipeline()
 36 {
 37     gst_element_set_state(pipeline,GST_STATE_NULL);
 38     g_object_unref(pipeline);
 39 
 40     g_object_unref(bus);
 41 }
 42 
 43 int GStreamerCameraExtract::CreateCameraExtractPipeline()
 44 {
 45     pipeline = gst_pipeline_new("mypipeline");
 46     v4l2_src = gst_element_factory_make("v4l2src","src");
 47     src_caps_filter = gst_element_factory_make("capsfilter","srccapsfilter");
 48     caps_src = gst_caps_new_simple("video/x-raw",
 49                                    "width",G_TYPE_INT,PICTURE_WIDTH,
 50                                    "height",G_TYPE_INT,PICTURE_HEIGHT,
 51                                    "framerate",GST_TYPE_FRACTION,FRAME_PER_SECOND,1,
 52                                    NULL);
 53     caps_sink = gst_caps_new_simple("video/x-raw",
 54                                     "format",G_TYPE_STRING,"RGB",
 55                                     "colorimetry",G_TYPE_STRING,"bt709",
 56                                     "width",G_TYPE_INT,PICTURE_WIDTH,
 57                                     "height",G_TYPE_INT,PICTURE_HEIGHT,NULL);
 58     video_convert = gst_element_factory_make("videoconvert","videoconv");
 59     appsink = (GstAppSink*)gst_element_factory_make("appsink","sink1");
 60 
 61     if(!pipeline || !v4l2_src ||!src_caps_filter \
 62             ||!caps_src ||!appsink \
 63             ||!caps_sink || !video_convert )
 64     {
 65         std::cout<<"create element error"<<std::endl;
 66         return -1;
 67     }
 68 
 69     g_object_set(v4l2_src,"device",CAMERA_DEVICE_NAME,NULL);
 70 
 71     g_object_set(src_caps_filter,"caps",caps_src,NULL);
 72     gst_caps_unref(caps_src);
 73 
 74     gst_app_sink_set_caps(appsink,caps_sink);
 75     gst_caps_unref(caps_sink);
 76 
 77     gst_bin_add_many(GST_BIN(pipeline),v4l2_src,src_caps_filter,video_convert,appsink,NULL);
 78 
 79     if(gst_element_link_many(v4l2_src,src_caps_filter,video_convert,appsink,NULL) == FALSE)
 80     {
 81         std::cout<<"link src & appsink error!"<<std::endl;
 82         gst_object_unref(pipeline);
 83         return -1;
 84     }
 85 
 86     gst_app_sink_set_drop(appsink, true);
 87     gst_app_sink_set_max_buffers(appsink, 1);
 88 
 89     appsink_callbacks = {NULL,NULL,appsink_new_sample_callback,NULL};
 90     gst_app_sink_set_callbacks(appsink,&appsink_callbacks,this,NULL);
 91 
 92     g_signal_connect(pipeline, "deep-notify", G_CALLBACK(gst_object_default_deep_notify), NULL);
 93 
 94     int ret = gst_element_set_state(pipeline,GST_STATE_PLAYING);
 95     if(ret == GST_STATE_CHANGE_FAILURE)
 96     {
 97         std::cout<<"set playing state error!"<<std::endl;
 98     }
 99 
100     bus = gst_element_get_bus(pipeline);
101 
102     return 0;
103 }

View Code

使用GStreamer 将摄像头数据采用硬件编码为H264格式数据的代码,暂不贴出了。

点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
待兔 待兔
5个月前
手写Java HashMap源码
HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22
Jacquelyn38 Jacquelyn38
3年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
Wesley13 Wesley13
3年前
Java获得今日零时零分零秒的时间(Date型)
publicDatezeroTime()throwsParseException{    DatetimenewDate();    SimpleDateFormatsimpnewSimpleDateFormat("yyyyMMdd00:00:00");    SimpleDateFormatsimp2newS
Wesley13 Wesley13
3年前
mysql设置时区
mysql设置时区mysql\_query("SETtime\_zone'8:00'")ordie('时区设置失败,请联系管理员!');中国在东8区所以加8方法二:selectcount(user\_id)asdevice,CONVERT\_TZ(FROM\_UNIXTIME(reg\_time),'08:00','0
Wesley13 Wesley13
3年前
00:Java简单了解
浅谈Java之概述Java是SUN(StanfordUniversityNetwork),斯坦福大学网络公司)1995年推出的一门高级编程语言。Java是一种面向Internet的编程语言。随着Java技术在web方面的不断成熟,已经成为Web应用程序的首选开发语言。Java是简单易学,完全面向对象,安全可靠,与平台无关的编程语言。
Stella981 Stella981
3年前
Django中Admin中的一些参数配置
设置在列表中显示的字段,id为django模型默认的主键list_display('id','name','sex','profession','email','qq','phone','status','create_time')设置在列表可编辑字段list_editable
Wesley13 Wesley13
3年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
Python进阶者 Python进阶者
11个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这