From 607b2e45bf3c40ae2a61f3270bf54fecbda9fdca Mon Sep 17 00:00:00 2001 From: "Ronald S. Bultje" Date: Wed, 20 Oct 2004 16:24:18 +0000 Subject: [PATCH] ext/: Seeking and querying finetune. Original commit message from CVS: * ext/ogg/gstoggdemux.c: (gst_ogg_demux_src_query), (gst_ogg_demux_src_event), (gst_ogg_pad_push): * ext/theora/theoradec.c: (theora_dec_sink_convert), (theora_dec_chain): * ext/vorbis/vorbisdec.c: (vorbis_dec_get_formats), (gst_vorbis_dec_init), (vorbis_dec_convert), (vorbis_dec_chain): Seeking and querying finetune. --- ChangeLog | 10 ++++++++++ ext/ogg/gstoggdemux.c | 43 +++++++++++++++++++++++++----------------- ext/theora/theoradec.c | 19 +++++++++++-------- ext/vorbis/vorbisdec.c | 10 +++++++++- 4 files changed, 56 insertions(+), 26 deletions(-) diff --git a/ChangeLog b/ChangeLog index 8edd53f410f..e71a76be296 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,13 @@ +2004-10-20 Ronald S. Bultje + + * ext/ogg/gstoggdemux.c: (gst_ogg_demux_src_query), + (gst_ogg_demux_src_event), (gst_ogg_pad_push): + * ext/theora/theoradec.c: (theora_dec_sink_convert), + (theora_dec_chain): + * ext/vorbis/vorbisdec.c: (vorbis_dec_get_formats), + (gst_vorbis_dec_init), (vorbis_dec_convert), (vorbis_dec_chain): + Seeking and querying finetune. + 2004-10-20 Thomas Vander Stichele * configure.ac: diff --git a/ext/ogg/gstoggdemux.c b/ext/ogg/gstoggdemux.c index 1cd44d504da..2f57fc080cb 100644 --- a/ext/ogg/gstoggdemux.c +++ b/ext/ogg/gstoggdemux.c @@ -407,14 +407,14 @@ gst_ogg_demux_src_query (GstPad * pad, GstQueryType type, switch (type) { case GST_QUERY_TOTAL:{ - if (cur->length != 0 && cur->length != cur->start) { + if (cur->length != 0 && cur->length > cur->start) { granulepos = cur->length; res = TRUE; } break; } case GST_QUERY_POSITION: - if (cur->length != 0 && cur->length != cur->start) { + if (cur->length != 0 && cur->length > cur->start) { granulepos = cur->known_offset; res = TRUE; } @@ -422,15 +422,18 @@ gst_ogg_demux_src_query (GstPad * pad, GstQueryType type, default: break; } + if (res) { GstFormat fmt = GST_FORMAT_TIME; guint64 base, time; /* subtract base */ - gst_pad_convert (GST_PAD_PEER (pad), - GST_FORMAT_DEFAULT, granulepos, &fmt, &time); - gst_pad_convert (GST_PAD_PEER (pad), - GST_FORMAT_DEFAULT, cur->start, &fmt, &base); + if (!gst_pad_convert (GST_PAD_PEER (pad), + GST_FORMAT_DEFAULT, granulepos, &fmt, &time) || + !gst_pad_convert (GST_PAD_PEER (pad), + GST_FORMAT_DEFAULT, cur->start, &fmt, &base)) + res = FALSE; + time -= base; /* still ok, got a granulepos then */ @@ -438,7 +441,6 @@ gst_ogg_demux_src_query (GstPad * pad, GstQueryType type, case GST_FORMAT_TIME: /* fine, result should be granulepos */ *value = time; - res = TRUE; break; default: /* something we have to ask our peer */ @@ -555,8 +557,11 @@ gst_ogg_demux_src_event (GstPad * pad, GstEvent * event) GST_OGG_SET_STATE (ogg, GST_OGG_STATE_PLAY); FOR_PAD_IN_CURRENT_CHAIN (ogg, pad, - pad->flags |= GST_OGG_PAD_NEEDS_DISCONT; - ); + pad->flags |= GST_OGG_PAD_NEEDS_DISCONT;); + if (GST_EVENT_SEEK_FLAGS (event) & GST_SEEK_FLAG_FLUSH) { + FOR_PAD_IN_CURRENT_CHAIN (ogg, pad, + pad->flags |= GST_OGG_PAD_NEEDS_FLUSH;); + } GST_DEBUG_OBJECT (ogg, "initiating seeking to format %d, offset %" G_GUINT64_FORMAT, format, offset); @@ -629,8 +634,7 @@ gst_ogg_demux_handle_event (GstPad * pad, GstEvent * event) gst_event_unref (event); GST_FLAG_UNSET (ogg, GST_OGG_FLAG_WAIT_FOR_DISCONT); FOR_PAD_IN_CURRENT_CHAIN (ogg, pad, - pad->flags |= GST_OGG_PAD_NEEDS_DISCONT; - ); + pad->flags |= GST_OGG_PAD_NEEDS_DISCONT;); break; default: gst_pad_event_default (pad, event); @@ -916,8 +920,7 @@ _find_chain_get_unknown_part (GstOggDemux * ogg, gint64 * start, gint64 * end) *end = G_MAXINT64; g_assert (ogg->current_chain >= 0); - FOR_PAD_IN_CURRENT_CHAIN (ogg, pad, *start = MAX (*start, pad->end_offset); - ); + FOR_PAD_IN_CURRENT_CHAIN (ogg, pad, *start = MAX (*start, pad->end_offset);); if (ogg->setup_state == SETUP_FIND_LAST_CHAIN) { *end = gst_file_pad_get_length (ogg->sinkpad); @@ -1046,8 +1049,7 @@ _find_streams_check (GstOggDemux * ogg) } else { endpos = G_MAXINT64; FOR_PAD_IN_CHAIN (ogg, pad, ogg->chains->len - 1, - endpos = MIN (endpos, pad->start_offset); - ); + endpos = MIN (endpos, pad->start_offset);); } if (!ogg->seek_skipped || gst_ogg_demux_position (ogg) >= endpos) { /* have we found the endposition for all streams yet? */ @@ -1427,7 +1429,6 @@ gst_ogg_pad_push (GstOggDemux * ogg, GstOggPad * pad) if (pad->start != -1) gst_pad_convert (GST_PAD_PEER (pad->pad), GST_FORMAT_DEFAULT, pad->start, &fmt, &base); - if (pos != -1 && base != -1) { pos -= base; fmt = GST_FORMAT_DEFAULT; @@ -1436,6 +1437,13 @@ gst_ogg_pad_push (GstOggDemux * ogg, GstOggPad * pad) } else pos = -1; + /* send flush if needed */ + if ((pad->flags & GST_OGG_PAD_NEEDS_FLUSH) + && GST_PAD_IS_USABLE (pad->pad)) { + gst_pad_push (pad->pad, GST_DATA (gst_event_new (GST_EVENT_FLUSH))); + pad->flags &= (~GST_OGG_PAD_NEEDS_FLUSH); + } + /* send discont if needed */ if (pos != -1 && (pad->flags & GST_OGG_PAD_NEEDS_DISCONT) && GST_PAD_IS_USABLE (pad->pad)) { @@ -1447,7 +1455,8 @@ gst_ogg_pad_push (GstOggDemux * ogg, GstOggPad * pad) gst_pad_push (pad->pad, GST_DATA (event)); pad->flags &= (~GST_OGG_PAD_NEEDS_DISCONT); - }; + } + /* optimization: use a bufferpool containing the ogg packet? */ buf = gst_pad_alloc_buffer (pad->pad, GST_BUFFER_OFFSET_NONE, diff --git a/ext/theora/theoradec.c b/ext/theora/theoradec.c index 84f1649b7ad..4fbbc6ee5a5 100644 --- a/ext/theora/theoradec.c +++ b/ext/theora/theoradec.c @@ -345,10 +345,17 @@ theora_dec_sink_convert (GstPad * pad, case GST_FORMAT_DEFAULT: { guint ilog = _theora_ilog (dec->info.keyframe_frequency_force - 1); + guint rest; + /* framecount */ *dest_value = src_value * dec->info.fps_numerator / (GST_SECOND * dec->info.fps_denominator); + + /* funny way of calculating granulepos in theora */ + rest = *dest_value / dec->info.keyframe_frequency_force; + *dest_value -= rest; *dest_value <<= ilog; + *dest_value += rest; break; } default: @@ -532,15 +539,11 @@ theora_dec_chain (GstPad * pad, GstData * data) offset_end = GST_BUFFER_OFFSET_END (buf); if (offset_end != -1) { dec->granulepos = offset_end; - /* granulepos to time */ - outtime = GST_SECOND * theora_granule_time (&dec->state, dec->granulepos); - } else { - GstFormat time_format = GST_FORMAT_TIME; - - /* framenumber to time */ - theora_dec_src_convert (dec->srcpad, GST_FORMAT_DEFAULT, - dec->packetno - 3, &time_format, &outtime); } + + /* granulepos to time */ + outtime = GST_SECOND * theora_granule_time (&dec->state, dec->granulepos); + dec->granulepos++; } else { /* we don't know yet */ outtime = -1; diff --git a/ext/vorbis/vorbisdec.c b/ext/vorbis/vorbisdec.c index c5f0747e2ff..9ff26c7ce65 100644 --- a/ext/vorbis/vorbisdec.c +++ b/ext/vorbis/vorbisdec.c @@ -113,7 +113,7 @@ vorbis_dec_get_formats (GstPad * pad) 0 }; static GstFormat sink_formats[] = { - GST_FORMAT_BYTES, + /*GST_FORMAT_BYTES, */ GST_FORMAT_TIME, GST_FORMAT_DEFAULT, /* granulepos or samples */ 0 @@ -153,6 +153,7 @@ gst_vorbis_dec_init (GstVorbisDec * dec) (&vorbis_dec_sink_factory), "sink"); gst_pad_set_chain_function (dec->sinkpad, vorbis_dec_chain); gst_pad_set_formats_function (dec->sinkpad, vorbis_dec_get_formats); + gst_pad_set_convert_function (dec->sinkpad, vorbis_dec_convert); gst_element_add_pad (GST_ELEMENT (dec), dec->sinkpad); dec->srcpad = @@ -184,6 +185,10 @@ vorbis_dec_convert (GstPad * pad, if (dec->packetno < 1) return FALSE; + if (dec->sinkpad == pad && + (src_format == GST_FORMAT_BYTES || *dest_format == GST_FORMAT_BYTES)) + return FALSE; + switch (src_format) { case GST_FORMAT_TIME: switch (*dest_format) { @@ -367,6 +372,9 @@ vorbis_dec_chain (GstPad * pad, GstData * data) packet.granulepos = GST_BUFFER_OFFSET_END (buf); packet.packetno = vd->packetno++; + if (GST_BUFFER_OFFSET_END_IS_VALID (buf)) + vd->granulepos = GST_BUFFER_OFFSET_END (buf);; + /* * FIXME. Is there anyway to know that this is the last packet and * set e_o_s??