| 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 |