How to change appsrc caps dynamically ?

comicfans44 comicfans44 at gmail.com
Tue May 6 07:36:02 PDT 2014


Hello everyone, I'm using appsrc to push some raw video frame,  frame size 
is changing dynamically, so I must changing appsrc caps before differenct 
size buffer pushed to it, I created a simple demo like this:

#include <stdlib.h>
#include <gst/gst.h>
#include <gst/app/gstappsrc.h>
#include <glib-object.h>


GstAppSrc *appsrc;

gboolean enough=FALSE;

int width=512;
int height=256;

GstCaps* create_caps(){
 return gst_caps_new_simple("video/x-raw",
                "format", G_TYPE_STRING, "RGBA",
                "width", G_TYPE_INT, width,
                "height", G_TYPE_INT, height,
                "framerate", GST_TYPE_FRACTION, 60, 1,
                "pixel-aspect-ratio",GST_TYPE_FRACTION,1,1,
                NULL) ;

}

static void
start_feed (GstElement * appSrc, guint size, void *nouse)
{
    enough=FALSE;
    while(enough==FALSE){

        int buf_size=width*height*4;
        char *buf=malloc(buf_size);
        int i=0;
        static counter=0;
	//random buffer
        for(;i<buf_size;++i){ buf[i]=(i+counter)%256;      }
        GstBuffer *gst_buf=gst_buffer_new_wrapped(buf,buf_size);
        gst_app_src_push_buffer(appsrc,gst_buf);
        ++counter;

      //changing caps
        if(counter%100==0){
            height+=10;
	GstCaps* new_caps=create_caps(); 
	gst_app_src_set_caps(appsrc,new_caps);
        }
    }
}


static void
stop_feed (GstElement * pipeline, void * dynamicCapsPipeline)
{
    enough=TRUE;
}

int main(int argc, char *argv[])
{
    g_type_init();
    gst_init(&argc,&argv);
    appsrc=gst_element_factory_make("appsrc",NULL);

    g_signal_connect (appsrc, "need-data", G_CALLBACK (start_feed), NULL); 
    g_signal_connect (appsrc, "enough-data", G_CALLBACK (stop_feed), NULL);

    GstCaps* caps=create_caps();
    gst_app_src_set_caps(appsrc,caps);

    gst_caps_unref(caps);
    GstElement *pipeline=gst_pipeline_new(NULL);
    GstElement *convert=gst_element_factory_make("videoconvert",NULL);
    GstElement *sink=gst_element_factory_make("ximagesink",NULL);
    gst_bin_add_many(pipeline,appsrc,convert,sink,NULL);
    gst_element_link_many(appsrc,convert,sink,NULL);
    gst_element_set_state(pipeline,GST_STATE_PLAYING);

    GMainLoop *main_loop=g_main_loop_new(NULL,FALSE);

    g_main_loop_run(main_loop);

}

every times caps changing, there is error like :
 default 
../../../../gst-libs/gst/video/video-frame.c:152:gst_video_frame_map_id: 
invalid buffer size 585728 < 606208
and video flicked (1~2 frame) . seems some buffer have not flushed before 
caps changed complete.  I tried to use 

            GstPad* pad=gst_element_get_static_pad(appSrc,"src");

            GstEvent *flushStart=gst_event_new_flush_start();
            GstEvent *flushStop=gst_event_new_flush_stop(TRUE/FALSE);
            
            gst_pad_push_event(pad,flushStart);
            gst_pad_push_event(pad,flushStop);

before set new caps to appsrc, but error still happened. if pipeline is 
videotestsrc ! capsfilter ! videoconvert ! ximagesink
I can changing capsfilter caps  with no problem .
how could I do similar within appsrc correctly? Thank you.








More information about the gstreamer-devel mailing list