From 9b0e11ec7e9bae339742acc8373f5e8655234486 Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Wed, 5 Jul 2000 10:21:08 +0000 Subject: [PATCH] Added seeking to some of the plugins. some MMX speedups in the MPEG decoders. Original commit message from CVS: Added seeking to some of the plugins. some MMX speedups in the MPEG decoders. Better YUV to MMX conversion implemented seeking to gstplay. --- gst/elements/gstaudiosink.c | 94 +++++++++++++++++------ gst/elements/gstaudiosink.h | 1 + gst/elements/gstdisksrc.c | 37 +++++++++- gst/elements/gstdisksrc.h | 2 + gst/elements/gstfdsrc.c | 3 +- gst/elements/gstqueue.c | 8 +- gst/gstbuffer.h | 1 + gstplay/Makefile.am | 2 +- gstplay/callbacks.c | 52 ++++++++++++- gstplay/callbacks.h | 15 ++++ gstplay/{main.c => gstplay.c} | 127 +++++++++++++++++++++++++++----- gstplay/interface.c | 103 ++++++++++++++++++++++++-- gstplay/interface.h | 3 + gstplay/mpeg1.c | 13 ++-- gstplay/mpeg2.c | 22 +++--- libs/colorspace/yuv2rgb.c | 8 +- libs/videoscale/gstvideoscale.c | 2 +- plugins/elements/gstaudiosink.c | 94 +++++++++++++++++------ plugins/elements/gstaudiosink.h | 1 + plugins/elements/gstdisksrc.c | 37 +++++++++- plugins/elements/gstdisksrc.h | 2 + plugins/elements/gstfdsrc.c | 3 +- plugins/elements/gstqueue.c | 8 +- test/mp2tomp1.c | 2 +- test/mpeg2parse.c | 12 ++- 25 files changed, 530 insertions(+), 122 deletions(-) rename gstplay/{main.c => gstplay.c} (54%) diff --git a/gst/elements/gstaudiosink.c b/gst/elements/gstaudiosink.c index eafacde107..b136419e4f 100644 --- a/gst/elements/gstaudiosink.c +++ b/gst/elements/gstaudiosink.c @@ -47,16 +47,23 @@ static gboolean gst_audiosink_stop(GstElement *element); static gboolean gst_audiosink_change_state(GstElement *element, GstElementState state); +static void gst_audiosink_set_arg(GtkObject *object,GtkArg *arg,guint id); +static void gst_audiosink_get_arg(GtkObject *object,GtkArg *arg,guint id); + void gst_audiosink_chain(GstPad *pad,GstBuffer *buf); /* AudioSink signals and args */ enum { - HANDOFF, + SIGNAL_HANDOFF, LAST_SIGNAL }; enum { ARG_0, + ARG_MUTE, + ARG_FORMAT, + ARG_CHANNELS, + ARG_FREQUENCY, /* FILL ME */ }; @@ -104,7 +111,19 @@ gst_audiosink_class_init(GstAudioSinkClass *klass) { parent_class = gtk_type_class(GST_TYPE_FILTER); - gst_audiosink_signals[HANDOFF] = + gtk_object_add_arg_type("GstAudioSink::mute", GTK_TYPE_BOOL, + GTK_ARG_READWRITE, ARG_MUTE); + gtk_object_add_arg_type("GstAudioSink::format", GTK_TYPE_INT, + GTK_ARG_READWRITE, ARG_FORMAT); + gtk_object_add_arg_type("GstAudioSink::channels", GTK_TYPE_INT, + GTK_ARG_READWRITE, ARG_CHANNELS); + gtk_object_add_arg_type("GstAudioSink::frequency", GTK_TYPE_INT, + GTK_ARG_READWRITE, ARG_FREQUENCY); + + gtkobject_class->set_arg = gst_audiosink_set_arg; + gtkobject_class->get_arg = gst_audiosink_get_arg; + + gst_audiosink_signals[SIGNAL_HANDOFF] = gtk_signal_new("handoff",GTK_RUN_LAST,gtkobject_class->type, GTK_SIGNAL_OFFSET(GstAudioSinkClass,handoff), gtk_marshal_NONE__POINTER,GTK_TYPE_NONE,1, @@ -192,7 +211,7 @@ void gst_audiosink_chain(GstPad *pad,GstBuffer *buf) { } } - gtk_signal_emit(GTK_OBJECT(audiosink),gst_audiosink_signals[HANDOFF], + gtk_signal_emit(GTK_OBJECT(audiosink),gst_audiosink_signals[SIGNAL_HANDOFF], audiosink); if (GST_BUFFER_DATA(buf) != NULL) { gst_trace_add_entry(NULL,0,buf,"audiosink: writing to soundcard"); @@ -204,7 +223,8 @@ void gst_audiosink_chain(GstPad *pad,GstBuffer *buf) { audiosink->clocktime = (info.bytes*1000000LL)/(audiosink->frequency*audiosink->channels); //g_print("audiosink: bytes sent %d time %llu\n", info.bytes, audiosink->clocktime); gst_clock_set(audiosink->clock, audiosink->clocktime); - write(audiosink->fd,GST_BUFFER_DATA(buf),GST_BUFFER_SIZE(buf)); + if (!audiosink->mute) + write(audiosink->fd,GST_BUFFER_DATA(buf),GST_BUFFER_SIZE(buf)); //audiosink->clocktime += (1000000LL*GST_BUFFER_SIZE(buf)/(audiosink->channels* // (audiosink->format/8)*(audiosink->frequency))); //g_print("audiosink: writing to soundcard ok\n"); @@ -216,31 +236,57 @@ void gst_audiosink_chain(GstPad *pad,GstBuffer *buf) { //g_print("a done\n"); } -void gst_audiosink_set_format(GstAudioSink *audiosink,gint format) { - g_return_if_fail(audiosink != NULL); - g_return_if_fail(GST_IS_AUDIOSINK(audiosink)); +static void gst_audiosink_set_arg(GtkObject *object,GtkArg *arg,guint id) { + GstAudioSink *audiosink; - audiosink->format = format; - - gst_audiosink_sync_parms(audiosink); + /* it's not null if we got it, but it might not be ours */ + g_return_if_fail(GST_IS_AUDIOSINK(object)); + audiosink = GST_AUDIOSINK(object); + + switch(id) { + case ARG_MUTE: + audiosink->mute = GTK_VALUE_BOOL(*arg); + break; + case ARG_FORMAT: + audiosink->format = GTK_VALUE_INT(*arg); + gst_audiosink_sync_parms(audiosink); + break; + case ARG_CHANNELS: + audiosink->channels = GTK_VALUE_INT(*arg); + gst_audiosink_sync_parms(audiosink); + break; + case ARG_FREQUENCY: + audiosink->frequency = GTK_VALUE_INT(*arg); + gst_audiosink_sync_parms(audiosink); + break; + default: + break; + } } -void gst_audiosink_set_channels(GstAudioSink *audiosink,gint channels) { - g_return_if_fail(audiosink != NULL); - g_return_if_fail(GST_IS_AUDIOSINK(audiosink)); +static void gst_audiosink_get_arg(GtkObject *object,GtkArg *arg,guint id) { + GstAudioSink *audiosink; - audiosink->channels = channels; - - gst_audiosink_sync_parms(audiosink); -} + /* it's not null if we got it, but it might not be ours */ + g_return_if_fail(GST_IS_AUDIOSINK(object)); + audiosink = GST_AUDIOSINK(object); -void gst_audiosink_set_frequency(GstAudioSink *audiosink,gint frequency) { - g_return_if_fail(audiosink != NULL); - g_return_if_fail(GST_IS_AUDIOSINK(audiosink)); - - audiosink->frequency = frequency; - - gst_audiosink_sync_parms(audiosink); + switch(id) { + case ARG_MUTE: + GTK_VALUE_BOOL(*arg) = audiosink->mute; + break; + case ARG_FORMAT: + GTK_VALUE_INT(*arg) = audiosink->format; + break; + case ARG_CHANNELS: + GTK_VALUE_INT(*arg) = audiosink->channels; + break; + case ARG_FREQUENCY: + GTK_VALUE_INT(*arg) = audiosink->frequency; + break; + default: + break; + } } static gboolean gst_audiosink_open_audio(GstAudioSink *sink) { diff --git a/gst/elements/gstaudiosink.h b/gst/elements/gstaudiosink.h index f39d706616..ecd441621c 100644 --- a/gst/elements/gstaudiosink.h +++ b/gst/elements/gstaudiosink.h @@ -62,6 +62,7 @@ struct _GstAudioSink { gint format; gint channels; gint frequency; + gboolean mute; }; struct _GstAudioSinkClass { diff --git a/gst/elements/gstdisksrc.c b/gst/elements/gstdisksrc.c index 68bb6fafa9..5e852f836f 100644 --- a/gst/elements/gstdisksrc.c +++ b/gst/elements/gstdisksrc.c @@ -46,6 +46,7 @@ enum { ARG_LOCATION, ARG_BYTESPERREAD, ARG_OFFSET, + ARG_SIZE, }; @@ -101,6 +102,8 @@ gst_disksrc_class_init(GstDiskSrcClass *klass) { GTK_ARG_READWRITE, ARG_BYTESPERREAD); gtk_object_add_arg_type("GstDiskSrc::offset", GTK_TYPE_INT, GTK_ARG_READWRITE, ARG_OFFSET); + gtk_object_add_arg_type("GstDiskSrc::size", GTK_TYPE_INT, + GTK_ARG_READABLE, ARG_SIZE); gtkobject_class->set_arg = gst_disksrc_set_arg; gtkobject_class->get_arg = gst_disksrc_get_arg; @@ -121,6 +124,8 @@ static void gst_disksrc_init(GstDiskSrc *disksrc) { disksrc->curoffset = 0; disksrc->bytes_per_read = 4096; disksrc->seq = 0; + disksrc->size = 0; + disksrc->new_seek = FALSE; } @@ -153,6 +158,7 @@ static void gst_disksrc_set_arg(GtkObject *object,GtkArg *arg,guint id) { case ARG_OFFSET: src->curoffset = GTK_VALUE_INT(*arg); lseek(src->fd,src->curoffset, SEEK_SET); + src->new_seek = TRUE; break; default: break; @@ -176,6 +182,9 @@ static void gst_disksrc_get_arg(GtkObject *object,GtkArg *arg,guint id) { case ARG_OFFSET: GTK_VALUE_INT(*arg) = src->curoffset; break; + case ARG_SIZE: + GTK_VALUE_INT(*arg) = src->size; + break; default: arg->type = GTK_TYPE_INVALID; break; @@ -203,19 +212,32 @@ void gst_disksrc_push(GstSrc *src) { /* read it in from the file */ readbytes = read(disksrc->fd,GST_BUFFER_DATA(buf),disksrc->bytes_per_read); - if (readbytes == 0) { + if (readbytes == -1) { + perror("read()"); + gst_buffer_unref(buf); + return; + } + else if (readbytes == 0) { gst_src_signal_eos(GST_SRC(disksrc)); - gst_buffer_unref(buf); + gst_buffer_unref(buf); return; } /* if we didn't get as many bytes as we asked for, we're at EOF */ if (readbytes < disksrc->bytes_per_read) - GST_BUFFER_FLAG_SET(buf,GST_BUFFER_EOS); + GST_BUFFER_FLAG_SET(buf, GST_BUFFER_EOS); + + /* if we have a new buffer froma seek, mark it */ + if (disksrc->new_seek) { + GST_BUFFER_FLAG_SET(buf, GST_BUFFER_FLUSH); + disksrc->new_seek = FALSE; + } + GST_BUFFER_OFFSET(buf) = disksrc->curoffset; GST_BUFFER_SIZE(buf) = readbytes; disksrc->curoffset += readbytes; + DEBUG("pushing with offset %lu\n", GST_BUFFER_OFFSET(buf)); /* we're done, push the buffer off now */ gst_pad_push(disksrc->srcpad,buf); } @@ -223,6 +245,7 @@ void gst_disksrc_push(GstSrc *src) { /* open the file, necessary to go to RUNNING state */ static gboolean gst_disksrc_open_file(GstDiskSrc *src) { + struct stat f_stat; g_return_val_if_fail(!GST_FLAG_IS_SET(src,GST_DISKSRC_OPEN), FALSE); /* open the file */ @@ -232,6 +255,13 @@ static gboolean gst_disksrc_open_file(GstDiskSrc *src) { gst_element_error(GST_ELEMENT(src),"opening file"); return FALSE; } + if (fstat(src->fd, &f_stat) < 0) { + perror("fstat()"); + } + else { + src->size = f_stat.st_size; + DEBUG("gstdisksrc: file size %ld\n", src->size); + } GST_FLAG_SET(src,GST_DISKSRC_OPEN); return TRUE; } @@ -247,6 +277,7 @@ static void gst_disksrc_close_file(GstDiskSrc *src) { src->fd = 0; src->curoffset = 0; src->seq = 0; + src->size = 0; GST_FLAG_UNSET(src,GST_DISKSRC_OPEN); } diff --git a/gst/elements/gstdisksrc.h b/gst/elements/gstdisksrc.h index bdf2f9e2c5..95c66b32ae 100644 --- a/gst/elements/gstdisksrc.h +++ b/gst/elements/gstdisksrc.h @@ -65,8 +65,10 @@ struct _GstDiskSrc { gulong curoffset; /* current offset in file */ gulong bytes_per_read; /* bytes per read */ + gboolean new_seek; gulong seq; /* buffer sequence number */ + gulong size; }; struct _GstDiskSrcClass { diff --git a/gst/elements/gstfdsrc.c b/gst/elements/gstfdsrc.c index 6ca61e128f..085f755bcb 100644 --- a/gst/elements/gstfdsrc.c +++ b/gst/elements/gstfdsrc.c @@ -198,7 +198,8 @@ void gst_fdsrc_push(GstSrc *src) { /* if we didn't get as many bytes as we asked for, we're at EOF */ if (readbytes < fdsrc->bytes_per_read) { - // FIXME: set the buffer's EOF bit here + // set the buffer's EOF bit here + GST_BUFFER_FLAG_SET(buf,GST_BUFFER_EOS); } GST_BUFFER_OFFSET(buf) = fdsrc->curoffset; GST_BUFFER_SIZE(buf) = readbytes; diff --git a/gst/elements/gstqueue.c b/gst/elements/gstqueue.c index 6d95c9f0d4..f383eb2c65 100644 --- a/gst/elements/gstqueue.c +++ b/gst/elements/gstqueue.c @@ -163,14 +163,14 @@ void gst_queue_chain(GstPad *pad,GstBuffer *buf) { if (queue->level_buffers >= queue->max_buffers) { DEBUG("queue: %s waiting %d\n", name, queue->level_buffers); - GST_UNLOCK(queue); while (queue->level_buffers >= queue->max_buffers) { + GST_UNLOCK(queue); g_mutex_lock(queue->fulllock); STATUS("O"); g_cond_wait(queue->fullcond,queue->fulllock); g_mutex_unlock(queue->fulllock); + GST_LOCK(queue); } - GST_LOCK(queue); DEBUG("queue: %s waiting done %d\n", name, queue->level_buffers); } @@ -218,14 +218,14 @@ void gst_queue_push(GstConnection *connection) { DEBUG("queue: %s push %d\n", name, queue->level_buffers); if (!queue->level_buffers) { - GST_UNLOCK(queue); while (!queue->level_buffers) { + GST_UNLOCK(queue); g_mutex_lock(queue->emptylock); STATUS("U"); g_cond_wait(queue->emptycond,queue->emptylock); g_mutex_unlock(queue->emptylock); + GST_LOCK(queue); } - GST_LOCK(queue); } front = queue->queue; diff --git a/gst/gstbuffer.h b/gst/gstbuffer.h index a550a25059..1255301f80 100644 --- a/gst/gstbuffer.h +++ b/gst/gstbuffer.h @@ -61,6 +61,7 @@ typedef enum { GST_BUFFER_EOS = (1 << 1), GST_BUFFER_ORIGINAL = (1 << 2), GST_BUFFER_DONTFREE = (1 << 3), + GST_BUFFER_FLUSH = (1 << 4), } GstBufferFlags; diff --git a/gstplay/Makefile.am b/gstplay/Makefile.am index 4a3405d579..f202536c80 100644 --- a/gstplay/Makefile.am +++ b/gstplay/Makefile.am @@ -7,7 +7,7 @@ INCLUDES = $(GLIB_CFLAGS) $(GTK_CFLAGS) -I$(top_srcdir) \ bin_PROGRAMS = gstplay gstplay_SOURCES = \ - main.c \ + gstplay.c \ mpeg1.c mpeg2.c avi.c\ support.c support.h \ interface.c interface.h \ diff --git a/gstplay/callbacks.c b/gstplay/callbacks.c index e8e5490594..ad4f30232d 100644 --- a/gstplay/callbacks.c +++ b/gstplay/callbacks.c @@ -5,11 +5,16 @@ #include #include +#include "gstplay.h" #include "callbacks.h" #include "interface.h" #include "support.h" extern GstElement *src; +extern gboolean picture_shown; +extern GstPlayState state; +extern guchar statusline[]; +extern guchar *statustext; void on_file1_activate (GtkMenuItem *menuitem, @@ -74,11 +79,56 @@ on_about1_activate (GtkMenuItem *menuitem, } +void +on_toggle_play_toggled (GtkToggleButton *togglebutton, + gpointer user_data) +{ + update_buttons(0); + change_state(GSTPLAY_PLAYING); + +} + +void +on_toggle_pause_toggled (GtkToggleButton *togglebutton, + gpointer user_data) +{ + update_buttons(1); + change_state(GSTPLAY_PAUSE); + +} + +void +on_toggle_stop_toggled (GtkToggleButton *togglebutton, + gpointer user_data) +{ + update_buttons(2); + change_state(GSTPLAY_STOPPED); +} + void on_hscale1_value_changed (GtkAdjustment *adj, gpointer user_data) { - gtk_object_set(GTK_OBJECT(src),"offset",10000000,NULL); + int size = gst_util_get_int_arg(GTK_OBJECT(src),"size"); + + gtk_object_set(GTK_OBJECT(src),"offset",(int)(adj->value*size/100.0),NULL); + if (state != GSTPLAY_PLAYING) { + show_next_picture(); + } +} + +void +on_drawingarea1_configure_event (GtkWidget *widget, GdkEventConfigure *event, + gpointer user_data) +{ + gdk_draw_rectangle(widget->window, + widget->style->black_gc, + TRUE, 0,0, + widget->allocation.width, + widget->allocation.height); + + gdk_draw_string(widget->window,widget->style->font,widget->style->white_gc, 8, 15, statustext); + gdk_draw_string(widget->window,widget->style->font,widget->style->white_gc, widget->allocation.width-100, 15, statusline); } diff --git a/gstplay/callbacks.h b/gstplay/callbacks.h index dfb61f6d05..032fb24f4f 100644 --- a/gstplay/callbacks.h +++ b/gstplay/callbacks.h @@ -36,3 +36,18 @@ void on_hscale1_value_changed (GtkAdjustment *adj, gpointer user_data); +void +on_drawingarea1_configure_event (GtkWidget *widget, GdkEventConfigure *event, + gpointer user_data); + +void +on_toggle_play_toggled (GtkToggleButton *togglebutton, + gpointer user_data); + +void +on_toggle_pause_toggled (GtkToggleButton *togglebutton, + gpointer user_data); + +void +on_toggle_stop_toggled (GtkToggleButton *togglebutton, + gpointer user_data); diff --git a/gstplay/main.c b/gstplay/gstplay.c similarity index 54% rename from gstplay/main.c rename to gstplay/gstplay.c index 96ec3ae606..a1b6fe0e84 100644 --- a/gstplay/main.c +++ b/gstplay/gstplay.c @@ -7,8 +7,7 @@ # include #endif -#include -#include +#include "gstplay.h" #include "interface.h" #include "support.h" @@ -17,19 +16,104 @@ extern gboolean _gst_plugin_spew; gboolean idle_func(gpointer data); -GstElement *show; +GstElement *show, *audio_play; GstElement *src; GstPipeline *pipeline; +GstElement *parse = NULL; +GstPlayState state; +gboolean picture_shown = FALSE; +guchar statusline[200]; +guchar *statustext = "stopped"; -void eof(GstSrc *src) { - g_print("have eos, quitting\n"); - exit(0); +static void frame_displayed(GstSrc *asrc) +{ + int size, time, frame_time = 0, src_pos; + guint mux_rate; + static int prev_time = -1; + + mux_rate = gst_util_get_int_arg(GTK_OBJECT(parse),"mux_rate"); + size = gst_util_get_int_arg(GTK_OBJECT(src),"size"); + time = (size*8)/mux_rate; + frame_time = gst_util_get_int_arg(GTK_OBJECT(show),"frame_time"); + src_pos = gst_util_get_int_arg(GTK_OBJECT(src),"offset"); + frame_time = (src_pos*8)/mux_rate; + + if (frame_time >= prev_time) { + + g_snprintf(statusline, 200, "%02d:%02d / %02d:%02d\n", + frame_time/60, frame_time%60, + time/60, time%60); + + //printf("%d %d %g\n", frame_time, size, frame_time*100.0/size); + + update_status_area(); + if (state == GSTPLAY_PLAYING) + update_slider(src_pos*100.0/size); + } + picture_shown = TRUE; + + prev_time = frame_time; } -void have_type(GstSink *sink) { +gboolean idle_func(gpointer data) { + gst_src_push(GST_SRC(data)); + return TRUE; +} + +static void eof(GstSrc *src) { + change_state(GSTPLAY_PAUSE); + picture_shown = TRUE; +} + +void show_next_picture() { + picture_shown = FALSE; + while (!picture_shown) { + gst_src_push(GST_SRC(src)); + gtk_main_iteration_do(FALSE); + } +} + +void mute_audio(gboolean mute) { + gtk_object_set(GTK_OBJECT(audio_play),"mute",mute,NULL); +} + +void change_state(GstPlayState new_state) { + + if (new_state == state) return; + switch (new_state) { + case GSTPLAY_PLAYING: + mute_audio(FALSE); + statustext = "playing"; + update_status_area(); + gtk_idle_add(idle_func,src); + state = GSTPLAY_PLAYING; + update_buttons(0); + break; + case GSTPLAY_PAUSE: + statustext = "paused"; + update_status_area(); + if (state != GSTPLAY_STOPPED) gtk_idle_remove_by_data(src); + mute_audio(TRUE); + state = GSTPLAY_PAUSE; + update_buttons(1); + break; + case GSTPLAY_STOPPED: + if (state != GSTPLAY_PAUSE) gtk_idle_remove_by_data(src); + statustext = "stopped"; + update_status_area(); + mute_audio(TRUE); + state = GSTPLAY_STOPPED; + gtk_object_set(GTK_OBJECT(src),"offset",0,NULL); + update_buttons(2); + update_slider(0.0); + show_next_picture(); + break; + } +} + +static void have_type(GstSink *sink) { gint type; GstType *gsttype; - GstElement *parse = NULL; type = gst_util_get_int_arg(GTK_OBJECT(sink),"type"); gsttype = gst_type_find_by_id(type); @@ -57,7 +141,7 @@ void have_type(GstSink *sink) { GTK_SIGNAL_FUNC(avi_new_pad_created),pipeline); } else if (strstr(gsttype->mime, "mpeg1")) { - mpeg1_setup_video_thread(gst_element_get_pad(src,"src"), show, pipeline); + mpeg1_setup_video_thread(gst_element_get_pad(src,"src"), show, GST_ELEMENT(pipeline)); } else { g_print("unknown media type\n"); @@ -82,21 +166,27 @@ main (int argc, char *argv[]) bindtextdomain (PACKAGE, PACKAGE_LOCALE_DIR); textdomain (PACKAGE); + gtk_init(&argc,&argv); gnome_init ("gstreamer", VERSION, argc, argv); gst_init(&argc,&argv); gst_plugin_load("mpeg1parse"); gst_plugin_load("mpeg2parse"); gst_plugin_load("mp1videoparse"); gst_plugin_load("mp3parse"); - gst_plugin_load("parsewav"); - gst_plugin_load("parseavi"); + //gst_plugin_load("parsewav"); + //gst_plugin_load("parseavi"); gst_plugin_load("videosink"); + g_snprintf(statusline, 200, "seeking"); + show = gst_elementfactory_make("videosink","show"); g_return_val_if_fail(show != NULL, -1); - window1 = create_window1 (gst_util_get_widget_arg(GTK_OBJECT(show),"widget")); gtk_widget_show (window1); + gtk_signal_connect(GTK_OBJECT(show),"frame_displayed", + GTK_SIGNAL_FUNC(frame_displayed),NULL); + + audio_play = gst_elementfactory_make("audiosink","play_audio"); pipeline = gst_pipeline_new("pipeline"); g_return_val_if_fail(pipeline != NULL, -1); @@ -106,6 +196,8 @@ main (int argc, char *argv[]) gtk_object_set(GTK_OBJECT(src),"location",argv[1],NULL); g_print("should be using file '%s'\n",argv[1]); + gtk_window_set_title (GTK_WINDOW (window1), g_strdup_printf("GStreamer Media player - %s", argv[1])); + typefind = gst_elementfactory_make("typefind","typefind"); g_return_val_if_fail(typefind != NULL, -1); @@ -126,16 +218,11 @@ main (int argc, char *argv[]) g_print("setting to RUNNING state\n"); gst_element_set_state(GST_ELEMENT(pipeline),GST_STATE_RUNNING); - /* - * The following code was added by Glade to create one of each component - * (except popup menus), just so that you see something after building - * the project. Delete any components that you don't want shown initially. - */ + state = GSTPLAY_STOPPED; - while (1) { - gst_src_push(GST_SRC(src)); - } + change_state(GSTPLAY_PLAYING); + gtk_main(); return 0; } diff --git a/gstplay/interface.c b/gstplay/interface.c index 26e8c40a8b..e6b469eb6b 100644 --- a/gstplay/interface.c +++ b/gstplay/interface.c @@ -17,6 +17,14 @@ #include "interface.h" #include "support.h" +GtkWidget *drawingarea1; +GtkObject *adjustment; +GtkWidget *button6; +GtkWidget *button7; +GtkWidget *button8; +extern guchar statusline[]; +extern guchar *statustext; + static GnomeUIInfo file1_menu_uiinfo[] = { { @@ -132,11 +140,7 @@ create_window1 (GtkWidget *video_element) GtkWidget *handlebox1; GtkWidget *toolbar1; GtkWidget *tmp_toolbar_icon; - GtkWidget *button6; - GtkWidget *button7; - GtkWidget *button8; GtkWidget *vseparator1; - GtkObject *adjustment; window1 = gtk_window_new (GTK_WINDOW_TOPLEVEL); gtk_object_set_data (GTK_OBJECT (window1), "window1", window1); @@ -235,7 +239,7 @@ create_window1 (GtkWidget *video_element) gtk_widget_show (vbox2); gtk_box_pack_start (GTK_BOX (vbox1), vbox2, FALSE, TRUE, 0); - adjustment = gtk_adjustment_new (0, 0, 100, 1, 10, 10); + adjustment = gtk_adjustment_new (0, 0.0, 110.0, 1, 10.0, 10.0); hscale1 = gtk_hscale_new (GTK_ADJUSTMENT (adjustment)); gtk_widget_ref (hscale1); gtk_object_set_data_full (GTK_OBJECT (window1), "hscale1", hscale1, @@ -270,7 +274,7 @@ create_window1 (GtkWidget *video_element) tmp_toolbar_icon = create_pixmap (window1, "pixmaps/play.xpm", TRUE); button6 = gtk_toolbar_append_element (GTK_TOOLBAR (toolbar1), - GTK_TOOLBAR_CHILD_BUTTON, + GTK_TOOLBAR_CHILD_TOGGLEBUTTON, NULL, _("button6"), NULL, NULL, @@ -280,9 +284,12 @@ create_window1 (GtkWidget *video_element) (GtkDestroyNotify) gtk_widget_unref); gtk_widget_show (button6); + gtk_signal_connect (GTK_OBJECT (button6), "toggled", + GTK_SIGNAL_FUNC (on_toggle_play_toggled), NULL); + tmp_toolbar_icon = create_pixmap (window1, "pixmaps/pause.xpm", TRUE); button7 = gtk_toolbar_append_element (GTK_TOOLBAR (toolbar1), - GTK_TOOLBAR_CHILD_BUTTON, + GTK_TOOLBAR_CHILD_TOGGLEBUTTON, NULL, _("button7"), NULL, NULL, @@ -292,9 +299,12 @@ create_window1 (GtkWidget *video_element) (GtkDestroyNotify) gtk_widget_unref); gtk_widget_show (button7); + gtk_signal_connect (GTK_OBJECT (button7), "toggled", + GTK_SIGNAL_FUNC (on_toggle_pause_toggled), NULL); + tmp_toolbar_icon = create_pixmap (window1, "pixmaps/stop.xpm", TRUE); button8 = gtk_toolbar_append_element (GTK_TOOLBAR (toolbar1), - GTK_TOOLBAR_CHILD_BUTTON, + GTK_TOOLBAR_CHILD_TOGGLEBUTTON, NULL, _("button8"), NULL, NULL, @@ -304,6 +314,9 @@ create_window1 (GtkWidget *video_element) (GtkDestroyNotify) gtk_widget_unref); gtk_widget_show (button8); + gtk_signal_connect (GTK_OBJECT (button8), "toggled", + GTK_SIGNAL_FUNC (on_toggle_stop_toggled), NULL); + vseparator1 = gtk_vseparator_new (); gtk_widget_ref (vseparator1); gtk_object_set_data_full (GTK_OBJECT (window1), "vseparator1", vseparator1, @@ -312,7 +325,81 @@ create_window1 (GtkWidget *video_element) gtk_toolbar_append_widget (GTK_TOOLBAR (toolbar1), vseparator1, NULL, NULL); gtk_widget_set_usize (vseparator1, 8, 21); + drawingarea1 = gtk_drawing_area_new (); + gtk_widget_ref (drawingarea1); + gtk_object_set_data_full (GTK_OBJECT (window1), "drawingarea1", drawingarea1, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (drawingarea1); + gtk_box_pack_start (GTK_BOX (vbox1), drawingarea1, FALSE, TRUE, 1); + gtk_widget_set_usize (drawingarea1, -2, 21); + + gtk_signal_connect (GTK_OBJECT (drawingarea1), "configure_event", + GTK_SIGNAL_FUNC (on_drawingarea1_configure_event), + NULL); return window1; } +void update_buttons(int active) +{ + gtk_signal_handler_block_by_func(GTK_OBJECT(button6), + GTK_SIGNAL_FUNC (on_toggle_play_toggled), + NULL); + gtk_signal_handler_block_by_func(GTK_OBJECT(button7), + GTK_SIGNAL_FUNC (on_toggle_pause_toggled), + NULL); + gtk_signal_handler_block_by_func(GTK_OBJECT(button8), + GTK_SIGNAL_FUNC (on_toggle_stop_toggled), + NULL); + + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button6), FALSE); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button7), FALSE); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button8), FALSE); + + if (active == 0) { + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button6), TRUE); + } + else if (active == 1) { + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button7), TRUE); + } + else if (active == 2) { + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button8), TRUE); + } + + gtk_signal_handler_unblock_by_func(GTK_OBJECT(button6), + GTK_SIGNAL_FUNC (on_toggle_play_toggled), + NULL); + gtk_signal_handler_unblock_by_func(GTK_OBJECT(button7), + GTK_SIGNAL_FUNC (on_toggle_pause_toggled), + NULL); + gtk_signal_handler_unblock_by_func(GTK_OBJECT(button8), + GTK_SIGNAL_FUNC (on_toggle_stop_toggled), + NULL); +} + +void update_slider(gfloat value) +{ + gtk_signal_handler_block_by_func(adjustment, + GTK_SIGNAL_FUNC (on_hscale1_value_changed), + NULL); + gtk_adjustment_set_value(GTK_ADJUSTMENT(adjustment), value); + gtk_signal_handler_unblock_by_func(adjustment, + GTK_SIGNAL_FUNC (on_hscale1_value_changed), + NULL); +} + +void update_status_area() +{ + GtkWidget *widget = drawingarea1; + + gdk_draw_rectangle(widget->window, + widget->style->black_gc, + TRUE, 0, + 0, + widget->allocation.width, + widget->allocation.height); + + gdk_draw_string(widget->window,widget->style->font,widget->style->white_gc, 8, 15, statustext); + gdk_draw_string(widget->window,widget->style->font,widget->style->white_gc, widget->allocation.width-100, 15, statusline); + +} diff --git a/gstplay/interface.h b/gstplay/interface.h index 26eee7d790..3230f61553 100644 --- a/gstplay/interface.h +++ b/gstplay/interface.h @@ -3,3 +3,6 @@ */ GtkWidget* create_window1 (GtkWidget *video_element); +void update_status_area(); +void update_slider(gfloat value); +void update_buttons(int active); diff --git a/gstplay/mpeg1.c b/gstplay/mpeg1.c index 8eb99449e8..f1d12eedfd 100644 --- a/gstplay/mpeg1.c +++ b/gstplay/mpeg1.c @@ -1,5 +1,5 @@ -#define BUFFER 1 +#define BUFFER 15 #define VIDEO_DECODER "mpeg_play" #ifdef HAVE_CONFIG_H @@ -14,10 +14,11 @@ extern gboolean _gst_plugin_spew; extern GstElement *show; +extern GstElement *audio_play; void mpeg1_new_pad_created(GstElement *parse,GstPad *pad,GstElement *pipeline) { - GstElement *parse_audio, *decode, *play; + GstElement *parse_audio, *decode; GstElement *audio_queue; GstElement *audio_thread; @@ -25,7 +26,7 @@ void mpeg1_new_pad_created(GstElement *parse,GstPad *pad,GstElement *pipeline) // connect to audio pad //if (0) { - if (strncmp(gst_pad_get_name(pad), "audio_", 6) == 0) { + if (strncmp(gst_pad_get_name(pad), "audio_", 6) == 0 && audio_play) { gst_plugin_load("mp3parse"); gst_plugin_load("mpg123"); // construct internal pipeline elements @@ -33,15 +34,13 @@ void mpeg1_new_pad_created(GstElement *parse,GstPad *pad,GstElement *pipeline) g_return_if_fail(parse_audio != NULL); decode = gst_elementfactory_make("mpg123","decode_audio"); g_return_if_fail(decode != NULL); - play = gst_elementfactory_make("audiosink","play_audio"); - g_return_if_fail(play != NULL); // create the thread and pack stuff into it audio_thread = gst_thread_new("audio_thread"); g_return_if_fail(audio_thread != NULL); gst_bin_add(GST_BIN(audio_thread),GST_ELEMENT(parse_audio)); gst_bin_add(GST_BIN(audio_thread),GST_ELEMENT(decode)); - gst_bin_add(GST_BIN(audio_thread),GST_ELEMENT(play)); + gst_bin_add(GST_BIN(audio_thread),GST_ELEMENT(audio_play)); // set up pad connections gst_element_add_ghost_pad(GST_ELEMENT(audio_thread), @@ -49,7 +48,7 @@ void mpeg1_new_pad_created(GstElement *parse,GstPad *pad,GstElement *pipeline) gst_pad_connect(gst_element_get_pad(parse_audio,"src"), gst_element_get_pad(decode,"sink")); gst_pad_connect(gst_element_get_pad(decode,"src"), - gst_element_get_pad(play,"sink")); + gst_element_get_pad(audio_play,"sink")); // construct queue and connect everything in the main pipelie audio_queue = gst_elementfactory_make("queue","audio_queue"); diff --git a/gstplay/mpeg2.c b/gstplay/mpeg2.c index f99456e722..4b5eaec38d 100644 --- a/gstplay/mpeg2.c +++ b/gstplay/mpeg2.c @@ -1,5 +1,5 @@ -#define BUFFER 1 +#define BUFFER 15 #define VIDEO_DECODER "mpeg2play" #ifdef HAVE_CONFIG_H @@ -13,11 +13,11 @@ extern gboolean _gst_plugin_spew; -extern GstElement *show; +extern GstElement *show, *audio_play; void mpeg2_new_pad_created(GstElement *parse,GstPad *pad,GstElement *pipeline) { - GstElement *parse_audio, *decode, *play; + GstElement *parse_audio, *decode; GstElement *audio_queue; GstElement *audio_thread; @@ -25,7 +25,7 @@ void mpeg2_new_pad_created(GstElement *parse,GstPad *pad,GstElement *pipeline) // connect to audio pad //if (0) { - if (strncmp(gst_pad_get_name(pad), "private_stream_1.0", 18) == 0) { + if (strncmp(gst_pad_get_name(pad), "private_stream_1.0", 18) == 0 && audio_play) { gst_plugin_load("ac3parse"); gst_plugin_load("ac3dec"); // construct internal pipeline elements @@ -33,15 +33,13 @@ void mpeg2_new_pad_created(GstElement *parse,GstPad *pad,GstElement *pipeline) g_return_if_fail(parse_audio != NULL); decode = gst_elementfactory_make("ac3dec","decode_audio"); g_return_if_fail(decode != NULL); - play = gst_elementfactory_make("audiosink","play_audio"); - g_return_if_fail(play != NULL); // create the thread and pack stuff into it audio_thread = gst_thread_new("audio_thread"); g_return_if_fail(audio_thread != NULL); gst_bin_add(GST_BIN(audio_thread),GST_ELEMENT(parse_audio)); gst_bin_add(GST_BIN(audio_thread),GST_ELEMENT(decode)); - gst_bin_add(GST_BIN(audio_thread),GST_ELEMENT(play)); + gst_bin_add(GST_BIN(audio_thread),GST_ELEMENT(audio_play)); // set up pad connections gst_element_add_ghost_pad(GST_ELEMENT(audio_thread), @@ -49,7 +47,7 @@ void mpeg2_new_pad_created(GstElement *parse,GstPad *pad,GstElement *pipeline) gst_pad_connect(gst_element_get_pad(parse_audio,"src"), gst_element_get_pad(decode,"sink")); gst_pad_connect(gst_element_get_pad(decode,"src"), - gst_element_get_pad(play,"sink")); + gst_element_get_pad(audio_play,"sink")); // construct queue and connect everything in the main pipelie audio_queue = gst_elementfactory_make("queue","audio_queue"); @@ -70,7 +68,7 @@ void mpeg2_new_pad_created(GstElement *parse,GstPad *pad,GstElement *pipeline) } // connect to audio pad //if (0) { - if (strncmp(gst_pad_get_name(pad), "audio_", 6) == 0) { + if (strncmp(gst_pad_get_name(pad), "audio_", 6) == 0 && audio_play) { gst_plugin_load("mp3parse"); gst_plugin_load("mpg123"); // construct internal pipeline elements @@ -78,15 +76,13 @@ void mpeg2_new_pad_created(GstElement *parse,GstPad *pad,GstElement *pipeline) g_return_if_fail(parse_audio != NULL); decode = gst_elementfactory_make("mpg123","decode_audio"); g_return_if_fail(decode != NULL); - play = gst_elementfactory_make("audiosink","play_audio"); - g_return_if_fail(play != NULL); // create the thread and pack stuff into it audio_thread = gst_thread_new("audio_thread"); g_return_if_fail(audio_thread != NULL); gst_bin_add(GST_BIN(audio_thread),GST_ELEMENT(parse_audio)); gst_bin_add(GST_BIN(audio_thread),GST_ELEMENT(decode)); - gst_bin_add(GST_BIN(audio_thread),GST_ELEMENT(play)); + gst_bin_add(GST_BIN(audio_thread),GST_ELEMENT(audio_play)); // set up pad connections gst_element_add_ghost_pad(GST_ELEMENT(audio_thread), @@ -94,7 +90,7 @@ void mpeg2_new_pad_created(GstElement *parse,GstPad *pad,GstElement *pipeline) gst_pad_connect(gst_element_get_pad(parse_audio,"src"), gst_element_get_pad(decode,"sink")); gst_pad_connect(gst_element_get_pad(decode,"src"), - gst_element_get_pad(play,"sink")); + gst_element_get_pad(audio_play,"sink")); // construct queue and connect everything in the main pipelie audio_queue = gst_elementfactory_make("queue","audio_queue"); diff --git a/libs/colorspace/yuv2rgb.c b/libs/colorspace/yuv2rgb.c index 98d9d5b02e..3253fc0a24 100644 --- a/libs/colorspace/yuv2rgb.c +++ b/libs/colorspace/yuv2rgb.c @@ -664,7 +664,7 @@ gst_colorspace_yuv_to_rgb32(tables, lum, cb, cr, out, rows, cols) } #ifdef HAVE_LIBMMX - +static mmx_t MMX_10w = (mmx_t)(long long)0x000D000D000D000DLL; //dd 00080 0080h, 000800080h static mmx_t MMX_80w = (mmx_t)(long long)0x0080008000800080LL; //dd 00080 0080h, 000800080h static mmx_t MMX_00FFw = (mmx_t)(long long)0x00ff00ff00ff00ffLL; //dd 000FF 00FFh, 000FF00FFh @@ -719,10 +719,10 @@ gst_colorspace_yuv_to_bgr16_mmx(tables, lum, cr, cb, out, rows, cols) pmullw_m2r(MMX16_Vgrncoeff, mm3); // Cr2green movq_m2r(*(mmx_t *)lum, mm7); // L2 pmullw_m2r(MMX16_Vredcoeff, mm1); // Cr2red - // "psubw MMX_10w, %%mm6\n" + psubw_m2r(MMX_10w, mm6); psrlw_i2r(8, mm7); // L2 00 L7 00 L5 00 L3 00 L1 pmullw_m2r(MMX16_Ycoeff, mm6); // lum1 - // "psubw MMX_10w, %%mm7\n" // L2 + psubw_m2r(MMX_10w, mm7); paddw_r2r(mm3, mm2); // Cb2green + Cr2green == green pmullw_m2r(MMX16_Ycoeff, mm7); // lum2 @@ -761,6 +761,7 @@ gst_colorspace_yuv_to_bgr16_mmx(tables, lum, cr, cb, out, rows, cols) packuswb_r2r(mm5, mm5); packuswb_r2r(mm7, mm7); pand_m2r(MMX_00FFw, mm6); // L3 + psubw_m2r(MMX_10w, mm6); punpcklbw_r2r(mm3, mm3); // "psubw MMX_10w, %%mm6\n" // L3 punpcklbw_r2r(mm5, mm5); @@ -778,6 +779,7 @@ gst_colorspace_yuv_to_bgr16_mmx(tables, lum, cr, cb, out, rows, cols) movq_r2r(mm4, mm5); // "psubw MMX_10w, %%mm7\n" // L4 punpcklwd_r2r(mm3, mm4); + psubw_m2r(MMX_10w, mm7); pmullw_m2r(MMX16_Ycoeff, mm7); // lum4 punpckhwd_r2r(mm3, mm5); diff --git a/libs/videoscale/gstvideoscale.c b/libs/videoscale/gstvideoscale.c index 824a93d1c5..b047bdb4be 100644 --- a/libs/videoscale/gstvideoscale.c +++ b/libs/videoscale/gstvideoscale.c @@ -270,7 +270,7 @@ static void generate_rowbytes(unsigned char *copy_row, int src_w, int dst_w, int pos += inc; } *eip++ = RETURN; - g_print("scaler start/end %p %p %p\n", copy_row, eip, eip-copy_row); + DEBUG("scaler start/end %p %p %p\n", copy_row, eip, eip-copy_row); } diff --git a/plugins/elements/gstaudiosink.c b/plugins/elements/gstaudiosink.c index eafacde107..b136419e4f 100644 --- a/plugins/elements/gstaudiosink.c +++ b/plugins/elements/gstaudiosink.c @@ -47,16 +47,23 @@ static gboolean gst_audiosink_stop(GstElement *element); static gboolean gst_audiosink_change_state(GstElement *element, GstElementState state); +static void gst_audiosink_set_arg(GtkObject *object,GtkArg *arg,guint id); +static void gst_audiosink_get_arg(GtkObject *object,GtkArg *arg,guint id); + void gst_audiosink_chain(GstPad *pad,GstBuffer *buf); /* AudioSink signals and args */ enum { - HANDOFF, + SIGNAL_HANDOFF, LAST_SIGNAL }; enum { ARG_0, + ARG_MUTE, + ARG_FORMAT, + ARG_CHANNELS, + ARG_FREQUENCY, /* FILL ME */ }; @@ -104,7 +111,19 @@ gst_audiosink_class_init(GstAudioSinkClass *klass) { parent_class = gtk_type_class(GST_TYPE_FILTER); - gst_audiosink_signals[HANDOFF] = + gtk_object_add_arg_type("GstAudioSink::mute", GTK_TYPE_BOOL, + GTK_ARG_READWRITE, ARG_MUTE); + gtk_object_add_arg_type("GstAudioSink::format", GTK_TYPE_INT, + GTK_ARG_READWRITE, ARG_FORMAT); + gtk_object_add_arg_type("GstAudioSink::channels", GTK_TYPE_INT, + GTK_ARG_READWRITE, ARG_CHANNELS); + gtk_object_add_arg_type("GstAudioSink::frequency", GTK_TYPE_INT, + GTK_ARG_READWRITE, ARG_FREQUENCY); + + gtkobject_class->set_arg = gst_audiosink_set_arg; + gtkobject_class->get_arg = gst_audiosink_get_arg; + + gst_audiosink_signals[SIGNAL_HANDOFF] = gtk_signal_new("handoff",GTK_RUN_LAST,gtkobject_class->type, GTK_SIGNAL_OFFSET(GstAudioSinkClass,handoff), gtk_marshal_NONE__POINTER,GTK_TYPE_NONE,1, @@ -192,7 +211,7 @@ void gst_audiosink_chain(GstPad *pad,GstBuffer *buf) { } } - gtk_signal_emit(GTK_OBJECT(audiosink),gst_audiosink_signals[HANDOFF], + gtk_signal_emit(GTK_OBJECT(audiosink),gst_audiosink_signals[SIGNAL_HANDOFF], audiosink); if (GST_BUFFER_DATA(buf) != NULL) { gst_trace_add_entry(NULL,0,buf,"audiosink: writing to soundcard"); @@ -204,7 +223,8 @@ void gst_audiosink_chain(GstPad *pad,GstBuffer *buf) { audiosink->clocktime = (info.bytes*1000000LL)/(audiosink->frequency*audiosink->channels); //g_print("audiosink: bytes sent %d time %llu\n", info.bytes, audiosink->clocktime); gst_clock_set(audiosink->clock, audiosink->clocktime); - write(audiosink->fd,GST_BUFFER_DATA(buf),GST_BUFFER_SIZE(buf)); + if (!audiosink->mute) + write(audiosink->fd,GST_BUFFER_DATA(buf),GST_BUFFER_SIZE(buf)); //audiosink->clocktime += (1000000LL*GST_BUFFER_SIZE(buf)/(audiosink->channels* // (audiosink->format/8)*(audiosink->frequency))); //g_print("audiosink: writing to soundcard ok\n"); @@ -216,31 +236,57 @@ void gst_audiosink_chain(GstPad *pad,GstBuffer *buf) { //g_print("a done\n"); } -void gst_audiosink_set_format(GstAudioSink *audiosink,gint format) { - g_return_if_fail(audiosink != NULL); - g_return_if_fail(GST_IS_AUDIOSINK(audiosink)); +static void gst_audiosink_set_arg(GtkObject *object,GtkArg *arg,guint id) { + GstAudioSink *audiosink; - audiosink->format = format; - - gst_audiosink_sync_parms(audiosink); + /* it's not null if we got it, but it might not be ours */ + g_return_if_fail(GST_IS_AUDIOSINK(object)); + audiosink = GST_AUDIOSINK(object); + + switch(id) { + case ARG_MUTE: + audiosink->mute = GTK_VALUE_BOOL(*arg); + break; + case ARG_FORMAT: + audiosink->format = GTK_VALUE_INT(*arg); + gst_audiosink_sync_parms(audiosink); + break; + case ARG_CHANNELS: + audiosink->channels = GTK_VALUE_INT(*arg); + gst_audiosink_sync_parms(audiosink); + break; + case ARG_FREQUENCY: + audiosink->frequency = GTK_VALUE_INT(*arg); + gst_audiosink_sync_parms(audiosink); + break; + default: + break; + } } -void gst_audiosink_set_channels(GstAudioSink *audiosink,gint channels) { - g_return_if_fail(audiosink != NULL); - g_return_if_fail(GST_IS_AUDIOSINK(audiosink)); +static void gst_audiosink_get_arg(GtkObject *object,GtkArg *arg,guint id) { + GstAudioSink *audiosink; - audiosink->channels = channels; - - gst_audiosink_sync_parms(audiosink); -} + /* it's not null if we got it, but it might not be ours */ + g_return_if_fail(GST_IS_AUDIOSINK(object)); + audiosink = GST_AUDIOSINK(object); -void gst_audiosink_set_frequency(GstAudioSink *audiosink,gint frequency) { - g_return_if_fail(audiosink != NULL); - g_return_if_fail(GST_IS_AUDIOSINK(audiosink)); - - audiosink->frequency = frequency; - - gst_audiosink_sync_parms(audiosink); + switch(id) { + case ARG_MUTE: + GTK_VALUE_BOOL(*arg) = audiosink->mute; + break; + case ARG_FORMAT: + GTK_VALUE_INT(*arg) = audiosink->format; + break; + case ARG_CHANNELS: + GTK_VALUE_INT(*arg) = audiosink->channels; + break; + case ARG_FREQUENCY: + GTK_VALUE_INT(*arg) = audiosink->frequency; + break; + default: + break; + } } static gboolean gst_audiosink_open_audio(GstAudioSink *sink) { diff --git a/plugins/elements/gstaudiosink.h b/plugins/elements/gstaudiosink.h index f39d706616..ecd441621c 100644 --- a/plugins/elements/gstaudiosink.h +++ b/plugins/elements/gstaudiosink.h @@ -62,6 +62,7 @@ struct _GstAudioSink { gint format; gint channels; gint frequency; + gboolean mute; }; struct _GstAudioSinkClass { diff --git a/plugins/elements/gstdisksrc.c b/plugins/elements/gstdisksrc.c index 68bb6fafa9..5e852f836f 100644 --- a/plugins/elements/gstdisksrc.c +++ b/plugins/elements/gstdisksrc.c @@ -46,6 +46,7 @@ enum { ARG_LOCATION, ARG_BYTESPERREAD, ARG_OFFSET, + ARG_SIZE, }; @@ -101,6 +102,8 @@ gst_disksrc_class_init(GstDiskSrcClass *klass) { GTK_ARG_READWRITE, ARG_BYTESPERREAD); gtk_object_add_arg_type("GstDiskSrc::offset", GTK_TYPE_INT, GTK_ARG_READWRITE, ARG_OFFSET); + gtk_object_add_arg_type("GstDiskSrc::size", GTK_TYPE_INT, + GTK_ARG_READABLE, ARG_SIZE); gtkobject_class->set_arg = gst_disksrc_set_arg; gtkobject_class->get_arg = gst_disksrc_get_arg; @@ -121,6 +124,8 @@ static void gst_disksrc_init(GstDiskSrc *disksrc) { disksrc->curoffset = 0; disksrc->bytes_per_read = 4096; disksrc->seq = 0; + disksrc->size = 0; + disksrc->new_seek = FALSE; } @@ -153,6 +158,7 @@ static void gst_disksrc_set_arg(GtkObject *object,GtkArg *arg,guint id) { case ARG_OFFSET: src->curoffset = GTK_VALUE_INT(*arg); lseek(src->fd,src->curoffset, SEEK_SET); + src->new_seek = TRUE; break; default: break; @@ -176,6 +182,9 @@ static void gst_disksrc_get_arg(GtkObject *object,GtkArg *arg,guint id) { case ARG_OFFSET: GTK_VALUE_INT(*arg) = src->curoffset; break; + case ARG_SIZE: + GTK_VALUE_INT(*arg) = src->size; + break; default: arg->type = GTK_TYPE_INVALID; break; @@ -203,19 +212,32 @@ void gst_disksrc_push(GstSrc *src) { /* read it in from the file */ readbytes = read(disksrc->fd,GST_BUFFER_DATA(buf),disksrc->bytes_per_read); - if (readbytes == 0) { + if (readbytes == -1) { + perror("read()"); + gst_buffer_unref(buf); + return; + } + else if (readbytes == 0) { gst_src_signal_eos(GST_SRC(disksrc)); - gst_buffer_unref(buf); + gst_buffer_unref(buf); return; } /* if we didn't get as many bytes as we asked for, we're at EOF */ if (readbytes < disksrc->bytes_per_read) - GST_BUFFER_FLAG_SET(buf,GST_BUFFER_EOS); + GST_BUFFER_FLAG_SET(buf, GST_BUFFER_EOS); + + /* if we have a new buffer froma seek, mark it */ + if (disksrc->new_seek) { + GST_BUFFER_FLAG_SET(buf, GST_BUFFER_FLUSH); + disksrc->new_seek = FALSE; + } + GST_BUFFER_OFFSET(buf) = disksrc->curoffset; GST_BUFFER_SIZE(buf) = readbytes; disksrc->curoffset += readbytes; + DEBUG("pushing with offset %lu\n", GST_BUFFER_OFFSET(buf)); /* we're done, push the buffer off now */ gst_pad_push(disksrc->srcpad,buf); } @@ -223,6 +245,7 @@ void gst_disksrc_push(GstSrc *src) { /* open the file, necessary to go to RUNNING state */ static gboolean gst_disksrc_open_file(GstDiskSrc *src) { + struct stat f_stat; g_return_val_if_fail(!GST_FLAG_IS_SET(src,GST_DISKSRC_OPEN), FALSE); /* open the file */ @@ -232,6 +255,13 @@ static gboolean gst_disksrc_open_file(GstDiskSrc *src) { gst_element_error(GST_ELEMENT(src),"opening file"); return FALSE; } + if (fstat(src->fd, &f_stat) < 0) { + perror("fstat()"); + } + else { + src->size = f_stat.st_size; + DEBUG("gstdisksrc: file size %ld\n", src->size); + } GST_FLAG_SET(src,GST_DISKSRC_OPEN); return TRUE; } @@ -247,6 +277,7 @@ static void gst_disksrc_close_file(GstDiskSrc *src) { src->fd = 0; src->curoffset = 0; src->seq = 0; + src->size = 0; GST_FLAG_UNSET(src,GST_DISKSRC_OPEN); } diff --git a/plugins/elements/gstdisksrc.h b/plugins/elements/gstdisksrc.h index bdf2f9e2c5..95c66b32ae 100644 --- a/plugins/elements/gstdisksrc.h +++ b/plugins/elements/gstdisksrc.h @@ -65,8 +65,10 @@ struct _GstDiskSrc { gulong curoffset; /* current offset in file */ gulong bytes_per_read; /* bytes per read */ + gboolean new_seek; gulong seq; /* buffer sequence number */ + gulong size; }; struct _GstDiskSrcClass { diff --git a/plugins/elements/gstfdsrc.c b/plugins/elements/gstfdsrc.c index 6ca61e128f..085f755bcb 100644 --- a/plugins/elements/gstfdsrc.c +++ b/plugins/elements/gstfdsrc.c @@ -198,7 +198,8 @@ void gst_fdsrc_push(GstSrc *src) { /* if we didn't get as many bytes as we asked for, we're at EOF */ if (readbytes < fdsrc->bytes_per_read) { - // FIXME: set the buffer's EOF bit here + // set the buffer's EOF bit here + GST_BUFFER_FLAG_SET(buf,GST_BUFFER_EOS); } GST_BUFFER_OFFSET(buf) = fdsrc->curoffset; GST_BUFFER_SIZE(buf) = readbytes; diff --git a/plugins/elements/gstqueue.c b/plugins/elements/gstqueue.c index 6d95c9f0d4..f383eb2c65 100644 --- a/plugins/elements/gstqueue.c +++ b/plugins/elements/gstqueue.c @@ -163,14 +163,14 @@ void gst_queue_chain(GstPad *pad,GstBuffer *buf) { if (queue->level_buffers >= queue->max_buffers) { DEBUG("queue: %s waiting %d\n", name, queue->level_buffers); - GST_UNLOCK(queue); while (queue->level_buffers >= queue->max_buffers) { + GST_UNLOCK(queue); g_mutex_lock(queue->fulllock); STATUS("O"); g_cond_wait(queue->fullcond,queue->fulllock); g_mutex_unlock(queue->fulllock); + GST_LOCK(queue); } - GST_LOCK(queue); DEBUG("queue: %s waiting done %d\n", name, queue->level_buffers); } @@ -218,14 +218,14 @@ void gst_queue_push(GstConnection *connection) { DEBUG("queue: %s push %d\n", name, queue->level_buffers); if (!queue->level_buffers) { - GST_UNLOCK(queue); while (!queue->level_buffers) { + GST_UNLOCK(queue); g_mutex_lock(queue->emptylock); STATUS("U"); g_cond_wait(queue->emptycond,queue->emptylock); g_mutex_unlock(queue->emptylock); + GST_LOCK(queue); } - GST_LOCK(queue); } front = queue->queue; diff --git a/test/mp2tomp1.c b/test/mp2tomp1.c index 2fa9c89a44..072e304b2c 100644 --- a/test/mp2tomp1.c +++ b/test/mp2tomp1.c @@ -151,7 +151,7 @@ void mp2tomp1(GstElement *parser,GstPad *pad, GstElement *pipeline) { gtk_object_set(GTK_OBJECT(smooth),"tolerance",9,NULL); encode = gst_elementfactory_make("mpeg2enc","encode"); g_return_if_fail(encode != NULL); - gtk_object_set(GTK_OBJECT(encode),"frames_per_second",29.97,NULL); + gtk_object_set(GTK_OBJECT(encode),"frames_per_second",24.0,NULL); //encode = gst_elementfactory_make("mpeg1encoder","encode"); //gtk_object_set(GTK_OBJECT(show),"width",640, "height", 480,NULL); diff --git a/test/mpeg2parse.c b/test/mpeg2parse.c index d5d7f2f03e..c189ed9d93 100644 --- a/test/mpeg2parse.c +++ b/test/mpeg2parse.c @@ -7,6 +7,11 @@ void eof(GstSrc *src) { exit(0); } +gboolean idle_func(gpointer data) { + gst_src_push(GST_SRC(data)); + return TRUE; +} + void mpeg2parse_newpad(GstElement *parser,GstPad *pad, GstElement *pipeline) { GstElement *parse_audio, *parse_video, *decode, *decode_video, *play, *show; GstElement *audio_queue, *video_queue; @@ -165,6 +170,7 @@ int main(int argc,char *argv[]) { g_print("have %d args\n",argc); + gtk_init(&argc,&argv); gst_init(&argc,&argv); gnome_init("MPEG2 Video player","0.0.1",argc,argv); gst_plugin_load("mpeg2parse"); @@ -204,7 +210,7 @@ int main(int argc,char *argv[]) { g_print("setting to RUNNING state\n"); gst_element_set_state(GST_ELEMENT(pipeline),GST_STATE_RUNNING); - while (1) { - gst_src_push(GST_SRC(src)); - } + gtk_idle_add(idle_func,src); + + gtk_main(); }