0

我正在尝试为 gstreamer 管道(如下所示)编写 c++ 代码,我可以调整其帧速率。

gst-launch-1.0 filesrc location= VD19_peoplewalking.mp4 ! qtdemux ! h264parse ! nvv4l2decoder ! nvvideoconvert ! videorate ! capsfilter ! "video/x-raw(ANY), width=384,height=288,framerate=7/1" ! nveglglessink

我可以通过更改framerate通过终端运行管道。例如

gst-launch-1.0 filesrc location= VD19_peoplewalking.mp4 ! qtdemux ! h264parse ! nvv4l2decoder ! nvvideoconvert ! videorate ! capsfilter ! "video/x-raw(ANY), width=384,height=288,framerate=1/1" ! nveglglessink

在代码中,我尝试使用g_object_set()设置帧速率,如下所示

GstCaps *filtercaps;
    
filtercaps = gst_caps_new_simple ("video/x-raw",
                   "width", G_TYPE_INT, 384,
                   "height", G_TYPE_INT, 288,
                   "framerate", GST_TYPE_FRACTION, 7,1,
                   NULL);
    
g_object_set (G_OBJECT (filter1), "caps", filtercaps, NULL);

插件元素及其链接方式如下所示

GstElement *src, *dbin, *conv, *mux, *parse, *pipeline;

GstElement *videorate1, *sink1, *filter1;
    
pipeline = gst_pipeline_new (NULL);
src = gst_element_factory_make ("filesrc", NULL);
mux = gst_element_factory_make("qtdemux",NULL);
parse = gst_element_factory_make("h264parse",NULL);
dbin = gst_element_factory_make ("nvv4l2decoder", NULL);
conv = gst_element_factory_make ("nvvideoconvert", NULL);
sink1 = gst_element_factory_make ("nveglglessink", NULL);
filter1 = gst_element_factory_make ("capsfilter", "filter");
videorate1 = gst_element_factory_make("videorate",NULL);
 

    gst_bin_add_many (GST_BIN (pipeline), src, dbin, conv, mux, parse, videorate1, filter1, sink1, NULL);

    if (!gst_element_link_many(src,mux,NULL) || !gst_element_link_many(parse,dbin, conv, videorate1, filter1 ,sink1, NULL) )//|| !gst_element_link_many (conv, tee, NULL))
    {
    std::cout << "test1\n";
    g_error("Failed to link elements");
    return -3;
    }

每当我在代码中将帧速率更改为视频的原始帧速率(此处为 7)以外的任何其他值时,我都会遇到错误。

在此处输入图像描述

注意:mux (qtdemux)parse (h264parse)在运行时通过调用回调函数链接pad_added_handler

作为参考,我在下面粘贴整个代码

#include <iostream>
#include <string.h>
#include <gst/gst.h>
#include <gst/app/app.h>


using namespace std;

GstElement *src, *dbin, *conv, *mux, *parse, *pipeline;

GstElement *videorate1, *sink1, *filter1;



GMainLoop *loop;

static gboolean
message_cb (GstBus * bus, GstMessage * message, gpointer user_data)
{
  //Cpipeline *obj_pipeline = (Cpipeline*)user_data;
  switch (GST_MESSAGE_TYPE (message)) {
    case GST_MESSAGE_ERROR:{
      GError *err = NULL;
      gchar *name, *debug = NULL;

      name = gst_object_get_path_string (message->src);
      gst_message_parse_error (message, &err, &debug);

      g_printerr ("ERROR: from element %s: %s\n", name, err->message);
      if (debug != NULL)
        g_printerr ("Additional debug info:\n%s\n", debug);

      g_error_free (err);
      g_free (debug);
      g_free (name);

      g_main_loop_quit (loop);
      break;
    }
    case GST_MESSAGE_WARNING:{
      GError *err = NULL;
      gchar *name, *debug = NULL;

      name = gst_object_get_path_string (message->src);
      gst_message_parse_warning (message, &err, &debug);

      g_printerr ("ERROR: from element %s: %s\n", name, err->message);
      if (debug != NULL)
        g_printerr ("Additional debug info:\n%s\n", debug);

      g_error_free (err);
      g_free (debug);
      g_free (name);
      break;
    }
    case GST_MESSAGE_EOS:
      g_print ("\nGot EOS\n");
      g_main_loop_quit (loop);
      break;
    default:
      break;
  }

  return TRUE;
}


