gstreamer appsrc test-Anwendung
Ich versuche zu lernen gstreamer appsrc plugin auf AV spielen, von einem transport stream demultiplexer, den ich geschrieben habe (ich weiß, plugins sind bereits verfügbar, ich wollte es selbst zu tun zu lernen). Ich habe extrahiert audio-und video-elementar-streams aus dem MPEG-transport-stream; ich muss jetzt schieben Sie es auf die appsrc plugin und spielen Sie es mit einem gst-pipeline (dieser Teil ist noch nicht ganz klar für mich: welche plugins zu verwenden - alle Tipps werden hoch geschätzt).
Fand ich eine Beispiel-code zur Verwendung appsrc, aber wenn ich ausführen, dass es keine Ausgabe. Ich habe überprüft, dass start_feed
und read_data
Funktionen sind in der Tat aufgerufen. In read_data
Funktion, es ist ein timer überprüfen, um zu entscheiden, ob Sie push-Daten oder nicht:
ms = g_timer_elapsed(app->timer, NULL);
printf("ms %f\n", ms);
if (ms > 1.0/20.0) {
Ich weiß nicht, was dieser timer ist für, aber der Wert von ms
ist immer um 0.035 und Daten nie geschoben in die appsrc. Also änderte ich die if-Bedingung if(ms > 0.03)
aber dann habe ich eine interne Datenfluss-Fehler:
ms 0.033747
ms 0.000010
ERROR from element mysource: Internal data flow error.
Debugging info: gstbasesrc.c(2582): gst_base_src_loop (): /GstPipeline:pipeline0/GstAppSrc:mysource:
streaming task paused, reason not-negotiated (-4)
Kann mir jemand sagen, wie das zwicken, um das video zu sehen? Der code von der verlinkten website ist unten angegeben.
#include <gst/gst.h>
#include <gst/app/gstappsrc.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <gdk-pixbuf/gdk-pixbuf.h>
GST_DEBUG_CATEGORY (appsrc_pipeline_debug);
#define GST_CAT_DEFAULT appsrc_pipeline_debug
typedef struct _App App;
struct _App
{
GstElement *pipeline;
GstElement *appsrc;
GMainLoop *loop;
guint sourceid;
GTimer *timer;
};
App s_app;
static gboolean
read_data (App * app)
{
guint len;
GstFlowReturn ret;
gdouble ms;
ms = g_timer_elapsed(app->timer, NULL);
printf("ms %f\n", ms);
if (ms > 1.0/20.0) {
GstBuffer *buffer;
GdkPixbuf *pb;
gboolean ok = TRUE;
buffer = gst_buffer_new();
pb = gdk_pixbuf_new(GDK_COLORSPACE_RGB, FALSE, 8, 640, 480);
gdk_pixbuf_fill(pb, 0xffffffff);
GST_BUFFER_DATA (buffer) = gdk_pixbuf_get_pixels(pb);
GST_BUFFER_SIZE (buffer) = 640*480*3*sizeof(guchar);
GST_DEBUG ("feed buffer");
g_signal_emit_by_name (app->appsrc, "push-buffer", buffer, &ret);
gst_buffer_unref (buffer);
if (ret != GST_FLOW_OK) {
/* some error, stop sending data */
GST_DEBUG ("some error");
ok = FALSE;
}
g_timer_start(app->timer);
return ok;
}
//g_signal_emit_by_name (app->appsrc, "end-of-stream", &ret);
return FALSE;
}
/* This signal callback is called when appsrc needs data, we add an idle handler
* to the mainloop to start pushing data into the appsrc */
static void
start_feed (GstElement * pipeline, guint size, App * app)
{
if (app->sourceid == 0) {
GST_DEBUG ("start feeding");
app->sourceid = g_idle_add ((GSourceFunc) read_data, app);
}
}
/* This callback is called when appsrc has enough data and we can stop sending.
* We remove the idle handler from the mainloop */
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;
gst_init (&argc, &argv);
GST_DEBUG_CATEGORY_INIT (appsrc_pipeline_debug, "appsrc-pipeline", 0,
"appsrc pipeline example");
/* 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 ! udpsink host=127.0.0.1 port=1234", 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);
return 0;
}
Update: ich habe versucht, anstelle udpsink mit normalen xvimagesink und es hat nicht geholfen
InformationsquelleAutor Amarghosh | 2012-01-05
Du musst angemeldet sein, um einen Kommentar abzugeben.
Da hat niemand Lust zu Antworten, werde ich nach einen funktionierenden test-code für appsrc plugin - obwohl dies nicht beantworten, warum der code in der Frage nicht funktioniert, dies wird den Menschen helfen, die Landung hier von Google, wenn Sie suchen für appsrc test-code.
InformationsquelleAutor Amarghosh
Mit viel Dank an die gurus im IRC/freenode/#gstreamer (vor allem, __tim!), Ich habe herausgefunden, wie man den Fehler in deinem Beispiel-code.
Fehler 1. Die Letzte Zeile read_data() soll "TRUE " zurückgeben", so dass diese Funktion bleibt auf den bus, und wird immer wieder aufgerufen werden. Nur FALSE zurück, wenn Sie wollen, zu stoppen senden von Daten völlig.
Fehler 2. Ersetzen gst_caps_new_simple() mit gst_video_format_new_caps(). Sie müssen auch zählen gst/video/video.h und link-gegen -lgstvideo-0.10.
Hier ist meine version des Codes, zeigt sowohl, wie um die Bilder anzuzeigen und so streamen Sie einen theora-kodierte version über UDP. Notieren Sie sich die Nutzung der videorate für den letzteren Fall, da theora erwartet eine Konstante frame-rate Quelle.
InformationsquelleAutor Anqi