2016-06-13 8 views
1

Я пытаюсь реализовать простейший конвейер gstreamer-1.0 с захватом видео с веб-камеры и записью его в файл. Оно работает. Howewer, во время записи очень маленькие видео (~ 2 с) продолжительную - с перезапуском трубопровода в петлю - иногда я получаю следующее сообщение об ошибке при перезапуске трубопровода:Правильный способ перезапуска конвейера gstreamer с v4l2scr

libv4l2: Ошибка установки pixformat: Устройство или ресурс занят

Похоже, что элемент v4l2src не выпущен правильно на предыдущем шаге записи.

Что нужно сделать для правильной перезагрузки трубопровода?

#include <iostream> 
#include <thread> 
#include <gst/gst.h> 

static GstElement* makeCamSrc(int deviceId) 
{ 
    GstElement* cam = gst_element_factory_make("v4l2src", "camSrc"); 

    if(!cam) 
     return NULL; 

    std::string devPath = std::string("/dev/video") + std::to_string(deviceId); 
    g_object_set(cam, "device", devPath.c_str(), NULL); 
    g_object_set(cam, "do-timestamp", true, NULL); 

    //Setup camera controls 
    GstStructure* extraCtrls = gst_structure_new("logitech_controls", 
               "sharpness", G_TYPE_INT, 220, 
               "contrast", G_TYPE_INT, 100, 
               "saturation", G_TYPE_INT, 160, 
               "focus_auto", G_TYPE_BOOLEAN, false, 
               "white_balance_temperature_auto", G_TYPE_BOOLEAN, false, 
               "white_balance_temperature", G_TYPE_INT, 3500, 
               NULL); 

    g_object_set(cam, "extra-controls" , extraCtrls, NULL); 

    return cam; 
} 

int main() 
{ 
    gst_init(NULL, NULL); 

    GstElement* vPipeline = gst_pipeline_new("vPipeline"); 
    GstElement* camSrc = makeCamSrc(1); 
    GstElement* converter = gst_element_factory_make("videoconvert", "converter"); 
    GstElement* tee = gst_element_factory_make("tee", "tee"); 
    GstElement* vQueue = gst_element_factory_make("queue", "vQueue"); 
    GstElement* vEncoder = gst_element_factory_make("x264enc", "vEncoder"); 
    GstElement* vMuxer = gst_element_factory_make("mp4mux", "muxer"); 
    GstElement* vFileSink = gst_element_factory_make("filesink", "vFileSink"); 

    GstCaps* camCaps = gst_caps_new_simple("video/x-raw", 
              "format", G_TYPE_STRING, "RGB", 
              "width", G_TYPE_INT,  1280, 
              "height", G_TYPE_INT,  720, 
              NULL); 

    gst_bin_add_many(GST_BIN(vPipeline), camSrc, converter, tee, vQueue, vEncoder, vMuxer, vFileSink, NULL); 

    gst_element_link_filtered(camSrc, converter, camCaps); 
    gst_caps_unref(camCaps); 

    gst_element_link(converter, tee); 
    gst_element_link_many(vQueue, vEncoder, vMuxer, vFileSink, NULL); 

    GstPadTemplate* padTemplate = gst_element_class_get_pad_template(GST_ELEMENT_GET_CLASS(tee), "src_%u"); 
    GstPad* vTeePad = gst_element_request_pad(tee, padTemplate, NULL, NULL); 

    GstPad* vQueuePad = gst_element_get_static_pad(vQueue, "sink"); 
    gst_pad_link(vTeePad, vQueuePad); 

    GstBus* bus = gst_element_get_bus(vPipeline); 

    for(int i = 0; i < 11; ++i) 
    { 
     std::string file = std::string("stream_") + std::to_string(i) + std::string(".mp4"); 
     g_object_set(vFileSink, "location", file.c_str(), NULL); 

     gst_element_set_state(vPipeline, GST_STATE_PLAYING); 

     std::thread([&] 
        { 
         std::this_thread::sleep_for(std::chrono::milliseconds(2000)); 
         gst_element_send_event(vPipeline, gst_event_new_eos()); 
        }).detach(); 

     GstMessage* msg = gst_bus_timed_pop_filtered(bus, GST_CLOCK_TIME_NONE, (GstMessageType)(GST_MESSAGE_ERROR | GST_MESSAGE_EOS)); 
     if (msg != NULL) 
     { 
      if(GST_MESSAGE_TYPE(msg) == GST_MESSAGE_ERROR) 
       return -1; 

      gst_message_unref (msg); 
     } 
     gst_element_set_state(vPipeline, GST_STATE_NULL); 
    } 

    gst_object_unref(vPipeline); 
} 

ответ

0

Т.Л. др - может быть, это будет работать:

Попробуйте добавить

gst_element_set_state(camSrc, GST_STATE_NULL); 

Перед трубопровода один

Или установите его первым в GST_STATE_PAUSED, а затем NULL с некоторой задержкой ..

Возможно, вам нужно использовать основной цикл событий glib для вызова вашего eos - check this