Gstreamer с захватом сети UDP-> modify-> stream Pipeline Error - PullRequest
1 голос
/ 08 января 2020

Резюме: я пытаюсь получить видео с помощью конвейера gstreamer, а затем внести некоторые изменения в полученный кадр с помощью opencv, наконец, хочу отправить этот кадр на другой хост с помощью конвейера opencv gstreamer. Все шаги выполняются в сети UDP. (udpsink)

Мне кажется, проблема в том, что полученное видео преобразуется в неправильный формат при использовании функции записи.

ШАГ 1:

Я могу чтобы получить видео с этим конвейером из плагина Speci c gstreamer:

VideoCapture cap("udpsrc port=5600 ! application/x-rtp,payload=96,encoding-name=H264 !"
                    "rtpjitterbuffer mode=1 ! rtph264depay ! h264parse ! decodebin ! videoconvert ! appsink emit-signals=true sync=false max-buffers=1 drop=true", CAP_GSTREAMER);

ШАГ 2:

Я нашел несколько конвейеров и перепробовал почти все, но я не был Невозможно отправить полученное видео с этим:

#include <stdio.h>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/opencv.hpp>

using namespace std;
using namespace cv;

int main(int argc, char** argv) {

VideoCapture cap("udpsrc port=5600 ! application/x-rtp,payload=96,encoding-name=H264 !"
                        "rtpjitterbuffer mode=1 ! rtph264depay ! h264parse ! decodebin ! videoconvert ! appsink emit-signals=true sync=false max-buffers=1 drop=true", CAP_GSTREAMER);
//int width  = cap.get(3);
//int height = cap.get(4);
if(!cap.isOpened())
{
    cout << "Could not read video file" << endl;
    return 1;
}

VideoWriter writer;
writer.open("appsrc ! videoconvert ! video/x-raw,format=I420,width=1280,height=720,framerate=30/1,bitrate=800 ! jpegenc ! rtpjpegpay ! udpsink host=127.0.0.1 port=5000"
            , 0, (double)30, Size(1280, 720), true);
if (!writer.isOpened()) {
    printf("=ERR= can't create video writer\n");
    return -1;
}

Mat frame;
while (true) {

    cap >> frame;
    if (frame.empty())
        break;

    /* Captured video will be processed here. Then send another IP. */

    writer << frame;

}
}

Что я пробовал :

Я пытался отправить видео в конечный пункт назначения с помощью командной строки, и это было успешно .

1:

gst-launch-1.0 -v videotestsrc pattern=snow ! video/x-raw,framerate=20/1 ! videoscale ! videoconvert ! x264enc tune=zerolatency bitrate=1000000 speed-preset=superfast ! rtph264pay ! udpsink host=127.0.0.1 port=5000 

2:

gst-launch-1.0 -v videotestsrc ! video/x-raw,framerate=20/1 ! videoscale ! videoconvert ! x264enc tune=zerolatency bitrate=500 speed-preset=superfast ! rtph264pay ! udpsink port=5000 

Оба они работают без проблем.

Я также изучил фрагменты кода из исходного кода , который отправляет в конвейер video_capture.

  GstElement* pipeline = gst_pipeline_new("sender");
  if (!pipeline) {
    gzerr << "ERR: Create pipeline failed. \n";
    return;
  }

  GstElement* dataSrc = gst_element_factory_make("appsrc", "AppSrc");
  GstElement* testSrc = gst_element_factory_make("videotestsrc", "FileSrc");
  GstElement* conv  = gst_element_factory_make("videoconvert", "Convert");
  GstElement* encoder = gst_element_factory_make("x264enc", "AvcEncoder");
  GstElement* parser  = gst_element_factory_make("h264parse", "Parser");
  GstElement* payload = gst_element_factory_make("rtph264pay", "PayLoad");
  GstElement* sink  = gst_element_factory_make("udpsink", "UdpSink");
  if (!dataSrc || !testSrc || !conv || !encoder || !parser || !payload || !sink) {
    gzerr << "ERR: Create elements failed. \n";
    return;
  }

// gzerr <<"width"<< this->width<<"\n";
// gzerr <<"height"<< this->height<<"\n";
// gzerr <<"rate"<< this->rate<<"\n";

  // Config src
  g_object_set(G_OBJECT(dataSrc), "caps",
      gst_caps_new_simple ("video/x-raw",
      "format", G_TYPE_STRING, "I420",
      "width", G_TYPE_INT, this->width,
      "height", G_TYPE_INT, this->height,
      "framerate", GST_TYPE_FRACTION, (unsigned int)this->rate, 1,
      NULL),
      "is-live", TRUE,
      NULL);

  // Config encoder
  g_object_set(G_OBJECT(encoder), "bitrate", 800, NULL);
  g_object_set(G_OBJECT(encoder), "speed-preset", 2, NULL); //lower = faster, 6=medium
  //g_object_set(G_OBJECT(encoder), "tune", "zerolatency", NULL);
  //g_object_set(G_OBJECT(encoder), "low-latency", 1, NULL);
  //g_object_set(G_OBJECT(encoder), "control-rate", 2, NULL);

  // Config payload
  g_object_set(G_OBJECT(payload), "config-interval", 1, NULL);

  // Config udpsink
  g_object_set(G_OBJECT(sink), "host", this->udpIP.c_str(), NULL);
  g_object_set(G_OBJECT(sink), "port", this->udpPort, NULL);
  //g_object_set(G_OBJECT(sink), "sync", false, NULL);
  //g_object_set(G_OBJECT(sink), "async", false, NULL);

  // Connect all elements to pipeline
  gst_bin_add_many(GST_BIN(pipeline), dataSrc, conv, encoder, parser, payload, sink, NULL);

  // Link all elements
  if (gst_element_link_many(dataSrc, conv, encoder, parser, payload, sink, NULL) != TRUE) {
    gzerr << "ERR: Link all the elements failed. \n";
    return;
  }

  // Set up appsrc
  g_object_set(G_OBJECT(dataSrc), "stream-type", 0, "format", GST_FORMAT_TIME, NULL);
  g_signal_connect(dataSrc, "need-data", G_CALLBACK(cb_need_data), this);

  // Start
  gst_element_set_state(pipeline, GST_STATE_PLAYING);
  g_main_loop_run(mainLoop);

  // Clean up
  gst_element_set_state(pipeline, GST_STATE_NULL);
  gst_object_unref(GST_OBJECT(pipeline));
  g_main_loop_unref(mainLoop);
  mainLoop = nullptr;
...