static void pad_added_handler (GstElement *src, GstPad *new_pad, gpointer x) 
{
    std::cout << "\nHi inside pad_added_handler\n";
    GstPad *sink_pad = gst_element_get_static_pad (parse, "sink");
    GstPadLinkReturn ret;
    GstCaps *new_pad_caps = NULL;
    GstStructure *new_pad_struct = NULL;
    const gchar *new_pad_type = NULL;


    /* If our converter is already linked, we have nothing to do here */
    if (gst_pad_is_linked (sink_pad)) {
    g_print ("We are already linked. Ignoring.\n");
    goto exit;
    }

    new_pad_caps = gst_pad_get_current_caps (new_pad);
    new_pad_struct = gst_caps_get_structure (new_pad_caps, 0);
    new_pad_type = gst_structure_get_name (new_pad_struct);
    std::cout << "\n" << new_pad_type << "\n";
    if (!g_str_has_prefix (new_pad_type, "video/x-h264")) {
    g_print ("It has type '%s' which is not raw video. Ignoring.\n", new_pad_type);
    goto exit;
    }
    ret = gst_pad_link (new_pad, sink_pad);
    if (GST_PAD_LINK_FAILED (ret)) {
    g_print ("Type is '%s' but link failed.\n", new_pad_type);
    goto exit;
    } 


    exit:
    /* Unreference the new pad's caps, if we got them */
    if (new_pad_caps != NULL)
        gst_caps_unref (new_pad_caps);

    /* Unreference the sink pad */
    gst_object_unref (sink_pad);

}

int main()
{
    gst_init (NULL, NULL);
    pipeline = gst_pipeline_new (NULL);
    src = gst_element_factory_make ("filesrc", NULL);
    mux = gst_element_factory_make("qtdemux",NULL);
    parse = gst_element_factory_make("h264parse",NULL);
    dbin = gst_element_factory_make ("nvv4l2decoder", NULL);
    conv = gst_element_factory_make ("nvvideoconvert", NULL);
    sink1 = gst_element_factory_make ("nveglglessink", NULL);
    filter1 = gst_element_factory_make ("capsfilter", "filter");
    videorate1 = gst_element_factory_make("videorate",NULL);


    std::string url = "VD19_peoplewalking.mp4";

    std::cout << "test1\n";
    if (!pipeline || !src || !dbin || !conv || !mux || !parse || !sink1 || !videorate1 || !filter1 || !sink1 ) {
    g_error ("Failed to create elements");
    return -1;
    }
    std::cout << "test1\n";
    g_object_set (src, "location", url.c_str(), NULL);

    gst_bin_add_many (GST_BIN (pipeline), src, dbin, conv, mux, parse, videorate1, filter1, sink1, NULL);

    if (!gst_element_link_many(src,mux,NULL) || !gst_element_link_many(parse,dbin, conv, videorate1, filter1 ,sink1, NULL) )//|| !gst_element_link_many (conv, tee, NULL))
    {
        std::cout << "test1\n";
    g_error("Failed to link elements");
    return -3;
    }

    GstCaps *filtercaps;

    filtercaps = gst_caps_new_simple ("video/x-raw",
               "width", G_TYPE_INT, 384,
               "height", G_TYPE_INT, 288,
               "framerate", GST_TYPE_FRACTION, 1,1,
               NULL);

    g_object_set (G_OBJECT (filter1), "caps", filtercaps, NULL);


    std::cout << "test1";
    g_signal_connect (mux, "pad-added", G_CALLBACK (pad_added_handler), NULL);


    GstBus *bus;
    loop = g_main_loop_new (NULL, FALSE);
    bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline));
    gst_bus_add_signal_watch (bus);
    g_signal_connect (G_OBJECT (bus), "message", G_CALLBACK (message_cb), NULL);
    gst_object_unref (GST_OBJECT (bus));

    gst_element_set_state (pipeline, GST_STATE_PLAYING);

    g_main_loop_run (loop);
    
    gst_element_set_state (pipeline, GST_STATE_NULL);

    g_main_loop_unref (loop);

    gst_object_unref (pipeline);
}
4

0 回答 0