qtdemux: Use already parsed codec data boxes instead of parsing a second time
And parse common boxes in a central place. Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8929>
This commit is contained in:
parent
cba7ce1228
commit
8a30c6b13b
@ -14541,7 +14541,6 @@ qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak, guint32 * mvhd_matrix)
|
|||||||
GNode *minf;
|
GNode *minf;
|
||||||
GNode *stbl;
|
GNode *stbl;
|
||||||
GNode *stsd;
|
GNode *stsd;
|
||||||
GNode *mp4a;
|
|
||||||
GNode *esds;
|
GNode *esds;
|
||||||
GNode *tref;
|
GNode *tref;
|
||||||
GNode *udta;
|
GNode *udta;
|
||||||
@ -14805,6 +14804,7 @@ qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak, guint32 * mvhd_matrix)
|
|||||||
GNode *colr;
|
GNode *colr;
|
||||||
GNode *fiel;
|
GNode *fiel;
|
||||||
GNode *pasp;
|
GNode *pasp;
|
||||||
|
GNode *btrt;
|
||||||
guint32 version;
|
guint32 version;
|
||||||
gboolean gray;
|
gboolean gray;
|
||||||
gint depth, palette_size, palette_count;
|
gint depth, palette_size, palette_count;
|
||||||
@ -14978,6 +14978,7 @@ qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak, guint32 * mvhd_matrix)
|
|||||||
pasp = qtdemux_tree_get_child_by_type (stsd_entry, FOURCC_pasp);
|
pasp = qtdemux_tree_get_child_by_type (stsd_entry, FOURCC_pasp);
|
||||||
colr = qtdemux_tree_get_child_by_type (stsd_entry, FOURCC_colr);
|
colr = qtdemux_tree_get_child_by_type (stsd_entry, FOURCC_colr);
|
||||||
fiel = qtdemux_tree_get_child_by_type (stsd_entry, FOURCC_fiel);
|
fiel = qtdemux_tree_get_child_by_type (stsd_entry, FOURCC_fiel);
|
||||||
|
btrt = qtdemux_tree_get_child_by_type (stsd_entry, FOURCC_btrt);
|
||||||
|
|
||||||
if (pasp) {
|
if (pasp) {
|
||||||
const guint8 *pasp_data = (const guint8 *) pasp->data;
|
const guint8 *pasp_data = (const guint8 *) pasp->data;
|
||||||
@ -15035,87 +15036,18 @@ qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak, guint32 * mvhd_matrix)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (esds) {
|
if (btrt) {
|
||||||
gst_qtdemux_handle_esds (qtdemux, stream, entry, esds,
|
const guint8 *data;
|
||||||
stream->stream_tags);
|
guint32 size;
|
||||||
} else {
|
|
||||||
switch (fourcc) {
|
|
||||||
case FOURCC_H264:
|
|
||||||
case FOURCC_avc1:
|
|
||||||
case FOURCC_avc3:
|
|
||||||
{
|
|
||||||
guint32 len = QT_UINT32 (stsd_entry_data);
|
|
||||||
len = len <= 0x56 ? 0 : len - 0x56;
|
|
||||||
const guint8 *avc_data = stsd_entry_data + 0x56;
|
|
||||||
|
|
||||||
/* find avcC */
|
data = btrt->data;
|
||||||
while (len >= 8) {
|
size = QT_UINT32 (data);
|
||||||
guint32 size = QT_UINT32 (avc_data);
|
|
||||||
|
|
||||||
if (size < 8 || size > len)
|
|
||||||
break;
|
|
||||||
|
|
||||||
switch (QT_FOURCC (avc_data + 4)) {
|
|
||||||
case FOURCC_avcC:
|
|
||||||
{
|
|
||||||
/* parse, if found */
|
|
||||||
GstBuffer *buf;
|
|
||||||
|
|
||||||
if (size < 8 + 1)
|
|
||||||
break;
|
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (qtdemux, "found avcC codec_data in stsd");
|
|
||||||
|
|
||||||
/* First 4 bytes are the length of the atom, the next 4 bytes
|
|
||||||
* are the fourcc, the next 1 byte is the version, and the
|
|
||||||
* subsequent bytes are profile_tier_level structure like data. */
|
|
||||||
gst_codec_utils_h264_caps_set_level_and_profile (entry->caps,
|
|
||||||
avc_data + 8 + 1, size - 8 - 1);
|
|
||||||
buf = gst_buffer_new_and_alloc (size - 8);
|
|
||||||
gst_buffer_fill (buf, 0, avc_data + 8, size - 8);
|
|
||||||
gst_caps_set_simple (entry->caps,
|
|
||||||
"codec_data", GST_TYPE_BUFFER, buf, NULL);
|
|
||||||
gst_buffer_unref (buf);
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case FOURCC_strf:
|
|
||||||
{
|
|
||||||
GstBuffer *buf;
|
|
||||||
|
|
||||||
if (size < 8 + 40 + 1)
|
|
||||||
break;
|
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (qtdemux, "found strf codec_data in stsd");
|
|
||||||
|
|
||||||
/* First 4 bytes are the length of the atom, the next 4 bytes
|
|
||||||
* are the fourcc, next 40 bytes are BITMAPINFOHEADER,
|
|
||||||
* next 1 byte is the version, and the
|
|
||||||
* subsequent bytes are sequence parameter set like data. */
|
|
||||||
|
|
||||||
gst_codec_utils_h264_caps_set_level_and_profile
|
|
||||||
(entry->caps, avc_data + 8 + 40 + 1, size - 8 - 40 - 1);
|
|
||||||
|
|
||||||
buf = gst_buffer_new_and_alloc (size - 8 - 40);
|
|
||||||
gst_buffer_fill (buf, 0, avc_data + 8 + 40, size - 8 - 40);
|
|
||||||
gst_caps_set_simple (entry->caps,
|
|
||||||
"codec_data", GST_TYPE_BUFFER, buf, NULL);
|
|
||||||
gst_buffer_unref (buf);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case FOURCC_btrt:
|
|
||||||
{
|
|
||||||
guint avg_bitrate, max_bitrate;
|
|
||||||
|
|
||||||
/* bufferSizeDB, maxBitrate and avgBitrate - 4 bytes each */
|
/* bufferSizeDB, maxBitrate and avgBitrate - 4 bytes each */
|
||||||
if (size < 8 + 12)
|
if (size >= 8 + 12) {
|
||||||
break;
|
|
||||||
|
|
||||||
max_bitrate = QT_UINT32 (avc_data + 8 + 4);
|
guint32 max_bitrate = QT_UINT32 (data + 8 + 4);
|
||||||
avg_bitrate = QT_UINT32 (avc_data + 8 + 8);
|
guint32 avg_bitrate = QT_UINT32 (data + 8 + 8);
|
||||||
|
|
||||||
if (!max_bitrate && !avg_bitrate)
|
|
||||||
break;
|
|
||||||
|
|
||||||
/* Some muxers seem to swap the average and maximum bitrates
|
/* Some muxers seem to swap the average and maximum bitrates
|
||||||
* (I'm looking at you, YouTube), so we swap for sanity. */
|
* (I'm looking at you, YouTube), so we swap for sanity. */
|
||||||
@ -15125,7 +15057,6 @@ qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak, guint32 * mvhd_matrix)
|
|||||||
avg_bitrate = max_bitrate;
|
avg_bitrate = max_bitrate;
|
||||||
max_bitrate = temp;
|
max_bitrate = temp;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (max_bitrate > 0 && max_bitrate < G_MAXUINT32) {
|
if (max_bitrate > 0 && max_bitrate < G_MAXUINT32) {
|
||||||
gst_tag_list_add (stream->stream_tags,
|
gst_tag_list_add (stream->stream_tags,
|
||||||
GST_TAG_MERGE_REPLACE, GST_TAG_MAXIMUM_BITRATE,
|
GST_TAG_MERGE_REPLACE, GST_TAG_MAXIMUM_BITRATE,
|
||||||
@ -15133,19 +15064,74 @@ qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak, guint32 * mvhd_matrix)
|
|||||||
}
|
}
|
||||||
if (avg_bitrate > 0 && avg_bitrate < G_MAXUINT32) {
|
if (avg_bitrate > 0 && avg_bitrate < G_MAXUINT32) {
|
||||||
gst_tag_list_add (stream->stream_tags,
|
gst_tag_list_add (stream->stream_tags,
|
||||||
GST_TAG_MERGE_REPLACE, GST_TAG_BITRATE, avg_bitrate,
|
GST_TAG_MERGE_REPLACE, GST_TAG_BITRATE, avg_bitrate, NULL);
|
||||||
NULL);
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
if (esds) {
|
||||||
}
|
gst_qtdemux_handle_esds (qtdemux, stream, entry, esds,
|
||||||
|
stream->stream_tags);
|
||||||
|
} else {
|
||||||
|
switch (fourcc) {
|
||||||
|
case FOURCC_H264:
|
||||||
|
case FOURCC_avc1:
|
||||||
|
case FOURCC_avc3:
|
||||||
|
{
|
||||||
|
GNode *avcC =
|
||||||
|
qtdemux_tree_get_child_by_type (stsd_entry, FOURCC_avcC);
|
||||||
|
GNode *strf =
|
||||||
|
qtdemux_tree_get_child_by_type (stsd_entry, FOURCC_strf);
|
||||||
|
|
||||||
default:
|
if (avcC) {
|
||||||
break;
|
const guint8 *data;
|
||||||
}
|
guint32 size;
|
||||||
|
|
||||||
len -= size;
|
data = avcC->data;
|
||||||
avc_data += size;
|
size = QT_UINT32 (data);
|
||||||
|
if (size >= 8 + 1) {
|
||||||
|
GstBuffer *buf;
|
||||||
|
|
||||||
|
GST_DEBUG_OBJECT (qtdemux, "found avcC codec_data in stsd");
|
||||||
|
|
||||||
|
/* First 4 bytes are the length of the atom, the next 4 bytes
|
||||||
|
* are the fourcc, the next 1 byte is the version, and the
|
||||||
|
* subsequent bytes are profile_tier_level structure like data. */
|
||||||
|
gst_codec_utils_h264_caps_set_level_and_profile (entry->caps,
|
||||||
|
data + 8 + 1, size - 8 - 1);
|
||||||
|
buf = gst_buffer_new_and_alloc (size - 8);
|
||||||
|
gst_buffer_fill (buf, 0, data + 8, size - 8);
|
||||||
|
gst_caps_set_simple (entry->caps,
|
||||||
|
"codec_data", GST_TYPE_BUFFER, buf, NULL);
|
||||||
|
gst_buffer_unref (buf);
|
||||||
|
}
|
||||||
|
} else if (strf) {
|
||||||
|
const guint8 *data;
|
||||||
|
guint32 size;
|
||||||
|
|
||||||
|
data = strf->data;
|
||||||
|
size = QT_UINT32 (data);
|
||||||
|
|
||||||
|
if (size >= 8 + 40 + 1) {
|
||||||
|
GstBuffer *buf;
|
||||||
|
|
||||||
|
|
||||||
|
GST_DEBUG_OBJECT (qtdemux, "found strf codec_data in stsd");
|
||||||
|
|
||||||
|
/* First 4 bytes are the length of the atom, the next 4 bytes
|
||||||
|
* are the fourcc, next 40 bytes are BITMAPINFOHEADER,
|
||||||
|
* next 1 byte is the version, and the
|
||||||
|
* subsequent bytes are sequence parameter set like data. */
|
||||||
|
|
||||||
|
gst_codec_utils_h264_caps_set_level_and_profile
|
||||||
|
(entry->caps, data + 8 + 40 + 1, size - 8 - 40 - 1);
|
||||||
|
|
||||||
|
buf = gst_buffer_new_and_alloc (size - 8 - 40);
|
||||||
|
gst_buffer_fill (buf, 0, data + 8 + 40, size - 8 - 40);
|
||||||
|
gst_caps_set_simple (entry->caps,
|
||||||
|
"codec_data", GST_TYPE_BUFFER, buf, NULL);
|
||||||
|
gst_buffer_unref (buf);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@ -15156,46 +15142,33 @@ qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak, guint32 * mvhd_matrix)
|
|||||||
case FOURCC_dvh1:
|
case FOURCC_dvh1:
|
||||||
case FOURCC_dvhe:
|
case FOURCC_dvhe:
|
||||||
{
|
{
|
||||||
guint32 len = QT_UINT32 (stsd_entry_data);
|
GNode *hvcC =
|
||||||
len = len <= 0x56 ? 0 : len - 0x56;
|
qtdemux_tree_get_child_by_type (stsd_entry, FOURCC_hvcC);
|
||||||
const guint8 *hevc_data = stsd_entry_data + 0x56;
|
|
||||||
|
|
||||||
/* find hevc */
|
if (hvcC) {
|
||||||
while (len >= 8) {
|
const guint8 *data;
|
||||||
guint32 size = QT_UINT32 (hevc_data);
|
guint32 size;
|
||||||
|
|
||||||
if (size < 8 || size > len)
|
data = hvcC->data;
|
||||||
break;
|
size = QT_UINT32 (data);
|
||||||
|
|
||||||
switch (QT_FOURCC (hevc_data + 4)) {
|
if (size >= 8 + 1) {
|
||||||
case FOURCC_hvcC:
|
|
||||||
{
|
|
||||||
/* parse, if found */
|
|
||||||
GstBuffer *buf;
|
GstBuffer *buf;
|
||||||
|
|
||||||
if (size < 8 + 1)
|
|
||||||
break;
|
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (qtdemux, "found hvcC codec_data in stsd");
|
GST_DEBUG_OBJECT (qtdemux, "found hvcC codec_data in stsd");
|
||||||
|
|
||||||
/* First 4 bytes are the length of the atom, the next 4 bytes
|
/* First 4 bytes are the length of the atom, the next 4 bytes
|
||||||
* are the fourcc, the next 1 byte is the version, and the
|
* are the fourcc, the next 1 byte is the version, and the
|
||||||
* subsequent bytes are sequence parameter set like data. */
|
* subsequent bytes are sequence parameter set like data. */
|
||||||
gst_codec_utils_h265_caps_set_level_tier_and_profile
|
gst_codec_utils_h265_caps_set_level_tier_and_profile
|
||||||
(entry->caps, hevc_data + 8 + 1, size - 8 - 1);
|
(entry->caps, data + 8 + 1, size - 8 - 1);
|
||||||
|
|
||||||
buf = gst_buffer_new_and_alloc (size - 8);
|
buf = gst_buffer_new_and_alloc (size - 8);
|
||||||
gst_buffer_fill (buf, 0, hevc_data + 8, size - 8);
|
gst_buffer_fill (buf, 0, data + 8, size - 8);
|
||||||
gst_caps_set_simple (entry->caps,
|
gst_caps_set_simple (entry->caps,
|
||||||
"codec_data", GST_TYPE_BUFFER, buf, NULL);
|
"codec_data", GST_TYPE_BUFFER, buf, NULL);
|
||||||
gst_buffer_unref (buf);
|
gst_buffer_unref (buf);
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
len -= size;
|
|
||||||
hevc_data += size;
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -15203,33 +15176,27 @@ qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak, guint32 * mvhd_matrix)
|
|||||||
case FOURCC_vvc1:
|
case FOURCC_vvc1:
|
||||||
case FOURCC_vvi1:
|
case FOURCC_vvi1:
|
||||||
{
|
{
|
||||||
guint len = QT_UINT32 (stsd_entry_data);
|
GNode *vvcC =
|
||||||
len = len <= 0x56 ? 0 : len - 0x56;
|
qtdemux_tree_get_child_by_type (stsd_entry, FOURCC_vvcC);
|
||||||
const guint8 *vvc_data = stsd_entry_data + 0x56;
|
|
||||||
|
|
||||||
/* find vvcC, which is a FullBox. */
|
if (vvcC) {
|
||||||
while (len >= 12) {
|
const guint8 *data;
|
||||||
guint size = QT_UINT32 (vvc_data);
|
guint32 size;
|
||||||
|
|
||||||
if (size < 12 || size > len)
|
data = vvcC->data;
|
||||||
break;
|
size = QT_UINT32 (data);
|
||||||
|
|
||||||
switch (QT_FOURCC (vvc_data + 4)) {
|
|
||||||
case FOURCC_vvcC:
|
if (size >= 12 + 1) {
|
||||||
{
|
|
||||||
/* parse, if found */
|
|
||||||
GstBuffer *buf;
|
GstBuffer *buf;
|
||||||
guint8 version;
|
guint8 version;
|
||||||
|
|
||||||
if (size < 12 + 1)
|
|
||||||
break;
|
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (qtdemux, "found vvcC codec_data in stsd");
|
GST_DEBUG_OBJECT (qtdemux, "found vvcC codec_data in stsd");
|
||||||
|
|
||||||
/* First 4 bytes are the length of the atom, the next 4 bytes
|
/* First 4 bytes are the length of the atom, the next 4 bytes
|
||||||
* are the fourcc, the next 1 byte is the version, the next 3 bytes are flags and the
|
* are the fourcc, the next 1 byte is the version, the next 3 bytes are flags and the
|
||||||
* subsequent bytes are the decoder configuration record. */
|
* subsequent bytes are the decoder configuration record. */
|
||||||
version = vvc_data[8];
|
version = data[8];
|
||||||
if (version != 0) {
|
if (version != 0) {
|
||||||
GST_ERROR_OBJECT (qtdemux,
|
GST_ERROR_OBJECT (qtdemux,
|
||||||
"Unsupported vvcC version %u. Only version 0 is supported",
|
"Unsupported vvcC version %u. Only version 0 is supported",
|
||||||
@ -15238,20 +15205,14 @@ qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak, guint32 * mvhd_matrix)
|
|||||||
}
|
}
|
||||||
|
|
||||||
gst_codec_utils_h266_caps_set_level_tier_and_profile
|
gst_codec_utils_h266_caps_set_level_tier_and_profile
|
||||||
(entry->caps, vvc_data + 12, size - 12);
|
(entry->caps, data + 12, size - 12);
|
||||||
|
|
||||||
buf = gst_buffer_new_and_alloc (size - 12);
|
buf = gst_buffer_new_and_alloc (size - 12);
|
||||||
gst_buffer_fill (buf, 0, vvc_data + 12, size - 12);
|
gst_buffer_fill (buf, 0, data + 12, size - 12);
|
||||||
gst_caps_set_simple (entry->caps,
|
gst_caps_set_simple (entry->caps,
|
||||||
"codec_data", GST_TYPE_BUFFER, buf, NULL);
|
"codec_data", GST_TYPE_BUFFER, buf, NULL);
|
||||||
gst_buffer_unref (buf);
|
gst_buffer_unref (buf);
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
len -= size;
|
|
||||||
vvc_data += size;
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -15291,7 +15252,7 @@ qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak, guint32 * mvhd_matrix)
|
|||||||
case FOURCC_mjp2:
|
case FOURCC_mjp2:
|
||||||
{
|
{
|
||||||
/* see annex I of the jpeg2000 spec */
|
/* see annex I of the jpeg2000 spec */
|
||||||
GNode *jp2h, *ihdr, *colr, *mjp2, *prefix, *cmap, *cdef;
|
GNode *jp2h, *ihdr, *colr, *prefix, *cmap, *cdef;
|
||||||
const guint8 *data;
|
const guint8 *data;
|
||||||
const gchar *colorspace = NULL;
|
const gchar *colorspace = NULL;
|
||||||
gint ncomp = 0;
|
gint ncomp = 0;
|
||||||
@ -15303,10 +15264,7 @@ qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak, guint32 * mvhd_matrix)
|
|||||||
|
|
||||||
GST_DEBUG_OBJECT (qtdemux, "found mjp2");
|
GST_DEBUG_OBJECT (qtdemux, "found mjp2");
|
||||||
/* some required atoms */
|
/* some required atoms */
|
||||||
mjp2 = qtdemux_tree_get_child_by_index (stsd, stsd_index);
|
jp2h = qtdemux_tree_get_child_by_type (stsd_entry, FOURCC_jp2h);
|
||||||
if (!mjp2)
|
|
||||||
break;
|
|
||||||
jp2h = qtdemux_tree_get_child_by_type (mjp2, FOURCC_jp2h);
|
|
||||||
if (!jp2h)
|
if (!jp2h)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -15453,7 +15411,7 @@ qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak, guint32 * mvhd_matrix)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* some optional atoms */
|
/* some optional atoms */
|
||||||
prefix = qtdemux_tree_get_child_by_type (mjp2, FOURCC_jp2x);
|
prefix = qtdemux_tree_get_child_by_type (stsd_entry, FOURCC_jp2x);
|
||||||
|
|
||||||
/* add codec_data if provided */
|
/* add codec_data if provided */
|
||||||
if (prefix) {
|
if (prefix) {
|
||||||
@ -15519,8 +15477,7 @@ qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak, guint32 * mvhd_matrix)
|
|||||||
case FOURCC_WRLE:
|
case FOURCC_WRLE:
|
||||||
{
|
{
|
||||||
gst_caps_set_simple (entry->caps,
|
gst_caps_set_simple (entry->caps,
|
||||||
"depth", G_TYPE_INT, QT_UINT16 (stsd_entry_data + offset + 66),
|
"depth", G_TYPE_INT, entry->bits_per_sample, NULL);
|
||||||
NULL);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case FOURCC_XiTh:
|
case FOURCC_XiTh:
|
||||||
@ -15575,16 +15532,12 @@ qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak, guint32 * mvhd_matrix)
|
|||||||
}
|
}
|
||||||
case FOURCC_ovc1:
|
case FOURCC_ovc1:
|
||||||
{
|
{
|
||||||
GNode *ovc1;
|
|
||||||
guint8 *ovc1_data;
|
guint8 *ovc1_data;
|
||||||
guint ovc1_len;
|
guint ovc1_len;
|
||||||
GstBuffer *buf;
|
GstBuffer *buf;
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (qtdemux, "parse ovc1 header");
|
GST_DEBUG_OBJECT (qtdemux, "parse ovc1 header");
|
||||||
ovc1 = qtdemux_tree_get_child_by_index (stsd, stsd_index);
|
ovc1_data = stsd_entry->data;
|
||||||
if (!ovc1)
|
|
||||||
break;
|
|
||||||
ovc1_data = ovc1->data;
|
|
||||||
ovc1_len = QT_UINT32 (ovc1_data);
|
ovc1_len = QT_UINT32 (ovc1_data);
|
||||||
if (ovc1_len <= 198) {
|
if (ovc1_len <= 198) {
|
||||||
GST_WARNING_OBJECT (qtdemux, "Too small ovc1 header, skipping");
|
GST_WARNING_OBJECT (qtdemux, "Too small ovc1 header, skipping");
|
||||||
@ -15599,55 +15552,37 @@ qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak, guint32 * mvhd_matrix)
|
|||||||
}
|
}
|
||||||
case FOURCC_vc_1:
|
case FOURCC_vc_1:
|
||||||
{
|
{
|
||||||
guint32 len = QT_UINT32 (stsd_entry_data);
|
GNode *dvc1;
|
||||||
len = len <= 0x56 ? 0 : len - 0x56;
|
|
||||||
const guint8 *vc1_data = stsd_entry_data + 0x56;
|
|
||||||
|
|
||||||
/* find dvc1 */
|
dvc1 =
|
||||||
while (len >= 8) {
|
qtdemux_tree_get_child_by_type (stsd_entry,
|
||||||
guint32 size = QT_UINT32 (vc1_data);
|
GST_MAKE_FOURCC ('d', 'v', 'c', '1'));
|
||||||
|
if (dvc1) {
|
||||||
|
guint32 size = QT_UINT32 (dvc1->data);
|
||||||
|
|
||||||
if (size < 8 || size > len)
|
if (size >= 8) {
|
||||||
break;
|
|
||||||
|
|
||||||
switch (QT_FOURCC (vc1_data + 4)) {
|
|
||||||
case GST_MAKE_FOURCC ('d', 'v', 'c', '1'):
|
|
||||||
{
|
|
||||||
GstBuffer *buf;
|
GstBuffer *buf;
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (qtdemux, "found dvc1 codec_data in stsd");
|
GST_DEBUG_OBJECT (qtdemux, "found dvc1 codec_data in stsd");
|
||||||
buf = gst_buffer_new_and_alloc (size - 8);
|
buf = gst_buffer_new_and_alloc (size - 8);
|
||||||
gst_buffer_fill (buf, 0, vc1_data + 8, size - 8);
|
gst_buffer_fill (buf, 0, (const guint8 *) dvc1->data + 8,
|
||||||
gst_caps_set_simple (entry->caps,
|
size - 8);
|
||||||
"codec_data", GST_TYPE_BUFFER, buf, NULL);
|
gst_caps_set_simple (entry->caps, "codec_data", GST_TYPE_BUFFER,
|
||||||
|
buf, NULL);
|
||||||
gst_buffer_unref (buf);
|
gst_buffer_unref (buf);
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
len -= size;
|
|
||||||
vc1_data += size;
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case FOURCC_av01:
|
case FOURCC_av01:
|
||||||
{
|
{
|
||||||
guint32 len = QT_UINT32 (stsd_entry_data);
|
GNode *av1C;
|
||||||
len = len <= 0x56 ? 0 : len - 0x56;
|
|
||||||
const guint8 *av1_data = stsd_entry_data + 0x56;
|
|
||||||
|
|
||||||
/* find av1C */
|
av1C = qtdemux_tree_get_child_by_type (stsd_entry, FOURCC_av1C);
|
||||||
while (len >= 8) {
|
if (av1C) {
|
||||||
guint32 size = QT_UINT32 (av1_data);
|
const guint8 *data = av1C->data;
|
||||||
|
guint32 size = QT_UINT32 (data);
|
||||||
|
|
||||||
if (size < 8 || size > len)
|
|
||||||
break;
|
|
||||||
|
|
||||||
switch (QT_FOURCC (av1_data + 4)) {
|
|
||||||
case FOURCC_av1C:
|
|
||||||
{
|
|
||||||
/* parse, if found */
|
|
||||||
GstBuffer *buf;
|
GstBuffer *buf;
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (qtdemux,
|
GST_DEBUG_OBJECT (qtdemux,
|
||||||
@ -15688,7 +15623,7 @@ qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak, guint32 * mvhd_matrix)
|
|||||||
* rest: OBUs.
|
* rest: OBUs.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
switch (av1_data[8]) {
|
switch (data[8]) {
|
||||||
case 0x81:{
|
case 0x81:{
|
||||||
guint8 pres_delay_field;
|
guint8 pres_delay_field;
|
||||||
|
|
||||||
@ -15696,7 +15631,7 @@ qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak, guint32 * mvhd_matrix)
|
|||||||
* av1parse and only include the presentation delay here
|
* av1parse and only include the presentation delay here
|
||||||
* if present */
|
* if present */
|
||||||
/* We skip initial_presentation_delay* for now */
|
/* We skip initial_presentation_delay* for now */
|
||||||
pres_delay_field = *(av1_data + 11);
|
pres_delay_field = *(data + 11);
|
||||||
if (pres_delay_field & (1 << 5)) {
|
if (pres_delay_field & (1 << 5)) {
|
||||||
gst_caps_set_simple (entry->caps,
|
gst_caps_set_simple (entry->caps,
|
||||||
"presentation-delay", G_TYPE_INT,
|
"presentation-delay", G_TYPE_INT,
|
||||||
@ -15705,50 +15640,30 @@ qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak, guint32 * mvhd_matrix)
|
|||||||
|
|
||||||
buf = gst_buffer_new_and_alloc (size - 8);
|
buf = gst_buffer_new_and_alloc (size - 8);
|
||||||
GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_HEADER);
|
GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_HEADER);
|
||||||
gst_buffer_fill (buf, 0, av1_data + 8, size - 8);
|
gst_buffer_fill (buf, 0, data + 8, size - 8);
|
||||||
gst_caps_set_simple (entry->caps,
|
gst_caps_set_simple (entry->caps,
|
||||||
"codec_data", GST_TYPE_BUFFER, buf, NULL);
|
"codec_data", GST_TYPE_BUFFER, buf, NULL);
|
||||||
gst_buffer_unref (buf);
|
gst_buffer_unref (buf);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
GST_WARNING ("Unknown version 0x%02x of av1C box",
|
GST_WARNING ("Unknown version 0x%02x of av1C box", data[8]);
|
||||||
av1_data[8]);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
len -= size;
|
|
||||||
av1_data += size;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* TODO: Need to parse vpcC for VP8 codec too.
|
case FOURCC_vp08:
|
||||||
* Note that VPCodecConfigurationBox (vpcC) is defined for
|
|
||||||
* vp08, vp09, and vp10 fourcc. */
|
|
||||||
case FOURCC_vp09:
|
case FOURCC_vp09:
|
||||||
{
|
{
|
||||||
guint32 len = QT_UINT32 (stsd_entry_data);
|
GNode *vpcC;
|
||||||
len = len <= 0x56 ? 0 : len - 0x56;
|
|
||||||
const guint8 *vpcc_data = stsd_entry_data + 0x56;
|
|
||||||
|
|
||||||
/* find vpcC */
|
vpcC = qtdemux_tree_get_child_by_type (stsd_entry, FOURCC_vpcC);
|
||||||
while (len >= 8) {
|
if (vpcC) {
|
||||||
guint32 size = QT_UINT32 (vpcc_data);
|
const guint8 *data = vpcC->data;
|
||||||
|
guint32 size = QT_UINT32 (data);
|
||||||
if (size < 8 || size > len)
|
|
||||||
break;
|
|
||||||
|
|
||||||
switch (QT_FOURCC (vpcc_data + 4)) {
|
|
||||||
case FOURCC_vpcC:
|
|
||||||
{
|
|
||||||
const gchar *profile_str = NULL;
|
const gchar *profile_str = NULL;
|
||||||
const gchar *chroma_format_str = NULL;
|
const gchar *chroma_format_str = NULL;
|
||||||
guint8 profile;
|
guint8 profile;
|
||||||
@ -15782,13 +15697,13 @@ qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak, guint32 * mvhd_matrix)
|
|||||||
* rest: codecIntializationData (not used for vp8 and vp9)
|
* rest: codecIntializationData (not used for vp8 and vp9)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (vpcc_data[8] != 1) {
|
if (data[8] != 1) {
|
||||||
GST_WARNING_OBJECT (qtdemux,
|
GST_WARNING_OBJECT (qtdemux,
|
||||||
"unknown vpcC version %d", vpcc_data[8]);
|
"unknown vpcC version %d", data[8]);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
profile = vpcc_data[12];
|
profile = data[12];
|
||||||
switch (profile) {
|
switch (profile) {
|
||||||
case 0:
|
case 0:
|
||||||
profile_str = "0";
|
profile_str = "0";
|
||||||
@ -15815,14 +15730,14 @@ qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak, guint32 * mvhd_matrix)
|
|||||||
* but webm spec define various ones. Add level to caps
|
* but webm spec define various ones. Add level to caps
|
||||||
* if we really need it then */
|
* if we really need it then */
|
||||||
|
|
||||||
bitdepth = (vpcc_data[14] & 0xf0) >> 4;
|
bitdepth = (data[14] & 0xf0) >> 4;
|
||||||
if (bitdepth == 8 || bitdepth == 10 || bitdepth == 12) {
|
if (bitdepth == 8 || bitdepth == 10 || bitdepth == 12) {
|
||||||
gst_caps_set_simple (entry->caps,
|
gst_caps_set_simple (entry->caps,
|
||||||
"bit-depth-luma", G_TYPE_UINT, bitdepth,
|
"bit-depth-luma", G_TYPE_UINT, bitdepth,
|
||||||
"bit-depth-chroma", G_TYPE_UINT, bitdepth, NULL);
|
"bit-depth-chroma", G_TYPE_UINT, bitdepth, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
chroma_format = (vpcc_data[14] & 0xe) >> 1;
|
chroma_format = (data[14] & 0xe) >> 1;
|
||||||
switch (chroma_format) {
|
switch (chroma_format) {
|
||||||
case 0:
|
case 0:
|
||||||
case 1:
|
case 1:
|
||||||
@ -15840,20 +15755,16 @@ qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak, guint32 * mvhd_matrix)
|
|||||||
|
|
||||||
if (chroma_format_str) {
|
if (chroma_format_str) {
|
||||||
gst_caps_set_simple (entry->caps,
|
gst_caps_set_simple (entry->caps,
|
||||||
"chroma-format", G_TYPE_STRING, chroma_format_str,
|
"chroma-format", G_TYPE_STRING, chroma_format_str, NULL);
|
||||||
NULL);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((vpcc_data[14] & 0x1) != 0)
|
if ((data[14] & 0x1) != 0)
|
||||||
cinfo.range = GST_VIDEO_COLOR_RANGE_0_255;
|
cinfo.range = GST_VIDEO_COLOR_RANGE_0_255;
|
||||||
else
|
else
|
||||||
cinfo.range = GST_VIDEO_COLOR_RANGE_16_235;
|
cinfo.range = GST_VIDEO_COLOR_RANGE_16_235;
|
||||||
cinfo.primaries =
|
cinfo.primaries = gst_video_color_primaries_from_iso (data[15]);
|
||||||
gst_video_color_primaries_from_iso (vpcc_data[15]);
|
cinfo.transfer = gst_video_transfer_function_from_iso (data[16]);
|
||||||
cinfo.transfer =
|
cinfo.matrix = gst_video_color_matrix_from_iso (data[17]);
|
||||||
gst_video_transfer_function_from_iso (vpcc_data[16]);
|
|
||||||
cinfo.matrix =
|
|
||||||
gst_video_color_matrix_from_iso (vpcc_data[17]);
|
|
||||||
|
|
||||||
if (cinfo.primaries != GST_VIDEO_COLOR_PRIMARIES_UNKNOWN &&
|
if (cinfo.primaries != GST_VIDEO_COLOR_PRIMARIES_UNKNOWN &&
|
||||||
cinfo.transfer != GST_VIDEO_TRANSFER_UNKNOWN &&
|
cinfo.transfer != GST_VIDEO_TRANSFER_UNKNOWN &&
|
||||||
@ -15862,20 +15773,9 @@ qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak, guint32 * mvhd_matrix)
|
|||||||
* might overwrite valid ones parsed from other color box */
|
* might overwrite valid ones parsed from other color box */
|
||||||
CUR_STREAM (stream)->colorimetry = cinfo;
|
CUR_STREAM (stream)->colorimetry = cinfo;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
len -= size;
|
|
||||||
vpcc_data += size;
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -15884,7 +15784,7 @@ qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak, guint32 * mvhd_matrix)
|
|||||||
GST_FOURCC_ARGS (fourcc), entry->caps);
|
GST_FOURCC_ARGS (fourcc), entry->caps);
|
||||||
|
|
||||||
} else if (stream->subtype == FOURCC_soun) {
|
} else if (stream->subtype == FOURCC_soun) {
|
||||||
GNode *wave;
|
GNode *wave, *btrt;
|
||||||
guint version, samplesize;
|
guint version, samplesize;
|
||||||
guint16 compression_id;
|
guint16 compression_id;
|
||||||
gboolean amrwb = FALSE;
|
gboolean amrwb = FALSE;
|
||||||
@ -16120,19 +16020,19 @@ qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak, guint32 * mvhd_matrix)
|
|||||||
case FOURCC_fl64:
|
case FOURCC_fl64:
|
||||||
{
|
{
|
||||||
GNode *enda;
|
GNode *enda;
|
||||||
GNode *fmt;
|
|
||||||
|
|
||||||
fmt = qtdemux_tree_get_child_by_type (stsd, fourcc);
|
enda = qtdemux_tree_get_child_by_type (stsd_entry, FOURCC_enda);
|
||||||
|
|
||||||
enda = qtdemux_tree_get_child_by_type (fmt, FOURCC_enda);
|
|
||||||
if (!enda) {
|
if (!enda) {
|
||||||
wave = qtdemux_tree_get_child_by_type (fmt, FOURCC_wave);
|
wave = qtdemux_tree_get_child_by_type (stsd_entry, FOURCC_wave);
|
||||||
if (wave)
|
if (wave)
|
||||||
enda = qtdemux_tree_get_child_by_type (wave, FOURCC_enda);
|
enda = qtdemux_tree_get_child_by_type (wave, FOURCC_enda);
|
||||||
}
|
}
|
||||||
if (enda) {
|
if (enda) {
|
||||||
int enda_value = QT_UINT16 ((guint8 *) enda->data + 8);
|
|
||||||
const gchar *format_str;
|
const gchar *format_str;
|
||||||
|
guint32 enda_len = QT_UINT32 (enda->data);
|
||||||
|
|
||||||
|
if (enda_len >= 9) {
|
||||||
|
guint16 enda_value = QT_UINT16 ((guint8 *) enda->data + 8);
|
||||||
|
|
||||||
switch (fourcc) {
|
switch (fourcc) {
|
||||||
case FOURCC_in24:
|
case FOURCC_in24:
|
||||||
@ -16154,6 +16054,7 @@ qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak, guint32 * mvhd_matrix)
|
|||||||
gst_caps_set_simple (entry->caps,
|
gst_caps_set_simple (entry->caps,
|
||||||
"format", G_TYPE_STRING, format_str, NULL);
|
"format", G_TYPE_STRING, format_str, NULL);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case FOURCC_owma:
|
case FOURCC_owma:
|
||||||
@ -16225,9 +16126,6 @@ qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak, guint32 * mvhd_matrix)
|
|||||||
}
|
}
|
||||||
case FOURCC_wma_:
|
case FOURCC_wma_:
|
||||||
{
|
{
|
||||||
guint32 len = QT_UINT32 (stsd_entry_data);
|
|
||||||
len = len <= offset ? 0 : len - offset;
|
|
||||||
const guint8 *wfex_data = stsd_entry_data + offset;
|
|
||||||
const gchar *codec_name = NULL;
|
const gchar *codec_name = NULL;
|
||||||
gint version = 1;
|
gint version = 1;
|
||||||
/* from http://msdn.microsoft.com/en-us/library/dd757720(VS.85).aspx */
|
/* from http://msdn.microsoft.com/en-us/library/dd757720(VS.85).aspx */
|
||||||
@ -16244,23 +16142,22 @@ qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak, guint32 * mvhd_matrix)
|
|||||||
gint16 cbSize;
|
gint16 cbSize;
|
||||||
} WAVEFORMATEX;
|
} WAVEFORMATEX;
|
||||||
WAVEFORMATEX wfex;
|
WAVEFORMATEX wfex;
|
||||||
|
GNode *wfex_node;
|
||||||
|
|
||||||
/* FIXME: unify with similar wavformatex parsing code above */
|
/* FIXME: unify with similar wavformatex parsing code above */
|
||||||
GST_DEBUG_OBJECT (qtdemux, "parse wma, looking for wfex");
|
GST_DEBUG_OBJECT (qtdemux, "parse wma, looking for wfex");
|
||||||
|
|
||||||
/* find wfex */
|
wfex_node =
|
||||||
while (len >= 8) {
|
qtdemux_tree_get_child_by_type (stsd_entry, GST_MAKE_FOURCC ('w',
|
||||||
guint32 size = QT_UINT32 (wfex_data);
|
'f', 'e', 'x'));
|
||||||
|
|
||||||
if (size < 8 || size > len)
|
if (wfex_node) {
|
||||||
break;
|
const guint8 *wfex_data = wfex_node->data;
|
||||||
|
guint32 wfex_size = QT_UINT32 (wfex_data);
|
||||||
|
|
||||||
switch (QT_FOURCC (wfex_data + 4)) {
|
|
||||||
case GST_MAKE_FOURCC ('w', 'f', 'e', 'x'):
|
|
||||||
{
|
|
||||||
GST_DEBUG_OBJECT (qtdemux, "found wfex in stsd");
|
GST_DEBUG_OBJECT (qtdemux, "found wfex in stsd");
|
||||||
|
|
||||||
if (size < 8 + 18)
|
if (wfex_size < 8 + 18)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
wfex.wFormatTag = GST_READ_UINT16_LE (wfex_data + 8 + 0);
|
wfex.wFormatTag = GST_READ_UINT16_LE (wfex_data + 8 + 0);
|
||||||
@ -16298,12 +16195,12 @@ qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak, guint32 * mvhd_matrix)
|
|||||||
"width", G_TYPE_INT, wfex.wBitsPerSample,
|
"width", G_TYPE_INT, wfex.wBitsPerSample,
|
||||||
"depth", G_TYPE_INT, wfex.wBitsPerSample, NULL);
|
"depth", G_TYPE_INT, wfex.wBitsPerSample, NULL);
|
||||||
|
|
||||||
if (size > 8 + wfex.cbSize) {
|
if (wfex_size > 8 + wfex.cbSize) {
|
||||||
GstBuffer *buf;
|
GstBuffer *buf;
|
||||||
|
|
||||||
buf = gst_buffer_new_and_alloc (size - 8 - wfex.cbSize);
|
buf = gst_buffer_new_and_alloc (wfex_size - 8 - wfex.cbSize);
|
||||||
gst_buffer_fill (buf, 0, wfex_data + 8 + wfex.cbSize,
|
gst_buffer_fill (buf, 0, wfex_data + 8 + wfex.cbSize,
|
||||||
size - 8 - wfex.cbSize);
|
wfex_size - 8 - wfex.cbSize);
|
||||||
gst_caps_set_simple (entry->caps,
|
gst_caps_set_simple (entry->caps,
|
||||||
"codec_data", GST_TYPE_BUFFER, buf, NULL);
|
"codec_data", GST_TYPE_BUFFER, buf, NULL);
|
||||||
gst_buffer_unref (buf);
|
gst_buffer_unref (buf);
|
||||||
@ -16317,12 +16214,6 @@ qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak, guint32 * mvhd_matrix)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
len -= size;
|
|
||||||
wfex_data += size;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case FOURCC_opus:
|
case FOURCC_opus:
|
||||||
@ -16335,16 +16226,9 @@ qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak, guint32 * mvhd_matrix)
|
|||||||
guint8 coupled_count;
|
guint8 coupled_count;
|
||||||
guint8 i;
|
guint8 i;
|
||||||
|
|
||||||
GNode *opus;
|
|
||||||
GNode *dops;
|
GNode *dops;
|
||||||
|
|
||||||
opus = qtdemux_tree_get_child_by_type (stsd, FOURCC_opus);
|
dops = qtdemux_tree_get_child_by_type (stsd_entry, FOURCC_dops);
|
||||||
if (opus == NULL) {
|
|
||||||
GST_WARNING_OBJECT (qtdemux, "Opus Sample Entry not found");
|
|
||||||
goto corrupt_file;
|
|
||||||
}
|
|
||||||
|
|
||||||
dops = qtdemux_tree_get_child_by_type (opus, FOURCC_dops);
|
|
||||||
if (dops == NULL) {
|
if (dops == NULL) {
|
||||||
GST_WARNING_OBJECT (qtdemux, "Opus Specific Box not found");
|
GST_WARNING_OBJECT (qtdemux, "Opus Specific Box not found");
|
||||||
goto corrupt_file;
|
goto corrupt_file;
|
||||||
@ -16428,12 +16312,9 @@ qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak, guint32 * mvhd_matrix)
|
|||||||
case FOURCC_ipcm:
|
case FOURCC_ipcm:
|
||||||
case FOURCC_fpcm:
|
case FOURCC_fpcm:
|
||||||
{
|
{
|
||||||
GNode *fmt;
|
|
||||||
GNode *pcmC;
|
GNode *pcmC;
|
||||||
|
|
||||||
fmt = qtdemux_tree_get_child_by_type (stsd, fourcc);
|
pcmC = qtdemux_tree_get_child_by_type (stsd_entry, FOURCC_pcmC);
|
||||||
|
|
||||||
pcmC = qtdemux_tree_get_child_by_type (fmt, FOURCC_pcmC);
|
|
||||||
if (pcmC) {
|
if (pcmC) {
|
||||||
const guint8 *data = pcmC->data;
|
const guint8 *data = pcmC->data;
|
||||||
gsize len = QT_UINT32 (data);
|
gsize len = QT_UINT32 (data);
|
||||||
@ -16530,29 +16411,46 @@ qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak, guint32 * mvhd_matrix)
|
|||||||
}
|
}
|
||||||
|
|
||||||
esds = NULL;
|
esds = NULL;
|
||||||
mp4a = qtdemux_tree_get_child_by_index (stsd, stsd_index);
|
wave = qtdemux_tree_get_child_by_type (stsd_entry, FOURCC_wave);
|
||||||
if (QTDEMUX_TREE_NODE_FOURCC (mp4a) != fourcc) {
|
|
||||||
if (stream->protected) {
|
|
||||||
if (QTDEMUX_TREE_NODE_FOURCC (mp4a) == FOURCC_aavd) {
|
|
||||||
esds = qtdemux_tree_get_child_by_type (mp4a, FOURCC_esds);
|
|
||||||
}
|
|
||||||
if (QTDEMUX_TREE_NODE_FOURCC (mp4a) != FOURCC_enca) {
|
|
||||||
mp4a = NULL;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
mp4a = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
wave = NULL;
|
|
||||||
if (mp4a) {
|
|
||||||
wave = qtdemux_tree_get_child_by_type (mp4a, FOURCC_wave);
|
|
||||||
if (wave)
|
if (wave)
|
||||||
esds = qtdemux_tree_get_child_by_type (wave, FOURCC_esds);
|
esds = qtdemux_tree_get_child_by_type (wave, FOURCC_esds);
|
||||||
if (!esds)
|
if (!esds)
|
||||||
esds = qtdemux_tree_get_child_by_type (mp4a, FOURCC_esds);
|
esds = qtdemux_tree_get_child_by_type (stsd_entry, FOURCC_esds);
|
||||||
}
|
|
||||||
|
|
||||||
|
btrt = qtdemux_tree_get_child_by_type (stsd_entry, FOURCC_btrt);
|
||||||
|
|
||||||
|
if (btrt) {
|
||||||
|
const guint8 *data;
|
||||||
|
guint32 size;
|
||||||
|
|
||||||
|
data = btrt->data;
|
||||||
|
size = QT_UINT32 (data);
|
||||||
|
|
||||||
|
/* bufferSizeDB, maxBitrate and avgBitrate - 4 bytes each */
|
||||||
|
if (size >= 8 + 12) {
|
||||||
|
|
||||||
|
guint32 max_bitrate = QT_UINT32 (data + 8 + 4);
|
||||||
|
guint32 avg_bitrate = QT_UINT32 (data + 8 + 8);
|
||||||
|
|
||||||
|
/* Some muxers seem to swap the average and maximum bitrates
|
||||||
|
* (I'm looking at you, YouTube), so we swap for sanity. */
|
||||||
|
if (max_bitrate > 0 && max_bitrate < avg_bitrate) {
|
||||||
|
guint temp = avg_bitrate;
|
||||||
|
|
||||||
|
avg_bitrate = max_bitrate;
|
||||||
|
max_bitrate = temp;
|
||||||
|
}
|
||||||
|
if (max_bitrate > 0 && max_bitrate < G_MAXUINT32) {
|
||||||
|
gst_tag_list_add (stream->stream_tags,
|
||||||
|
GST_TAG_MERGE_REPLACE, GST_TAG_MAXIMUM_BITRATE,
|
||||||
|
max_bitrate, NULL);
|
||||||
|
}
|
||||||
|
if (avg_bitrate > 0 && avg_bitrate < G_MAXUINT32) {
|
||||||
|
gst_tag_list_add (stream->stream_tags,
|
||||||
|
GST_TAG_MERGE_REPLACE, GST_TAG_BITRATE, avg_bitrate, NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* If the fourcc's bottom 16 bits gives 'sm', then the top
|
/* If the fourcc's bottom 16 bits gives 'sm', then the top
|
||||||
16 bits is a byte-swapped wave-style codec identifier,
|
16 bits is a byte-swapped wave-style codec identifier,
|
||||||
@ -16643,19 +16541,15 @@ qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak, guint32 * mvhd_matrix)
|
|||||||
}
|
}
|
||||||
case FOURCC_alac:
|
case FOURCC_alac:
|
||||||
{
|
{
|
||||||
GNode *alac, *wave = NULL;
|
GNode *alac;
|
||||||
|
|
||||||
/* apparently, m4a has this atom appended directly in the stsd entry,
|
/* apparently, m4a has this atom appended directly in the stsd entry,
|
||||||
* while mov has it in a wave atom */
|
* while mov has it in a wave atom */
|
||||||
alac = qtdemux_tree_get_child_by_type (stsd, FOURCC_alac);
|
|
||||||
if (alac) {
|
|
||||||
/* alac now refers to stsd entry atom */
|
/* alac now refers to stsd entry atom */
|
||||||
wave = qtdemux_tree_get_child_by_type (alac, FOURCC_wave);
|
|
||||||
if (wave)
|
if (wave)
|
||||||
alac = qtdemux_tree_get_child_by_type (wave, FOURCC_alac);
|
alac = qtdemux_tree_get_child_by_type (wave, FOURCC_alac);
|
||||||
else
|
else
|
||||||
alac = qtdemux_tree_get_child_by_type (alac, FOURCC_alac);
|
alac = qtdemux_tree_get_child_by_type (stsd_entry, FOURCC_alac);
|
||||||
}
|
|
||||||
if (alac) {
|
if (alac) {
|
||||||
const guint8 *alac_data = alac->data;
|
const guint8 *alac_data = alac->data;
|
||||||
gint len = QT_UINT32 (alac->data);
|
gint len = QT_UINT32 (alac->data);
|
||||||
@ -16686,13 +16580,10 @@ qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak, guint32 * mvhd_matrix)
|
|||||||
case FOURCC_fLaC:
|
case FOURCC_fLaC:
|
||||||
{
|
{
|
||||||
/* The codingname of the sample entry is 'fLaC' */
|
/* The codingname of the sample entry is 'fLaC' */
|
||||||
GNode *flac = qtdemux_tree_get_child_by_type (stsd, FOURCC_fLaC);
|
|
||||||
|
|
||||||
if (flac) {
|
|
||||||
/* The 'dfLa' box is added to the sample entry to convey
|
/* The 'dfLa' box is added to the sample entry to convey
|
||||||
initializing information for the decoder. */
|
initializing information for the decoder. */
|
||||||
const GNode *dfla =
|
const GNode *dfla =
|
||||||
qtdemux_tree_get_child_by_type (flac, FOURCC_dfLa);
|
qtdemux_tree_get_child_by_type (stsd_entry, FOURCC_dfLa);
|
||||||
|
|
||||||
if (dfla) {
|
if (dfla) {
|
||||||
const guint32 len = QT_UINT32 (dfla->data);
|
const guint32 len = QT_UINT32 (dfla->data);
|
||||||
@ -16782,7 +16673,6 @@ qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak, guint32 * mvhd_matrix)
|
|||||||
(QT_UINT32 (metadata_blocks + 14) >> 12) & 0xFFFFF;
|
(QT_UINT32 (metadata_blocks + 14) >> 12) & 0xFFFFF;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case FOURCC_sawb:
|
case FOURCC_sawb:
|
||||||
@ -16859,12 +16749,11 @@ qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak, guint32 * mvhd_matrix)
|
|||||||
case FOURCC_fl32:
|
case FOURCC_fl32:
|
||||||
case FOURCC_fl64:
|
case FOURCC_fl64:
|
||||||
case FOURCC_s16l:{
|
case FOURCC_s16l:{
|
||||||
GNode *fmt, *chnl, *chan;
|
GNode *chnl, *chan;
|
||||||
|
|
||||||
// Parse channel layout information for raw PCM
|
// Parse channel layout information for raw PCM
|
||||||
fmt = qtdemux_tree_get_child_by_type (stsd, fourcc);
|
chnl = qtdemux_tree_get_child_by_type (stsd_entry, FOURCC_chnl);
|
||||||
chnl = qtdemux_tree_get_child_by_type (fmt, FOURCC_chnl);
|
chan = qtdemux_tree_get_child_by_type (stsd_entry, FOURCC_chan);
|
||||||
chan = qtdemux_tree_get_child_by_type (fmt, FOURCC_chan);
|
|
||||||
|
|
||||||
if (chnl) {
|
if (chnl) {
|
||||||
const guint8 *data = chnl->data;
|
const guint8 *data = chnl->data;
|
||||||
@ -16939,13 +16828,10 @@ qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak, guint32 * mvhd_matrix)
|
|||||||
switch (fourcc) {
|
switch (fourcc) {
|
||||||
case FOURCC_mp4s:
|
case FOURCC_mp4s:
|
||||||
{
|
{
|
||||||
GNode *mp4s = NULL;
|
|
||||||
GNode *esds = NULL;
|
GNode *esds = NULL;
|
||||||
|
|
||||||
/* look for palette in a stsd->mp4s->esds sub-atom */
|
/* look for palette in a stsd->mp4s->esds sub-atom */
|
||||||
mp4s = qtdemux_tree_get_child_by_type (stsd, FOURCC_mp4s);
|
esds = qtdemux_tree_get_child_by_type (stsd_entry, FOURCC_esds);
|
||||||
if (mp4s)
|
|
||||||
esds = qtdemux_tree_get_child_by_type (mp4s, FOURCC_esds);
|
|
||||||
if (esds == NULL) {
|
if (esds == NULL) {
|
||||||
/* Invalid STSD */
|
/* Invalid STSD */
|
||||||
GST_LOG_OBJECT (qtdemux, "Skipping invalid stsd: no esds child");
|
GST_LOG_OBJECT (qtdemux, "Skipping invalid stsd: no esds child");
|
||||||
|
Loading…
x
Reference in New Issue
Block a user