[gst-devel] MPEG->DIVX

Joshua N Pritikin vishnu at pobox.com
Sun Jun 1 21:06:05 CEST 2003


i tried to reproduce the pipeline below in C so i can chop out
any arbitrary range of the film:

  ./gst-launch { avimux name=mux ! filesink location=/tmp/test.avi } filesrc location=/local/aleader/trans.mpg ! mpegdemux name=demux demux.video_00 ! mpeg2dec ! divxenc ! queue name=vmux_q ! mux.video_00 demux.audio_00 ! queue name=audio_q ! mux.audio_00

This pipeline works OK with CVS HEAD.  However, the playback
shows too much distortion.  A/V is off and the video has some
broken frames (maybe 5%).  The source MPEG needs to be at least
30 seconds to really see the playback problems.

+ i added segment-start to avimux (patch attached).  This patch
allows avimux to continue after the seek and drop any buffers
that somehow didn't get flushed.  Part of my patch is really
needed for avimux anyway, otherwise some random event can cause
avimux to believe that no buffers remain and close the AVI file.

The other way to do it, to reconfigure the pipeline after the seek,
seems to confuse the scheduler.  What i tried is building the
pipeline up to mpegdemux, running the pipeline, doing the seek,
pause, building the remainder of the pipeline, and go back to running.
The scheduler always seemed to get confused.  i can try to debug
this but, to me, the scheduler is a big scary mess.

+ If i don't do the seek, then my C program works as well as the
gst-launch pipeline.

Any ideas how to improve this situation?

-- 
Victory to the Divine Mother!!         after all,
  http://sahajayoga.org                  http://why-compete.org
-------------- next part --------------
? d1
? gstavimux.c.old2
? gstavimux.c.old3
Index: gstavimux.c
===================================================================
RCS file: /cvsroot/gstreamer/gst-plugins/gst/avi/gstavimux.c,v
retrieving revision 1.38
diff -u -r1.38 gstavimux.c
--- gstavimux.c	1 Jun 2003 13:28:46 -0000	1.38
+++ gstavimux.c	2 Jun 2003 03:45:58 -0000
@@ -63,6 +63,7 @@
 enum {
   ARG_0,
   ARG_BIGFILE,
+  ARG_SEGMENT_START,
 };
 
 GST_PAD_TEMPLATE_FACTORY (src_factory,
@@ -237,6 +238,10 @@
     g_param_spec_boolean("bigfile","Bigfile Support","Whether to capture large or small AVI files",
     0,G_PARAM_READWRITE));
 
+  g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_SEGMENT_START,
+    g_param_spec_int64("segment-start","","Ignores all timestamps prior to this time",
+		       0,G_MAXINT64, 0, G_PARAM_READWRITE));
+
   gstelement_class->request_new_pad = gst_avimux_request_new_pad;
 
   gstelement_class->change_state = gst_avimux_change_state;
@@ -1038,6 +1043,7 @@
 		  	      GST_SEEK_METHOD_SET, avimux->total_data);
 
   avimux->write_header = TRUE;
+  g_warning ("avimux: stopped file, header written");
 }
 
 static void
@@ -1084,10 +1090,11 @@
 
 
 /* fill the internal queue for each available pad */
