2017-12-13 5 views
0

Ich möchte das appsrc Element des gstreamer verwenden, um Bilder als Videostream an die Pipeline von gstreamer zu senden. Ich schaue auf das Beispiel appsrc, wo das zeitbasierte Streaming-Format verwendet wird. Wo jeder Puffer die Timestamp-Schritte auf 0,5 Sekunden hat und der "Need-Data" -Rückruf alle 0,5 Sekunden aufruft.Wie benutze ich die gst_app_src_push_buffer() manuell mit benutzerdefinierten Ereignis

Aber in meinem Fall brauche ich diese Funktion nicht, ich muss die gst_app_src_push_buffer() direkt verwenden, wenn ein Bild zum Senden bereit ist (wie ich es verstehe).

ich den folgenden Code für die Initialisierung verwenden (vereinfacht, Pseudo-Code):

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; 
    } 
} 

und die folgenden Puffer-Zugangscode (vereinfacht, Pseudo-Code):

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; 
} 

Aber nichts passiert, ich habe nicht den Video-Stream sehen, z mit dem VLC-Player (mit der SDP-Datei), und nach einiger Zeit stürzt die Anwendung ab.

Aber, wenn ich die "need-Daten" -Signal verwenden und die GST_FORMAT_TIME Option:

::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); 
} 

dann funktioniert es ...

ich überhaupt nicht verstehen, was ich brauche, um ändern, damit es ohne die Zeitstempel und die GST_FORMAT_TIME-Option funktioniert.

Könnte mir bitte jemand helfen?

BR, Denis

Antwort

0

Ah .. Es tut mir leid, ich dumm.

Es ist enougth zur Einrichtung der GST_FORMAT_TIME:

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

Und am Puffer Schöpfung nur gesetzt pts Feld eines aktueller Zeitstempel-Wert zu puffern, z.B. mit dem 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; 
} 

nun alle Arbeiten, yeehaa .. :)

Verwandte Themen