Загрузка изображений в конвейер gstreamer - PullRequest
6 голосов
/ 15 марта 2011

После игры с некоторыми игрушечными приложениями, изучения документации и поиска в Google (включая архивы списков рассылки) я все еще озадачен тем, что я считаю довольно распространенным вариантом использования.

У меня есть существующийкод, который генерирует изображения (в памяти), и я хотел бы поместить эти изображения в конвейер gstreamer (для создания FLV-видео в конце).

Я не смог найти «очевидный способ сделать это».Моим лучшим предположением будет копаться в исходном коде GstMultiFileSrc и его родительском GstPushSrc, чтобы понять это.

Может ли кто-нибудь из вас указать мне на «очевидный способ» сделать это?Есть ли какая-либо связанная с этим документация / учебное пособие / пример по этому поводу?

Как только я получу право ввода, все остальное - кусок пирога, благодаря удивительности Gstreamer!(что-то вроде «мой волшебный ввод -> ffmpegcolorspace! ffenc_flv! flvmux! filesink location = desktop.flv»)

Спасибо за ваши ответы.

Ответы [ 3 ]

7 голосов
/ 15 марта 2011

GStreamer использует плагины, чтобы делать все. Плагины, которые создают данные или получают их из внешнего источника, называются плагинами "src".

Универсальный плагин src для ввода данных, генерируемых приложением, в конвейер называется appsrc . API, предоставляемый appsrc, задокументирован как часть библиотеки приложений .

Вот один пример, демонстрирующий подачу appsrc сгенерированными изображениями: gdk-gstappsrc-stream.c . Похоже, он получен из некоторого тестового кода в дереве исходных кодов GStreamer: здесь .

Другой подход заключается в создании собственного плагина src. Посмотрите на плагин goom для музыкальной визуализации, чтобы увидеть пример, который работает аналогично тому, как вы указали.

2 голосов
/ 29 марта 2011

Я нашел решение (возможно) для этого (я получаю изображения с OpenCV) ... но у меня есть ошибка с конвейером: ОШИБКА от элемента mysource: Ошибка en el flujo de datos interno. Информация об отладке: gstbasesrc.c (2574): gst_base_src_loop (): / GstPipeline: pipe0 / GstAppSrc: mysource: задача потоковой передачи приостановлена, причина не согласована (-4)

это код:

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

Есть идеи ???

1 голос
/ 15 марта 2011

Вы можете попробовать взломать imagefreeze , чтобы сделать то, что вы хотите. appsrc также может это сделать.

...