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

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

Issue 1129643002: Moved media mime type and codec checks to media/base/mime_util.* (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: More build fixes Created 5 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (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_number_conversions.h"
15 #include "base/strings/string_split.h" 15 #include "base/strings/string_split.h"
16 #include "base/strings/string_util.h" 16 #include "base/strings/string_util.h"
17 #include "base/strings/utf_string_conversions.h" 17 #include "base/strings/utf_string_conversions.h"
18 #include "net/base/mime_util.h" 18 #include "net/base/mime_util.h"
19 #include "net/base/platform_mime_util.h" 19 #include "net/base/platform_mime_util.h"
20 #include "net/http/http_util.h" 20 #include "net/http/http_util.h"
21 21
22 #if defined(OS_ANDROID)
23 #include "base/android/build_info.h"
24 #endif
25
26 using std::string; 22 using std::string;
27 23
28 namespace net { 24 namespace net {
29 25
30 // Singleton utility class for mime types. 26 // Singleton utility class for mime types.
31 class MimeUtil : public PlatformMimeUtil { 27 class MimeUtil : public PlatformMimeUtil {
32 public: 28 public:
33 enum Codec {
34 INVALID_CODEC,
35 PCM,
36 MP3,
37 MPEG2_AAC_LC,
38 MPEG2_AAC_MAIN,
39 MPEG2_AAC_SSR,
40 MPEG4_AAC_LC,
41 MPEG4_AAC_SBR_v1,
42 MPEG4_AAC_SBR_PS_v2,
43 VORBIS,
44 OPUS,
45 H264_BASELINE,
46 H264_MAIN,
47 H264_HIGH,
48 VP8,
49 VP9,
50 THEORA
51 };
52
53 bool GetMimeTypeFromExtension(const base::FilePath::StringType& ext, 29 bool GetMimeTypeFromExtension(const base::FilePath::StringType& ext,
54 std::string* mime_type) const; 30 std::string* mime_type) const;
55 31
56 bool GetMimeTypeFromFile(const base::FilePath& file_path, 32 bool GetMimeTypeFromFile(const base::FilePath& file_path,
57 std::string* mime_type) const; 33 std::string* mime_type) const;
58 34
59 bool GetWellKnownMimeTypeFromExtension(const base::FilePath::StringType& ext, 35 bool GetWellKnownMimeTypeFromExtension(const base::FilePath::StringType& ext,
60 std::string* mime_type) const; 36 std::string* mime_type) const;
61 37
62 bool IsSupportedMediaMimeType(const std::string& mime_type) const;
63
64 bool MatchesMimeType(const std::string &mime_type_pattern, 38 bool MatchesMimeType(const std::string &mime_type_pattern,
65 const std::string &mime_type) const; 39 const std::string &mime_type) const;
66 40
67 bool ParseMimeTypeWithoutParameter(const std::string& type_string, 41 bool ParseMimeTypeWithoutParameter(const std::string& type_string,
68 std::string* top_level_type, 42 std::string* top_level_type,
69 std::string* subtype) const; 43 std::string* subtype) const;
70 44
71 bool IsValidTopLevelMimeType(const std::string& type_string) const; 45 bool IsValidTopLevelMimeType(const std::string& type_string) const;
72 46
73 bool AreSupportedMediaCodecs(const std::vector<std::string>& codecs) const;
74
75 void ParseCodecString(const std::string& codecs,
76 std::vector<std::string>* codecs_out,
77 bool strip);
78
79 bool IsStrictMediaMimeType(const std::string& mime_type) const;
80 SupportsType IsSupportedStrictMediaMimeType(
81 const std::string& mime_type,
82 const std::vector<std::string>& codecs) const;
83
84 void RemoveProprietaryMediaTypesAndCodecsForTests();
85
86 private: 47 private:
87 friend struct base::DefaultLazyInstanceTraits<MimeUtil>; 48 friend struct base::DefaultLazyInstanceTraits<MimeUtil>;
88 49
89 typedef base::hash_set<std::string> MimeMappings;
90
91 typedef base::hash_set<int> CodecSet;
92 typedef std::map<std::string, CodecSet> StrictMappings;
93 struct CodecEntry {
94 CodecEntry() : codec(INVALID_CODEC), is_ambiguous(true) {}
95 CodecEntry(Codec c, bool ambiguous) : codec(c), is_ambiguous(ambiguous) {}
96 Codec codec;
97 bool is_ambiguous;
98 };
99 typedef std::map<std::string, CodecEntry> StringToCodecMappings;
100
101 MimeUtil(); 50 MimeUtil();
102 51
103 // Returns IsSupported if all codec IDs in |codecs| are unambiguous
104 // and are supported by the platform. MayBeSupported is returned if
105 // at least one codec ID in |codecs| is ambiguous but all the codecs
106 // are supported by the platform. IsNotSupported is returned if at
107 // least one codec ID is not supported by the platform.
108 SupportsType AreSupportedCodecs(
109 const CodecSet& supported_codecs,
110 const std::vector<std::string>& codecs) const;
111
112 // For faster lookup, keep hash sets.
113 void InitializeMimeTypeMaps();
114
115 bool GetMimeTypeFromExtensionHelper(const base::FilePath::StringType& ext, 52 bool GetMimeTypeFromExtensionHelper(const base::FilePath::StringType& ext,
116 bool include_platform_types, 53 bool include_platform_types,
117 std::string* mime_type) const; 54 std::string* mime_type) const;
118
119 // Converts a codec ID into an Codec enum value and indicates
120 // whether the conversion was ambiguous.
121 // Returns true if this method was able to map |codec_id| to a specific
122 // Codec enum value. |codec| and |is_ambiguous| are only valid if true
123 // is returned. Otherwise their value is undefined after the call.
124 // |is_ambiguous| is true if |codec_id| did not have enough information to
125 // unambiguously determine the proper Codec enum value. If |is_ambiguous|
126 // is true |codec| contains the best guess for the intended Codec enum value.
127 bool StringToCodec(const std::string& codec_id,
128 Codec* codec,
129 bool* is_ambiguous) const;
130
131 // Returns true if |codec| is supported by the platform.
132 // Note: This method will return false if the platform supports proprietary
133 // codecs but |allow_proprietary_codecs_| is set to false.
134 bool IsCodecSupported(Codec codec) const;
135
136 // Returns true if |codec| refers to a proprietary codec.
137 bool IsCodecProprietary(Codec codec) const;
138
139 // Returns true and sets |*default_codec| if |mime_type| has a default codec
140 // associated with it. Returns false otherwise and the value of
141 // |*default_codec| is undefined.
142 bool GetDefaultCodecLowerCase(const std::string& mime_type_lower_case,
143 Codec* default_codec) const;
144
145 // Returns true if |mime_type_lower_case| has a default codec associated with
146 // it and IsCodecSupported() returns true for that particular codec.
147 bool IsDefaultCodecSupportedLowerCase(
148 const std::string& mime_type_lower_case) const;
149
150 MimeMappings media_map_;
151
152 // A map of mime_types and hash map of the supported codecs for the mime_type.
153 StrictMappings strict_format_map_;
154
155 // Keeps track of whether proprietary codec support should be
156 // advertised to callers.
157 bool allow_proprietary_codecs_;
158
159 // Lookup table for string compare based string -> Codec mappings.
160 StringToCodecMappings string_to_codec_map_;
161 }; // class MimeUtil 55 }; // class MimeUtil
162 56
163 // This variable is Leaky because we need to access it from WorkerPool threads. 57 // This variable is Leaky because we need to access it from WorkerPool threads.
164 static base::LazyInstance<MimeUtil>::Leaky g_mime_util = 58 static base::LazyInstance<MimeUtil>::Leaky g_mime_util =
165 LAZY_INSTANCE_INITIALIZER; 59 LAZY_INSTANCE_INITIALIZER;
166 60
167 struct MimeInfo { 61 struct MimeInfo {
168 const char* const mime_type; 62 const char* const mime_type;
169 const char* const extensions; // comma separated list 63 const char* const extensions; // comma separated list
170 }; 64 };
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after
290 mime_type = FindMimeType(secondary_mappings, arraysize(secondary_mappings), 184 mime_type = FindMimeType(secondary_mappings, arraysize(secondary_mappings),
291 ext_narrow_str.c_str()); 185 ext_narrow_str.c_str());
292 if (mime_type) { 186 if (mime_type) {
293 *result = mime_type; 187 *result = mime_type;
294 return true; 188 return true;
295 } 189 }
296 190
297 return false; 191 return false;
298 } 192 }
299 193
300 // A list of media types: http://en.wikipedia.org/wiki/Internet_media_type 194 MimeUtil::MimeUtil() {
301 // A comprehensive mime type list: http://plugindoc.mozdev.org/winmime.php
302 // This set of codecs is supported by all variations of Chromium.
303 static const char* const common_media_types[] = {
304 // Ogg.
305 "audio/ogg",
306 "application/ogg",
307 #if !defined(OS_ANDROID) // Android doesn't support Ogg Theora.
308 "video/ogg",
309 #endif
310
311 // WebM.
312 "video/webm",
313 "audio/webm",
314
315 // Wav.
316 "audio/wav",
317 "audio/x-wav",
318
319 #if defined(OS_ANDROID)
320 // HLS.
321 "application/vnd.apple.mpegurl",
322 "application/x-mpegurl",
323 #endif
324 };
325
326 // List of proprietary types only supported by Google Chrome.
327 static const char* const proprietary_media_types[] = {
328 // MPEG-4.
329 "video/mp4",
330 "video/x-m4v",
331 "audio/mp4",
332 "audio/x-m4a",
333
334 // MP3.
335 "audio/mp3",
336 "audio/x-mp3",
337 "audio/mpeg",
338 "audio/aac",
339
340 #if defined(ENABLE_MPEG2TS_STREAM_PARSER)
341 // MPEG-2 TS.
342 "video/mp2t",
343 #endif
344 };
345
346 #if defined(OS_ANDROID)
347 static bool IsCodecSupportedOnAndroid(MimeUtil::Codec codec) {
348 switch (codec) {
349 case MimeUtil::INVALID_CODEC:
350 return false;
351
352 case MimeUtil::PCM:
353 case MimeUtil::MP3:
354 case MimeUtil::MPEG4_AAC_LC:
355 case MimeUtil::MPEG4_AAC_SBR_v1:
356 case MimeUtil::MPEG4_AAC_SBR_PS_v2:
357 case MimeUtil::H264_BASELINE:
358 case MimeUtil::H264_MAIN:
359 case MimeUtil::H264_HIGH:
360 case MimeUtil::VP8:
361 case MimeUtil::VORBIS:
362 return true;
363
364 case MimeUtil::MPEG2_AAC_LC:
365 case MimeUtil::MPEG2_AAC_MAIN:
366 case MimeUtil::MPEG2_AAC_SSR:
367 // MPEG-2 variants of AAC are not supported on Android.
368 return false;
369
370 case MimeUtil::VP9:
371 // VP9 is supported only in KitKat+ (API Level 19).
372 return base::android::BuildInfo::GetInstance()->sdk_int() >= 19;
373
374 case MimeUtil::OPUS:
375 // Opus is supported only in Lollipop+ (API Level 21).
376 return base::android::BuildInfo::GetInstance()->sdk_int() >= 21;
377
378 case MimeUtil::THEORA:
379 return false;
380 }
381
382 return false;
383 }
384 #endif
385
386 struct MediaFormatStrict {
387 const char* const mime_type;
388 const char* const codecs_list;
389 };
390
391 // Following is the list of RFC 6381 compliant codecs:
392 // mp4a.66 - MPEG-2 AAC MAIN
393 // mp4a.67 - MPEG-2 AAC LC
394 // mp4a.68 - MPEG-2 AAC SSR
395 // mp4a.69 - MPEG-2 extension to MPEG-1
396 // mp4a.6B - MPEG-1 audio
397 // mp4a.40.2 - MPEG-4 AAC LC
398 // mp4a.40.02 - MPEG-4 AAC LC (leading 0 in aud-oti for compatibility)
399 // mp4a.40.5 - MPEG-4 HE-AAC v1 (AAC LC + SBR)
400 // mp4a.40.05 - MPEG-4 HE-AAC v1 (AAC LC + SBR) (leading 0 in aud-oti for
401 // compatibility)
402 // mp4a.40.29 - MPEG-4 HE-AAC v2 (AAC LC + SBR + PS)
403 //
404 // avc1.42E0xx - H.264 Baseline
405 // avc1.4D40xx - H.264 Main
406 // avc1.6400xx - H.264 High
407 static const char kMP4AudioCodecsExpression[] =
408 "mp4a.66,mp4a.67,mp4a.68,mp4a.69,mp4a.6B,mp4a.40.2,mp4a.40.02,mp4a.40.5,"
409 "mp4a.40.05,mp4a.40.29";
410 static const char kMP4VideoCodecsExpression[] =
411 // This is not a complete list of supported avc1 codecs. It is simply used
412 // to register support for the corresponding Codec enum. Instead of using
413 // strings in these three arrays, we should use the Codec enum values.
414 // This will avoid confusion and unnecessary parsing at runtime.
415 // kUnambiguousCodecStringMap/kAmbiguousCodecStringMap should be the only
416 // mapping from strings to codecs. See crbug.com/461009.
417 "avc1.42E00A,avc1.4D400A,avc1.64000A,"
418 "mp4a.66,mp4a.67,mp4a.68,mp4a.69,mp4a.6B,mp4a.40.2,mp4a.40.02,mp4a.40.5,"
419 "mp4a.40.05,mp4a.40.29";
420
421 // These containers are also included in
422 // common_media_types/proprietary_media_types. See crbug.com/461012.
423 static const MediaFormatStrict format_codec_mappings[] = {
424 {"video/webm", "opus,vorbis,vp8,vp8.0,vp9,vp9.0"},
425 {"audio/webm", "opus,vorbis"},
426 {"audio/wav", "1"},
427 {"audio/x-wav", "1"},
428 // Android does not support Opus in Ogg container.
429 #if defined(OS_ANDROID)
430 {"video/ogg", "theora,vorbis"},
431 {"audio/ogg", "vorbis"},
432 {"application/ogg", "theora,vorbis"},
433 #else
434 {"video/ogg", "opus,theora,vorbis"},
435 {"audio/ogg", "opus,vorbis"},
436 {"application/ogg", "opus,theora,vorbis"},
437 #endif
438 {"audio/mpeg", "mp3"},
439 {"audio/mp3", ""},
440 {"audio/x-mp3", ""},
441 {"audio/mp4", kMP4AudioCodecsExpression},
442 {"audio/x-m4a", kMP4AudioCodecsExpression},
443 {"video/mp4", kMP4VideoCodecsExpression},
444 {"video/x-m4v", kMP4VideoCodecsExpression},
445 {"application/x-mpegurl", kMP4VideoCodecsExpression},
446 {"application/vnd.apple.mpegurl", kMP4VideoCodecsExpression}};
447
448 struct CodecIDMappings {
449 const char* const codec_id;
450 MimeUtil::Codec codec;
451 };
452
453 // List of codec IDs that provide enough information to determine the
454 // codec and profile being requested.
455 //
456 // The "mp4a" strings come from RFC 6381.
457 static const CodecIDMappings kUnambiguousCodecStringMap[] = {
458 {"1", MimeUtil::PCM}, // We only allow this for WAV so it isn't ambiguous.
459 // avc1/avc3.XXXXXX may be unambiguous; handled by ParseH264CodecID().
460 {"mp3", MimeUtil::MP3},
461 {"mp4a.66", MimeUtil::MPEG2_AAC_MAIN},
462 {"mp4a.67", MimeUtil::MPEG2_AAC_LC},
463 {"mp4a.68", MimeUtil::MPEG2_AAC_SSR},
464 {"mp4a.69", MimeUtil::MP3},
465 {"mp4a.6B", MimeUtil::MP3},
466 {"mp4a.40.2", MimeUtil::MPEG4_AAC_LC},
467 {"mp4a.40.02", MimeUtil::MPEG4_AAC_LC},
468 {"mp4a.40.5", MimeUtil::MPEG4_AAC_SBR_v1},
469 {"mp4a.40.05", MimeUtil::MPEG4_AAC_SBR_v1},
470 {"mp4a.40.29", MimeUtil::MPEG4_AAC_SBR_PS_v2},
471 {"vorbis", MimeUtil::VORBIS},
472 {"opus", MimeUtil::OPUS},
473 {"vp8", MimeUtil::VP8},
474 {"vp8.0", MimeUtil::VP8},
475 {"vp9", MimeUtil::VP9},
476 {"vp9.0", MimeUtil::VP9},
477 {"theora", MimeUtil::THEORA}};
478
479 // List of codec IDs that are ambiguous and don't provide
480 // enough information to determine the codec and profile.
481 // The codec in these entries indicate the codec and profile
482 // we assume the user is trying to indicate.
483 static const CodecIDMappings kAmbiguousCodecStringMap[] = {
484 {"mp4a.40", MimeUtil::MPEG4_AAC_LC},
485 {"avc1", MimeUtil::H264_BASELINE},
486 {"avc3", MimeUtil::H264_BASELINE},
487 // avc1/avc3.XXXXXX may be ambiguous; handled by ParseH264CodecID().
488 };
489
490 MimeUtil::MimeUtil() : allow_proprietary_codecs_(false) {
491 InitializeMimeTypeMaps();
492 }
493
494 SupportsType MimeUtil::AreSupportedCodecs(
495 const CodecSet& supported_codecs,
496 const std::vector<std::string>& codecs) const {
497 DCHECK(!supported_codecs.empty());
498 DCHECK(!codecs.empty());
499
500 SupportsType result = IsSupported;
501 for (size_t i = 0; i < codecs.size(); ++i) {
502 bool is_ambiguous = true;
503 Codec codec = INVALID_CODEC;
504 if (!StringToCodec(codecs[i], &codec, &is_ambiguous))
505 return IsNotSupported;
506
507 if (!IsCodecSupported(codec) ||
508 supported_codecs.find(codec) == supported_codecs.end()) {
509 return IsNotSupported;
510 }
511
512 if (is_ambiguous)
513 result = MayBeSupported;
514 }
515
516 return result;
517 }
518
519 void MimeUtil::InitializeMimeTypeMaps() {
520 // Initialize the supported media types.
521 for (size_t i = 0; i < arraysize(common_media_types); ++i)
522 media_map_.insert(common_media_types[i]);
523 #if defined(USE_PROPRIETARY_CODECS)
524 allow_proprietary_codecs_ = true;
525
526 for (size_t i = 0; i < arraysize(proprietary_media_types); ++i)
527 media_map_.insert(proprietary_media_types[i]);
528 #endif
529
530 for (size_t i = 0; i < arraysize(kUnambiguousCodecStringMap); ++i) {
531 string_to_codec_map_[kUnambiguousCodecStringMap[i].codec_id] =
532 CodecEntry(kUnambiguousCodecStringMap[i].codec, false);
533 }
534
535 for (size_t i = 0; i < arraysize(kAmbiguousCodecStringMap); ++i) {
536 string_to_codec_map_[kAmbiguousCodecStringMap[i].codec_id] =
537 CodecEntry(kAmbiguousCodecStringMap[i].codec, true);
538 }
539
540 // Initialize the strict supported media types.
541 for (size_t i = 0; i < arraysize(format_codec_mappings); ++i) {
542 std::vector<std::string> mime_type_codecs;
543 ParseCodecString(format_codec_mappings[i].codecs_list,
544 &mime_type_codecs,
545 false);
546
547 CodecSet codecs;
548 for (size_t j = 0; j < mime_type_codecs.size(); ++j) {
549 Codec codec = INVALID_CODEC;
550 bool is_ambiguous = true;
551 CHECK(StringToCodec(mime_type_codecs[j], &codec, &is_ambiguous));
552 DCHECK(!is_ambiguous);
553 codecs.insert(codec);
554 }
555
556 strict_format_map_[format_codec_mappings[i].mime_type] = codecs;
557 }
558 }
559
560 bool MimeUtil::IsSupportedMediaMimeType(const std::string& mime_type) const {
561 return media_map_.find(base::StringToLowerASCII(mime_type)) !=
562 media_map_.end();
563 } 195 }
564 196
565 // Tests for MIME parameter equality. Each parameter in the |mime_type_pattern| 197 // Tests for MIME parameter equality. Each parameter in the |mime_type_pattern|
566 // must be matched by a parameter in the |mime_type|. If there are no 198 // must be matched by a parameter in the |mime_type|. If there are no
567 // parameters in the pattern, the match is a success. 199 // parameters in the pattern, the match is a success.
568 // 200 //
569 // According rfc2045 keys of parameters are case-insensitive, while values may 201 // According rfc2045 keys of parameters are case-insensitive, while values may
570 // or may not be case-sensitive, but they are usually case-sensitive. So, this 202 // or may not be case-sensitive, but they are usually case-sensitive. So, this
571 // function matches values in *case-sensitive* manner, however note that this 203 // function matches values in *case-sensitive* manner, however note that this
572 // may produce some false negatives. 204 // may produce some false negatives.
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after
696 bool MimeUtil::IsValidTopLevelMimeType(const std::string& type_string) const { 328 bool MimeUtil::IsValidTopLevelMimeType(const std::string& type_string) const {
697 std::string lower_type = base::StringToLowerASCII(type_string); 329 std::string lower_type = base::StringToLowerASCII(type_string);
698 for (size_t i = 0; i < arraysize(legal_top_level_types); ++i) { 330 for (size_t i = 0; i < arraysize(legal_top_level_types); ++i) {
699 if (lower_type.compare(legal_top_level_types[i]) == 0) 331 if (lower_type.compare(legal_top_level_types[i]) == 0)
700 return true; 332 return true;
701 } 333 }
702 334
703 return type_string.size() > 2 && StartsWithASCII(type_string, "x-", false); 335 return type_string.size() > 2 && StartsWithASCII(type_string, "x-", false);
704 } 336 }
705 337
706 bool MimeUtil::AreSupportedMediaCodecs(
707 const std::vector<std::string>& codecs) const {
708 for (size_t i = 0; i < codecs.size(); ++i) {
709 Codec codec = INVALID_CODEC;
710 bool is_ambiguous = true;
711 if (!StringToCodec(codecs[i], &codec, &is_ambiguous) ||
712 !IsCodecSupported(codec)) {
713 return false;
714 }
715 }
716 return true;
717 }
718
719 void MimeUtil::ParseCodecString(const std::string& codecs,
720 std::vector<std::string>* codecs_out,
721 bool strip) {
722 std::string no_quote_codecs;
723 base::TrimString(codecs, "\"", &no_quote_codecs);
724 base::SplitString(no_quote_codecs, ',', codecs_out);
725
726 if (!strip)
727 return;
728
729 // Strip everything past the first '.'
730 for (std::vector<std::string>::iterator it = codecs_out->begin();
731 it != codecs_out->end();
732 ++it) {
733 size_t found = it->find_first_of('.');
734 if (found != std::string::npos)
735 it->resize(found);
736 }
737 }
738
739 bool MimeUtil::IsStrictMediaMimeType(const std::string& mime_type) const {
740 return strict_format_map_.find(base::StringToLowerASCII(mime_type)) !=
741 strict_format_map_.end();
742 }
743
744 SupportsType MimeUtil::IsSupportedStrictMediaMimeType(
745 const std::string& mime_type,
746 const std::vector<std::string>& codecs) const {
747 const std::string mime_type_lower_case = base::StringToLowerASCII(mime_type);
748 StrictMappings::const_iterator it_strict_map =
749 strict_format_map_.find(mime_type_lower_case);
750 if (it_strict_map == strict_format_map_.end())
751 return codecs.empty() ? MayBeSupported : IsNotSupported;
752
753 if (it_strict_map->second.empty()) {
754 // We get here if the mimetype does not expect a codecs parameter.
755 return (codecs.empty() &&
756 IsDefaultCodecSupportedLowerCase(mime_type_lower_case))
757 ? IsSupported
758 : IsNotSupported;
759 }
760
761 if (codecs.empty()) {
762 // We get here if the mimetype expects to get a codecs parameter,
763 // but didn't get one. If |mime_type_lower_case| does not have a default
764 // codec the best we can do is say "maybe" because we don't have enough
765 // information.
766 Codec default_codec = INVALID_CODEC;
767 if (!GetDefaultCodecLowerCase(mime_type_lower_case, &default_codec))
768 return MayBeSupported;
769
770 return IsCodecSupported(default_codec) ? IsSupported : IsNotSupported;
771 }
772
773 return AreSupportedCodecs(it_strict_map->second, codecs);
774 }
775
776 void MimeUtil::RemoveProprietaryMediaTypesAndCodecsForTests() {
777 for (size_t i = 0; i < arraysize(proprietary_media_types); ++i)
778 media_map_.erase(proprietary_media_types[i]);
779 allow_proprietary_codecs_ = false;
780 }
781
782 // Returns true iff |profile_str| conforms to hex string "42y0", where y is one
783 // of [8..F]. Requiring constraint_set0_flag be set and profile_idc be 0x42 is
784 // taken from ISO-14496-10 7.3.2.1, 7.4.2.1, and Annex A.2.1.
785 //
786 // |profile_str| is the first four characters of the H.264 suffix string
787 // (ignoring the last 2 characters of the full 6 character suffix that are
788 // level_idc). From ISO-14496-10 7.3.2.1, it consists of:
789 // 8 bits: profile_idc: required to be 0x42 here.
790 // 1 bit: constraint_set0_flag : required to be true here.
791 // 1 bit: constraint_set1_flag : ignored here.
792 // 1 bit: constraint_set2_flag : ignored here.
793 // 1 bit: constraint_set3_flag : ignored here.
794 // 4 bits: reserved : required to be 0 here.
795 //
796 // The spec indicates other ways, not implemented here, that a |profile_str|
797 // can indicate a baseline conforming decoder is sufficient for decode in Annex
798 // A.2.1: "[profile_idc not necessarily 0x42] with constraint_set0_flag set and
799 // in which level_idc and constraint_set3_flag represent a level less than or
800 // equal to the specified level."
801 static bool IsValidH264BaselineProfile(const std::string& profile_str) {
802 uint32 constraint_set_bits;
803 if (profile_str.size() != 4 ||
804 profile_str[0] != '4' ||
805 profile_str[1] != '2' ||
806 profile_str[3] != '0' ||
807 !base::HexStringToUInt(base::StringPiece(profile_str.c_str() + 2, 1),
808 &constraint_set_bits)) {
809 return false;
810 }
811
812 return constraint_set_bits >= 8;
813 }
814
815 static bool IsValidH264Level(const std::string& level_str) {
816 uint32 level;
817 if (level_str.size() != 2 || !base::HexStringToUInt(level_str, &level))
818 return false;
819
820 // Valid levels taken from Table A-1 in ISO-14496-10.
821 // Essentially |level_str| is toHex(10 * level).
822 return ((level >= 10 && level <= 13) ||
823 (level >= 20 && level <= 22) ||
824 (level >= 30 && level <= 32) ||
825 (level >= 40 && level <= 42) ||
826 (level >= 50 && level <= 51));
827 }
828
829 // Handle parsing H.264 codec IDs as outlined in RFC 6381 and ISO-14496-10.
830 // avc1.42y0xx, y >= 8 - H.264 Baseline
831 // avc1.4D40xx - H.264 Main
832 // avc1.6400xx - H.264 High
833 //
834 // avc1.xxxxxx & avc3.xxxxxx are considered ambiguous forms that are trying to
835 // signal H.264 Baseline. For example, the idc_level, profile_idc and
836 // constraint_set3_flag pieces may explicitly require decoder to conform to
837 // baseline profile at the specified level (see Annex A and constraint_set0 in
838 // ISO-14496-10).
839 static bool ParseH264CodecID(const std::string& codec_id,
840 MimeUtil::Codec* codec,
841 bool* is_ambiguous) {
842 // Make sure we have avc1.xxxxxx or avc3.xxxxxx
843 if (codec_id.size() != 11 ||
844 (!StartsWithASCII(codec_id, "avc1.", true) &&
845 !StartsWithASCII(codec_id, "avc3.", true))) {
846 return false;
847 }
848
849 std::string profile = StringToUpperASCII(codec_id.substr(5, 4));
850 if (IsValidH264BaselineProfile(profile)) {
851 *codec = MimeUtil::H264_BASELINE;
852 } else if (profile == "4D40") {
853 *codec = MimeUtil::H264_MAIN;
854 } else if (profile == "6400") {
855 *codec = MimeUtil::H264_HIGH;
856 } else {
857 *codec = MimeUtil::H264_BASELINE;
858 *is_ambiguous = true;
859 return true;
860 }
861
862 *is_ambiguous = !IsValidH264Level(StringToUpperASCII(codec_id.substr(9)));
863 return true;
864 }
865
866 bool MimeUtil::StringToCodec(const std::string& codec_id,
867 Codec* codec,
868 bool* is_ambiguous) const {
869 StringToCodecMappings::const_iterator itr =
870 string_to_codec_map_.find(codec_id);
871 if (itr != string_to_codec_map_.end()) {
872 *codec = itr->second.codec;
873 *is_ambiguous = itr->second.is_ambiguous;
874 return true;
875 }
876
877 // If |codec_id| is not in |string_to_codec_map_|, then we assume that it is
878 // an H.264 codec ID because currently those are the only ones that can't be
879 // stored in the |string_to_codec_map_| and require parsing.
880 return ParseH264CodecID(codec_id, codec, is_ambiguous);
881 }
882
883 bool MimeUtil::IsCodecSupported(Codec codec) const {
884 DCHECK_NE(codec, INVALID_CODEC);
885
886 #if defined(OS_ANDROID)
887 if (!IsCodecSupportedOnAndroid(codec))
888 return false;
889 #endif
890
891 return allow_proprietary_codecs_ || !IsCodecProprietary(codec);
892 }
893
894 bool MimeUtil::IsCodecProprietary(Codec codec) const {
895 switch (codec) {
896 case INVALID_CODEC:
897 case MP3:
898 case MPEG2_AAC_LC:
899 case MPEG2_AAC_MAIN:
900 case MPEG2_AAC_SSR:
901 case MPEG4_AAC_LC:
902 case MPEG4_AAC_SBR_v1:
903 case MPEG4_AAC_SBR_PS_v2:
904 case H264_BASELINE:
905 case H264_MAIN:
906 case H264_HIGH:
907 return true;
908
909 case PCM:
910 case VORBIS:
911 case OPUS:
912 case VP8:
913 case VP9:
914 case THEORA:
915 return false;
916 }
917
918 return true;
919 }
920
921 bool MimeUtil::GetDefaultCodecLowerCase(const std::string& mime_type_lower_case,
922 Codec* default_codec) const {
923 if (mime_type_lower_case == "audio/mpeg" ||
924 mime_type_lower_case == "audio/mp3" ||
925 mime_type_lower_case == "audio/x-mp3") {
926 *default_codec = MimeUtil::MP3;
927 return true;
928 }
929
930 return false;
931 }
932
933 bool MimeUtil::IsDefaultCodecSupportedLowerCase(
934 const std::string& mime_type_lower_case) const {
935 Codec default_codec = Codec::INVALID_CODEC;
936 if (!GetDefaultCodecLowerCase(mime_type_lower_case, &default_codec))
937 return false;
938 return IsCodecSupported(default_codec);
939 }
940
941 //---------------------------------------------------------------------------- 338 //----------------------------------------------------------------------------
942 // Wrappers for the singleton 339 // Wrappers for the singleton
943 //---------------------------------------------------------------------------- 340 //----------------------------------------------------------------------------
944 341
945 bool GetMimeTypeFromExtension(const base::FilePath::StringType& ext, 342 bool GetMimeTypeFromExtension(const base::FilePath::StringType& ext,
946 std::string* mime_type) { 343 std::string* mime_type) {
947 return g_mime_util.Get().GetMimeTypeFromExtension(ext, mime_type); 344 return g_mime_util.Get().GetMimeTypeFromExtension(ext, mime_type);
948 } 345 }
949 346
950 bool GetMimeTypeFromFile(const base::FilePath& file_path, 347 bool GetMimeTypeFromFile(const base::FilePath& file_path,
951 std::string* mime_type) { 348 std::string* mime_type) {
952 return g_mime_util.Get().GetMimeTypeFromFile(file_path, mime_type); 349 return g_mime_util.Get().GetMimeTypeFromFile(file_path, mime_type);
953 } 350 }
954 351
955 bool GetWellKnownMimeTypeFromExtension(const base::FilePath::StringType& ext, 352 bool GetWellKnownMimeTypeFromExtension(const base::FilePath::StringType& ext,
956 std::string* mime_type) { 353 std::string* mime_type) {
957 return g_mime_util.Get().GetWellKnownMimeTypeFromExtension(ext, mime_type); 354 return g_mime_util.Get().GetWellKnownMimeTypeFromExtension(ext, mime_type);
958 } 355 }
959 356
960 bool GetPreferredExtensionForMimeType(const std::string& mime_type, 357 bool GetPreferredExtensionForMimeType(const std::string& mime_type,
961 base::FilePath::StringType* extension) { 358 base::FilePath::StringType* extension) {
962 return g_mime_util.Get().GetPreferredExtensionForMimeType(mime_type, 359 return g_mime_util.Get().GetPreferredExtensionForMimeType(mime_type,
963 extension); 360 extension);
964 } 361 }
965 362
966 bool IsSupportedMediaMimeType(const std::string& mime_type) {
967 return g_mime_util.Get().IsSupportedMediaMimeType(mime_type);
968 }
969
970 bool MatchesMimeType(const std::string& mime_type_pattern, 363 bool MatchesMimeType(const std::string& mime_type_pattern,
971 const std::string& mime_type) { 364 const std::string& mime_type) {
972 return g_mime_util.Get().MatchesMimeType(mime_type_pattern, mime_type); 365 return g_mime_util.Get().MatchesMimeType(mime_type_pattern, mime_type);
973 } 366 }
974 367
975 bool ParseMimeTypeWithoutParameter(const std::string& type_string, 368 bool ParseMimeTypeWithoutParameter(const std::string& type_string,
976 std::string* top_level_type, 369 std::string* top_level_type,
977 std::string* subtype) { 370 std::string* subtype) {
978 return g_mime_util.Get().ParseMimeTypeWithoutParameter( 371 return g_mime_util.Get().ParseMimeTypeWithoutParameter(
979 type_string, top_level_type, subtype); 372 type_string, top_level_type, subtype);
980 } 373 }
981 374
982 bool IsValidTopLevelMimeType(const std::string& type_string) { 375 bool IsValidTopLevelMimeType(const std::string& type_string) {
983 return g_mime_util.Get().IsValidTopLevelMimeType(type_string); 376 return g_mime_util.Get().IsValidTopLevelMimeType(type_string);
984 } 377 }
985 378
986 bool AreSupportedMediaCodecs(const std::vector<std::string>& codecs) {
987 return g_mime_util.Get().AreSupportedMediaCodecs(codecs);
988 }
989
990 bool IsStrictMediaMimeType(const std::string& mime_type) {
991 return g_mime_util.Get().IsStrictMediaMimeType(mime_type);
992 }
993
994 SupportsType IsSupportedStrictMediaMimeType(
995 const std::string& mime_type,
996 const std::vector<std::string>& codecs) {
997 return g_mime_util.Get().IsSupportedStrictMediaMimeType(mime_type, codecs);
998 }
999
1000 void ParseCodecString(const std::string& codecs,
1001 std::vector<std::string>* codecs_out,
1002 const bool strip) {
1003 g_mime_util.Get().ParseCodecString(codecs, codecs_out, strip);
1004 }
1005
1006 namespace { 379 namespace {
1007 380
1008 // From http://www.w3schools.com/media/media_mimeref.asp and 381 // From http://www.w3schools.com/media/media_mimeref.asp and
1009 // http://plugindoc.mozdev.org/winmime.php 382 // http://plugindoc.mozdev.org/winmime.php
1010 static const char* const kStandardImageTypes[] = { 383 static const char* const kStandardImageTypes[] = {
1011 "image/bmp", 384 "image/bmp",
1012 "image/cis-cod", 385 "image/cis-cod",
1013 "image/gif", 386 "image/gif",
1014 "image/ief", 387 "image/ief",
1015 "image/jpeg", 388 "image/jpeg",
(...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after
1178 551
1179 GetExtensionsFromHardCodedMappings(secondary_mappings, 552 GetExtensionsFromHardCodedMappings(secondary_mappings,
1180 arraysize(secondary_mappings), 553 arraysize(secondary_mappings),
1181 mime_type, 554 mime_type,
1182 &unique_extensions); 555 &unique_extensions);
1183 } 556 }
1184 557
1185 HashSetToVector(&unique_extensions, extensions); 558 HashSetToVector(&unique_extensions, extensions);
1186 } 559 }
1187 560
1188 void RemoveProprietaryMediaTypesAndCodecsForTests() {
1189 g_mime_util.Get().RemoveProprietaryMediaTypesAndCodecsForTests();
1190 }
1191
1192 void AddMultipartValueForUpload(const std::string& value_name, 561 void AddMultipartValueForUpload(const std::string& value_name,
1193 const std::string& value, 562 const std::string& value,
1194 const std::string& mime_boundary, 563 const std::string& mime_boundary,
1195 const std::string& content_type, 564 const std::string& content_type,
1196 std::string* post_data) { 565 std::string* post_data) {
1197 DCHECK(post_data); 566 DCHECK(post_data);
1198 // First line is the boundary. 567 // First line is the boundary.
1199 post_data->append("--" + mime_boundary + "\r\n"); 568 post_data->append("--" + mime_boundary + "\r\n");
1200 // Next line is the Content-disposition. 569 // Next line is the Content-disposition.
1201 post_data->append("Content-Disposition: form-data; name=\"" + 570 post_data->append("Content-Disposition: form-data; name=\"" +
1202 value_name + "\"\r\n"); 571 value_name + "\"\r\n");
1203 if (!content_type.empty()) { 572 if (!content_type.empty()) {
1204 // If Content-type is specified, the next line is that. 573 // If Content-type is specified, the next line is that.
1205 post_data->append("Content-Type: " + content_type + "\r\n"); 574 post_data->append("Content-Type: " + content_type + "\r\n");
1206 } 575 }
1207 // Leave an empty line and append the value. 576 // Leave an empty line and append the value.
1208 post_data->append("\r\n" + value + "\r\n"); 577 post_data->append("\r\n" + value + "\r\n");
1209 } 578 }
1210 579
1211 void AddMultipartFinalDelimiterForUpload(const std::string& mime_boundary, 580 void AddMultipartFinalDelimiterForUpload(const std::string& mime_boundary,
1212 std::string* post_data) { 581 std::string* post_data) {
1213 DCHECK(post_data); 582 DCHECK(post_data);
1214 post_data->append("--" + mime_boundary + "--\r\n"); 583 post_data->append("--" + mime_boundary + "--\r\n");
1215 } 584 }
1216 585
1217 } // namespace net 586 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698