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, чтобы увидеть, какая очередь заполняется первой и т. д., это всегда полезно при отладке "тупика данных".

Другие вопросы по тегам