mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-27 10:40:34 +00:00
qtdemux: Parse VP Codec Configuration Box
The VP Codec Configuration Box (vpcC) contains vp9 profile and colorimetry information. Especially the profile information might be useful for downstream to select capable decoder element.
This commit is contained in:
parent
9feb35638a
commit
f286f30640
2 changed files with 151 additions and 0 deletions
|
@ -259,6 +259,7 @@ G_BEGIN_DECLS
|
|||
#define FOURCC_vmhd GST_MAKE_FOURCC('v','m','h','d')
|
||||
#define FOURCC_vp08 GST_MAKE_FOURCC('v','p','0','8')
|
||||
#define FOURCC_vp09 GST_MAKE_FOURCC('v','p','0','9')
|
||||
#define FOURCC_vpcC GST_MAKE_FOURCC('v','p','c','C')
|
||||
#define FOURCC_xvid GST_MAKE_FOURCC('x','v','i','d')
|
||||
#define FOURCC_wave GST_MAKE_FOURCC('w','a','v','e')
|
||||
#define FOURCC_wide GST_MAKE_FOURCC('w','i','d','e')
|
||||
|
|
|
@ -11859,6 +11859,156 @@ qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak)
|
|||
|
||||
break;
|
||||
}
|
||||
|
||||
/* TODO: Need to parse vpcC for VP8 codec too.
|
||||
* Note that VPCodecConfigurationBox (vpcC) is defined for
|
||||
* vp08, vp09, and vp10 fourcc. */
|
||||
case FOURCC_vp09:
|
||||
{
|
||||
gint len = QT_UINT32 (stsd_entry_data) - 0x56;
|
||||
const guint8 *vpcc_data = stsd_entry_data + 0x56;
|
||||
|
||||
/* find vpcC */
|
||||
while (len >= 0x8) {
|
||||
gint size;
|
||||
|
||||
if (QT_UINT32 (vpcc_data) <= len)
|
||||
size = QT_UINT32 (vpcc_data) - 0x8;
|
||||
else
|
||||
size = len - 0x8;
|
||||
|
||||
if (size < 1)
|
||||
/* No real data, so break out */
|
||||
break;
|
||||
|
||||
switch (QT_FOURCC (vpcc_data + 0x4)) {
|
||||
case FOURCC_vpcC:
|
||||
{
|
||||
const gchar *profile_str = NULL;
|
||||
const gchar *chroma_format_str = NULL;
|
||||
guint8 profile;
|
||||
guint8 bitdepth;
|
||||
guint8 chroma_format;
|
||||
GstVideoColorimetry cinfo;
|
||||
|
||||
/* parse, if found */
|
||||
GST_DEBUG_OBJECT (qtdemux,
|
||||
"found vp codec_data in stsd of size %d", size);
|
||||
|
||||
/* the meaning of "size" is length of the atom body, excluding
|
||||
* atom length and fourcc fields */
|
||||
if (size < 12)
|
||||
break;
|
||||
|
||||
/* Content is:
|
||||
* 4 bytes: atom length
|
||||
* 4 bytes: fourcc
|
||||
* 1 byte: version
|
||||
* 3 bytes: flags
|
||||
* 1 byte: profile
|
||||
* 1 byte: level
|
||||
* 4 bits: bitDepth
|
||||
* 3 bits: chromaSubsampling
|
||||
* 1 bit: videoFullRangeFlag
|
||||
* 1 byte: colourPrimaries
|
||||
* 1 byte: transferCharacteristics
|
||||
* 1 byte: matrixCoefficients
|
||||
* 2 bytes: codecIntializationDataSize (should be zero for vp8 and vp9)
|
||||
* rest: codecIntializationData (not used for vp8 and vp9)
|
||||
*/
|
||||
|
||||
if (vpcc_data[8] != 1) {
|
||||
GST_WARNING_OBJECT (qtdemux,
|
||||
"unknown vpcC version %d", vpcc_data[8]);
|
||||
break;
|
||||
}
|
||||
|
||||
profile = vpcc_data[12];
|
||||
switch (profile) {
|
||||
case 0:
|
||||
profile_str = "0";
|
||||
break;
|
||||
case 1:
|
||||
profile_str = "1";
|
||||
break;
|
||||
case 2:
|
||||
profile_str = "2";
|
||||
break;
|
||||
case 3:
|
||||
profile_str = "3";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (profile_str) {
|
||||
gst_caps_set_simple (entry->caps,
|
||||
"profile", G_TYPE_STRING, profile_str, NULL);
|
||||
}
|
||||
|
||||
/* skip level, the VP9 spec v0.6 defines only one level atm,
|
||||
* but webm spec define various ones. Add level to caps
|
||||
* if we really need it then */
|
||||
|
||||
bitdepth = (vpcc_data[14] & 0xf0) >> 4;
|
||||
if (bitdepth == 8 || bitdepth == 10 || bitdepth == 12) {
|
||||
gst_caps_set_simple (entry->caps,
|
||||
"bit-depth-luma", G_TYPE_UINT, bitdepth,
|
||||
"bit-depth-chroma", G_TYPE_UINT, bitdepth, NULL);
|
||||
}
|
||||
|
||||
chroma_format = (vpcc_data[14] & 0xe) >> 1;
|
||||
switch (chroma_format) {
|
||||
case 0:
|
||||
case 1:
|
||||
chroma_format_str = "4:2:0";
|
||||
break;
|
||||
case 2:
|
||||
chroma_format_str = "4:2:2";
|
||||
break;
|
||||
case 3:
|
||||
chroma_format_str = "4:4:4";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (chroma_format_str) {
|
||||
gst_caps_set_simple (entry->caps,
|
||||
"chroma-format", G_TYPE_STRING, chroma_format_str,
|
||||
NULL);
|
||||
}
|
||||
|
||||
if ((vpcc_data[14] & 0x1) != 0)
|
||||
cinfo.range = GST_VIDEO_COLOR_RANGE_0_255;
|
||||
else
|
||||
cinfo.range = GST_VIDEO_COLOR_RANGE_16_235;
|
||||
cinfo.primaries =
|
||||
gst_video_color_primaries_from_iso (vpcc_data[15]);
|
||||
cinfo.transfer =
|
||||
gst_video_color_transfer_from_iso (vpcc_data[16]);
|
||||
cinfo.matrix =
|
||||
gst_video_color_matrix_from_iso (vpcc_data[17]);
|
||||
|
||||
if (cinfo.primaries != GST_VIDEO_COLOR_PRIMARIES_UNKNOWN &&
|
||||
cinfo.transfer != GST_VIDEO_TRANSFER_UNKNOWN &&
|
||||
cinfo.matrix != GST_VIDEO_COLOR_MATRIX_UNKNOWN) {
|
||||
/* set this only if all values are known, otherwise this
|
||||
* might overwrite valid ones parsed from other color box */
|
||||
CUR_STREAM (stream)->colorimetry = cinfo;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
len -= size + 8;
|
||||
vpcc_data += size + 8;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue