OLD | NEW |
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "media/base/video_codecs.h" | 5 #include "media/base/video_codecs.h" |
6 | 6 |
7 #include "base/logging.h" | 7 #include "base/logging.h" |
8 #include "base/strings/string_number_conversions.h" | 8 #include "base/strings/string_number_conversions.h" |
9 #include "base/strings/string_split.h" | 9 #include "base/strings/string_split.h" |
10 #include "base/strings/string_util.h" | 10 #include "base/strings/string_util.h" |
| 11 #include "media/base/video_color_space.h" |
11 | 12 |
12 namespace media { | 13 namespace media { |
13 | 14 |
14 // The names come from src/third_party/ffmpeg/libavcodec/codec_desc.c | 15 // The names come from src/third_party/ffmpeg/libavcodec/codec_desc.c |
15 std::string GetCodecName(VideoCodec codec) { | 16 std::string GetCodecName(VideoCodec codec) { |
16 switch (codec) { | 17 switch (codec) { |
17 case kUnknownVideoCodec: | 18 case kUnknownVideoCodec: |
18 return "unknown"; | 19 return "unknown"; |
19 case kCodecH264: | 20 case kCodecH264: |
20 return "h264"; | 21 return "h264"; |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
87 return "dolby vision profile 4"; | 88 return "dolby vision profile 4"; |
88 case DOLBYVISION_PROFILE5: | 89 case DOLBYVISION_PROFILE5: |
89 return "dolby vision profile 5"; | 90 return "dolby vision profile 5"; |
90 case DOLBYVISION_PROFILE7: | 91 case DOLBYVISION_PROFILE7: |
91 return "dolby vision profile 7"; | 92 return "dolby vision profile 7"; |
92 } | 93 } |
93 NOTREACHED(); | 94 NOTREACHED(); |
94 return ""; | 95 return ""; |
95 } | 96 } |
96 | 97 |
97 // Described in ISO 23001-8:2016 Table 3. | |
98 bool ParseVp9Eotf(const int value, gfx::ColorSpace::TransferID* eotf) { | |
99 switch (value) { | |
100 case 1: | |
101 *eotf = gfx::ColorSpace::TransferID::BT709; | |
102 break; | |
103 case 2: | |
104 // "2" is interpreted as "Unspecified" | |
105 *eotf = gfx::ColorSpace::TransferID::INVALID; | |
106 break; | |
107 case 4: | |
108 *eotf = gfx::ColorSpace::TransferID::GAMMA22; | |
109 break; | |
110 case 5: | |
111 *eotf = gfx::ColorSpace::TransferID::GAMMA28; | |
112 break; | |
113 case 6: | |
114 *eotf = gfx::ColorSpace::TransferID::SMPTE170M; | |
115 break; | |
116 case 7: | |
117 *eotf = gfx::ColorSpace::TransferID::SMPTE240M; | |
118 break; | |
119 case 8: | |
120 *eotf = gfx::ColorSpace::TransferID::LINEAR; | |
121 break; | |
122 case 9: | |
123 *eotf = gfx::ColorSpace::TransferID::LOG; | |
124 break; | |
125 case 10: | |
126 *eotf = gfx::ColorSpace::TransferID::LOG_SQRT; | |
127 break; | |
128 case 11: | |
129 *eotf = gfx::ColorSpace::TransferID::IEC61966_2_4; | |
130 break; | |
131 case 12: | |
132 *eotf = gfx::ColorSpace::TransferID::BT1361_ECG; | |
133 break; | |
134 case 13: | |
135 *eotf = gfx::ColorSpace::TransferID::IEC61966_2_1; | |
136 break; | |
137 case 14: | |
138 *eotf = gfx::ColorSpace::TransferID::BT2020_10; | |
139 break; | |
140 case 15: | |
141 *eotf = gfx::ColorSpace::TransferID::BT2020_12; | |
142 break; | |
143 case 16: | |
144 *eotf = gfx::ColorSpace::TransferID::SMPTEST2084; | |
145 break; | |
146 case 17: | |
147 *eotf = gfx::ColorSpace::TransferID::SMPTEST428_1; | |
148 break; | |
149 default: | |
150 // Includes reserved values of 0, 3, 18 - 255. | |
151 *eotf = gfx::ColorSpace::TransferID::INVALID; | |
152 return false; | |
153 } | |
154 | |
155 return true; | |
156 } | |
157 | |
158 bool ParseNewStyleVp9CodecID(const std::string& codec_id, | 98 bool ParseNewStyleVp9CodecID(const std::string& codec_id, |
159 VideoCodecProfile* profile, | 99 VideoCodecProfile* profile, |
160 uint8_t* level_idc, | 100 uint8_t* level_idc, |
161 gfx::ColorSpace::TransferID* eotf) { | 101 VideoColorSpace* color_space) { |
162 // Initialize optional fields to their defaults. | 102 // Initialize optional fields to their defaults. |
163 *eotf = gfx::ColorSpace::TransferID::BT709; | 103 *color_space = VideoColorSpace::BT709(); |
164 | 104 |
165 std::vector<std::string> fields = base::SplitString( | 105 std::vector<std::string> fields = base::SplitString( |
166 codec_id, ".", base::KEEP_WHITESPACE, base::SPLIT_WANT_ALL); | 106 codec_id, ".", base::KEEP_WHITESPACE, base::SPLIT_WANT_ALL); |
167 | 107 |
168 // First four fields are mandatory. No more than 9 fields are expected. | 108 // First four fields are mandatory. No more than 9 fields are expected. |
169 if (fields.size() < 4 || fields.size() > 9) { | 109 if (fields.size() < 4 || fields.size() > 9) { |
170 DVLOG(3) << __func__ << " Invalid number of fields (" << fields.size() | 110 DVLOG(3) << __func__ << " Invalid number of fields (" << fields.size() |
171 << ")"; | 111 << ")"; |
172 return false; | 112 return false; |
173 } | 113 } |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
234 } | 174 } |
235 | 175 |
236 const int bit_depth = values[2]; | 176 const int bit_depth = values[2]; |
237 if (bit_depth != 8 && bit_depth != 10 && bit_depth != 12) { | 177 if (bit_depth != 8 && bit_depth != 10 && bit_depth != 12) { |
238 DVLOG(3) << __func__ << " Invalid bit-depth (" << bit_depth << ")"; | 178 DVLOG(3) << __func__ << " Invalid bit-depth (" << bit_depth << ")"; |
239 return false; | 179 return false; |
240 } | 180 } |
241 | 181 |
242 if (values.size() < 4) | 182 if (values.size() < 4) |
243 return true; | 183 return true; |
244 const int color_primaries = values[3]; | 184 color_space->primaries = VideoColorSpace::GetPrimaryID(values[3]); |
245 // TODO(chcunningham): parse and bubble up color primaries, described in ISO | 185 if (color_space->primaries == VideoColorSpace::PrimaryID::INVALID) { |
246 // 23001-8:2016 Table 2. | 186 DVLOG(3) << __func__ << " Invalid color primaries (" << values[3] << ")"; |
247 // Values 0, 3, and 23 - 255 are reserved. | |
248 if (color_primaries == 0 || color_primaries == 3 || color_primaries > 22) { | |
249 DVLOG(3) << __func__ << " Invalid color primaries (" << color_primaries | |
250 << ")"; | |
251 return false; | 187 return false; |
252 } | 188 } |
253 | 189 |
254 if (values.size() < 5) | 190 if (values.size() < 5) |
255 return true; | 191 return true; |
256 if (!ParseVp9Eotf(values[4], eotf)) { | 192 color_space->transfer = VideoColorSpace::GetTransferID(values[4]); |
| 193 if (color_space->transfer == VideoColorSpace::TransferID::INVALID) { |
257 DVLOG(3) << __func__ << " Invalid transfer function (" << values[4] << ")"; | 194 DVLOG(3) << __func__ << " Invalid transfer function (" << values[4] << ")"; |
258 return false; | 195 return false; |
259 } | 196 } |
260 | 197 |
261 // TODO(chcunningham): Parse and bubble up the following fields. For now just | |
262 // doing basic validation. | |
263 | |
264 if (values.size() < 6) | 198 if (values.size() < 6) |
265 return true; | 199 return true; |
266 const int matrix_coefficients = values[5]; | 200 color_space->matrix = VideoColorSpace::GetMatrixID(values[5]); |
267 if (matrix_coefficients > 11) { | 201 if (color_space->matrix == VideoColorSpace::MatrixID::INVALID) { |
268 DVLOG(3) << __func__ << " Invalid matrix coefficients (" | 202 DVLOG(3) << __func__ << " Invalid matrix coefficients (" << values[5] |
269 << matrix_coefficients << ")"; | 203 << ")"; |
270 return false; | 204 return false; |
271 } | 205 } |
272 | 206 |
273 if (values.size() < 7) | 207 if (values.size() < 7) |
274 return true; | 208 return true; |
275 const int video_full_range_flag = values[6]; | 209 const int video_full_range_flag = values[6]; |
276 if (video_full_range_flag > 1) { | 210 if (video_full_range_flag > 1) { |
277 DVLOG(3) << __func__ << " Invalid full range flag (" | 211 DVLOG(3) << __func__ << " Invalid full range flag (" |
278 << video_full_range_flag << ")"; | 212 << video_full_range_flag << ")"; |
279 return false; | 213 return false; |
280 } | 214 } |
| 215 color_space->range = video_full_range_flag == 1 |
| 216 ? gfx::ColorSpace::RangeID::FULL |
| 217 : gfx::ColorSpace::RangeID::LIMITED; |
281 | 218 |
282 if (values.size() < 8) | 219 if (values.size() < 8) |
283 return true; | 220 return true; |
284 const int chroma_subsampling = values[7]; | 221 const int chroma_subsampling = values[7]; |
285 if (chroma_subsampling > 3 || | 222 if (chroma_subsampling > 3 || |
286 (chroma_subsampling != 3 && matrix_coefficients == 0)) { | 223 (chroma_subsampling != 3 && |
| 224 color_space->matrix == VideoColorSpace::MatrixID::RGB)) { |
287 DVLOG(3) << __func__ << " Invalid chroma subsampling (" | 225 DVLOG(3) << __func__ << " Invalid chroma subsampling (" |
288 << chroma_subsampling << ")"; | 226 << chroma_subsampling << ")"; |
289 return false; | 227 return false; |
290 } | 228 } |
291 | 229 |
292 return true; | 230 return true; |
293 } | 231 } |
294 | 232 |
295 bool ParseLegacyVp9CodecID(const std::string& codec_id, | 233 bool ParseLegacyVp9CodecID(const std::string& codec_id, |
296 VideoCodecProfile* profile, | 234 VideoCodecProfile* profile, |
(...skipping 358 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
655 #endif | 593 #endif |
656 | 594 |
657 VideoCodec StringToVideoCodec(const std::string& codec_id) { | 595 VideoCodec StringToVideoCodec(const std::string& codec_id) { |
658 std::vector<std::string> elem = base::SplitString( | 596 std::vector<std::string> elem = base::SplitString( |
659 codec_id, ".", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL); | 597 codec_id, ".", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL); |
660 if (elem.empty()) | 598 if (elem.empty()) |
661 return kUnknownVideoCodec; | 599 return kUnknownVideoCodec; |
662 | 600 |
663 VideoCodecProfile profile = VIDEO_CODEC_PROFILE_UNKNOWN; | 601 VideoCodecProfile profile = VIDEO_CODEC_PROFILE_UNKNOWN; |
664 uint8_t level = 0; | 602 uint8_t level = 0; |
665 gfx::ColorSpace::TransferID eotf = gfx::ColorSpace::TransferID::INVALID; | 603 VideoColorSpace color_space; |
666 | 604 |
667 if (codec_id == "vp8" || codec_id == "vp8.0") | 605 if (codec_id == "vp8" || codec_id == "vp8.0") |
668 return kCodecVP8; | 606 return kCodecVP8; |
669 if (ParseNewStyleVp9CodecID(codec_id, &profile, &level, &eotf) || | 607 if (ParseNewStyleVp9CodecID(codec_id, &profile, &level, &color_space) || |
670 ParseLegacyVp9CodecID(codec_id, &profile, &level)) { | 608 ParseLegacyVp9CodecID(codec_id, &profile, &level)) { |
671 return kCodecVP9; | 609 return kCodecVP9; |
672 } | 610 } |
673 if (codec_id == "theora") | 611 if (codec_id == "theora") |
674 return kCodecTheora; | 612 return kCodecTheora; |
675 if (ParseAVCCodecId(codec_id, &profile, &level)) | 613 if (ParseAVCCodecId(codec_id, &profile, &level)) |
676 return kCodecH264; | 614 return kCodecH264; |
677 #if BUILDFLAG(ENABLE_MSE_MPEG2TS_STREAM_PARSER) | 615 #if BUILDFLAG(ENABLE_MSE_MPEG2TS_STREAM_PARSER) |
678 if (ParseAVCCodecId(TranslateLegacyAvc1CodecIds(codec_id), &profile, &level)) | 616 if (ParseAVCCodecId(TranslateLegacyAvc1CodecIds(codec_id), &profile, &level)) |
679 return kCodecH264; | 617 return kCodecH264; |
680 #endif | 618 #endif |
681 #if BUILDFLAG(ENABLE_HEVC_DEMUXING) | 619 #if BUILDFLAG(ENABLE_HEVC_DEMUXING) |
682 if (ParseHEVCCodecId(codec_id, &profile, &level)) | 620 if (ParseHEVCCodecId(codec_id, &profile, &level)) |
683 return kCodecHEVC; | 621 return kCodecHEVC; |
684 #endif | 622 #endif |
685 #if BUILDFLAG(ENABLE_DOLBY_VISION_DEMUXING) | 623 #if BUILDFLAG(ENABLE_DOLBY_VISION_DEMUXING) |
686 if (ParseDolbyVisionCodecId(codec_id, &profile, &level)) | 624 if (ParseDolbyVisionCodecId(codec_id, &profile, &level)) |
687 return kCodecDolbyVision; | 625 return kCodecDolbyVision; |
688 #endif | 626 #endif |
689 return kUnknownVideoCodec; | 627 return kUnknownVideoCodec; |
690 } | 628 } |
691 | 629 |
692 } // namespace media | 630 } // namespace media |
OLD | NEW |