diff options
author | Vincent Penquerc'h <vincent.penquerch@collabora.co.uk> | 2016-10-10 13:00:01 +0100 |
---|---|---|
committer | Sebastian Dröge <sebastian@centricular.com> | 2016-11-01 20:10:23 +0200 |
commit | 5a889647ba202d1fe8d902eef4251ca6ed1283bd (patch) | |
tree | 4161b5a3a034c6563c4ba1186a21d63d610863a8 | |
parent | d94287c0474a3dd6430108c1aa5a603ce2128e5c (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.c | 74 |
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: { |