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

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: Fix VP9 support on Android condition. Created 6 years, 5 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 typedef std::pair<Codec, bool> StringToCodecEntry;
Ryan Sleevi 2014/07/26 02:15:54 Unnamed tuples are hard to grok. What's the bool m
acolwell GONE FROM CHROMIUM 2014/07/28 17:31:42 Done. Changed to a struct.
120 typedef std::map<std::string, StringToCodecEntry> StringToCodecMappings;
101 121
102 MimeUtil(); 122 MimeUtil();
103 123
104 // Returns true if |codecs| is nonempty and all the items in it are present in 124 // Returns IsSupported if all codec IDs in |codecs| are unambiguous
105 // |supported_codecs|. 125 // and are supported by the platform. MayBeSupported is returned if
106 static bool AreSupportedCodecs(const MimeMappings& supported_codecs, 126 // at least one codec ID in |codecs| is ambiguous but all the codecs
107 const std::vector<std::string>& codecs); 127 // 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 128 // least one codec ID is not supported by the platform.
109 // codecs expression in |supported_codecs|. 129 SupportsType AreSupportedCodecs(
110 static bool AreSupportedCodecsWithProfile( 130 const CodecSet& supported_codecs,
111 const MimeExpressionMappings& supported_codecs, 131 const std::vector<std::string>& codecs) const;
112 const std::vector<std::string>& codecs);
113 132
114 // For faster lookup, keep hash sets. 133 // For faster lookup, keep hash sets.
115 void InitializeMimeTypeMaps(); 134 void InitializeMimeTypeMaps();
116 135
117 bool GetMimeTypeFromExtensionHelper(const base::FilePath::StringType& ext, 136 bool GetMimeTypeFromExtensionHelper(const base::FilePath::StringType& ext,
118 bool include_platform_types, 137 bool include_platform_types,
119 std::string* mime_type) const; 138 std::string* mime_type) const;
120 139
140 // Converts a codec ID into an Codec enum value and indicates
141 // whether the conversion was ambiguous.
142 // Returns true if this method was able to map |codec_id| to a specific
143 // Codec enum value. |codec| and |is_ambiguous| are only valid if true
144 // is returned. Otherwise their value is undefined after the call.
145 // |is_ambiguous| is true if |codec_id| did not have enough information to
146 // unambiguously determine the proper Codec enum value. If |is_ambiguous|
147 // is true |codec| contains the best guess for the intended Codec enum value.
148 bool StringToCodec(const std::string& codec_id,
149 Codec* codec,
150 bool* is_ambiguous) const;
151 // Returns true if |codec| is supported by the platform.
152 // Note: This method will return false if the platform supports proprietary
153 // codecs but |allow_proprietary_codecs_| is set to false.
154 bool IsCodecSupported(Codec codec) const;
155
156 // Returns true if |codec| refers to a proprietary codec.
157 bool IsCodecProprietary(Codec codec) const;
158
159 // Returns true if |mime_type| has a default codec associated with it
160 // and IsCodecSupported() returns true for that particular codec.
161 bool IsDefaultCodecSupported(const std::string& mime_type) const;
162
121 MimeMappings image_map_; 163 MimeMappings image_map_;
122 MimeMappings media_map_; 164 MimeMappings media_map_;
123 MimeMappings non_image_map_; 165 MimeMappings non_image_map_;
124 MimeMappings unsupported_text_map_; 166 MimeMappings unsupported_text_map_;
125 MimeMappings javascript_map_; 167 MimeMappings javascript_map_;
126 MimeMappings codecs_map_;
127 168
128 // A map of mime_types and hash map of the supported codecs for the mime_type. 169 // A map of mime_types and hash map of the supported codecs for the mime_type.
129 StrictMappings strict_format_map_; 170 StrictMappings strict_format_map_;
130 // A map of MP4 mime_types which expect codecs with profile parameter and 171
131 // vector of supported codecs expressions for the mime_type. 172 // Keeps track of whether proprietary codec support should be
132 StrictExpressionMappings strict_mp4_format_map_; 173 // advertised to callers.
174 bool allow_proprietary_codecs_;
175
176 // Lookup table for string compare based string -> Codec mappings.
177 StringToCodecMappings string_to_codec_map_;
133 }; // class MimeUtil 178 }; // class MimeUtil
134 179
135 // This variable is Leaky because we need to access it from WorkerPool threads. 180 // This variable is Leaky because we need to access it from WorkerPool threads.
136 static base::LazyInstance<MimeUtil>::Leaky g_mime_util = 181 static base::LazyInstance<MimeUtil>::Leaky g_mime_util =
137 LAZY_INSTANCE_INITIALIZER; 182 LAZY_INSTANCE_INITIALIZER;
138 183
139 struct MimeInfo { 184 struct MimeInfo {
140 const char* mime_type; 185 const char* mime_type;
141 const char* extensions; // comma separated list 186 const char* extensions; // comma separated list
142 }; 187 };
(...skipping 173 matching lines...) Expand 10 before | Expand all | Expand 10 after
316 "video/x-m4v", 361 "video/x-m4v",
317 "audio/mp4", 362 "audio/mp4",
318 "audio/x-m4a", 363 "audio/x-m4a",
319 364
320 // MP3. 365 // MP3.
321 "audio/mp3", 366 "audio/mp3",
322 "audio/x-mp3", 367 "audio/x-mp3",
323 "audio/mpeg", 368 "audio/mpeg",
324 }; 369 };
325 370
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: 371 // Note:
353 // - does not include javascript types list (see supported_javascript_types) 372 // - does not include javascript types list (see supported_javascript_types)
354 // - does not include types starting with "text/" (see 373 // - does not include types starting with "text/" (see
355 // IsSupportedNonImageMimeType()) 374 // IsSupportedNonImageMimeType())
356 static const char* const supported_non_image_types[] = { 375 static const char* const supported_non_image_types[] = {
357 "image/svg+xml", // SVG is text-based XML, even though it has an image/ type 376 "image/svg+xml", // SVG is text-based XML, even though it has an image/ type
358 "application/xml", 377 "application/xml",
359 "application/atom+xml", 378 "application/atom+xml",
360 "application/rss+xml", 379 "application/rss+xml",
361 "application/xhtml+xml", 380 "application/xhtml+xml",
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
423 "application/ecmascript", 442 "application/ecmascript",
424 "application/x-javascript", 443 "application/x-javascript",
425 "text/javascript1.1", 444 "text/javascript1.1",
426 "text/javascript1.2", 445 "text/javascript1.2",
427 "text/javascript1.3", 446 "text/javascript1.3",
428 "text/jscript", 447 "text/jscript",
429 "text/livescript" 448 "text/livescript"
430 }; 449 };
431 450
432 #if defined(OS_ANDROID) 451 #if defined(OS_ANDROID)
433 static bool IsCodecSupportedOnAndroid(const std::string& codec) { 452 static bool IsCodecSupportedOnAndroid(MimeUtil::Codec codec) {
434 // Theora is not supported in Android 453 switch (codec) {
435 if (!codec.compare("theora")) 454 case MimeUtil::INVALID_CODEC:
436 return false; 455 return false;
437 456
438 // VP9 is supported only in KitKat+ (API Level 19). 457 case MimeUtil::PCM:
439 if ((!codec.compare("vp9") || !codec.compare("vp9.0")) && 458 case MimeUtil::MP3:
440 base::android::BuildInfo::GetInstance()->sdk_int() < 19) { 459 case MimeUtil::MPEG4_AAC_LC:
441 return false; 460 case MimeUtil::MPEG4_AAC_SBRv1:
461 case MimeUtil::H264_BASELINE:
462 case MimeUtil::VP8:
463 case MimeUtil::VORBIS:
464 return true;
465
466 case MimeUtil::MPEG2_AAC_LC:
467 case MimeUtil::MPEG2_AAC_MAIN:
468 case MimeUtil::MPEG2_AAC_SSR:
469 // MPEG-2 variants of AAC are not supported on Android.
470 return false;
471
472 case MimeUtil::H264_MAIN:
473 case MimeUtil::H264_HIGH:
474 // H.264 Main and High profiles are not supported on Android
475 return false;
476
477 case MimeUtil::VP9:
478 // VP9 is supported only in KitKat+ (API Level 19).
479 return base::android::BuildInfo::GetInstance()->sdk_int() >= 19;
480
481 case MimeUtil::OPUS:
482 // TODO(vigneshv): Change this similar to the VP9 check once Opus is
483 // supported on Android (http://crbug.com/318436).
484 return false;
485
486 case MimeUtil::THEORA:
487 return false;
442 } 488 }
443 489
444 // TODO(vigneshv): Change this similar to the VP9 check once Opus is 490 return false;
445 // supported on Android (http://crbug.com/318436).
446 if (!codec.compare("opus")) {
447 return false;
448 }
449 return true;
450 } 491 }
451 492
452 static bool IsMimeTypeSupportedOnAndroid(const std::string& mimeType) { 493 static bool IsMimeTypeSupportedOnAndroid(const std::string& mimeType) {
453 // HLS codecs are supported in ICS and above (API level 14) 494 // HLS codecs are supported in ICS and above (API level 14)
454 if ((!mimeType.compare("application/vnd.apple.mpegurl") || 495 if ((!mimeType.compare("application/vnd.apple.mpegurl") ||
455 !mimeType.compare("application/x-mpegurl")) && 496 !mimeType.compare("application/x-mpegurl")) &&
456 base::android::BuildInfo::GetInstance()->sdk_int() < 14) { 497 base::android::BuildInfo::GetInstance()->sdk_int() < 14) {
457 return false; 498 return false;
458 } 499 }
459 return true; 500 return true;
460 } 501 }
461 #endif 502 #endif
462 503
463 struct MediaFormatStrict { 504 struct MediaFormatStrict {
464 const char* mime_type; 505 const char* mime_type;
465 const char* codecs_list; 506 const char* codecs_list;
466 }; 507 };
467 508
509 // Following is the list of RFC 6381 compliant codecs:
510 // mp4a.66 - MPEG-2 AAC MAIN
511 // mp4a.67 - MPEG-2 AAC LC
512 // mp4a.68 - MPEG-2 AAC SSR
513 // mp4a.69 - MPEG-2 extension to MPEG-1
514 // mp4a.6B - MPEG-1 audio
515 // mp4a.40.2 - MPEG-4 AAC LC
516 // mp4a.40.5 - MPEG-4 AAC SBRv1
517 //
518 // avc1.42E0xx - H.264 Baseline
519 // avc1.4D40xx - H.264 Main
520 // avc1.6400xx - H.264 High
521 static const char kProprietaryAudioCodecsExpression[] =
522 "mp4a.66,mp4a.67,mp4a.68,mp4a.69,mp4a.6B,mp4a.40.2,mp4a.40.5";
523 static const char kProprietaryCodecsExpression[] =
Ryan Sleevi 2014/07/26 02:15:55 Is this really kProprietaryVideoCodecsExpression?
acolwell GONE FROM CHROMIUM 2014/07/28 17:31:42 For all intents and purposes yes. Techincally thes
524 "avc1.42E00A,avc1.4D400A,avc1.64000A," \
525 "mp4a.66,mp4a.67,mp4a.68,mp4a.69,mp4a.6B,mp4a.40.2,mp4a.40.5";
526
468 static const MediaFormatStrict format_codec_mappings[] = { 527 static const MediaFormatStrict format_codec_mappings[] = {
469 { "video/webm", "opus,vorbis,vp8,vp8.0,vp9,vp9.0" }, 528 { "video/webm", "opus,vorbis,vp8,vp8.0,vp9,vp9.0" },
470 { "audio/webm", "opus,vorbis" }, 529 { "audio/webm", "opus,vorbis" },
471 { "audio/wav", "1" }, 530 { "audio/wav", "1" },
472 { "audio/x-wav", "1" }, 531 { "audio/x-wav", "1" },
473 { "video/ogg", "opus,theora,vorbis" }, 532 { "video/ogg", "opus,theora,vorbis" },
474 { "audio/ogg", "opus,vorbis" }, 533 { "audio/ogg", "opus,vorbis" },
475 { "application/ogg", "opus,theora,vorbis" }, 534 { "application/ogg", "opus,theora,vorbis" },
476 { "audio/mpeg", ",mp3" }, // Note: The comma before the 'mp3'results in an 535 { "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", "" }, 536 { "audio/mp3", "" },
483 { "audio/x-mp3", "" } 537 { "audio/x-mp3", "" },
484 };
485
486 // Following is the list of RFC 6381 compliant codecs:
487 // mp4a.6B - MPEG-1 audio
488 // mp4a.69 - MPEG-2 extension to MPEG-1
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 }, 538 { "audio/mp4", kProprietaryAudioCodecsExpression },
510 { "audio/x-m4a", kProprietaryAudioCodecsExpression }, 539 { "audio/x-m4a", kProprietaryAudioCodecsExpression },
511 { "video/mp4", kProprietaryCodecsExpression }, 540 { "video/mp4", kProprietaryCodecsExpression },
512 { "video/x-m4v", kProprietaryCodecsExpression }, 541 { "video/x-m4v", kProprietaryCodecsExpression },
513 { "application/x-mpegurl", kProprietaryCodecsExpression }, 542 { "application/x-mpegurl", kProprietaryCodecsExpression },
514 { "application/vnd.apple.mpegurl", kProprietaryCodecsExpression } 543 { "application/vnd.apple.mpegurl", kProprietaryCodecsExpression }
515 }; 544 };
516 545
517 MimeUtil::MimeUtil() { 546 struct CodecIDMappings {
547 const char* codec_id;
Ryan Sleevi 2014/07/26 02:15:55 const char* const? Not because it tangibly alters
acolwell GONE FROM CHROMIUM 2014/07/28 17:31:42 Done.
548 MimeUtil::Codec codec;
549 };
550
551 // List of codec IDs that provide enough information to determine the
552 // codec and profile being requested.
553 //
554 // The "mp4a" strings come from RFC 6381.
555 static const CodecIDMappings kUnambiguousCodecIDs[] = {
556 { "1", MimeUtil::PCM }, // We only allow this for WAV so it isn't ambiguous.
557 { "mp3", MimeUtil::MP3 },
558 { "mp4a.66", MimeUtil::MPEG2_AAC_MAIN },
559 { "mp4a.67", MimeUtil::MPEG2_AAC_LC },
560 { "mp4a.68", MimeUtil::MPEG2_AAC_SSR },
561 { "mp4a.69", MimeUtil::MP3 },
562 { "mp4a.6B", MimeUtil::MP3 },
563 { "mp4a.40.2", MimeUtil::MPEG4_AAC_LC },
564 { "mp4a.40.5", MimeUtil::MPEG4_AAC_SBRv1 },
565 { "vorbis", MimeUtil::VORBIS },
566 { "opus", MimeUtil::OPUS },
567 { "vp8", MimeUtil::VP8 },
568 { "vp8.0", MimeUtil::VP8 },
569 { "vp9", MimeUtil::VP9 },
570 { "vp9.0", MimeUtil::VP9 },
571 { "theora", MimeUtil::THEORA }
572 };
573
574 // List of codec IDs that are ambiguous and don't provide
575 // enough information to determine the codec and profile.
576 // The codec in these entries indicate the codec and profile
577 // we assume the user is trying to indicate.
578 static const CodecIDMappings kAmbiguousCodecIDs[] = {
579 { "mp4a.40", MimeUtil::MPEG4_AAC_LC },
580 { "avc1", MimeUtil::H264_BASELINE },
581 { "avc3", MimeUtil::H264_BASELINE },
582 };
583
584 MimeUtil::MimeUtil() : allow_proprietary_codecs_(false) {
518 InitializeMimeTypeMaps(); 585 InitializeMimeTypeMaps();
519 } 586 }
520 587
521 // static 588 SupportsType MimeUtil::AreSupportedCodecs(
522 bool MimeUtil::AreSupportedCodecs(const MimeMappings& supported_codecs, 589 const CodecSet& supported_codecs,
523 const std::vector<std::string>& codecs) { 590 const std::vector<std::string>& codecs) const {
524 if (supported_codecs.empty()) 591 DCHECK(!supported_codecs.empty());
525 return codecs.empty(); 592 DCHECK(!codecs.empty());
526 593
527 // If no codecs are specified in the mimetype, check to see if a missing 594 SupportsType result = IsSupported;
528 // codecs parameter is allowed. 595 for (size_t i = 0; i < codecs.size(); ++i) {
529 if (codecs.empty()) 596 bool is_ambiguous = true;
530 return supported_codecs.find(std::string()) != supported_codecs.end(); 597 Codec codec = INVALID_CODEC;
598 if (!StringToCodec(codecs[i], &codec, &is_ambiguous))
599 return IsNotSupported;
531 600
532 for (size_t i = 0; i < codecs.size(); ++i) { 601 if (supported_codecs.find(codec) == supported_codecs.end() ||
533 if (codecs[i].empty() || 602 !IsCodecSupported(codec))
Ryan Sleevi 2014/07/26 02:15:55 Do the IsCodecSupported() check before the find, s
acolwell GONE FROM CHROMIUM 2014/07/28 17:31:42 Done.
534 supported_codecs.find(codecs[i]) == supported_codecs.end()) { 603 return IsNotSupported;
535 return false; 604
536 } 605 if (is_ambiguous)
606 result = MayBeSupported;
537 } 607 }
538 608
539 return true; 609 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 } 610 }
576 611
577 void MimeUtil::InitializeMimeTypeMaps() { 612 void MimeUtil::InitializeMimeTypeMaps() {
578 for (size_t i = 0; i < arraysize(supported_image_types); ++i) 613 for (size_t i = 0; i < arraysize(supported_image_types); ++i)
579 image_map_.insert(supported_image_types[i]); 614 image_map_.insert(supported_image_types[i]);
580 615
581 // Initialize the supported non-image types. 616 // Initialize the supported non-image types.
582 for (size_t i = 0; i < arraysize(supported_non_image_types); ++i) 617 for (size_t i = 0; i < arraysize(supported_non_image_types); ++i)
583 non_image_map_.insert(supported_non_image_types[i]); 618 non_image_map_.insert(supported_non_image_types[i]);
584 for (size_t i = 0; i < arraysize(supported_certificate_types); ++i) 619 for (size_t i = 0; i < arraysize(supported_certificate_types); ++i)
585 non_image_map_.insert(supported_certificate_types[i].mime_type); 620 non_image_map_.insert(supported_certificate_types[i].mime_type);
586 for (size_t i = 0; i < arraysize(unsupported_text_types); ++i) 621 for (size_t i = 0; i < arraysize(unsupported_text_types); ++i)
587 unsupported_text_map_.insert(unsupported_text_types[i]); 622 unsupported_text_map_.insert(unsupported_text_types[i]);
588 for (size_t i = 0; i < arraysize(supported_javascript_types); ++i) 623 for (size_t i = 0; i < arraysize(supported_javascript_types); ++i)
589 non_image_map_.insert(supported_javascript_types[i]); 624 non_image_map_.insert(supported_javascript_types[i]);
590 for (size_t i = 0; i < arraysize(common_media_types); ++i) { 625 for (size_t i = 0; i < arraysize(common_media_types); ++i) {
591 #if defined(OS_ANDROID) 626 #if defined(OS_ANDROID)
592 if (!IsMimeTypeSupportedOnAndroid(common_media_types[i])) 627 if (!IsMimeTypeSupportedOnAndroid(common_media_types[i]))
593 continue; 628 continue;
594 #endif 629 #endif
595 non_image_map_.insert(common_media_types[i]); 630 non_image_map_.insert(common_media_types[i]);
596 } 631 }
597 #if defined(USE_PROPRIETARY_CODECS) 632 #if defined(USE_PROPRIETARY_CODECS)
633 allow_proprietary_codecs_ = true;
634
598 for (size_t i = 0; i < arraysize(proprietary_media_types); ++i) 635 for (size_t i = 0; i < arraysize(proprietary_media_types); ++i)
599 non_image_map_.insert(proprietary_media_types[i]); 636 non_image_map_.insert(proprietary_media_types[i]);
600 #endif 637 #endif
601 638
602 // Initialize the supported media types. 639 // Initialize the supported media types.
603 for (size_t i = 0; i < arraysize(common_media_types); ++i) { 640 for (size_t i = 0; i < arraysize(common_media_types); ++i) {
604 #if defined(OS_ANDROID) 641 #if defined(OS_ANDROID)
605 if (!IsMimeTypeSupportedOnAndroid(common_media_types[i])) 642 if (!IsMimeTypeSupportedOnAndroid(common_media_types[i]))
606 continue; 643 continue;
607 #endif 644 #endif
608 media_map_.insert(common_media_types[i]); 645 media_map_.insert(common_media_types[i]);
609 } 646 }
610 #if defined(USE_PROPRIETARY_CODECS) 647 #if defined(USE_PROPRIETARY_CODECS)
611 for (size_t i = 0; i < arraysize(proprietary_media_types); ++i) 648 for (size_t i = 0; i < arraysize(proprietary_media_types); ++i)
612 media_map_.insert(proprietary_media_types[i]); 649 media_map_.insert(proprietary_media_types[i]);
613 #endif 650 #endif
614 651
615 for (size_t i = 0; i < arraysize(supported_javascript_types); ++i) 652 for (size_t i = 0; i < arraysize(supported_javascript_types); ++i)
616 javascript_map_.insert(supported_javascript_types[i]); 653 javascript_map_.insert(supported_javascript_types[i]);
617 654
618 for (size_t i = 0; i < arraysize(common_media_codecs); ++i) { 655 for (size_t i = 0; i < arraysize(kUnambiguousCodecIDs); ++i) {
619 #if defined(OS_ANDROID) 656 string_to_codec_map_[kUnambiguousCodecIDs[i].codec_id] =
620 if (!IsCodecSupportedOnAndroid(common_media_codecs[i])) 657 StringToCodecEntry(kUnambiguousCodecIDs[i].codec, false);
Ryan Sleevi 2014/07/26 02:15:54 Tripped me up, because I thought this was a functi
acolwell GONE FROM CHROMIUM 2014/07/28 17:31:42 Renamed the class to CodecEntry.
621 continue;
622 #endif
623 codecs_map_.insert(common_media_codecs[i]);
624 } 658 }
625 #if defined(USE_PROPRIETARY_CODECS) 659
626 for (size_t i = 0; i < arraysize(proprietary_media_codecs); ++i) 660 for (size_t i = 0; i < arraysize(kAmbiguousCodecIDs); ++i) {
627 codecs_map_.insert(proprietary_media_codecs[i]); 661 string_to_codec_map_[kAmbiguousCodecIDs[i].codec_id] =
628 #endif 662 StringToCodecEntry(kAmbiguousCodecIDs[i].codec, true);
663 }
629 664
630 // Initialize the strict supported media types. 665 // Initialize the strict supported media types.
631 for (size_t i = 0; i < arraysize(format_codec_mappings); ++i) { 666 for (size_t i = 0; i < arraysize(format_codec_mappings); ++i) {
632 std::vector<std::string> mime_type_codecs; 667 std::vector<std::string> mime_type_codecs;
633 ParseCodecString(format_codec_mappings[i].codecs_list, 668 ParseCodecString(format_codec_mappings[i].codecs_list,
634 &mime_type_codecs, 669 &mime_type_codecs,
635 false); 670 false);
636 671
637 MimeMappings codecs; 672 CodecSet codecs;
638 for (size_t j = 0; j < mime_type_codecs.size(); ++j) { 673 for (size_t j = 0; j < mime_type_codecs.size(); ++j) {
639 #if defined(OS_ANDROID) 674 Codec codec = INVALID_CODEC;
640 if (!IsCodecSupportedOnAndroid(mime_type_codecs[j])) 675 bool is_ambiguous = true;
641 continue; 676 CHECK(StringToCodec(mime_type_codecs[j], &codec, &is_ambiguous));
642 #endif 677 CHECK(!is_ambiguous);
Ryan Sleevi 2014/07/26 02:15:55 Why CHECK? Isn't this really a DCHECK() situation?
acolwell GONE FROM CHROMIUM 2014/07/28 17:31:42 Converted to a DCHECK.
643 codecs.insert(mime_type_codecs[j]); 678 codecs.insert(codec);
644 } 679 }
680
645 strict_format_map_[format_codec_mappings[i].mime_type] = codecs; 681 strict_format_map_[format_codec_mappings[i].mime_type] = codecs;
646 } 682 }
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 } 683 }
658 684
659 bool MimeUtil::IsSupportedImageMimeType(const std::string& mime_type) const { 685 bool MimeUtil::IsSupportedImageMimeType(const std::string& mime_type) const {
660 return image_map_.find(mime_type) != image_map_.end(); 686 return image_map_.find(mime_type) != image_map_.end();
661 } 687 }
662 688
663 bool MimeUtil::IsSupportedMediaMimeType(const std::string& mime_type) const { 689 bool MimeUtil::IsSupportedMediaMimeType(const std::string& mime_type) const {
664 return media_map_.find(mime_type) != media_map_.end(); 690 return media_map_.find(mime_type) != media_map_.end();
665 } 691 }
666 692
(...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) { 829 for (size_t i = 0; i < arraysize(legal_top_level_types); ++i) {
804 if (lower_type.compare(legal_top_level_types[i]) == 0) 830 if (lower_type.compare(legal_top_level_types[i]) == 0)
805 return true; 831 return true;
806 } 832 }
807 833
808 return type_string.size() > 2 && StartsWithASCII(type_string, "x-", false); 834 return type_string.size() > 2 && StartsWithASCII(type_string, "x-", false);
809 } 835 }
810 836
811 bool MimeUtil::AreSupportedMediaCodecs( 837 bool MimeUtil::AreSupportedMediaCodecs(
812 const std::vector<std::string>& codecs) const { 838 const std::vector<std::string>& codecs) const {
813 return AreSupportedCodecs(codecs_map_, codecs); 839 for (size_t i = 0; i < codecs.size(); ++i) {
840 Codec codec = INVALID_CODEC;
841 bool is_ambiguous = true;
842 if (!StringToCodec(codecs[i], &codec, &is_ambiguous) ||
843 !IsCodecSupported(codec)) {
844 return false;
845 }
846 }
847 return true;
814 } 848 }
815 849
816 void MimeUtil::ParseCodecString(const std::string& codecs, 850 void MimeUtil::ParseCodecString(const std::string& codecs,
817 std::vector<std::string>* codecs_out, 851 std::vector<std::string>* codecs_out,
818 bool strip) { 852 bool strip) {
819 std::string no_quote_codecs; 853 std::string no_quote_codecs;
820 base::TrimString(codecs, "\"", &no_quote_codecs); 854 base::TrimString(codecs, "\"", &no_quote_codecs);
821 base::SplitString(no_quote_codecs, ',', codecs_out); 855 base::SplitString(no_quote_codecs, ',', codecs_out);
822 856
823 if (!strip) 857 if (!strip)
824 return; 858 return;
825 859
826 // Strip everything past the first '.' 860 // Strip everything past the first '.'
827 for (std::vector<std::string>::iterator it = codecs_out->begin(); 861 for (std::vector<std::string>::iterator it = codecs_out->begin();
828 it != codecs_out->end(); 862 it != codecs_out->end();
829 ++it) { 863 ++it) {
830 size_t found = it->find_first_of('.'); 864 size_t found = it->find_first_of('.');
831 if (found != std::string::npos) 865 if (found != std::string::npos)
832 it->resize(found); 866 it->resize(found);
833 } 867 }
834 } 868 }
835 869
836 bool MimeUtil::IsStrictMediaMimeType(const std::string& mime_type) const { 870 bool MimeUtil::IsStrictMediaMimeType(const std::string& mime_type) const {
837 if (strict_format_map_.find(mime_type) == strict_format_map_.end() && 871 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 } 872 }
842 873
843 SupportsType MimeUtil::IsSupportedStrictMediaMimeType( 874 SupportsType MimeUtil::IsSupportedStrictMediaMimeType(
844 const std::string& mime_type, 875 const std::string& mime_type,
845 const std::vector<std::string>& codecs) const { 876 const std::vector<std::string>& codecs) const {
846 StrictMappings::const_iterator it_strict_map = 877 StrictMappings::const_iterator it_strict_map =
847 strict_format_map_.find(mime_type); 878 strict_format_map_.find(mime_type);
848 if ((it_strict_map != strict_format_map_.end()) && 879 if (it_strict_map == strict_format_map_.end())
849 AreSupportedCodecs(it_strict_map->second, codecs)) { 880 return codecs.empty() ? MayBeSupported : IsNotSupported;
850 return IsSupported; 881
882 if (it_strict_map->second.empty()) {
883 // We get here if the mimetype does not expect a codecs parameter.
884 return (codecs.empty() && IsDefaultCodecSupported(mime_type)) ?
885 IsSupported : IsNotSupported;
851 } 886 }
852 887
853 StrictExpressionMappings::const_iterator it_expression_map = 888 if (codecs.empty()) {
854 strict_mp4_format_map_.find(mime_type); 889 // We get here if the mimetype expects to get a codecs parameter,
855 if ((it_expression_map != strict_mp4_format_map_.end()) && 890 // but didn't get one.
856 AreSupportedCodecsWithProfile(it_expression_map->second, codecs)) { 891 return IsDefaultCodecSupported(mime_type) ? IsSupported : MayBeSupported;
Ryan Sleevi 2014/07/26 02:15:55 Is this correct? I'm surprised that a mimetype tha
acolwell GONE FROM CHROMIUM 2014/07/28 17:31:42 Yes this is to deal with the MP3 situation where e
857 return MayBeSupported;
858 } 892 }
859 893
860 if (codecs.empty()) 894 return AreSupportedCodecs(it_strict_map->second, codecs);
861 return MayBeSupported;
862
863 return IsNotSupported;
864 } 895 }
865 896
866 void MimeUtil::RemoveProprietaryMediaTypesAndCodecsForTests() { 897 void MimeUtil::RemoveProprietaryMediaTypesAndCodecsForTests() {
867 for (size_t i = 0; i < arraysize(proprietary_media_types); ++i) { 898 for (size_t i = 0; i < arraysize(proprietary_media_types); ++i) {
868 non_image_map_.erase(proprietary_media_types[i]); 899 non_image_map_.erase(proprietary_media_types[i]);
869 media_map_.erase(proprietary_media_types[i]); 900 media_map_.erase(proprietary_media_types[i]);
870 } 901 }
871 for (size_t i = 0; i < arraysize(proprietary_media_codecs); ++i) 902 allow_proprietary_codecs_ = false;
872 codecs_map_.erase(proprietary_media_codecs[i]); 903 }
904
905 static bool IsValidH264Level(const std::string& level_str) {
906 uint32 level;
907 if (level_str.size() != 2 || !base::HexStringToUInt(level_str, &level))
908 return false;
909
910 // Valid levels taken from Table A-1 in ISO-14496-10.
911 // Essentially |level_str| is toHex(10 * level).
912 return ((level >= 10 && level <= 13) ||
913 (level >= 20 && level <= 22) ||
914 (level >= 30 && level <= 32) ||
915 (level >= 40 && level <= 42) ||
916 (level >= 50 && level <= 51));
917 }
918
919 // Handle parsing H.264 codec IDs as outlined in RFC 6381
920 // avc1.42E0xx - H.264 Baseline
921 // avc1.4D40xx - H.264 Main
922 // avc1.6400xx - H.264 High
923 //
924 // avc1.xxxxxx & avc3.xxxxxx are considered ambiguous forms that
925 // are trying to signal H.264 Baseline.
926 static bool ParseH264CodecID(const std::string& codec_id,
927 MimeUtil::Codec* codec,
928 bool* is_ambiguous) {
929 // Make sure we have avc1.xxxxxx or avc3.xxxxxx
930 if ((!StartsWithASCII(codec_id, "avc1.", true) &&
931 !StartsWithASCII(codec_id, "avc3.", true)) ||
932 codec_id.size() != 11) {
Ryan Sleevi 2014/07/26 02:15:54 Length check (constant) before the variable check
acolwell GONE FROM CHROMIUM 2014/07/28 17:31:42 Done.
933 return false;
934 }
935
936 // By default assume that the user is ambiguously signalling baseline.
937 *codec = MimeUtil::H264_BASELINE;
938 *is_ambiguous = true;
939
940 std::string profile = StringToUpperASCII(codec_id.substr(5, 4));
941 std::string level = StringToUpperASCII(codec_id.substr(9));
942 if (profile == "42E0") {
943 *codec = MimeUtil::H264_BASELINE;
944 } else if (profile == "4D40") {
945 *codec = MimeUtil::H264_MAIN;
946 } else if (profile == "6400") {
947 *codec = MimeUtil::H264_HIGH;
948 } else {
949 *codec = MimeUtil::H264_BASELINE;
950 *is_ambiguous = true;
Ryan Sleevi 2014/07/26 02:15:55 Seems redundant with line 937-938. 937-938 should
acolwell GONE FROM CHROMIUM 2014/07/28 17:31:42 oops. Yes. I've removed those lines.
951 return true;
952 }
953
954 *is_ambiguous = !IsValidH264Level(level);
955 return true;
956 }
957
958 bool MimeUtil::StringToCodec(const std::string& codec_id,
959 Codec* codec,
960 bool* is_ambiguous) const {
961 StringToCodecMappings::const_iterator itr =
962 string_to_codec_map_.find(codec_id);
963 if (itr != string_to_codec_map_.end()) {
964 *codec = itr->second.first;
965 *is_ambiguous = itr->second.second;
966 return true;
967 }
968
969 return ParseH264CodecID(codec_id, codec, is_ambiguous);
Ryan Sleevi 2014/07/26 02:15:55 Need a comment here explaining.
acolwell GONE FROM CHROMIUM 2014/07/28 17:31:43 Done.
970 }
971
972 bool MimeUtil::IsCodecSupported(Codec codec) const {
973 #if defined(OS_ANDROID)
974 if (!IsCodecSupportedOnAndroid(codec))
975 return false;
976 #endif
977
978 return allow_proprietary_codecs_ || !IsCodecProprietary(codec);
979 }
980
981 bool MimeUtil::IsCodecProprietary(Codec codec) const {
982 switch (codec) {
983 case INVALID_CODEC:
984 case MP3:
985 case MPEG2_AAC_LC:
986 case MPEG2_AAC_MAIN:
987 case MPEG2_AAC_SSR:
988 case MPEG4_AAC_LC:
989 case MPEG4_AAC_SBRv1:
990 case H264_BASELINE:
991 case H264_MAIN:
992 case H264_HIGH:
993 return true;
994
995 case PCM:
996 case VORBIS:
997 case OPUS:
998 case VP8:
999 case VP9:
1000 case THEORA:
1001 return false;
1002 }
1003
1004 return true;
1005 }
1006
1007 bool MimeUtil::IsDefaultCodecSupported(const std::string& mime_type) const {
1008 return (mime_type == "audio/mpeg" ||
1009 mime_type == "audio/mp3" ||
1010 mime_type == "audio/x-mp3") && IsCodecSupported(MimeUtil::MP3);
873 } 1011 }
874 1012
875 //---------------------------------------------------------------------------- 1013 //----------------------------------------------------------------------------
876 // Wrappers for the singleton 1014 // Wrappers for the singleton
877 //---------------------------------------------------------------------------- 1015 //----------------------------------------------------------------------------
878 1016
879 bool GetMimeTypeFromExtension(const base::FilePath::StringType& ext, 1017 bool GetMimeTypeFromExtension(const base::FilePath::StringType& ext,
880 std::string* mime_type) { 1018 std::string* mime_type) {
881 return g_mime_util.Get().GetMimeTypeFromExtension(ext, mime_type); 1019 return g_mime_util.Get().GetMimeTypeFromExtension(ext, mime_type);
882 } 1020 }
(...skipping 305 matching lines...) Expand 10 before | Expand all | Expand 10 after
1188 post_data->append("\r\n" + value + "\r\n"); 1326 post_data->append("\r\n" + value + "\r\n");
1189 } 1327 }
1190 1328
1191 void AddMultipartFinalDelimiterForUpload(const std::string& mime_boundary, 1329 void AddMultipartFinalDelimiterForUpload(const std::string& mime_boundary,
1192 std::string* post_data) { 1330 std::string* post_data) {
1193 DCHECK(post_data); 1331 DCHECK(post_data);
1194 post_data->append("--" + mime_boundary + "--\r\n"); 1332 post_data->append("--" + mime_boundary + "--\r\n");
1195 } 1333 }
1196 1334
1197 } // namespace net 1335 } // 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