Hi Leonardo,
I don't know if you want me just to run the audio-player of the hello-world app or run my video getting rid of playbin2.
As I cannot confirm a complete de-initialisation of the audio player, I've done the second one using mfw_v4lsink, based on this code: All Boards Creating App Video
My code looks as follows:
===============================================================================================================
void on_pad_added (GstElement *element, GstPad *pad){
g_debug ("Signal: pad-added");
GstCaps *caps;
GstStructure *str;
caps = gst_pad_get_caps (pad);
g_assert (caps != NULL);
str = gst_caps_get_structure (caps, 0);
g_assert (str != NULL);
printf("STR[%s]\n", gst_structure_get_name (str));
if (g_strrstr (gst_structure_get_name (str), "video")) {
g_debug ("Linking video pad to dec_vd");
// Link it actually
GstPad *targetsink = gst_element_get_pad (decvd, "sink");
g_assert (targetsink != NULL);
gst_pad_link (pad, targetsink);
gst_object_unref (targetsink);
}
if (g_strrstr (gst_structure_get_name (str), "audio")) {
g_debug ("Linking audio pad to dec_ad");
// Link it actually
GstPad *targetsink = gst_element_get_pad (decad, "sink");
g_assert (targetsink != NULL);
gst_pad_link (pad, targetsink);
gst_object_unref (targetsink);
}
gst_caps_unref (caps);
}
static gboolean bus_call (GstBus *bus, GstMessage *msg, gpointer data){
GMainLoop *loop = (GMainLoop *) data;
gchar *debug;
GError *error;
switch (GST_MESSAGE_TYPE (msg)) {
case GST_MESSAGE_EOS:
g_print ("End of stream\n");
g_main_loop_quit (loop);
break;
case GST_MESSAGE_ERROR:
gst_message_parse_error (msg, &error, &debug);
g_free (debug);
g_printerr ("Error: %s\n", error->message);
g_error_free (error);
g_main_loop_quit (loop);
break;
default:
break;
}
return TRUE;
}
int play_video (char* video_file){
GMainLoop *loop;
GstElement *pipeline;
GstBus *bus;
static int init = 1;
loop = g_main_loop_new (NULL, FALSE);
/* Create gstreamer elements */
pipeline = gst_pipeline_new ("media-player");
source = gst_element_factory_make ("filesrc", "file-source");
fqueue = gst_element_factory_make ("multiqueue", "file-queue");
demuxer = gst_element_factory_make ("qtdemux", "avi-demuxer");
decvd = gst_element_factory_make ("mfw_h264decoder", "video-decoder");
vdqueue = gst_element_factory_make ("queue", "video-queue");
vdsink = gst_element_factory_make ("mfw_v4lsink", "video-sink");
decad = gst_element_factory_make ("mfw_mp3decoder", "audio-decoder");
adqueue = gst_element_factory_make ("queue", "audio-queue");
adconv = gst_element_factory_make ("audioconvert", "audio-converter");
adresamp = gst_element_factory_make ("audioresample", "audio-resampler");
adsink = gst_element_factory_make ("alsasink", "audio-sink"); // "autoaudiosink"
if (!pipeline) {g_printerr ("Error: [pipeline] could not be created. Exiting.\n"); return -1;}
if (!source) {g_printerr ("Error: [source] could not be created. Exiting.\n"); return -1;}
if (!fqueue) {g_printerr ("Error: [fqueue] could not be created. Exiting.\n"); return -1;}
if (!demuxer) {g_printerr ("Error: [demuxer] could not be created. Exiting.\n"); return -1;}
if (!decvd) {g_printerr ("Error: [decvd] could not be created. Exiting.\n"); return -1;}
if (!vdqueue) {g_printerr ("Error: [vdqueue] could not be created. Exiting.\n"); return -1;}
if (!vdsink) {g_printerr ("Error: [vdsink] could not be created. Exiting.\n"); return -1;}
if (!decad) {g_printerr ("Error: [decad] could not be created. Exiting.\n"); return -1;}
if (!adqueue) {g_printerr ("Error: [adqueue] could not be created. Exiting.\n"); return -1;}
if (!adconv) {g_printerr ("Error: [adconv] could not be created. Exiting.\n"); return -1;}
if (!adresamp) {g_printerr ("Error: [adresamp] could not be created. Exiting.\n"); return -1;}
if (!adsink) {g_printerr ("Error: [adsink] could not be created. Exiting.\n"); return -1;}
/* Set up the pipeline */
/* we set the input filename to the source element */
g_object_set (G_OBJECT (source), "location", video_file, NULL);
/* we add a message handler */
bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline));
gst_bus_add_watch (bus, bus_call, loop);
gst_object_unref (bus);
/* we add all elements into the pipeline */
/* file-source | ogg-demuxer | vorbis-decoder | converter | alsa-output */
gst_bin_add_many (GST_BIN (pipeline), source, fqueue, demuxer, decvd, vdqueue, vdsink, decad, adqueue, adconv, adresamp, adsink, NULL);
/* we link the elements together */
if (!gst_element_link (source, fqueue)) {g_printerr ("Error: unable to link [source <> fqueue]. Exiting.\n"); return -1;}
if (!gst_element_link (fqueue, demuxer)) {g_printerr ("Error: unable to link [fqueue <> demuxer]. Exiting.\n"); return -1;}
if (!gst_element_link (decvd, vdqueue)) {g_printerr ("Error: unable to link [decvd <> vdqueue]. Exiting.\n"); return -1;}
if (!gst_element_link (vdqueue, vdsink)) {g_printerr ("Error: unable to link [vdqueue <> vdsink]. Exiting.\n"); return -1;}
if (!gst_element_link (decad, adqueue)) {g_printerr ("Error: unable to link [decad <> adqueue]. Exiting.\n"); return -1;}
if (!gst_element_link (adqueue, adconv)) {g_printerr ("Error: unable to link [adqueue <> adconv]. Exiting.\n"); return -1;}
if (!gst_element_link (adconv, adresamp)) {g_printerr ("Error: unable to link [adconv <> adresamp]. Exiting.\n"); return -1;}
if (!gst_element_link (adresamp, adsink)) {g_printerr ("Error: unable to link [adresamp <> adsink]. Exiting.\n"); return -1;}
g_signal_connect (demuxer, "pad-added", G_CALLBACK (on_pad_added), NULL);
/* note that the demuxer will be linked to the decoder dynamically.
The reason is that Ogg may contain various streams (for example
audio and video). The source pad(s) will be created at run time,
by the demuxer when it detects the amount and nature of streams.
Therefore we connect a callback function which will be executed
when the "pad-added" is emitted.*/
/* Set the pipeline to "playing" state*/
g_print ("Now playing: %s\n", video_file);
gst_element_set_state (pipeline, GST_STATE_PLAYING);
/* Iterate */
g_print ("Running...\n");
g_main_loop_run (loop);
/* Out of the main loop, clean up nicely */
g_print ("Returned, stopping playback\n");
gst_element_set_state (pipeline, GST_STATE_NULL);
g_print ("Deleting pipeline\n");
gst_object_unref (GST_OBJECT (pipeline));
return 0;
}
int main (int argc, char *argv[]){
gst_init (NULL, NULL);
while(1){
play_video("/mnt/gonzalo/Copreci-heart_x264_200x120_12000_15fps_320_22050.mp4");
}
return -1;
}
===============================================================================================================
As in my previous tests using playbin2 , this code runs fine only for the first time. /dev/video0 remains open for ever and in the second run the driver returns EBUSY and mfw_v4lsink fails.
Thanks,
Gonzalo.