ext/ogg/gstoggdemux.c: Faster seeking.

Original commit message from CVS:
* ext/ogg/gstoggdemux.c: (gst_ogg_demux_src_query),
(gst_ogg_demux_src_event), (gst_ogg_pad_populate),
(_read_bos_process), (gst_ogg_demux_iterate), (gst_ogg_pad_new):
Faster seeking.
* ext/theora/theoradec.c: (theora_dec_sink_convert):
Time-to-default conversion.
* ext/vorbis/vorbisdec.c: (vorbis_dec_chain):
Don't error on unknown packets, just skip. We should probably
read them if we want to support chained ogg.
This commit is contained in:
Ronald S. Bultje 2004-10-18 15:23:41 +00:00
parent c9db916d3e
commit b5ce9ade82
4 changed files with 87 additions and 27 deletions

View file

@ -1,3 +1,15 @@
2004-10-18 Ronald S. Bultje <rbultje@ronald.bitfreak.net>
* ext/ogg/gstoggdemux.c: (gst_ogg_demux_src_query),
(gst_ogg_demux_src_event), (gst_ogg_pad_populate),
(_read_bos_process), (gst_ogg_demux_iterate), (gst_ogg_pad_new):
Faster seeking.
* ext/theora/theoradec.c: (theora_dec_sink_convert):
Time-to-default conversion.
* ext/vorbis/vorbisdec.c: (vorbis_dec_chain):
Don't error on unknown packets, just skip. We should probably
read them if we want to support chained ogg.
2004-10-18 Wim Taymans <wim@fluendo.com> 2004-10-18 Wim Taymans <wim@fluendo.com>
* configure.ac: * configure.ac:

View file

