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

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
157 // Returns true if |codec| is supported by the platform.
158 // Note: This method will return false if the platform supports proprietary
159 // codecs but |allow_proprietary_codecs_| is set to false.
160 bool IsCodecSupported(Codec codec) const;
161
162 // Returns true if |codec| refers to a proprietary codec.
163 bool IsCodecProprietary(Codec codec) const;
164
165 // Returns true and sets |*default_codec| if |mime_type| has a
166 // default codec associated with it.
167 // Returns false otherwise and the value of |*default_codec| is undefined.
168 bool GetDefaultCodec(const std::string& mime_type,
169 Codec* default_codec) const;
170
171 // Returns true if |mime_type| has a default codec associated with it
172 // and IsCodecSupported() returns true for that particular codec.
173 bool IsDefaultCodecSupported(const std::string& mime_type) const;
174
121 MimeMappings image_map_; 175 MimeMappings image_map_;
122 MimeMappings media_map_; 176 MimeMappings media_map_;
123 MimeMappings non_image_map_; 177 MimeMappings non_image_map_;
124 MimeMappings unsupported_text_map_; 178 MimeMappings unsupported_text_map_;
125 MimeMappings javascript_map_; 179 MimeMappings javascript_map_;
126 MimeMappings codecs_map_;
127 180
128 // A map of mime_types and hash map of the supported codecs for the mime_type. 181 // A map of mime_types and hash map of the supported codecs for the mime_type.
129 StrictMappings strict_format_map_; 182 StrictMappings strict_format_map_;
130 // A map of MP4 mime_types which expect codecs with profile parameter and 183
131 // vector of supported codecs expressions for the mime_type. 184 // Keeps track of whether proprietary codec support should be
132 StrictExpressionMappings strict_mp4_format_map_; 185 // advertised to callers.
186 bool allow_proprietary_codecs_;
187
188 // Lookup table for string compare based string -> Codec mappings.
189 StringToCodecMappings string_to_codec_map_;
133 }; // class MimeUtil 190 }; // class MimeUtil
134 191
135 // This variable is Leaky because we need to access it from WorkerPool threads. 192 // This variable is Leaky because we need to access it from WorkerPool threads.
136 static base::LazyInstance<MimeUtil>::Leaky g_mime_util = 193 static base::LazyInstance<MimeUtil>::Leaky g_mime_util =
137 LAZY_INSTANCE_INITIALIZER; 194 LAZY_INSTANCE_INITIALIZER;
138 195
139 struct MimeInfo { 196 struct MimeInfo {
140 const char* mime_type; 197 const char* mime_type;
141 const char* extensions; // comma separated list 198 const char* extensions; // comma separated list
142 }; 199 };
(...skipping 173 matching lines...) Expand 10 before | Expand all | Expand 10 after
316 "video/x-m4v", 373 "video/x-m4v",
317 "audio/mp4", 374 "audio/mp4",
318 "audio/x-m4a", 375 "audio/x-m4a",
319 376
320 // MP3. 377 // MP3.
321 "audio/mp3", 378 "audio/mp3",
322 "audio/x-mp3", 379 "audio/x-mp3",
323 "audio/mpeg", 380 "audio/mpeg",
324 }; 381 };
325 382
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: 383 // Note:
353 // - does not include javascript types list (see supported_javascript_types) 384 // - does not include javascript types list (see supported_javascript_types)
354 // - does not include types starting with "text/" (see 385 // - does not include types starting with "text/" (see
355 // IsSupportedNonImageMimeType()) 386 // IsSupportedNonImageMimeType())
356 static const char* const supported_non_image_types[] = { 387 static const char* const supported_non_image_types[] = {
357 "image/svg+xml", // SVG is text-based XML, even though it has an image/ type 388 "image/svg+xml", // SVG is text-based XML, even though it has an image/ type
358 "application/xml", 389 "application/xml",
359 "application/atom+xml", 390 "application/atom+xml",
360 "application/rss+xml", 391 "application/rss+xml",
361 "application/xhtml+xml", 392 "application/xhtml+xml",
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
423 "application/ecmascript", 454 "application/ecmascript",
424 "application/x-javascript", 455 "application/x-javascript",
425 "text/javascript1.1", 456 "text/javascript1.1",
426 "text/javascript1.2", 457 "text/javascript1.2",
427 "text/javascript1.3", 458 "text/javascript1.3",
428 "text/jscript", 459 "text/jscript",
429 "text/livescript" 460 "text/livescript"
430 }; 461 };
431 462
432 #if defined(OS_ANDROID) 463 #if defined(OS_ANDROID)
433 static bool IsCodecSupportedOnAndroid(const std::string& codec) { 464 static bool IsCodecSupportedOnAndroid(MimeUtil::Codec codec) {
434 // Theora is not supported in Android 465 switch (codec) {
435 if (!codec.compare("theora")) 466 case MimeUtil::INVALID_CODEC:
436 return false; 467 return false;
437 468
438 // VP9 is supported only in KitKat+ (API Level 19). 469 case MimeUtil::PCM:
439 if ((!codec.compare("vp9") || !codec.compare("vp9.0")) && 470 case MimeUtil::MP3:
440 base::android::BuildInfo::GetInstance()->sdk_int() < 19) { 471 case MimeUtil::MPEG4_AAC_LC:
441 return false; 472 case MimeUtil::MPEG4_AAC_SBRv1:
473 case MimeUtil::H264_BASELINE:
474 case MimeUtil::VP8:
475 case MimeUtil::VORBIS:
476 return true;
477
478 case MimeUtil::MPEG2_AAC_LC:
479 case MimeUtil::MPEG2_AAC_MAIN:
480 case MimeUtil::MPEG2_AAC_SSR:
481 // MPEG-2 variants of AAC are not supported on Android.
482 return false;
483
484 case MimeUtil::H264_MAIN:
485 case MimeUtil::H264_HIGH:
486 // H.264 Main and High profiles are not supported on Android.
487 return false;
488
489 case MimeUtil::VP9:
490 // VP9 is supported only in KitKat+ (API Level 19).
491 return base::android::BuildInfo::GetInstance()->sdk_int() >= 19;
492
493 case MimeUtil::OPUS:
494 // TODO(vigneshv): Change this similar to the VP9 check once Opus is
495 // supported on Android (http://crbug.com/318436).
496 return false;
497
498 case MimeUtil::THEORA:
499 return false;
442 } 500 }
443 501
444 // TODO(vigneshv): Change this similar to the VP9 check once Opus is 502 return false;
445 // supported on Android (http://crbug.com/318436).
446 if (!codec.compare("opus")) {
447 return false;
448 }
449 return true;
450 } 503 }
451 504
452 static bool IsMimeTypeSupportedOnAndroid(const std::string& mimeType) { 505 static bool IsMimeTypeSupportedOnAndroid(const std::string& mimeType) {
453 // HLS codecs are supported in ICS and above (API level 14) 506 // HLS codecs are supported in ICS and above (API level 14)
454 if ((!mimeType.compare("application/vnd.apple.mpegurl") || 507 if ((!mimeType.compare("application/vnd.apple.mpegurl") ||
455 !mimeType.compare("application/x-mpegurl")) && 508 !mimeType.compare("application/x-mpegurl")) &&
456 base::android::BuildInfo::GetInstance()->sdk_int() < 14) { 509 base::android::BuildInfo::GetInstance()->sdk_int() < 14) {
457 return false; 510 return false;
458 } 511 }
459 return true; 512 return true;
460 } 513 }
461 #endif 514 #endif
462 515
463 struct MediaFormatStrict { 516 struct MediaFormatStrict {
464 const char* mime_type; 517 const char* mime_type;
465 const char* codecs_list; 518 const char* codecs_list;
466 }; 519 };
467 520
521 // Following is the list of RFC 6381 compliant codecs:
522 // mp4a.66 - MPEG-2 AAC MAIN
523 // mp4a.67 - MPEG-2 AAC LC
524 // mp4a.68 - MPEG-2 AAC SSR
525 // mp4a.69 - MPEG-2 extension to MPEG-1
526 // mp4a.6B - MPEG-1 audio
527 // mp4a.40.2 - MPEG-4 AAC LC
528 // mp4a.40.5 - MPEG-4 AAC SBRv1
529 //
530 // avc1.42E0xx - H.264 Baseline
531 // avc1.4D40xx - H.264 Main
532 // avc1.6400xx - H.264 High
533 static const char kMP4AudioCodecsExpression[] =
534 "mp4a.66,mp4a.67,mp4a.68,mp4a.69,mp4a.6B,mp4a.40.2,mp4a.40.5";
535 static const char kMP4VideoCodecsExpression[] =
536 "avc1.42E00A,avc1.4D400A,avc1.64000A," \
537 "mp4a.66,mp4a.67,mp4a.68,mp4a.69,mp4a.6B,mp4a.40.2,mp4a.40.5";
538
468 static const MediaFormatStrict format_codec_mappings[] = { 539 static const MediaFormatStrict format_codec_mappings[] = {
469 { "video/webm", "opus,vorbis,vp8,vp8.0,vp9,vp9.0" }, 540 { "video/webm", "opus,vorbis,vp8,vp8.0,vp9,vp9.0" },
470 { "audio/webm", "opus,vorbis" }, 541 { "audio/webm", "opus,vorbis" },
471 { "audio/wav", "1" }, 542 { "audio/wav", "1" },
472 { "audio/x-wav", "1" }, 543 { "audio/x-wav", "1" },
473 { "video/ogg", "opus,theora,vorbis" }, 544 { "video/ogg", "opus,theora,vorbis" },
474 { "audio/ogg", "opus,vorbis" }, 545 { "audio/ogg", "opus,vorbis" },
475 { "application/ogg", "opus,theora,vorbis" }, 546 { "application/ogg", "opus,theora,vorbis" },
476 { "audio/mpeg", ",mp3" }, // Note: The comma before the 'mp3'results in an 547 { "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", "" }, 548 { "audio/mp3", "" },
483 { "audio/x-mp3", "" } 549 { "audio/x-mp3", "" },
550 { "audio/mp4", kMP4AudioCodecsExpression },
551 { "audio/x-m4a", kMP4AudioCodecsExpression },
552 { "video/mp4", kMP4VideoCodecsExpression },
553 { "video/x-m4v", kMP4VideoCodecsExpression },
554 { "application/x-mpegurl", kMP4VideoCodecsExpression },
555 { "application/vnd.apple.mpegurl", kMP4VideoCodecsExpression }
484 }; 556 };
485 557
486 // Following is the list of RFC 6381 compliant codecs: 558 struct CodecIDMappings {
487 // mp4a.6B - MPEG-1 audio 559 const char* const codec_id;
488 // mp4a.69 - MPEG-2 extension to MPEG-1 560 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 }; 561 };
516 562
517 MimeUtil::MimeUtil() { 563 // List of codec IDs that provide enough information to determine the
564 // codec and profile being requested.
565 //
566 // The "mp4a" strings come from RFC 6381.
567 static const CodecIDMappings kUnambiguousCodecIDs[] = {
568 { "1", MimeUtil::PCM }, // We only allow this for WAV so it isn't ambiguous.
569 { "mp3", MimeUtil::MP3 },
570 { "mp4a.66", MimeUtil::MPEG2_AAC_MAIN },
571 { "mp4a.67", MimeUtil::MPEG2_AAC_LC },
572 { "mp4a.68", MimeUtil::MPEG2_AAC_SSR },
573 { "mp4a.69", MimeUtil::MP3 },
574 { "mp4a.6B", MimeUtil::MP3 },
575 { "mp4a.40.2", MimeUtil::MPEG4_AAC_LC },
576 { "mp4a.40.5", MimeUtil::MPEG4_AAC_SBRv1 },
577 { "vorbis", MimeUtil::VORBIS },
578 { "opus", MimeUtil::OPUS },
579 { "vp8", MimeUtil::VP8 },
580 { "vp8.0", MimeUtil::VP8 },
581 { "vp9", MimeUtil::VP9 },
582 { "vp9.0", MimeUtil::VP9 },
583 { "theora", MimeUtil::THEORA }
584 };
585
586 // List of codec IDs that are ambiguous and don't provide
587 // enough information to determine the codec and profile.
588 // The codec in these entries indicate the codec and profile
589 // we assume the user is trying to indicate.
590 static const CodecIDMappings kAmbiguousCodecIDs[] = {
591 { "mp4a.40", MimeUtil::MPEG4_AAC_LC },
592 { "avc1", MimeUtil::H264_BASELINE },
593 { "avc3", MimeUtil::H264_BASELINE },
594 };
595
596 MimeUtil::MimeUtil() : allow_proprietary_codecs_(false) {
518 InitializeMimeTypeMaps(); 597 InitializeMimeTypeMaps();
519 } 598 }
520 599
521 // static 600 SupportsType MimeUtil::AreSupportedCodecs(
522 bool MimeUtil::AreSupportedCodecs(const MimeMappings& supported_codecs, 601 const CodecSet& supported_codecs,
523 const std::vector<std::string>& codecs) { 602 const std::vector<std::string>& codecs) const {
524 if (supported_codecs.empty()) 603 DCHECK(!supported_codecs.empty());
525 return codecs.empty(); 604 DCHECK(!codecs.empty());
526 605
527 // If no codecs are specified in the mimetype, check to see if a missing 606 SupportsType result = IsSupported;
528 // codecs parameter is allowed. 607 for (size_t i = 0; i < codecs.size(); ++i) {
529 if (codecs.empty()) 608 bool is_ambiguous = true;
530 return supported_codecs.find(std::string()) != supported_codecs.end(); 609 Codec codec = INVALID_CODEC;
610 if (!StringToCodec(codecs[i], &codec, &is_ambiguous))
611 return IsNotSupported;
531 612
532 for (size_t i = 0; i < codecs.size(); ++i) { 613 if (!IsCodecSupported(codec) ||
533 if (codecs[i].empty() || 614 supported_codecs.find(codec) == supported_codecs.end()) {
534 supported_codecs.find(codecs[i]) == supported_codecs.end()) { 615 return IsNotSupported;
535 return false;
536 } 616 }
617
618 if (is_ambiguous)
619 result = MayBeSupported;
537 } 620 }
538 621
539 return true; 622 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 } 623 }
576 624
577 void MimeUtil::InitializeMimeTypeMaps() { 625 void MimeUtil::InitializeMimeTypeMaps() {
578 for (size_t i = 0; i < arraysize(supported_image_types); ++i) 626 for (size_t i = 0; i < arraysize(supported_image_types); ++i)
579 image_map_.insert(supported_image_types[i]); 627 image_map_.insert(supported_image_types[i]);
580 628
581 // Initialize the supported non-image types. 629 // Initialize the supported non-image types.
582 for (size_t i = 0; i < arraysize(supported_non_image_types); ++i) 630 for (size_t i = 0; i < arraysize(supported_non_image_types); ++i)
583 non_image_map_.insert(supported_non_image_types[i]); 631 non_image_map_.insert(supported_non_image_types[i]);
584 for (size_t i = 0; i < arraysize(supported_certificate_types); ++i) 632 for (size_t i = 0; i < arraysize(supported_certificate_types); ++i)
585 non_image_map_.insert(supported_certificate_types[i].mime_type); 633 non_image_map_.insert(supported_certificate_types[i].mime_type);
586 for (size_t i = 0; i < arraysize(unsupported_text_types); ++i) 634 for (size_t i = 0; i < arraysize(unsupported_text_types); ++i)
587 unsupported_text_map_.insert(unsupported_text_types[i]); 635 unsupported_text_map_.insert(unsupported_text_types[i]);
588 for (size_t i = 0; i < arraysize(supported_javascript_types); ++i) 636 for (size_t i = 0; i < arraysize(supported_javascript_types); ++i)
589 non_image_map_.insert(supported_javascript_types[i]); 637 non_image_map_.insert(supported_javascript_types[i]);
590 for (size_t i = 0; i < arraysize(common_media_types); ++i) { 638 for (size_t i = 0; i < arraysize(common_media_types); ++i) {
591 #if defined(OS_ANDROID) 639 #if defined(OS_ANDROID)
592 if (!IsMimeTypeSupportedOnAndroid(common_media_types[i])) 640 if (!IsMimeTypeSupportedOnAndroid(common_media_types[i]))
593 continue; 641 continue;
594 #endif 642 #endif
595 non_image_map_.insert(common_media_types[i]); 643 non_image_map_.insert(common_media_types[i]);
596 } 644 }
597 #if defined(USE_PROPRIETARY_CODECS) 645 #if defined(USE_PROPRIETARY_CODECS)
646 allow_proprietary_codecs_ = true;
647
598 for (size_t i = 0; i < arraysize(proprietary_media_types); ++i) 648 for (size_t i = 0; i < arraysize(proprietary_media_types); ++i)
599 non_image_map_.insert(proprietary_media_types[i]); 649 non_image_map_.insert(proprietary_media_types[i]);
600 #endif 650 #endif
601 651
602 // Initialize the supported media types. 652 // Initialize the supported media types.
603 for (size_t i = 0; i < arraysize(common_media_types); ++i) { 653 for (size_t i = 0; i < arraysize(common_media_types); ++i) {
604 #if defined(OS_ANDROID) 654 #if defined(OS_ANDROID)
605 if (!IsMimeTypeSupportedOnAndroid(common_media_types[i])) 655 if (!IsMimeTypeSupportedOnAndroid(common_media_types[i]))
606 continue; 656 continue;
607 #endif 657 #endif
608 media_map_.insert(common_media_types[i]); 658 media_map_.insert(common_media_types[i]);
609 } 659 }
610 #if defined(USE_PROPRIETARY_CODECS) 660 #if defined(USE_PROPRIETARY_CODECS)
611 for (size_t i = 0; i < arraysize(proprietary_media_types); ++i) 661 for (size_t i = 0; i < arraysize(proprietary_media_types); ++i)
612 media_map_.insert(proprietary_media_types[i]); 662 media_map_.insert(proprietary_media_types[i]);
613 #endif 663 #endif
614 664
615 for (size_t i = 0; i < arraysize(supported_javascript_types); ++i) 665 for (size_t i = 0; i < arraysize(supported_javascript_types); ++i)
616 javascript_map_.insert(supported_javascript_types[i]); 666 javascript_map_.insert(supported_javascript_types[i]);
617 667
618 for (size_t i = 0; i < arraysize(common_media_codecs); ++i) { 668 for (size_t i = 0; i < arraysize(kUnambiguousCodecIDs); ++i) {
619 #if defined(OS_ANDROID) 669 string_to_codec_map_[kUnambiguousCodecIDs[i].codec_id] =
620 if (!IsCodecSupportedOnAndroid(common_media_codecs[i])) 670 CodecEntry(kUnambiguousCodecIDs[i].codec, false);
621 continue;
622 #endif
623 codecs_map_.insert(common_media_codecs[i]);
624 } 671 }
625 #if defined(USE_PROPRIETARY_CODECS) 672
626 for (size_t i = 0; i < arraysize(proprietary_media_codecs); ++i) 673 for (size_t i = 0; i < arraysize(kAmbiguousCodecIDs); ++i) {
627 codecs_map_.insert(proprietary_media_codecs[i]); 674 string_to_codec_map_[kAmbiguousCodecIDs[i].codec_id] =
628 #endif 675 CodecEntry(kAmbiguousCodecIDs[i].codec, true);
676 }
629 677
630 // Initialize the strict supported media types. 678 // Initialize the strict supported media types.
631 for (size_t i = 0; i < arraysize(format_codec_mappings); ++i) { 679 for (size_t i = 0; i < arraysize(format_codec_mappings); ++i) {
632 std::vector<std::string> mime_type_codecs; 680 std::vector<std::string> mime_type_codecs;
633 ParseCodecString(format_codec_mappings[i].codecs_list, 681 ParseCodecString(format_codec_mappings[i].codecs_list,
634 &mime_type_codecs, 682 &mime_type_codecs,
635 false); 683 false);
636 684
637 MimeMappings codecs; 685 CodecSet codecs;
638 for (size_t j = 0; j < mime_type_codecs.size(); ++j) { 686 for (size_t j = 0; j < mime_type_codecs.size(); ++j) {
639 #if defined(OS_ANDROID) 687 Codec codec = INVALID_CODEC;
640 if (!IsCodecSupportedOnAndroid(mime_type_codecs[j])) 688 bool is_ambiguous = true;
641 continue; 689 CHECK(StringToCodec(mime_type_codecs[j], &codec, &is_ambiguous));
642 #endif 690 DCHECK(!is_ambiguous);
643 codecs.insert(mime_type_codecs[j]); 691 codecs.insert(codec);
644 } 692 }
693
645 strict_format_map_[format_codec_mappings[i].mime_type] = codecs; 694 strict_format_map_[format_codec_mappings[i].mime_type] = codecs;
646 } 695 }
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 } 696 }
658 697
659 bool MimeUtil::IsSupportedImageMimeType(const std::string& mime_type) const { 698 bool MimeUtil::IsSupportedImageMimeType(const std::string& mime_type) const {
660 return image_map_.find(mime_type) != image_map_.end(); 699 return image_map_.find(mime_type) != image_map_.end();
661 } 700 }
662 701
663 bool MimeUtil::IsSupportedMediaMimeType(const std::string& mime_type) const { 702 bool MimeUtil::IsSupportedMediaMimeType(const std::string& mime_type) const {
664 return media_map_.find(mime_type) != media_map_.end(); 703 return media_map_.find(mime_type) != media_map_.end();
665 } 704 }
666 705
(...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) { 842 for (size_t i = 0; i < arraysize(legal_top_level_types); ++i) {
804 if (lower_type.compare(legal_top_level_types[i]) == 0) 843 if (lower_type.compare(legal_top_level_types[i]) == 0)
805 return true; 844 return true;
806 } 845 }
807 846
808 return type_string.size() > 2 && StartsWithASCII(type_string, "x-", false); 847 return type_string.size() > 2 && StartsWithASCII(type_string, "x-", false);
809 } 848 }
810 849
811 bool MimeUtil::AreSupportedMediaCodecs( 850 bool MimeUtil::AreSupportedMediaCodecs(
812 const std::vector<std::string>& codecs) const { 851 const std::vector<std::string>& codecs) const {
813 return AreSupportedCodecs(codecs_map_, codecs); 852 for (size_t i = 0; i < codecs.size(); ++i) {
853 Codec codec = INVALID_CODEC;
854 bool is_ambiguous = true;
855 if (!StringToCodec(codecs[i], &codec, &is_ambiguous) ||
856 !IsCodecSupported(codec)) {
857 return false;
858 }
859 }
860 return true;
814 } 861 }
815 862
816 void MimeUtil::ParseCodecString(const std::string& codecs, 863 void MimeUtil::ParseCodecString(const std::string& codecs,
817 std::vector<std::string>* codecs_out, 864 std::vector<std::string>* codecs_out,
818 bool strip) { 865 bool strip) {
819 std::string no_quote_codecs; 866 std::string no_quote_codecs;
820 base::TrimString(codecs, "\"", &no_quote_codecs); 867 base::TrimString(codecs, "\"", &no_quote_codecs);
821 base::SplitString(no_quote_codecs, ',', codecs_out); 868 base::SplitString(no_quote_codecs, ',', codecs_out);
822 869
823 if (!strip) 870 if (!strip)
824 return; 871 return;
825 872
826 // Strip everything past the first '.' 873 // Strip everything past the first '.'
827 for (std::vector<std::string>::iterator it = codecs_out->begin(); 874 for (std::vector<std::string>::iterator it = codecs_out->begin();
828 it != codecs_out->end(); 875 it != codecs_out->end();
829 ++it) { 876 ++it) {
830 size_t found = it->find_first_of('.'); 877 size_t found = it->find_first_of('.');
831 if (found != std::string::npos) 878 if (found != std::string::npos)
832 it->resize(found); 879 it->resize(found);
833 } 880 }
834 } 881 }
835 882
836 bool MimeUtil::IsStrictMediaMimeType(const std::string& mime_type) const { 883 bool MimeUtil::IsStrictMediaMimeType(const std::string& mime_type) const {
837 if (strict_format_map_.find(mime_type) == strict_format_map_.end() && 884 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 } 885 }
842 886
843 SupportsType MimeUtil::IsSupportedStrictMediaMimeType( 887 SupportsType MimeUtil::IsSupportedStrictMediaMimeType(
844 const std::string& mime_type, 888 const std::string& mime_type,
845 const std::vector<std::string>& codecs) const { 889 const std::vector<std::string>& codecs) const {
846 StrictMappings::const_iterator it_strict_map = 890 StrictMappings::const_iterator it_strict_map =
847 strict_format_map_.find(mime_type); 891 strict_format_map_.find(mime_type);
848 if ((it_strict_map != strict_format_map_.end()) && 892 if (it_strict_map == strict_format_map_.end())
849 AreSupportedCodecs(it_strict_map->second, codecs)) { 893 return codecs.empty() ? MayBeSupported : IsNotSupported;
850 return IsSupported; 894
895 if (it_strict_map->second.empty()) {
896 // We get here if the mimetype does not expect a codecs parameter.
897 return (codecs.empty() && IsDefaultCodecSupported(mime_type)) ?
898 IsSupported : IsNotSupported;
851 } 899 }
852 900
853 StrictExpressionMappings::const_iterator it_expression_map = 901 if (codecs.empty()) {
854 strict_mp4_format_map_.find(mime_type); 902 // We get here if the mimetype expects to get a codecs parameter,
855 if ((it_expression_map != strict_mp4_format_map_.end()) && 903 // but didn't get one. If |mime_type| does not have a default codec
856 AreSupportedCodecsWithProfile(it_expression_map->second, codecs)) { 904 // the best we can do is say "maybe" because we don't have enough
857 return MayBeSupported; 905 // information.
906 Codec default_codec = INVALID_CODEC;
907 if (!GetDefaultCodec(mime_type, &default_codec))
908 return MayBeSupported;
909
910 return IsCodecSupported(default_codec) ? IsSupported : IsNotSupported;
858 } 911 }
859 912
860 if (codecs.empty()) 913 return AreSupportedCodecs(it_strict_map->second, codecs);
861 return MayBeSupported;
862
863 return IsNotSupported;
864 } 914 }
865 915
866 void MimeUtil::RemoveProprietaryMediaTypesAndCodecsForTests() { 916 void MimeUtil::RemoveProprietaryMediaTypesAndCodecsForTests() {
867 for (size_t i = 0; i < arraysize(proprietary_media_types); ++i) { 917 for (size_t i = 0; i < arraysize(proprietary_media_types); ++i) {
868 non_image_map_.erase(proprietary_media_types[i]); 918 non_image_map_.erase(proprietary_media_types[i]);
869 media_map_.erase(proprietary_media_types[i]); 919 media_map_.erase(proprietary_media_types[i]);
870 } 920 }
871 for (size_t i = 0; i < arraysize(proprietary_media_codecs); ++i) 921 allow_proprietary_codecs_ = false;
872 codecs_map_.erase(proprietary_media_codecs[i]); 922 }
923
924 static bool IsValidH264Level(const std::string& level_str) {
925 uint32 level;
926 if (level_str.size() != 2 || !base::HexStringToUInt(level_str, &level))
927 return false;
928
929 // Valid levels taken from Table A-1 in ISO-14496-10.
930 // Essentially |level_str| is toHex(10 * level).
931 return ((level >= 10 && level <= 13) ||
932 (level >= 20 && level <= 22) ||
933 (level >= 30 && level <= 32) ||
934 (level >= 40 && level <= 42) ||
935 (level >= 50 && level <= 51));
936 }
937
938 // Handle parsing H.264 codec IDs as outlined in RFC 6381
939 // avc1.42E0xx - H.264 Baseline
940 // avc1.4D40xx - H.264 Main
941 // avc1.6400xx - H.264 High
942 //
943 // avc1.xxxxxx & avc3.xxxxxx are considered ambiguous forms that
944 // are trying to signal H.264 Baseline.
945 static bool ParseH264CodecID(const std::string& codec_id,
946 MimeUtil::Codec* codec,
947 bool* is_ambiguous) {
948 // Make sure we have avc1.xxxxxx or avc3.xxxxxx
949 if (codec_id.size() != 11 ||
950 (!StartsWithASCII(codec_id, "avc1.", true) &&
951 !StartsWithASCII(codec_id, "avc3.", true))) {
952 return false;
953 }
954
955 std::string profile = StringToUpperASCII(codec_id.substr(5, 4));
956 if (profile == "42E0") {
957 *codec = MimeUtil::H264_BASELINE;
958 } else if (profile == "4D40") {
959 *codec = MimeUtil::H264_MAIN;
960 } else if (profile == "6400") {
961 *codec = MimeUtil::H264_HIGH;
962 } else {
963 *codec = MimeUtil::H264_BASELINE;
964 *is_ambiguous = true;
965 return true;
966 }
967
968 *is_ambiguous = !IsValidH264Level(StringToUpperASCII(codec_id.substr(9)));
969 return true;
970 }
971
972 bool MimeUtil::StringToCodec(const std::string& codec_id,
973 Codec* codec,
974 bool* is_ambiguous) const {
975 StringToCodecMappings::const_iterator itr =
976 string_to_codec_map_.find(codec_id);
977 if (itr != string_to_codec_map_.end()) {
978 *codec = itr->second.codec;
979 *is_ambiguous = itr->second.is_ambiguous;
980 return true;
981 }
982
983 // If |codec_id| is not in |string_to_codec_map_|, then we assume that it is
984 // an H.264 codec ID because currently those are the only ones that can't be
985 // stored in the |string_to_codec_map_| and require parsing.
986 return ParseH264CodecID(codec_id, codec, is_ambiguous);
987 }
988
989 bool MimeUtil::IsCodecSupported(Codec codec) const {
990 DCHECK_NE(codec, INVALID_CODEC);
991
992 #if defined(OS_ANDROID)
993 if (!IsCodecSupportedOnAndroid(codec))
994 return false;
995 #endif
996
997 return allow_proprietary_codecs_ || !IsCodecProprietary(codec);
998 }
999
1000 bool MimeUtil::IsCodecProprietary(Codec codec) const {
1001 switch (codec) {
1002 case INVALID_CODEC:
1003 case MP3:
1004 case MPEG2_AAC_LC:
1005 case MPEG2_AAC_MAIN:
1006 case MPEG2_AAC_SSR:
1007 case MPEG4_AAC_LC:
1008 case MPEG4_AAC_SBRv1:
1009 case H264_BASELINE:
1010 case H264_MAIN:
1011 case H264_HIGH:
1012 return true;
1013
1014 case PCM:
1015 case VORBIS:
1016 case OPUS:
1017 case VP8:
1018 case VP9:
1019 case THEORA:
1020 return false;
1021 }
1022
1023 return true;
1024 }
1025
1026 bool MimeUtil::GetDefaultCodec(const std::string& mime_type,
1027 Codec* default_codec) const {
1028 if (mime_type == "audio/mpeg" ||
1029 mime_type == "audio/mp3" ||
1030 mime_type == "audio/x-mp3") {
1031 *default_codec = MimeUtil::MP3;
1032 return true;
1033 }
1034
1035 return false;
1036 }
1037
1038
1039 bool MimeUtil::IsDefaultCodecSupported(const std::string& mime_type) const {
1040 Codec default_codec = Codec::INVALID_CODEC;
1041 if (!GetDefaultCodec(mime_type, &default_codec))
1042 return false;
1043 return IsCodecSupported(default_codec);
873 } 1044 }
874 1045
875 //---------------------------------------------------------------------------- 1046 //----------------------------------------------------------------------------
876 // Wrappers for the singleton 1047 // Wrappers for the singleton
877 //---------------------------------------------------------------------------- 1048 //----------------------------------------------------------------------------
878 1049
879 bool GetMimeTypeFromExtension(const base::FilePath::StringType& ext, 1050 bool GetMimeTypeFromExtension(const base::FilePath::StringType& ext,
880 std::string* mime_type) { 1051 std::string* mime_type) {
881 return g_mime_util.Get().GetMimeTypeFromExtension(ext, mime_type); 1052 return g_mime_util.Get().GetMimeTypeFromExtension(ext, mime_type);
882 } 1053 }
(...skipping 305 matching lines...) Expand 10 before | Expand all | Expand 10 after
1188 post_data->append("\r\n" + value + "\r\n"); 1359 post_data->append("\r\n" + value + "\r\n");
1189 } 1360 }
1190 1361
1191 void AddMultipartFinalDelimiterForUpload(const std::string& mime_boundary, 1362 void AddMultipartFinalDelimiterForUpload(const std::string& mime_boundary,
1192 std::string* post_data) { 1363 std::string* post_data) {
1193 DCHECK(post_data); 1364 DCHECK(post_data);
1194 post_data->append("--" + mime_boundary + "--\r\n"); 1365 post_data->append("--" + mime_boundary + "--\r\n");
1195 } 1366 }
1196 1367
1197 } // namespace net 1368 } // 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