2016-06-13 58 views
1

ウェブカメラからビデオをキャプチャしてファイルに書き込むことで、最も単純なgstreamer-1.0パイプラインを実装しようとしています。できます。 Howewer、continiously非常に小さなビデオ(〜2秒)を記録しながら、 - ループ内でパイプラインを再起動すると - 私は時々パイプラインの再起動時に次のエラーを取得する:v4l2scrでgstreamerのパイプラインを再起動する正しい方法

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

TLのDR - 多分これは動作します:パイプライン1

それともGST_STATE_PAUSEDに最初にそれを設定し、いくつかの遅延でNULLの前に

gst_element_set_state(camSrc, GST_STATE_NULL); 

を追加

てみてください。..

あなたはeos-checkを呼び出すためにglibメインイベントループを使うべきでしょうか?

関連する問題