@ -79,6 +79,7 @@ typedef struct
guint64 known_offset; /* last known offset */ guint64 known_offset; /* last known offset */
gint64 packetno; /* number of next expected packet */ gint64 packetno; /* number of next expected packet */
guint64 start; /* first valid granulepos */
guint64 length; /* length of stream or 0 */ guint64 length; /* length of stream or 0 */
glong pages; /* number of pages in stream or 0 */ glong pages; /* number of pages in stream or 0 */
@ -406,14 +407,14 @@ gst_ogg_demux_src_query (GstPad * pad, GstQueryType type,
switch (type) { switch (type) {
case GST_QUERY_TOTAL:{ case GST_QUERY_TOTAL:{
if (cur->length != 0) { if (cur->length != 0 && cur->length != cur->start) {
granulepos = cur->length; granulepos = cur->length;
res = TRUE; res = TRUE;
} }
break; break;
} }
case GST_QUERY_POSITION: case GST_QUERY_POSITION:
if (cur->length != 0) { if (cur->length != 0 && cur->length != cur->start) {
granulepos = cur->known_offset; granulepos = cur->known_offset;
res = TRUE; res = TRUE;
} }
@ -434,6 +435,8 @@ gst_ogg_demux_src_query (GstPad * pad, GstQueryType type,
if (GST_PAD_PEER (pad)) { if (GST_PAD_PEER (pad)) {
res = gst_pad_convert (GST_PAD_PEER (pad), res = gst_pad_convert (GST_PAD_PEER (pad),
GST_FORMAT_DEFAULT, granulepos, format, value); GST_FORMAT_DEFAULT, granulepos, format, value);
} else {
res = FALSE;
} }
break; break;
} }
@ -519,21 +522,27 @@ gst_ogg_demux_src_event (GstPad * pad, GstEvent * event)
goto error; goto error;
} }
if (offset < position) { if (offset < 0)
/* seek backwards, move to beginning of file */ offset = 0;
if (gst_file_pad_seek (ogg->sinkpad, 0, GST_SEEK_METHOD_SET) != 0) position = offset;
if (format != GST_FORMAT_DEFAULT) {
GstFormat fmt = GST_FORMAT_DEFAULT;
if (!gst_pad_convert (GST_PAD_PEER (pad), format,
offset, &fmt, &position))
goto error; goto error;
ogg_sync_clear (&ogg->sync);
} else {
/* seek forwards flush and skip */
FOR_PAD_IN_CURRENT_CHAIN (ogg, pad, if (GST_PAD_IS_USABLE (pad->pad))
gst_pad_push (pad->pad,
GST_DATA (gst_event_new (GST_EVENT_FLUSH))););
} }
GST_OGG_SET_STATE (ogg, GST_OGG_STATE_SEEK); if (gst_file_pad_seek (ogg->sinkpad,
gst_file_pad_get_length (ogg->sinkpad) * (position - cur->start) /
(cur->length - cur->start), GST_SEEK_METHOD_SET) != 0)
goto error;
ogg_sync_clear (&ogg->sync);
GST_OGG_SET_STATE (ogg, GST_OGG_STATE_PLAY);
FOR_PAD_IN_CURRENT_CHAIN (ogg, pad, FOR_PAD_IN_CURRENT_CHAIN (ogg, pad,
pad->flags |= GST_OGG_PAD_NEEDS_DISCONT;); pad->flags |= GST_OGG_PAD_NEEDS_DISCONT;
);
GST_DEBUG_OBJECT (ogg, GST_DEBUG_OBJECT (ogg,
"initiating seeking to format %d, offset %" G_GUINT64_FORMAT, format, "initiating seeking to format %d, offset %" G_GUINT64_FORMAT, format,
offset); offset);
@ -606,7 +615,8 @@ gst_ogg_demux_handle_event (GstPad * pad, GstEvent * event)
gst_event_unref (event); gst_event_unref (event);
GST_FLAG_UNSET (ogg, GST_OGG_FLAG_WAIT_FOR_DISCONT); GST_FLAG_UNSET (ogg, GST_OGG_FLAG_WAIT_FOR_DISCONT);
FOR_PAD_IN_CURRENT_CHAIN (ogg, pad, FOR_PAD_IN_CURRENT_CHAIN (ogg, pad,
pad->flags |= GST_OGG_PAD_NEEDS_DISCONT;); pad->flags |= GST_OGG_PAD_NEEDS_DISCONT;
);
break; break;
default: default:
gst_pad_event_default (pad, event); gst_pad_event_default (pad, event);
@ -690,6 +700,9 @@ gst_ogg_pad_populate (GstOggDemux * ogg, GstOggPad * pad, ogg_page * page)
{ {
gint64 start, end; gint64 start, end;
if (pad->start > ogg_page_granulepos (page) && ogg_page_granulepos (page) > 0) {
pad->start = ogg_page_granulepos (page);
}
if (pad->length < ogg_page_granulepos (page)) if (pad->length < ogg_page_granulepos (page))
pad->length = ogg_page_granulepos (page); pad->length = ogg_page_granulepos (page);
if (pad->pages < ogg_page_pageno (page)) if (pad->pages < ogg_page_pageno (page))
@ -851,10 +864,17 @@ _read_bos_process (GstOggDemux * ogg, ogg_page * page)
CURRENT_CHAIN (ogg)->pads = CURRENT_CHAIN (ogg)->pads =
g_slist_prepend (CURRENT_CHAIN (ogg)->pads, pad); g_slist_prepend (CURRENT_CHAIN (ogg)->pads, pad);
} else { } else {
gboolean have_all_first_pages = TRUE;
if (CURRENT_CHAIN (ogg)->pads == NULL) { if (CURRENT_CHAIN (ogg)->pads == NULL) {
GST_ERROR_OBJECT (ogg, "broken ogg stream, chain has no BOS pages"); GST_ERROR_OBJECT (ogg, "broken ogg stream, chain has no BOS pages");
return FALSE; return FALSE;
} }
FOR_PAD_IN_CURRENT_CHAIN (ogg, pad, if (pad->start == (guint64) - 1)
have_all_first_pages = FALSE;);
if (have_all_first_pages) {
GST_DEBUG_OBJECT (ogg, GST_DEBUG_OBJECT (ogg,
"SETUP_READ_BOS: no more bos pages, going to find end of stream"); "SETUP_READ_BOS: no more bos pages, going to find end of stream");
if (ogg->setup_state == SETUP_READ_FIRST_BOS) { if (ogg->setup_state == SETUP_READ_FIRST_BOS) {
@ -865,6 +885,12 @@ _read_bos_process (GstOggDemux * ogg, ogg_page * page)
} else { } else {
return gst_ogg_demux_set_setup_state (ogg, SETUP_FIND_END_OF_STREAMS); return gst_ogg_demux_set_setup_state (ogg, SETUP_FIND_END_OF_STREAMS);
} }
} else {
GstOggPad *pad =
gst_ogg_pad_get_in_current_chain (ogg, ogg_page_serialno (page));
gst_ogg_pad_populate (ogg, pad, page);
}
} }
return TRUE; return TRUE;
} }
@ -876,7 +902,8 @@ _find_chain_get_unknown_part (GstOggDemux * ogg, gint64 * start, gint64 * end)
*end = G_MAXINT64; *end = G_MAXINT64;
g_assert (ogg->current_chain >= 0); 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) { if (ogg->setup_state == SETUP_FIND_LAST_CHAIN) {
*end = gst_file_pad_get_length (ogg->sinkpad); *end = gst_file_pad_get_length (ogg->sinkpad);
@ -1005,7 +1032,8 @@ _find_streams_check (GstOggDemux * ogg)
} else { } else {
endpos = G_MAXINT64; endpos = G_MAXINT64;
FOR_PAD_IN_CHAIN (ogg, pad, ogg->chains->len - 1, 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) { if (!ogg->seek_skipped || gst_ogg_demux_position (ogg) >= endpos) {
/* have we found the endposition for all streams yet? */ /* have we found the endposition for all streams yet? */
@ -1079,6 +1107,7 @@ gst_ogg_demux_iterate (GstFilePad * pad)
GST_DEBUG_OBJECT (ogg, "no data available, doing nothing"); GST_DEBUG_OBJECT (ogg, "no data available, doing nothing");
return; return;
} }
return;
} }
GST_LOG_OBJECT (ogg, "queueing next %u bytes of data", available); GST_LOG_OBJECT (ogg, "queueing next %u bytes of data", available);
data = (guint8 *) ogg_sync_buffer (&ogg->sync, available); data = (guint8 *) ogg_sync_buffer (&ogg->sync, available);
@ -1196,6 +1225,7 @@ gst_ogg_pad_new (GstOggDemux * ogg, int serial)
GST_LOG_OBJECT (ogg, "created new ogg src %p for stream with serial %d", ret, GST_LOG_OBJECT (ogg, "created new ogg src %p for stream with serial %d", ret,
serial); serial);
ret->start_offset = ret->end_offset = -1; ret->start_offset = ret->end_offset = -1;
ret->start = -1;
ret->start_found = ret->end_found = FALSE; ret->start_found = ret->end_found = FALSE;
return ret; return ret;

