Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(52)

Side by Side Diff: media/base/mime_util_internal.cc

Issue 1690063002: Fix mime type mappings when the unified media pipeline is enabled. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Comments. Created 4 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698