Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2012 The Chromium Authors. All rights reserved. | 1 // Copyright 2012 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/mime_util_internal.h" | 5 #include "media/base/mime_util_internal.h" |
| 6 | 6 |
| 7 #include "base/strings/string_number_conversions.h" | 7 #include "base/strings/string_number_conversions.h" |
| 8 #include "base/strings/string_split.h" | 8 #include "base/strings/string_split.h" |
| 9 #include "base/strings/string_util.h" | 9 #include "base/strings/string_util.h" |
| 10 #include "build/build_config.h" | 10 #include "build/build_config.h" |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 26 }; | 26 }; |
| 27 | 27 |
| 28 // List of codec IDs that provide enough information to determine the | 28 // List of codec IDs that provide enough information to determine the |
| 29 // codec and profile being requested. | 29 // codec and profile being requested. |
| 30 // | 30 // |
| 31 // The "mp4a" strings come from RFC 6381. | 31 // The "mp4a" strings come from RFC 6381. |
| 32 static const CodecIDMappings kUnambiguousCodecStringMap[] = { | 32 static const CodecIDMappings kUnambiguousCodecStringMap[] = { |
| 33 {"1", MimeUtil::PCM}, // We only allow this for WAV so it isn't ambiguous. | 33 {"1", MimeUtil::PCM}, // We only allow this for WAV so it isn't ambiguous. |
| 34 // avc1/avc3.XXXXXX may be unambiguous; handled by ParseAVCCodecId(). | 34 // avc1/avc3.XXXXXX may be unambiguous; handled by ParseAVCCodecId(). |
| 35 // hev1/hvc1.XXXXXX may be unambiguous; handled by ParseHEVCCodecID(). | 35 // hev1/hvc1.XXXXXX may be unambiguous; handled by ParseHEVCCodecID(). |
| 36 // vp9, vp9.0, vp09.xx.xx.xx.xx.xx.xx.xx may be unambiguous; handled by | |
|
ddorwin
2016/04/18 22:53:29
Is it possible for these to be ambiguous (at least
kqyang
2016/04/19 00:28:05
Per your suggestion below. Now it might be ambiguo
ddorwin
2016/04/19 17:10:00
ambiguous is not the same as "maybe". I'll make th
| |
| 37 // ParseVp9CodecID(). | |
| 36 {"mp3", MimeUtil::MP3}, | 38 {"mp3", MimeUtil::MP3}, |
| 37 // Following is the list of RFC 6381 compliant audio codec strings: | 39 // Following is the list of RFC 6381 compliant audio codec strings: |
| 38 // mp4a.66 - MPEG-2 AAC MAIN | 40 // mp4a.66 - MPEG-2 AAC MAIN |
| 39 // mp4a.67 - MPEG-2 AAC LC | 41 // mp4a.67 - MPEG-2 AAC LC |
| 40 // mp4a.68 - MPEG-2 AAC SSR | 42 // mp4a.68 - MPEG-2 AAC SSR |
| 41 // mp4a.69 - MPEG-2 extension to MPEG-1 (MP3) | 43 // mp4a.69 - MPEG-2 extension to MPEG-1 (MP3) |
| 42 // mp4a.6B - MPEG-1 audio (MP3) | 44 // mp4a.6B - MPEG-1 audio (MP3) |
| 43 // mp4a.40.2 - MPEG-4 AAC LC | 45 // mp4a.40.2 - MPEG-4 AAC LC |
| 44 // mp4a.40.02 - MPEG-4 AAC LC (leading 0 in aud-oti for compatibility) | 46 // mp4a.40.02 - MPEG-4 AAC LC (leading 0 in aud-oti for compatibility) |
| 45 // mp4a.40.5 - MPEG-4 HE-AAC v1 (AAC LC + SBR) | 47 // mp4a.40.5 - MPEG-4 HE-AAC v1 (AAC LC + SBR) |
| (...skipping 21 matching lines...) Expand all Loading... | |
| 67 {"mp4a.a5", MimeUtil::AC3}, | 69 {"mp4a.a5", MimeUtil::AC3}, |
| 68 {"mp4a.A5", MimeUtil::AC3}, | 70 {"mp4a.A5", MimeUtil::AC3}, |
| 69 {"ec-3", MimeUtil::EAC3}, | 71 {"ec-3", MimeUtil::EAC3}, |
| 70 {"mp4a.a6", MimeUtil::EAC3}, | 72 {"mp4a.a6", MimeUtil::EAC3}, |
| 71 {"mp4a.A6", MimeUtil::EAC3}, | 73 {"mp4a.A6", MimeUtil::EAC3}, |
| 72 #endif | 74 #endif |
| 73 {"vorbis", MimeUtil::VORBIS}, | 75 {"vorbis", MimeUtil::VORBIS}, |
| 74 {"opus", MimeUtil::OPUS}, | 76 {"opus", MimeUtil::OPUS}, |
| 75 {"vp8", MimeUtil::VP8}, | 77 {"vp8", MimeUtil::VP8}, |
| 76 {"vp8.0", MimeUtil::VP8}, | 78 {"vp8.0", MimeUtil::VP8}, |
| 77 {"vp9", MimeUtil::VP9}, | |
| 78 {"vp9.0", MimeUtil::VP9}, | |
| 79 {"theora", MimeUtil::THEORA}}; | 79 {"theora", MimeUtil::THEORA}}; |
| 80 | 80 |
| 81 // List of codec IDs that are ambiguous and don't provide | 81 // List of codec IDs that are ambiguous and don't provide |
| 82 // enough information to determine the codec and profile. | 82 // enough information to determine the codec and profile. |
| 83 // The codec in these entries indicate the codec and profile | 83 // The codec in these entries indicate the codec and profile |
| 84 // we assume the user is trying to indicate. | 84 // we assume the user is trying to indicate. |
| 85 static const CodecIDMappings kAmbiguousCodecStringMap[] = { | 85 static const CodecIDMappings kAmbiguousCodecStringMap[] = { |
| 86 {"mp4a.40", MimeUtil::MPEG4_AAC}, | 86 {"mp4a.40", MimeUtil::MPEG4_AAC}, |
| 87 {"avc1", MimeUtil::H264}, | 87 {"avc1", MimeUtil::H264}, |
| 88 {"avc3", MimeUtil::H264}, | 88 {"avc3", MimeUtil::H264}, |
| (...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 178 *is_ambiguous = false; | 178 *is_ambiguous = false; |
| 179 } | 179 } |
| 180 | 180 |
| 181 return true; | 181 return true; |
| 182 } | 182 } |
| 183 | 183 |
| 184 return false; | 184 return false; |
| 185 } | 185 } |
| 186 #endif | 186 #endif |
| 187 | 187 |
| 188 // Handle parsing of vp9 codec IDs. | |
| 189 static bool ParseVp9CodecID(const std::string& mime_type_lower_case, | |
| 190 const std::string& codec_id, | |
| 191 MimeUtil::Codec* codec) { | |
| 192 if (mime_type_lower_case == "video/webm") { | |
| 193 if (codec_id == "vp9" || codec_id == "vp9.0") { | |
| 194 *codec = MimeUtil::VP9; | |
| 195 return true; | |
| 196 } | |
| 197 // TODO(kqyang): Should we support new codec string in WebM? | |
| 198 return false; | |
| 199 } else if (mime_type_lower_case == "audio/webm") { | |
| 200 return false; | |
| 201 } | |
| 202 | |
| 203 #if BUILDFLAG(ENABLE_MP4_VP9_DEMUXING) | |
| 204 std::vector<std::string> fields = base::SplitString( | |
| 205 codec_id, ".", base::KEEP_WHITESPACE, base::SPLIT_WANT_ALL); | |
| 206 if (fields.size() < 1) | |
| 207 return false; | |
| 208 | |
| 209 if (fields[0] == "vp09") { | |
| 210 *codec = MimeUtil::VP9; | |
| 211 } else { | |
| 212 return false; | |
| 213 } | |
| 214 | |
| 215 if (fields.size() > 8) | |
| 216 return false; | |
| 217 | |
| 218 std::vector<int> values; | |
| 219 for (size_t i = 1; i < fields.size(); ++i) { | |
| 220 // Missing value is not allowed. | |
| 221 if (fields[i] == "") | |
| 222 return false; | |
| 223 int value; | |
| 224 if (!base::StringToInt(fields[i], &value)) | |
| 225 return false; | |
| 226 if (value < 0) | |
| 227 return false; | |
| 228 values.push_back(value); | |
| 229 } | |
| 230 | |
| 231 // The spec specifies 8 fields (7 values excluding the first codec field). | |
| 232 // We do not allow missing fields. | |
| 233 if (values.size() < 7) | |
| 234 return false; | |
| 235 | |
| 236 const int profile = values[0]; | |
| 237 if (profile > 3) | |
| 238 return false; | |
| 239 | |
| 240 const int bit_depth = values[2]; | |
| 241 if (bit_depth != 8 && bit_depth != 10 && bit_depth != 12) | |
| 242 return false; | |
| 243 | |
| 244 const int color_space = values[3]; | |
| 245 if (color_space > 7) | |
| 246 return false; | |
| 247 | |
| 248 const int chroma_subsampling = values[4]; | |
| 249 if (chroma_subsampling > 3) | |
| 250 return false; | |
| 251 | |
| 252 const int transfer_function = values[5]; | |
| 253 if (transfer_function > 1) | |
| 254 return false; | |
| 255 | |
| 256 const int video_full_range_flag = values[6]; | |
| 257 if (video_full_range_flag > 1) | |
| 258 return false; | |
| 259 | |
| 260 return true; | |
| 261 #else | |
| 262 return false; | |
| 263 #endif // #if BUILDFLAG(ENABLE_MP4_VP9_DEMUXING) | |
| 264 } | |
| 265 | |
| 188 MimeUtil::MimeUtil() : allow_proprietary_codecs_(false) { | 266 MimeUtil::MimeUtil() : allow_proprietary_codecs_(false) { |
| 189 #if defined(OS_ANDROID) | 267 #if defined(OS_ANDROID) |
| 190 platform_info_.is_unified_media_pipeline_enabled = | 268 platform_info_.is_unified_media_pipeline_enabled = |
| 191 IsUnifiedMediaPipelineEnabled(); | 269 IsUnifiedMediaPipelineEnabled(); |
| 192 // When the unified media pipeline is enabled, we need support for both GPU | 270 // When the unified media pipeline is enabled, we need support for both GPU |
| 193 // video decoders and MediaCodec; indicated by HasPlatformDecoderSupport(). | 271 // video decoders and MediaCodec; indicated by HasPlatformDecoderSupport(). |
| 194 // When the Android pipeline is used, we only need access to MediaCodec. | 272 // When the Android pipeline is used, we only need access to MediaCodec. |
| 195 platform_info_.has_platform_decoders = ArePlatformDecodersAvailable(); | 273 platform_info_.has_platform_decoders = ArePlatformDecodersAvailable(); |
| 196 platform_info_.has_platform_vp8_decoder = | 274 platform_info_.has_platform_vp8_decoder = |
| 197 MediaCodecUtil::IsVp8DecoderAvailable(); | 275 MediaCodecUtil::IsVp8DecoderAvailable(); |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 210 const std::vector<std::string>& codecs, | 288 const std::vector<std::string>& codecs, |
| 211 const std::string& mime_type_lower_case, | 289 const std::string& mime_type_lower_case, |
| 212 bool is_encrypted) const { | 290 bool is_encrypted) const { |
| 213 DCHECK(!supported_codecs.empty()); | 291 DCHECK(!supported_codecs.empty()); |
| 214 DCHECK(!codecs.empty()); | 292 DCHECK(!codecs.empty()); |
| 215 | 293 |
| 216 SupportsType result = IsSupported; | 294 SupportsType result = IsSupported; |
| 217 for (size_t i = 0; i < codecs.size(); ++i) { | 295 for (size_t i = 0; i < codecs.size(); ++i) { |
| 218 bool is_ambiguous = true; | 296 bool is_ambiguous = true; |
| 219 Codec codec = INVALID_CODEC; | 297 Codec codec = INVALID_CODEC; |
| 220 if (!StringToCodec(codecs[i], &codec, &is_ambiguous, is_encrypted)) | 298 if (!StringToCodec(mime_type_lower_case, codecs[i], &codec, &is_ambiguous, |
| 299 is_encrypted)) { | |
| 221 return IsNotSupported; | 300 return IsNotSupported; |
| 301 } | |
| 222 | 302 |
| 223 if (!IsCodecSupported(codec, mime_type_lower_case, is_encrypted) || | 303 if (!IsCodecSupported(codec, mime_type_lower_case, is_encrypted) || |
| 224 supported_codecs.find(codec) == supported_codecs.end()) { | 304 supported_codecs.find(codec) == supported_codecs.end()) { |
| 225 return IsNotSupported; | 305 return IsNotSupported; |
| 226 } | 306 } |
| 227 | 307 |
| 228 if (is_ambiguous) | 308 if (is_ambiguous) |
| 229 result = MayBeSupported; | 309 result = MayBeSupported; |
| 230 } | 310 } |
| 231 | 311 |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 294 #if BUILDFLAG(ENABLE_AC3_EAC3_AUDIO_DEMUXING) | 374 #if BUILDFLAG(ENABLE_AC3_EAC3_AUDIO_DEMUXING) |
| 295 mp4_audio_codecs.insert(AC3); | 375 mp4_audio_codecs.insert(AC3); |
| 296 mp4_audio_codecs.insert(EAC3); | 376 mp4_audio_codecs.insert(EAC3); |
| 297 #endif // BUILDFLAG(ENABLE_AC3_EAC3_AUDIO_DEMUXING) | 377 #endif // BUILDFLAG(ENABLE_AC3_EAC3_AUDIO_DEMUXING) |
| 298 | 378 |
| 299 CodecSet mp4_video_codecs; | 379 CodecSet mp4_video_codecs; |
| 300 mp4_video_codecs.insert(H264); | 380 mp4_video_codecs.insert(H264); |
| 301 #if BUILDFLAG(ENABLE_HEVC_DEMUXING) | 381 #if BUILDFLAG(ENABLE_HEVC_DEMUXING) |
| 302 mp4_video_codecs.insert(HEVC_MAIN); | 382 mp4_video_codecs.insert(HEVC_MAIN); |
| 303 #endif // BUILDFLAG(ENABLE_HEVC_DEMUXING) | 383 #endif // BUILDFLAG(ENABLE_HEVC_DEMUXING) |
| 384 #if BUILDFLAG(ENABLE_MP4_VP9_DEMUXING) | |
| 385 // Only VP9 with valid codec string vp09.xx.xx.xx.xx.xx.xx.xx is supported. | |
| 386 // See ParseVp9CodecID for details. | |
| 387 mp4_video_codecs.insert(VP9); | |
| 388 #endif // BUILDFLAG(ENABLE_MP4_VP9_DEMUXING) | |
| 304 CodecSet mp4_codecs(mp4_audio_codecs); | 389 CodecSet mp4_codecs(mp4_audio_codecs); |
| 305 mp4_codecs.insert(mp4_video_codecs.begin(), mp4_video_codecs.end()); | 390 mp4_codecs.insert(mp4_video_codecs.begin(), mp4_video_codecs.end()); |
| 306 #endif // defined(USE_PROPRIETARY_CODECS) | 391 #endif // defined(USE_PROPRIETARY_CODECS) |
| 307 | 392 |
| 308 AddContainerWithCodecs("audio/wav", wav_codecs, false); | 393 AddContainerWithCodecs("audio/wav", wav_codecs, false); |
| 309 AddContainerWithCodecs("audio/x-wav", wav_codecs, false); | 394 AddContainerWithCodecs("audio/x-wav", wav_codecs, false); |
| 310 AddContainerWithCodecs("audio/webm", webm_audio_codecs, false); | 395 AddContainerWithCodecs("audio/webm", webm_audio_codecs, false); |
| 311 DCHECK(!webm_video_codecs.empty()); | 396 DCHECK(!webm_video_codecs.empty()); |
| 312 AddContainerWithCodecs("video/webm", webm_codecs, false); | 397 AddContainerWithCodecs("video/webm", webm_codecs, false); |
| 313 AddContainerWithCodecs("audio/ogg", ogg_audio_codecs, false); | 398 AddContainerWithCodecs("audio/ogg", ogg_audio_codecs, false); |
| (...skipping 232 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 546 | 631 |
| 547 // MediaPlayer can always play VP8. Note: This is incorrect for MSE, but | 632 // MediaPlayer can always play VP8. Note: This is incorrect for MSE, but |
| 548 // MSE does not use this code. http://crbug.com/587303. | 633 // MSE does not use this code. http://crbug.com/587303. |
| 549 return true; | 634 return true; |
| 550 | 635 |
| 551 case VP9: { | 636 case VP9: { |
| 552 // If clear, the unified pipeline can always decode VP9 in software. | 637 // If clear, the unified pipeline can always decode VP9 in software. |
| 553 if (!is_encrypted && platform_info.is_unified_media_pipeline_enabled) | 638 if (!is_encrypted && platform_info.is_unified_media_pipeline_enabled) |
| 554 return true; | 639 return true; |
| 555 | 640 |
| 556 // Otherwise, platform support is required. | 641 if (!platform_info.has_platform_vp9_decoder) |
| 557 return platform_info.has_platform_vp9_decoder; | 642 return false; |
| 643 | |
| 644 // Encrypted content is demuxed so the container is irrelevant. | |
| 645 if (is_encrypted) | |
| 646 return true; | |
| 647 | |
| 648 // MediaPlayer only supports VP9 in WebM. | |
| 649 return mime_type_lower_case == "video/webm"; | |
| 558 } | 650 } |
| 559 } | 651 } |
| 560 | 652 |
| 561 return false; | 653 return false; |
| 562 } | 654 } |
| 563 | 655 |
| 564 bool MimeUtil::StringToCodec(const std::string& codec_id, | 656 bool MimeUtil::StringToCodec(const std::string& mime_type_lower_case, |
| 657 const std::string& codec_id, | |
| 565 Codec* codec, | 658 Codec* codec, |
| 566 bool* is_ambiguous, | 659 bool* is_ambiguous, |
| 567 bool is_encrypted) const { | 660 bool is_encrypted) const { |
| 568 StringToCodecMappings::const_iterator itr = | 661 StringToCodecMappings::const_iterator itr = |
| 569 string_to_codec_map_.find(codec_id); | 662 string_to_codec_map_.find(codec_id); |
| 570 if (itr != string_to_codec_map_.end()) { | 663 if (itr != string_to_codec_map_.end()) { |
| 571 *codec = itr->second.codec; | 664 *codec = itr->second.codec; |
| 572 *is_ambiguous = itr->second.is_ambiguous; | 665 *is_ambiguous = itr->second.is_ambiguous; |
| 573 return true; | 666 return true; |
| 574 } | 667 } |
| (...skipping 30 matching lines...) Expand all Loading... | |
| 605 case H264PROFILE_MAIN: | 698 case H264PROFILE_MAIN: |
| 606 case H264PROFILE_HIGH: | 699 case H264PROFILE_HIGH: |
| 607 *is_ambiguous = !IsValidH264Level(level_idc); | 700 *is_ambiguous = !IsValidH264Level(level_idc); |
| 608 break; | 701 break; |
| 609 default: | 702 default: |
| 610 *is_ambiguous = true; | 703 *is_ambiguous = true; |
| 611 } | 704 } |
| 612 return true; | 705 return true; |
| 613 } | 706 } |
| 614 | 707 |
| 708 if (ParseVp9CodecID(mime_type_lower_case, codec_id, codec)) { | |
| 709 *is_ambiguous = false; | |
|
ddorwin
2016/04/18 22:53:29
Please see the conversations at https://codereview
kqyang
2016/04/19 00:28:05
Done. vp9 and vp9.0 are assumed to be profile 0.
| |
| 710 return true; | |
| 711 } | |
| 712 | |
| 615 DVLOG(4) << __FUNCTION__ << ": Unrecognized codec id " << codec_id; | 713 DVLOG(4) << __FUNCTION__ << ": Unrecognized codec id " << codec_id; |
| 616 return false; | 714 return false; |
| 617 } | 715 } |
| 618 | 716 |
| 619 bool MimeUtil::IsCodecSupported(Codec codec, | 717 bool MimeUtil::IsCodecSupported(Codec codec, |
| 620 const std::string& mime_type_lower_case, | 718 const std::string& mime_type_lower_case, |
| 621 bool is_encrypted) const { | 719 bool is_encrypted) const { |
| 622 DCHECK_NE(codec, INVALID_CODEC); | 720 DCHECK_NE(codec, INVALID_CODEC); |
| 623 | 721 |
| 624 #if defined(OS_ANDROID) | 722 #if defined(OS_ANDROID) |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 676 const std::string& mime_type_lower_case, | 774 const std::string& mime_type_lower_case, |
| 677 bool is_encrypted) const { | 775 bool is_encrypted) const { |
| 678 Codec default_codec = Codec::INVALID_CODEC; | 776 Codec default_codec = Codec::INVALID_CODEC; |
| 679 if (!GetDefaultCodecLowerCase(mime_type_lower_case, &default_codec)) | 777 if (!GetDefaultCodecLowerCase(mime_type_lower_case, &default_codec)) |
| 680 return false; | 778 return false; |
| 681 return IsCodecSupported(default_codec, mime_type_lower_case, is_encrypted); | 779 return IsCodecSupported(default_codec, mime_type_lower_case, is_encrypted); |
| 682 } | 780 } |
| 683 | 781 |
| 684 } // namespace internal | 782 } // namespace internal |
| 685 } // namespace media | 783 } // namespace media |
| OLD | NEW |