View file

@ -339,6 +339,24 @@ theora_dec_sink_convert (GstPad * pad,
} }
break; break;
} }
case GST_FORMAT_TIME:
{
switch (*dest_format) {
case GST_FORMAT_DEFAULT:
{
guint ilog = _theora_ilog (dec->info.keyframe_frequency_force - 1);
*dest_value = src_value * dec->info.fps_numerator /
(GST_SECOND * dec->info.fps_denominator);
*dest_value <<= ilog;
break;
}
default:
res = FALSE;
break;
}
break;
}
default: default:
res = FALSE; res = FALSE;
} }

View file

@ -378,9 +378,9 @@ vorbis_dec_chain (GstPad * pad, GstData * data)
/* header packet */ /* header packet */
if (packet.packet[0] / 2 != packet.packetno) { if (packet.packet[0] / 2 != packet.packetno) {
/* FIXME: just skip? */ /* FIXME: just skip? */
GST_ELEMENT_ERROR (GST_ELEMENT (vd), STREAM, DECODE, GST_WARNING_OBJECT (GST_ELEMENT (vd),
(NULL), ("unexpected packet type %d, expected %d", "unexpected packet type %d, expected %d",
(gint) packet.packet[0], (gint) packet.packetno)); (gint) packet.packet[0], (gint) packet.packetno);
gst_data_unref (data); gst_data_unref (data);
return; return;
} }