1 // Copyright (c) 2016 The WebM project authors. All Rights Reserved.
3 // Use of this source code is governed by a BSD-style license
4 // that can be found in the LICENSE file in the root of the source
5 // tree. An additional intellectual property rights grant can be found
6 // in the file PATENTS. All contributing project authors may
7 // be found in the AUTHORS file in the root of the source tree.
14 #include "mkvparser/mkvparser.h"
17 const int Vp9CodecFeatures::kValueNotPresent = INT_MAX;
19 bool CopyPrimaryChromaticity(const mkvparser::PrimaryChromaticity& parser_pc,
20 PrimaryChromaticityPtr* muxer_pc) {
21 muxer_pc->reset(new (std::nothrow)
22 mkvmuxer::PrimaryChromaticity(parser_pc.x, parser_pc.y));
28 bool MasteringMetadataValuePresent(double value) {
29 return value != mkvparser::MasteringMetadata::kValueNotPresent;
32 bool CopyMasteringMetadata(const mkvparser::MasteringMetadata& parser_mm,
33 mkvmuxer::MasteringMetadata* muxer_mm) {
34 if (MasteringMetadataValuePresent(parser_mm.luminance_max))
35 muxer_mm->set_luminance_max(parser_mm.luminance_max);
36 if (MasteringMetadataValuePresent(parser_mm.luminance_min))
37 muxer_mm->set_luminance_min(parser_mm.luminance_min);
39 PrimaryChromaticityPtr r_ptr(nullptr);
40 PrimaryChromaticityPtr g_ptr(nullptr);
41 PrimaryChromaticityPtr b_ptr(nullptr);
42 PrimaryChromaticityPtr wp_ptr(nullptr);
45 if (!CopyPrimaryChromaticity(*parser_mm.r, &r_ptr))
49 if (!CopyPrimaryChromaticity(*parser_mm.g, &g_ptr))
53 if (!CopyPrimaryChromaticity(*parser_mm.b, &b_ptr))
56 if (parser_mm.white_point) {
57 if (!CopyPrimaryChromaticity(*parser_mm.white_point, &wp_ptr))
61 if (!muxer_mm->SetChromaticity(r_ptr.get(), g_ptr.get(), b_ptr.get(),
69 bool ColourValuePresent(long long value) {
70 return value != mkvparser::Colour::kValueNotPresent;
73 bool CopyColour(const mkvparser::Colour& parser_colour,
74 mkvmuxer::Colour* muxer_colour) {
78 if (ColourValuePresent(parser_colour.matrix_coefficients))
79 muxer_colour->set_matrix_coefficients(parser_colour.matrix_coefficients);
80 if (ColourValuePresent(parser_colour.bits_per_channel))
81 muxer_colour->set_bits_per_channel(parser_colour.bits_per_channel);
82 if (ColourValuePresent(parser_colour.chroma_subsampling_horz)) {
83 muxer_colour->set_chroma_subsampling_horz(
84 parser_colour.chroma_subsampling_horz);
86 if (ColourValuePresent(parser_colour.chroma_subsampling_vert)) {
87 muxer_colour->set_chroma_subsampling_vert(
88 parser_colour.chroma_subsampling_vert);
90 if (ColourValuePresent(parser_colour.cb_subsampling_horz))
91 muxer_colour->set_cb_subsampling_horz(parser_colour.cb_subsampling_horz);
92 if (ColourValuePresent(parser_colour.cb_subsampling_vert))
93 muxer_colour->set_cb_subsampling_vert(parser_colour.cb_subsampling_vert);
94 if (ColourValuePresent(parser_colour.chroma_siting_horz))
95 muxer_colour->set_chroma_siting_horz(parser_colour.chroma_siting_horz);
96 if (ColourValuePresent(parser_colour.chroma_siting_vert))
97 muxer_colour->set_chroma_siting_vert(parser_colour.chroma_siting_vert);
98 if (ColourValuePresent(parser_colour.range))
99 muxer_colour->set_range(parser_colour.range);
100 if (ColourValuePresent(parser_colour.transfer_characteristics)) {
101 muxer_colour->set_transfer_characteristics(
102 parser_colour.transfer_characteristics);
104 if (ColourValuePresent(parser_colour.primaries))
105 muxer_colour->set_primaries(parser_colour.primaries);
106 if (ColourValuePresent(parser_colour.max_cll))
107 muxer_colour->set_max_cll(parser_colour.max_cll);
108 if (ColourValuePresent(parser_colour.max_fall))
109 muxer_colour->set_max_fall(parser_colour.max_fall);
111 if (parser_colour.mastering_metadata) {
112 mkvmuxer::MasteringMetadata muxer_mm;
113 if (!CopyMasteringMetadata(*parser_colour.mastering_metadata, &muxer_mm))
115 if (!muxer_colour->SetMasteringMetadata(muxer_mm))
121 // Format of VPx private data:
123 // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
124 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
125 // | ID Byte | Length | |
126 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
128 // : Bytes 1..Length of Codec Feature :
130 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
133 // ID byte is an unsigned byte.
139 // The X bit is reserved.
141 // See the following link for more information:
142 // http://www.webmproject.org/vp9/profiles/
143 bool ParseVpxCodecPrivate(const uint8_t* private_data, int32_t length,
144 Vp9CodecFeatures* features) {
145 const int kVpxCodecPrivateMinLength = 3;
146 if (!private_data || !features || length < kVpxCodecPrivateMinLength)
149 const uint8_t kVp9ProfileId = 1;
150 const uint8_t kVp9LevelId = 2;
151 const uint8_t kVp9BitDepthId = 3;
152 const uint8_t kVp9ChromaSubsamplingId = 4;
153 const int kVpxFeatureLength = 1;
156 // Set features to not set.
157 features->profile = Vp9CodecFeatures::kValueNotPresent;
158 features->level = Vp9CodecFeatures::kValueNotPresent;
159 features->bit_depth = Vp9CodecFeatures::kValueNotPresent;
160 features->chroma_subsampling = Vp9CodecFeatures::kValueNotPresent;
162 const uint8_t id_byte = private_data[offset++];
163 const uint8_t length_byte = private_data[offset++];
164 if (length_byte != kVpxFeatureLength)
166 if (id_byte == kVp9ProfileId) {
167 const int priv_profile = static_cast<int>(private_data[offset++]);
168 if (priv_profile < 0 || priv_profile > 3)
170 if (features->profile != Vp9CodecFeatures::kValueNotPresent &&
171 features->profile != priv_profile) {
174 features->profile = priv_profile;
175 } else if (id_byte == kVp9LevelId) {
176 const int priv_level = static_cast<int>(private_data[offset++]);
178 const int kNumLevels = 14;
179 const int levels[kNumLevels] = {10, 11, 20, 21, 30, 31, 40,
180 41, 50, 51, 52, 60, 61, 62};
182 for (int i = 0; i < kNumLevels; ++i) {
183 if (priv_level == levels[i]) {
184 if (features->level != Vp9CodecFeatures::kValueNotPresent &&
185 features->level != priv_level) {
188 features->level = priv_level;
192 if (features->level == Vp9CodecFeatures::kValueNotPresent)
194 } else if (id_byte == kVp9BitDepthId) {
195 const int priv_profile = static_cast<int>(private_data[offset++]);
196 if (priv_profile != 8 && priv_profile != 10 && priv_profile != 12)
198 if (features->bit_depth != Vp9CodecFeatures::kValueNotPresent &&
199 features->bit_depth != priv_profile) {
202 features->bit_depth = priv_profile;
203 } else if (id_byte == kVp9ChromaSubsamplingId) {
204 const int priv_profile = static_cast<int>(private_data[offset++]);
205 if (priv_profile != 0 && priv_profile != 2 && priv_profile != 3)
207 if (features->chroma_subsampling != Vp9CodecFeatures::kValueNotPresent &&
208 features->chroma_subsampling != priv_profile) {
211 features->chroma_subsampling = priv_profile;
216 } while (offset + kVpxCodecPrivateMinLength <= length);
220 } // namespace libwebm