ext/dvdread/dvdreadsrc.c: Allow and implement non-flushing and/or segment seek (mainl...
authorMark Nauwelaerts <mark.nauwelaerts@collabora.co.uk>
Fri, 27 Jun 2008 12:58:35 +0000 (12:58 +0000)
committerMark Nauwelaerts <mark.nauwelaerts@collabora.co.uk>
Fri, 27 Jun 2008 12:58:35 +0000 (12:58 +0000)
Original commit message from CVS:
* ext/dvdread/dvdreadsrc.c: (gst_dvd_read_src_read),
(gst_dvd_read_src_create), (gst_dvd_read_src_handle_seek_event):
Allow and implement non-flushing and/or segment seek
(mainly in TIME and chapter format).
* gst/mpegstream/gstdvddemux.c: (gst_dvd_demux_process_event),
(gst_dvd_demux_get_subpicture_stream),
(gst_dvd_demux_synchronise_pads),
(gst_dvd_demux_sync_stream_to_time):
* gst/mpegstream/gstmpegdemux.c: (gst_mpeg_demux_process_event),
(gst_mpeg_demux_send_subbuffer),
(gst_mpeg_demux_sync_stream_to_time),
(gst_mpeg_streams_reset_cur_ts):
* gst/mpegstream/gstmpegdemux.h:
* gst/mpegstream/gstmpegparse.c: (gst_mpeg_parse_process_event),
(gst_mpeg_parse_pad_added), (gst_mpeg_parse_handle_src_query):
Delegate a query to upstream if it can't be handled.
Make segment stop aware.
Fix (subtitle) stream synchronization.
Add some debug statements.

ChangeLog
ext/dvdread/dvdreadsrc.c
gst/mpegstream/gstdvddemux.c
gst/mpegstream/gstmpegdemux.c
gst/mpegstream/gstmpegdemux.h
gst/mpegstream/gstmpegparse.c

index db99138..47a5e06 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,25 @@
+2008-06-27  Mark Nauwelaerts  <mark.nauwelaerts@collabora.co.uk>
+
+       * ext/dvdread/dvdreadsrc.c: (gst_dvd_read_src_read),
+       (gst_dvd_read_src_create), (gst_dvd_read_src_handle_seek_event):
+       Allow and implement non-flushing and/or segment seek
+       (mainly in TIME and chapter format).
+       * gst/mpegstream/gstdvddemux.c: (gst_dvd_demux_process_event),
+       (gst_dvd_demux_get_subpicture_stream),
+       (gst_dvd_demux_synchronise_pads),
+       (gst_dvd_demux_sync_stream_to_time):
+       * gst/mpegstream/gstmpegdemux.c: (gst_mpeg_demux_process_event),
+       (gst_mpeg_demux_send_subbuffer),
+       (gst_mpeg_demux_sync_stream_to_time),
+       (gst_mpeg_streams_reset_cur_ts):
+       * gst/mpegstream/gstmpegdemux.h:
+       * gst/mpegstream/gstmpegparse.c: (gst_mpeg_parse_process_event),
+       (gst_mpeg_parse_pad_added), (gst_mpeg_parse_handle_src_query):
+       Delegate a query to upstream if it can't be handled.
+       Make segment stop aware.
+       Fix (subtitle) stream synchronization.
+       Add some debug statements.
+
 2008-06-26  Edward Hervey  <edward.hervey@collabora.co.uk>
 
        * gst/mpegaudioparse/gstmpegaudioparse.c: (head_check):
index 06b1b85..79eb980 100644 (file)
@@ -724,11 +724,15 @@ gst_dvd_read_src_read (GstDvdReadSrc * src, gint angle, gint new_seek,
     GstBuffer ** p_buf)
 {
   GstBuffer *buf;
+  GstSegment *seg;
   guint8 oneblock[DVD_VIDEO_LB_LEN];
   dsi_t dsi_pack;
   guint next_vobu, next_ilvu_start, cur_output_size;
   gint len;
   gint retries;
+  gint64 next_time;
+
+  seg = &(GST_BASE_SRC (src)->segment);
 
   /* playback by cell in this pgc, starting at the cell for our chapter */
   if (new_seek)
@@ -738,8 +742,12 @@ again:
 
   if (src->cur_cell >= src->last_cell) {
     /* advance to next chapter */
-    if (src->chapter == (src->num_chapters - 1))
+    if (src->chapter == (src->num_chapters - 1) ||
+        (seg->format == chapter_format && seg->stop != -1 &&
+            src->chapter == (seg->stop - 1))) {
+      GST_DEBUG_OBJECT (src, "end of chapter segment");
       goto eos;
+    }
 
     GST_INFO_OBJECT (src, "end of chapter %d, switch to next",
         src->chapter + 1);
@@ -847,16 +855,24 @@ nav_retry:
 
   *p_buf = buf;
 
+  GST_LOG_OBJECT (src, "Read %u sectors", cur_output_size);
+
   src->cur_pack = next_vobu;
 
-  GST_LOG_OBJECT (src, "Read %u sectors", cur_output_size);
+  next_time = GST_BUFFER_TIMESTAMP (buf);
+  if (GST_CLOCK_TIME_IS_VALID (next_time) && seg->format == GST_FORMAT_TIME &&
+      GST_CLOCK_TIME_IS_VALID (seg->stop) &&
+      next_time > seg->stop + 5 * GST_SECOND) {
+    GST_DEBUG_OBJECT (src, "end of TIME segment");
+    goto eos;
+  }
 
   return GST_DVD_READ_OK;
 
   /* ERRORS */
 eos:
   {
-    GST_INFO_OBJECT (src, "last chapter done - EOS");
+    GST_INFO_OBJECT (src, "Reached end-of-segment/stream - EOS");
     return GST_DVD_READ_EOS;
   }
 read_error:
@@ -920,7 +936,6 @@ gst_dvd_read_src_create (GstPushSrc * pushsrc, GstBuffer ** p_buf)
       return GST_FLOW_ERROR;
     }
     case GST_DVD_READ_EOS:{
-      GST_INFO_OBJECT (src, "Reached EOS");
       return GST_FLOW_UNEXPECTED;
     }
     case GST_DVD_READ_OK:{
@@ -1060,19 +1075,12 @@ gst_dvd_read_src_handle_seek_event (GstDvdReadSrc * src, GstEvent * event)
     return FALSE;
   }
 
-  if ((flags & GST_SEEK_FLAG_SEGMENT) != 0) {
-    GST_DEBUG_OBJECT (src, "segment seek not supported");
-    return FALSE;
-  }
-
-  if ((flags & GST_SEEK_FLAG_FLUSH) == 0) {
-    GST_DEBUG_OBJECT (src, "can only do flushing seeks at the moment");
-    return FALSE;
-  }
-
   if (end_type != GST_SEEK_TYPE_NONE) {
-    GST_DEBUG_OBJECT (src, "end seek type not supported");
-    return FALSE;
+    if ((format != chapter_format && format != GST_FORMAT_TIME) ||
+        end_type != GST_SEEK_TYPE_SET) {
+      GST_DEBUG_OBJECT (src, "end seek type not supported");
+      return FALSE;
+    }
   }
 
   if (cur_type != GST_SEEK_TYPE_SET) {
index 8a7130c..f2de7b3 100644 (file)
@@ -309,6 +309,10 @@ gst_dvd_demux_process_event (GstMPEGParse * mpeg_parse, GstEvent * event)
            may mean that we find some audio blocks lying outside the
            segment. Filter them. */
         dvd_demux->segment_filter = TRUE;
+
+        /* reset stream synchronization; parent handles other streams */
+        gst_mpeg_streams_reset_cur_ts (dvd_demux->subpicture_stream,
+            GST_DVD_DEMUX_NUM_SUBPICTURE_STREAMS, 0);
       }
 
       ret = GST_MPEG_PARSE_CLASS (parent_class)->process_event (mpeg_parse,
@@ -733,9 +737,6 @@ gst_dvd_demux_get_subpicture_stream (GstMPEGDemux * mpeg_demux,
     }
 
     if (add_pad) {
-      gst_pad_set_active (str->pad, TRUE);
-      gst_element_add_pad (GST_ELEMENT (mpeg_demux), str->pad);
-
       if (dvd_demux->langcodes) {
         gchar *t;
 
@@ -744,15 +745,21 @@ gst_dvd_demux_get_subpicture_stream (GstMPEGDemux * mpeg_demux,
             gst_structure_get_string (gst_event_get_structure (dvd_demux->
                 langcodes), t);
         g_free (t);
+      }
 
-        if (lang_code) {
-          GstTagList *list = gst_tag_list_new ();
+      GST_DEBUG_OBJECT (mpeg_demux, "adding pad %s with language = %s",
+          GST_PAD_NAME (str->pad), (lang_code) ? lang_code : "(unknown)");
 
-          gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
-              GST_TAG_LANGUAGE_CODE, lang_code, NULL);
-          gst_element_found_tags_for_pad (GST_ELEMENT (mpeg_demux),
-              str->pad, list);
-        }
+      gst_pad_set_active (str->pad, TRUE);
+      gst_element_add_pad (GST_ELEMENT (mpeg_demux), str->pad);
+
+      if (lang_code) {
+        GstTagList *list = gst_tag_list_new ();
+
+        gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
+            GST_TAG_LANGUAGE_CODE, lang_code, NULL);
+        gst_element_found_tags_for_pad (GST_ELEMENT (mpeg_demux),
+            str->pad, list);
       }
     }
     str->type = GST_DVD_DEMUX_SUBP_DVD;
@@ -1155,6 +1162,14 @@ gst_dvd_demux_synchronise_pads (GstMPEGDemux * mpeg_demux,
   parent_class->synchronise_pads (mpeg_demux, threshold, new_ts);
 
   for (i = 0; i < GST_DVD_DEMUX_NUM_SUBPICTURE_STREAMS; i++) {
+#ifndef GST_DISABLE_DEBUG
+    if (dvd_demux->subpicture_stream[i]) {
+      GST_LOG_OBJECT (mpeg_demux, "stream: %d, current: %" GST_TIME_FORMAT
+          ", threshold %" GST_TIME_FORMAT, i,
+          GST_TIME_ARGS (dvd_demux->subpicture_stream[i]->cur_ts),
+          GST_TIME_ARGS (threshold));
+    }
+#endif
     if (dvd_demux->subpicture_stream[i]
         && (dvd_demux->subpicture_stream[i]->cur_ts < threshold)) {
       DEMUX_CLASS (mpeg_demux)->sync_stream_to_time (mpeg_demux,
@@ -1193,9 +1208,13 @@ gst_dvd_demux_sync_stream_to_time (GstMPEGDemux * mpeg_demux,
   }
 
   if (outpad && (cur_nr == stream->number)) {
+    guint64 update_time;
+
+    update_time =
+        MIN ((guint64) last_ts, (guint64) mpeg_parse->current_segment.stop);
     gst_pad_push_event (outpad, gst_event_new_new_segment (TRUE,
             mpeg_parse->current_segment.rate, GST_FORMAT_TIME,
-            last_ts, -1, last_ts));
+            update_time, mpeg_parse->current_segment.stop, update_time));
   }
 }
 
index 3a1a24d..057b9fe 100644 (file)
@@ -252,6 +252,15 @@ gst_mpeg_demux_process_event (GstMPEGParse * mpeg_parse, GstEvent * event)
       gst_mpeg_streams_reset_last_flow (demux->private_stream,
           GST_MPEG_DEMUX_NUM_PRIVATE_STREAMS);
       break;
+    case GST_EVENT_NEWSEGMENT:
+      /* reset stream synchronization */
+      gst_mpeg_streams_reset_cur_ts (demux->video_stream,
+          GST_MPEG_DEMUX_NUM_VIDEO_STREAMS, 0);
+      gst_mpeg_streams_reset_cur_ts (demux->audio_stream,
+          GST_MPEG_DEMUX_NUM_AUDIO_STREAMS, 0);
+      gst_mpeg_streams_reset_cur_ts (demux->private_stream,
+          GST_MPEG_DEMUX_NUM_PRIVATE_STREAMS, 0);
+      /* fallthrough */
     default:
       ret = GST_MPEG_PARSE_CLASS (parent_class)->process_event (mpeg_parse,
           event);
@@ -1011,7 +1020,7 @@ gst_mpeg_demux_send_subbuffer (GstMPEGDemux * mpeg_demux,
           GST_FORMAT_BYTES,
           GST_BUFFER_OFFSET (buffer), GST_FORMAT_TIME, timestamp, 0);
     }
-  } else
+  } else if (mpeg_parse->current_ts != GST_CLOCK_TIME_NONE)
     outstream->cur_ts = mpeg_parse->current_ts + outstream->scr_offs;
 
   if (size == 0)
