ext/dvdread/dvdreadsrc.c: Allow and implement non-flushing and/or segment seek (mainly in TIME and chapter format).

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.
This commit is contained in:
Mark Nauwelaerts 2008-06-27 12:58:35 +00:00
parent 8c0a922780
commit a977cd5ac6
6 changed files with 127 additions and 33 deletions

View file

@ -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> 2008-06-26 Edward Hervey <edward.hervey@collabora.co.uk>
* gst/mpegaudioparse/gstmpegaudioparse.c: (head_check): * gst/mpegaudioparse/gstmpegaudioparse.c: (head_check):

View file

@ -724,11 +724,15 @@ gst_dvd_read_src_read (GstDvdReadSrc * src, gint angle, gint new_seek,
GstBuffer ** p_buf) GstBuffer ** p_buf)
{ {
GstBuffer *buf; GstBuffer *buf;
GstSegment *seg;
guint8 oneblock[DVD_VIDEO_LB_LEN]; guint8 oneblock[DVD_VIDEO_LB_LEN];
dsi_t dsi_pack; dsi_t dsi_pack;
guint next_vobu, next_ilvu_start, cur_output_size; guint next_vobu, next_ilvu_start, cur_output_size;
gint len; gint len;
gint retries; gint retries;
gint64 next_time;
seg = &(GST_BASE_SRC (src)->segment);
/* playback by cell in this pgc, starting at the cell for our chapter */ /* playback by cell in this pgc, starting at the cell for our chapter */
if (new_seek) if (new_seek)
@ -738,8 +742,12 @@ again:
if (src->cur_cell >= src->last_cell) { if (src->cur_cell >= src->last_cell) {
/* advance to next chapter */ /* 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; goto eos;
}
GST_INFO_OBJECT (src, "end of chapter %d, switch to next", GST_INFO_OBJECT (src, "end of chapter %d, switch to next",
src->chapter + 1); src->chapter + 1);
@ -847,16 +855,24 @@ nav_retry:
*p_buf = buf; *p_buf = buf;
GST_LOG_OBJECT (src, "Read %u sectors", cur_output_size);
src->cur_pack = next_vobu; 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; return GST_DVD_READ_OK;
/* ERRORS */ /* ERRORS */
eos: eos:
{ {
GST_INFO_OBJECT (src, "last chapter done - EOS"); GST_INFO_OBJECT (src, "Reached end-of-segment/stream - EOS");
return GST_DVD_READ_EOS; return GST_DVD_READ_EOS;
} }
read_error: read_error:
@ -920,7 +936,6 @@ gst_dvd_read_src_create (GstPushSrc * pushsrc, GstBuffer ** p_buf)
return GST_FLOW_ERROR; return GST_FLOW_ERROR;
} }
case GST_DVD_READ_EOS:{ case GST_DVD_READ_EOS:{
GST_INFO_OBJECT (src, "Reached EOS");
return GST_FLOW_UNEXPECTED; return GST_FLOW_UNEXPECTED;
} }
case GST_DVD_READ_OK:{ case GST_DVD_READ_OK:{
@ -1060,19 +1075,12 @@ gst_dvd_read_src_handle_seek_event (GstDvdReadSrc * src, GstEvent * event)
return FALSE; 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) { if (end_type != GST_SEEK_TYPE_NONE) {
GST_DEBUG_OBJECT (src, "end seek type not supported"); if ((format != chapter_format && format != GST_FORMAT_TIME) ||
return FALSE; end_type != GST_SEEK_TYPE_SET) {
GST_DEBUG_OBJECT (src, "end seek type not supported");
return FALSE;
}
} }
if (cur_type != GST_SEEK_TYPE_SET) { if (cur_type != GST_SEEK_TYPE_SET) {

View 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 may mean that we find some audio blocks lying outside the
segment. Filter them. */ segment. Filter them. */
dvd_demux->segment_filter = TRUE; 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, 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) { if (add_pad) {
gst_pad_set_active (str->pad, TRUE);
gst_element_add_pad (GST_ELEMENT (mpeg_demux), str->pad);
if (dvd_demux->langcodes) { if (dvd_demux->langcodes) {
gchar *t; 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-> gst_structure_get_string (gst_event_get_structure (dvd_demux->
langcodes), t); langcodes), t);
g_free (t); g_free (t);
}
if (lang_code) { GST_DEBUG_OBJECT (mpeg_demux, "adding pad %s with language = %s",
GstTagList *list = gst_tag_list_new (); GST_PAD_NAME (str->pad), (lang_code) ? lang_code : "(unknown)");
gst_tag_list_add (list, GST_TAG_MERGE_REPLACE, gst_pad_set_active (str->pad, TRUE);
GST_TAG_LANGUAGE_CODE, lang_code, NULL); gst_element_add_pad (GST_ELEMENT (mpeg_demux), str->pad);
gst_element_found_tags_for_pad (GST_ELEMENT (mpeg_demux),
str->pad, list); 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; 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); parent_class->synchronise_pads (mpeg_demux, threshold, new_ts);
for (i = 0; i < GST_DVD_DEMUX_NUM_SUBPICTURE_STREAMS; i++) { 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] if (dvd_demux->subpicture_stream[i]
&& (dvd_demux->subpicture_stream[i]->cur_ts < threshold)) { && (dvd_demux->subpicture_stream[i]->cur_ts < threshold)) {
DEMUX_CLASS (mpeg_demux)->sync_stream_to_time (mpeg_demux, 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)) { 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, gst_pad_push_event (outpad, gst_event_new_new_segment (TRUE,
mpeg_parse->current_segment.rate, GST_FORMAT_TIME, mpeg_parse->current_segment.rate, GST_FORMAT_TIME,
last_ts, -1, last_ts)); update_time, mpeg_parse->current_segment.stop, update_time));
} }
} }

