summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKishore Arepalli <kishore.arepalli@gmail.com>2010-12-11 17:46:17 +0100
committerSebastian Dröge <sebastian.droege@collabora.co.uk>2010-12-11 17:46:17 +0100
commit5d9c8996da5e86a2faf66c8e94fb9524efbeb7fb (patch)
treee9e2bb137f840fa106bd9f224e28adffeb88c164
parentd73440cb976d8b2ae51f231f19c10d7eaddb6074 (diff)
qtdemux: Implement CONVERT and FORMATS query
Fixes bug #636784.
-rw-r--r--gst/qtdemux/qtdemux.c127
1 files changed, 101 insertions, 26 deletions
diff --git a/gst/qtdemux/qtdemux.c b/gst/qtdemux/qtdemux.c
index a744fbc00..5a6fb7e1f 100644
--- a/gst/qtdemux/qtdemux.c
+++ b/gst/qtdemux/qtdemux.c
@@ -387,6 +387,13 @@ GST_BOILERPLATE (GstQTDemux, gst_qtdemux, GstQTDemux, GST_TYPE_ELEMENT);
static void gst_qtdemux_dispose (GObject * object);
+static guint32
+gst_qtdemux_find_index_linear (GstQTDemux * qtdemux, QtDemuxStream * str,
+ guint64 media_time);
+static guint32
+gst_qtdemux_find_index_for_given_media_offset_linear (GstQTDemux * qtdemux,
+ QtDemuxStream * str, gint64 media_offset);
+
static void gst_qtdemux_set_index (GstElement * element, GstIndex * index);
static GstIndex *gst_qtdemux_get_index (GstElement * element);
static GstStateChangeReturn gst_qtdemux_change_state (GstElement * element,
@@ -561,47 +568,57 @@ gst_qtdemux_pull_atom (GstQTDemux * qtdemux, guint64 offset, guint64 size,
return flow;
}
-#if 0
+#if 1
static gboolean
gst_qtdemux_src_convert (GstPad * pad, GstFormat src_format, gint64 src_value,
- GstFormat * dest_format, gint64 * dest_value)
+ GstFormat dest_format, gint64 * dest_value)
{
gboolean res = TRUE;
QtDemuxStream *stream = gst_pad_get_element_private (pad);
+ GstQTDemux *qtdemux = GST_QTDEMUX (gst_pad_get_parent (pad));
+ gint32 index;
- if (stream->subtype == GST_MAKE_FOURCC ('v', 'i', 'd', 'e') &&
- (src_format == GST_FORMAT_BYTES || *dest_format == GST_FORMAT_BYTES))
+ if (stream->subtype != FOURCC_vide)
return FALSE;
switch (src_format) {
case GST_FORMAT_TIME:
- switch (*dest_format) {
- case GST_FORMAT_BYTES:
- *dest_value = src_value * 1; /* FIXME */
- break;
- case GST_FORMAT_DEFAULT:
- *dest_value = src_value * 1; /* FIXME */
+ switch (dest_format) {
+ case GST_FORMAT_BYTES:{
+ index = gst_qtdemux_find_index_linear (qtdemux, stream, src_value);
+ if (-1 == index)
+ return FALSE;
+
+ *dest_value = stream->samples[index].offset;
+
+ GST_DEBUG_OBJECT (qtdemux, "Format Conversion Time->Offset :%"
+ GST_TIME_FORMAT "->%" G_GUINT64_FORMAT,
+ GST_TIME_ARGS (src_value), *dest_value);
break;
+ }
default:
res = FALSE;
break;
}
break;
case GST_FORMAT_BYTES:
- switch (*dest_format) {
- case GST_FORMAT_TIME:
- *dest_value = src_value * 1; /* FIXME */
- break;
- default:
- res = FALSE;
- break;
- }
- break;
- case GST_FORMAT_DEFAULT:
- switch (*dest_format) {
- case GST_FORMAT_TIME:
- *dest_value = src_value * 1; /* FIXME */
+ switch (dest_format) {
+ case GST_FORMAT_TIME:{
+ index =
+ gst_qtdemux_find_index_for_given_media_offset_linear (qtdemux,
+ stream, src_value);
+
+ if (-1 == index)
+ return FALSE;
+
+ *dest_value =
+ gst_util_uint64_scale (stream->samples[index].timestamp,
+ GST_SECOND, stream->timescale);
+ GST_DEBUG_OBJECT (qtdemux, "Format Conversion Offset->Time :%"
+ G_GUINT64_FORMAT "->%" GST_TIME_FORMAT,
+ src_value, GST_TIME_ARGS (*dest_value));
break;
+ }
default:
res = FALSE;
break;
@@ -621,6 +638,8 @@ gst_qtdemux_get_src_query_types (GstPad * pad)
static const GstQueryType src_types[] = {
GST_QUERY_POSITION,
GST_QUERY_DURATION,
+ GST_QUERY_CONVERT,
+ GST_QUERY_FORMATS,
GST_QUERY_SEEKING,
0
};
@@ -675,6 +694,24 @@ gst_qtdemux_handle_src_query (GstPad * pad, GstQuery * query)
}
break;
}
+ case GST_QUERY_CONVERT:{
+ GstFormat src_fmt, dest_fmt;
+ gint64 src_value, dest_value;
+
+ gst_query_parse_convert (query, &src_fmt, &src_value, &dest_fmt, NULL);
+
+ res = gst_qtdemux_src_convert (pad,
+ src_fmt, src_value, dest_fmt, &dest_value);
+ if (res) {
+ gst_query_set_convert (query, src_fmt, src_value, dest_fmt, dest_value);
+ res = TRUE;
+ }
+ break;
+ }
+ case GST_QUERY_FORMATS:
+ gst_query_set_formats (query, 2, GST_FORMAT_TIME, GST_FORMAT_BYTES);
+ res = TRUE;
+ break;
case GST_QUERY_SEEKING:{
GstFormat fmt;
gboolean seekable;
@@ -825,6 +862,44 @@ gst_qtdemux_find_index (GstQTDemux * qtdemux, QtDemuxStream * str,
return index;
}
+
+
+/* find the index of the sample that includes the data for @media_offset using a
+ * linear search
+ *
+ * Returns the index of the sample.
+ */
+static guint32
+gst_qtdemux_find_index_for_given_media_offset_linear (GstQTDemux * qtdemux,
+ QtDemuxStream * str, gint64 media_offset)
+{
+ QtDemuxSample *result = str->samples;
+ guint32 index = 0;
+
+ if (media_offset == result->offset)
+ return index;
+
+ result++;
+ while (index < str->n_samples - 1) {
+ if (!qtdemux_parse_samples (qtdemux, str, index + 1))
+ goto parse_failed;
+
+ if (media_offset < result->offset)
+ break;
+
+ index++;
+ result++;
+ }
+ return index;
+
+ /* ERRORS */
+parse_failed:
+ {
+ GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!", index + 1);
+ return -1;
+ }
+}
+
/* find the index of the sample that includes the data for @media_time using a
* linear search, and keeping in mind that not all samples may have been parsed
* yet. If possible, it will delegate to binary search.
@@ -5123,7 +5198,7 @@ qtdemux_stbl_init (GstQTDemux * qtdemux, QtDemuxStream * stream, GNode * stbl)
/* sync sample atom */
stream->stps_present = FALSE;
if ((stream->stss_present =
- !!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stss,
+ ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stss,
&stream->stss) ? TRUE : FALSE) == TRUE) {
/* copy atom data into a new buffer for later use */
stream->stss.data = g_memdup (stream->stss.data, stream->stss.size);
@@ -5141,7 +5216,7 @@ qtdemux_stbl_init (GstQTDemux * qtdemux, QtDemuxStream * stream, GNode * stbl)
/* partial sync sample atom */
if ((stream->stps_present =
- !!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stps,
+ ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stps,
&stream->stps) ? TRUE : FALSE) == TRUE) {
/* copy atom data into a new buffer for later use */
stream->stps.data = g_memdup (stream->stps.data, stream->stps.size);
@@ -5261,7 +5336,7 @@ qtdemux_stbl_init (GstQTDemux * qtdemux, QtDemuxStream * stream, GNode * stbl)
/* composition time-to-sample */
if ((stream->ctts_present =
- !!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_ctts,
+ ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_ctts,
&stream->ctts) ? TRUE : FALSE) == TRUE) {
/* copy atom data into a new buffer for later use */
stream->ctts.data = g_memdup (stream->ctts.data, stream->ctts.size);