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.
This commit is contained in:
Wim Taymans 2010-04-30 17:41:05 +02:00
parent 63931dc80b
commit f9ca4f6097
4 changed files with 44 additions and 3 deletions

View file

@ -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;

View file

@ -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;

View file

@ -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) *

View file

@ -54,6 +54,7 @@ struct _GstOggStream
gint n_header_packets_seen;
gint64 accumulated_granule;
gint frame_size;
gint bitrate;
GstCaps *caps;