2016-06-13 249 views
1

我試圖通過從網絡攝像頭捕獲視頻並將其寫入文件來實現最簡單的gstreamer-1.0管道。有用。 Howewer,同時記錄非常小的視頻(〜2秒)continiously - 與重啓的循環管道 - 我有時會收到以下錯誤在管道重新啓動:使用v4l2scr重新啓動gstreamer管道的正確方法

libv4l2:錯誤設置pixformat:設備或資源忙

看來,在上一個記錄步驟中,元素沒有正確釋放。

必須做些什麼才能正確地重新啓動管道?

#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

TL博士 - 也許這將工作:

嘗試增加

gst_element_set_state(camSrc, GST_STATE_NULL); 

管道一個

之前或與一些延遲首先將其設置爲GST_STATE_PAUSED然後空..

也許你應該使用glib主事件循環來調用你的eos - 檢查this