@@ -1036,6 +1045,11 @@ gst_mpeg_demux_send_subbuffer (GstMPEGDemux * mpeg_demux,
   GST_LOG_OBJECT (outstream->pad, "flow: %s", gst_flow_get_name (ret));
   ++outstream->buffers_sent;
 
+  GST_LOG_OBJECT (mpeg_demux, "current: %" GST_TIME_FORMAT
+      ", gap %" GST_TIME_FORMAT ", tol: %" GST_TIME_FORMAT,
+      GST_TIME_ARGS (mpeg_parse->current_ts),
+      GST_TIME_ARGS (mpeg_demux->max_gap),
+      GST_TIME_ARGS (mpeg_demux->max_gap_tolerance));
   if (GST_CLOCK_TIME_IS_VALID (mpeg_demux->max_gap) &&
       GST_CLOCK_TIME_IS_VALID (mpeg_parse->current_ts) &&
       (mpeg_parse->current_ts > mpeg_demux->max_gap)) {
@@ -1114,12 +1128,15 @@ gst_mpeg_demux_sync_stream_to_time (GstMPEGDemux * mpeg_demux,
     GstMPEGStream * stream, GstClockTime last_ts)
 {
   GstMPEGParse *mpeg_parse = GST_MPEG_PARSE (mpeg_demux);
+  guint64 update_time;
 
+  update_time =
+      MIN ((guint64) last_ts, (guint64) mpeg_parse->current_segment.stop);
   gst_pad_push_event (stream->pad, gst_event_new_new_segment (TRUE,
           mpeg_parse->current_segment.rate, GST_FORMAT_TIME,
-          last_ts, -1, last_ts));
+          update_time, mpeg_parse->current_segment.stop, update_time));
 
-  mpeg_parse->current_segment.start = last_ts;
+  mpeg_parse->current_segment.last_stop = update_time;
 }
 
 #if 0
