summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog9
-rw-r--r--gst/flv/gstflvdemux.c32
-rw-r--r--gst/flv/gstflvparse.c31
-rw-r--r--gst/flv/gstflvparse.h2
4 files changed, 74 insertions, 0 deletions
diff --git a/ChangeLog b/ChangeLog
index d377d8b5..bf5cb732 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,14 @@
2008-10-09 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+ * gst/flv/gstflvdemux.c: (gst_flv_demux_loop):
+ * gst/flv/gstflvparse.c: (gst_flv_parse_tag_timestamp):
+ * gst/flv/gstflvparse.h:
+ Get an approximate duration of the file by looking at the timestamp
+ of the last tag in pull mode. If we get (maybe better) duration from
+ metadata later we'll use that instead.
+
+2008-10-09 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+
* gst/flv/gstflvdemux.c: (gst_flv_demux_pull_range),
(gst_flv_demux_pull_tag), (gst_flv_demux_pull_header):
Refactor _pull_range() logic with checks into a seperate function
diff --git a/gst/flv/gstflvdemux.c b/gst/flv/gstflvdemux.c
index dc148507..8cc74f1d 100644
--- a/gst/flv/gstflvdemux.c
+++ b/gst/flv/gstflvdemux.c
@@ -443,6 +443,38 @@ gst_flv_demux_loop (GstPad * pad)
break;
default:
ret = gst_flv_demux_pull_header (pad, demux);
+
+ /* If we parsed the header successfully try to get an
+ * approximate duration by looking at the last tag's timestamp */
+ if (ret == GST_FLOW_OK) {
+ gint64 size;
+ GstFormat fmt = GST_FORMAT_BYTES;
+
+ if (gst_pad_query_peer_duration (pad, &fmt, &size) &&
+ fmt == GST_FORMAT_BYTES && size != -1 && size > FLV_HEADER_SIZE) {
+ GstBuffer *buffer;
+
+ if (gst_flv_demux_pull_range (demux, pad, size - 4, 4,
+ &buffer) == GST_FLOW_OK) {
+ guint32 prev_tag_size =
+ GST_READ_UINT32_BE (GST_BUFFER_DATA (buffer));
+
+ gst_buffer_unref (buffer);
+
+ if (size - 4 - prev_tag_size > FLV_HEADER_SIZE &&
+ prev_tag_size >= 8 &&
+ gst_flv_demux_pull_range (demux, pad,
+ size - prev_tag_size - 4, prev_tag_size,
+ &buffer) == GST_FLOW_OK) {
+ demux->duration =
+ gst_flv_parse_tag_timestamp (demux,
+ GST_BUFFER_DATA (buffer), GST_BUFFER_SIZE (buffer));
+
+ gst_buffer_unref (buffer);
+ }
+ }
+ }
+ }
}
/* pause if something went wrong */
diff --git a/gst/flv/gstflvparse.c b/gst/flv/gstflvparse.c
index fd51cbfe..c5545054 100644
--- a/gst/flv/gstflvparse.c
+++ b/gst/flv/gstflvparse.c
@@ -1006,6 +1006,37 @@ beach:
return ret;
}
+GstClockTime
+gst_flv_parse_tag_timestamp (GstFLVDemux * demux, const guint8 * data,
+ size_t data_size)
+{
+ guint32 pts = 0, pts_ext = 0;
+
+ if (data[0] != 9 && data[0] != 8 && data[0] != 18) {
+ GST_WARNING_OBJECT (demux, "Unsupported tag type %u", data[0]);
+ return GST_CLOCK_TIME_NONE;
+ }
+
+ if (FLV_GET_BEUI24 (data + 1, data_size - 1) != data_size - 11) {
+ GST_WARNING_OBJECT (demux, "Invalid tag");
+ return GST_CLOCK_TIME_NONE;
+ }
+
+ data += 4;
+
+ GST_LOG_OBJECT (demux, "pts bytes %02X %02X %02X %02X", data[0], data[1],
+ data[2], data[3]);
+
+ /* Grab timestamp of tag tag */
+ pts = FLV_GET_BEUI24 (data, data_size);
+ /* read the pts extension to 32 bits integer */
+ pts_ext = GST_READ_UINT8 (data + 3);
+ /* Combine them */
+ pts |= pts_ext << 24;
+
+ return pts * GST_MSECOND;
+}
+
GstFlowReturn
gst_flv_parse_tag_type (GstFLVDemux * demux, const guint8 * data,
size_t data_size)
diff --git a/gst/flv/gstflvparse.h b/gst/flv/gstflvparse.h
index 7b9d498e..0dfeaa97 100644
--- a/gst/flv/gstflvparse.h
+++ b/gst/flv/gstflvparse.h
@@ -38,5 +38,7 @@ GstFlowReturn gst_flv_parse_tag_type (GstFLVDemux * demux, const guint8 * data,
GstFlowReturn gst_flv_parse_header (GstFLVDemux * demux, const guint8 * data,
size_t data_size);
+GstClockTime gst_flv_parse_tag_timestamp (GstFLVDemux *demux, const guint8 *data, size_t data_size);
+
G_END_DECLS
#endif /* __FLV_PARSE_H__ */