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
This commit is contained in:
Vincent Penquerc'h 2016-10-10 13:00:01 +01:00 committed by Sebastian Dröge
parent d94287c047
commit 5a889647ba

View file

@ -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:
{