diff --git a/ext/ogg/gstoggdemux.c b/ext/ogg/gstoggdemux.c index a77d2c9e25..bf4072f24f 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 2cee7b6b8d..97cbdd3279 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 9c3392c2af..707fa03ea6 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 78b55c06db..770fac7523 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;