View 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_streams_reset_last_flow (demux->private_stream,
GST_MPEG_DEMUX_NUM_PRIVATE_STREAMS); GST_MPEG_DEMUX_NUM_PRIVATE_STREAMS);
break; 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: default:
ret = GST_MPEG_PARSE_CLASS (parent_class)->process_event (mpeg_parse, ret = GST_MPEG_PARSE_CLASS (parent_class)->process_event (mpeg_parse,
event); event);
@ -1011,7 +1020,7 @@ gst_mpeg_demux_send_subbuffer (GstMPEGDemux * mpeg_demux,
GST_FORMAT_BYTES, GST_FORMAT_BYTES,
GST_BUFFER_OFFSET (buffer), GST_FORMAT_TIME, timestamp, 0); 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; outstream->cur_ts = mpeg_parse->current_ts + outstream->scr_offs;
if (size == 0) 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)); GST_LOG_OBJECT (outstream->pad, "flow: %s", gst_flow_get_name (ret));
++outstream->buffers_sent; ++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) && if (GST_CLOCK_TIME_IS_VALID (mpeg_demux->max_gap) &&
GST_CLOCK_TIME_IS_VALID (mpeg_parse->current_ts) && GST_CLOCK_TIME_IS_VALID (mpeg_parse->current_ts) &&
(mpeg_parse->current_ts > mpeg_demux->max_gap)) { (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) GstMPEGStream * stream, GstClockTime last_ts)
{ {
GstMPEGParse *mpeg_parse = GST_MPEG_PARSE (mpeg_demux); 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, gst_pad_push_event (stream->pad, gst_event_new_new_segment (TRUE,
mpeg_parse->current_segment.rate, GST_FORMAT_TIME, 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 #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 gboolean
gst_mpeg_demux_plugin_init (GstPlugin * plugin) gst_mpeg_demux_plugin_init (GstPlugin * plugin)
{ {

View file

@ -206,6 +206,9 @@ struct _GstMPEGDemuxClass {
void gst_mpeg_streams_reset_last_flow (GstMPEGStream *streams[], void gst_mpeg_streams_reset_last_flow (GstMPEGStream *streams[],
guint num); guint num);
void gst_mpeg_streams_reset_cur_ts (GstMPEGStream *streams[],
guint num,
GstClockTime cur_ts);
GType gst_mpeg_demux_get_type (void); GType gst_mpeg_demux_get_type (void);

View file

@ -383,9 +383,16 @@ gst_mpeg_parse_process_event (GstMPEGParse * mpeg_parse, GstEvent * event)
if (CLASS (mpeg_parse)->send_event) { if (CLASS (mpeg_parse)->send_event) {
CLASS (mpeg_parse)->send_event (mpeg_parse, CLASS (mpeg_parse)->send_event (mpeg_parse,
gst_event_new_new_segment (FALSE, rate, GST_FORMAT_TIME, 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; 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, event = gst_event_new_new_segment (FALSE,
mpeg_parse->current_segment.rate, mpeg_parse->current_segment.rate,
GST_FORMAT_TIME, mpeg_parse->current_segment.start, 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); 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. */ /* Convert the value to the desired format. */
if ((res = gst_mpeg_parse_convert (mpeg_parse, src_format, src_value, 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))) { &format, &value))) {
gst_query_set_duration (query, 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. */ /* Convert the value to the desired format. */
if ((res = gst_mpeg_parse_convert (mpeg_parse, src_format, src_value, 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))) { &format, &value))) {
gst_query_set_position (query, 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); gst_query_parse_convert (query, &src_format, &src_value, &format, NULL);
if ((res = gst_mpeg_parse_convert (mpeg_parse, src_format, src_value, 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); gst_query_set_convert (query, src_format, src_value, format, value);
} }
break; break;