How to change the filesink location on runtime.

Danny churli at empal.com
Tue Aug 30 23:43:39 PDT 2011


Hi all.

In advance I want to say that sorry for my poor English.

I'm a newbie to Gstreamer.

I tried to make recording app like this(v4l2 -> omx_h264enc ->
queue->mpegtsmux -> filesink).

I got some tip that is about dynamic filesink location change from this site 

and I made recording app as I learned.

I want my app to make new recoding file every 1 min without loosing data.

Below is my code. I doesn't work. 

I think that there are some problem when gst_pad_set_blocked_async() is
called.

Callback function seems not to be called.

please give me a good way. 

have a nice day!


#include <gst/gst.h>
#include <glib.h>

#define true 1
#define false 0

GstElement *pipeline, *vsource, *asource, *conv,  *acodec, *h264enc, *mux,
*sink, *q1;
GstPad *q1_srcpad;
char name_buf[128];

GStaticRecMutex mutex;

int cnt;
static void create_filesink_tail()
{
    GstPad *srcpad;
    GstPad *sinkpad;
    
    sink = NULL;
   sink = gst_element_factory_make ("filesink", NULL);

    if(!sink)
    {
        g_print("faile to create new sink element! \n");
        return; 
    }

    gst_bin_add(GST_BIN (pipeline), sink); 

    gst_element_link(mux, sink);
    srcpad = gst_element_get_static_pad( mux, "src" ); 
    sinkpad = gst_element_get_static_pad( sink, "sink" ); 

    gst_pad_link(srcpad,sinkpad);

    sprintf(name_buf, "test%d.mp4", cnt++);
    g_object_set( G_OBJECT( sink ), "location", name_buf, NULL ); 
}


static gboolean destroy_bin_cb (gpointer user_data) 
{ 
    GstElement *oldbin = user_data; 

    g_print("Destroying old bin.\n"); 
    if (pipeline) 
    { 
        gst_element_set_state (oldbin, GST_STATE_NULL); 
        gst_bin_remove (GST_BIN(pipeline), oldbin); 
    } 
    return FALSE; 
} 


