Encode YUV420 buffer with appsrc

pchaurasia pchaurasia at gameloreinc.com
Fri Oct 6 18:41:46 UTC 2017


I would like to encode output of my opencv algorithm. THe buffer to encode is
not available exactly at 33 ms for encoder to encode at 30 fps.  It seems
there are two way I can send buffer-to-be-encoded to appsrc

a) VideoWriter::write method.

    GstCaps *caps;

    string aaDebugPipeline          = "appsrc name=myappsrc !
autovideoconvert ! omxh265enc ! matroskamux ! filesink location=test.mkv ";    
    m_ppipeline                        =
gst_parse_launch(aaDebugPipeline.c_str(),NULL);
    g_assert (m_ppipeline);

    m_pappsrc                          = gst_bin_get_by_name
(GST_BIN(m_ppipeline), "myappsrc");
    g_assert (m_pappsrc);

	caps = gst_caps_new_simple ("video/x-raw",
			"format",G_TYPE_STRING,"I420",
			"bpp",G_TYPE_INT,12,
			"depth",G_TYPE_INT,8,
			"width", G_TYPE_INT, 1920,
			"height", G_TYPE_INT, 1080,
			"pitch", G_TYPE_INT, 2048,
			"framerate", GST_TYPE_FRACTION, 30, 1,
			NULL);

    gst_app_src_set_caps(GST_APP_SRC(appsrc), caps);
     GstStateChangeReturn state_ret =
gst_element_set_state((GstElement*)m_ppipeline, GST_STATE_PLAYING);
     g_warning("set state returned %d\n", state_ret);  

   m_videoWriter.open(aaDebugPipeline,0, (double)30, cv::Size(1920, 1080),
false);
   if (!m_videoWriter.isOpened()) {
      REPORT_ERROR("can't create writer\n");
      exit(1);
   }


// call VideoWriter::write

m_videoWriter.write (cv::Mat imgY)  

However I am not able to specify format of buffer while calling
m_videoWriter::write() . Is there a way I can specify video frame format to
m_videoWriter.write() , in this methods ?

b) Can attach GstVideoMeta to a GstBuffer and pass that buffer to
gst_app_src_push_buffer().

void initAppSrc()
{
    GstStateChangeReturn state_ret;

    m_offset[0] = m_offset[1] = m_offset[2] = 0;
    m_stride[0] = 2048; // TBD : FIXME : no magic no
    m_stride[1] = 1024; 
    m_stride[2] = 1024;

    m_ppipeline            = (GstPipeline*)gst_pipeline_new("mypipeline");
    m_pappsrc              = (GstAppSrc*)gst_element_factory_make("appsrc",
"aa-appsrc");
    m_pvideoConvert        = gst_element_factory_make("autovideoconvert",
"aa-videoconvert");
    m_pencoder             = gst_element_factory_make("omxh265enc",
"aa-videoencoder");
    m_pmux                 = gst_element_factory_make("matroskamux",
"aa-mux");
    m_pfsink               = gst_element_factory_make("filesink",
"aa-filesink");


    g_assert(m_ppipeline);
    g_assert(m_pappsrc);
    g_assert(m_pvideoConvert);
    g_assert(m_pencoder);
    g_assert(m_pmux);
    g_assert(m_pfsink);


    g_signal_connect(m_pappsrc, "need-data", G_CALLBACK(start_feed), this);
    g_signal_connect(m_pappsrc, "enough-data", G_CALLBACK(stop_feed), this);

    g_object_set( G_OBJECT( m_pfsink ), "location", "test1.mkv", NULL ); 

    gst_bin_add_many(GST_BIN(m_ppipeline), (GstElement*)m_pappsrc,
m_pvideoConvert, m_pencoder, m_pmux, m_pfsink, NULL);

    if(!gst_element_link_many((GstElement*)m_pappsrc, m_pvideoConvert,
m_pencoder, m_pmux, m_pfsink)){
       g_warning("failed to link appsrc, autovideoconvert, encoder, muxer,
and filesink");
    }

    state_ret = gst_element_set_state((GstElement*)m_ppipeline,
GST_STATE_PLAYING);
    g_warning("set state returned %d\n", state_ret);
}

static gboolean read_data(gst_app_t *app)
{

// I would need to wait for opencv output here ; 
// Can this thread block ??

}

static void start_feed (GstElement * pipeline, guint size, gst_app_t *app)
{
 if (app->sourceid == 0) {
  GST_DEBUG ("start feeding");
  app->sourceid = g_idle_add ((GSourceFunc) read_data, app);
 }
}

static void stop_feed (GstElement * pipeline, gst_app_t *app)
{
 if (app->sourceid != 0) {
  GST_DEBUG ("stop feeding");
  g_source_remove (app->sourceid);
  app->sourceid = 0;
 }
}

void pushFrame()
{
    int size              = 1920*1080*1.5;
    m_pgstBuffer          = gst_buffer_new_wrapped_full( (GstMemoryFlags)0,
(gpointer)(img.data), size, 0, size, NULL, NULL );
    m_pgstVideoMeta       =
gst_buffer_add_video_meta_full(m_pgstBuffer,GST_VIDEO_FRAME_FLAG_NONE,
GST_VIDEO_FORMAT_I420, 1920,1080, 3, m_offset, m_stride );

    //ref buffer to give copy to appsrc
    gst_buffer_ref(m_pgstBuffer);


    GstFlowReturn ret;
    ret                  = gst_app_src_push_buffer((GstAppSrc*)m_pappsrc,
m_pgstBuffer);
    if(ret != GST_FLOW_OK)
    {
        g_printerr("could not push buffer\n");
        g_printerr("ret enum: %i\n", ret);
    }

    //dec. ref count so that we can edit data on next run
    gst_buffer_unref(m_pgstBuffer);

}


Here I am able to specify input GstBuffer format. But do not quite know how
to supply output of my opencv code to a function like pushFrame() ? Or
alternatively, if I make a queue between output of my opencv and appsrc read
function , read_data(), can this function block and wait for opencv output
to arrive ?

Thanks







--
Sent from: http://gstreamer-devel.966125.n4.nabble.com/


More information about the gstreamer-devel mailing list