From 8f2b441e96d217918256d6771cc51de7d7ede882 Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Sun, 21 May 2000 21:58:20 +0000 Subject: [PATCH] Fixed the mpeg2 encoder. Added MMX optimisations for motion estimation. Original commit message from CVS: Fixed the mpeg2 encoder. Added MMX optimisations for motion estimation. Added another mpeg1 encoder. Added Two filters: smooth and median (a median cut filter) Made the queue pull buffers. --- configure.in | 4 + docs/gst/gstreamer-decl.txt | 116 ++++++++++++++-------------- docs/gst/gstreamer.hierarchy | 4 + docs/gst/tmpl/gsthttpsrc.sgml | 11 +++ docs/gst/tmpl/gstreamer-unused.sgml | 91 ++++++++++------------ gst/elements/gstqueue.c | 47 +++++++---- gst/gstbuffer.h | 2 + libs/videoscale/gstvideoscale.c | 12 +-- plugins/elements/gstqueue.c | 47 +++++++---- test/Makefile.am | 4 +- test/avi2mpg.c | 14 +++- test/mp2tomp1.c | 2 + test/vidcapture.c | 32 ++++++-- 13 files changed, 227 insertions(+), 159 deletions(-) diff --git a/configure.in b/configure.in index 0550616296..542948beda 100644 --- a/configure.in +++ b/configure.in @@ -345,8 +345,12 @@ plugins/mpeg2/mpeg2enc/Makefile plugins/mpeg1/Makefile plugins/mpeg1/mpeg_play/Makefile plugins/mpeg1/parse/Makefile +plugins/mpeg1/mpeg1encoder/Makefile plugins/mpeg1video/Makefile plugins/mpeg1video/parse/Makefile +plugins/filters/Makefile +plugins/filters/smooth/Makefile +plugins/filters/median/Makefile plugins/effects/Makefile plugins/effects/stereo/Makefile plugins/effects/volume/Makefile diff --git a/docs/gst/gstreamer-decl.txt b/docs/gst/gstreamer-decl.txt index ca4a6d42e1..ce2f17a172 100644 --- a/docs/gst/gstreamer-decl.txt +++ b/docs/gst/gstreamer-decl.txt @@ -359,6 +359,64 @@ GstBuffer *buffer void GstBuffer *buffer,GstMeta *meta + +GstClockTime +typedef guint64 GstClockTime; + + +GstClockTimeDiff +typedef gint64 GstClockTimeDiff; + + +GST_CLOCK_DIFF +#define GST_CLOCK_DIFF(s, e) (GstClockTimeDiff)((s)-(e)) + + +GstClock + + +GstClock +struct GstClock { + gchar *name; + GstClockTime start_time; + GstClockTime current_time; + GstClockTimeDiff adjust; + gboolean locking; + GList *sinkobjects; + GMutex *sinkmutex; + GMutex *lock; +}; + + +gst_clock_new +GstClock * +gchar *name + + +gst_clock_get_system +GstClock * +void + + +gst_clock_register +void +GstClock *clock, GstObject *obj + + +gst_clock_set +void +GstClock *clock, GstClockTime time + + +gst_clock_reset +void +GstClock *clock + + +gst_clock_wait +void +GstClock *clock, GstClockTime time, GstObject *obj + GST_TYPE_CONNECTION #define GST_TYPE_CONNECTION \ @@ -1767,64 +1825,6 @@ GtkObject *object,guchar *argname xmlDocPtr GstElement *element - -GstClockTime -typedef guint64 GstClockTime; - - -GstClockTimeDiff -typedef gint64 GstClockTimeDiff; - - -GST_CLOCK_DIFF -#define GST_CLOCK_DIFF(s, e) (GstClockTimeDiff)((s)-(e)) - - -GstClock - - -GstClock -struct GstClock { - gchar *name; - GstClockTime start_time; - GstClockTime current_time; - GstClockTimeDiff adjust; - gboolean locking; - GList *sinkobjects; - GMutex *sinkmutex; - GMutex *lock; -}; - - -gst_clock_new -GstClock * -gchar *name - - -gst_clock_get_system -GstClock * -void - - -gst_clock_register -void -GstClock *clock, GstObject *obj - - -gst_clock_set -void -GstClock *clock, GstClockTime time - - -gst_clock_reset -void -GstClock *clock - - -gst_clock_wait -void -GstClock *clock, GstClockTime time, GstObject *obj - GST_TYPE_ASYNCDISKSRC #define GST_TYPE_ASYNCDISKSRC \ diff --git a/docs/gst/gstreamer.hierarchy b/docs/gst/gstreamer.hierarchy index 9ff9ac89df..9f67b2d2e1 100644 --- a/docs/gst/gstreamer.hierarchy +++ b/docs/gst/gstreamer.hierarchy @@ -1,4 +1,7 @@ GtkObject + GtkWidget + GtkRange + GtkContainer GstObject GstElement GstBin @@ -15,6 +18,7 @@ GtkObject GstFakeSrc GstDiskSrc GstAsyncDiskSrc + GstHttpSrc GstFdSrc GstAudioSrc GstSineSrc diff --git a/docs/gst/tmpl/gsthttpsrc.sgml b/docs/gst/tmpl/gsthttpsrc.sgml index 2ba4a00e8d..f1c74b859a 100644 --- a/docs/gst/tmpl/gsthttpsrc.sgml +++ b/docs/gst/tmpl/gsthttpsrc.sgml @@ -14,3 +14,14 @@ Reads data from a URL. + + +Specify the location of the file. The location must be a fully qualified URL. + + + + +Specify how many bytes to read at a time. + + + diff --git a/docs/gst/tmpl/gstreamer-unused.sgml b/docs/gst/tmpl/gstreamer-unused.sgml index 24320c0752..3a53dc78ab 100644 --- a/docs/gst/tmpl/gstreamer-unused.sgml +++ b/docs/gst/tmpl/gstreamer-unused.sgml @@ -72,13 +72,6 @@ - - -Specify how many bytes to read at a time. - - - - @@ -174,13 +167,6 @@ Specify how many bytes to read at a time. @Returns: - - - - - -@obj: - @@ -188,19 +174,19 @@ Specify how many bytes to read at a time. @Returns: + + + + + +@obj: + - - - - - -@klass: - @@ -208,6 +194,13 @@ Specify how many bytes to read at a time. @Returns: + + + + + +@klass: + @@ -346,6 +339,12 @@ Specify how many bytes to read at a time. + + + + + + @@ -353,12 +352,6 @@ Specify how many bytes to read at a time. @klass: - - - - - - @@ -667,14 +660,14 @@ The frequency. - + @klass: - + @@ -1274,13 +1267,6 @@ plugin - - - - - -@Returns: - @@ -1288,6 +1274,13 @@ plugin @meta: + + + + + +@Returns: + @@ -1329,12 +1322,6 @@ plugin - - - - - - @@ -1342,6 +1329,12 @@ plugin @obj: + + + + + + @@ -1419,10 +1412,6 @@ GstElement @obj: - - - - @@ -1430,6 +1419,10 @@ GstElement @src: + + + + @@ -1495,12 +1488,6 @@ GstElement @klass: - - -Specify the location of the file. The location must be a fully qualified URL. - - - diff --git a/gst/elements/gstqueue.c b/gst/elements/gstqueue.c index 45867c6f28..4cf73cc8e9 100644 --- a/gst/elements/gstqueue.c +++ b/gst/elements/gstqueue.c @@ -17,6 +17,7 @@ * Boston, MA 02111-1307, USA. */ +//#define DEBUG_ENABLED #include @@ -48,6 +49,7 @@ static void gst_queue_class_init(GstQueueClass *klass); static void gst_queue_init(GstQueue *queue); static void gst_queue_set_arg(GtkObject *object,GtkArg *arg,guint id); static void gst_queue_get_arg(GtkObject *object,GtkArg *arg,guint id); +static GstBuffer *gst_queue_pull(GstPad *pad); void gst_queue_push(GstConnection *connection); void gst_queue_chain(GstPad *pad,GstBuffer *buf); @@ -99,6 +101,7 @@ static void gst_queue_init(GstQueue *queue) { queue->sinkpad = gst_pad_new("sink",GST_PAD_SINK); gst_element_add_pad(GST_ELEMENT(queue),queue->sinkpad); gst_pad_set_chain_function(queue->sinkpad,gst_queue_chain); + gst_pad_set_pull_function(queue->sinkpad,gst_queue_pull); queue->srcpad = gst_pad_new("src",GST_PAD_SRC); gst_element_add_pad(GST_ELEMENT(queue),queue->srcpad); @@ -123,6 +126,18 @@ GstElement *gst_queue_new(gchar *name) { return queue; } +static GstBuffer *gst_queue_pull(GstPad *pad) { + GstQueue *queue; + GstBuffer *buf; + + queue = GST_QUEUE(pad->parent); + + if (GST_PAD_CAN_PULL(queue->srcpad) && (buf = gst_pad_pull(queue->srcpad)) != NULL) { + return buf; + } + else return NULL; +} + void gst_queue_chain(GstPad *pad,GstBuffer *buf) { GstQueue *queue; gboolean tosignal = FALSE; @@ -136,19 +151,19 @@ void gst_queue_chain(GstPad *pad,GstBuffer *buf) { /* we have to lock the queue since we span threads */ GST_LOCK(queue); - //g_print("queue: chain %d\n", queue->level_buffers); + DEBUG("queue: chain %d %p\n", queue->level_buffers, buf); if (queue->level_buffers >= queue->max_buffers) { - //g_print("queue: waiting %d\n", queue->level_buffers); + DEBUG("queue: waiting %d\n", queue->level_buffers); GST_UNLOCK(queue); while (queue->level_buffers >= queue->max_buffers) { g_mutex_lock(queue->fulllock); -// g_print("0"); + //g_print("O"); g_cond_wait(queue->fullcond,queue->fulllock); g_mutex_unlock(queue->fulllock); } GST_LOCK(queue); - //g_print("queue: waiting done %d\n", queue->level_buffers); + DEBUG("queue: waiting done %d\n", queue->level_buffers); } @@ -163,20 +178,21 @@ void gst_queue_chain(GstPad *pad,GstBuffer *buf) { // queue->tail = g_list_next(queue->tail); queue->queue = g_list_append(queue->queue,buf); } -// g_print("+"); + //g_print("+"); /* if we were empty, but aren't any more, signal a condition */ - tosignal = (queue->level_buffers++ == 0); + tosignal = (queue->level_buffers <= 0); + queue->level_buffers++; /* we can unlock now */ - //g_print("queue: chain %d end\n", queue->level_buffers); + DEBUG("queue: chain %d end\n", queue->level_buffers); GST_UNLOCK(queue); if (tosignal) { g_mutex_lock(queue->emptylock); g_cond_signal(queue->emptycond); g_mutex_unlock(queue->emptylock); -// g_print(">"); + //g_print(">"); } } @@ -188,13 +204,13 @@ void gst_queue_push(GstConnection *connection) { /* have to lock for thread-safety */ GST_LOCK(queue); - //g_print("queue: push %d\n", queue->level_buffers); + DEBUG("queue: push %d\n", queue->level_buffers); if (!queue->level_buffers) { GST_UNLOCK(queue); while (!queue->level_buffers) { g_mutex_lock(queue->emptylock); -// g_print("0"); + //g_print("U"); g_cond_wait(queue->emptycond,queue->emptylock); g_mutex_unlock(queue->emptylock); } @@ -204,14 +220,10 @@ void gst_queue_push(GstConnection *connection) { front = queue->queue; buf = (GstBuffer *)(front->data); queue->queue = g_list_remove_link(queue->queue,front); - //g_print("queue: pushing %d\n", queue->level_buffers); - gst_pad_push(queue->srcpad,buf); - //g_print("queue: pushing %d done\n", queue->level_buffers); g_list_free(front); queue->level_buffers--; - + //g_print("-%d", queue->level_buffers); tosignal = queue->level_buffers < queue->max_buffers; - //g_print("queue: push end %d\n", queue->level_buffers); GST_UNLOCK(queue); if (tosignal) { @@ -219,7 +231,10 @@ void gst_queue_push(GstConnection *connection) { g_cond_signal(queue->fullcond); g_mutex_unlock(queue->fulllock); } - + + DEBUG("queue: pushing %d %p\n", queue->level_buffers, buf); + gst_pad_push(queue->srcpad,buf); + DEBUG("queue: pushing %d done\n", queue->level_buffers); /* unlock now */ } diff --git a/gst/gstbuffer.h b/gst/gstbuffer.h index f52db4f746..a550a25059 100644 --- a/gst/gstbuffer.h +++ b/gst/gstbuffer.h @@ -73,8 +73,10 @@ struct _GstBuffer { /* refcounting */ #ifdef HAVE_ATOMIC_H atomic_t refcount; +#define GST_BUFFER_REFCOUNT(buf) (atomic_read(&(GST_BUFFER((buf))->refcount))) #else int refcount; +#define GST_BUFFER_REFCOUNT(buf) (GST_BUFFER(buf)->refcount) #endif /* data type of this buffer */ diff --git a/libs/videoscale/gstvideoscale.c b/libs/videoscale/gstvideoscale.c index 8ac083ab9a..0b78c6376e 100644 --- a/libs/videoscale/gstvideoscale.c +++ b/libs/videoscale/gstvideoscale.c @@ -74,18 +74,19 @@ static char gst_videoscale_interp_simple(unsigned char *src, int x, int y, int d int interp; int i,j; - if (x>0) src--; - if (x>dw-1) src--; - if (y>0) src-=sw; - if (y>dh-1) src-=sw; + //printf("scale: %d %d %p\n", ix, iy, src); + if (x>=ix) src-=(ix); + if (y>=iy) src-=(sw*iy); isourcep = src; interp =0; for (i =0; i @@ -48,6 +49,7 @@ static void gst_queue_class_init(GstQueueClass *klass); static void gst_queue_init(GstQueue *queue); static void gst_queue_set_arg(GtkObject *object,GtkArg *arg,guint id); static void gst_queue_get_arg(GtkObject *object,GtkArg *arg,guint id); +static GstBuffer *gst_queue_pull(GstPad *pad); void gst_queue_push(GstConnection *connection); void gst_queue_chain(GstPad *pad,GstBuffer *buf); @@ -99,6 +101,7 @@ static void gst_queue_init(GstQueue *queue) { queue->sinkpad = gst_pad_new("sink",GST_PAD_SINK); gst_element_add_pad(GST_ELEMENT(queue),queue->sinkpad); gst_pad_set_chain_function(queue->sinkpad,gst_queue_chain); + gst_pad_set_pull_function(queue->sinkpad,gst_queue_pull); queue->srcpad = gst_pad_new("src",GST_PAD_SRC); gst_element_add_pad(GST_ELEMENT(queue),queue->srcpad); @@ -123,6 +126,18 @@ GstElement *gst_queue_new(gchar *name) { return queue; } +static GstBuffer *gst_queue_pull(GstPad *pad) { + GstQueue *queue; + GstBuffer *buf; + + queue = GST_QUEUE(pad->parent); + + if (GST_PAD_CAN_PULL(queue->srcpad) && (buf = gst_pad_pull(queue->srcpad)) != NULL) { + return buf; + } + else return NULL; +} + void gst_queue_chain(GstPad *pad,GstBuffer *buf) { GstQueue *queue; gboolean tosignal = FALSE; @@ -136,19 +151,19 @@ void gst_queue_chain(GstPad *pad,GstBuffer *buf) { /* we have to lock the queue since we span threads */ GST_LOCK(queue); - //g_print("queue: chain %d\n", queue->level_buffers); + DEBUG("queue: chain %d %p\n", queue->level_buffers, buf); if (queue->level_buffers >= queue->max_buffers) { - //g_print("queue: waiting %d\n", queue->level_buffers); + DEBUG("queue: waiting %d\n", queue->level_buffers); GST_UNLOCK(queue); while (queue->level_buffers >= queue->max_buffers) { g_mutex_lock(queue->fulllock); -// g_print("0"); + //g_print("O"); g_cond_wait(queue->fullcond,queue->fulllock); g_mutex_unlock(queue->fulllock); } GST_LOCK(queue); - //g_print("queue: waiting done %d\n", queue->level_buffers); + DEBUG("queue: waiting done %d\n", queue->level_buffers); } @@ -163,20 +178,21 @@ void gst_queue_chain(GstPad *pad,GstBuffer *buf) { // queue->tail = g_list_next(queue->tail); queue->queue = g_list_append(queue->queue,buf); } -// g_print("+"); + //g_print("+"); /* if we were empty, but aren't any more, signal a condition */ - tosignal = (queue->level_buffers++ == 0); + tosignal = (queue->level_buffers <= 0); + queue->level_buffers++; /* we can unlock now */ - //g_print("queue: chain %d end\n", queue->level_buffers); + DEBUG("queue: chain %d end\n", queue->level_buffers); GST_UNLOCK(queue); if (tosignal) { g_mutex_lock(queue->emptylock); g_cond_signal(queue->emptycond); g_mutex_unlock(queue->emptylock); -// g_print(">"); + //g_print(">"); } } @@ -188,13 +204,13 @@ void gst_queue_push(GstConnection *connection) { /* have to lock for thread-safety */ GST_LOCK(queue); - //g_print("queue: push %d\n", queue->level_buffers); + DEBUG("queue: push %d\n", queue->level_buffers); if (!queue->level_buffers) { GST_UNLOCK(queue); while (!queue->level_buffers) { g_mutex_lock(queue->emptylock); -// g_print("0"); + //g_print("U"); g_cond_wait(queue->emptycond,queue->emptylock); g_mutex_unlock(queue->emptylock); } @@ -204,14 +220,10 @@ void gst_queue_push(GstConnection *connection) { front = queue->queue; buf = (GstBuffer *)(front->data); queue->queue = g_list_remove_link(queue->queue,front); - //g_print("queue: pushing %d\n", queue->level_buffers); - gst_pad_push(queue->srcpad,buf); - //g_print("queue: pushing %d done\n", queue->level_buffers); g_list_free(front); queue->level_buffers--; - + //g_print("-%d", queue->level_buffers); tosignal = queue->level_buffers < queue->max_buffers; - //g_print("queue: push end %d\n", queue->level_buffers); GST_UNLOCK(queue); if (tosignal) { @@ -219,7 +231,10 @@ void gst_queue_push(GstConnection *connection) { g_cond_signal(queue->fullcond); g_mutex_unlock(queue->fulllock); } - + + DEBUG("queue: pushing %d %p\n", queue->level_buffers, buf); + gst_pad_push(queue->srcpad,buf); + DEBUG("queue: pushing %d done\n", queue->level_buffers); /* unlock now */ } diff --git a/test/Makefile.am b/test/Makefile.am index 27c826ade3..25dce549b0 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -1,7 +1,7 @@ #noinst_PROGRAMS = basic m types a r plugin w s args mpg123 mcut push qtest noinst_PROGRAMS = qtest spectrum record wave mp3 teardown buffer mp3parse \ mpeg2parse mp1parse mp3play ac3parse ac3play dvdcat fake cobin videotest \ - aviparse vidcapture avi2mpg mp2tomp1 + aviparse vidcapture avi2mpg mp2tomp1 mp1tomp1 SUBDIRS = xml cothreads bindings @@ -19,6 +19,8 @@ mpeg2parse_CFLAGS = $(shell gnome-config --cflags gnomeui) mpeg2parse_LDFLAGS = $(shell gnome-config --libs gnomeui) mp2tomp1_CFLAGS = $(shell gnome-config --cflags gnomeui) mp2tomp1_LDFLAGS = $(shell gnome-config --libs gnomeui) +mp1tomp1_CFLAGS = $(shell gnome-config --cflags gnomeui) +mp1tomp1_LDFLAGS = $(shell gnome-config --libs gnomeui) buffer_SOURCES = buffer.c mem.c teardown_SOURCES = teardown.c mem.c diff --git a/test/avi2mpg.c b/test/avi2mpg.c index c332dc5d23..23203e63c7 100644 --- a/test/avi2mpg.c +++ b/test/avi2mpg.c @@ -16,7 +16,7 @@ void eof(GstSrc *src) { } void new_pad_created(GstElement *parse,GstPad *pad,GstElement *pipeline) { - GstElement *parse_audio, *parse_video, *decode, *decode_video, *play, *encode; + GstElement *parse_audio, *parse_video, *decode, *decode_video, *play, *encode, *smooth; GstElement *audio_queue, *video_queue; GstElement *audio_thread, *video_thread; GstElement *fdsink; @@ -60,11 +60,16 @@ void new_pad_created(GstElement *parse,GstPad *pad,GstElement *pipeline) { } else if (strncmp(gst_pad_get_name(pad), "video_", 6) == 0) { //} else if (0) { + gst_plugin_load("smooth"); + gst_plugin_load("median"); gst_plugin_load("mpeg2enc"); // construct internal pipeline elements + smooth = gst_elementfactory_make("smooth","smooth"); + //smooth = gst_elementfactory_make("median","median"); + g_return_if_fail(smooth != NULL); + //gtk_object_set(GTK_OBJECT(smooth),"filtersize",9,NULL); encode = gst_elementfactory_make("mpeg2enc","encode"); g_return_if_fail(encode != NULL); - //gtk_object_set(GTK_OBJECT(show),"width",640, "height", 480,NULL); fd = open(outfile,O_CREAT|O_RDWR|O_TRUNC); fdsinkfactory = gst_elementfactory_find("fdsink"); @@ -76,14 +81,17 @@ void new_pad_created(GstElement *parse,GstPad *pad,GstElement *pipeline) { // create the thread and pack stuff into it video_thread = gst_thread_new("video_thread"); g_return_if_fail(video_thread != NULL); + gst_bin_add(GST_BIN(video_thread),GST_ELEMENT(smooth)); gst_bin_add(GST_BIN(video_thread),GST_ELEMENT(encode)); gst_bin_add(GST_BIN(video_thread),GST_ELEMENT(fdsink)); + gst_pad_connect(gst_element_get_pad(smooth,"src"), + gst_element_get_pad(encode,"sink")); gst_pad_connect(gst_element_get_pad(encode,"src"), gst_element_get_pad(fdsink,"sink")); // set up pad connections gst_element_add_ghost_pad(GST_ELEMENT(video_thread), - gst_element_get_pad(encode,"sink")); + gst_element_get_pad(smooth,"sink")); // construct queue and connect everything in the main pipeline video_queue = gst_elementfactory_make("queue","video_queue"); diff --git a/test/mp2tomp1.c b/test/mp2tomp1.c index 5557e628b9..7d7b3ef7ec 100644 --- a/test/mp2tomp1.c +++ b/test/mp2tomp1.c @@ -116,6 +116,7 @@ void mp2tomp1(GstElement *parser,GstPad *pad, GstElement *pipeline) { gst_plugin_load("mpeg2play"); gst_plugin_load("videoscale"); gst_plugin_load("mpeg2enc"); + //gst_plugin_load("mpeg1encoder"); // construct internal pipeline elements parse_video = gst_elementfactory_make("mp1videoparse","parse_video"); g_return_if_fail(parse_video != NULL); @@ -124,6 +125,7 @@ void mp2tomp1(GstElement *parser,GstPad *pad, GstElement *pipeline) { videoscale = gst_elementfactory_make("videoscale","videoscale"); g_return_if_fail(videoscale != NULL); encode = gst_elementfactory_make("mpeg2enc","encode"); + //encode = gst_elementfactory_make("mpeg1encoder","encode"); g_return_if_fail(encode != NULL); //gtk_object_set(GTK_OBJECT(show),"width",640, "height", 480,NULL); fd = open(outfile,O_CREAT|O_RDWR|O_TRUNC); diff --git a/test/vidcapture.c b/test/vidcapture.c index ecc6a28e8f..1886bbe45c 100644 --- a/test/vidcapture.c +++ b/test/vidcapture.c @@ -7,7 +7,7 @@ int main(int argc,char *argv[]) { int fd; GstPipeline *pipeline; - GstElement *audiosrc, *videosrc, *fdsink, *encoder, *compress; + GstElement *audiosrc, *videosrc, *fdsink, *encoder, *compress, *video_queue, *video_thread; GstElementFactory *audiosrcfactory, *fdsinkfactory, *encoderfactory, *compressfactory; GstElementFactory *videosrcfactory; GList *padlist; @@ -22,13 +22,14 @@ int main(int argc,char *argv[]) { audiosrcfactory = gst_elementfactory_find("audiosrc"); audiosrc = gst_elementfactory_create(audiosrcfactory,"audiosrc"); + videosrcfactory = gst_elementfactory_find("v4lsrc"); videosrc = gst_elementfactory_create(videosrcfactory,"videosrc"); compressfactory = gst_elementfactory_find("jpegenc"); compress = gst_elementfactory_create(compressfactory,"jpegenc"); encoderfactory = gst_elementfactory_find("aviencoder"); encoder = gst_elementfactory_create(encoderfactory,"aviencoder"); - gtk_object_set(GTK_OBJECT(videosrc),"width",256,"height",192,NULL); + gtk_object_set(GTK_OBJECT(videosrc),"width",384,"height",288,NULL); gtk_object_set(GTK_OBJECT(encoder),"video","00:MJPG",NULL); @@ -38,22 +39,37 @@ int main(int argc,char *argv[]) { fdsink = gst_elementfactory_create(fdsinkfactory,"fdsink"); gtk_object_set(GTK_OBJECT(fdsink),"fd",fd,NULL); - /* add objects to the main pipeline */ gst_bin_add(GST_BIN(pipeline),GST_ELEMENT(videosrc)); - gst_bin_add(GST_BIN(pipeline),GST_ELEMENT(encoder)); - gst_bin_add(GST_BIN(pipeline),GST_ELEMENT(fdsink)); + + /* add objects to the main pipeline */ + video_thread = gst_thread_new("video_thread"); + g_return_if_fail(video_thread != NULL); + gst_bin_add(GST_BIN(video_thread),GST_ELEMENT(compress)); + gst_bin_add(GST_BIN(video_thread),GST_ELEMENT(encoder)); + gst_bin_add(GST_BIN(video_thread),GST_ELEMENT(fdsink)); /* connect src to sink */ - gst_pad_connect(gst_element_get_pad(videosrc,"src"), - gst_element_get_pad(compress,"sink")); + gst_element_add_ghost_pad(GST_ELEMENT(video_thread), + gst_element_get_pad(compress,"sink")); gst_pad_connect(gst_element_get_pad(compress,"src"), gst_element_get_pad(encoder,"video_00")); gst_pad_connect(gst_element_get_pad(encoder,"src"), gst_element_get_pad(fdsink,"sink")); + + // construct queue and connect everything in the main pipeline + video_queue = gst_elementfactory_make("queue","video_queue"); + gtk_object_set(GTK_OBJECT(video_queue),"max_level",30,NULL); + gst_bin_add(GST_BIN(pipeline),GST_ELEMENT(video_queue)); + gst_bin_add(GST_BIN(pipeline),GST_ELEMENT(video_thread)); + gst_pad_connect(gst_element_get_pad(videosrc, "src"), + gst_element_get_pad(video_queue,"sink")); + gst_pad_connect(gst_element_get_pad(video_queue,"src"), + gst_element_get_pad(video_thread,"sink")); + + gtk_object_set(GTK_OBJECT(video_thread),"create_thread",TRUE,NULL); g_print("\neverything's built, setting it up to be runnable\n"); gst_element_set_state(GST_ELEMENT(pipeline),GST_STATE_RUNNING); - g_print("\nok, runnable, hitting 'play'...\n"); gst_element_set_state(GST_ELEMENT(pipeline),GST_STATE_PLAYING);