ext/a52dec/gsta52dec.c: Add some debug output. Check that a discont has a valid time...
authorJan Schmidt <thaytan@mad.scientist.com>
Tue, 25 Jan 2005 15:34:08 +0000 (15:34 +0000)
committerJan Schmidt <thaytan@mad.scientist.com>
Tue, 25 Jan 2005 15:34:08 +0000 (15:34 +0000)
Original commit message from CVS:
* ext/a52dec/gsta52dec.c: (gst_a52dec_push),
(gst_a52dec_handle_event), (gst_a52dec_chain):
Add some debug output. Check that a discont has a valid
time associated.
* ext/alsa/gstalsasink.c: (gst_alsa_sink_check_event),
(gst_alsa_sink_loop):
Ignore TAG events. A little extra debug for broken timestamps.
* ext/dvdnav/dvdnavsrc.c: (dvdnavsrc_init), (dvdnavsrc_loop),
(dvdnavsrc_change_state):
Ensure we send a discont to engage the link before we send any
other events.
* ext/dvdread/dvdreadsrc.c: (dvdreadsrc_init),
(dvdreadsrc_finalize), (_close), (_open), (_seek_title),
(_seek_chapter), (seek_sector), (dvdreadsrc_get),
(dvdreadsrc_uri_get_uri), (dvdreadsrc_uri_set_uri):
Handle URI of the form dvd://title[,chapter[,angle]]. Currently only
dvd://title works in totem because typefinding sends a seek that ends
up going back to chapter 1 regardless.
* ext/mpeg2dec/gstmpeg2dec.c:
* ext/mpeg2dec/gstmpeg2dec.h:
Output correct timestamps and handle disconts.
* ext/ogg/gstoggdemux.c: (get_relative):
Small guard against a null dereference.
* ext/pango/gsttextoverlay.c: (gst_textoverlay_finalize),
(gst_textoverlay_set_property):
Free memory when done. Don't call gst_event_filler_get_duration on
EOS events. Use GST_LOG and GST_WARNING instead of g_message and
g_warning.
* ext/smoothwave/gstsmoothwave.c: (gst_smoothwave_init),
(draw_line), (gst_smoothwave_dispose), (gst_sw_sinklink),
(gst_sw_srclink), (gst_smoothwave_chain):
Draw solid lines, prettier colours.
* gst/mpeg2sub/gstmpeg2subt.c: (gst_mpeg2subt_init):
Add a default palette that'll work for some movies.
* gst/mpegstream/gstdvddemux.c: (gst_dvd_demux_init),
(gst_dvd_demux_handle_dvd_event), (gst_dvd_demux_send_discont),
(gst_dvd_demux_send_subbuffer), (gst_dvd_demux_reset):
* gst/mpegstream/gstdvddemux.h:
* gst/mpegstream/gstmpegdemux.c: (gst_mpeg_demux_send_discont),
(gst_mpeg_demux_parse_syshead), (gst_mpeg_demux_parse_pes):
* gst/mpegstream/gstmpegparse.c: (gst_mpeg_parse_init),
(gst_mpeg_parse_handle_discont), (gst_mpeg_parse_parse_packhead):
* gst/mpegstream/gstmpegparse.h:
Use PTM/NAV events when for timestamp adjustment when connected to
dvdnavsrc. Don't use many discont events where one suffices.
* gst/playback/gstplaybasebin.c: (group_destroy),
(gen_preroll_element), (gst_play_base_bin_add_element):
* gst/playback/gstplaybasebin.h:
Make sure we remove subtitles from the same bin we put them in.
* gst/subparse/gstsubparse.c: (convert_encoding), (parse_subrip),
(gst_subparse_buffer_format_autodetect),
(gst_subparse_change_state):
Fix some memleaks and invalid accesses.
* gst/typefind/gsttypefindfunctions.c: (ogganx_type_find),
(oggskel_type_find), (cmml_type_find), (plugin_init):
Some typefind functions for Annodex v3.0 files
* gst/wavparse/gstwavparse.h:
GstRiffReadClass is the correct parent class.

ChangeLog
ext/a52dec/gsta52dec.c
ext/dvdnav/dvdnavsrc.c
ext/dvdread/dvdreadsrc.c
ext/mpeg2dec/gstmpeg2dec.c
ext/mpeg2dec/gstmpeg2dec.h
gst/mpegstream/gstdvddemux.c
gst/mpegstream/gstdvddemux.h
gst/mpegstream/gstmpegdemux.c
gst/mpegstream/gstmpegparse.c
gst/mpegstream/gstmpegparse.h

