I can't change filesink location on runtime without loosing data.

Danny churli at empal.com
Wed Aug 31 17:04:58 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
forum

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/I-can-t-change-filesink-location-on-runtime-without-loosing-data-tp3782508p3782508.html
Sent from the GStreamer-devel mailing list archive at Nabble.com.


More information about the gstreamer-devel mailing list