Added seeking to some of the plugins. some MMX speedups in the MPEG decoders.
authorWim Taymans <wim.taymans@gmail.com>
Wed, 5 Jul 2000 10:21:08 +0000 (10:21 +0000)
committerWim Taymans <wim.taymans@gmail.com>
Wed, 5 Jul 2000 10:21:08 +0000 (10:21 +0000)
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.

25 files changed:
gst/elements/gstaudiosink.c
gst/elements/gstaudiosink.h
gst/elements/gstdisksrc.c
gst/elements/gstdisksrc.h
gst/elements/gstfdsrc.c
gst/elements/gstqueue.c
gst/gstbuffer.h
gstplay/Makefile.am
gstplay/callbacks.c
gstplay/callbacks.h
gstplay/gstplay.c [moved from gstplay/main.c with 54% similarity]
gstplay/interface.c
gstplay/interface.h
gstplay/mpeg1.c
gstplay/mpeg2.c
libs/colorspace/yuv2rgb.c
libs/videoscale/gstvideoscale.c
plugins/elements/gstaudiosink.c
plugins/elements/gstaudiosink.h
plugins/elements/gstdisksrc.c
plugins/elements/gstdisksrc.h
plugins/elements/gstfdsrc.c
plugins/elements/gstqueue.c
test/mp2tomp1.c
test/mpeg2parse.c

index eafacde..b136419 100644 (file)
@@ -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));
-
-  audiosink->format = format;
-  
-  gst_audiosink_sync_parms(audiosink);
-}
+static void gst_audiosink_set_arg(GtkObject *object,GtkArg *arg,guint id) {
+  GstAudioSink *audiosink;
 
-void gst_audiosink_set_channels(GstAudioSink *audiosink,gint channels) {
-  g_return_if_fail(audiosink != NULL);
-  g_return_if_fail(GST_IS_AUDIOSINK(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);
 
-  audiosink->channels = channels;
-  
-  gst_audiosink_sync_parms(audiosink);
+  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_frequency(GstAudioSink *audiosink,gint frequency) {
-  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;
+
+  /* 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);
 
-  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) {
index f39d706..ecd4416 100644 (file)
@@ -62,6 +62,7 @@ struct _GstAudioSink {
   gint format;
   gint channels;
   gint frequency;
+  gboolean mute;
 };
 
 struct _GstAudioSinkClass {
index 68bb6fa..5e852f8 100644 (file)
@@ -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);
 }
index bdf2f9e..95c66b3 100644 (file)
@@ -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 {
index 6ca61e1..085f755 100644 (file)
@@ -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;
index 6d95c9f..f383eb2 100644 (file)
@@ -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;
index a550a25..1255301 100644 (file)
@@ -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;
 
 
index 4a3405d..f202536 100644 (file)
@@ -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 \
index e8e5490..ad4f302 100644 (file)
@@ -5,11 +5,16 @@
 #include <gnome.h>
 #include <gst/gst.h>
 
+#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,
@@ -75,10 +80,55 @@ 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);
 }
 
index dfb61f6..032fb24 100644 (file)
@@ -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);
similarity index 54%
rename from gstplay/main.c
rename to gstplay/gstplay.c
index 96ec3ae..a1b6fe0 100644 (file)
@@ -7,8 +7,7 @@
 #  include <config.h>
 #endif
 
-#include <gnome.h>
-#include <gst/gst.h>
+#include "gstplay.h"
 
 #include "interface.h"
 #include "support.h"
 
 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;
+}
+
+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 have_type(GstSink *sink) {
+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;
 }
 
index 26e8c40..e6b469e 100644 (file)
 #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);
+  
+}
index 26eee7d..3230f61 100644 (file)
@@ -3,3 +3,6 @@
  */
 
 GtkWidget* create_window1 (GtkWidget *video_element);
+void update_status_area();
+void update_slider(gfloat value);
+void update_buttons(int active);
index 8eb9944..f1d12ee 100644 (file)
@@ -1,5 +1,5 @@
 
-#define BUFFER 1
+#define BUFFER 15
 #define VIDEO_DECODER "mpeg_play"
 
 #ifdef HAVE_CONFIG_H
 
 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");
index f99456e..4b5eaec 100644 (file)
@@ -1,5 +1,5 @@
 
-#define BUFFER 1
+#define BUFFER 15
 #define VIDEO_DECODER "mpeg2play"
 
 #ifdef HAVE_CONFIG_H
 
 
 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");
index 98d9d5b..3253fc0 100644 (file)
@@ -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);
 
index 824a93d..b047bdb 100644 (file)
@@ -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);
 }
 
 
index eafacde..b136419 100644 (file)
@@ -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));
-
-  audiosink->format = format;
-  
-  gst_audiosink_sync_parms(audiosink);
-}
+static void gst_audiosink_set_arg(GtkObject *object,GtkArg *arg,guint id) {
+  GstAudioSink *audiosink;
 
-void gst_audiosink_set_channels(GstAudioSink *audiosink,gint channels) {
-  g_return_if_fail(audiosink != NULL);
-  g_return_if_fail(GST_IS_AUDIOSINK(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);
 
-  audiosink->channels = channels;
-  
-  gst_audiosink_sync_parms(audiosink);
+  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_frequency(GstAudioSink *audiosink,gint frequency) {
-  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;
+
+  /* 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);
 
-  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) {
index f39d706..ecd4416 100644 (file)
@@ -62,6 +62,7 @@ struct _GstAudioSink {
   gint format;
   gint channels;
   gint frequency;
+  gboolean mute;
 };
 
 struct _GstAudioSinkClass {
index 68bb6fa..5e852f8 100644 (file)
@@ -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);
 }
index bdf2f9e..95c66b3 100644 (file)
@@ -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 {
index 6ca61e1..085f755 100644 (file)
@@ -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;
index 6d95c9f..f383eb2 100644 (file)
@@ -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;
index 2fa9c89..072e304 100644 (file)
@@ -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);
 
index d5d7f2f..c189ed9 100644 (file)
@@ -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();
 }