-static void
+static gboolean
 gst_avimux_fill_queue (GstAviMux *avimux)
 {
   GstBuffer *buffer;
+  gboolean skipped = FALSE;
 
   while (!avimux->audio_buffer_queue &&
           avimux->audiosinkpad &&
@@ -1098,7 +1105,15 @@
     buffer = gst_pad_pull(avimux->audiosinkpad);
     if (GST_IS_EVENT(buffer)) {
       gst_avimux_handle_event(avimux->audiosinkpad, GST_EVENT(buffer));
+      skipped = TRUE;
     } else {
+      if (buffer && GST_BUFFER_TIMESTAMP (buffer) < avimux->segment_start) {
+	gst_buffer_unref (buffer);
+	g_warning ("skip audio buffer %lld < %lld",
+		   GST_BUFFER_TIMESTAMP (buffer), avimux->segment_start);
+	skipped = TRUE;
+	continue;
+      }
       avimux->audio_buffer_queue = buffer;
       break;
     }
@@ -1113,11 +1128,34 @@
     buffer = gst_pad_pull(avimux->videosinkpad);
     if (GST_IS_EVENT(buffer)) {
       gst_avimux_handle_event(avimux->videosinkpad, GST_EVENT(buffer));
+      skipped = TRUE;
     } else {
+      if (buffer && GST_BUFFER_TIMESTAMP (buffer) < avimux->segment_start) {
+	gst_buffer_unref (buffer);
+	g_warning ("skip video buffer %lld < %lld",
+		   GST_BUFFER_TIMESTAMP (buffer), avimux->segment_start);
+	skipped = TRUE;
+	continue;
+      }
       avimux->video_buffer_queue = buffer;
       break;
     }
   }
+
+  if (avimux->audio_pad_connected && !avimux->audio_buffer_queue)
+    g_warning ("no audio buffer");
+  if (avimux->video_pad_connected && !avimux->video_buffer_queue)
+    g_warning ("no video buffer");
+
+  if (avimux->audio_pad_connected && avimux->audio_buffer_queue)
+    g_warning ("a %p %lld",
+	       avimux->audio_buffer_queue,
+	       GST_BUFFER_TIMESTAMP(avimux->audio_buffer_queue));
+  if (avimux->video_pad_connected && avimux->video_buffer_queue)
+    g_warning ("v %p %lld",
+	       avimux->video_buffer_queue,
+	       GST_BUFFER_TIMESTAMP(avimux->video_buffer_queue));
+  return skipped;
 }
 
 
@@ -1228,7 +1266,7 @@
 
 /* take the oldest buffer in our internal queue and push-it */
 static gboolean
-gst_avimux_do_one_buffer (GstAviMux *avimux)
+gst_avimux_do_one_buffer (GstAviMux *avimux, gboolean skipped)
 {
   if (avimux->video_buffer_queue &&
       avimux->audio_buffer_queue)
@@ -1247,7 +1285,9 @@
     else
       gst_avimux_do_audio_buffer(avimux);
   }
-  else {
+  else if (!skipped) {
+    g_warning ("no buffers, closing AVI");
+
     /* simply finish off the file and send EOS */
     gst_avimux_stop_file(avimux);
     gst_pad_push(avimux->srcpad,
@@ -1269,12 +1309,12 @@
 
   /* first fill queue (some elements only set caps when
    * flowing data), then write header */
-  gst_avimux_fill_queue(avimux);
+  gboolean skipped = gst_avimux_fill_queue(avimux);
   
   if (avimux->write_header)
     gst_avimux_start_file(avimux);
 
-  gst_avimux_do_one_buffer(avimux);
+  gst_avimux_do_one_buffer(avimux, skipped);
 }
 
 static void
@@ -1294,6 +1334,9 @@
     case ARG_BIGFILE:
       g_value_set_boolean(value, avimux->enable_large_avi);
       break;
+    case ARG_SEGMENT_START:
+      g_value_set_int64 (value, avimux->segment_start);
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -1316,6 +1359,9 @@
   {
     case ARG_BIGFILE:
       avimux->enable_large_avi = g_value_get_boolean(value);
+      break;
+    case ARG_SEGMENT_START:
+      avimux->segment_start = g_value_get_int64 (value);
       break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
Index: gstavimux.h
===================================================================
RCS file: /cvsroot/gstreamer/gst-plugins/gst/avi/gstavimux.h,v
retrieving revision 1.9
diff -u -r1.9 gstavimux.h
--- gstavimux.h	1 Jun 2003 12:23:46 -0000	1.9
+++ gstavimux.h	2 Jun 2003 03:45:58 -0000
@@ -84,6 +84,7 @@
   /* are we a big file already? */
   gboolean is_bigfile;
   guint64 avix_start;
+  gint64 segment_start;
 
   /* whether to use "large AVI files" or just stick to small indexed files */
   gboolean enable_large_avi;
-------------- next part --------------
A non-text attachment was scrubbed...
Name: extract.c
Type: text/x-csrc
Size: 7786 bytes
Desc: not available
URL: <http://lists.freedesktop.org/archives/gstreamer-devel/attachments/20030601/f7cface6/attachment.c>


More information about the gstreamer-devel mailing list