Gstreamer Appsink не получает данные из конвейера
Я проектирую конвейер для кодирования видеокадра из приложения opencv (полученного с веб-камеры) в формат video/x-h264, отправки его по сети и декодирования на другом устройстве другого типа (возможно, в raspberry pi) на правильный RGB поток для моего проекта.
Для этого я должен использовать Encoder и Decoder с аппаратным ускорением. Поскольку весь сценарий огромен, текущая разработка выполняется на машине Intel с использованием плагинов VAAPI gstreamer (vaapiencode_h264 & vaapidecode) . А также тот факт, что нам НЕ нужно использовать какие-либо сетевые плагины, такие как TCPServer или UDPServer.
Для этого я использовал приведенный ниже конвейер для своей цели: на стороне кодера:
appsrc name=applicationSource ! videoconvert ! video/x-raw, format=I420, width=640, height=480,framerate=30/1, pixel-aspect-ratio=1/1,interlace-mode=progressive ! vaapiencode_h264 bitrate=600 tune=high-compression ! h264parse config-interval=1 ! appsink name=applicationSink sync=false
Часть Appsrc работает отлично, в то время как часть appsink имеет некоторые проблемы с ней.
Часть appsink этого конвейера была установлена с помощью следующих заглавных букв:
"video/x-h264, format = (string) {avc, avc3, byte-stream}, выравнивание =(string){au,nal};video/mpeg, mpegversion=(int)2, profile=(string)simple"
Код для извлечения данных моей appsink является
bool HWEncoder::grabData()
{
// initial checks..
if (!cameraPipeline)
{
GST_ERROR("ERROR AS TO NO PIPE FOUND ... Stopping FRAME GRAB HERE !! ");
return false;
}
if (gst_app_sink_is_eos (GST_APP_SINK(applicationSink)))
{
GST_WARNING("APP SINK GAVE US AN EOS! BAILING OUT ");
return false;
}
if (sample)
{
cout << "sample available ... unrefing it ! "<< endl;
gst_sample_unref(sample);
}
sample = gst_app_sink_pull_sample (GST_APP_SINK(applicationSink));
if (!sample)
{
GST_WARNING("No valid sample");
return false; // no valid sample pulled !
}
sink_buffer = gst_sample_get_buffer(sample);
if (!sink_buffer)
{
GST_ERROR("No Valid Buffer ");return false;
}
return true;
}
После запуска конвейера и проверки заполнения буфера в моей программе, я застрял в указанных ниже строках моего кода на неопределенное время:
sample = gst_app_sink_pull_sample (GST_APP_SINK(applicationSink));
У меня есть следующие вопросы: 1) Правильны ли мои Caps для appsink? Если нет, как я могу определить колпачки для них? 2) Что-то не так в моем конвейере выше?
Как я могу исправить эту проблему с Appsink??
Любая помощь будет полезна!
Спасибо!!
1 ответ
Просто предположение (у меня были похожие проблемы) проблема, связанная с наличием appsink и appsrc в одном конвейере, может заключаться в том, что при заполнении / опустошении одного из них оно блокирует другое (подробнее об этом ниже).
appsink и appsrc блокируются, когда они заполнены / пусты - это нормальное желаемое поведение. Есть вариант drop
для appsink или для appsrc есть опция block
- но с их помощью это может быть просто обходной путь, и вы получите глюки в своем потоке. Правильное решение заключается в улучшении синхронизации между appsrc и appsink.
Вы можете реагировать на сигналы приложения enough-data
а также need-data
- это наш путь. Также мы поиграли со свойствами appsrc: is-live
, do-timestamp
и размер буфера (это может или не может помочь вам):
g_object_set(src->appsrc,
"stream-type", GST_APP_STREAM_TYPE_STREAM,
"format", GST_FORMAT_TIME,
"do-timestamp", TRUE,
"is-live", TRUE,
"block", TRUE,
NULL);
Почему они блокируют друг друга? Потому что (я думаю) вы обрабатываете appsink и одновременно appsrc в главном потоке приложений. Когда один из appsink/appsrc блокирует поток, нет никого, кто бы обрабатывал обработку для другого. Поэтому, когда appsink заблокирован, потому что у него нет никаких данных, нет никого, кто мог бы снабдить appsrc новыми данными - таким образом, бесконечная тупиковая ситуация.
Мы также внедрили ноблочную версию метода appsink *pull_sample, но это был просто обходной путь, который привел к большему количеству проблем, чем к решениям.
Если вы хотите отладить происходящее, вы можете добавить запись GST_DEBUG для appsrc/appsink (я не помню, что это было), вы можете добавить обратный вызов для упомянутых enough-data
а также need-data
или вы можете добавить очереди и включить GST_DEBUG=queue_dataflow:5, чтобы увидеть, какая очередь заполняется первой и т. д., это всегда полезно при отладке "тупика данных".