@@ -1367,6 +1384,18 @@ gst_mpeg_streams_reset_last_flow (GstMPEGStream * streams[], guint num)
   }
 }
 
+void
+gst_mpeg_streams_reset_cur_ts (GstMPEGStream * streams[], guint num,
+    GstClockTime cur_ts)
+{
+  guint i;
+
+  for (i = 0; i < num; ++i) {
+    if (streams[i] != NULL)
+      streams[i]->cur_ts = cur_ts;
+  }
+}
+
 gboolean
 gst_mpeg_demux_plugin_init (GstPlugin * plugin)
 {
index c810595..a2a56fd 100644 (file)
@@ -206,6 +206,9 @@ struct _GstMPEGDemuxClass {
 
 void            gst_mpeg_streams_reset_last_flow (GstMPEGStream *streams[],
                                                   guint          num);
+void            gst_mpeg_streams_reset_cur_ts    (GstMPEGStream *streams[],
+                                                  guint          num,
+                                                  GstClockTime   cur_ts);
 
 GType           gst_mpeg_demux_get_type          (void);
 
index e074682..aa5c614 100644 (file)
@@ -383,9 +383,16 @@ gst_mpeg_parse_process_event (GstMPEGParse * mpeg_parse, GstEvent * event)
           if (CLASS (mpeg_parse)->send_event) {
             CLASS (mpeg_parse)->send_event (mpeg_parse,
                 gst_event_new_new_segment (FALSE, rate, GST_FORMAT_TIME,
-                    start, -1, time));
+                    start, stop, time));
+            mpeg_parse->pending_newsegment = FALSE;
           }
         }
