Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2012 The Chromium Authors. All rights reserved. | 1 // Copyright 2012 The Chromium Authors. All rights reserved. |
|
ddorwin
2016/02/17 19:31:20
This is going to conflict with Dale's CL to move m
| |
| 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 <stddef.h> | 5 #include <stddef.h> |
| 6 #include <stdint.h> | 6 #include <stdint.h> |
| 7 | 7 |
| 8 #include <map> | 8 #include <map> |
| 9 | 9 |
| 10 #include "base/containers/hash_tables.h" | 10 #include "base/containers/hash_tables.h" |
| 11 #include "base/lazy_instance.h" | 11 #include "base/lazy_instance.h" |
| 12 #include "base/macros.h" | 12 #include "base/macros.h" |
| 13 #include "base/strings/string_number_conversions.h" | 13 #include "base/strings/string_number_conversions.h" |
| 14 #include "base/strings/string_split.h" | 14 #include "base/strings/string_split.h" |
| 15 #include "base/strings/string_util.h" | 15 #include "base/strings/string_util.h" |
| 16 #include "build/build_config.h" | 16 #include "build/build_config.h" |
| 17 #include "media/base/mime_util.h" | 17 #include "media/base/mime_util.h" |
| 18 #include "media/base/video_codecs.h" | |
| 18 #include "media/media_features.h" | 19 #include "media/media_features.h" |
| 19 | 20 |
| 20 #if defined(OS_ANDROID) | 21 #if defined(OS_ANDROID) |
| 21 #include "base/android/build_info.h" | 22 #include "base/android/build_info.h" |
| 22 #endif | 23 #endif |
| 23 | 24 |
| 24 namespace media { | 25 namespace media { |
| 25 | 26 |
| 26 // Singleton utility class for mime types. | 27 // Singleton utility class for mime types. |
| 27 class MimeUtil { | 28 class MimeUtil { |
| 28 public: | 29 public: |
| 29 enum Codec { | 30 enum Codec { |
| 30 INVALID_CODEC, | 31 INVALID_CODEC, |
| 31 PCM, | 32 PCM, |
| 32 MP3, | 33 MP3, |
| 33 AC3, | 34 AC3, |
| 34 EAC3, | 35 EAC3, |
| 35 MPEG2_AAC_LC, | 36 MPEG2_AAC_LC, |
| 36 MPEG2_AAC_MAIN, | 37 MPEG2_AAC_MAIN, |
| 37 MPEG2_AAC_SSR, | 38 MPEG2_AAC_SSR, |
| 38 MPEG4_AAC_LC, | 39 MPEG4_AAC_LC, |
| 39 MPEG4_AAC_SBR_v1, | 40 MPEG4_AAC_SBR_v1, |
| 40 MPEG4_AAC_SBR_PS_v2, | 41 MPEG4_AAC_SBR_PS_v2, |
| 41 VORBIS, | 42 VORBIS, |
| 42 OPUS, | 43 OPUS, |
| 43 H264_BASELINE, | 44 H264, |
| 44 H264_MAIN, | |
| 45 H264_HIGH, | |
| 46 HEVC_MAIN, | 45 HEVC_MAIN, |
|
ddorwin
2016/02/17 19:31:20
Should we remove _MAIN here too?
servolk
2016/02/17 19:49:54
Yes, I'm planning to do that in a separate CL whic
| |
| 47 VP8, | 46 VP8, |
| 48 VP9, | 47 VP9, |
| 49 THEORA | 48 THEORA |
| 50 }; | 49 }; |
| 51 | 50 |
| 52 bool IsSupportedMediaMimeType(const std::string& mime_type) const; | 51 bool IsSupportedMediaMimeType(const std::string& mime_type) const; |
| 53 | 52 |
| 54 void ParseCodecString(const std::string& codecs, | 53 void ParseCodecString(const std::string& codecs, |
| 55 std::vector<std::string>* codecs_out, | 54 std::vector<std::string>* codecs_out, |
| 56 bool strip); | 55 bool strip); |
| (...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 141 switch (codec) { | 140 switch (codec) { |
| 142 case MimeUtil::INVALID_CODEC: | 141 case MimeUtil::INVALID_CODEC: |
| 143 return false; | 142 return false; |
| 144 | 143 |
| 145 case MimeUtil::PCM: | 144 case MimeUtil::PCM: |
| 146 case MimeUtil::MP3: | 145 case MimeUtil::MP3: |
| 147 case MimeUtil::MPEG4_AAC_LC: | 146 case MimeUtil::MPEG4_AAC_LC: |
| 148 case MimeUtil::MPEG4_AAC_SBR_v1: | 147 case MimeUtil::MPEG4_AAC_SBR_v1: |
| 149 case MimeUtil::MPEG4_AAC_SBR_PS_v2: | 148 case MimeUtil::MPEG4_AAC_SBR_PS_v2: |
| 150 case MimeUtil::VORBIS: | 149 case MimeUtil::VORBIS: |
| 151 case MimeUtil::H264_BASELINE: | 150 case MimeUtil::H264: |
| 152 case MimeUtil::H264_MAIN: | |
| 153 case MimeUtil::H264_HIGH: | |
| 154 case MimeUtil::VP8: | 151 case MimeUtil::VP8: |
| 155 return true; | 152 return true; |
| 156 | 153 |
| 157 case MimeUtil::AC3: | 154 case MimeUtil::AC3: |
| 158 case MimeUtil::EAC3: | 155 case MimeUtil::EAC3: |
| 159 // TODO(servolk): Revisit this for AC3/EAC3 support on AndroidTV | 156 // TODO(servolk): Revisit this for AC3/EAC3 support on AndroidTV |
| 160 return false; | 157 return false; |
| 161 | 158 |
| 162 case MimeUtil::MPEG2_AAC_LC: | 159 case MimeUtil::MPEG2_AAC_LC: |
| 163 case MimeUtil::MPEG2_AAC_MAIN: | 160 case MimeUtil::MPEG2_AAC_MAIN: |
| (...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 288 const char* const codec_id; | 285 const char* const codec_id; |
| 289 MimeUtil::Codec codec; | 286 MimeUtil::Codec codec; |
| 290 }; | 287 }; |
| 291 | 288 |
| 292 // List of codec IDs that provide enough information to determine the | 289 // List of codec IDs that provide enough information to determine the |
| 293 // codec and profile being requested. | 290 // codec and profile being requested. |
| 294 // | 291 // |
| 295 // The "mp4a" strings come from RFC 6381. | 292 // The "mp4a" strings come from RFC 6381. |
| 296 static const CodecIDMappings kUnambiguousCodecStringMap[] = { | 293 static const CodecIDMappings kUnambiguousCodecStringMap[] = { |
| 297 {"1", MimeUtil::PCM}, // We only allow this for WAV so it isn't ambiguous. | 294 {"1", MimeUtil::PCM}, // We only allow this for WAV so it isn't ambiguous. |
| 298 // avc1/avc3.XXXXXX may be unambiguous; handled by ParseH264CodecID(). | 295 // avc1/avc3.XXXXXX may be unambiguous; handled by ParseAVCCodecId(). |
| 299 // hev1/hvc1.XXXXXX may be unambiguous; handled by ParseHEVCCodecID(). | 296 // hev1/hvc1.XXXXXX may be unambiguous; handled by ParseHEVCCodecID(). |
| 300 {"mp3", MimeUtil::MP3}, | 297 {"mp3", MimeUtil::MP3}, |
| 301 {"mp4a.66", MimeUtil::MPEG2_AAC_MAIN}, | 298 {"mp4a.66", MimeUtil::MPEG2_AAC_MAIN}, |
| 302 {"mp4a.67", MimeUtil::MPEG2_AAC_LC}, | 299 {"mp4a.67", MimeUtil::MPEG2_AAC_LC}, |
| 303 {"mp4a.68", MimeUtil::MPEG2_AAC_SSR}, | 300 {"mp4a.68", MimeUtil::MPEG2_AAC_SSR}, |
| 304 {"mp4a.69", MimeUtil::MP3}, | 301 {"mp4a.69", MimeUtil::MP3}, |
| 305 {"mp4a.6B", MimeUtil::MP3}, | 302 {"mp4a.6B", MimeUtil::MP3}, |
| 306 {"mp4a.40.2", MimeUtil::MPEG4_AAC_LC}, | 303 {"mp4a.40.2", MimeUtil::MPEG4_AAC_LC}, |
| 307 {"mp4a.40.02", MimeUtil::MPEG4_AAC_LC}, | 304 {"mp4a.40.02", MimeUtil::MPEG4_AAC_LC}, |
| 308 {"mp4a.40.5", MimeUtil::MPEG4_AAC_SBR_v1}, | 305 {"mp4a.40.5", MimeUtil::MPEG4_AAC_SBR_v1}, |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 329 {"vp9", MimeUtil::VP9}, | 326 {"vp9", MimeUtil::VP9}, |
| 330 {"vp9.0", MimeUtil::VP9}, | 327 {"vp9.0", MimeUtil::VP9}, |
| 331 {"theora", MimeUtil::THEORA}}; | 328 {"theora", MimeUtil::THEORA}}; |
| 332 | 329 |
| 333 // List of codec IDs that are ambiguous and don't provide | 330 // List of codec IDs that are ambiguous and don't provide |
| 334 // enough information to determine the codec and profile. | 331 // enough information to determine the codec and profile. |
| 335 // The codec in these entries indicate the codec and profile | 332 // The codec in these entries indicate the codec and profile |
| 336 // we assume the user is trying to indicate. | 333 // we assume the user is trying to indicate. |
| 337 static const CodecIDMappings kAmbiguousCodecStringMap[] = { | 334 static const CodecIDMappings kAmbiguousCodecStringMap[] = { |
| 338 {"mp4a.40", MimeUtil::MPEG4_AAC_LC}, | 335 {"mp4a.40", MimeUtil::MPEG4_AAC_LC}, |
| 339 {"avc1", MimeUtil::H264_BASELINE}, | 336 {"avc1", MimeUtil::H264}, |
| 340 {"avc3", MimeUtil::H264_BASELINE}, | 337 {"avc3", MimeUtil::H264}, |
| 341 // avc1/avc3.XXXXXX may be ambiguous; handled by ParseH264CodecID(). | 338 // avc1/avc3.XXXXXX may be ambiguous; handled by ParseAVCCodecId(). |
| 342 }; | 339 }; |
| 343 | 340 |
| 344 #if BUILDFLAG(ENABLE_MSE_MPEG2TS_STREAM_PARSER) | 341 #if BUILDFLAG(ENABLE_MSE_MPEG2TS_STREAM_PARSER) |
| 345 static const char kHexString[] = "0123456789ABCDEF"; | 342 static const char kHexString[] = "0123456789ABCDEF"; |
| 346 static char IntToHex(int i) { | 343 static char IntToHex(int i) { |
| 347 DCHECK_GE(i, 0) << i << " not a hex value"; | 344 DCHECK_GE(i, 0) << i << " not a hex value"; |
| 348 DCHECK_LE(i, 15) << i << " not a hex value"; | 345 DCHECK_LE(i, 15) << i << " not a hex value"; |
| 349 return kHexString[i]; | 346 return kHexString[i]; |
| 350 } | 347 } |
| 351 | 348 |
| (...skipping 173 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 525 return AreSupportedCodecs(it_media_format_map->second, codecs); | 522 return AreSupportedCodecs(it_media_format_map->second, codecs); |
| 526 } | 523 } |
| 527 | 524 |
| 528 void MimeUtil::RemoveProprietaryMediaTypesAndCodecsForTests() { | 525 void MimeUtil::RemoveProprietaryMediaTypesAndCodecsForTests() { |
| 529 for (size_t i = 0; i < arraysize(kFormatCodecMappings); ++i) | 526 for (size_t i = 0; i < arraysize(kFormatCodecMappings); ++i) |
| 530 if (kFormatCodecMappings[i].format_type == PROPRIETARY) | 527 if (kFormatCodecMappings[i].format_type == PROPRIETARY) |
| 531 media_format_map_.erase(kFormatCodecMappings[i].mime_type); | 528 media_format_map_.erase(kFormatCodecMappings[i].mime_type); |
| 532 allow_proprietary_codecs_ = false; | 529 allow_proprietary_codecs_ = false; |
| 533 } | 530 } |
| 534 | 531 |
| 535 static bool IsValidH264Level(const std::string& level_str) { | 532 static bool IsValidH264Level(uint8_t level_idc) { |
| 536 uint32_t level; | 533 // Valid levels taken from Table A-1 in ISO/IEC 14496-10. |
| 537 if (level_str.size() != 2 || !base::HexStringToUInt(level_str, &level)) | 534 // Level_idc represents the standard level represented as decimal number |
| 538 return false; | 535 // multiplied by ten, e.g. level_idc==32 corresponds to level==3.2 |
| 539 | 536 return ((level_idc >= 10 && level_idc <= 13) || |
| 540 // Valid levels taken from Table A-1 in ISO-14496-10. | 537 (level_idc >= 20 && level_idc <= 22) || |
| 541 // Essentially |level_str| is toHex(10 * level). | 538 (level_idc >= 30 && level_idc <= 32) || |
| 542 return ((level >= 10 && level <= 13) || | 539 (level_idc >= 40 && level_idc <= 42) || |
| 543 (level >= 20 && level <= 22) || | 540 (level_idc >= 50 && level_idc <= 51)); |
| 544 (level >= 30 && level <= 32) || | |
| 545 (level >= 40 && level <= 42) || | |
| 546 (level >= 50 && level <= 51)); | |
| 547 } | |
| 548 | |
| 549 // Handle parsing H.264 codec IDs as outlined in RFC 6381 and ISO-14496-10. | |
| 550 // avc1.42x0yy - H.264 Baseline | |
| 551 // avc1.4Dx0yy - H.264 Main | |
| 552 // avc1.64x0yy - H.264 High | |
| 553 // | |
| 554 // avc1.xxxxxx & avc3.xxxxxx are considered ambiguous forms that are trying to | |
| 555 // signal H.264 Baseline. For example, the idc_level, profile_idc and | |
| 556 // constraint_set3_flag pieces may explicitly require decoder to conform to | |
| 557 // baseline profile at the specified level (see Annex A and constraint_set0 in | |
| 558 // ISO-14496-10). | |
| 559 static bool ParseH264CodecID(const std::string& codec_id, | |
| 560 MimeUtil::Codec* codec, | |
| 561 bool* is_ambiguous) { | |
| 562 // Make sure we have avc1.xxxxxx or avc3.xxxxxx , where xxxxxx are hex digits | |
| 563 if (!base::StartsWith(codec_id, "avc1.", base::CompareCase::SENSITIVE) && | |
| 564 !base::StartsWith(codec_id, "avc3.", base::CompareCase::SENSITIVE)) { | |
| 565 return false; | |
| 566 } | |
| 567 if (codec_id.size() != 11 || | |
| 568 !base::IsHexDigit(codec_id[5]) || !base::IsHexDigit(codec_id[6]) || | |
| 569 !base::IsHexDigit(codec_id[7]) || !base::IsHexDigit(codec_id[8]) || | |
| 570 !base::IsHexDigit(codec_id[9]) || !base::IsHexDigit(codec_id[10])) { | |
| 571 return false; | |
| 572 } | |
| 573 | |
| 574 // Validate constraint flags and reserved bits. | |
| 575 if (!base::IsHexDigit(codec_id[7]) || codec_id[8] != '0') { | |
| 576 *codec = MimeUtil::H264_BASELINE; | |
| 577 *is_ambiguous = true; | |
| 578 return true; | |
| 579 } | |
| 580 | |
| 581 // Extract the profile. | |
| 582 std::string profile = base::ToUpperASCII(codec_id.substr(5, 2)); | |
| 583 if (profile == "42") { | |
| 584 *codec = MimeUtil::H264_BASELINE; | |
| 585 } else if (profile == "4D") { | |
| 586 *codec = MimeUtil::H264_MAIN; | |
| 587 } else if (profile == "64") { | |
| 588 *codec = MimeUtil::H264_HIGH; | |
| 589 } else { | |
| 590 *codec = MimeUtil::H264_BASELINE; | |
| 591 *is_ambiguous = true; | |
| 592 return true; | |
| 593 } | |
| 594 | |
| 595 // Validate level. | |
| 596 *is_ambiguous = !IsValidH264Level(codec_id.substr(9)); | |
| 597 return true; | |
| 598 } | 541 } |
| 599 | 542 |
| 600 #if BUILDFLAG(ENABLE_HEVC_DEMUXING) | 543 #if BUILDFLAG(ENABLE_HEVC_DEMUXING) |
| 601 // ISO/IEC FDIS 14496-15 standard section E.3 describes the syntax of codec ids | 544 // ISO/IEC FDIS 14496-15 standard section E.3 describes the syntax of codec ids |
| 602 // reserved for HEVC. According to that spec HEVC codec id must start with | 545 // reserved for HEVC. According to that spec HEVC codec id must start with |
| 603 // either "hev1." or "hvc1.". We don't yet support full parsing of HEVC codec | 546 // either "hev1." or "hvc1.". We don't yet support full parsing of HEVC codec |
| 604 // ids, but since no other codec id starts with those string we'll just treat | 547 // ids, but since no other codec id starts with those string we'll just treat |
| 605 // any string starting with "hev1." or "hvc1." as valid HEVC codec ids. | 548 // any string starting with "hev1." or "hvc1." as valid HEVC codec ids. |
| 606 // crbug.com/482761 | 549 // crbug.com/482761 |
| 607 static bool ParseHEVCCodecID(const std::string& codec_id, | 550 static bool ParseHEVCCodecID(const std::string& codec_id, |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 645 } | 588 } |
| 646 | 589 |
| 647 // If |codec_id| is not in |string_to_codec_map_|, then we assume that it is | 590 // If |codec_id| is not in |string_to_codec_map_|, then we assume that it is |
| 648 // either H.264 or HEVC/H.265 codec ID because currently those are the only | 591 // either H.264 or HEVC/H.265 codec ID because currently those are the only |
| 649 // ones that are not added to the |string_to_codec_map_| and require parsing. | 592 // ones that are not added to the |string_to_codec_map_| and require parsing. |
| 650 #if BUILDFLAG(ENABLE_HEVC_DEMUXING) | 593 #if BUILDFLAG(ENABLE_HEVC_DEMUXING) |
| 651 if (ParseHEVCCodecID(codec_id, codec, is_ambiguous)) { | 594 if (ParseHEVCCodecID(codec_id, codec, is_ambiguous)) { |
| 652 return true; | 595 return true; |
| 653 } | 596 } |
| 654 #endif | 597 #endif |
| 655 return ParseH264CodecID(codec_id, codec, is_ambiguous); | 598 |
| 599 VideoCodecProfile profile = VIDEO_CODEC_PROFILE_UNKNOWN; | |
| 600 uint8_t level_idc = 0; | |
| 601 if (ParseAVCCodecId(codec_id, &profile, &level_idc)) { | |
| 602 *codec = MimeUtil::H264; | |
| 603 *is_ambiguous = | |
| 604 (profile != H264PROFILE_BASELINE && profile != H264PROFILE_MAIN && | |
| 605 profile != H264PROFILE_HIGH) || | |
| 606 !IsValidH264Level(level_idc); | |
| 607 return true; | |
| 608 } | |
| 609 | |
| 610 DVLOG(4) << __FUNCTION__ << ": Unrecognized codec id " << codec_id; | |
| 611 return false; | |
| 656 } | 612 } |
| 657 | 613 |
| 658 bool MimeUtil::IsCodecSupported(Codec codec) const { | 614 bool MimeUtil::IsCodecSupported(Codec codec) const { |
| 659 DCHECK_NE(codec, INVALID_CODEC); | 615 DCHECK_NE(codec, INVALID_CODEC); |
| 660 | 616 |
| 661 #if defined(OS_ANDROID) | 617 #if defined(OS_ANDROID) |
| 662 if (!IsCodecSupportedOnAndroid(codec)) | 618 if (!IsCodecSupportedOnAndroid(codec)) |
| 663 return false; | 619 return false; |
| 664 #endif | 620 #endif |
| 665 | 621 |
| 666 return allow_proprietary_codecs_ || !IsCodecProprietary(codec); | 622 return allow_proprietary_codecs_ || !IsCodecProprietary(codec); |
| 667 } | 623 } |
| 668 | 624 |
| 669 bool MimeUtil::IsCodecProprietary(Codec codec) const { | 625 bool MimeUtil::IsCodecProprietary(Codec codec) const { |
| 670 switch (codec) { | 626 switch (codec) { |
| 671 case INVALID_CODEC: | 627 case INVALID_CODEC: |
| 672 case AC3: | 628 case AC3: |
| 673 case EAC3: | 629 case EAC3: |
| 674 case MP3: | 630 case MP3: |
| 675 case MPEG2_AAC_LC: | 631 case MPEG2_AAC_LC: |
| 676 case MPEG2_AAC_MAIN: | 632 case MPEG2_AAC_MAIN: |
| 677 case MPEG2_AAC_SSR: | 633 case MPEG2_AAC_SSR: |
| 678 case MPEG4_AAC_LC: | 634 case MPEG4_AAC_LC: |
| 679 case MPEG4_AAC_SBR_v1: | 635 case MPEG4_AAC_SBR_v1: |
| 680 case MPEG4_AAC_SBR_PS_v2: | 636 case MPEG4_AAC_SBR_PS_v2: |
| 681 case H264_BASELINE: | 637 case H264: |
| 682 case H264_MAIN: | |
| 683 case H264_HIGH: | |
| 684 case HEVC_MAIN: | 638 case HEVC_MAIN: |
| 685 return true; | 639 return true; |
| 686 | 640 |
| 687 case PCM: | 641 case PCM: |
| 688 case VORBIS: | 642 case VORBIS: |
| 689 case OPUS: | 643 case OPUS: |
| 690 case VP8: | 644 case VP8: |
| 691 case VP9: | 645 case VP9: |
| 692 case THEORA: | 646 case THEORA: |
| 693 return false; | 647 return false; |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 734 std::vector<std::string>* codecs_out, | 688 std::vector<std::string>* codecs_out, |
| 735 const bool strip) { | 689 const bool strip) { |
| 736 g_media_mime_util.Get().ParseCodecString(codecs, codecs_out, strip); | 690 g_media_mime_util.Get().ParseCodecString(codecs, codecs_out, strip); |
| 737 } | 691 } |
| 738 | 692 |
| 739 void RemoveProprietaryMediaTypesAndCodecsForTests() { | 693 void RemoveProprietaryMediaTypesAndCodecsForTests() { |
| 740 g_media_mime_util.Get().RemoveProprietaryMediaTypesAndCodecsForTests(); | 694 g_media_mime_util.Get().RemoveProprietaryMediaTypesAndCodecsForTests(); |
| 741 } | 695 } |
| 742 | 696 |
| 743 } // namespace media | 697 } // namespace media |
| OLD | NEW |