zoukankan      html  css  js  c++  java
  • GStreamer 从摄像头获取图像 转264

      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的。

      例子:

      建立一个如上的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文件

     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文件

      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格式数据的代码,暂不贴出了。

  • 相关阅读:
    并行计算第一次作业(openmp)
    数据结构入门第二课(浙大mooc笔记)
    数据结构入门第一课(浙大mooc笔记)
    手把手教你用java实现syslog消息的收发,学不会你打我喽!
    单例模式你真的会了吗(上篇)?
    redis分布式锁,面试官请随便问,我都会
    快手面试归来篇一,希望你看后能过
    程序员不会理财,那跟咸鱼有什么区别?
    人生的康波周期,把握住一次,足以改变命运!
    各大公司面试题分类整理
  • 原文地址:https://www.cnblogs.com/kanite/p/10743085.html
Copyright © 2011-2022 走看看