Получение видео по udp от ROC-RK35
У меня есть устройство с rockchip rk3588. Компьютер и этот вычислитель находятся в одной wifi сети и видят друг друга. Видеопоток на экране рокчипа получается с аналоговых камер и отображается на экране, вот его конфигурация
{"identifier": "right","source": "rtspsrc location=rtsp://192.168.1.:5/channel=1&stream=0.sdp user-id=****** user-pw=****** tcp-timeout=5000000","parser": "rtph265depay ! h265parse ","decoder": "mppvideodec width=1280 height=720","postprocessor": "videoflip video-direction=5","remote_enabled": true,"remote_host": "192.168.2.2","remote_port": 49023,"sink": "appsink name=sink sync=false","frame": {"width": 1280,"height": 720,"channels": 3}},
здесь прописано что он отсылает udp датаграммы на соответствующий порт моего компьютера. Компьютер на основе анализа wireshark успешно получает эти udp пакеты.
Приложение на компьютере прослушивает этот порт с помощью следующий конфигурации
rc::stream::StreamConfig config {.identifier = "",.source = "udpsrc port=49023 caps="application/x-rtp, payload=98"",.parser = "rtph265depay ! h265parse",.decoder = "avdec_h265",.postprocessor = "",.sink = "appsink name=sink sync=false",.frame_shape = {.width = 1280,.height = 720,.channels = 3}};
значение payload и caps корректны - взяты из отправителя.
Собранный пайплайн выглядит у меня следующим образом:
udpsrc port=49023 caps="application/x-rtp, payload=98" ! rtph265depay ! h265parse ! avdec_h265 ! appsink name=sink sync=false
case State::kConnecting: {
if (!active_.load(std::memory_order::relaxed)) {
local_active = false;
continue;
}
//std::string pipeline_str = source_;
//фомируем строку pipeline
// if(remote_enabled_) {
// pipeline_str = EnableStreamingPipeline();
//
// } else {
// pipeline_str = DisableStreamingPipeline();
// }
std::string pipeline_str = source_;
if (!parser_.empty())
pipeline_str = fmt::format("{} ! {}", pipeline_str, parser_);
if (!decoder_.empty())
pipeline_str = fmt::format("{} ! {}", pipeline_str, decoder_);
if (!postprocessor_.empty())
pipeline_str = fmt::format("{} ! {}", pipeline_str, postprocessor_);
pipeline_str = fmt::format("{} ! {}", pipeline_str, sink_);
logger_->info(pipeline_str);
GError* error;
pipeline = gst_parse_launch(pipeline_str.c_str(), &error);
if (error) {
logger_->error("Ошибка создания pipeline: {} " ,error->message );
g_error_free(error);
}
//pipeline = gst_parse_launch(pipeline_str.c_str(), nullptr);
ret = gst_element_set_state(pipeline, GST_STATE_PLAYING);
if (ret == GST_STATE_CHANGE_FAILURE) {
logger_->error("Unable to set the pipeline to the playing state ({}).", pipeline_str);
gst_object_unref(pipeline);
active_.store(false, std::memory_order::relaxed);
}
appsink = gst_bin_get_by_name(GST_BIN(pipeline), "sink");
g_object_set(appsink, "emit-signals", TRUE, nullptr);
g_signal_connect(appsink,
"new-sample",
G_CALLBACK(static_cast<NewSampleCallback>([](GstElement* sink, Stream* stream) {
return stream->NewSample(sink);
})),
this);
bus = gst_element_get_bus(pipeline);
logger_->info("Constructed pipeline.");
state = State::kStreaming;
break;
}
case State::kStreaming: {
if (!active_.load(std::memory_order::relaxed)) {
state = State::kFinishing;
continue;
}
msg = gst_bus_timed_pop_filtered(bus, TimeCountIn<nanoseconds>(kBusTimeout),
static_cast<GstMessageType>(GST_MESSAGE_ERROR | GST_MESSAGE_EOS | GST_MESSAGE_PROGRESS));
if (msg == nullptr) {
logger_->info("Received nullptr message");
} else {
logger_->info("Received message type: {}", GST_MESSAGE_TYPE_NAME(msg));
}
if (msg != nullptr) {
switch (GST_MESSAGE_TYPE (msg)) {
case GST_MESSAGE_ERROR: {
GError* err;
gchar* debug_info;
gst_message_parse_error(msg, &err, &debug_info);
logger_->error("Error received from element {}: {}", GST_OBJECT_NAME (msg->src), err->message);
g_clear_error(&err);
g_free(debug_info);
Reset(bus, pipeline);
state = State::kConnecting;
break;
}
case GST_MESSAGE_EOS: {
logger_->info("Connection list (EOS).");
Reset(bus, pipeline);
state = State::kConnecting;
break;
}
case GST_MESSAGE_PROGRESS: {
GstProgressType type;
gchar* progress_code;
gchar* progress_text;
gst_message_parse_progress(msg, &type, &progress_code, &progress_text);
if (type == GST_PROGRESS_TYPE_COMPLETE && std::string(progress_code) == "request")
logger_->info("Started streaming");
break;
}
default:
break;
}
gst_message_unref(msg);
}
break;
}
Во время работы msg = gst_bus_timed_pop_filtered возвращает всегда nullptr по этой причине видео в дальнейшем не отображается в моем окошке qt.
пробовал запустить через командную строку и вот вывод$ gst-launch-1.0 -v udpsrc port=49023 caps="application/x-rtp, payload=98" ! rtph265depay ! h265parse ! avdec_h265 ! appsink name=sink sync=false
Setting pipeline to PAUSED ...Pipeline is live and does not need PREROLL ...Pipeline is PREROLLED ...Setting pipeline to PLAYING ...New clock: GstSystemClock/GstPipeline:pipeline0/GstUDPSrc:udpsrc0.GstPad:src: caps = application/x-rtp, payload=(int)98, media=(string)video, clock-rate=(int)90000, encoding-name=(string)H265/GstPipeline:pipeline0/GstRtpH265Depay:rtph265depay0.GstPad:sink: caps = application/x-rtp, payload=(int)98, media=(string)video, clock-rate=(int)90000, encoding-name=(string)H265