index b6e0567..d525a72 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,63 @@
+2005-01-26  Jan Schmidt  <thaytan@mad.scientist.com>
+       * ext/a52dec/gsta52dec.c: (gst_a52dec_push),
+       (gst_a52dec_handle_event), (gst_a52dec_chain):
+       Add some debug output. Check that a discont has a valid
+       time associated.
+       * ext/alsa/gstalsasink.c: (gst_alsa_sink_check_event),
+       (gst_alsa_sink_loop):
+       Ignore TAG events. A little extra debug for broken timestamps.
+       * ext/dvdnav/dvdnavsrc.c: (dvdnavsrc_init), (dvdnavsrc_loop),
+       (dvdnavsrc_change_state):
+       Ensure we send a discont to engage the link before we send any
+       other events.
+       * ext/dvdread/dvdreadsrc.c: (dvdreadsrc_init),
+       (dvdreadsrc_finalize), (_close), (_open), (_seek_title),
+       (_seek_chapter), (seek_sector), (dvdreadsrc_get),
+       (dvdreadsrc_uri_get_uri), (dvdreadsrc_uri_set_uri):
+       Handle URI of the form dvd://title[,chapter[,angle]]. Currently only
+       dvd://title works in totem because typefinding sends a seek that ends
+       up going back to chapter 1 regardless.
+       * ext/mpeg2dec/gstmpeg2dec.c:
+       * ext/mpeg2dec/gstmpeg2dec.h:
+       Output correct timestamps and handle disconts.
+       * ext/ogg/gstoggdemux.c: (get_relative):
+       Small guard against a null dereference.
+       * ext/pango/gsttextoverlay.c: (gst_textoverlay_finalize),
+       (gst_textoverlay_set_property):
+       Free memory when done. Don't call gst_event_filler_get_duration on
+       EOS events. Use GST_LOG and GST_WARNING instead of g_message and
+       g_warning.
+       * ext/smoothwave/gstsmoothwave.c: (gst_smoothwave_init),
+       (draw_line), (gst_smoothwave_dispose), (gst_sw_sinklink),
+       (gst_sw_srclink), (gst_smoothwave_chain):
+       Draw solid lines, prettier colours.
+       * gst/mpeg2sub/gstmpeg2subt.c: (gst_mpeg2subt_init):
+       Add a default palette that'll work for some movies.
+       * gst/mpegstream/gstdvddemux.c: (gst_dvd_demux_init),
+       (gst_dvd_demux_handle_dvd_event), (gst_dvd_demux_send_discont),
+       (gst_dvd_demux_send_subbuffer), (gst_dvd_demux_reset):
+       * gst/mpegstream/gstdvddemux.h:
+       * gst/mpegstream/gstmpegdemux.c: (gst_mpeg_demux_send_discont),
+       (gst_mpeg_demux_parse_syshead), (gst_mpeg_demux_parse_pes):
+       * gst/mpegstream/gstmpegparse.c: (gst_mpeg_parse_init),
+       (gst_mpeg_parse_handle_discont), (gst_mpeg_parse_parse_packhead):
+       * gst/mpegstream/gstmpegparse.h:
+       Use PTM/NAV events when for timestamp adjustment when connected to 
+       dvdnavsrc. Don't use many discont events where one suffices.
+       * gst/playback/gstplaybasebin.c: (group_destroy),
+       (gen_preroll_element), (gst_play_base_bin_add_element):
+       * gst/playback/gstplaybasebin.h:
+       Make sure we remove subtitles from the same bin we put them in.
+       * gst/subparse/gstsubparse.c: (convert_encoding), (parse_subrip),
+       (gst_subparse_buffer_format_autodetect),
+       (gst_subparse_change_state):
+       Fix some memleaks and invalid accesses.
+       * gst/typefind/gsttypefindfunctions.c: (ogganx_type_find),
+       (oggskel_type_find), (cmml_type_find), (plugin_init):
+       Some typefind functions for Annodex v3.0 files
+       * gst/wavparse/gstwavparse.h:
+       GstRiffReadClass is the correct parent class.
+
 2005-01-25  Ronald S. Bultje  <rbultje@ronald.bitfreak.net>
 
        * gst-libs/gst/riff/riff-media.c:
index 4e25e9d..1c2ba80 100644 (file)
@@ -283,6 +283,11 @@ gst_a52dec_push (GstA52Dec * a52dec,
   GST_BUFFER_TIMESTAMP (buf) = timestamp;
   GST_BUFFER_DURATION (buf) = 256 * GST_SECOND / a52dec->sample_rate;
 
+  GST_DEBUG_OBJECT (a52dec,
+      "Pushing buffer with ts %" GST_TIME_FORMAT " duration %" GST_TIME_FORMAT,
+      GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)),
+      GST_TIME_ARGS (GST_BUFFER_DURATION (buf)));
+
   gst_pad_push (srcpad, GST_DATA (buf));
 
   return 0;
@@ -324,7 +329,8 @@ gst_a52dec_handle_event (GstA52Dec * a52dec, GstEvent * event)
     case GST_EVENT_DISCONTINUOUS:{
       gint64 val;
 
-      if (!gst_event_discont_get_value (event, GST_FORMAT_TIME, &val)) {
+      if (!gst_event_discont_get_value (event, GST_FORMAT_TIME, &val)
+          || !GST_CLOCK_TIME_IS_VALID (val)) {
         GST_WARNING ("No time discont value in event %p", event);
       } else {
         a52dec->time = val;
@@ -442,7 +448,12 @@ gst_a52dec_chain (GstPad * pad, GstData * _data)
   buf = GST_BUFFER (_data);
   if (GST_BUFFER_TIMESTAMP_IS_VALID (buf)) {
     a52dec->time = GST_BUFFER_TIMESTAMP (buf);
+    GST_DEBUG_OBJECT (a52dec,
+        "Received buffer with ts %" GST_TIME_FORMAT " duration %"
+        GST_TIME_FORMAT, GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)),
+        GST_TIME_ARGS (GST_BUFFER_DURATION (buf)));
   }
+
   if (a52dec->cache) {
     buf = gst_buffer_join (a52dec->cache, buf);
     a52dec->cache = NULL;
index 4fc0338..38fedcc 100644 (file)
@@ -124,7 +124,7 @@ struct _DVDNavSrc
 
   gboolean did_seek;
   gboolean need_flush;
-  gboolean need_discont;
+  gboolean need_newmedia;
 
   /* Timing */
   GstClock *clock;              /* The clock for this element. */
@@ -395,6 +395,7 @@ dvdnavsrc_init (DVDNavSrc * src)
 
   src->did_seek = FALSE;
   src->need_flush = FALSE;
+  src->need_newmedia = TRUE;
 
   /* Pause mode is initially inactive. */
   src->pause_mode = DVDNAVSRC_PAUSE_OFF;
@@ -1278,13 +1279,16 @@ dvdnavsrc_loop (GstElement * element)
 
   g_return_if_fail (dvdnavsrc_is_open (src));
 
-  if (src->did_seek) {
+  if (src->did_seek || src->need_newmedia) {
     GstEvent *event;
 
     src->did_seek = FALSE;
     GST_INFO_OBJECT (src, "sending discont");
-    event = gst_event_new_discontinuous (FALSE, 0);
+
+    event = gst_event_new_discontinuous (src->need_newmedia, 0);
+
     src->need_flush = FALSE;
+    src->need_newmedia = FALSE;
     gst_pad_push (src->srcpad, GST_DATA (event));
     return;
   }
@@ -1595,6 +1599,7 @@ dvdnavsrc_change_state (GstElement * element)
         }
       }
       src->streaminfo = NULL;
+      src->need_newmedia = TRUE;
       break;
     case GST_STATE_PAUSED_TO_PLAYING:
       break;
index 060e82f..73c8cd5 100644 (file)
@@ -53,6 +53,7 @@ struct _DVDReadSrcPrivate
 
   /* location */
   gchar *location;
+  gchar *last_uri;
 
   gboolean new_seek;
 
@@ -235,7 +236,13 @@ dvdreadsrc_init (DVDReadSrc * dvdreadsrc)
       dvdreadsrc_get_formats);
   gst_element_add_pad (GST_ELEMENT (dvdreadsrc), dvdreadsrc->priv->srcpad);
 
