2011-03-15 15 views
6

Después de jugar con algunas aplicaciones de juguete, la exploración de la documentación y alrededor de google (incluyendo la lista de correo archivos) Todavía estoy intrigado por lo que yo creo que es un caso bastante común uso.imágenes que empujan en una tubería GStreamer

Tengo un código existente que genera imágenes (en memoria) y me gustaría como insertar estas imágenes en una tubería gstreamer (para crear un video flv al final).

No pude encontrar una "forma obvia de hacerlo". Mi mejor intento será excavar en el código fuente de GstMultiFileSrc y su padre GstPushSrc, para resolverlo.

¿Podría alguno de ustedes señalarme la "forma obvia" de hacer esto? ¿Hay alguna pieza relacionada de documentación/tutorial/ejemplo sobre esto?

Una vez que tengo la entrada correcta, el resto es pan comido, gracias a genialidad de Gstreamer! (algo así como "mi entrada de la magia -> ffmpegcolorspace ffenc_flv flvmux filesink ubicación = desktop.flv!")

Gracias por sus respuestas.

Respuesta

7

GStreamer utiliza complementos para hacer todo. Los complementos que crean datos o los toman de una fuente externa se llaman complementos "src".

El complemento src genérico para inyectar datos generados por la aplicación en una tubería se llama appsrc. La API proporcionada por appsrc está documentada como parte del App Library.

Aquí hay un ejemplo que muestra cómo alimentar appsrc con imágenes generadas: gdk-gstappsrc-stream.c. Parece derivarse de algún código de prueba en el árbol fuente de GStreamer: here.

Otro enfoque sería crear su propio plugin src. Mira el goom plugin de visualización de música para un ejemplo que parece funcionar de una manera similar a lo que has especificado.

+0

gracias! GstAppSrc es exactamente lo que estaba buscando. – rodrigob

2

Encontré una solución (tal vez) a esto (obtengo las imágenes con OpenCV) ... pero tengo un error con la tubería: ERROR del elemento mysource: Error en el flujo de datos interno. información de depuración: gstbasesrc.c (2574): gst_base_src_loop():/GstPipeline: pipeline0/GstAppSrc: MySource: tarea de streaming en pausa, la razón no negoció-(-4)

este es el código:

typedef struct _App App; 
struct _App{ 
    GstElement *pipeline; 
    GstElement *appsrc; 

    GMainLoop *loop; 
    guint sourceid; 
    GTimer *timer; 
}; 

App s_app; 
CvCapture *capture; 
static gboolean read_data(App *app){ 
    GstFlowReturn ret; 
    GstBuffer *buffer = gst_buffer_new(); 
    IplImage* frame = cvQueryFrame(capture); 
    GST_BUFFER_DATA(buffer) = (uchar*)frame->imageData; 
    GST_BUFFER_SIZE(buffer) = frame->width*frame->height*sizeof(uchar*); 
    g_signal_emit_by_name(app->appsrc,"push-buffer",buffer,&ret); 
    gst_buffer_unref(buffer); 
    if(ret != GST_FLOW_OK){ 
     GST_DEBUG("Error al alimentar buffer"); 
     return FALSE; 
    } 
    return TRUE; 
} 

static void start_feed(GstElement* pipeline,guint size, App* app){ 
    if(app->sourceid == 0){ 
     GST_DEBUG("Alimentando"); 
     app->sourceid = g_idle_add((GSourceFunc) read_data, app); 
    } 
} 

static void stop_feed(GstElement* pipeline, App* app){ 
    if(app->sourceid !=0){ 
     GST_DEBUG("Stop feeding"); 
     g_source_remove(app->sourceid); 
     app->sourceid = 0; 
    } 
} 

static gboolean 
bus_message (GstBus * bus, GstMessage * message, App * app) 
{ 
    GST_DEBUG ("got message %s", 
    gst_message_type_get_name (GST_MESSAGE_TYPE (message))); 

    switch (GST_MESSAGE_TYPE (message)) { 
    case GST_MESSAGE_ERROR: { 
     GError *err = NULL; 
     gchar *dbg_info = NULL; 
     gst_message_parse_error (message, &err, &dbg_info); 
     g_printerr ("ERROR from element %s: %s\n", 
      GST_OBJECT_NAME (message->src), err->message); 
     g_printerr ("Debugging info: %s\n", (dbg_info) ? dbg_info : "none"); 
     g_error_free (err); 
     g_free (dbg_info); 
     g_main_loop_quit (app->loop); 
     break; 
    } 
    case GST_MESSAGE_EOS: 
     g_main_loop_quit (app->loop); 
     break; 
    default: 
     break; 
    } 
    return TRUE; 
} 

int main(int argc, char* argv[]){ 
    App *app = &s_app; 
    GError *error = NULL; 
    GstBus *bus; 
    GstCaps *caps; 
    capture = cvCaptureFromCAM(0); 
    gst_init(&argc,&argv); 
    /* create a mainloop to get messages and to handle the idle handler that will 
    * feed data to appsrc. */ 
    app->loop = g_main_loop_new (NULL, TRUE); 
    app->timer = g_timer_new(); 

    app->pipeline = gst_parse_launch("appsrc name=mysource ! video/x-raw-rgb,width=640,height=480,bpp=24,depth=24 ! ffmpegcolorspace ! videoscale method=1 ! theoraenc bitrate=150 ! tcpserversink host=127.0.0.1 port=5000", NULL); 
    g_assert (app->pipeline); 
    bus = gst_pipeline_get_bus (GST_PIPELINE (app->pipeline)); 
    g_assert(bus); 
    /* add watch for messages */ 
    gst_bus_add_watch (bus, (GstBusFunc) bus_message, app); 
    /* get the appsrc */ 
    app->appsrc = gst_bin_get_by_name (GST_BIN(app->pipeline), "mysource"); 
    g_assert(app->appsrc); 
    g_assert(GST_IS_APP_SRC(app->appsrc)); 
    g_signal_connect (app->appsrc, "need-data", G_CALLBACK (start_feed), app); 
    g_signal_connect (app->appsrc, "enough-data", G_CALLBACK (stop_feed), app); 

    /* set the caps on the source */ 
    caps = gst_caps_new_simple ("video/x-raw-rgb", 
    "bpp",G_TYPE_INT,24, 
    "depth",G_TYPE_INT,24, 
    "width", G_TYPE_INT, 640, 
    "height", G_TYPE_INT, 480, 
    NULL); 
    gst_app_src_set_caps(GST_APP_SRC(app->appsrc), caps); 
    /* go to playing and wait in a mainloop. */ 
    gst_element_set_state (app->pipeline, GST_STATE_PLAYING); 

    /* this mainloop is stopped when we receive an error or EOS */ 
    g_main_loop_run (app->loop); 
    GST_DEBUG ("stopping"); 
    gst_element_set_state (app->pipeline, GST_STATE_NULL); 
    gst_object_unref (bus); 
    g_main_loop_unref (app->loop); 
    cvReleaseCapture(&capture); 
return 0; 
} 

¿Alguna idea ???

+0

intenta publicar esto como una pregunta separada, no como respuesta –

Cuestiones relacionadas