From f9ca4f60975121f73a0683466bb7dae035cd42e3 Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Fri, 30 Apr 2010 17:41:05 +0200 Subject: oggdemux: use bitrate to estimate length in pushmode Parse the bitrate from the various streams. Use the bitrate and the upstream length in bytes to estimate the total stream duration in push mode. --- ext/ogg/gstoggdemux.c | 35 ++++++++++++++++++++++++++++++++--- ext/ogg/gstoggdemux.h | 1 + ext/ogg/gstoggstream.c | 10 ++++++++++ ext/ogg/gstoggstream.h | 1 + 4 files changed, 44 insertions(+), 3 deletions(-) diff --git a/ext/ogg/gstoggdemux.c b/ext/ogg/gstoggdemux.c index a77d2c9e2..bf4072f24 100644 --- a/ext/ogg/gstoggdemux.c +++ b/ext/ogg/gstoggdemux.c @@ -230,7 +230,7 @@ gst_ogg_pad_src_query (GstPad * pad, GstQuery * query) case GST_QUERY_DURATION: { GstFormat format; - gint64 total_time; + gint64 total_time = -1; gst_query_parse_duration (query, &format, NULL); /* can only get position in time */ @@ -241,8 +241,29 @@ gst_ogg_pad_src_query (GstPad * pad, GstQuery * query) /* we must return the total length */ total_time = ogg->total_time; } else { - /* in push mode we can answer the query and we must return -1 */ - total_time = -1; + gint bitrate = ogg->bitrate; + + /* try with length and bitrate */ + if (bitrate > 0) { + GstQuery *uquery; + + /* ask upstream for total length in bytes */ + uquery = gst_query_new_duration (GST_FORMAT_BYTES); + if (gst_pad_peer_query (ogg->sinkpad, uquery)) { + gint64 length; + + gst_query_parse_duration (uquery, NULL, &length); + + /* estimate using the bitrate */ + total_time = + gst_util_uint64_scale (length, 8 * GST_SECOND, bitrate); + + GST_LOG_OBJECT (ogg, + "length: %" G_GINT64_FORMAT ", bitrate %d, total_time %" + GST_TIME_FORMAT, length, bitrate, GST_TIME_ARGS (total_time)); + } + gst_query_unref (uquery); + } } gst_query_set_duration (query, GST_FORMAT_TIME, total_time); @@ -1624,8 +1645,12 @@ gst_ogg_demux_activate_chain (GstOggDemux * ogg, GstOggChain * chain, /* FIXME, should not be called with NULL */ if (chain != NULL) { + gint bitrate; + GST_DEBUG_OBJECT (ogg, "activating chain %p", chain); + bitrate = 0; + /* first add the pads */ for (i = 0; i < chain->streams->len; i++) { GstOggPad *pad; @@ -1633,6 +1658,8 @@ gst_ogg_demux_activate_chain (GstOggDemux * ogg, GstOggChain * chain, pad = g_array_index (chain->streams, GstOggPad *, i); + bitrate += pad->map.bitrate; + if (pad->map.is_skeleton || pad->added || GST_PAD_CAPS (pad) == NULL) continue; @@ -1656,6 +1683,7 @@ gst_ogg_demux_activate_chain (GstOggDemux * ogg, GstOggChain * chain, gst_element_add_pad (GST_ELEMENT (ogg), GST_PAD_CAST (pad)); } + ogg->bitrate = bitrate; } /* after adding the new pads, remove the old pads */ @@ -3293,6 +3321,7 @@ gst_ogg_demux_change_state (GstElement * element, GstStateChange transition) case GST_STATE_CHANGE_READY_TO_PAUSED: ogg_sync_reset (&ogg->sync); ogg->running = FALSE; + ogg->bitrate = 0; ogg->segment_running = FALSE; gst_segment_init (&ogg->segment, GST_FORMAT_TIME); break; diff --git a/ext/ogg/gstoggdemux.h b/ext/ogg/gstoggdemux.h index 2cee7b6b8..97cbdd327 100644 --- a/ext/ogg/gstoggdemux.h +++ b/ext/ogg/gstoggdemux.h @@ -145,6 +145,7 @@ struct _GstOggDemux GMutex *chain_lock; /* we need the lock to protect the chains */ GArray *chains; /* list of chains we know */ GstClockTime total_time; + gint bitrate; /* bitrate of the current chain */ GstOggChain *current_chain; GstOggChain *building_chain; diff --git a/ext/ogg/gstoggstream.c b/ext/ogg/gstoggstream.c index 9c3392c2a..707fa03ea 100644 --- a/ext/ogg/gstoggstream.c +++ b/ext/ogg/gstoggstream.c @@ -304,6 +304,9 @@ setup_theora_mapper (GstOggStream * pad, ogg_packet * packet) pad->n_header_packets = 3; pad->frame_size = 1; + pad->bitrate = GST_READ_UINT24_BE (data + 37); + GST_LOG ("bit rate: %d", pad->bitrate); + if (pad->granulerate_n == 0 || pad->granulerate_d == 0) { GST_WARNING ("frame rate %d/%d", pad->granulerate_n, pad->granulerate_d); return FALSE; @@ -478,6 +481,10 @@ setup_vorbis_mapper (GstOggStream * pad, ogg_packet * packet) pad->last_size = 0; GST_LOG ("sample rate: %d", pad->granulerate_n); + data += 8; + pad->bitrate = GST_READ_UINT32_LE (data); + GST_LOG ("bit rate: %d", pad->bitrate); + pad->n_header_packets = 3; if (pad->granulerate_n == 0) @@ -546,8 +553,11 @@ setup_speex_mapper (GstOggStream * pad, ogg_packet * packet) data += 4 + 4 + 4; chans = GST_READ_UINT32_LE (data); + data += 4; + pad->bitrate = GST_READ_UINT32_LE (data); GST_LOG ("sample rate: %d, channels: %u", pad->granulerate_n, chans); + GST_LOG ("bit rate: %d", pad->bitrate); pad->n_header_packets = GST_READ_UINT32_LE (packet->packet + 68) + 2; pad->frame_size = GST_READ_UINT32_LE (packet->packet + 64) * diff --git a/ext/ogg/gstoggstream.h b/ext/ogg/gstoggstream.h index 78b55c06d..770fac752 100644 --- a/ext/ogg/gstoggstream.h +++ b/ext/ogg/gstoggstream.h @@ -54,6 +54,7 @@ struct _GstOggStream gint n_header_packets_seen; gint64 accumulated_granule; gint frame_size; + gint bitrate; GstCaps *caps; -- cgit v1.2.3