static void replace_filesink_blocked_cb (GstPad *pad, gboolean blocked,
gpointer user_data) 
{ 
    int ret;
    
    if (blocked) 
    { 
        GstElement *oldbin; 
        GstPad *sinkpad; 

        g_print("Blocked filesink queue.\n"); 
       // g_static_rec_mutex_lock(&mutex); 
        g_print("Locked.\n"); 
        oldbin = sink; 
        sinkpad = gst_element_get_static_pad(oldbin, "sink"); 
        if (!sinkpad) 
        { 
            g_print("replace_filesink_blocked_cb: oldbin doesn't have sink
pad.\n"); 
            goto fail; 
        } 
        gst_pad_unlink(q1_srcpad, sinkpad); 
        g_print("Unlinked.\n"); 


        gst_pad_send_event(sinkpad, gst_event_new_eos()); 
        g_print("Sent event.\n"); 

        g_print("Checked sinks.\n"); 

        g_idle_add(destroy_bin_cb, oldbin); 

        create_filesink_tail(); 
        g_print("Created filesink.\n"); 
        //g_static_rec_mutex_unlock(&mutex); 
        g_print("Unlocked mutex.\n"); 

        /* And unblock again. */ 
        ret = gst_pad_set_blocked_async(q1_srcpad, false,
replace_filesink_blocked_cb, NULL); 
        g_print("gst_pad_set_unblocked_async ret : %d \n", ret );

        g_print("Done replacing filesink.\n"); 
    } 
    else 
    { 
        g_print("Unblocked filesink queue.\n"); 
    } 
    return; 

fail: 
    return;
} 

static void replace_filesink() 
{ 
    int ret;
    if (q1_srcpad == NULL) 
        g_print("replace_filesink while no queuesrcpad yet, waiting for it
to appear.\n"); 
    else 
    {
       ret =  gst_pad_set_blocked_async(q1_srcpad, true, 
replace_filesink_blocked_cb, NULL); 
       g_print("gst_pad_set_blocked_async ret : %d \n", ret );
    }
} 




static gboolean link_video_elements_with_filter (GstElement *element1,
GstElement *element2)
{
    gboolean link_ok;
    GstCaps *caps;

    caps = gst_caps_new_simple ("video/x-raw-yuv",
    //"format", GST_TYPE_FOURCC, GST_MAKE_FOURCC ('I','4','2','0'),
    "width", G_TYPE_INT, 1280,
    "height", G_TYPE_INT, 720,
    //"framerate", GST_TYPE_FRACTION, 25, 1,
    NULL);
    
    link_ok = gst_element_link_filtered (element1, element2, caps);
    gst_caps_unref (caps);
    
    if (!link_ok) {
        g_warning ("Failed to link element1 and element2!(v4l2src)");
    }
    return link_ok;
}



static gboolean link_audio_elements_with_filter (GstElement *element1,
GstElement *element2)
{
    gboolean link_ok;
    GstCaps *caps;

    caps = gst_caps_new_simple ("audio/x-raw-int",
    "channels", G_TYPE_INT, 2,
    "rate", G_TYPE_INT, 44100,
    "width", G_TYPE_INT, 16,
    "signed", G_TYPE_BOOLEAN, 1,
    "depth", G_TYPE_INT, 16,
    NULL);
    
    link_ok = gst_element_link_filtered (element1, element2, caps);
    gst_caps_unref (caps);
    
    if (!link_ok) {
        g_warning ("Failed to link element1 and element2!(alsasrc)");
    }
    return link_ok;
}


static void on_pad_added (GstElement *element, GstPad *pad, gpointer data)
{
    GstPad *sinkpad;
    GstElement *decoder = (GstElement *) data;
    
    /* We can now link this pad with the vorbis-decoder sink pad */
    g_print ("Dynamic pad created, linking demuxer/decoder\n");
    
    sinkpad = gst_element_get_static_pad (decoder, "sink");
    gst_pad_link (pad, sinkpad);
    gst_object_unref (sinkpad);
}






int cnt;
static gboolean bus_call (GstBus *bus, GstMessage *msg, gpointer data)
{
    GMainLoop *loop = (GMainLoop *) data;
    int rc;
    
    switch (GST_MESSAGE_TYPE (msg)) {
        case GST_MESSAGE_EOS:
            g_print("get EOS ... \n");
            break;
        case GST_MESSAGE_ERROR: {
            gchar *debug;
            GError *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;
}


 gpointer rec_loop(gpointer data)
 {
    int rc;

    g_print("start recording loop ... \n ");
    
    while(1)
    {
        sleep(60);

       replace_filesink( ); 
      
       g_print("replacing file sink complte .. \n");
    }
 }



 
int main (int argc, char *argv[])
{
    int ret = 0;
    
    GMainLoop *loop;

    GstBus *bus;
    pthread_t *thread;
    
    GError *err = NULL;

    GStaticRecMutex mut = G_STATIC_REC_MUTEX_INIT;
    mutex = mut;
   

    /* Initialisation */
    gst_init (&argc, &argv);
    loop = g_main_loop_new (NULL, FALSE);    

    
    /* Create gstreamer elements */
    pipeline = gst_pipeline_new ("cl-blackboxr");
    vsource = gst_element_factory_make ("v4l2src", "v4l-source");
    h264enc = gst_element_factory_make ("omx_h264enc", "h264enc");

    //asource =  gst_element_factory_make ("alsasrc", "alsa-source");
    //conv =  gst_element_factory_make ("audioconvert", "audio-converter");    
    //acodec =  gst_element_factory_make ("faac", "audio-codec");        

    mux = gst_element_factory_make ("avimux", "muxer");
    sink = gst_element_factory_make ("filesink", "fsink");

    q1 = gst_element_factory_make ("queue", "q1");



    if (!pipeline || !vsource || !h264enc || !mux ) {
        g_print ("One element 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 (h264enc), "bitrate",400000, NULL);
    g_object_set (G_OBJECT (sink), "location","test.mp4", 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);

    gst_bin_add_many (GST_BIN (pipeline), vsource, h264enc, q1, mux, sink,
NULL); 


    /* we link the elements together */
    /* file-source -> ogg-demuxer ~> vorbis-decoder -> converter ->
alsa-output */
      link_video_elements_with_filter(vsource, h264enc);

    gst_element_link_many (h264enc, q1, mux, sink, NULL);
    //g_signal_connect (h264enc, "pad-added", G_CALLBACK (on_pad_added),
mux);
    g_signal_connect (q1, "pad-added", G_CALLBACK (on_pad_added), mux);


    /* Set the pipeline to "playing" state*/
    g_print ("Now playing: %s\n", argv[1]);
    ret = gst_element_set_state (pipeline, GST_STATE_PLAYING);
    g_print("set state : %d \n", ret);

    /* Iterate */

    q1_srcpad =   gst_element_get_static_pad( q1, "src" ); 
    
    g_print ("Running...\n");

    g_thread_create((void *)rec_loop, NULL, FALSE, &err);

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






--
View this message in context: http://gstreamer-devel.966125.n4.nabble.com/How-to-change-the-filesink-location-on-runtime-tp3780325p3780325.html
Sent from the GStreamer-devel mailing list archive at Nabble.com.


More information about the gstreamer-devel mailing list