Резюме: я пытаюсь получить видео с помощью конвейера 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;