2017-12-13 17 views
0

gstreamerのappsrc要素を使用して、イメージをgstreamerのパイプラインにビデオストリームとして送信します。私はappsrcの例を見ています。ここでは時間ベースのストリーミング形式が使われています。各バッファに0.5秒のタイムスタンプステップがあり、 'need-data'コールバックが0.5秒ごとに呼び出されます。gst_app_src_push_buffer()をカスタムイベントで手動で使用する

私の場合、私はこの機能は必要ありません。私が理解しているように、画像を送る準備ができたら、gst_app_src_push_buffer()を直接使う必要があります。

私は、次の初期化コード(単純化し、擬似コード)を使用します。

void Foo::initializeGst() 
{ 
    // Init gstreamer. 
    ::gst_init(nullptr, nullptr); 

    // Configure appsrc element. 
    m_appsrc = ::gst_element_factory_make(
       "appsrc", "source"); 

    ::g_object_set(G_OBJECT(m_appsrc), 
        "stream-type", GST_APP_STREAM_TYPE_STREAM, 
        "is-live", true, 
        nullptr); 

    // Configure appsrc caps. 
    const auto caps = ::gst_caps_new_simple(
       "video/x-raw", 
       "format", G_TYPE_STRING, "BGRA", 
       "width", G_TYPE_INT, 800, 
       "height", G_TYPE_INT, 600, 
       "framerate", GST_TYPE_FRACTION, 0, 1, 
       nullptr); 

    ::g_object_set(G_OBJECT(m_appsrc), 
        "caps", caps, 
        nullptr); 

    // Configure video convertor element. 
    const auto conv = ::gst_element_factory_make(
       "videoconvert", "conv"); 

    // Configure video encoder element. 
    const auto videoenc = ::gst_element_factory_make(
       "x264enc", "video_encoder"); 

    // Configure payloader element. 
    const auto payloader = ::gst_element_factory_make(
       "rtph264pay", "payloader"); 

    ::g_object_set(G_OBJECT(payloader), 
        "config-interval", 60, 
        nullptr); 

    // Configure udpsink element. 
    const auto udpsink = ::gst_element_factory_make(
       "udpsink", "udpsink"); 

    ::g_object_set(G_OBJECT(udpsink), 
        "host", "127.0.0.1", 
        "port", 50666, 
        nullptr); 

    // Build pipeline. 
    m_pipeline = ::gst_pipeline_new("pipeline"); 

    ::gst_bin_add_many(GST_BIN(m_pipeline), 
         m_appsrc, 
         conv, 
         videoenc, 
         payloader, 
         udpsink, 
         nullptr); 

    const auto result = ::gst_element_link_many(
       m_appsrc, conv, videoenc, payloader, udpsink, nullptr); 

    if (!result) { 
     qDebug() << "Unable to initialize the GST"; 
    } else { 
     // Play. 
     const auto status = ::gst_element_set_state(m_pipeline, GST_STATE_PLAYING); 
     qDebug() << "Status:" << status; 
    } 
} 

そして、次のバッファ・アクセスコード(単純化し、擬似コード):

void Foo::setImage(const QImage &image) 
{ 
    GstBuffer *buffer = gst_buffer_new_and_alloc(m_image.byteCount()); 
    const auto bytesCopied = ::gst_buffer_fill(
       buffer, 0, m_image.constBits(), m_image.byteCount()); 

    const auto result = ::gst_app_src_push_buffer(
       GST_APP_SRC(m_appsrc), buffer); 

    qDebug() << "Push result" << result << "for copied bytes" 
      << bytesCopied; 
} 

をしかし、何も起こりません、私がやりましたビデオストリームを見ない、例えばVLCプレーヤー(SDPファイルを使用)を使用して、しばらくしてから、アプリケーションがクラッシュします。

しかし、私は「必要性データ」信号を使用し、GST_FORMAT_TIMEオプション場合:

::g_object_set(G_OBJECT(appsrc), 
       "stream-type", 0, 
       "is-live", TRUE, 
       "format", GST_FORMAT_TIME, 
       nullptr); 

g_signal_connect(appsrc, "need-data", G_CALLBACK(need_data_cb), nullptr); 

static void need_data_cb(GstElement *appsrc, guint unused_size, gpointer user_data) 
{ 
    static gboolean white = FALSE; 
    static GstClockTime timestamp = 0; 

    const guint size = 800 * 600 * 4; 
    GstBuffer *buffer = ::gst_buffer_new_allocate(nullptr, size, nullptr); 

    // This makes the image black/white. 
    ::gst_buffer_memset(buffer, 0, white ? 0xff : 0x0, size); 

    white = !white; 

    GST_BUFFER_PTS(buffer) = timestamp; 
    GST_BUFFER_DURATION(buffer) = ::gst_util_uint64_scale_int (1, GST_SECOND, 20); 

    timestamp += GST_BUFFER_DURATION(buffer); 

    GstFlowReturn ret; 
    ::g_signal_emit_by_name(appsrc, "push-buffer", buffer, &ret); 

    ::gst_buffer_unref(buffer); 
} 

それが動作する...

私は私が必要なものを、全く理解していませんでしたタイムスタンプとGST_FORMAT_TIMEオプションなしで動作するように変更してください。

誰かが私を助けてくれますか?

BR、 デニス

答えて

0

ああ..私は、私は愚かな、ごめんなさい。

それはGST_FORMAT_TIMEセットアップにenougthです:

::g_object_set(G_OBJECT(appsrc), 
       "stream-type", 0, 
       "is-live", TRUE, 
       "format", GST_FORMAT_TIME, 
       nullptr); 

そして、ちょうど例えば、PTSフィールドに現在のタイムスタンプ値をバッファするように設定し、バッファの作成でQElapsedTimerを使用して:今

void Foo::setImage(const QImage &image) 
{ 
    GstBuffer *buffer = gst_buffer_new_and_alloc(m_image.byteCount()); 
    const auto bytesCopied = ::gst_buffer_fill(
       buffer, 0, m_image.constBits(), m_image.byteCount()); 

    GST_BUFFER_PTS(buffer) = m_timer.nsecsElapsed(); 

    const auto result = ::gst_app_src_push_buffer(
       GST_APP_SRC(m_appsrc), buffer); 

    qDebug() << "Push result" << result << "for copied bytes" 
      << bytesCopied; 
} 

、すべての作品は、yeehaa .. :)

関連する問題