gstreamer appsrc application de test
Je suis en train d'apprendre gstreamer appsrc plugin pour jouer AV à partir d'un flux de transport démultiplexeur que j'ai écrit (je sais que les plugins sont déjà disponibles, je voulais le faire moi-même pour apprendre). J'ai extrait l'audio et de la vidéo en flux élémentaires à partir du flux de transport MPEG; maintenant, je dois le pousser à la appsrc plugin et de le lire avec un tps de pipeline (cette partie n'est pas encore clair pour moi: tant de plugins à utiliser - des conseils seront très appréciés).
J'ai trouvé un exemple de code sur l'utilisation de appsrc, mais quand je le lance il n'y a pas de sortie. J'ai vérifié que start_feed
et read_data
fonctions sont en effet invoqué. Dans read_data
fonction, il y a un timer de vérifier pour décider d'envoyer des données ou pas:
ms = g_timer_elapsed(app->timer, NULL);
printf("ms %f\n", ms);
if (ms > 1.0/20.0) {
Je ne sais pas ce que ce timer est pour, mais la valeur de ms
est toujours autour de 0,035 et les données ne sont jamais poussé dans la appsrc. J'ai donc changé la condition if pour if(ms > 0.03)
mais j'ai eu un interne de flux de données d'erreur:
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)
Quelqu'un peut me dire comment modifier ce fichier pour voir la vidéo? Le code à partir du site web lié est donnée ci-dessous.
#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;
}
Mise à jour: j'ai essayé de remplacer udpsink normale xvimagesink et il n'a pas aidé
- La réponse que j'ai posté est une version de travail de appsrc code de test, mais n'a pas vraiment répondre à la question de savoir pourquoi ce code ne fonctionne pas. Donc merci de poster si vous connaissez la réponse.
Vous devez vous connecter pour publier un commentaire.
Depuis, personne n'a pris la peine de répondre, je les poste de travail, le code de test pour appsrc plugin - bien que cela n'est pas la réponse à pourquoi le code en question ne fonctionne pas, cela aidera les gens à l'atterrissage ici de Google lors de la recherche de appsrc code de test.
Avec beaucoup de grâce pour les gourous sur IRC/freenode/#gstreamer (surtout __tim!), J'ai trouvé comment corriger les bugs dans votre exemple de code.
Bug 1. La dernière ligne de read_data() doit "return TRUE" pour que cette fonction reste dans le bus, et sera appelé à plusieurs reprises. Seulement return FALSE lorsque vous voulez arrêter d'envoyer des données complètement.
Bug 2. Remplacer gst_caps_new_simple() avec gst_video_format_new_caps(). Vous aurez aussi besoin d'inclure la tps/vidéo/vidéo.h, et le lien de contre -lgstvideo-0.10.
Voici ma version du code, en montrant à la fois la façon d'afficher les images et comment diffuser une theora-version codée par UDP. Notez l'utilisation de videorate pour le dernier cas, depuis theora s'attend à une constante de la fréquence d'image de la source.