summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWim Taymans <wim.taymans@collabora.co.uk>2010-04-30 15:41:05 (GMT)
committerWim Taymans <wim.taymans@collabora.co.uk>2010-04-30 15:43:06 (GMT)
commitf9ca4f60975121f73a0683466bb7dae035cd42e3 (patch)
tree62c9f7232205bdb13cc4a2b9a125a5f5e55ab2b0
parent63931dc80b2b921171ff423f9a54b72adea80104 (diff)
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.
-rw-r--r--ext/ogg/gstoggdemux.c35
-rw-r--r--ext/ogg/gstoggdemux.h1
-rw-r--r--ext/ogg/gstoggstream.c10
-rw-r--r--ext/ogg/gstoggstream.h1
4 files changed, 44 insertions, 3 deletions
diff --git a/ext/ogg/gstoggdemux.c b/ext/ogg/gstoggdemux.c
index a77d2c9..bf4072f 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 2cee7b6..97cbdd3 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 9c3392c..707fa03 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 78b55c0..770fac7 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;