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

Side by Side Diff: net/base/mime_util.cc

Issue 422573005: Refactor net::MimeUtil media code to return probably for codecs the platform likely supports. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Address CR comments Created 6 years, 4 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 | Annotate | Revision Log
« no previous file with comments | « content/browser/media/media_canplaytype_browsertest.cc ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 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 <algorithm> 5 #include <algorithm>
6 #include <iterator> 6 #include <iterator>
7 #include <map> 7 #include <map>
8 #include <string> 8 #include <string>
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/logging.h" 12 #include "base/logging.h"
13 #include "base/stl_util.h" 13 #include "base/stl_util.h"
14 #include "base/strings/string_number_conversions.h"
14 #include "base/strings/string_split.h" 15 #include "base/strings/string_split.h"
15 #include "base/strings/string_util.h" 16 #include "base/strings/string_util.h"
16 #include "base/strings/utf_string_conversions.h" 17 #include "base/strings/utf_string_conversions.h"
17 #include "net/base/mime_util.h" 18 #include "net/base/mime_util.h"
18 #include "net/base/platform_mime_util.h" 19 #include "net/base/platform_mime_util.h"
19 #include "net/http/http_util.h" 20 #include "net/http/http_util.h"
20 21
21 #if defined(OS_ANDROID) 22 #if defined(OS_ANDROID)
22 #include "base/android/build_info.h" 23 #include "base/android/build_info.h"
23 #endif 24 #endif
(...skipping 19 matching lines...) Expand all
43 { "video", "video/" }, 44 { "video", "video/" },
44 }; 45 };
45 46
46 } // namespace 47 } // namespace
47 48
48 namespace net { 49 namespace net {
49 50
50 // Singleton utility class for mime types. 51 // Singleton utility class for mime types.
51 class MimeUtil : public PlatformMimeUtil { 52 class MimeUtil : public PlatformMimeUtil {
52 public: 53 public:
54 enum Codec {
55 INVALID_CODEC,
56 PCM,
57 MP3,
58 MPEG2_AAC_LC,
59 MPEG2_AAC_MAIN,
60 MPEG2_AAC_SSR,
61 MPEG4_AAC_LC,
62 MPEG4_AAC_SBRv1,
63 VORBIS,
64 OPUS,
65 H264_BASELINE,
66 H264_MAIN,
67 H264_HIGH,
68 VP8,
69 VP9,
70 THEORA
71 };
72
53 bool GetMimeTypeFromExtension(const base::FilePath::StringType& ext, 73 bool GetMimeTypeFromExtension(const base::FilePath::StringType& ext,
54 std::string* mime_type) const; 74 std::string* mime_type) const;
55 75
56 bool GetMimeTypeFromFile(const base::FilePath& file_path, 76 bool GetMimeTypeFromFile(const base::FilePath& file_path,
57 std::string* mime_type) const; 77 std::string* mime_type) const;
58 78
59 bool GetWellKnownMimeTypeFromExtension(const base::FilePath::StringType& ext, 79 bool GetWellKnownMimeTypeFromExtension(const base::FilePath::StringType& ext,
60 std::string* mime_type) const; 80 std::string* mime_type) const;
61 81
62 bool IsSupportedImageMimeType(const std::string& mime_type) const; 82 bool IsSupportedImageMimeType(const std::string& mime_type) const;
(...skipping 23 matching lines...) Expand all
86 SupportsType IsSupportedStrictMediaMimeType( 106 SupportsType IsSupportedStrictMediaMimeType(
87 const std::string& mime_type, 107 const std::string& mime_type,
88 const std::vector<std::string>& codecs) const; 108 const std::vector<std::string>& codecs) const;
89 109
90 void RemoveProprietaryMediaTypesAndCodecsForTests(); 110 void RemoveProprietaryMediaTypesAndCodecsForTests();
91 111
92 private: 112 private:
93 friend struct base::DefaultLazyInstanceTraits<MimeUtil>; 113 friend struct base::DefaultLazyInstanceTraits<MimeUtil>;
94 114
95 typedef base::hash_set<std::string> MimeMappings; 115 typedef base::hash_set<std::string> MimeMappings;
96 typedef std::map<std::string, MimeMappings> StrictMappings;
97 116
98 typedef std::vector<std::string> MimeExpressionMappings; 117 typedef base::hash_set<int> CodecSet;
99 typedef std::map<std::string, MimeExpressionMappings> 118 typedef std::map<std::string, CodecSet> StrictMappings;
100 StrictExpressionMappings; 119 struct CodecEntry {
120 CodecEntry() : codec(INVALID_CODEC), is_ambiguous(true) {}
121 CodecEntry(Codec c, bool ambiguous) : codec(c), is_ambiguous(ambiguous) {}
122 Codec codec;
123 bool is_ambiguous;
124 };
125 typedef std::map<std::string, CodecEntry> StringToCodecMappings;
101 126
102 MimeUtil(); 127 MimeUtil();
103 128
104 // Returns true if |codecs| is nonempty and all the items in it are present in 129 // Returns IsSupported if all codec IDs in |codecs| are unambiguous
105 // |supported_codecs|. 130 // and are supported by the platform. MayBeSupported is returned if
106 static bool AreSupportedCodecs(const MimeMappings& supported_codecs, 131 // at least one codec ID in |codecs| is ambiguous but all the codecs
107 const std::vector<std::string>& codecs); 132 // are supported by the platform. IsNotSupported is returned if at
108 // Returns true is |codecs| is nonempty and all the items in it match with the 133 // least one codec ID is not supported by the platform.
109 // codecs expression in |supported_codecs|. 134 SupportsType AreSupportedCodecs(
110 static bool AreSupportedCodecsWithProfile( 135 const CodecSet& supported_codecs,
111 const MimeExpressionMappings& supported_codecs, 136 const std::vector<std::string>& codecs) const;
112 const std::vector<std::string>& codecs);
113 137
114 // For faster lookup, keep hash sets. 138 // For faster lookup, keep hash sets.
115 void InitializeMimeTypeMaps(); 139 void InitializeMimeTypeMaps();
116 140
117 bool GetMimeTypeFromExtensionHelper(const base::FilePath::StringType& ext, 141 bool GetMimeTypeFromExtensionHelper(const base::FilePath::StringType& ext,
118 bool include_platform_types, 142 bool include_platform_types,
119 std::string* mime_type) const; 143 std::string* mime_type) const;
120 144
145 // Converts a codec ID into an Codec enum value and indicates
146 // whether the conversion was ambiguous.
147 // Returns true if this method was able to map |codec_id| to a specific
148 // Codec enum value. |codec| and |is_ambiguous| are only valid if true
149 // is returned. Otherwise their value is undefined after the call.
150 // |is_ambiguous| is true if |codec_id| did not have enough information to
151 // unambiguously determine the proper Codec enum value. If |is_ambiguous|
152 // is true |codec| contains the best guess for the intended Codec enum value.
153 bool StringToCodec(const std::string& codec_id,
154 Codec* codec,
155 bool* is_ambiguous) const;
156 // Returns true if |codec| is supported by the platform.
scherkus (not reviewing) 2014/07/29 02:05:09 nit: looks like rest of the code here keeps a blan
acolwell GONE FROM CHROMIUM 2014/07/29 16:26:17 Done.
157 // Note: This method will return false if the platform supports proprietary
158 // codecs but |allow_proprietary_codecs_| is set to false.
159 bool IsCodecSupported(Codec codec) const;
160
161 // Returns true if |codec| refers to a proprietary codec.
162 bool IsCodecProprietary(Codec codec) const;
163
164 // Returns true and sets |*default_codec| if |mime_type| has a
165 // default codec associated with it.
166 // Returns false otherwise and the value of |*default_codec| is undefined.
167 bool GetDefaultCodec(const std::string& mime_type,
168 Codec* default_codec) const;
169
170 // Returns true if |mime_type| has a default codec associated with it
171 // and IsCodecSupported() returns true for that particular codec.
172 bool IsDefaultCodecSupported(const std::string& mime_type) const;
173
121 MimeMappings image_map_; 174 MimeMappings image_map_;
122 MimeMappings media_map_; 175 MimeMappings media_map_;
123 MimeMappings non_image_map_; 176 MimeMappings non_image_map_;
124 MimeMappings unsupported_text_map_; 177 MimeMappings unsupported_text_map_;
125 MimeMappings javascript_map_; 178 MimeMappings javascript_map_;
126 MimeMappings codecs_map_;
127 179
128 // A map of mime_types and hash map of the supported codecs for the mime_type. 180 // A map of mime_types and hash map of the supported codecs for the mime_type.
129 StrictMappings strict_format_map_; 181 StrictMappings strict_format_map_;
130 // A map of MP4 mime_types which expect codecs with profile parameter and 182
131 // vector of supported codecs expressions for the mime_type. 183 // Keeps track of whether proprietary codec support should be
132 StrictExpressionMappings strict_mp4_format_map_; 184 // advertised to callers.
185 bool allow_proprietary_codecs_;
186
187 // Lookup table for string compare based string -> Codec mappings.
188 StringToCodecMappings string_to_codec_map_;
133 }; // class MimeUtil 189 }; // class MimeUtil
134 190
135 // This variable is Leaky because we need to access it from WorkerPool threads. 191 // This variable is Leaky because we need to access it from WorkerPool threads.
136 static base::LazyInstance<MimeUtil>::Leaky g_mime_util = 192 static base::LazyInstance<MimeUtil>::Leaky g_mime_util =
137 LAZY_INSTANCE_INITIALIZER; 193 LAZY_INSTANCE_INITIALIZER;
138 194
139 struct MimeInfo { 195 struct MimeInfo {
140 const char* mime_type; 196 const char* mime_type;
141 const char* extensions; // comma separated list 197 const char* extensions; // comma separated list
142 }; 198 };
(...skipping 173 matching lines...) Expand 10 before | Expand all | Expand 10 after
316 "video/x-m4v", 372 "video/x-m4v",
317 "audio/mp4", 373 "audio/mp4",
318 "audio/x-m4a", 374 "audio/x-m4a",
319 375
320 // MP3. 376 // MP3.
321 "audio/mp3", 377 "audio/mp3",
322 "audio/x-mp3", 378 "audio/x-mp3",
323 "audio/mpeg", 379 "audio/mpeg",
324 }; 380 };
325 381
326 // List of supported codecs when passed in with <source type="...">.
327 // This set of codecs is supported by all variations of Chromium.
328 //
329 // Refer to http://wiki.whatwg.org/wiki/Video_type_parameters#Browser_Support
330 // for more information.
331 //
332 // The codecs for WAV are integers as defined in Appendix A of RFC2361:
333 // http://tools.ietf.org/html/rfc2361
334 static const char* const common_media_codecs[] = {
335 #if !defined(OS_ANDROID) // Android doesn't support Ogg Theora.
336 "theora",
337 #endif
338 "opus",
339 "vorbis",
340 "vp8",
341 "vp9",
342 "1" // WAVE_FORMAT_PCM.
343 };
344
345 // List of proprietary codecs only supported by Google Chrome.
346 static const char* const proprietary_media_codecs[] = {
347 "avc1",
348 "avc3",
349 "mp4a"
350 };
351
352 // Note: 382 // Note:
353 // - does not include javascript types list (see supported_javascript_types) 383 // - does not include javascript types list (see supported_javascript_types)
354 // - does not include types starting with "text/" (see 384 // - does not include types starting with "text/" (see
355 // IsSupportedNonImageMimeType()) 385 // IsSupportedNonImageMimeType())
356 static const char* const supported_non_image_types[] = { 386 static const char* const supported_non_image_types[] = {
357 "image/svg+xml", // SVG is text-based XML, even though it has an image/ type 387 "image/svg+xml", // SVG is text-based XML, even though it has an image/ type
358 "application/xml", 388 "application/xml",
359 "application/atom+xml", 389 "application/atom+xml",
360 "application/rss+xml", 390 "application/rss+xml",
361 "application/xhtml+xml", 391 "application/xhtml+xml",
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
423 "application/ecmascript", 453 "application/ecmascript",
424 "application/x-javascript", 454 "application/x-javascript",
425 "text/javascript1.1", 455 "text/javascript1.1",
426 "text/javascript1.2", 456 "text/javascript1.2",
427 "text/javascript1.3", 457 "text/javascript1.3",
428 "text/jscript", 458 "text/jscript",
429 "text/livescript" 459 "text/livescript"
430 }; 460 };
431 461
432 #if defined(OS_ANDROID) 462 #if defined(OS_ANDROID)
433 static bool IsCodecSupportedOnAndroid(const std::string& codec) { 463 static bool IsCodecSupportedOnAndroid(MimeUtil::Codec codec) {
434 // Theora is not supported in Android 464 switch (codec) {
435 if (!codec.compare("theora")) 465 case MimeUtil::INVALID_CODEC:
436 return false; 466 return false;
437 467
438 // VP9 is supported only in KitKat+ (API Level 19). 468 case MimeUtil::PCM:
439 if ((!codec.compare("vp9") || !codec.compare("vp9.0")) && 469 case MimeUtil::MP3:
440 base::android::BuildInfo::GetInstance()->sdk_int() < 19) { 470 case MimeUtil::MPEG4_AAC_LC:
441 return false; 471 case MimeUtil::MPEG4_AAC_SBRv1:
472 case MimeUtil::H264_BASELINE:
473 case MimeUtil::VP8:
474 case MimeUtil::VORBIS:
475 return true;
476
477 case MimeUtil::MPEG2_AAC_LC:
478 case MimeUtil::MPEG2_AAC_MAIN:
479 case MimeUtil::MPEG2_AAC_SSR:
480 // MPEG-2 variants of AAC are not supported on Android.
481 return false;
482
483 case MimeUtil::H264_MAIN:
484 case MimeUtil::H264_HIGH:
485 // H.264 Main and High profiles are not supported on Android
scherkus (not reviewing) 2014/07/29 02:05:09 period
acolwell GONE FROM CHROMIUM 2014/07/29 16:26:17 Done.
486 return false;
487
488 case MimeUtil::VP9:
489 // VP9 is supported only in KitKat+ (API Level 19).
490 return base::android::BuildInfo::GetInstance()->sdk_int() >= 19;
491
492 case MimeUtil::OPUS:
493 // TODO(vigneshv): Change this similar to the VP9 check once Opus is
494 // supported on Android (http://crbug.com/318436).
495 return false;
496
497 case MimeUtil::THEORA:
498 return false;
442 } 499 }
443 500
444 // TODO(vigneshv): Change this similar to the VP9 check once Opus is 501 return false;
445 // supported on Android (http://crbug.com/318436).
446 if (!codec.compare("opus")) {
447 return false;
448 }
449 return true;
450 } 502 }
451 503
452 static bool IsMimeTypeSupportedOnAndroid(const std::string& mimeType) { 504 static bool IsMimeTypeSupportedOnAndroid(const std::string& mimeType) {
453 // HLS codecs are supported in ICS and above (API level 14) 505 // HLS codecs are supported in ICS and above (API level 14)
454 if ((!mimeType.compare("application/vnd.apple.mpegurl") || 506 if ((!mimeType.compare("application/vnd.apple.mpegurl") ||
455 !mimeType.compare("application/x-mpegurl")) && 507 !mimeType.compare("application/x-mpegurl")) &&
456 base::android::BuildInfo::GetInstance()->sdk_int() < 14) { 508 base::android::BuildInfo::GetInstance()->sdk_int() < 14) {
457 return false; 509 return false;
458 } 510 }
459 return true; 511 return true;
460 } 512 }
461 #endif 513 #endif
462 514
463 struct MediaFormatStrict { 515 struct MediaFormatStrict {
464 const char* mime_type; 516 const char* mime_type;
465 const char* codecs_list; 517 const char* codecs_list;
466 }; 518 };
467 519
520 // Following is the list of RFC 6381 compliant codecs:
521 // mp4a.66 - MPEG-2 AAC MAIN
522 // mp4a.67 - MPEG-2 AAC LC
523 // mp4a.68 - MPEG-2 AAC SSR
524 // mp4a.69 - MPEG-2 extension to MPEG-1
525 // mp4a.6B - MPEG-1 audio
526 // mp4a.40.2 - MPEG-4 AAC LC
527 // mp4a.40.5 - MPEG-4 AAC SBRv1
528 //
529 // avc1.42E0xx - H.264 Baseline
530 // avc1.4D40xx - H.264 Main
531 // avc1.6400xx - H.264 High
532 static const char kMP4AudioCodecsExpression[] =
533 "mp4a.66,mp4a.67,mp4a.68,mp4a.69,mp4a.6B,mp4a.40.2,mp4a.40.5";
534 static const char kMP4VideoCodecsExpression[] =
535 "avc1.42E00A,avc1.4D400A,avc1.64000A," \
536 "mp4a.66,mp4a.67,mp4a.68,mp4a.69,mp4a.6B,mp4a.40.2,mp4a.40.5";
537
468 static const MediaFormatStrict format_codec_mappings[] = { 538 static const MediaFormatStrict format_codec_mappings[] = {
469 { "video/webm", "opus,vorbis,vp8,vp8.0,vp9,vp9.0" }, 539 { "video/webm", "opus,vorbis,vp8,vp8.0,vp9,vp9.0" },
470 { "audio/webm", "opus,vorbis" }, 540 { "audio/webm", "opus,vorbis" },
471 { "audio/wav", "1" }, 541 { "audio/wav", "1" },
472 { "audio/x-wav", "1" }, 542 { "audio/x-wav", "1" },
473 { "video/ogg", "opus,theora,vorbis" }, 543 { "video/ogg", "opus,theora,vorbis" },
474 { "audio/ogg", "opus,vorbis" }, 544 { "audio/ogg", "opus,vorbis" },
475 { "application/ogg", "opus,theora,vorbis" }, 545 { "application/ogg", "opus,theora,vorbis" },
476 { "audio/mpeg", ",mp3" }, // Note: The comma before the 'mp3'results in an 546 { "audio/mpeg", "mp3" },
477 // empty string codec ID and indicates
478 // a missing codecs= parameter is also valid.
479 // The presense of 'mp3' is not RFC compliant,
480 // but is common in the wild so it is a defacto
481 // standard.
482 { "audio/mp3", "" }, 547 { "audio/mp3", "" },
483 { "audio/x-mp3", "" } 548 { "audio/x-mp3", "" },
549 { "audio/mp4", kMP4AudioCodecsExpression },
550 { "audio/x-m4a", kMP4AudioCodecsExpression },
551 { "video/mp4", kMP4VideoCodecsExpression },
552 { "video/x-m4v", kMP4VideoCodecsExpression },
553 { "application/x-mpegurl", kMP4VideoCodecsExpression },
554 { "application/vnd.apple.mpegurl", kMP4VideoCodecsExpression }
484 }; 555 };
485 556
486 // Following is the list of RFC 6381 compliant codecs: 557 struct CodecIDMappings {
487 // mp4a.6B - MPEG-1 audio 558 const char* const codec_id;
488 // mp4a.69 - MPEG-2 extension to MPEG-1 559 MimeUtil::Codec codec;
489 // mp4a.67 - MPEG-2 AAC
490 // mp4a.40.2 - MPEG-4 AAC
491 // mp4a.40.5 - MPEG-4 HE-AAC
492 //
493 // avc1.42E0xx - H.264 Baseline
494 // avc1.4D40xx - H.264 Main
495 // avc1.6400xx - H.264 High
496 //
497 // Additionally, several non-RFC compliant codecs are allowed, due to their
498 // existing use on web.
499 // mp4a.40
500 // avc1.xxxxxx
501 // avc3.xxxxxx
502 // mp4a.6x
503 static const char kProprietaryAudioCodecsExpression[] =
504 "mp4a.6?,mp4a.40,mp4a.40.?";
505 static const char kProprietaryCodecsExpression[] =
506 "avc1,avc3,avc1.??????,avc3.??????,mp4a.6?,mp4a.40,mp4a.40.?";
507
508 static const MediaFormatStrict format_mp4_codec_mappings[] = {
509 { "audio/mp4", kProprietaryAudioCodecsExpression },
510 { "audio/x-m4a", kProprietaryAudioCodecsExpression },
511 { "video/mp4", kProprietaryCodecsExpression },
512 { "video/x-m4v", kProprietaryCodecsExpression },
513 { "application/x-mpegurl", kProprietaryCodecsExpression },
514 { "application/vnd.apple.mpegurl", kProprietaryCodecsExpression }
515 }; 560 };
516 561
517 MimeUtil::MimeUtil() { 562 // List of codec IDs that provide enough information to determine the
563 // codec and profile being requested.
564 //
565 // The "mp4a" strings come from RFC 6381.
566 static const CodecIDMappings kUnambiguousCodecIDs[] = {
567 { "1", MimeUtil::PCM }, // We only allow this for WAV so it isn't ambiguous.
568 { "mp3", MimeUtil::MP3 },
569 { "mp4a.66", MimeUtil::MPEG2_AAC_MAIN },
570 { "mp4a.67", MimeUtil::MPEG2_AAC_LC },
571 { "mp4a.68", MimeUtil::MPEG2_AAC_SSR },
572 { "mp4a.69", MimeUtil::MP3 },
573 { "mp4a.6B", MimeUtil::MP3 },
574 { "mp4a.40.2", MimeUtil::MPEG4_AAC_LC },
575 { "mp4a.40.5", MimeUtil::MPEG4_AAC_SBRv1 },
576 { "vorbis", MimeUtil::VORBIS },
577 { "opus", MimeUtil::OPUS },
578 { "vp8", MimeUtil::VP8 },
579 { "vp8.0", MimeUtil::VP8 },
580 { "vp9", MimeUtil::VP9 },
581 { "vp9.0", MimeUtil::VP9 },
582 { "theora", MimeUtil::THEORA }
583 };
584
585 // List of codec IDs that are ambiguous and don't provide
586 // enough information to determine the codec and profile.
587 // The codec in these entries indicate the codec and profile
588 // we assume the user is trying to indicate.
589 static const CodecIDMappings kAmbiguousCodecIDs[] = {
590 { "mp4a.40", MimeUtil::MPEG4_AAC_LC },
591 { "avc1", MimeUtil::H264_BASELINE },
592 { "avc3", MimeUtil::H264_BASELINE },
593 };
594
595 MimeUtil::MimeUtil() : allow_proprietary_codecs_(false) {
518 InitializeMimeTypeMaps(); 596 InitializeMimeTypeMaps();
519 } 597 }
520 598
521 // static 599 SupportsType MimeUtil::AreSupportedCodecs(
522 bool MimeUtil::AreSupportedCodecs(const MimeMappings& supported_codecs, 600 const CodecSet& supported_codecs,
523 const std::vector<std::string>& codecs) { 601 const std::vector<std::string>& codecs) const {
524 if (supported_codecs.empty()) 602 DCHECK(!supported_codecs.empty());
525 return codecs.empty(); 603 DCHECK(!codecs.empty());
526 604
527 // If no codecs are specified in the mimetype, check to see if a missing 605 SupportsType result = IsSupported;
528 // codecs parameter is allowed. 606 for (size_t i = 0; i < codecs.size(); ++i) {
529 if (codecs.empty()) 607 bool is_ambiguous = true;
530 return supported_codecs.find(std::string()) != supported_codecs.end(); 608 Codec codec = INVALID_CODEC;
609 if (!StringToCodec(codecs[i], &codec, &is_ambiguous))
610 return IsNotSupported;
531 611
532 for (size_t i = 0; i < codecs.size(); ++i) { 612 if (!IsCodecSupported(codec) ||
533 if (codecs[i].empty() || 613 supported_codecs.find(codec) == supported_codecs.end()) {
534 supported_codecs.find(codecs[i]) == supported_codecs.end()) { 614 return IsNotSupported;
535 return false;
536 } 615 }
616
617 if (is_ambiguous)
618 result = MayBeSupported;
537 } 619 }
538 620
539 return true; 621 return result;
540 }
541
542 // Checks all the codecs present in the |codecs| against the entries in
543 // |supported_codecs|. Returns true only if |codecs| is non-empty and all the
544 // codecs match |supported_codecs| expressions.
545 bool MimeUtil::AreSupportedCodecsWithProfile(
546 const MimeExpressionMappings& supported_codecs,
547 const std::vector<std::string>& codecs) {
548 DCHECK(!supported_codecs.empty());
549 for (size_t i = 0; i < codecs.size(); ++i) {
550 bool codec_matched = false;
551 for (size_t j = 0; j < supported_codecs.size(); ++j) {
552 if (!MatchPattern(base::StringPiece(codecs[i]),
553 base::StringPiece(supported_codecs[j]))) {
554 continue;
555 }
556 // If suffix exists, check whether it is hexadecimal.
557 for (size_t wildcard_pos = supported_codecs[j].find('?');
558 wildcard_pos != std::string::npos &&
559 wildcard_pos < supported_codecs[j].length();
560 wildcard_pos = supported_codecs[j].find('?', wildcard_pos + 1)) {
561 // Don't enforce case sensitivity, even though it's called for, as it
562 // would break some websites.
563 if (wildcard_pos >= codecs[i].length() ||
564 !IsHexDigit(codecs[i].at(wildcard_pos))) {
565 return false;
566 }
567 }
568 codec_matched = true;
569 break;
570 }
571 if (!codec_matched)
572 return false;
573 }
574 return !codecs.empty();
575 } 622 }
576 623
577 void MimeUtil::InitializeMimeTypeMaps() { 624 void MimeUtil::InitializeMimeTypeMaps() {
578 for (size_t i = 0; i < arraysize(supported_image_types); ++i) 625 for (size_t i = 0; i < arraysize(supported_image_types); ++i)
579 image_map_.insert(supported_image_types[i]); 626 image_map_.insert(supported_image_types[i]);
580 627
581 // Initialize the supported non-image types. 628 // Initialize the supported non-image types.
582 for (size_t i = 0; i < arraysize(supported_non_image_types); ++i) 629 for (size_t i = 0; i < arraysize(supported_non_image_types); ++i)
583 non_image_map_.insert(supported_non_image_types[i]); 630 non_image_map_.insert(supported_non_image_types[i]);
584 for (size_t i = 0; i < arraysize(supported_certificate_types); ++i) 631 for (size_t i = 0; i < arraysize(supported_certificate_types); ++i)
585 non_image_map_.insert(supported_certificate_types[i].mime_type); 632 non_image_map_.insert(supported_certificate_types[i].mime_type);
586 for (size_t i = 0; i < arraysize(unsupported_text_types); ++i) 633 for (size_t i = 0; i < arraysize(unsupported_text_types); ++i)
587 unsupported_text_map_.insert(unsupported_text_types[i]); 634 unsupported_text_map_.insert(unsupported_text_types[i]);
588 for (size_t i = 0; i < arraysize(supported_javascript_types); ++i) 635 for (size_t i = 0; i < arraysize(supported_javascript_types); ++i)
589 non_image_map_.insert(supported_javascript_types[i]); 636 non_image_map_.insert(supported_javascript_types[i]);
590 for (size_t i = 0; i < arraysize(common_media_types); ++i) { 637 for (size_t i = 0; i < arraysize(common_media_types); ++i) {
591 #if defined(OS_ANDROID) 638 #if defined(OS_ANDROID)
592 if (!IsMimeTypeSupportedOnAndroid(common_media_types[i])) 639 if (!IsMimeTypeSupportedOnAndroid(common_media_types[i]))
593 continue; 640 continue;
594 #endif 641 #endif
595 non_image_map_.insert(common_media_types[i]); 642 non_image_map_.insert(common_media_types[i]);
596 } 643 }
597 #if defined(USE_PROPRIETARY_CODECS) 644 #if defined(USE_PROPRIETARY_CODECS)
645 allow_proprietary_codecs_ = true;
646
598 for (size_t i = 0; i < arraysize(proprietary_media_types); ++i) 647 for (size_t i = 0; i < arraysize(proprietary_media_types); ++i)
599 non_image_map_.insert(proprietary_media_types[i]); 648 non_image_map_.insert(proprietary_media_types[i]);
600 #endif 649 #endif
601 650
602 // Initialize the supported media types. 651 // Initialize the supported media types.
603 for (size_t i = 0; i < arraysize(common_media_types); ++i) { 652 for (size_t i = 0; i < arraysize(common_media_types); ++i) {
604 #if defined(OS_ANDROID) 653 #if defined(OS_ANDROID)
605 if (!IsMimeTypeSupportedOnAndroid(common_media_types[i])) 654 if (!IsMimeTypeSupportedOnAndroid(common_media_types[i]))
606 continue; 655 continue;
607 #endif 656 #endif
608 media_map_.insert(common_media_types[i]); 657 media_map_.insert(common_media_types[i]);
609 } 658 }
610 #if defined(USE_PROPRIETARY_CODECS) 659 #if defined(USE_PROPRIETARY_CODECS)
611 for (size_t i = 0; i < arraysize(proprietary_media_types); ++i) 660 for (size_t i = 0; i < arraysize(proprietary_media_types); ++i)
612 media_map_.insert(proprietary_media_types[i]); 661 media_map_.insert(proprietary_media_types[i]);
613 #endif 662 #endif
614 663
615 for (size_t i = 0; i < arraysize(supported_javascript_types); ++i) 664 for (size_t i = 0; i < arraysize(supported_javascript_types); ++i)
616 javascript_map_.insert(supported_javascript_types[i]); 665 javascript_map_.insert(supported_javascript_types[i]);
617 666
618 for (size_t i = 0; i < arraysize(common_media_codecs); ++i) { 667 for (size_t i = 0; i < arraysize(kUnambiguousCodecIDs); ++i) {
619 #if defined(OS_ANDROID) 668 string_to_codec_map_[kUnambiguousCodecIDs[i].codec_id] =
620 if (!IsCodecSupportedOnAndroid(common_media_codecs[i])) 669 CodecEntry(kUnambiguousCodecIDs[i].codec, false);
621 continue;
622 #endif
623 codecs_map_.insert(common_media_codecs[i]);
624 } 670 }
625 #if defined(USE_PROPRIETARY_CODECS) 671
626 for (size_t i = 0; i < arraysize(proprietary_media_codecs); ++i) 672 for (size_t i = 0; i < arraysize(kAmbiguousCodecIDs); ++i) {
627 codecs_map_.insert(proprietary_media_codecs[i]); 673 string_to_codec_map_[kAmbiguousCodecIDs[i].codec_id] =
628 #endif 674 CodecEntry(kAmbiguousCodecIDs[i].codec, true);
675 }
629 676
630 // Initialize the strict supported media types. 677 // Initialize the strict supported media types.
631 for (size_t i = 0; i < arraysize(format_codec_mappings); ++i) { 678 for (size_t i = 0; i < arraysize(format_codec_mappings); ++i) {
632 std::vector<std::string> mime_type_codecs; 679 std::vector<std::string> mime_type_codecs;
633 ParseCodecString(format_codec_mappings[i].codecs_list, 680 ParseCodecString(format_codec_mappings[i].codecs_list,
634 &mime_type_codecs, 681 &mime_type_codecs,
635 false); 682 false);
636 683
637 MimeMappings codecs; 684 CodecSet codecs;
638 for (size_t j = 0; j < mime_type_codecs.size(); ++j) { 685 for (size_t j = 0; j < mime_type_codecs.size(); ++j) {
639 #if defined(OS_ANDROID) 686 Codec codec = INVALID_CODEC;
640 if (!IsCodecSupportedOnAndroid(mime_type_codecs[j])) 687 bool is_ambiguous = true;
641 continue; 688 CHECK(StringToCodec(mime_type_codecs[j], &codec, &is_ambiguous));
642 #endif 689 DCHECK(!is_ambiguous);
643 codecs.insert(mime_type_codecs[j]); 690 codecs.insert(codec);
644 } 691 }
692
645 strict_format_map_[format_codec_mappings[i].mime_type] = codecs; 693 strict_format_map_[format_codec_mappings[i].mime_type] = codecs;
646 } 694 }
647 for (size_t i = 0; i < arraysize(format_mp4_codec_mappings); ++i) {
648 std::vector<std::string> mime_type_codecs;
649 ParseCodecString(
650 format_mp4_codec_mappings[i].codecs_list, &mime_type_codecs, false);
651
652 MimeExpressionMappings codecs;
653 for (size_t j = 0; j < mime_type_codecs.size(); ++j)
654 codecs.push_back(mime_type_codecs[j]);
655 strict_mp4_format_map_[format_mp4_codec_mappings[i].mime_type] = codecs;
656 }
657 } 695 }
658 696
659 bool MimeUtil::IsSupportedImageMimeType(const std::string& mime_type) const { 697 bool MimeUtil::IsSupportedImageMimeType(const std::string& mime_type) const {
660 return image_map_.find(mime_type) != image_map_.end(); 698 return image_map_.find(mime_type) != image_map_.end();
661 } 699 }
662 700
663 bool MimeUtil::IsSupportedMediaMimeType(const std::string& mime_type) const { 701 bool MimeUtil::IsSupportedMediaMimeType(const std::string& mime_type) const {
664 return media_map_.find(mime_type) != media_map_.end(); 702 return media_map_.find(mime_type) != media_map_.end();
665 } 703 }
666 704
(...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after
803 for (size_t i = 0; i < arraysize(legal_top_level_types); ++i) { 841 for (size_t i = 0; i < arraysize(legal_top_level_types); ++i) {
804 if (lower_type.compare(legal_top_level_types[i]) == 0) 842 if (lower_type.compare(legal_top_level_types[i]) == 0)
805 return true; 843 return true;
806 } 844 }
807 845
808 return type_string.size() > 2 && StartsWithASCII(type_string, "x-", false); 846 return type_string.size() > 2 && StartsWithASCII(type_string, "x-", false);
809 } 847 }
810 848
811 bool MimeUtil::AreSupportedMediaCodecs( 849 bool MimeUtil::AreSupportedMediaCodecs(
812 const std::vector<std::string>& codecs) const { 850 const std::vector<std::string>& codecs) const {
813 return AreSupportedCodecs(codecs_map_, codecs); 851 for (size_t i = 0; i < codecs.size(); ++i) {
852 Codec codec = INVALID_CODEC;
853 bool is_ambiguous = true;
854 if (!StringToCodec(codecs[i], &codec, &is_ambiguous) ||
855 !IsCodecSupported(codec)) {
856 return false;
857 }
858 }
859 return true;
814 } 860 }
815 861
816 void MimeUtil::ParseCodecString(const std::string& codecs, 862 void MimeUtil::ParseCodecString(const std::string& codecs,
817 std::vector<std::string>* codecs_out, 863 std::vector<std::string>* codecs_out,
818 bool strip) { 864 bool strip) {
819 std::string no_quote_codecs; 865 std::string no_quote_codecs;
820 base::TrimString(codecs, "\"", &no_quote_codecs); 866 base::TrimString(codecs, "\"", &no_quote_codecs);
821 base::SplitString(no_quote_codecs, ',', codecs_out); 867 base::SplitString(no_quote_codecs, ',', codecs_out);
822 868
823 if (!strip) 869 if (!strip)
824 return; 870 return;
825 871
826 // Strip everything past the first '.' 872 // Strip everything past the first '.'
827 for (std::vector<std::string>::iterator it = codecs_out->begin(); 873 for (std::vector<std::string>::iterator it = codecs_out->begin();
828 it != codecs_out->end(); 874 it != codecs_out->end();
829 ++it) { 875 ++it) {
830 size_t found = it->find_first_of('.'); 876 size_t found = it->find_first_of('.');
831 if (found != std::string::npos) 877 if (found != std::string::npos)
832 it->resize(found); 878 it->resize(found);
833 } 879 }
834 } 880 }
835 881
836 bool MimeUtil::IsStrictMediaMimeType(const std::string& mime_type) const { 882 bool MimeUtil::IsStrictMediaMimeType(const std::string& mime_type) const {
837 if (strict_format_map_.find(mime_type) == strict_format_map_.end() && 883 return strict_format_map_.find(mime_type) != strict_format_map_.end();
838 strict_mp4_format_map_.find(mime_type) == strict_mp4_format_map_.end())
839 return false;
840 return true;
841 } 884 }
842 885
843 SupportsType MimeUtil::IsSupportedStrictMediaMimeType( 886 SupportsType MimeUtil::IsSupportedStrictMediaMimeType(
844 const std::string& mime_type, 887 const std::string& mime_type,
845 const std::vector<std::string>& codecs) const { 888 const std::vector<std::string>& codecs) const {
846 StrictMappings::const_iterator it_strict_map = 889 StrictMappings::const_iterator it_strict_map =
847 strict_format_map_.find(mime_type); 890 strict_format_map_.find(mime_type);
848 if ((it_strict_map != strict_format_map_.end()) && 891 if (it_strict_map == strict_format_map_.end())
849 AreSupportedCodecs(it_strict_map->second, codecs)) { 892 return codecs.empty() ? MayBeSupported : IsNotSupported;
850 return IsSupported; 893
894 if (it_strict_map->second.empty()) {
895 // We get here if the mimetype does not expect a codecs parameter.
896 return (codecs.empty() && IsDefaultCodecSupported(mime_type)) ?
897 IsSupported : IsNotSupported;
851 } 898 }
852 899
853 StrictExpressionMappings::const_iterator it_expression_map = 900 if (codecs.empty()) {
854 strict_mp4_format_map_.find(mime_type); 901 // We get here if the mimetype expects to get a codecs parameter,
855 if ((it_expression_map != strict_mp4_format_map_.end()) && 902 // but didn't get one. If |mime_type| does not have a default codec
856 AreSupportedCodecsWithProfile(it_expression_map->second, codecs)) { 903 // the best we can do is say "maybe" because we don't have enough
857 return MayBeSupported; 904 // information.
905 Codec default_codec = INVALID_CODEC;
906 if (!GetDefaultCodec(mime_type, &default_codec))
907 return MayBeSupported;
908
909 return IsCodecSupported(default_codec) ? IsSupported : IsNotSupported;
858 } 910 }
859 911
860 if (codecs.empty()) 912 return AreSupportedCodecs(it_strict_map->second, codecs);
861 return MayBeSupported;
862
863 return IsNotSupported;
864 } 913 }
865 914
866 void MimeUtil::RemoveProprietaryMediaTypesAndCodecsForTests() { 915 void MimeUtil::RemoveProprietaryMediaTypesAndCodecsForTests() {
867 for (size_t i = 0; i < arraysize(proprietary_media_types); ++i) { 916 for (size_t i = 0; i < arraysize(proprietary_media_types); ++i) {
868 non_image_map_.erase(proprietary_media_types[i]); 917 non_image_map_.erase(proprietary_media_types[i]);
869 media_map_.erase(proprietary_media_types[i]); 918 media_map_.erase(proprietary_media_types[i]);
870 } 919 }
871 for (size_t i = 0; i < arraysize(proprietary_media_codecs); ++i) 920 allow_proprietary_codecs_ = false;
872 codecs_map_.erase(proprietary_media_codecs[i]); 921 }
922
923 static bool IsValidH264Level(const std::string& level_str) {
924 uint32 level;
925 if (level_str.size() != 2 || !base::HexStringToUInt(level_str, &level))
926 return false;
927
928 // Valid levels taken from Table A-1 in ISO-14496-10.
929 // Essentially |level_str| is toHex(10 * level).
930 return ((level >= 10 && level <= 13) ||
931 (level >= 20 && level <= 22) ||
932 (level >= 30 && level <= 32) ||
933 (level >= 40 && level <= 42) ||
934 (level >= 50 && level <= 51));
935 }
936
937 // Handle parsing H.264 codec IDs as outlined in RFC 6381
938 // avc1.42E0xx - H.264 Baseline
939 // avc1.4D40xx - H.264 Main
940 // avc1.6400xx - H.264 High
941 //
942 // avc1.xxxxxx & avc3.xxxxxx are considered ambiguous forms that
943 // are trying to signal H.264 Baseline.
944 static bool ParseH264CodecID(const std::string& codec_id,
945 MimeUtil::Codec* codec,
946 bool* is_ambiguous) {
947 // Make sure we have avc1.xxxxxx or avc3.xxxxxx
948 if (codec_id.size() != 11 ||
949 (!StartsWithASCII(codec_id, "avc1.", true) &&
950 !StartsWithASCII(codec_id, "avc3.", true))) {
951 return false;
952 }
953
954 std::string profile = StringToUpperASCII(codec_id.substr(5, 4));
955 if (profile == "42E0") {
956 *codec = MimeUtil::H264_BASELINE;
957 } else if (profile == "4D40") {
958 *codec = MimeUtil::H264_MAIN;
959 } else if (profile == "6400") {
960 *codec = MimeUtil::H264_HIGH;
961 } else {
962 *codec = MimeUtil::H264_BASELINE;
963 *is_ambiguous = true;
964 return true;
965 }
966
967 *is_ambiguous = !IsValidH264Level(StringToUpperASCII(codec_id.substr(9)));
968 return true;
969 }
970
971 bool MimeUtil::StringToCodec(const std::string& codec_id,
972 Codec* codec,
973 bool* is_ambiguous) const {
974 StringToCodecMappings::const_iterator itr =
975 string_to_codec_map_.find(codec_id);
976 if (itr != string_to_codec_map_.end()) {
977 *codec = itr->second.codec;
978 *is_ambiguous = itr->second.is_ambiguous;
979 return true;
980 }
981
982 // If |codec_id| is not in |string_to_codec_map_|, then we assume that it is
983 // an H.264 codec ID because currently those are the only ones that can't be
984 // stored in the |string_to_codec_map_| and require parsing.
985 return ParseH264CodecID(codec_id, codec, is_ambiguous);
986 }
987
988 bool MimeUtil::IsCodecSupported(Codec codec) const {
989 DCHECK_NE(codec, INVALID_CODEC);
990
991 #if defined(OS_ANDROID)
992 if (!IsCodecSupportedOnAndroid(codec))
993 return false;
994 #endif
995
996 return allow_proprietary_codecs_ || !IsCodecProprietary(codec);
997 }
998
999 bool MimeUtil::IsCodecProprietary(Codec codec) const {
1000 switch (codec) {
1001 case INVALID_CODEC:
1002 case MP3:
1003 case MPEG2_AAC_LC:
1004 case MPEG2_AAC_MAIN:
1005 case MPEG2_AAC_SSR:
1006 case MPEG4_AAC_LC:
1007 case MPEG4_AAC_SBRv1:
1008 case H264_BASELINE:
1009 case H264_MAIN:
1010 case H264_HIGH:
1011 return true;
1012
1013 case PCM:
1014 case VORBIS:
1015 case OPUS:
1016 case VP8:
1017 case VP9:
1018 case THEORA:
1019 return false;
1020 }
1021
1022 return true;
1023 }
1024
1025 bool MimeUtil::GetDefaultCodec(const std::string& mime_type,
1026 Codec* default_codec) const {
1027 if (mime_type == "audio/mpeg" ||
1028 mime_type == "audio/mp3" ||
1029 mime_type == "audio/x-mp3") {
1030 *default_codec = MimeUtil::MP3;
1031 return true;
1032 }
1033
1034 return false;
1035 }
1036
1037
1038 bool MimeUtil::IsDefaultCodecSupported(const std::string& mime_type) const {
1039 Codec default_codec = Codec::INVALID_CODEC;
1040 if (!GetDefaultCodec(mime_type, &default_codec))
1041 return false;
scherkus (not reviewing) 2014/07/29 02:05:09 de-indent by 2
acolwell GONE FROM CHROMIUM 2014/07/29 16:26:17 Done.
1042 return IsCodecSupported(default_codec);
873 } 1043 }
874 1044
875 //---------------------------------------------------------------------------- 1045 //----------------------------------------------------------------------------
876 // Wrappers for the singleton 1046 // Wrappers for the singleton
877 //---------------------------------------------------------------------------- 1047 //----------------------------------------------------------------------------
878 1048
879 bool GetMimeTypeFromExtension(const base::FilePath::StringType& ext, 1049 bool GetMimeTypeFromExtension(const base::FilePath::StringType& ext,
880 std::string* mime_type) { 1050 std::string* mime_type) {
881 return g_mime_util.Get().GetMimeTypeFromExtension(ext, mime_type); 1051 return g_mime_util.Get().GetMimeTypeFromExtension(ext, mime_type);
882 } 1052 }
(...skipping 305 matching lines...) Expand 10 before | Expand all | Expand 10 after
1188 post_data->append("\r\n" + value + "\r\n"); 1358 post_data->append("\r\n" + value + "\r\n");
1189 } 1359 }
1190 1360
1191 void AddMultipartFinalDelimiterForUpload(const std::string& mime_boundary, 1361 void AddMultipartFinalDelimiterForUpload(const std::string& mime_boundary,
1192 std::string* post_data) { 1362 std::string* post_data) {
1193 DCHECK(post_data); 1363 DCHECK(post_data);
1194 post_data->append("--" + mime_boundary + "--\r\n"); 1364 post_data->append("--" + mime_boundary + "--\r\n");
1195 } 1365 }
1196 1366
1197 } // namespace net 1367 } // namespace net
OLDNEW
« no previous file with comments | « content/browser/media/media_canplaytype_browsertest.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698