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/video_codecs.h" | 12 #include "media/base/video_codecs.h" |
12 #include "media/media_features.h" | 13 #include "media/media_features.h" |
13 | 14 |
14 #if defined(OS_ANDROID) | 15 #if defined(OS_ANDROID) |
15 #include "base/android/build_info.h" | 16 #include "base/android/build_info.h" |
17 #include "media/base/android/media_codec_util.h" | |
16 #endif | 18 #endif |
17 | 19 |
18 namespace media { | 20 namespace media { |
19 namespace internal { | 21 namespace internal { |
20 | 22 |
21 enum MediaFormatType { COMMON, PROPRIETARY }; | 23 enum MediaFormatType { COMMON, PROPRIETARY }; |
22 | 24 |
23 struct MediaFormat { | 25 struct MediaFormat { |
24 const char* const mime_type; | 26 const char* const mime_type; |
25 MediaFormatType format_type; | 27 MediaFormatType format_type; |
(...skipping 233 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
259 } | 261 } |
260 | 262 |
261 return true; | 263 return true; |
262 } | 264 } |
263 | 265 |
264 return false; | 266 return false; |
265 } | 267 } |
266 #endif | 268 #endif |
267 | 269 |
268 MimeUtil::MimeUtil() : allow_proprietary_codecs_(false) { | 270 MimeUtil::MimeUtil() : allow_proprietary_codecs_(false) { |
271 #if defined(OS_ANDROID) | |
272 platform_info_.using_unified_media_pipeline = IsUnifiedMediaPipelineEnabled(); | |
273 platform_info_.has_platform_decoders = | |
274 platform_info_.using_unified_media_pipeline | |
275 ? HasPlatformDecoderSupport() | |
276 : MediaCodecUtil::IsMediaCodecAvailable(); | |
ddorwin
2016/02/18 20:37:44
Why doesn't HasPlatformDecoderSupport() - namely t
DaleCurtis
2016/02/19 01:35:46
As discussed via chat, comment added.
| |
277 platform_info_.supports_encrypted_vp8 = !MediaCodecUtil::IsVp8Blacklisted(); | |
ddorwin
2016/02/18 20:37:44
Yes, VP8 only applies in the encrypted case, but t
DaleCurtis
2016/02/19 01:35:46
Done.
| |
278 platform_info_.supports_opus = MediaCodecUtil::PlatformHasOpusSupport(); | |
279 platform_info_.supports_vp9 = MediaCodecUtil::PlatformHasVp9Support(); | |
280 #endif | |
281 | |
269 InitializeMimeTypeMaps(); | 282 InitializeMimeTypeMaps(); |
270 } | 283 } |
271 | 284 |
272 MimeUtil::~MimeUtil() {} | 285 MimeUtil::~MimeUtil() {} |
273 | 286 |
274 SupportsType MimeUtil::AreSupportedCodecs( | 287 SupportsType MimeUtil::AreSupportedCodecs( |
275 const CodecSet& supported_codecs, | 288 const CodecSet& supported_codecs, |
276 const std::vector<std::string>& codecs) const { | 289 const std::vector<std::string>& codecs, |
290 const std::string& mime_type_lower_case, | |
291 bool is_encrypted) const { | |
277 DCHECK(!supported_codecs.empty()); | 292 DCHECK(!supported_codecs.empty()); |
278 DCHECK(!codecs.empty()); | 293 DCHECK(!codecs.empty()); |
279 | 294 |
280 SupportsType result = IsSupported; | 295 SupportsType result = IsSupported; |
281 for (size_t i = 0; i < codecs.size(); ++i) { | 296 for (size_t i = 0; i < codecs.size(); ++i) { |
282 bool is_ambiguous = true; | 297 bool is_ambiguous = true; |
283 Codec codec = INVALID_CODEC; | 298 Codec codec = INVALID_CODEC; |
284 if (!StringToCodec(codecs[i], &codec, &is_ambiguous)) | 299 if (!StringToCodec(codecs[i], &codec, &is_ambiguous)) |
285 return IsNotSupported; | 300 return IsNotSupported; |
286 | 301 |
287 if (!IsCodecSupported(codec) || | 302 if (!IsCodecSupported(codec, mime_type_lower_case, is_encrypted) || |
288 supported_codecs.find(codec) == supported_codecs.end()) { | 303 supported_codecs.find(codec) == supported_codecs.end()) { |
289 return IsNotSupported; | 304 return IsNotSupported; |
290 } | 305 } |
291 | 306 |
292 if (is_ambiguous) | 307 if (is_ambiguous) |
293 result = MayBeSupported; | 308 result = MayBeSupported; |
294 } | 309 } |
295 | 310 |
296 return result; | 311 return result; |
297 } | 312 } |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
354 for (std::vector<std::string>::iterator it = codecs_out->begin(); | 369 for (std::vector<std::string>::iterator it = codecs_out->begin(); |
355 it != codecs_out->end(); ++it) { | 370 it != codecs_out->end(); ++it) { |
356 size_t found = it->find_first_of('.'); | 371 size_t found = it->find_first_of('.'); |
357 if (found != std::string::npos) | 372 if (found != std::string::npos) |
358 it->resize(found); | 373 it->resize(found); |
359 } | 374 } |
360 } | 375 } |
361 | 376 |
362 SupportsType MimeUtil::IsSupportedMediaFormat( | 377 SupportsType MimeUtil::IsSupportedMediaFormat( |
363 const std::string& mime_type, | 378 const std::string& mime_type, |
364 const std::vector<std::string>& codecs) const { | 379 const std::vector<std::string>& codecs, |
380 bool is_encrypted) const { | |
365 const std::string mime_type_lower_case = base::ToLowerASCII(mime_type); | 381 const std::string mime_type_lower_case = base::ToLowerASCII(mime_type); |
366 MediaFormatMappings::const_iterator it_media_format_map = | 382 MediaFormatMappings::const_iterator it_media_format_map = |
367 media_format_map_.find(mime_type_lower_case); | 383 media_format_map_.find(mime_type_lower_case); |
368 if (it_media_format_map == media_format_map_.end()) | 384 if (it_media_format_map == media_format_map_.end()) |
369 return IsNotSupported; | 385 return IsNotSupported; |
370 | 386 |
371 if (it_media_format_map->second.empty()) { | 387 if (it_media_format_map->second.empty()) { |
372 // We get here if the mimetype does not expect a codecs parameter. | 388 // We get here if the mimetype does not expect a codecs parameter. |
373 return (codecs.empty() && | 389 return (codecs.empty() && IsDefaultCodecSupportedLowerCase( |
374 IsDefaultCodecSupportedLowerCase(mime_type_lower_case)) | 390 mime_type_lower_case, is_encrypted)) |
375 ? IsSupported | 391 ? IsSupported |
376 : IsNotSupported; | 392 : IsNotSupported; |
377 } | 393 } |
378 | 394 |
379 if (codecs.empty()) { | 395 if (codecs.empty()) { |
380 // We get here if the mimetype expects to get a codecs parameter, | 396 // We get here if the mimetype expects to get a codecs parameter, |
381 // but didn't get one. If |mime_type_lower_case| does not have a default | 397 // but didn't get one. If |mime_type_lower_case| does not have a default |
382 // codec the best we can do is say "maybe" because we don't have enough | 398 // codec the best we can do is say "maybe" because we don't have enough |
383 // information. | 399 // information. |
384 Codec default_codec = INVALID_CODEC; | 400 Codec default_codec = INVALID_CODEC; |
385 if (!GetDefaultCodecLowerCase(mime_type_lower_case, &default_codec)) | 401 if (!GetDefaultCodecLowerCase(mime_type_lower_case, &default_codec)) |
386 return MayBeSupported; | 402 return MayBeSupported; |
387 | 403 |
388 return IsCodecSupported(default_codec) ? IsSupported : IsNotSupported; | 404 return IsCodecSupported(default_codec, mime_type_lower_case, is_encrypted) |
405 ? IsSupported | |
406 : IsNotSupported; | |
389 } | 407 } |
390 | 408 |
391 #if BUILDFLAG(ENABLE_MSE_MPEG2TS_STREAM_PARSER) | 409 #if BUILDFLAG(ENABLE_MSE_MPEG2TS_STREAM_PARSER) |
392 if (mime_type_lower_case == "video/mp2t") { | 410 if (mime_type_lower_case == "video/mp2t") { |
393 std::vector<std::string> codecs_to_check; | 411 std::vector<std::string> codecs_to_check; |
394 for (const auto& codec_id : codecs) { | 412 for (const auto& codec_id : codecs) { |
395 codecs_to_check.push_back(TranslateLegacyAvc1CodecIds(codec_id)); | 413 codecs_to_check.push_back(TranslateLegacyAvc1CodecIds(codec_id)); |
396 } | 414 } |
397 return AreSupportedCodecs(it_media_format_map->second, codecs_to_check); | 415 return AreSupportedCodecs(it_media_format_map->second, codecs_to_check, |
416 mime_type_lower_case, is_encrypted); | |
398 } | 417 } |
399 #endif | 418 #endif |
400 | 419 |
401 return AreSupportedCodecs(it_media_format_map->second, codecs); | 420 return AreSupportedCodecs(it_media_format_map->second, codecs, |
421 mime_type_lower_case, is_encrypted); | |
402 } | 422 } |
403 | 423 |
404 void MimeUtil::RemoveProprietaryMediaTypesAndCodecs() { | 424 void MimeUtil::RemoveProprietaryMediaTypesAndCodecs() { |
405 for (size_t i = 0; i < arraysize(kFormatCodecMappings); ++i) | 425 for (size_t i = 0; i < arraysize(kFormatCodecMappings); ++i) |
406 if (kFormatCodecMappings[i].format_type == PROPRIETARY) | 426 if (kFormatCodecMappings[i].format_type == PROPRIETARY) |
407 media_format_map_.erase(kFormatCodecMappings[i].mime_type); | 427 media_format_map_.erase(kFormatCodecMappings[i].mime_type); |
408 allow_proprietary_codecs_ = false; | 428 allow_proprietary_codecs_ = false; |
409 } | 429 } |
410 | 430 |
431 void MimeUtil::SetPlatformInfoForTests(const PlatformInfo& info) { | |
432 platform_info_ = info; | |
433 } | |
434 | |
411 bool MimeUtil::StringToCodec(const std::string& codec_id, | 435 bool MimeUtil::StringToCodec(const std::string& codec_id, |
412 Codec* codec, | 436 Codec* codec, |
413 bool* is_ambiguous) const { | 437 bool* is_ambiguous) const { |
414 StringToCodecMappings::const_iterator itr = | 438 StringToCodecMappings::const_iterator itr = |
415 string_to_codec_map_.find(codec_id); | 439 string_to_codec_map_.find(codec_id); |
416 if (itr != string_to_codec_map_.end()) { | 440 if (itr != string_to_codec_map_.end()) { |
417 *codec = itr->second.codec; | 441 *codec = itr->second.codec; |
418 *is_ambiguous = itr->second.is_ambiguous; | 442 *is_ambiguous = itr->second.is_ambiguous; |
419 return true; | 443 return true; |
420 } | 444 } |
421 | 445 |
422 // If |codec_id| is not in |string_to_codec_map_|, then we assume that it is | 446 // If |codec_id| is not in |string_to_codec_map_|, then we assume that it is |
ddorwin
2016/02/18 20:37:44
Does the new line below not allow us to indent the
DaleCurtis
2016/02/19 01:35:46
Apparently not. It does when I format a section ma
| |
423 // either H.264 or HEVC/H.265 codec ID because currently those are the only | 447 // either H.264 or HEVC/H.265 codec ID because currently those are the only |
424 // ones that are not added to the |string_to_codec_map_| and require parsing. | 448 // ones that are not added to the |string_to_codec_map_| and require parsing. |
425 | 449 |
426 #if BUILDFLAG(ENABLE_HEVC_DEMUXING) | 450 #if BUILDFLAG(ENABLE_HEVC_DEMUXING) |
427 if (ParseHEVCCodecID(codec_id, codec, is_ambiguous)) { | 451 if (ParseHEVCCodecID(codec_id, codec, is_ambiguous)) { |
428 return true; | 452 return true; |
429 } | 453 } |
430 #endif | 454 #endif |
431 | 455 |
432 VideoCodecProfile profile = VIDEO_CODEC_PROFILE_UNKNOWN; | 456 VideoCodecProfile profile = VIDEO_CODEC_PROFILE_UNKNOWN; |
433 uint8_t level_idc = 0; | 457 uint8_t level_idc = 0; |
434 if (ParseAVCCodecId(codec_id, &profile, &level_idc)) { | 458 if (ParseAVCCodecId(codec_id, &profile, &level_idc)) { |
435 *codec = MimeUtil::H264; | 459 *codec = MimeUtil::H264; |
436 *is_ambiguous = | 460 *is_ambiguous = |
437 (profile != H264PROFILE_BASELINE && profile != H264PROFILE_MAIN && | 461 (profile != H264PROFILE_BASELINE && profile != H264PROFILE_MAIN && |
438 profile != H264PROFILE_HIGH) || | 462 profile != H264PROFILE_HIGH) || |
439 !IsValidH264Level(level_idc); | 463 !IsValidH264Level(level_idc); |
440 return true; | 464 return true; |
441 } | 465 } |
442 | 466 |
443 DVLOG(4) << __FUNCTION__ << ": Unrecognized codec id " << codec_id; | 467 DVLOG(4) << __FUNCTION__ << ": Unrecognized codec id " << codec_id; |
444 return false; | 468 return false; |
445 } | 469 } |
446 | 470 |
447 bool MimeUtil::IsCodecSupported(Codec codec) const { | 471 bool MimeUtil::IsCodecSupported(Codec codec, |
472 const std::string& mime_type_lower_case, | |
473 bool is_encrypted) const { | |
448 DCHECK_NE(codec, INVALID_CODEC); | 474 DCHECK_NE(codec, INVALID_CODEC); |
449 | 475 |
450 #if defined(OS_ANDROID) | 476 #if defined(OS_ANDROID) |
451 if (!IsCodecSupportedOnAndroid(codec)) | 477 if (!IsCodecSupportedOnAndroid(codec, mime_type_lower_case, is_encrypted)) |
452 return false; | 478 return false; |
453 #endif | 479 #endif |
454 | 480 |
455 return allow_proprietary_codecs_ || !IsCodecProprietary(codec); | 481 return allow_proprietary_codecs_ || !IsCodecProprietary(codec); |
456 } | 482 } |
457 | 483 |
458 bool MimeUtil::IsCodecProprietary(Codec codec) const { | 484 bool MimeUtil::IsCodecProprietary(Codec codec) const { |
459 switch (codec) { | 485 switch (codec) { |
460 case INVALID_CODEC: | 486 case INVALID_CODEC: |
461 case AC3: | 487 case AC3: |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
494 | 520 |
495 if (mime_type_lower_case == "audio/aac") { | 521 if (mime_type_lower_case == "audio/aac") { |
496 *default_codec = MimeUtil::MPEG4_AAC_LC; | 522 *default_codec = MimeUtil::MPEG4_AAC_LC; |
497 return true; | 523 return true; |
498 } | 524 } |
499 | 525 |
500 return false; | 526 return false; |
501 } | 527 } |
502 | 528 |
503 bool MimeUtil::IsDefaultCodecSupportedLowerCase( | 529 bool MimeUtil::IsDefaultCodecSupportedLowerCase( |
504 const std::string& mime_type_lower_case) const { | 530 const std::string& mime_type_lower_case, |
531 bool is_encrypted) const { | |
505 Codec default_codec = Codec::INVALID_CODEC; | 532 Codec default_codec = Codec::INVALID_CODEC; |
506 if (!GetDefaultCodecLowerCase(mime_type_lower_case, &default_codec)) | 533 if (!GetDefaultCodecLowerCase(mime_type_lower_case, &default_codec)) |
507 return false; | 534 return false; |
508 return IsCodecSupported(default_codec); | 535 return IsCodecSupported(default_codec, mime_type_lower_case, is_encrypted); |
509 } | 536 } |
510 | 537 |
511 #if defined(OS_ANDROID) | 538 bool MimeUtil::IsCodecSupportedOnAndroid( |
512 bool MimeUtil::IsCodecSupportedOnAndroid(Codec codec) const { | 539 Codec codec, |
540 const std::string& mime_type_lower_case, | |
541 bool is_encrypted) const { | |
542 // Encrypted block support is never available without platform decoders. | |
543 if (is_encrypted && !platform_info_.has_platform_decoders) | |
544 return false; | |
545 | |
546 // NOTE: We do not account for Media Source Extensions (MSE) within these | |
547 // checks since it has its own isTypeSupported() which will handle platform | |
548 // specific codec rejections. See http://crbug.com/587303. | |
549 | |
513 switch (codec) { | 550 switch (codec) { |
551 // ---------------------------------------------------------------------- | |
552 // The following codecs are never supported. | |
553 // ---------------------------------------------------------------------- | |
554 case AC3: | |
555 case EAC3: | |
514 case INVALID_CODEC: | 556 case INVALID_CODEC: |
ddorwin
2016/02/18 20:37:44
This should be first.
DaleCurtis
2016/02/19 01:35:46
Done.
| |
557 case THEORA: | |
515 return false; | 558 return false; |
516 | 559 |
560 // ---------------------------------------------------------------------- | |
561 // The remaining codecs may be supported depending on platform abilities. | |
562 // ---------------------------------------------------------------------- | |
517 case PCM: | 563 case PCM: |
ddorwin
2016/02/18 20:37:44
WDYT of an empty line before this to avoid linking
DaleCurtis
2016/02/19 01:35:46
Done.
| |
518 case MP3: | 564 case MP3: |
519 case MPEG4_AAC_LC: | 565 case MPEG4_AAC_LC: |
520 case MPEG4_AAC_SBR_v1: | 566 case MPEG4_AAC_SBR_v1: |
521 case MPEG4_AAC_SBR_PS_v2: | 567 case MPEG4_AAC_SBR_PS_v2: |
522 case VORBIS: | 568 case VORBIS: |
523 case H264: | 569 // These codecs are always supported; via a platform decoder (when used |
524 case VP8: | 570 // with MSE/EME), a software decoder (the unified pipeline), or with |
571 // MediaPlayer. | |
572 DCHECK(!is_encrypted || platform_info_.has_platform_decoders); | |
525 return true; | 573 return true; |
526 | 574 |
527 case AC3: | |
528 case EAC3: | |
529 // TODO(servolk): Revisit this for AC3/EAC3 support on AndroidTV | |
530 return false; | |
531 | |
532 case MPEG2_AAC_LC: | 575 case MPEG2_AAC_LC: |
533 case MPEG2_AAC_MAIN: | 576 case MPEG2_AAC_MAIN: |
534 case MPEG2_AAC_SSR: | 577 case MPEG2_AAC_SSR: |
535 // MPEG-2 variants of AAC are not supported on Android. | 578 // MPEG-2 variants of AAC are not supported on Android unless the unified |
536 return false; | 579 // media pipeline can be used. These codecs will be decoded in software. |
580 return !is_encrypted && platform_info_.using_unified_media_pipeline; | |
537 | 581 |
538 case OPUS: | 582 case OPUS: |
539 // Opus is supported only in Lollipop+ (API Level 21). | 583 // If clear, the unified pipeline can always decode OPUS in software. |
540 return base::android::BuildInfo::GetInstance()->sdk_int() >= 21; | 584 if (!is_encrypted && platform_info_.using_unified_media_pipeline) |
585 return true; | |
586 | |
587 // Otherwise, platform support is required. | |
588 if (!platform_info_.supports_opus) | |
589 return false; | |
590 | |
591 // MediaPlayer does not support opus in ogg containers. | |
592 if (base::EndsWith(mime_type_lower_case, "ogg", | |
593 base::CompareCase::SENSITIVE)) { | |
594 return false; | |
595 } | |
596 | |
597 DCHECK(!is_encrypted || platform_info_.has_platform_decoders); | |
598 return true; | |
599 | |
600 case H264: | |
601 // The unified pipeline requires platform support for h264. | |
602 if (platform_info_.using_unified_media_pipeline) | |
603 return platform_info_.has_platform_decoders; | |
604 | |
605 // When MediaPlayer is used, h264 is always supported. | |
606 DCHECK(!is_encrypted || platform_info_.has_platform_decoders); | |
607 return true; | |
541 | 608 |
542 case HEVC_MAIN: | 609 case HEVC_MAIN: |
543 #if BUILDFLAG(ENABLE_HEVC_DEMUXING) | 610 #if BUILDFLAG(ENABLE_HEVC_DEMUXING) |
611 if (platform_info_.using_unified_media_pipeline) | |
612 return platform_info_.has_platform_decoders; | |
ddorwin
2016/02/18 20:37:44
This skips the API level check below. I think you
DaleCurtis
2016/02/19 01:35:46
Done.
| |
613 | |
544 // HEVC/H.265 is supported in Lollipop+ (API Level 21), according to | 614 // HEVC/H.265 is supported in Lollipop+ (API Level 21), according to |
545 // http://developer.android.com/reference/android/media/MediaFormat.html | 615 // http://developer.android.com/reference/android/media/MediaFormat.html |
546 return base::android::BuildInfo::GetInstance()->sdk_int() >= 21; | 616 return base::android::BuildInfo::GetInstance()->sdk_int() >= 21; |
ddorwin
2016/02/18 20:37:44
This line will only compile on Android. This is th
DaleCurtis
2016/02/19 01:35:46
Done.
| |
547 #else | 617 #else |
548 return false; | 618 return false; |
549 #endif | 619 #endif |
550 | 620 |
551 case VP9: | 621 case VP8: |
552 // VP9 is supported only in KitKat+ (API Level 19). | 622 // If clear, the unified pipeline can always decode VP8 in software. |
553 return base::android::BuildInfo::GetInstance()->sdk_int() >= 19; | 623 if (!is_encrypted && platform_info_.using_unified_media_pipeline) |
624 return true; | |
554 | 625 |
555 case THEORA: | 626 if (is_encrypted) |
556 return false; | 627 return platform_info_.supports_encrypted_vp8; |
628 | |
629 // MediaPlayer can always play vp8. Note: This is incorrect for MSE, but | |
ddorwin
2016/02/18 20:37:44
nit: "VP8" for consistency.
DaleCurtis
2016/02/19 01:35:46
Done.
| |
630 // MSE does not use this code. http://crbug.com/587303. | |
631 return true; | |
632 | |
633 case VP9: { | |
634 // If clear, the unified pipeline can always decode VP9 in software. | |
635 if (!is_encrypted && platform_info_.using_unified_media_pipeline) | |
636 return true; | |
637 | |
638 // Otherwise, platform support is required. | |
639 return platform_info_.supports_vp9; | |
640 } | |
557 } | 641 } |
558 | 642 |
559 return false; | 643 return false; |
560 } | 644 } |
561 #endif | |
562 | 645 |
563 } // namespace internal | 646 } // namespace internal |
564 } // namespace media | 647 } // namespace media |
OLD | NEW |