В Gstreamer при воспроизведении конвейера в iOS 8 и после входа в фоновый режим и возврата на передний план конвейер не работает :(?

- На самом деле я скачал образец учебника для gstreamer по ссылке,

http://cgit.freedesktop.org/~slomo/gst-sdk-tutorials/

git://people.freedesktop.org/~slomo/gst-sdk-tutorials

  • Теперь я изменил следующий код в учебнике 3,

    -(void) app_function
     {
    GstBus *bus;
    GSource *bus_source;
    GError *error = NULL;
    
    GST_DEBUG ("Creating pipeline");
    
    pipeline = gst_pipeline_new ("e-pipeline");
    
    
    /* Create our own GLib Main Context and make it the default one */
    context = g_main_context_new ();
    g_main_context_push_thread_default(context);
    
    /* Build pipeline */
    // pipeline = gst_parse_launch("videotestsrc ! warptv ! videoconvert ! autovideosink", &error);
    
    
    source = gst_element_factory_make("udpsrc", "source");
    
    g_object_set( G_OBJECT ( source),   "port", 8001, NULL );
    
    GstCaps *caps;
    
    caps = gst_caps_new_simple ("application/x-rtp",
                                "encoding-name", G_TYPE_STRING, "H264",
                                "payload", G_TYPE_INT, 96,
                                "clock-rate", G_TYPE_INT, 90000,
                                NULL);
    
    g_object_set (source, "caps", caps, NULL);
    
    
    
    
    rtp264depay = gst_element_factory_make ("rtph264depay", "rtph264depay");
    h264parse = gst_element_factory_make ("h264parse", "h264parse");
    vtdec = gst_element_factory_make ("vtdec", "vtdec");
    glimagesink  = gst_element_factory_make ("glimagesink", "glimagesink");
    
    gst_bin_add_many (GST_BIN(pipeline), source,  rtp264depay, h264parse, vtdec, glimagesink, NULL);
    
    
    
    
    if (error) {
        gchar *message = g_strdup_printf("Unable to build pipeline: %s", error->message);
        g_clear_error (&error);
        [self setUIMessage:message];
        g_free (message);
        return;
    }
    
    /* Set the pipeline to READY, so it can already accept a window handle */
    gst_element_set_state(pipeline, GST_STATE_READY);
    
    video_sink = gst_bin_get_by_interface(GST_BIN(pipeline), GST_TYPE_VIDEO_OVERLAY);
    if (!video_sink) {
        GST_ERROR ("Could not retrieve video sink");
        return;
    }
    gst_video_overlay_set_window_handle(GST_VIDEO_OVERLAY(video_sink), (guintptr) (id) ui_video_view);
    
    /* Instruct the bus to emit signals for each received message, and connect to the interesting signals */
    bus = gst_element_get_bus (pipeline);
    bus_source = gst_bus_create_watch (bus);
    g_source_set_callback (bus_source, (GSourceFunc) gst_bus_async_signal_func, NULL, NULL);
    g_source_attach (bus_source, context);
    g_source_unref (bus_source);
    g_signal_connect (G_OBJECT (bus), "message::error", (GCallback)error_cb, (__bridge void *)self);
    g_signal_connect (G_OBJECT (bus), "message::state-changed", (GCallback)state_changed_cb, (__bridge void *)self);
    gst_object_unref (bus);
    
    /* Create a GLib Main Loop and set it to run */
    GST_DEBUG ("Entering main loop...");
    main_loop = g_main_loop_new (context, FALSE);
    [self check_initialization_complete];
    g_main_loop_run (main_loop);
    GST_DEBUG ("Exited main loop");
    g_main_loop_unref (main_loop);
    main_loop = NULL;
    
    /* Free resources */
    g_main_context_pop_thread_default(context);
    g_main_context_unref (context);
    gst_element_set_state (pipeline, GST_STATE_NULL);
    gst_object_unref (pipeline);
    
    return;
    

    }

-Теперь я запускаю приложение на iPad, и приложение начинает играть.

  • Теперь я вхожу в фоновый режим и возвращаюсь на передний план, потоковые обновления Gstreamer не видны в пользовательском интерфейсе, но при использовании сети xcode я мог видеть, что пакеты принимаются.... :(

Заранее спасибо....iOS GEEKS....


person Legolas    schedule 17.06.2015    source источник
comment
Я также сталкиваюсь с той же проблемой в Gstreamer на iPhone. пожалуйста, напишите, если вы найдете решение. :(   -  person Whoami    schedule 17.06.2015
comment
конвейер = gst_parse_launch (хост udpsrc = 192.168.7.45, порт = 5000! Приложение / x-rtp, полезная нагрузка = 96! rtpjitterbuffer! rtph264depay! Ошибка Ошибка конвейера Невозможно построить конвейер: нет элемента udpsrc   -  person DURGESH    schedule 16.05.2017
comment
Пожалуйста, объясните, какую дополнительную переменную вы используете, и введите, например, источник, rtp264depay и т. д.   -  person DURGESH    schedule 26.05.2017
comment
Привет, я новичок в Gstremer и запускаю демо-версию // pipe = gst_parse_launch(videotestsrc ! warptv ! videoconvert ! autovideosink, &error); Приведенная выше строка не закомментирована на моей стороне, и я получил сообщение об ошибке: элемент для warptv не найден? у вас есть какое-нибудь решение Пожалуйста, помогите мне Спасибо   -  person Anita    schedule 09.10.2017


Ответы (2)


Обновление: заставьте UDP работать.

После дальнейших исследований я получил потоковую передачу UDP h264 для работы на Linux (PC x86), но принцип должен быть таким же на IOS (в частности, avdec_h264 (используемый на ПК) должен быть заменен на vtdec< /сильный>).

Ключевые различия между конвейерами TCP и UDP:

На стороне сервера:

  • IP: первый элемент, который смутил меня между серверами UDP и TCP: на UDP-сервере IP-адрес, указанный в элементе udpsink, является IP-адресом на стороне клиента< /strong>, то есть gst-launch-1.0 -v fdsrc ! h264parse ! rtph264pay config-interval=1 pt=96 ! udpsink host=$CLIENTIP port=5000

На стороне TCP-сервера IP-адрес является одним из серверных (параметр host на tcpserversink), т. е. gst-launch-1.0 -v fdsrc ! h264parse ! rtph264pay config-interval=1 pt=96 ! gdppay ! tcpserversink host=$SERVERIP port=5000

  • Полезная нагрузка/формат видеопотока. Чтобы клиент мог определить формат и размер кадров, сторона TCP-сервера использует gdppay, >payloader в конвейере. На клиентской стороне напротив элемента используется загрузчик de-payloader gdpdepay, чтобы иметь возможность считывать полученные кадры. то есть

gst-launch-1.0 -v fdsrc ! h264parse ! rtph264pay config-interval=1 pt=96 ! gdppay ! tcpserversink хост = $ SERVERIP порт = 5000

Сторона сервера UDP не использует элемент gdpay, она предоставляет стороне клиента использовать CAPS на своем udpsink, см. ниже различия на стороне клиента.

Клиентская сторона

  • IP: Клиенту UDP НЕ не требуется указание какого-либо IP-адреса. В то время как клиентской стороне TCP нужен IP-адрес сервера (параметр host в tcpclientsrc), т. е. gst-launch-1.0 -v tcpclientsrc host=$SERVERIP port=5000 ! gdpdepay ! rtph264depay ! avdec_h264 ! videoconvert ! autovideosink sync=false enable-last-buffer=false
  • Полезная нагрузка/формат видеопотока: как упоминалось в предыдущем абзаце, на стороне сервера TCP используется загрузчик полезных данных gdppay, а на стороне клиента используется загрузчик полезных данных для распознавания формата и размера кадров.

Вместо этого клиент UDP должен указать это явно, используя заглавные буквы в своем элементе udpsrc, т. е. CAPS='application/x-rtp, media=(string)video, clock-rate=(int)90000, encoding-name=(string)H264, payload=(int)96'

gst-launch-1.0 -v udpsrc port=5000 caps=$CAPS ! rtph264depay ! avdec_h264 ! видео конвертировать ! autovideosink sync=false enable-last-buffer=false`

Как указать заглавные буквы: это немного хакерски, но это работает: запустите свой UDP-сервер с подробным параметром -v, т. е. gst-launch-1.0 -v fdsrc ! h264parse ! rtph264pay config-interval=1 pt=96 ! udpsink host=$CLIENTIP port=5000

Вы получите следующий журнал:

Setting pipeline to PAUSED ... Pipeline is PREROLLING ... /GstPipeline:pipeline0/GstH264Parse:h264parse0.GstPad:src: caps = video/x-h264, width=(int)1280, height=(int)720, parsed=(boolean)true, stream-format=(string)avc, alignment=(string)au, codec_data=(buffer)01640028ffe1000e27640028ac2b402802dd00f1226a01000428ee1f2c /GstPipeline:pipeline0/GstRtpH264Pay:rtph264pay0.GstPad:src: caps = application/x-rtp, media=(string)video, clock-rate=(int)90000, encoding-name=(string)H264, sprop-parameter-sets=(string)"J2QAKKwrQCgC3QDxImo\=\,KO4fLA\=\=", payload=(int)96, ssrc=(uint)3473549335, timestamp-offset=(uint)257034921, seqnum-offset=(uint)12956 /GstPipeline:pipeline0/GstUDPSink:udpsink0.GstPad:sink: caps = application/x-rtp, media=(string)video, clock-rate=(int)90000, encoding-name=(string)H264, sprop-parameter-sets=(string)"J2QAKKwrQCgC3QDxImo\=\,KO4fLA\=\=", payload=(int)96, ssrc=(uint)3473549335, timestamp-offset=(uint)257034921, seqnum-offset=(uint)12956 /GstPipeline:pipeline0/GstRtpH264Pay:rtph264pay0.GstPad:sink: caps = video/x-h264, width=(int)1280, height=(int)720, parsed=(boolean)true, stream-format=(string)avc, alignment=(string)au, codec_data=(buffer)01640028ffe1000e27640028ac2b402802dd00f1226a01000428ee1f2c /GstPipeline:pipeline0/GstRtpH264Pay:rtph264pay0: timestamp = 257034921 /GstPipeline:pipeline0/GstRtpH264Pay:rtph264pay0: seqnum = 12956 Pipeline is PREROLLED ... Setting pipeline to PLAYING ...

Теперь скопируйте заглавные буквы, начинающиеся с caps = application/x-rtp. Это тот, который указывает формат потока rtp. Насколько я знаю, тот, который действительно необходим, чтобы клиент UDP распознал содержимое потока rtp, а затем инициализировал воспроизведение.

Чтобы завершить это и избежать путаницы, найдите полные примеры командной строки ниже, используя raspivid с Raspberry pi. если вы хотите попробовать это (в Linux)

UDP

  • Сервер: raspivid -t 0 -w 1280 -h 720 -fps 25 -b 2500000 -o - | gst-launch-1.0 -v fdsrc ! h264parse ! rtph264pay config-interval=1 pt=96 ! udpsink host=$CLIENTIP port=5000
  • Клиент: CAPS='application/x-rtp, media=(string)video, clock-rate=(int)90000, encoding-name=(string)H264, payload=(int)96' gst-launch-1.0 -v udpsrc port=5000 caps=$CAPS ! rtph264depay ! avdec_h264 ! videoconvert ! autovideosink sync=false enable-last-buffer=false

TCP

  • Сервер: raspivid -t 0 -w 1280 -h 720 -fps 25 -b 2500000 -o - | gst-launch-0.10 -v fdsrc ! h264parse ! rtph264pay config-interval=1 pt=96 ! gdppay ! tcpserversink host=$SERVERIP port=5000

  • Клиент: gst-launch-1.0 -v tcpclientsrc host=$SERVERIP port=5000 ! gdpdepay ! rtph264depay ! avdec_h264 ! videoconvert ! autovideosink sync=false enable-last-buffer=false

Примечание: Raspivid можно легко заменить простым файлом h264, используя cat, т. е. cat myfile.h264 | gst-launch...

person rsacchettini    schedule 11.08.2015
comment
Я столкнулся с некоторой ошибкой при создании конвейера в Gstreamer Ошибка конвейера Невозможно построить конвейер: нет элемента udpsrc Пожалуйста, укажите правильный синтаксис - person DURGESH; 16.05.2017

Недавно я попытался запустить прямую трансляцию с RaspberryPi на IOS8, используя аппаратное декодирование h264, используя API Apple VideoToolBox через плагин gstreamer «vtdec».

Я просмотрел множество туториалов, а именно от braincorp (https://github.com/braincorp/gstreamer_ios_tutorial)

и Себастьян Дрёге: http://cgit.freedesktop.org/~slomo/gst-sdk-tutorials/

Я заставил последний работать, учебник 3 изменен:

  • Конвейер сервера на RaspberryPi с использованием pi Camera и Raspivid + gstreamer:
    raspivid -t 0 -w 1280 -h 720 -fps 25 -b 2500000 - р 0,0,640,480 -о - | gst-launch-0.10 -v fdsrc ! h264parse ! rtph264pay config-interval=1 pt=96 ! гдппай ! tcpserversink host=ServerIPRaspberryPi port=any_port_on_Rpi

  • клиентская конвейерная линия для одного устройства IOS 8:
    tcpclientsrc host=ServerIPRaspberryPi port=any_port_on_Rpi ! гдпдепай ! rtph264depay ! h264parse ! втдек ! глимаджесинк

или то же самое вместо glimagesink autovideosink.

Это решение работает, и несколько клиентов могут использоваться одновременно. Я пытался заставить работать udpsink вместо tcpserversink, но пока не повезло, это так и не сработало.

===ВАЖНО===
Кроме того, заводской способ с использованием gst_element_factory_make() + gst_bin_add_many (GST_BIN(конвейер), ...) никогда не работал. Вместо этого я использовал метод pipeline = gst_parse_launch(...).

Итак, в нашем случае на стороне клиента IOS:
pipeline = gst_parse_launch("tcpclientsrc host=172.19.20.82 port=5000 ! gdpdepay ! rtph264depay ! h264parse ! vtdec ! autovideosink", &error);

Возможная причина: существует страница, документирующая различия и способы переноса кода из gstreamer 0.10 и 1.0: http://gstreamer.freedesktop.org/data/doc/gstreamer/head/manual/html/chapter-porting-1.0.html

Мы заметили, что при использовании "фабричного метода" отсутствовали различные элементы конвейера в зависимости от того, использовали ли мы gstreamer 1.0 или 0.1, т.е. trph264depay или avdec_h264 (используется на других платформах, например, на стороне клиента Linux) для декодирования h264 вместо IOS конкретного vtdec) .

Мы с трудом смогли собрать все элементы вместе с помощью метода Factory, но нам удалось без проблем использовать функцию "gst_parse_launch()" на IOS и Linux.

Итак, в заключение, пока мы не тестировали и не заставили приемник UDP работать, попробуйте способ TCP, используя вместо этого элемент tcpclientsrc, получите он работает, и только после того, как он заработает, попробуйте найти путь к udp и, пожалуйста, дайте нам знать, если вы доберетесь до конца.

С уважением, надеюсь, что это поможет многим из вас.

Роман С

person rsacchettini    schedule 03.08.2015