+  dvdreadsrc->priv->dvd = NULL;
+  dvdreadsrc->priv->vts_file = NULL;
+  dvdreadsrc->priv->vmg_file = NULL;
+  dvdreadsrc->priv->dvd_title = NULL;
+
   dvdreadsrc->priv->location = g_strdup ("/dev/dvd");
+  dvdreadsrc->priv->last_uri = NULL;
   dvdreadsrc->priv->new_seek = TRUE;
   dvdreadsrc->priv->new_cell = TRUE;
   dvdreadsrc->priv->title = 0;
@@ -254,6 +261,7 @@ dvdreadsrc_finalize (GObject * object)
 
   if (dvdreadsrc->priv) {
     g_free (dvdreadsrc->priv->location);
+    g_free (dvdreadsrc->priv->last_uri);
     g_free (dvdreadsrc->priv);
     dvdreadsrc->priv = NULL;
   }
@@ -550,6 +558,24 @@ is_nav_pack (unsigned char *buffer)
 }
 
 static int
+_close (DVDReadSrcPrivate * priv)
+{
+  ifoClose (priv->vts_file);
+  priv->vts_file = NULL;
+
+  ifoClose (priv->vmg_file);
+  priv->vmg_file = NULL;
+
+  DVDCloseFile (priv->dvd_title);
+  priv->dvd_title = NULL;
+
+  DVDClose (priv->dvd);
+  priv->dvd = NULL;
+
+  return 0;
+}
+
+static int
 _open (DVDReadSrcPrivate * priv, const gchar * location)
 {
   g_return_val_if_fail (priv != NULL, -1);
@@ -572,7 +598,6 @@ _open (DVDReadSrcPrivate * priv, const gchar * location)
   priv->vmg_file = ifoOpen (priv->dvd, 0);
   if (!priv->vmg_file) {
     GST_ERROR ("Can't open VMG info");
-    DVDClose (priv->dvd);
     return -1;
   }
   priv->tt_srpt = priv->vmg_file->tt_srpt;
@@ -581,16 +606,6 @@ _open (DVDReadSrcPrivate * priv, const gchar * location)
 }
 
 static int