+      } else if (format != GST_FORMAT_TIME && !update) {
+        GST_DEBUG_OBJECT (mpeg_parse,
+            "Received non-time newsegment from stream");
+        mpeg_parse->do_adjust = TRUE;
+        mpeg_parse->adjust = 0;
+        mpeg_parse->pending_newsegment = TRUE;
       }
       mpeg_parse->packetize->resync = TRUE;
 
@@ -488,7 +495,7 @@ gst_mpeg_parse_pad_added (GstElement * element, GstPad * pad)
   event = gst_event_new_new_segment (FALSE,
       mpeg_parse->current_segment.rate,
       GST_FORMAT_TIME, mpeg_parse->current_segment.start,
-      -1, mpeg_parse->current_segment.start);
+      mpeg_parse->current_segment.stop, mpeg_parse->current_segment.start);
 
   gst_pad_push_event (pad, event);
 }
@@ -1038,6 +1045,8 @@ gst_mpeg_parse_handle_src_query (GstPad * pad, GstQuery * query)
 
       /* Convert the value to the desired format. */
       if ((res = gst_mpeg_parse_convert (mpeg_parse, src_format, src_value,
+                  &format, &value)) ||
+          (res = gst_pad_query_peer_duration (mpeg_parse->sinkpad,
                   &format, &value))) {
         gst_query_set_duration (query, format, value);
       }
@@ -1067,6 +1076,8 @@ gst_mpeg_parse_handle_src_query (GstPad * pad, GstQuery * query)
 
       /* Convert the value to the desired format. */
       if ((res = gst_mpeg_parse_convert (mpeg_parse, src_format, src_value,
+                  &format, &value)) ||
+          (res = gst_pad_query_peer_position (mpeg_parse->sinkpad,
                   &format, &value))) {
         gst_query_set_position (query, format, value);
       }
@@ -1076,7 +1087,9 @@ gst_mpeg_parse_handle_src_query (GstPad * pad, GstQuery * query)
       gst_query_parse_convert (query, &src_format, &src_value, &format, NULL);
 
       if ((res = gst_mpeg_parse_convert (mpeg_parse, src_format, src_value,
-                  &format, &value))) {
+                  &format, &value)) ||
+          (res = gst_pad_query_peer_convert (mpeg_parse->sinkpad,
+                  src_format, src_value, &format, &value))) {
         gst_query_set_convert (query, src_format, src_value, format, value);
       }
       break;