+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):
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)
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);
*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:
return GST_FLOW_ERROR;
}
case GST_DVD_READ_EOS:{
- GST_INFO_OBJECT (src, "Reached EOS");
return GST_FLOW_UNEXPECTED;
}
case GST_DVD_READ_OK:{
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) {
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,
}
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;
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;
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,
}
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));
}
}
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);
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)
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)) {
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
}
}
+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)
{
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);
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;
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);
}
/* 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);
}
/* 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);
}
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;