-_close (DVDReadSrcPrivate * priv)
-{
-  ifoClose (priv->vts_file);
-  ifoClose (priv->vmg_file);
-  DVDCloseFile (priv->dvd_title);
-  DVDClose (priv->dvd);
-  return 0;
-}
-
-static int
 _seek_title (DVDReadSrcPrivate * priv, int title, int angle)
 {
   GHashTable *languagelist = NULL;
@@ -600,11 +615,13 @@ _seek_title (DVDReadSrcPrivate * priv, int title, int angle)
      */
   GST_LOG ("There are %d titles on this DVD", priv->tt_srpt->nr_of_srpts);
   if (title < 0 || title >= priv->tt_srpt->nr_of_srpts) {
-    GST_ERROR ("Invalid title %d (only %d available)",
+    GST_WARNING ("Invalid title %d (only %d available)",
         title, priv->tt_srpt->nr_of_srpts);
-    ifoClose (priv->vmg_file);
-    DVDClose (priv->dvd);
-    return -1;
+
+    if (title < 0)
+      title = 0;
+    else
+      title = priv->tt_srpt->nr_of_srpts - 1;
   }
 
   GST_LOG ("There are %d chapters in this title",
@@ -617,14 +634,14 @@ _seek_title (DVDReadSrcPrivate * priv, int title, int angle)
       priv->tt_srpt->title[title].nr_of_angles);
 
   if (angle < 0 || angle >= priv->tt_srpt->title[title].nr_of_angles) {
-    GST_ERROR ("Invalid angle %d (only %d available)",
+    GST_WARNING ("Invalid angle %d (only %d available)",
         angle, priv->tt_srpt->title[title].nr_of_angles);
-    ifoClose (priv->vmg_file);
-    DVDClose (priv->dvd);
-    return -1;
+    if (angle < 0)
+      angle = 0;
+    else
+      angle = priv->tt_srpt->title[title].nr_of_angles - 1;
   }
 
-
     /**
      * Load the VTS information for the title set our title is in.
      */
@@ -633,8 +650,7 @@ _seek_title (DVDReadSrcPrivate * priv, int title, int angle)
   if (!priv->vts_file) {
     GST_ERROR ("Can't open the info file of title %d",
         priv->tt_srpt->title[title].title_set_nr);
-    ifoClose (priv->vmg_file);
-    DVDClose (priv->dvd);
+    _close (priv);
     return -1;
   }
 
@@ -650,9 +666,7 @@ _seek_title (DVDReadSrcPrivate * priv, int title, int angle)
   if (!priv->dvd_title) {
     GST_ERROR ("Can't open title VOBS (VTS_%02d_1.VOB)",
         priv->tt_srpt->title[title].title_set_nr);
-    ifoClose (priv->vts_file);
-    ifoClose (priv->vmg_file);
-    DVDClose (priv->dvd);
+    _close (priv);
     return -1;
   }
 
@@ -665,6 +679,8 @@ _seek_title (DVDReadSrcPrivate * priv, int title, int angle)
   g_hash_table_destroy (languagelist);
 
   GST_LOG ("Opened title %d, angle %d", title, angle);
+  priv->title = title;
+  priv->angle = angle;
 
   return 0;
 }
@@ -678,11 +694,11 @@ _seek_chapter (DVDReadSrcPrivate * priv, int chapter)
      * Make sure the chapter number is valid for this title.
      */
   if (chapter < 0 || chapter >= priv->tt_srpt->title[priv->title].nr_of_ptts) {
-    GST_ERROR ("Invalid chapter %d (only %d available)",
+    GST_WARNING ("Invalid chapter %d (only %d available)",
         chapter, priv->tt_srpt->title[priv->title].nr_of_ptts);
-    ifoClose (priv->vmg_file);
-    DVDClose (priv->dvd);
-    return -1;
+    if (chapter < 0)
+      chapter = 0;
+    chapter = priv->tt_srpt->title[priv->title].nr_of_ptts - 1;
   }
 
     /**
@@ -730,6 +746,7 @@ _seek_chapter (DVDReadSrcPrivate * priv, int chapter)
   priv->new_cell = TRUE;
   priv->next_cell = priv->start_cell;
 
+  priv->chapter = chapter;
   return 0;
 }
 
@@ -907,7 +924,8 @@ again:
 static gboolean
 seek_sector (DVDReadSrcPrivate * priv, int angle)
 {
-  gint seek_to = priv->cur_pack, chapter, sectors, next, cur, i;
+  gint seek_to = priv->cur_pack;
+  gint chapter, sectors, next, cur, i;
 
   /* retrieve position */
   priv->cur_pack = 0;
@@ -992,6 +1010,7 @@ dvdreadsrc_get (GstPad * pad)
       priv->seek_pend_fmt = GST_FORMAT_UNDEFINED;
     } else {
       if (!seek_sector (priv, priv->angle)) {
+        gst_element_set_eos (GST_ELEMENT (dvdreadsrc));
         return GST_DATA (gst_event_new (GST_EVENT_EOS));
       }
     }
@@ -1122,17 +1141,76 @@ dvdreadsrc_uri_get_protocols (void)
 static const gchar *
 dvdreadsrc_uri_get_uri (GstURIHandler * handler)
 {
-  return "dvd://";
+  DVDReadSrc *dvdreadsrc = DVDREADSRC (handler);
+
+  g_free (dvdreadsrc->priv->last_uri);
+  dvdreadsrc->priv->last_uri =
+      g_strdup_printf ("dvd://%d,%d,%d", dvdreadsrc->priv->title,
+      dvdreadsrc->priv->chapter, dvdreadsrc->priv->angle);
+
+  return dvdreadsrc->priv->last_uri;
 }
 
 static gboolean
 dvdreadsrc_uri_set_uri (GstURIHandler * handler, const gchar * uri)
 {
+  DVDReadSrc *dvdreadsrc = DVDREADSRC (handler);
   gboolean ret;
   gchar *protocol = gst_uri_get_protocol (uri);
 
   ret = (protocol && !strcmp (protocol, "dvd")) ? TRUE : FALSE;
   g_free (protocol);
+  protocol = NULL;
+
+  if (!ret)
+    return ret;
+
+  /*
+   * Parse out the new t/c/a and seek to them
+   */
+  {
+    gchar *location = NULL;
+    gchar **strs;
+    gchar **strcur;
+    gint pos = 0;
+
+    location = gst_uri_get_location (uri);
+
+    if (!location)
+      return ret;
+
+    strcur = strs = g_strsplit (location, ",", 0);
+    while (strcur && *strcur) {
+      gint val;
+
+      if (!sscanf (*strcur, "%d", &val))
+        break;
+
+      switch (pos) {
+        case 0:
+          if (val != dvdreadsrc->priv->title) {
+            dvdreadsrc->priv->title = val;
+            dvdreadsrc->priv->new_seek = TRUE;
+          }
+          break;
+        case 1:
+          if (val != dvdreadsrc->priv->chapter) {
+            dvdreadsrc->priv->chapter = val;
+            dvdreadsrc->priv->new_seek = TRUE;
+          }
+          break;
+        case 2:
+          dvdreadsrc->priv->angle = val;
+          break;
+      }
+
+      strcur++;
+      pos++;
+    }
+
+    g_strfreev (strs);
+    g_free (location);
+  }
 
   return ret;
 }
index a70b8b6..84aae6c 100644 (file)
@@ -585,7 +585,7 @@ gst_mpeg2dec_chain (GstPad * pad, GstData * _data)
   GstMpeg2dec *mpeg2dec = GST_MPEG2DEC (gst_pad_get_parent (pad));
   guint32 size;
   guint8 *data, *end;
-  gint64 pts;
+  GstClockTime pts;
   const mpeg2_info_t *info;
   mpeg2_state_t state;
   gboolean done = FALSE;
@@ -596,8 +596,20 @@ gst_mpeg2dec_chain (GstPad * pad, GstData * _data)
     switch (GST_EVENT_TYPE (event)) {
       case GST_EVENT_DISCONTINUOUS:
       {
-        GST_DEBUG_OBJECT (mpeg2dec, "discont, resetting next_time to 0");
-        mpeg2dec->next_time = 0;
+        GstClockTime time;
+
+        if (!gst_event_discont_get_value (event, GST_FORMAT_TIME, &time)
+            || !GST_CLOCK_TIME_IS_VALID (time)) {
+          GST_WARNING_OBJECT (mpeg2dec,
+              "No new time offset in discont event %p", event);
+        } else {
+          mpeg2dec->next_time = time;
+          GST_DEBUG_OBJECT (mpeg2dec,
+              "discont, reset next_time to %" G_GUINT64_FORMAT " (%"
+              GST_TIME_FORMAT ")", mpeg2dec->next_time,
+              GST_TIME_ARGS (mpeg2dec->next_time));
+        }
+
         mpeg2dec->discont_state = MPEG2DEC_DISC_NEW_PICTURE;
         gst_mpeg2dec_flush_decoder (mpeg2dec);
         gst_pad_event_default (pad, event);
@@ -626,7 +638,7 @@ gst_mpeg2dec_chain (GstPad * pad, GstData * _data)
   info = mpeg2_info (mpeg2dec->decoder);
   end = data + size;
 
-  if (pts != -1) {
+  if (pts != GST_CLOCK_TIME_NONE) {
     gint64 mpeg_pts = GST_TIME_TO_MPEG_TIME (pts);
 
     GST_DEBUG_OBJECT (mpeg2dec,
@@ -643,14 +655,14 @@ gst_mpeg2dec_chain (GstPad * pad, GstData * _data)
     GST_LOG ("no pts");
   }
 
-  GST_LOG ("calling mpeg2_buffer");
+  GST_LOG_OBJECT (mpeg2dec, "calling mpeg2_buffer");
   mpeg2_buffer (mpeg2dec->decoder, data, end);
-  GST_LOG ("calling mpeg2_buffer done");
+  GST_LOG_OBJECT (mpeg2dec, "calling mpeg2_buffer done");
 
   while (!done) {
     gboolean slice = FALSE;
 
-    GST_LOG ("calling parse");
+    GST_LOG_OBJECT (mpeg2dec, "calling parse");
     state = mpeg2_parse (mpeg2dec->decoder);
     GST_DEBUG_OBJECT (mpeg2dec, "parse state %d", state);
     switch (state) {
@@ -676,8 +688,9 @@ gst_mpeg2dec_chain (GstPad * pad, GstData * _data)
             info->sequence->frame_period * GST_USECOND / 27;
 
         GST_DEBUG_OBJECT (mpeg2dec,
-            "sequence flags: %d, frame period: %d, frame rate: %d",
+            "sequence flags: %d, frame period: %d (%g), frame rate: %g",
             info->sequence->flags, info->sequence->frame_period,
+            (double) (mpeg2dec->frame_period) / GST_SECOND,
             mpeg2dec->frame_rate);
         GST_DEBUG_OBJECT (mpeg2dec, "profile: %02x, colour_primaries: %d",
             info->sequence->profile_level_id, info->sequence->colour_primaries);
@@ -741,10 +754,11 @@ gst_mpeg2dec_chain (GstPad * pad, GstData * _data)
         break;
       }
       case STATE_SLICE_1ST:
-        GST_DEBUG_OBJECT (mpeg2dec, "slice 1st");
+        GST_LOG_OBJECT (mpeg2dec, "1st slice of frame encountered");
         break;
       case STATE_PICTURE_2ND:
-        GST_DEBUG_OBJECT (mpeg2dec, "picture second");
+        GST_LOG_OBJECT (mpeg2dec,
+            "Second picture header encountered. Decoding 2nd field");
         break;
       case STATE_SLICE:
         slice = TRUE;
@@ -788,22 +802,31 @@ gst_mpeg2dec_chain (GstPad * pad, GstData * _data)
 #else
           if (picture->flags & PIC_FLAG_TAGS) {
             GstClockTime time =
-                MPEG_TIME_TO_GST_TIME ((guint64) picture->tag2 << 32 | picture->
-                tag);
+                MPEG_TIME_TO_GST_TIME ((GstClockTime) (picture->
+                    tag2) << 32 | picture->tag);
 #endif
-
-            GST_DEBUG_OBJECT (mpeg2dec, "picture had pts %" GST_TIME_FORMAT,
-                GST_TIME_ARGS (time));
+            GST_DEBUG_OBJECT (mpeg2dec,
+                "picture had pts %" GST_TIME_FORMAT ", we had %"
+                GST_TIME_FORMAT, GST_TIME_ARGS (time),
+                GST_TIME_ARGS (mpeg2dec->next_time));
             GST_BUFFER_TIMESTAMP (outbuf) = mpeg2dec->next_time = time;
           } else {
             GST_DEBUG_OBJECT (mpeg2dec,
-                "picture didn't have pts using %" GST_TIME_FORMAT,
+                "picture didn't have pts. Using %" GST_TIME_FORMAT,
                 GST_TIME_ARGS (mpeg2dec->next_time));
             GST_BUFFER_TIMESTAMP (outbuf) = mpeg2dec->next_time;
           }
 
-          mpeg2dec->next_time +=
-              (mpeg2dec->frame_period * picture->nb_fields) >> 1;
+          /* TODO set correct offset here based on frame number */
+          if (info->display_picture_2nd) {
+            GST_BUFFER_DURATION (outbuf) = (picture->nb_fields +
+                info->display_picture_2nd->nb_fields) * mpeg2dec->frame_period /
+                2;
+          } else {
+            GST_BUFFER_DURATION (outbuf) =
+                picture->nb_fields * mpeg2dec->frame_period / 2;
+          }
+          mpeg2dec->next_time += GST_BUFFER_DURATION (outbuf);
 
           GST_DEBUG_OBJECT (mpeg2dec,
               "picture: %s %s fields:%d off:%" G_GINT64_FORMAT " ts:%"
@@ -840,8 +863,6 @@ gst_mpeg2dec_chain (GstPad * pad, GstData * _data)
             GST_DEBUG_OBJECT (mpeg2dec, "dropping buffer, asked to skip");
             gst_buffer_unref (outbuf);
           } else {
-            /* TODO set correct offset here based on frame number */
-            GST_BUFFER_DURATION (outbuf) = mpeg2dec->frame_period;
             GST_LOG_OBJECT (mpeg2dec, "pushing buffer, timestamp %"
                 GST_TIME_FORMAT ", duration %" GST_TIME_FORMAT,
                 GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (outbuf)),
@@ -869,14 +890,13 @@ gst_mpeg2dec_chain (GstPad * pad, GstData * _data)
         break;
         /* error */
       case STATE_INVALID:
-        g_warning ("mpeg2dec: decoding error");
+        GST_WARNING_OBJECT (mpeg2dec, "Decoding error");
         /* it looks like setting a new frame in libmpeg2 avoids a crash */
         /* FIXME figure out how this screws up sync and buffer leakage */
         gst_mpeg2dec_alloc_buffer (mpeg2dec, info, GST_BUFFER_OFFSET (buf));
         break;
       default:
-        g_warning ("%s: unhandled state %d, FIXME",
-            gst_element_get_name (GST_ELEMENT (mpeg2dec)), state);
+        GST_ERROR_OBJECT (mpeg2dec, "Unknown libmpeg2 state %d, FIXME", state);
         break;
     }
 
@@ -1306,6 +1326,7 @@ gst_mpeg2dec_change_state (GstElement * element)
     case GST_STATE_PLAYING_TO_PAUSED:
       break;
     case GST_STATE_PAUSED_TO_READY:
+      gst_mpeg2dec_flush_decoder (mpeg2dec);
       gst_mpeg2dec_close_decoder (mpeg2dec);
       break;
     case GST_STATE_READY_TO_NULL:
index 4eb1368..72cd743 100644 (file)
@@ -71,9 +71,10 @@ struct _GstMpeg2dec {
   gboolean      closed;
   gboolean      have_fbuf;
 
-  /* the timestamp of the next frame */
   DiscontState  discont_state;
-  gint64        next_time;
+
+  /* the timestamp of the next frame */
+  GstClockTime   next_time;
   gint64        segment_start;
   gint64        segment_end;
 
index b152886..45cb5c8 100644 (file)
 
 #include "gstdvddemux.h"
 
+/* 
+ * Start the timestamp sequence at 2 seconds to allow for strange audio
+ * timestamps when audio crosses a VOBU 
+ */
+#define INITIAL_END_PTM (2 * GST_SECOND)
 
 GST_DEBUG_CATEGORY_STATIC (gstdvddemux_debug);
 #define GST_CAT_DEFAULT (gstdvddemux_debug)
@@ -290,28 +295,7 @@ gst_dvd_demux_init (GstDVDDemux * dvd_demux)
   dvd_demux->cur_audio_nr = 0;
   dvd_demux->cur_subpicture_nr = 0;
 
-  /* Start the timestamp sequence in 0. */
-  dvd_demux->last_end_ptm = 0;
-
-  /* (Ronald) so, this was disabled. I'm enabling (default) it again.
-   * Timestamp adjustment is fairly evil, we would ideally use discont
-   * events instead. However, our current clocking has a pretty serious
-   * race condition: imagine that $pipeline is at time 30sec and $audio
-   * receives a discont to 0sec. Video processes its last buffer and
-   * calls _wait() on $timestamp, which is 30s - so we wait (hang) 30sec.
-   * This is unacceptable, obviously, and timestamp adjustment, no matter
-   * how evil, solves this.
-   * Before disabling this again, tripple check that al .vob files on our
-   * websites /media/ directory work fine, especially bullet.vob and
-   * barrage.vob.
-   */
-#if 0
-  /* Try to prevent the mpegparse infrastructure from doing timestamp
-     adjustment. */
-  mpeg_parse->do_adjust = FALSE;
-  mpeg_parse->adjust = 0;
-#endif
-
+  dvd_demux->last_end_ptm = INITIAL_END_PTM;
   dvd_demux->just_flushed = FALSE;
   dvd_demux->discont_time = GST_CLOCK_TIME_NONE;
 
@@ -416,6 +400,26 @@ gst_dvd_demux_handle_dvd_event (GstDVDDemux * dvd_demux, GstEvent * event)
           (double) dvd_demux->last_end_ptm / GST_SECOND,
           (double) start_ptm / GST_SECOND,
           (double) mpeg_demux->adjust / GST_SECOND);
+
+      /* Disable mpeg_parse's timestamp adjustment in favour of the info
+       * from DVD nav packets.
+       * Timestamp adjustment is fairly evil, we would ideally use discont
+       * events instead. However, our current clocking has a pretty serious
+       * race condition: imagine that $pipeline is at time 30sec and $audio
+       * receives a discont to 0sec. Video processes its last buffer and
+       * calls _wait() on $timestamp, which is 30s - so we wait (hang) 30sec.
+       * This is unacceptable, obviously, and timestamp adjustment, no matter
+       * how evil, solves this.
+       * Before disabling this again, tripple check that al .vob files on our
+       * websites /media/ directory work fine, especially bullet.vob and
+       * barrage.vob.
+       */
+#if 1
+      /* Try to prevent the mpegparse infrastructure from doing timestamp
+         adjustment. */
+      mpeg_parse->use_adjust = FALSE;
+      mpeg_parse->adjust = 0;
+#endif
     }
     dvd_demux->last_end_ptm = end_ptm;
 
@@ -425,6 +429,9 @@ gst_dvd_demux_handle_dvd_event (GstDVDDemux * dvd_demux, GstEvent * event)
          time gap between the discontinuity and the subsequent data
          blocks. */
       dvd_demux->discont_time = start_ptm + mpeg_demux->adjust;
+      GST_DEBUG_OBJECT (dvd_demux, "Set discont time to %" G_GINT64_FORMAT,
+          start_ptm + mpeg_demux->adjust);
+
       dvd_demux->just_flushed = FALSE;
     }
 
@@ -454,34 +461,39 @@ gst_dvd_demux_send_discont (GstMPEGParse * mpeg_parse, GstClockTime time)
 
   GST_MPEG_PARSE_CLASS (parent_class)->send_discont (mpeg_parse, time);
 
+  discont = gst_event_new_discontinuous (FALSE, GST_FORMAT_TIME, time, NULL);
+  if (!discont) {
+    GST_ELEMENT_ERROR (GST_ELEMENT (dvd_demux),
+        RESOURCE, FAILED, (NULL), ("Allocation failed"));
+    return;
+  }
+
   for (i = 0; i < GST_DVD_DEMUX_NUM_SUBPICTURE_STREAMS; i++) {
     if (dvd_demux->subpicture_stream[i] &&
         GST_PAD_IS_USABLE (dvd_demux->subpicture_stream[i]->pad)) {
-      discont = gst_event_new_discontinuous (FALSE, GST_FORMAT_TIME,
-          time, NULL);
 
+      gst_event_ref (discont);
       gst_pad_push (dvd_demux->subpicture_stream[i]->pad, GST_DATA (discont));
     }
   }
 
   /* Distribute the event to the "current" pads. */
   if (GST_PAD_IS_USABLE (dvd_demux->cur_video)) {
-    discont = gst_event_new_discontinuous (FALSE, GST_FORMAT_TIME, time, NULL);
-
+    gst_event_ref (discont);
     gst_pad_push (dvd_demux->cur_video, GST_DATA (discont));
   }
 
   if (GST_PAD_IS_USABLE (dvd_demux->cur_audio)) {
-    discont = gst_event_new_discontinuous (FALSE, GST_FORMAT_TIME, time, NULL);
-
+    gst_event_ref (discont);
     gst_pad_push (dvd_demux->cur_audio, GST_DATA (discont));
   }
 
   if (GST_PAD_IS_USABLE (dvd_demux->cur_subpicture)) {
-    discont = gst_event_new_discontinuous (FALSE, GST_FORMAT_TIME, time, NULL);
-
+    gst_event_ref (discont);
     gst_pad_push (dvd_demux->cur_subpicture, GST_DATA (discont));
   }
+
+  gst_event_unref (discont);
 }
 
 static void
@@ -857,8 +869,12 @@ gst_dvd_demux_send_subbuffer (GstMPEGDemux * mpeg_demux,
      minimize the time interval between the discontinuity and the data
      buffers following it. */
   if (dvd_demux->discont_time != GST_CLOCK_TIME_NONE) {
+    if ((gint64) (dvd_demux->discont_time) < 0) {
+      GST_ERROR ("DVD Discont < 0! % " G_GINT64_FORMAT,
+          (gint64) dvd_demux->discont_time);
+    }
     PARSE_CLASS (mpeg_demux)->send_discont (mpeg_parse,
-        dvd_demux->discont_time - 200 * GST_MSECOND);
+        dvd_demux->discont_time);
     dvd_demux->discont_time = GST_CLOCK_TIME_NONE;
   }
 
@@ -991,7 +1007,7 @@ gst_dvd_demux_reset (GstDVDDemux * dvd_demux)
   dvd_demux->cur_audio_nr = 0;
   dvd_demux->cur_subpicture_nr = 0;
   dvd_demux->mpeg_version = 0;
-  dvd_demux->last_end_ptm = 0;
+  dvd_demux->last_end_ptm = INITIAL_END_PTM;
 
   dvd_demux->just_flushed = FALSE;
   dvd_demux->discont_time = GST_CLOCK_TIME_NONE;
index 3b7a6d6..002cfe5 100644 (file)
@@ -107,7 +107,7 @@ struct _GstDVDDemux {
   gboolean just_flushed;       /* The element just received a flush event. */
   GstClockTime discont_time;   /* If different from GST_CLOCK_TIME_NONE, a
                                    discontinuous event should be sent with the
-                                   given time, before sending the next dara
+                                   given time, before sending the next data
                                    block.. */
 
   gint mpeg_version;           /* Version of the MPEG video stream */
index ac48cb4..b49edbe 100644 (file)
@@ -275,13 +275,18 @@ gst_mpeg_demux_send_discont (GstMPEGParse * mpeg_parse, GstClockTime time)
   gint i;
 
   GST_DEBUG_OBJECT (mpeg_demux, "discont %" G_GUINT64_FORMAT, time);
+  discont = gst_event_new_discontinuous (FALSE, GST_FORMAT_TIME, time, NULL);
+
+  if (!discont) {
+    GST_ELEMENT_ERROR (GST_ELEMENT (mpeg_demux),
+        RESOURCE, FAILED, (NULL), ("Allocation failed"));
+    return;
+  }
 
   for (i = 0; i < GST_MPEG_DEMUX_NUM_VIDEO_STREAMS; i++) {
     if (mpeg_demux->video_stream[i] &&
         GST_PAD_IS_USABLE (mpeg_demux->video_stream[i]->pad)) {
-      discont = gst_event_new_discontinuous (FALSE, GST_FORMAT_TIME,
-          time, NULL);
-
+      gst_event_ref (discont);
       gst_pad_push (mpeg_demux->video_stream[i]->pad, GST_DATA (discont));
     }
   }
@@ -289,9 +294,7 @@ gst_mpeg_demux_send_discont (GstMPEGParse * mpeg_parse, GstClockTime time)
   for (i = 0; i < GST_MPEG_DEMUX_NUM_AUDIO_STREAMS; i++) {
     if (mpeg_demux->audio_stream[i] &&
         GST_PAD_IS_USABLE (mpeg_demux->audio_stream[i]->pad)) {
-      discont = gst_event_new_discontinuous (FALSE, GST_FORMAT_TIME,
-          time, NULL);
-
+      gst_event_ref (discont);
       gst_pad_push (mpeg_demux->audio_stream[i]->pad, GST_DATA (discont));
     }
   }
@@ -299,12 +302,12 @@ gst_mpeg_demux_send_discont (GstMPEGParse * mpeg_parse, GstClockTime time)
   for (i = 0; i < GST_MPEG_DEMUX_NUM_PRIVATE_STREAMS; i++) {
     if (mpeg_demux->private_stream[i] &&
         GST_PAD_IS_USABLE (mpeg_demux->private_stream[i]->pad)) {
-      discont = gst_event_new_discontinuous (FALSE, GST_FORMAT_TIME,
-          time, NULL);
-
+      gst_event_ref (discont);
       gst_pad_push (mpeg_demux->private_stream[i]->pad, GST_DATA (discont));
     }
   }
+
+  gst_event_unref (discont);
 }
 
 static void
@@ -618,13 +621,13 @@ gst_mpeg_demux_parse_syshead (GstMPEGParse * mpeg_parse, GstBuffer * buffer)
 
         if (GST_PAD_IS_USABLE (outstream->pad)) {
           GstEvent *event;
-          gint64 time;
+          GstClockTime time;
 
           time = MPEGTIME_TO_GSTTIME (mpeg_parse->current_scr
               + mpeg_parse->adjust) + mpeg_demux->adjust;
 
           event = gst_event_new_discontinuous (FALSE, GST_FORMAT_TIME,
-              MPEGTIME_TO_GSTTIME (time), NULL);
+              time, NULL);
 
           gst_pad_push (outstream->pad, GST_DATA (event));
         }
@@ -839,11 +842,14 @@ gst_mpeg_demux_parse_pes (GstMPEGParse * mpeg_parse, GstBuffer * buffer)
       pts |= ((guint64) * buf++) << 7;
       pts |= ((guint64) (*buf++ & 0xFE)) >> 1;
 
-      GST_DEBUG_OBJECT (mpeg_demux, "0x%02x (%lld) PTS = %" G_GUINT64_FORMAT,
-          id, pts, MPEGTIME_TO_GSTTIME (pts));
+      timestamp =
+          MPEGTIME_TO_GSTTIME (pts + mpeg_parse->adjust) + mpeg_demux->adjust;
 
-      pts += mpeg_parse->adjust;
-      timestamp = MPEGTIME_TO_GSTTIME (pts) + mpeg_demux->adjust;
+      GST_DEBUG_OBJECT (mpeg_demux,
+          "0x%02x (% " G_GINT64_FORMAT ") PTS = %" G_GUINT64_FORMAT
+          " (adjusted = %" G_GINT64_FORMAT ")", id, pts,
+          MPEGTIME_TO_GSTTIME (pts),
+          MPEGTIME_TO_GSTTIME (pts + mpeg_parse->adjust) + mpeg_demux->adjust);
     } else {
       timestamp = GST_CLOCK_TIME_NONE;
     }
index 8e5fee8..a7deb6c 100644 (file)
@@ -238,6 +238,7 @@ gst_mpeg_parse_init (GstMPEGParse * mpeg_parse)
   mpeg_parse->max_discont = DEFAULT_MAX_DISCONT;
 
   mpeg_parse->do_adjust = TRUE;
+  mpeg_parse->use_adjust = TRUE;
 
   GST_FLAG_SET (mpeg_parse, GST_ELEMENT_EVENT_AWARE);
 }
@@ -283,9 +284,10 @@ gst_mpeg_parse_handle_discont (GstMPEGParse * mpeg_parse, GstEvent * event)
 
   g_return_if_fail (GST_EVENT_TYPE (event) == GST_EVENT_DISCONTINUOUS);
 
-  if (gst_event_discont_get_value (event, GST_FORMAT_TIME, &time)) {
-    GST_DEBUG_OBJECT (mpeg_parse,
-        "forwarding discontinuity, time: %0.3fs", (double) time / GST_SECOND);
+  if (gst_event_discont_get_value (event, GST_FORMAT_TIME, &time)
+      && (GST_CLOCK_TIME_IS_VALID (time))) {
+    GST_DEBUG_OBJECT (mpeg_parse, "forwarding discontinuity, time: %0.3fs",
+        (double) time / GST_SECOND);
 
     if (CLASS (mpeg_parse)->send_discont)
       CLASS (mpeg_parse)->send_discont (mpeg_parse, time);
@@ -452,10 +454,11 @@ gst_mpeg_parse_parse_packhead (GstMPEGParse * mpeg_parse, GstBuffer * buffer)
         mpeg_parse->current_scr, mpeg_parse->adjust);
 
     if (mpeg_parse->do_adjust) {
-      mpeg_parse->adjust +=
-          (gint64) mpeg_parse->next_scr - (gint64) mpeg_parse->current_scr;
-
-      GST_DEBUG ("new adjust: %" G_GINT64_FORMAT, mpeg_parse->adjust);
+      if (mpeg_parse->use_adjust) {
+        mpeg_parse->adjust +=
+            (gint64) mpeg_parse->next_scr - (gint64) mpeg_parse->current_scr;
+        GST_DEBUG ("new adjust: %" G_GINT64_FORMAT, mpeg_parse->adjust);
+      }
     } else {
       mpeg_parse->discont_pending = TRUE;
     }
index 70db04b..e6d83d0 100644 (file)
@@ -65,8 +65,12 @@ struct _GstMPEGParse {
   guint64       next_scr;              /* Expected next SCR. */
   guint64       bytes_since_scr;
 
-  gboolean      do_adjust;             /* Adjust timestamps to smooth
-                                           discontinuities. */
+  gboolean     do_adjust;              /* If false, send discont events on SCR
+                                        * jumps
+                                       */
+  gboolean      use_adjust;            /* Collect SCR jumps into 'adjust' in
+                                        * order to adjust timestamps to smooth
+                                         * discontinuities. */
   gint64        adjust;                /* Current timestamp adjust value. */
 
   gboolean      discont_pending;