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" |
| 11 #include "media/base/media.h" | 11 #include "media/base/media.h" |
| 12 #include "media/base/video_codecs.h" | 12 #include "media/base/video_codecs.h" |
| 13 #include "media/media_features.h" | 13 #include "media/media_features.h" |
| 14 | 14 |
| 15 #if defined(OS_ANDROID) | 15 #if defined(OS_ANDROID) |
| 16 #include "base/android/build_info.h" | 16 #include "base/android/build_info.h" |
| 17 #include "media/base/android/media_codec_util.h" | 17 #include "media/base/android/media_codec_util.h" |
| 18 #endif | 18 #endif |
| 19 | 19 |
| 20 namespace media { | 20 namespace media { |
| 21 namespace internal { | 21 namespace internal { |
| 22 | 22 |
| 23 enum MediaFormatType { COMMON, PROPRIETARY }; | |
| 24 | |
| 25 struct MediaFormat { | |
| 26 const char* const mime_type; | |
| 27 MediaFormatType format_type; | |
| 28 const char* const codecs_list; | |
| 29 }; | |
| 30 | |
| 31 // Strings used as the |codecs_list| only need one valid unambiguous variant for | |
| 32 // each supported MimeUtil::Codec enum value. Each codec string is parsed and | |
| 33 // mapped to corresponding MimeUtil::Codec value. See https://crbug.com/461009. | |
| 34 #if defined(USE_PROPRIETARY_CODECS) | |
| 35 static const char kMP4AudioCodecsExpression[] = | |
| 36 #if BUILDFLAG(ENABLE_AC3_EAC3_AUDIO_DEMUXING) | |
| 37 "ac-3,ec-3," // AC-3 and E-AC-3. | |
| 38 #endif | |
| 39 "mp4a.66,mp4a.69,mp4a.40.2"; // MPEG-2 AAC, MP3, and MPEG-4 AAC. | |
| 40 static const char kMP4VideoCodecsExpression[] = | |
| 41 "avc1.42E00A," | |
| 42 #if BUILDFLAG(ENABLE_HEVC_DEMUXING) | |
| 43 "hev1.1.6.L93.B0," | |
| 44 #endif | |
| 45 #if BUILDFLAG(ENABLE_AC3_EAC3_AUDIO_DEMUXING) | |
| 46 "ac-3,ec-3," // AC-3 and E-AC-3. | |
| 47 #endif | |
| 48 "mp4a.66,mp4a.69,mp4a.40.2"; // MPEG-2 AAC, MP3, and MPEG-4 AAC. | |
| 49 #endif // USE_PROPRIETARY_CODECS | |
| 50 | |
| 51 // A list of media types (https://en.wikipedia.org/wiki/Media_type) and | |
| 52 // corresponding media codecs supported by these types/containers. | |
| 53 // Media formats marked as PROPRIETARY are not supported by Chromium, only | |
| 54 // Google Chrome browser supports them. | |
| 55 static const MediaFormat kFormatCodecMappings[] = { | |
| 56 {"video/webm", COMMON, "opus,vorbis,vp8,vp9"}, | |
| 57 {"audio/webm", COMMON, "opus,vorbis"}, | |
| 58 {"audio/wav", COMMON, "1"}, | |
| 59 {"audio/x-wav", COMMON, "1"}, | |
| 60 #if !defined(OS_ANDROID) | |
| 61 // Note: Android does not support Theora and thus video/ogg. | |
| 62 {"video/ogg", COMMON, "opus,theora,vorbis"}, | |
| 63 #endif | |
| 64 {"audio/ogg", COMMON, "opus,vorbis"}, | |
| 65 // Note: Theora is not supported on Android and will be rejected during the | |
| 66 // call to IsCodecSupportedOnPlatform(). | |
| 67 {"application/ogg", COMMON, "opus,theora,vorbis"}, | |
| 68 #if defined(USE_PROPRIETARY_CODECS) | |
| 69 {"audio/mpeg", PROPRIETARY, "mp3"}, | |
| 70 {"audio/mp3", PROPRIETARY, ""}, | |
| 71 {"audio/x-mp3", PROPRIETARY, ""}, | |
| 72 {"audio/aac", PROPRIETARY, ""}, // AAC / ADTS | |
| 73 {"audio/mp4", PROPRIETARY, kMP4AudioCodecsExpression}, | |
| 74 {"audio/x-m4a", PROPRIETARY, kMP4AudioCodecsExpression}, | |
| 75 {"video/mp4", PROPRIETARY, kMP4VideoCodecsExpression}, | |
| 76 {"video/x-m4v", PROPRIETARY, kMP4VideoCodecsExpression}, | |
| 77 #if BUILDFLAG(ENABLE_MSE_MPEG2TS_STREAM_PARSER) | |
| 78 {"video/mp2t", PROPRIETARY, kMP4VideoCodecsExpression}, | |
| 79 #endif | |
| 80 #if defined(OS_ANDROID) | |
| 81 // HTTP Live Streaming (HLS) | |
| 82 {"application/x-mpegurl", PROPRIETARY, kMP4VideoCodecsExpression}, | |
| 83 {"application/vnd.apple.mpegurl", PROPRIETARY, kMP4VideoCodecsExpression} | |
| 84 #endif | |
| 85 #endif // USE_PROPRIETARY_CODECS | |
| 86 }; | |
| 87 | |
| 88 struct CodecIDMappings { | 23 struct CodecIDMappings { |
| 89 const char* const codec_id; | 24 const char* const codec_id; |
| 90 MimeUtil::Codec codec; | 25 MimeUtil::Codec codec; |
| 91 }; | 26 }; |
| 92 | 27 |
| 93 // List of codec IDs that provide enough information to determine the | 28 // List of codec IDs that provide enough information to determine the |
| 94 // codec and profile being requested. | 29 // codec and profile being requested. |
| 95 // | 30 // |
| 96 // The "mp4a" strings come from RFC 6381. | 31 // The "mp4a" strings come from RFC 6381. |
| 97 static const CodecIDMappings kUnambiguousCodecStringMap[] = { | 32 static const CodecIDMappings kUnambiguousCodecStringMap[] = { |
| 98 {"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. |
| 99 // avc1/avc3.XXXXXX may be unambiguous; handled by ParseAVCCodecId(). | 34 // avc1/avc3.XXXXXX may be unambiguous; handled by ParseAVCCodecId(). |
| 100 // hev1/hvc1.XXXXXX may be unambiguous; handled by ParseHEVCCodecID(). | 35 // hev1/hvc1.XXXXXX may be unambiguous; handled by ParseHEVCCodecID(). |
| 101 {"mp3", MimeUtil::MP3}, | 36 {"mp3", MimeUtil::MP3}, |
| 102 // Following is the list of RFC 6381 compliant audio codecs: | 37 // Following is the list of RFC 6381 compliant audio codec strings: |
| 103 // mp4a.66 - MPEG-2 AAC MAIN | 38 // mp4a.66 - MPEG-2 AAC MAIN |
| 104 // mp4a.67 - MPEG-2 AAC LC | 39 // mp4a.67 - MPEG-2 AAC LC |
| 105 // mp4a.68 - MPEG-2 AAC SSR | 40 // mp4a.68 - MPEG-2 AAC SSR |
| 106 // mp4a.69 - MPEG-2 extension to MPEG-1 (MP3) | 41 // mp4a.69 - MPEG-2 extension to MPEG-1 (MP3) |
| 107 // mp4a.6B - MPEG-1 audio (MP3) | 42 // mp4a.6B - MPEG-1 audio (MP3) |
| 108 // mp4a.40.2 - MPEG-4 AAC LC | 43 // mp4a.40.2 - MPEG-4 AAC LC |
| 109 // mp4a.40.02 - MPEG-4 AAC LC (leading 0 in aud-oti for compatibility) | 44 // mp4a.40.02 - MPEG-4 AAC LC (leading 0 in aud-oti for compatibility) |
| 110 // mp4a.40.5 - MPEG-4 HE-AAC v1 (AAC LC + SBR) | 45 // mp4a.40.5 - MPEG-4 HE-AAC v1 (AAC LC + SBR) |
| 111 // mp4a.40.05 - MPEG-4 HE-AAC v1 (AAC LC + SBR) (leading 0 in aud-oti for | 46 // mp4a.40.05 - MPEG-4 HE-AAC v1 (AAC LC + SBR) (leading 0 in aud-oti for |
| 112 // compatibility) | 47 // compatibility) |
| (...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 289 return IsNotSupported; | 224 return IsNotSupported; |
| 290 } | 225 } |
| 291 | 226 |
| 292 if (is_ambiguous) | 227 if (is_ambiguous) |
| 293 result = MayBeSupported; | 228 result = MayBeSupported; |
| 294 } | 229 } |
| 295 | 230 |
| 296 return result; | 231 return result; |
| 297 } | 232 } |
| 298 | 233 |
| 299 void MimeUtil::InitializeMimeTypeMaps() { | 234 void MimeUtil::InitializeMimeTypeMaps() { |
|
DaleCurtis
2016/03/31 22:19:46
Out of curiosity how long does this function take
ddorwin
2016/03/31 23:24:57
I'll find out.
The std::string operations are new
ddorwin
2016/04/01 00:01:41
For a Linux x64 release build on a workstation: 45
ddorwin
2016/04/01 16:45:07
For the record, without this CL, the equivalent co
| |
| 300 // Initialize the supported media types. | |
| 301 #if defined(USE_PROPRIETARY_CODECS) | 235 #if defined(USE_PROPRIETARY_CODECS) |
| 302 allow_proprietary_codecs_ = true; | 236 allow_proprietary_codecs_ = true; |
| 303 #endif | 237 #endif |
| 304 | 238 |
| 305 for (size_t i = 0; i < arraysize(kUnambiguousCodecStringMap); ++i) { | 239 for (size_t i = 0; i < arraysize(kUnambiguousCodecStringMap); ++i) { |
| 306 string_to_codec_map_[kUnambiguousCodecStringMap[i].codec_id] = | 240 string_to_codec_map_[kUnambiguousCodecStringMap[i].codec_id] = |
| 307 CodecEntry(kUnambiguousCodecStringMap[i].codec, false); | 241 CodecEntry(kUnambiguousCodecStringMap[i].codec, false); |
| 308 } | 242 } |
| 309 | 243 |
| 310 for (size_t i = 0; i < arraysize(kAmbiguousCodecStringMap); ++i) { | 244 for (size_t i = 0; i < arraysize(kAmbiguousCodecStringMap); ++i) { |
| 311 string_to_codec_map_[kAmbiguousCodecStringMap[i].codec_id] = | 245 string_to_codec_map_[kAmbiguousCodecStringMap[i].codec_id] = |
| 312 CodecEntry(kAmbiguousCodecStringMap[i].codec, true); | 246 CodecEntry(kAmbiguousCodecStringMap[i].codec, true); |
| 313 } | 247 } |
| 314 | 248 |
| 315 // Initialize the supported media formats. | 249 AddSupportedMediaFormats(); |
| 316 for (size_t i = 0; i < arraysize(kFormatCodecMappings); ++i) { | 250 } |
| 317 std::vector<std::string> mime_type_codecs; | |
| 318 ParseCodecString(kFormatCodecMappings[i].codecs_list, &mime_type_codecs, | |
| 319 false); | |
| 320 | 251 |
| 321 CodecSet codecs; | 252 // Each call to AddContainerWithCodecs() contains a media type |
|
DaleCurtis
2016/03/31 22:19:46
Typically we put these comments in the .h file, bu
ddorwin
2016/03/31 23:24:57
This seems to be implementation details. Note that
| |
| 322 for (size_t j = 0; j < mime_type_codecs.size(); ++j) { | 253 // (https://en.wikipedia.org/wiki/Media_type) and corresponding media codec(s) |
| 323 Codec codec = INVALID_CODEC; | 254 // supported by these types/containers. |
| 324 bool is_ambiguous = true; | 255 // |
| 325 CHECK(StringToCodec(mime_type_codecs[j], &codec, &is_ambiguous)); | 256 // Strings used as the |codecs_list| only need one valid unambiguous variant for |
| 326 DCHECK(!is_ambiguous); | 257 // each supported MimeUtil::Codec enum value. Each codec string is parsed and |
| 327 codecs.insert(codec); | 258 // mapped to corresponding MimeUtil::Codec value. See https://crbug.com/461009. |
| 328 } | 259 void MimeUtil::AddSupportedMediaFormats() { |
| 260 const std::string ogg_audio_codecs = "opus,vorbis"; | |
| 261 const std::string ogg_video_codecs = | |
| 262 #if !defined(OS_ANDROID) | |
|
DaleCurtis
2016/03/31 22:19:46
Kind of ugly, I'd prefer to just have "const std::
ddorwin
2016/03/31 23:24:57
I changed it to add theora since there is more com
| |
| 263 "theora"; | |
| 264 #endif | |
|
DaleCurtis
2016/03/31 22:19:46
Lots of defs in this area so please include the
ddorwin
2016/03/31 23:24:57
Done.
| |
| 265 ; | |
| 266 const std::string ogg_codecs = ogg_video_codecs + "," + ogg_audio_codecs; | |
| 329 | 267 |
| 330 media_format_map_[kFormatCodecMappings[i].mime_type] = codecs; | 268 #if defined(USE_PROPRIETARY_CODECS) |
| 269 const std::string aac = "mp4a.66,mp4a.40.2"; // MPEG-2 and MPEG-4 AAC. | |
| 270 const std::string mp3 = "mp4a.69"; | |
| 271 const std::string avc = "avc1.42E00A"; | |
| 272 | |
| 273 const std::string avc_and_aac = avc + "," + aac; | |
| 274 const std::string mp4_audio_codecs = | |
| 275 #if BUILDFLAG(ENABLE_AC3_EAC3_AUDIO_DEMUXING) | |
|
DaleCurtis
2016/03/31 22:19:46
Similarly these are a little error prone, might be
ddorwin
2016/03/31 23:24:57
In this case, it's not just the variable name - we
| |
| 276 "ac-3,ec-3," + // AC-3 and E-AC-3. | |
| 277 #endif | |
| 278 aac + "," + mp3; | |
| 279 const std::string mp4_video_codecs = | |
| 280 #if BUILDFLAG(ENABLE_HEVC_DEMUXING) | |
|
DaleCurtis
2016/03/31 22:19:46
Ditto.
ddorwin
2016/03/31 23:24:57
See above.
| |
| 281 "hev1.1.6.L93.B0," + | |
| 282 #endif | |
| 283 avc; | |
| 284 const std::string mp4_codecs = mp4_video_codecs + "," + mp4_audio_codecs; | |
| 285 #endif // defined(USE_PROPRIETARY_CODECS) | |
| 286 | |
| 287 AddContainerWithCodecs("audio/wav", "1", false); | |
|
DaleCurtis
2016/03/31 22:19:46
As an aside, what's the "1" about?
ddorwin
2016/03/31 23:24:57
I don't know. It's always been that way. There is
| |
| 288 AddContainerWithCodecs("audio/x-wav", "1", false); | |
| 289 AddContainerWithCodecs("audio/webm", "opus,vorbis", false); | |
| 290 AddContainerWithCodecs("video/webm", "opus,vorbis,vp8,vp9", false); | |
| 291 AddContainerWithCodecs("audio/ogg", ogg_audio_codecs, false); | |
| 292 // video/ogg is only supported if an appropriate video codec is supported. | |
| 293 // Note: This assumes such codecs cannot be later excluded. | |
| 294 if (!ogg_video_codecs.empty()) | |
| 295 AddContainerWithCodecs("video/ogg", ogg_codecs, false); | |
|
DaleCurtis
2016/03/31 22:19:46
ogg_video_codecs?
ddorwin
2016/03/31 23:24:57
Naming fun. "video/foo" supports all foo codecs. T
| |
| 296 // TODO(ddorwin): Should the application type support Opus? | |
| 297 AddContainerWithCodecs("application/ogg", ogg_codecs, false); | |
| 298 | |
| 299 #if defined(USE_PROPRIETARY_CODECS) | |
| 300 AddContainerWithCodecs("audio/mpeg", "mp3", true); | |
| 301 AddContainerWithCodecs("audio/mp3", "", true); | |
| 302 AddContainerWithCodecs("audio/x-mp3", "", true); | |
| 303 AddContainerWithCodecs("audio/aac", "", true); // AAC / ADTS | |
| 304 AddContainerWithCodecs("audio/mp4", mp4_audio_codecs, true); | |
| 305 DCHECK(!mp4_video_codecs.empty()); | |
| 306 AddContainerWithCodecs("video/mp4", mp4_codecs, true); | |
| 307 // These strings are supported for backwards compatibility only and thus only | |
| 308 // support the codecs needed for compatibility. | |
| 309 AddContainerWithCodecs("audio/x-m4a", aac, true); | |
| 310 AddContainerWithCodecs("video/x-m4v", avc_and_aac, true); | |
| 311 | |
| 312 #if BUILDFLAG(ENABLE_MSE_MPEG2TS_STREAM_PARSER) | |
| 313 // TODO(ddorwin): Exactly which codecs should be supported? | |
| 314 DCHECK(!mp4_video_codecs.empty()); | |
| 315 AddContainerWithCodecs("video/mp2t", mp4_codecs, true); | |
| 316 #endif | |
| 317 #if defined(OS_ANDROID) | |
| 318 // HTTP Live Streaming (HLS). | |
| 319 // TODO(ddorwin): Is any MP3 codec string variant included in real queries? | |
| 320 const std::string hls_codecs = avc_and_aac + "," + mp3; | |
| 321 AddContainerWithCodecs("application/x-mpegurl", hls_codecs, true); | |
| 322 AddContainerWithCodecs("application/vnd.apple.mpegurl", hls_codecs, true); | |
| 323 #endif | |
| 324 #endif // defined(USE_PROPRIETARY_CODECS) | |
| 325 } | |
| 326 | |
| 327 // TODO(ddorwin): Replace |codecs_list| with a vector of MimeUtil::Codec values. | |
| 328 // See https://crbug.com/461009. | |
| 329 void MimeUtil::AddContainerWithCodecs(const std::string& mime_type, | |
| 330 const std::string& codecs_list, | |
| 331 bool is_proprietary_mime_type) { | |
| 332 #if !defined(USE_PROPRIETARY_CODECS) | |
| 333 DCHECK(!is_proprietary_mime_type); | |
| 334 #endif | |
| 335 | |
| 336 std::vector<std::string> mime_type_codecs; | |
| 337 ParseCodecString(codecs_list, &mime_type_codecs, false); | |
| 338 | |
| 339 CodecSet codecs; | |
| 340 for (size_t j = 0; j < mime_type_codecs.size(); ++j) { | |
|
DaleCurtis
2016/03/31 22:19:46
for (const auto& mime_codec : mime_type_codecs) ?
ddorwin
2016/03/31 23:24:57
Done. This was just moved. :)
| |
| 341 Codec codec = INVALID_CODEC; | |
| 342 bool is_ambiguous = true; | |
| 343 CHECK(StringToCodec(mime_type_codecs[j], &codec, &is_ambiguous)); | |
| 344 DCHECK(!is_ambiguous); | |
| 345 codecs.insert(codec); | |
| 331 } | 346 } |
| 347 | |
| 348 media_format_map_[mime_type] = codecs; | |
| 349 | |
| 350 if (is_proprietary_mime_type) | |
| 351 proprietary_media_containers_.push_back(mime_type); | |
| 332 } | 352 } |
| 333 | 353 |
| 334 bool MimeUtil::IsSupportedMediaMimeType(const std::string& mime_type) const { | 354 bool MimeUtil::IsSupportedMediaMimeType(const std::string& mime_type) const { |
| 335 return media_format_map_.find(base::ToLowerASCII(mime_type)) != | 355 return media_format_map_.find(base::ToLowerASCII(mime_type)) != |
| 336 media_format_map_.end(); | 356 media_format_map_.end(); |
| 337 } | 357 } |
| 338 | 358 |
| 339 void MimeUtil::ParseCodecString(const std::string& codecs, | 359 void MimeUtil::ParseCodecString(const std::string& codecs, |
| 340 std::vector<std::string>* codecs_out, | 360 std::vector<std::string>* codecs_out, |
| 341 bool strip) { | 361 bool strip) { |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 400 return AreSupportedCodecs(it_media_format_map->second, codecs_to_check, | 420 return AreSupportedCodecs(it_media_format_map->second, codecs_to_check, |
| 401 mime_type_lower_case, is_encrypted); | 421 mime_type_lower_case, is_encrypted); |
| 402 } | 422 } |
| 403 #endif | 423 #endif |
| 404 | 424 |
| 405 return AreSupportedCodecs(it_media_format_map->second, codecs, | 425 return AreSupportedCodecs(it_media_format_map->second, codecs, |
| 406 mime_type_lower_case, is_encrypted); | 426 mime_type_lower_case, is_encrypted); |
| 407 } | 427 } |
| 408 | 428 |
| 409 void MimeUtil::RemoveProprietaryMediaTypesAndCodecs() { | 429 void MimeUtil::RemoveProprietaryMediaTypesAndCodecs() { |
| 410 for (size_t i = 0; i < arraysize(kFormatCodecMappings); ++i) | 430 for (const std::string& container : proprietary_media_containers_) |
| 411 if (kFormatCodecMappings[i].format_type == PROPRIETARY) | 431 media_format_map_.erase(container); |
| 412 media_format_map_.erase(kFormatCodecMappings[i].mime_type); | |
| 413 allow_proprietary_codecs_ = false; | 432 allow_proprietary_codecs_ = false; |
| 414 } | 433 } |
| 415 | 434 |
| 416 // static | 435 // static |
| 417 bool MimeUtil::IsCodecSupportedOnPlatform( | 436 bool MimeUtil::IsCodecSupportedOnPlatform( |
| 418 Codec codec, | 437 Codec codec, |
| 419 const std::string& mime_type_lower_case, | 438 const std::string& mime_type_lower_case, |
| 420 bool is_encrypted, | 439 bool is_encrypted, |
| 421 const PlatformInfo& platform_info) { | 440 const PlatformInfo& platform_info) { |
| 422 DCHECK_NE(mime_type_lower_case, ""); | 441 DCHECK_NE(mime_type_lower_case, ""); |
| (...skipping 202 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 625 const std::string& mime_type_lower_case, | 644 const std::string& mime_type_lower_case, |
| 626 bool is_encrypted) const { | 645 bool is_encrypted) const { |
| 627 Codec default_codec = Codec::INVALID_CODEC; | 646 Codec default_codec = Codec::INVALID_CODEC; |
| 628 if (!GetDefaultCodecLowerCase(mime_type_lower_case, &default_codec)) | 647 if (!GetDefaultCodecLowerCase(mime_type_lower_case, &default_codec)) |
| 629 return false; | 648 return false; |
| 630 return IsCodecSupported(default_codec, mime_type_lower_case, is_encrypted); | 649 return IsCodecSupported(default_codec, mime_type_lower_case, is_encrypted); |
| 631 } | 650 } |
| 632 | 651 |
| 633 } // namespace internal | 652 } // namespace internal |
| 634 } // namespace media | 653 } // namespace media |
| OLD | NEW |