summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVincent Penquerc'h <vincent.penquerch@collabora.co.uk>2016-10-10 13:00:01 +0100
committerSebastian Dröge <sebastian@centricular.com>2016-11-01 20:10:23 +0200
commit5a889647ba202d1fe8d902eef4251ca6ed1283bd (patch)
tree4161b5a3a034c6563c4ba1186a21d63d610863a8
parentd94287c0474a3dd6430108c1aa5a603ce2128e5c (diff)
qtdemux: extract interlaced information from jpeg video
This information is hidden in a small chunk of data. Format found at https://developer.apple.com/standards/qtff-2001.pdf, page 92, "Video Sample Description", under table 3.1. https://bugzilla.gnome.org/show_bug.cgi?id=767771
-rw-r--r--gst/isomp4/qtdemux.c74
1 files changed, 74 insertions, 0 deletions
diff --git a/gst/isomp4/qtdemux.c b/gst/isomp4/qtdemux.c
index 8b7b0f534..183f74cd7 100644
--- a/gst/isomp4/qtdemux.c
+++ b/gst/isomp4/qtdemux.c
@@ -10022,6 +10022,80 @@ qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak)
}
break;
}
+ case FOURCC_jpeg:
+ {
+ /* https://developer.apple.com/standards/qtff-2001.pdf,
+ * page 92, "Video Sample Description", under table 3.1 */
+ GstByteReader br;
+
+ const off_t compressor_offset =
+ 16 + 4 + 4 * 3 + 2 * 2 + 2 * 4 + 4 + 2;
+ const off_t min_size = compressor_offset + 32 + 2 + 2;
+ GNode *jpeg;
+ guint32 len;
+ guint16 color_table_id;
+ gboolean ok;
+
+ GST_DEBUG_OBJECT (qtdemux, "found jpeg");
+
+ /* recover information on interlaced/progressive */
+ jpeg = qtdemux_tree_get_child_by_type (stsd, FOURCC_jpeg);
+ if (!jpeg)
+ break;
+
+ len = QT_UINT32 (jpeg->data);
+ GST_DEBUG_OBJECT (qtdemux, "Found jpeg: len %u, need %lu", len,
+ min_size);
+ if (len >= min_size) {
+ gst_byte_reader_init (&br, jpeg->data, len);
+
+ gst_byte_reader_skip (&br, compressor_offset + 32 + 2);
+ gst_byte_reader_get_uint16_le (&br, &color_table_id);
+ if (color_table_id != 0) {
+ /* the spec says there can be concatenated chunks in the data, and we want
+ * to find one called field. Walk through them. */
+ off_t offset = min_size;
+ while (offset + 8 < len) {
+ guint32 size, tag;
+ ok = gst_byte_reader_get_uint32_le (&br, &size);
+ ok &= gst_byte_reader_get_uint32_le (&br, &tag);
+ if (!ok || size < 8) {
+ GST_WARNING_OBJECT (qtdemux,
+ "Failed to walk optional chunk list");
+ break;
+ }
+ GST_DEBUG_OBJECT (qtdemux,
+ "Found optional %4.4s chunk, size %u", (const char *) &tag,
+ size);
+ if (tag == FOURCC_fiel) {
+ guint8 n_fields, ordering;
+ gst_byte_reader_get_uint8 (&br, &n_fields);
+ gst_byte_reader_get_uint8 (&br, &ordering);
+ if (n_fields == 1 || n_fields == 2) {
+ GST_DEBUG_OBJECT (qtdemux,
+ "Found fiel tag with %u fields, ordering %u", n_fields,
+ ordering);
+ if (n_fields == 2)
+ gst_caps_set_simple (stream->caps, "interlace-mode",
+ G_TYPE_STRING, "interleaved", NULL);
+ } else {
+ GST_WARNING_OBJECT (qtdemux,
+ "Found fiel tag with invalid fields (%u)", n_fields);
+ }
+ }
+ offset += size;
+ }
+ } else {
+ GST_DEBUG_OBJECT (qtdemux,
+ "Color table ID is 0, not trying to get interlacedness");
+ }
+ } else {
+ GST_WARNING_OBJECT (qtdemux,
+ "Length of jpeg chunk is too small, not trying to get interlacedness");
+ }
+
+ break;
+ }
case FOURCC_SVQ3:
case FOURCC_VP31:
{