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

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

Issue 2700893003: Various MimeUtil cleanups. (Closed)
Patch Set: whackamole Created 3 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
« no previous file with comments | « media/base/mime_util_internal.h ('k') | media/base/mime_util_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 <map>
8
7 #include "base/command_line.h" 9 #include "base/command_line.h"
8 #include "base/strings/string_number_conversions.h" 10 #include "base/strings/string_number_conversions.h"
9 #include "base/strings/string_split.h" 11 #include "base/strings/string_split.h"
10 #include "base/strings/string_util.h" 12 #include "base/strings/string_util.h"
11 #include "build/build_config.h" 13 #include "build/build_config.h"
12 #include "media/base/media.h" 14 #include "media/base/media.h"
13 #include "media/base/media_client.h" 15 #include "media/base/media_client.h"
14 #include "media/base/media_switches.h" 16 #include "media/base/media_switches.h"
15 #include "media/base/video_codecs.h" 17 #include "media/base/video_codecs.h"
16 #include "media/media_features.h" 18 #include "media/media_features.h"
17 19
18 #if defined(OS_ANDROID) 20 #if defined(OS_ANDROID)
19 #include "base/android/build_info.h" 21 #include "base/android/build_info.h"
20 #include "media/base/android/media_codec_util.h" 22 #include "media/base/android/media_codec_util.h"
21 #endif 23 #endif
22 24
23 namespace media { 25 namespace media {
24 namespace internal { 26 namespace internal {
25 27
26 struct CodecIDMappings { 28 // Wrapped to avoid static initializer startup cost.
27 const char* const codec_id; 29 const std::map<std::string, MimeUtil::Codec>& GetStringToCodecMap() {
28 MimeUtil::Codec codec; 30 static const std::map<std::string, MimeUtil::Codec> kStringToCodecMap = {
29 }; 31 // We only allow this for WAV so it isn't ambiguous.
30 32 {"1", MimeUtil::PCM},
31 // List of codec IDs that provide enough information to determine the
32 // codec and profile being requested.
33 //
34 // The "mp4a" strings come from RFC 6381.
35 static const CodecIDMappings kUnambiguousCodecStringMap[] = {
36 {"1", MimeUtil::PCM}, // We only allow this for WAV so it isn't ambiguous.
37 // avc1/avc3.XXXXXX may be unambiguous; handled by ParseAVCCodecId(). 33 // avc1/avc3.XXXXXX may be unambiguous; handled by ParseAVCCodecId().
38 // hev1/hvc1.XXXXXX may be unambiguous; handled by ParseHEVCCodecID(). 34 // hev1/hvc1.XXXXXX may be unambiguous; handled by ParseHEVCCodecID().
39 // vp9, vp9.0, vp09.xx.xx.xx.xx.xx.xx.xx may be unambiguous; handled by 35 // vp9, vp9.0, vp09.xx.xx.xx.xx.xx.xx.xx may be unambiguous; handled by
40 // ParseVp9CodecID(). 36 // ParseVp9CodecID().
41 {"mp3", MimeUtil::MP3}, 37 {"mp3", MimeUtil::MP3},
42 // Following is the list of RFC 6381 compliant audio codec strings: 38 // Following is the list of RFC 6381 compliant audio codec strings:
43 // mp4a.66 - MPEG-2 AAC MAIN 39 // mp4a.66 - MPEG-2 AAC MAIN
44 // mp4a.67 - MPEG-2 AAC LC 40 // mp4a.67 - MPEG-2 AAC LC
45 // mp4a.68 - MPEG-2 AAC SSR 41 // mp4a.68 - MPEG-2 AAC SSR
46 // mp4a.69 - MPEG-2 extension to MPEG-1 (MP3) 42 // mp4a.69 - MPEG-2 extension to MPEG-1 (MP3)
47 // mp4a.6B - MPEG-1 audio (MP3) 43 // mp4a.6B - MPEG-1 audio (MP3)
48 // mp4a.40.2 - MPEG-4 AAC LC 44 // mp4a.40.2 - MPEG-4 AAC LC
49 // mp4a.40.02 - MPEG-4 AAC LC (leading 0 in aud-oti for compatibility) 45 // mp4a.40.02 - MPEG-4 AAC LC (leading 0 in aud-oti for compatibility)
50 // mp4a.40.5 - MPEG-4 HE-AAC v1 (AAC LC + SBR) 46 // mp4a.40.5 - MPEG-4 HE-AAC v1 (AAC LC + SBR)
51 // mp4a.40.05 - MPEG-4 HE-AAC v1 (AAC LC + SBR) (leading 0 in aud-oti for 47 // mp4a.40.05 - MPEG-4 HE-AAC v1 (AAC LC + SBR) (leading 0 in aud-oti
52 // compatibility) 48 // for compatibility)
53 // mp4a.40.29 - MPEG-4 HE-AAC v2 (AAC LC + SBR + PS) 49 // mp4a.40.29 - MPEG-4 HE-AAC v2 (AAC LC + SBR + PS)
54 {"mp4a.66", MimeUtil::MPEG2_AAC}, 50 {"mp4a.66", MimeUtil::MPEG2_AAC},
55 {"mp4a.67", MimeUtil::MPEG2_AAC}, 51 {"mp4a.67", MimeUtil::MPEG2_AAC},
56 {"mp4a.68", MimeUtil::MPEG2_AAC}, 52 {"mp4a.68", MimeUtil::MPEG2_AAC},
57 {"mp4a.69", MimeUtil::MP3}, 53 {"mp4a.69", MimeUtil::MP3},
58 {"mp4a.6B", MimeUtil::MP3}, 54 {"mp4a.6B", MimeUtil::MP3},
59 {"mp4a.40.2", MimeUtil::MPEG4_AAC}, 55 {"mp4a.40.2", MimeUtil::MPEG4_AAC},
60 {"mp4a.40.02", MimeUtil::MPEG4_AAC}, 56 {"mp4a.40.02", MimeUtil::MPEG4_AAC},
61 {"mp4a.40.5", MimeUtil::MPEG4_AAC}, 57 {"mp4a.40.5", MimeUtil::MPEG4_AAC},
62 {"mp4a.40.05", MimeUtil::MPEG4_AAC}, 58 {"mp4a.40.05", MimeUtil::MPEG4_AAC},
63 {"mp4a.40.29", MimeUtil::MPEG4_AAC}, 59 {"mp4a.40.29", MimeUtil::MPEG4_AAC},
64 #if BUILDFLAG(ENABLE_AC3_EAC3_AUDIO_DEMUXING) 60 #if BUILDFLAG(ENABLE_AC3_EAC3_AUDIO_DEMUXING)
65 // TODO(servolk): Strictly speaking only mp4a.A5 and mp4a.A6 codec ids are 61 // TODO(servolk): Strictly speaking only mp4a.A5 and mp4a.A6 codec ids are
66 // valid according to RFC 6381 section 3.3, 3.4. Lower-case oti (mp4a.a5 and 62 // valid according to RFC 6381 section 3.3, 3.4. Lower-case oti (mp4a.a5
67 // mp4a.a6) should be rejected. But we used to allow those in older versions 63 // and mp4a.a6) should be rejected. But we used to allow those in older
68 // of Chromecast firmware and some apps (notably MPL) depend on those codec 64 // versions of Chromecast firmware and some apps (notably MPL) depend on
69 // types being supported, so they should be allowed for now 65 // those codec types being supported, so they should be allowed for now
70 // (crbug.com/564960). 66 // (crbug.com/564960).
71 {"ac-3", MimeUtil::AC3}, 67 {"ac-3", MimeUtil::AC3},
72 {"mp4a.a5", MimeUtil::AC3}, 68 {"mp4a.a5", MimeUtil::AC3},
73 {"mp4a.A5", MimeUtil::AC3}, 69 {"mp4a.A5", MimeUtil::AC3},
74 {"ec-3", MimeUtil::EAC3}, 70 {"ec-3", MimeUtil::EAC3},
75 {"mp4a.a6", MimeUtil::EAC3}, 71 {"mp4a.a6", MimeUtil::EAC3},
76 {"mp4a.A6", MimeUtil::EAC3}, 72 {"mp4a.A6", MimeUtil::EAC3},
77 #endif 73 #endif
78 {"vorbis", MimeUtil::VORBIS}, 74 {"vorbis", MimeUtil::VORBIS},
79 {"opus", MimeUtil::OPUS}, 75 {"opus", MimeUtil::OPUS},
80 {"flac", MimeUtil::FLAC}, 76 {"flac", MimeUtil::FLAC},
81 {"vp8", MimeUtil::VP8}, 77 {"vp8", MimeUtil::VP8},
82 {"vp8.0", MimeUtil::VP8}, 78 {"vp8.0", MimeUtil::VP8},
83 {"theora", MimeUtil::THEORA}}; 79 {"theora", MimeUtil::THEORA}
80 };
84 81
85 // List of codec IDs that are ambiguous and don't provide 82 return kStringToCodecMap;
86 // enough information to determine the codec and profile. 83 }
87 // The codec in these entries indicate the codec and profile
88 // we assume the user is trying to indicate.
89 static const CodecIDMappings kAmbiguousCodecStringMap[] = {
90 {"mp4a.40", MimeUtil::MPEG4_AAC},
91 {"avc1", MimeUtil::H264},
92 {"avc3", MimeUtil::H264},
93 // avc1/avc3.XXXXXX may be ambiguous; handled by ParseAVCCodecId().
94 };
95 84
96 static bool ParseVp9CodecID(const std::string& mime_type_lower_case, 85 static bool ParseVp9CodecID(const std::string& mime_type_lower_case,
97 const std::string& codec_id, 86 const std::string& codec_id,
98 VideoCodecProfile* out_profile, 87 VideoCodecProfile* out_profile,
99 uint8_t* out_level) { 88 uint8_t* out_level) {
100 if (mime_type_lower_case == "video/mp4") { 89 if (mime_type_lower_case == "video/mp4") {
101 if (base::CommandLine::ForCurrentProcess()->HasSwitch( 90 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
102 switches::kEnableVp9InMp4)) { 91 switches::kEnableVp9InMp4)) {
103 return ParseNewStyleVp9CodecID(codec_id, out_profile, out_level); 92 return ParseNewStyleVp9CodecID(codec_id, out_profile, out_level);
104 } 93 }
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
158 } 147 }
159 148
160 SupportsType MimeUtil::AreSupportedCodecs( 149 SupportsType MimeUtil::AreSupportedCodecs(
161 const CodecSet& supported_codecs, 150 const CodecSet& supported_codecs,
162 const std::vector<std::string>& codecs, 151 const std::vector<std::string>& codecs,
163 const std::string& mime_type_lower_case, 152 const std::string& mime_type_lower_case,
164 bool is_encrypted) const { 153 bool is_encrypted) const {
165 DCHECK(!supported_codecs.empty()); 154 DCHECK(!supported_codecs.empty());
166 DCHECK(!codecs.empty()); 155 DCHECK(!codecs.empty());
167 156
168 SupportsType result = IsSupported; 157 SupportsType combined_result = IsSupported;
158
169 for (size_t i = 0; i < codecs.size(); ++i) { 159 for (size_t i = 0; i < codecs.size(); ++i) {
170 bool is_ambiguous = true; 160 // Parse the string.
161 bool ambiguous_codec_string = false;
171 Codec codec = INVALID_CODEC; 162 Codec codec = INVALID_CODEC;
172 VideoCodecProfile video_profile = VIDEO_CODEC_PROFILE_UNKNOWN; 163 VideoCodecProfile video_profile = VIDEO_CODEC_PROFILE_UNKNOWN;
173 uint8_t video_level = 0; 164 uint8_t video_level = 0;
174 if (!StringToCodec(mime_type_lower_case, codecs[i], &codec, &is_ambiguous, 165 if (!ParseCodecString(mime_type_lower_case, codecs[i], &codec,
175 &video_profile, &video_level, is_encrypted)) { 166 &ambiguous_codec_string, &video_profile,
167 &video_level)) {
176 return IsNotSupported; 168 return IsNotSupported;
177 } 169 }
178 170
179 VideoCodec video_codec = MimeUtilToVideoCodec(codec); 171 // Bail if codec not in supported list for given container.
172 if (supported_codecs.find(codec) == supported_codecs.end())
173 return IsNotSupported;
180 174
181 if (GetMediaClient() && video_codec != kUnknownVideoCodec && 175 // Make conservative guesses to resolve ambiguity before checking platform
182 !GetMediaClient()->IsSupportedVideoConfig(video_codec, video_profile, 176 // support. H264 and VP9 are the only allowed ambiguous video codec. DO NOT
183 video_level)) { 177 // ADD SUPPORT FOR MORE AMIBIGUOUS STRINGS.
184 return IsNotSupported; 178 if (codec == MimeUtil::H264 && ambiguous_codec_string) {
179 if (video_profile == VIDEO_CODEC_PROFILE_UNKNOWN)
180 video_profile = H264PROFILE_BASELINE;
181 if (!IsValidH264Level(video_level))
182 video_level = 10;
183 } else if (codec == MimeUtil::VP9 && video_level == 0) {
184 // Original VP9 content type (codecs="vp9") does not specify the level.
185 // TODO(chcunningham): Mark this string as ambiguous when new multi-part
186 // VP9 content type is published.
187 video_level = 10;
185 } 188 }
186 189
187 if (!IsCodecSupported(codec, mime_type_lower_case, is_encrypted) || 190 // Check platform support.
188 supported_codecs.find(codec) == supported_codecs.end()) { 191 SupportsType result = IsCodecSupported(
192 mime_type_lower_case, codec, video_profile, video_level, is_encrypted);
193 if (result == IsNotSupported)
189 return IsNotSupported; 194 return IsNotSupported;
190 }
191 195
192 if (is_ambiguous) 196 // If any codec is "MayBeSupported", return Maybe for the combined result.
193 result = MayBeSupported; 197 // Downgrade to MayBeSupported if we had to guess the meaning of one of the
198 // codec strings.
199 if (result == MayBeSupported ||
200 (result == IsSupported && ambiguous_codec_string))
201 combined_result = MayBeSupported;
jrummell 2017/02/22 19:23:19 Not sure why you added |combined_result|. Can you
chcunningham 2017/02/22 20:44:12 Unfortunately not. Its possible that this codec is
194 } 202 }
195 203
196 return result; 204 return combined_result;
197 } 205 }
198 206
199 void MimeUtil::InitializeMimeTypeMaps() { 207 void MimeUtil::InitializeMimeTypeMaps() {
200 #if BUILDFLAG(USE_PROPRIETARY_CODECS) 208 #if BUILDFLAG(USE_PROPRIETARY_CODECS)
201 allow_proprietary_codecs_ = true; 209 allow_proprietary_codecs_ = true;
202 #endif 210 #endif
203 211
204 for (size_t i = 0; i < arraysize(kUnambiguousCodecStringMap); ++i) {
205 string_to_codec_map_[kUnambiguousCodecStringMap[i].codec_id] =
206 CodecEntry(kUnambiguousCodecStringMap[i].codec, false);
207 }
208
209 for (size_t i = 0; i < arraysize(kAmbiguousCodecStringMap); ++i) {
210 string_to_codec_map_[kAmbiguousCodecStringMap[i].codec_id] =
211 CodecEntry(kAmbiguousCodecStringMap[i].codec, true);
212 }
213
214 AddSupportedMediaFormats(); 212 AddSupportedMediaFormats();
215 } 213 }
216 214
217 // Each call to AddContainerWithCodecs() contains a media type 215 // Each call to AddContainerWithCodecs() contains a media type
218 // (https://en.wikipedia.org/wiki/Media_type) and corresponding media codec(s) 216 // (https://en.wikipedia.org/wiki/Media_type) and corresponding media codec(s)
219 // supported by these types/containers. 217 // supported by these types/containers.
220 // TODO(ddorwin): Replace insert() calls with initializer_list when allowed. 218 // TODO(ddorwin): Replace insert() calls with initializer_list when allowed.
221 void MimeUtil::AddSupportedMediaFormats() { 219 void MimeUtil::AddSupportedMediaFormats() {
222 CodecSet implicit_codec; 220 CodecSet implicit_codec;
223 CodecSet wav_codecs; 221 CodecSet wav_codecs;
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after
332 330
333 if (is_proprietary_mime_type) 331 if (is_proprietary_mime_type)
334 proprietary_media_containers_.push_back(mime_type); 332 proprietary_media_containers_.push_back(mime_type);
335 } 333 }
336 334
337 bool MimeUtil::IsSupportedMediaMimeType(const std::string& mime_type) const { 335 bool MimeUtil::IsSupportedMediaMimeType(const std::string& mime_type) const {
338 return media_format_map_.find(base::ToLowerASCII(mime_type)) != 336 return media_format_map_.find(base::ToLowerASCII(mime_type)) !=
339 media_format_map_.end(); 337 media_format_map_.end();
340 } 338 }
341 339
342 void MimeUtil::ParseCodecString(const std::string& codecs, 340 void MimeUtil::SplitCodecsToVector(const std::string& codecs,
343 std::vector<std::string>* codecs_out, 341 std::vector<std::string>* codecs_out,
344 bool strip) { 342 bool strip) {
345 *codecs_out = 343 *codecs_out =
346 base::SplitString(base::TrimString(codecs, "\"", base::TRIM_ALL), ",", 344 base::SplitString(base::TrimString(codecs, "\"", base::TRIM_ALL), ",",
347 base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL); 345 base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
348 346
349 // Convert empty or all-whitespace input to 0 results. 347 // Convert empty or all-whitespace input to 0 results.
350 if (codecs_out->size() == 1 && (*codecs_out)[0].empty()) 348 if (codecs_out->size() == 1 && (*codecs_out)[0].empty())
351 codecs_out->clear(); 349 codecs_out->clear();
352 350
353 if (!strip) 351 if (!strip)
354 return; 352 return;
(...skipping 12 matching lines...) Expand all
367 const std::vector<std::string>& codecs, 365 const std::vector<std::string>& codecs,
368 bool is_encrypted) const { 366 bool is_encrypted) const {
369 const std::string mime_type_lower_case = base::ToLowerASCII(mime_type); 367 const std::string mime_type_lower_case = base::ToLowerASCII(mime_type);
370 MediaFormatMappings::const_iterator it_media_format_map = 368 MediaFormatMappings::const_iterator it_media_format_map =
371 media_format_map_.find(mime_type_lower_case); 369 media_format_map_.find(mime_type_lower_case);
372 if (it_media_format_map == media_format_map_.end()) 370 if (it_media_format_map == media_format_map_.end())
373 return IsNotSupported; 371 return IsNotSupported;
374 372
375 if (it_media_format_map->second.empty()) { 373 if (it_media_format_map->second.empty()) {
376 // We get here if the mimetype does not expect a codecs parameter. 374 // We get here if the mimetype does not expect a codecs parameter.
377 return (codecs.empty() && IsDefaultCodecSupportedLowerCase( 375 if (codecs.empty()) {
378 mime_type_lower_case, is_encrypted)) 376 return IsDefaultCodecSupportedLowerCase(mime_type_lower_case,
379 ? IsSupported 377 is_encrypted);
380 : IsNotSupported; 378 } else {
379 return IsNotSupported;
380 }
381 } 381 }
382 382
383 if (codecs.empty()) { 383 if (codecs.empty()) {
384 // We get here if the mimetype expects to get a codecs parameter, 384 // We get here if the mimetype expects to get a codecs parameter,
385 // but didn't get one. If |mime_type_lower_case| does not have a default 385 // but didn't get one. If |mime_type_lower_case| does not have a default
386 // codec the best we can do is say "maybe" because we don't have enough 386 // codec the best we can do is say "maybe" because we don't have enough
387 // information. 387 // information.
388 Codec default_codec = INVALID_CODEC; 388 Codec default_codec = INVALID_CODEC;
389 if (!GetDefaultCodecLowerCase(mime_type_lower_case, &default_codec)) 389 if (!GetDefaultCodecLowerCase(mime_type_lower_case, &default_codec))
390 return MayBeSupported; 390 return MayBeSupported;
391 391
392 return IsCodecSupported(default_codec, mime_type_lower_case, is_encrypted) 392 return IsSimpleCodecSupported(mime_type_lower_case, default_codec,
393 ? IsSupported 393 is_encrypted);
394 : IsNotSupported;
395 } 394 }
396 395
397 #if BUILDFLAG(ENABLE_MSE_MPEG2TS_STREAM_PARSER) 396 #if BUILDFLAG(ENABLE_MSE_MPEG2TS_STREAM_PARSER)
398 if (mime_type_lower_case == "video/mp2t") { 397 if (mime_type_lower_case == "video/mp2t") {
399 std::vector<std::string> codecs_to_check; 398 std::vector<std::string> codecs_to_check;
400 for (const auto& codec_id : codecs) { 399 for (const auto& codec_id : codecs) {
401 codecs_to_check.push_back(TranslateLegacyAvc1CodecIds(codec_id)); 400 codecs_to_check.push_back(TranslateLegacyAvc1CodecIds(codec_id));
402 } 401 }
403 return AreSupportedCodecs(it_media_format_map->second, codecs_to_check, 402 return AreSupportedCodecs(it_media_format_map->second, codecs_to_check,
404 mime_type_lower_case, is_encrypted); 403 mime_type_lower_case, is_encrypted);
405 } 404 }
406 #endif 405 #endif
407 406
408 return AreSupportedCodecs(it_media_format_map->second, codecs, 407 return AreSupportedCodecs(it_media_format_map->second, codecs,
409 mime_type_lower_case, is_encrypted); 408 mime_type_lower_case, is_encrypted);
410 } 409 }
411 410
412 void MimeUtil::RemoveProprietaryMediaTypesAndCodecs() { 411 void MimeUtil::RemoveProprietaryMediaTypesAndCodecs() {
413 for (const auto& container : proprietary_media_containers_) 412 for (const auto& container : proprietary_media_containers_)
414 media_format_map_.erase(container); 413 media_format_map_.erase(container);
415 allow_proprietary_codecs_ = false; 414 allow_proprietary_codecs_ = false;
416 } 415 }
417 416
418 // static 417 // static
419 bool MimeUtil::IsCodecSupportedOnPlatform( 418 bool MimeUtil::IsCodecSupportedOnAndroid(
jrummell 2017/02/22 19:23:19 Should this be #if defined(ANDROID)? Maybe not for
chcunningham 2017/02/22 20:44:11 Leaving as is for testing.
420 Codec codec, 419 Codec codec,
421 const std::string& mime_type_lower_case, 420 const std::string& mime_type_lower_case,
422 bool is_encrypted, 421 bool is_encrypted,
423 const PlatformInfo& platform_info) { 422 const PlatformInfo& platform_info) {
424 DCHECK_NE(mime_type_lower_case, ""); 423 DCHECK_NE(mime_type_lower_case, "");
425 424
426 // Encrypted block support is never available without platform decoders. 425 // Encrypted block support is never available without platform decoders.
427 if (is_encrypted && !platform_info.has_platform_decoders) 426 if (is_encrypted && !platform_info.has_platform_decoders)
428 return false; 427 return false;
429 428
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after
535 return true; 534 return true;
536 535
537 // MediaPlayer only supports VP9 in WebM. 536 // MediaPlayer only supports VP9 in WebM.
538 return mime_type_lower_case == "video/webm"; 537 return mime_type_lower_case == "video/webm";
539 } 538 }
540 } 539 }
541 540
542 return false; 541 return false;
543 } 542 }
544 543
545 bool MimeUtil::StringToCodec(const std::string& mime_type_lower_case, 544 bool MimeUtil::ParseCodecString(const std::string& mime_type_lower_case,
546 const std::string& codec_id, 545 const std::string& codec_id,
547 Codec* codec, 546 Codec* codec,
548 bool* is_ambiguous, 547 bool* ambiguous_codec_string,
549 VideoCodecProfile* out_profile, 548 VideoCodecProfile* out_profile,
550 uint8_t* out_level, 549 uint8_t* out_level) const {
551 bool is_encrypted) const { 550 DCHECK(codec);
552 DCHECK(out_profile); 551 DCHECK(out_profile);
553 DCHECK(out_level); 552 DCHECK(out_level);
553
554 *codec = INVALID_CODEC;
555 *ambiguous_codec_string = false;
554 *out_profile = VIDEO_CODEC_PROFILE_UNKNOWN; 556 *out_profile = VIDEO_CODEC_PROFILE_UNKNOWN;
555 *out_level = 0; 557 *out_level = 0;
556 558
557 StringToCodecMappings::const_iterator itr = 559 std::map<std::string, Codec>::const_iterator itr =
558 string_to_codec_map_.find(codec_id); 560 GetStringToCodecMap().find(codec_id);
559 if (itr != string_to_codec_map_.end()) { 561 if (itr != GetStringToCodecMap().end()) {
560 *codec = itr->second.codec; 562 *codec = itr->second;
561 *is_ambiguous = itr->second.is_ambiguous; 563
562 return true; 564 return true;
563 } 565 }
564 566
565 // If |codec_id| is not in |string_to_codec_map_|, then we assume that it is 567 // Check codec string against short list of allowed ambiguous codecs.
568 // Hard-coded to discourage expansion. DO NOT ADD TO THIS LIST. DO NOT
569 // INCREASE PLACES WHERE |ambiguous_codec_string| = true.
570 // NOTE: avc1/avc3.XXXXXX may be ambiguous handled after ParseAVCCodecId().
jrummell 2017/02/22 19:23:19 Like the comment!
chcunningham 2017/02/22 20:44:11 Thanks :)
571 if (codec_id == "avc1" || codec_id == "avc3") {
572 *codec = MimeUtil::H264;
573 *ambiguous_codec_string = true;
574 return true;
575 } else if (codec_id == "mp4a.40") {
576 *codec = MimeUtil::MPEG4_AAC;
577 *ambiguous_codec_string = true;
578 return true;
579 }
580
581 // If |codec_id| is not in |kStringToCodecMap|, then we assume that it is
566 // either VP9, H.264 or HEVC/H.265 codec ID because currently those are the 582 // either VP9, H.264 or HEVC/H.265 codec ID because currently those are the
567 // only ones that are not added to the |string_to_codec_map_| and require 583 // only ones that are not added to the |kStringToCodecMap| and require
568 // parsing. 584 // parsing.
569 if (ParseVp9CodecID(mime_type_lower_case, codec_id, out_profile, out_level)) { 585 if (ParseVp9CodecID(mime_type_lower_case, codec_id, out_profile, out_level)) {
570 *codec = MimeUtil::VP9; 586 *codec = MimeUtil::VP9;
571 switch (*out_profile) {
572 case VP9PROFILE_PROFILE0:
573 // Profile 0 should always be supported if VP9 is supported.
574 *is_ambiguous = false;
575 break;
576 default:
577 // We don't know if the underlying platform supports these profiles.
578 // Need to add platform level querying to get supported profiles
579 // (crbug/604566).
580 *is_ambiguous = true;
581 break;
582 }
583 return true; 587 return true;
584 } 588 }
585 589
586 if (ParseAVCCodecId(codec_id, out_profile, out_level)) { 590 if (ParseAVCCodecId(codec_id, out_profile, out_level)) {
587 *codec = MimeUtil::H264; 591 *codec = MimeUtil::H264;
588 switch (*out_profile) { 592 // Allowed string ambiguity since 2014. DO NOT ADD NEW CASES FOR AMBIGUITY.
589 // HIGH10PROFILE is supported through fallback to the ffmpeg decoder 593 *ambiguous_codec_string = !IsValidH264Level(*out_level);
590 // which is not available on Android, or if FFMPEG is not used.
591 #if !defined(MEDIA_DISABLE_FFMPEG) && !defined(OS_ANDROID)
592 case H264PROFILE_HIGH10PROFILE:
593 if (is_encrypted) {
594 // FFmpeg is not generally used for encrypted videos, so we do not
595 // know whether 10-bit is supported.
596 *is_ambiguous = true;
597 break;
598 }
599 // Fall through.
600 #endif
601
602 case H264PROFILE_BASELINE:
603 case H264PROFILE_MAIN:
604 case H264PROFILE_HIGH:
605 *is_ambiguous = !IsValidH264Level(*out_level);
606 break;
607 default:
608 *is_ambiguous = true;
609 }
610 return true; 594 return true;
611 } 595 }
612 596
613 #if BUILDFLAG(ENABLE_HEVC_DEMUXING) 597 #if BUILDFLAG(ENABLE_HEVC_DEMUXING)
614 if (ParseHEVCCodecId(codec_id, out_profile, out_level)) { 598 if (ParseHEVCCodecId(codec_id, out_profile, out_level)) {
615 *codec = MimeUtil::HEVC; 599 *codec = MimeUtil::HEVC;
616 *is_ambiguous = false;
617 return true; 600 return true;
618 } 601 }
619 #endif 602 #endif
620 603
621 DVLOG(4) << __func__ << ": Unrecognized codec id " << codec_id; 604 LOG(WARNING) << __func__ << ": Unrecognized codec id " << codec_id;
jrummell 2017/02/22 19:23:19 Do we want WARNINGs for this?
chcunningham 2017/02/22 20:44:12 Changing to DVLOG(2) (4 seems a bit high)
622 return false; 605 return false;
623 } 606 }
624 607
625 bool MimeUtil::IsCodecSupported(Codec codec, 608 SupportsType MimeUtil::IsSimpleCodecSupported(
626 const std::string& mime_type_lower_case, 609 const std::string& mime_type_lower_case,
627 bool is_encrypted) const { 610 Codec codec,
611 bool is_encrypted) const {
612 // Video codecs are not "simple" because they require a profile and level to
613 // be specified. There is no "default" video codec for a given container.
614 DCHECK_EQ(MimeUtilToVideoCodec(codec), kUnknownVideoCodec);
615
616 SupportsType result =
617 IsCodecSupported(mime_type_lower_case, codec, VIDEO_CODEC_PROFILE_UNKNOWN,
618 0 /* video_level */, is_encrypted);
619
620 // Platform support should never be ambiguous for simple codecs (no range of
621 // profiles to consider).
622 DCHECK_NE(result, MayBeSupported);
623 return result;
624 }
625
626 SupportsType MimeUtil::IsCodecSupported(const std::string& mime_type_lower_case,
627 Codec codec,
628 VideoCodecProfile video_profile,
629 uint8_t video_level,
630 bool is_encrypted) const {
628 DCHECK_NE(codec, INVALID_CODEC); 631 DCHECK_NE(codec, INVALID_CODEC);
629 632
633 VideoCodec video_codec = MimeUtilToVideoCodec(codec);
634 if (video_codec != kUnknownVideoCodec &&
635 // Theora and VP8 do not have profiles/levels.
636 video_codec != kCodecTheora && video_codec != kCodecVP8) {
637 DCHECK_NE(video_profile, VIDEO_CODEC_PROFILE_UNKNOWN);
638 DCHECK_GT(video_level, 0);
639 }
640
641 // Bail early for disabled proprietary codecs
642 if (!allow_proprietary_codecs_ && IsCodecProprietary(codec)) {
643 return IsNotSupported;
644 }
645
646 // Check for cases of ambiguous platform support.
647 // TODO(chcunningham): DELETE THIS. Platform should know its capabilities.
648 // Answer should come from MediaClient.
649 bool ambiguous_platform_support = false;
650 if (codec == MimeUtil::H264) {
651 switch (video_profile) {
652 // Always supported
653 case H264PROFILE_BASELINE:
654 case H264PROFILE_MAIN:
655 case H264PROFILE_HIGH:
656 break;
657 // HIGH10PROFILE is supported through fallback to the ffmpeg decoder
658 // which is not available on Android, or if FFMPEG is not used.
659 #if !defined(MEDIA_DISABLE_FFMPEG) && !defined(OS_ANDROID)
660 case H264PROFILE_HIGH10PROFILE:
661 // FFmpeg is not generally used for encrypted videos, so we do not
662 // know whether 10-bit is supported.
663 ambiguous_platform_support = is_encrypted;
664 break;
665 #endif
666 default:
667 ambiguous_platform_support = true;
668 }
669 } else if (codec == MimeUtil::VP9 && video_profile != VP9PROFILE_PROFILE0) {
670 // We don't know if the underlying platform supports these profiles. Need
671 // to add platform level querying to get supported profiles.
672 // https://crbug.com/604566
673 ambiguous_platform_support = true;
674 }
675
676 if (GetMediaClient() && video_codec != kUnknownVideoCodec &&
677 !GetMediaClient()->IsSupportedVideoConfig(video_codec, video_profile,
678 video_level)) {
679 return IsNotSupported;
680 }
681
630 #if defined(OS_ANDROID) 682 #if defined(OS_ANDROID)
631 if (!IsCodecSupportedOnPlatform(codec, mime_type_lower_case, is_encrypted, 683 // TODO(chcunningham): Delete this. Android platform support should be
632 platform_info_)) { 684 // handled by (android specific) MediaClient.
633 return false; 685 if (!IsCodecSupportedOnAndroid(codec, mime_type_lower_case, is_encrypted,
686 platform_info_)) {
687 return IsNotSupported;
634 } 688 }
635 #endif 689 #endif
636 690
637 return allow_proprietary_codecs_ || !IsCodecProprietary(codec); 691 return ambiguous_platform_support ? MayBeSupported : IsSupported;
638 } 692 }
639 693
640 bool MimeUtil::IsCodecProprietary(Codec codec) const { 694 bool MimeUtil::IsCodecProprietary(Codec codec) const {
641 switch (codec) { 695 switch (codec) {
642 case INVALID_CODEC: 696 case INVALID_CODEC:
643 case AC3: 697 case AC3:
644 case EAC3: 698 case EAC3:
645 case MP3: 699 case MP3:
646 case MPEG2_AAC: 700 case MPEG2_AAC:
647 case MPEG4_AAC: 701 case MPEG4_AAC:
(...skipping 29 matching lines...) Expand all
677 } 731 }
678 732
679 if (mime_type_lower_case == "audio/flac") { 733 if (mime_type_lower_case == "audio/flac") {
680 *default_codec = MimeUtil::FLAC; 734 *default_codec = MimeUtil::FLAC;
681 return true; 735 return true;
682 } 736 }
683 737
684 return false; 738 return false;
685 } 739 }
686 740
687 bool MimeUtil::IsDefaultCodecSupportedLowerCase( 741 SupportsType MimeUtil::IsDefaultCodecSupportedLowerCase(
jrummell 2017/02/22 19:23:19 I see you're not changing this, but it seems weird
chcunningham 2017/02/22 20:44:12 Removed it from the method name to match the other
688 const std::string& mime_type_lower_case, 742 const std::string& mime_type_lower_case,
689 bool is_encrypted) const { 743 bool is_encrypted) const {
690 Codec default_codec = Codec::INVALID_CODEC; 744 Codec default_codec = Codec::INVALID_CODEC;
691 if (!GetDefaultCodecLowerCase(mime_type_lower_case, &default_codec)) 745 if (!GetDefaultCodecLowerCase(mime_type_lower_case, &default_codec))
692 return false; 746 return IsNotSupported;
693 return IsCodecSupported(default_codec, mime_type_lower_case, is_encrypted); 747 return IsSimpleCodecSupported(mime_type_lower_case, default_codec,
748 is_encrypted);
694 } 749 }
695 750
696 } // namespace internal 751 } // namespace internal
697 } // namespace media 752 } // namespace media
OLDNEW
« no previous file with comments | « media/base/mime_util_internal.h ('k') | media/base/mime_util_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698