mime_util_internal.cc 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976
  1. // Copyright 2012 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "media/base/mime_util_internal.h"
  5. #include "base/command_line.h"
  6. #include "base/feature_list.h"
  7. #include "base/logging.h"
  8. #include "base/no_destructor.h"
  9. #include "base/notreached.h"
  10. #include "base/strings/string_number_conversions.h"
  11. #include "base/strings/string_split.h"
  12. #include "base/strings/string_util.h"
  13. #include "build/build_config.h"
  14. #include "media/base/media.h"
  15. #include "media/base/media_client.h"
  16. #include "media/base/media_switches.h"
  17. #include "media/base/supported_types.h"
  18. #include "media/base/video_codecs.h"
  19. #include "media/base/video_color_space.h"
  20. #include "media/media_buildflags.h"
  21. #if BUILDFLAG(IS_ANDROID)
  22. #include "base/android/build_info.h"
  23. // TODO(dalecurtis): This include is not allowed by media/base since
  24. // media/base/android is technically a different component. We should move
  25. // mime_util*.{cc,h} out of media/base to fix this.
  26. #include "media/base/android/media_codec_util.h" // nogncheck
  27. #endif
  28. namespace media {
  29. namespace internal {
  30. // A map from codec string to MimeUtil::Codec.
  31. using StringToCodecMap = base::flat_map<std::string, MimeUtil::Codec>;
  32. // Wrapped to avoid static initializer startup cost.
  33. const StringToCodecMap& GetStringToCodecMap() {
  34. static const base::NoDestructor<StringToCodecMap> kStringToCodecMap({
  35. // We only allow this for WAV so it isn't ambiguous.
  36. {"1", MimeUtil::PCM},
  37. // avc1/avc3.XXXXXX may be unambiguous; handled by
  38. // ParseAVCCodecId(). hev1/hvc1.XXXXXX may be unambiguous;
  39. // handled by ParseHEVCCodecID(). vp9, vp9.0,
  40. // vp09.xx.xx.xx.xx.xx.xx.xx may be unambiguous; handled by
  41. // ParseVp9CodecID().
  42. {"mp3", MimeUtil::MP3},
  43. // Following is the list of RFC 6381 compliant audio codec
  44. // strings:
  45. // mp4a.66 - MPEG-2 AAC MAIN
  46. // mp4a.67 - MPEG-2 AAC LC
  47. // mp4a.68 - MPEG-2 AAC SSR
  48. // mp4a.69 - MPEG-2 extension to MPEG-1 (MP3)
  49. // mp4a.6B - MPEG-1 audio (MP3)
  50. // mp4a.40.2 - MPEG-4 AAC LC
  51. // mp4a.40.02 - MPEG-4 AAC LC (leading 0 in aud-oti for
  52. // compatibility)
  53. // mp4a.40.5 - MPEG-4 HE-AAC v1 (AAC LC + SBR)
  54. // mp4a.40.05 - MPEG-4 HE-AAC v1 (AAC LC + SBR) (leading 0
  55. // in aud-oti for compatibility)
  56. // mp4a.40.29 - MPEG-4 HE-AAC v2 (AAC LC + SBR + PS)
  57. {"mp4a.66", MimeUtil::MPEG2_AAC},
  58. {"mp4a.67", MimeUtil::MPEG2_AAC},
  59. {"mp4a.68", MimeUtil::MPEG2_AAC},
  60. {"mp4a.69", MimeUtil::MP3},
  61. {"mp4a.6B", MimeUtil::MP3},
  62. {"mp4a.40.2", MimeUtil::MPEG4_AAC},
  63. {"mp4a.40.02", MimeUtil::MPEG4_AAC},
  64. {"mp4a.40.5", MimeUtil::MPEG4_AAC},
  65. {"mp4a.40.05", MimeUtil::MPEG4_AAC},
  66. {"mp4a.40.29", MimeUtil::MPEG4_AAC},
  67. {"mp4a.40.42", MimeUtil::MPEG4_XHE_AAC},
  68. // TODO(servolk): Strictly speaking only mp4a.A5 and mp4a.A6
  69. // codec ids are valid according to RFC 6381 section 3.3, 3.4.
  70. // Lower-case oti (mp4a.a5 and mp4a.a6) should be rejected. But
  71. // we used to allow those in older versions of Chromecast
  72. // firmware and some apps (notably MPL) depend on those codec
  73. // types being supported, so they should be allowed for now
  74. // (crbug.com/564960).
  75. {"ac-3", MimeUtil::AC3},
  76. {"mp4a.a5", MimeUtil::AC3},
  77. {"mp4a.A5", MimeUtil::AC3},
  78. {"ec-3", MimeUtil::EAC3},
  79. {"mp4a.a6", MimeUtil::EAC3},
  80. {"mp4a.A6", MimeUtil::EAC3},
  81. {"vorbis", MimeUtil::VORBIS},
  82. {"opus", MimeUtil::OPUS},
  83. {"flac", MimeUtil::FLAC},
  84. {"vp8", MimeUtil::VP8},
  85. {"vp8.0", MimeUtil::VP8},
  86. {"theora", MimeUtil::THEORA},
  87. {"dtsc", MimeUtil::DTS},
  88. {"mp4a.a9", MimeUtil::DTS},
  89. {"mp4a.A9", MimeUtil::DTS},
  90. {"dtsx", MimeUtil::DTSXP2},
  91. {"mp4a.b2", MimeUtil::DTSXP2},
  92. {"mp4a.B2", MimeUtil::DTSXP2},
  93. });
  94. return *kStringToCodecMap;
  95. }
  96. static bool ParseVp9CodecID(const std::string& mime_type_lower_case,
  97. const std::string& codec_id,
  98. VideoCodecProfile* out_profile,
  99. uint8_t* out_level,
  100. VideoColorSpace* out_color_space) {
  101. if (ParseNewStyleVp9CodecID(codec_id, out_profile, out_level,
  102. out_color_space)) {
  103. // New style (e.g. vp09.00.10.08) is accepted with any mime type (including
  104. // empty mime type).
  105. return true;
  106. }
  107. // Legacy style (e.g. "vp9") is ambiguous about codec profile, and is only
  108. // valid with video/webm for legacy reasons.
  109. if (mime_type_lower_case == "video/webm")
  110. return ParseLegacyVp9CodecID(codec_id, out_profile, out_level);
  111. return false;
  112. }
  113. static bool IsValidH264Level(uint8_t level_idc) {
  114. // Valid levels taken from Table A-1 in ISO/IEC 14496-10.
  115. // Level_idc represents the standard level represented as decimal number
  116. // multiplied by ten, e.g. level_idc==32 corresponds to level==3.2
  117. return ((level_idc >= 10 && level_idc <= 13) ||
  118. (level_idc >= 20 && level_idc <= 22) ||
  119. (level_idc >= 30 && level_idc <= 32) ||
  120. (level_idc >= 40 && level_idc <= 42) ||
  121. (level_idc >= 50 && level_idc <= 52) ||
  122. (level_idc >= 60 && level_idc <= 62));
  123. }
  124. // Make a default ParsedCodecResult. Values should indicate "unspecified"
  125. // where possible. Color space is an exception where we choose a default value
  126. // because most codec strings will not describe a color space.
  127. static MimeUtil::ParsedCodecResult MakeDefaultParsedCodecResult() {
  128. return {
  129. MimeUtil::INVALID_CODEC, false, VIDEO_CODEC_PROFILE_UNKNOWN, 0,
  130. // We choose 709 as default color space elsewhere, so defaulting to 709
  131. // here as well. See here for context: https://crrev.com/1221903003/
  132. VideoColorSpace::REC709()};
  133. }
  134. MimeUtil::MimeUtil() {
  135. #if BUILDFLAG(IS_ANDROID)
  136. #if BUILDFLAG(ENABLE_PLATFORM_DOLBY_VISION)
  137. platform_info_.has_platform_dv_decoder =
  138. MediaCodecUtil::IsDolbyVisionDecoderAvailable();
  139. #endif
  140. platform_info_.has_platform_vp8_decoder =
  141. MediaCodecUtil::IsVp8DecoderAvailable();
  142. platform_info_.has_platform_vp9_decoder =
  143. MediaCodecUtil::IsVp9DecoderAvailable();
  144. #if BUILDFLAG(ENABLE_PLATFORM_HEVC)
  145. platform_info_.has_platform_hevc_decoder =
  146. MediaCodecUtil::IsHEVCDecoderAvailable();
  147. #endif
  148. platform_info_.has_platform_opus_decoder =
  149. MediaCodecUtil::IsOpusDecoderAvailable();
  150. #endif // BUILDFLAG(IS_ANDROID)
  151. InitializeMimeTypeMaps();
  152. }
  153. MimeUtil::~MimeUtil() = default;
  154. AudioCodec MimeUtilToAudioCodec(MimeUtil::Codec codec) {
  155. switch (codec) {
  156. case MimeUtil::PCM:
  157. return AudioCodec::kPCM;
  158. case MimeUtil::MP3:
  159. return AudioCodec::kMP3;
  160. case MimeUtil::AC3:
  161. return AudioCodec::kAC3;
  162. case MimeUtil::EAC3:
  163. return AudioCodec::kEAC3;
  164. case MimeUtil::MPEG2_AAC:
  165. case MimeUtil::MPEG4_AAC:
  166. case MimeUtil::MPEG4_XHE_AAC:
  167. return AudioCodec::kAAC;
  168. case MimeUtil::MPEG_H_AUDIO:
  169. return AudioCodec::kMpegHAudio;
  170. case MimeUtil::VORBIS:
  171. return AudioCodec::kVorbis;
  172. case MimeUtil::OPUS:
  173. return AudioCodec::kOpus;
  174. case MimeUtil::FLAC:
  175. return AudioCodec::kFLAC;
  176. case MimeUtil::DTS:
  177. return AudioCodec::kDTS;
  178. case MimeUtil::DTSXP2:
  179. return AudioCodec::kDTSXP2;
  180. default:
  181. break;
  182. }
  183. return AudioCodec::kUnknown;
  184. }
  185. VideoCodec MimeUtilToVideoCodec(MimeUtil::Codec codec) {
  186. switch (codec) {
  187. case MimeUtil::AV1:
  188. return VideoCodec::kAV1;
  189. case MimeUtil::H264:
  190. return VideoCodec::kH264;
  191. case MimeUtil::HEVC:
  192. return VideoCodec::kHEVC;
  193. case MimeUtil::VP8:
  194. return VideoCodec::kVP8;
  195. case MimeUtil::VP9:
  196. return VideoCodec::kVP9;
  197. case MimeUtil::THEORA:
  198. return VideoCodec::kTheora;
  199. case MimeUtil::DOLBY_VISION:
  200. return VideoCodec::kDolbyVision;
  201. default:
  202. break;
  203. }
  204. return VideoCodec::kUnknown;
  205. }
  206. SupportsType MimeUtil::AreSupportedCodecs(
  207. const std::vector<ParsedCodecResult>& parsed_codecs,
  208. const std::string& mime_type_lower_case,
  209. bool is_encrypted) const {
  210. DCHECK(!parsed_codecs.empty());
  211. DCHECK_EQ(base::ToLowerASCII(mime_type_lower_case), mime_type_lower_case);
  212. SupportsType combined_result = SupportsType::kSupported;
  213. for (const auto& parsed_codec : parsed_codecs) {
  214. // Make conservative guesses to resolve ambiguity before checking platform
  215. // support. Historically we allowed some ambiguity in H264 and VP9 codec
  216. // strings, so we must continue to allow going forward. DO NOT ADD NEW
  217. // SUPPORT FOR MORE AMBIGUOUS STRINGS.
  218. VideoCodecProfile video_profile = parsed_codec.video_profile;
  219. uint8_t video_level = parsed_codec.video_level;
  220. if (parsed_codec.is_ambiguous) {
  221. switch (parsed_codec.codec) {
  222. case MimeUtil::H264:
  223. if (video_profile == VIDEO_CODEC_PROFILE_UNKNOWN)
  224. video_profile = H264PROFILE_BASELINE;
  225. if (!IsValidH264Level(video_level))
  226. video_level = 10;
  227. break;
  228. case MimeUtil::VP9:
  229. if (video_profile == VIDEO_CODEC_PROFILE_UNKNOWN)
  230. video_profile = VP9PROFILE_PROFILE0;
  231. if (video_level == 0)
  232. video_level = 10;
  233. break;
  234. case MimeUtil::MPEG4_AAC:
  235. // Nothing to do for AAC; no notion of profile / level to guess.
  236. break;
  237. default:
  238. NOTREACHED()
  239. << "Only VP9, H264, and AAC codec strings can be ambiguous.";
  240. }
  241. }
  242. // Check platform support.
  243. SupportsType result = IsCodecSupported(
  244. mime_type_lower_case, parsed_codec.codec, video_profile, video_level,
  245. parsed_codec.video_color_space, is_encrypted);
  246. if (result == SupportsType::kNotSupported) {
  247. DVLOG(2) << __func__ << ": Codec " << parsed_codec.codec
  248. << " not supported by platform.";
  249. return SupportsType::kNotSupported;
  250. }
  251. // If any codec is "kMaybeSupported", return Maybe for the combined result.
  252. if (result == SupportsType::kMaybeSupported ||
  253. // Downgrade to kMaybeSupported if we had to guess the meaning of one of
  254. // the codec strings. Do not downgrade for VP9 because we historically
  255. // returned "Probably" for the old "vp9" string and cannot change to
  256. // returning "Maybe" as this will break sites.
  257. (result == SupportsType::kSupported && parsed_codec.is_ambiguous &&
  258. parsed_codec.codec != MimeUtil::VP9)) {
  259. combined_result = SupportsType::kMaybeSupported;
  260. }
  261. }
  262. return combined_result;
  263. }
  264. void MimeUtil::InitializeMimeTypeMaps() {
  265. AddSupportedMediaFormats();
  266. }
  267. // Each call to AddContainerWithCodecs() contains a media type
  268. // (https://en.wikipedia.org/wiki/Media_type) and corresponding media codec(s)
  269. // supported by these types/containers.
  270. void MimeUtil::AddSupportedMediaFormats() {
  271. const CodecSet wav_codecs{PCM};
  272. const CodecSet ogg_audio_codecs{FLAC, OPUS, VORBIS};
  273. CodecSet ogg_video_codecs{VP8};
  274. #if BUILDFLAG(ENABLE_FFMPEG_VIDEO_DECODERS)
  275. ogg_video_codecs.emplace(THEORA);
  276. #endif // BUILDFLAG(ENABLE_FFMPEG_VIDEO_DECODERS)
  277. CodecSet ogg_codecs(ogg_audio_codecs);
  278. ogg_codecs.insert(ogg_video_codecs.begin(), ogg_video_codecs.end());
  279. const CodecSet webm_audio_codecs{OPUS, VORBIS};
  280. CodecSet webm_video_codecs{VP8, VP9};
  281. #if BUILDFLAG(ENABLE_AV1_DECODER)
  282. webm_video_codecs.emplace(AV1);
  283. #endif
  284. CodecSet webm_codecs(webm_audio_codecs);
  285. webm_codecs.insert(webm_video_codecs.begin(), webm_video_codecs.end());
  286. const CodecSet mp3_codecs{MP3};
  287. CodecSet mp4_audio_codecs{FLAC, MP3, OPUS};
  288. // Only VP9 with valid codec string vp09.xx.xx.xx.xx.xx.xx.xx is supported.
  289. // See ParseVp9CodecID for details.
  290. CodecSet mp4_video_codecs;
  291. mp4_video_codecs.emplace(VP9);
  292. #if BUILDFLAG(USE_PROPRIETARY_CODECS)
  293. const CodecSet aac{MPEG2_AAC, MPEG4_AAC, MPEG4_XHE_AAC};
  294. mp4_audio_codecs.insert(aac.begin(), aac.end());
  295. CodecSet avc_and_aac(aac);
  296. avc_and_aac.emplace(H264);
  297. #if BUILDFLAG(ENABLE_PLATFORM_AC3_EAC3_AUDIO)
  298. mp4_audio_codecs.emplace(AC3);
  299. mp4_audio_codecs.emplace(EAC3);
  300. #endif // BUILDFLAG(ENABLE_PLATFORM_AC3_EAC3_AUDIO)
  301. #if BUILDFLAG(ENABLE_PLATFORM_MPEG_H_AUDIO)
  302. mp4_audio_codecs.emplace(MPEG_H_AUDIO);
  303. #endif // BUILDFLAG(ENABLE_PLATFORM_MPEG_H_AUDIO)
  304. mp4_video_codecs.emplace(H264);
  305. #if BUILDFLAG(ENABLE_PLATFORM_HEVC)
  306. mp4_video_codecs.emplace(HEVC);
  307. #endif // BUILDFLAG(ENABLE_PLATFORM_HEVC)
  308. #if BUILDFLAG(ENABLE_PLATFORM_DOLBY_VISION)
  309. mp4_video_codecs.emplace(DOLBY_VISION);
  310. #endif // BUILDFLAG(ENABLE_PLATFORM_DOLBY_VISION)
  311. #endif // BUILDFLAG(USE_PROPRIETARY_CODECS)
  312. #if BUILDFLAG(ENABLE_AV1_DECODER)
  313. mp4_video_codecs.emplace(AV1);
  314. #endif
  315. #if BUILDFLAG(ENABLE_PLATFORM_DTS_AUDIO)
  316. mp4_audio_codecs.emplace(DTS);
  317. mp4_audio_codecs.emplace(DTSXP2);
  318. #endif // BUILDFLAG(ENABLE_PLATFORM_DTS_AUDIO)
  319. CodecSet mp4_codecs(mp4_audio_codecs);
  320. mp4_codecs.insert(mp4_video_codecs.begin(), mp4_video_codecs.end());
  321. const CodecSet implicit_codec;
  322. AddContainerWithCodecs("audio/wav", wav_codecs);
  323. AddContainerWithCodecs("audio/x-wav", wav_codecs);
  324. AddContainerWithCodecs("audio/webm", webm_audio_codecs);
  325. DCHECK(!webm_video_codecs.empty());
  326. AddContainerWithCodecs("video/webm", webm_codecs);
  327. AddContainerWithCodecs("audio/ogg", ogg_audio_codecs);
  328. // video/ogg is only supported if an appropriate video codec is supported.
  329. // Note: This assumes such codecs cannot be later excluded.
  330. if (!ogg_video_codecs.empty())
  331. AddContainerWithCodecs("video/ogg", ogg_codecs);
  332. // TODO(ddorwin): Should the application type support Opus?
  333. AddContainerWithCodecs("application/ogg", ogg_codecs);
  334. AddContainerWithCodecs("audio/flac", implicit_codec);
  335. AddContainerWithCodecs("audio/mpeg", mp3_codecs); // Allow "mp3".
  336. AddContainerWithCodecs("audio/mp3", implicit_codec);
  337. AddContainerWithCodecs("audio/x-mp3", implicit_codec);
  338. AddContainerWithCodecs("audio/mp4", mp4_audio_codecs);
  339. DCHECK(!mp4_video_codecs.empty());
  340. AddContainerWithCodecs("video/mp4", mp4_codecs);
  341. #if BUILDFLAG(USE_PROPRIETARY_CODECS)
  342. AddContainerWithCodecs("audio/aac", implicit_codec); // AAC / ADTS.
  343. // These strings are supported for backwards compatibility only and thus only
  344. // support the codecs needed for compatibility.
  345. AddContainerWithCodecs("audio/x-m4a", aac);
  346. AddContainerWithCodecs("video/x-m4v", avc_and_aac);
  347. CodecSet video_3gpp_codecs(aac);
  348. video_3gpp_codecs.emplace(H264);
  349. AddContainerWithCodecs("video/3gpp", video_3gpp_codecs);
  350. #if BUILDFLAG(ENABLE_MSE_MPEG2TS_STREAM_PARSER)
  351. CodecSet mp2t_codecs{H264, MPEG2_AAC, MPEG4_AAC, MP3};
  352. AddContainerWithCodecs("video/mp2t", mp2t_codecs);
  353. #endif // BUILDFLAG(ENABLE_MSE_MPEG2TS_STREAM_PARSER)
  354. #if BUILDFLAG(IS_ANDROID)
  355. if (base::FeatureList::IsEnabled(kCanPlayHls)) {
  356. // HTTP Live Streaming (HLS).
  357. CodecSet hls_codecs{H264,
  358. // TODO(ddorwin): Is any MP3 codec string variant
  359. // included in real queries?
  360. MP3,
  361. // Android HLS only supports MPEG4_AAC (missing demuxer
  362. // support for MPEG2_AAC)
  363. MPEG4_AAC};
  364. AddContainerWithCodecs("application/x-mpegurl", hls_codecs);
  365. AddContainerWithCodecs("application/vnd.apple.mpegurl", hls_codecs);
  366. AddContainerWithCodecs("audio/mpegurl", hls_codecs);
  367. // Not documented by Apple, but unfortunately used extensively by Apple and
  368. // others for both audio-only and audio+video playlists. See
  369. // https://crbug.com/675552 for details and examples.
  370. AddContainerWithCodecs("audio/x-mpegurl", hls_codecs);
  371. }
  372. #endif // BUILDFLAG(IS_ANDROID)
  373. #endif // BUILDFLAG(USE_PROPRIETARY_CODECS)
  374. }
  375. void MimeUtil::AddContainerWithCodecs(const std::string& mime_type,
  376. const CodecSet& codecs) {
  377. media_format_map_[mime_type] = codecs;
  378. }
  379. bool MimeUtil::IsSupportedMediaMimeType(const std::string& mime_type) const {
  380. return media_format_map_.contains(base::ToLowerASCII(mime_type));
  381. }
  382. void MimeUtil::SplitCodecs(const std::string& codecs,
  383. std::vector<std::string>* codecs_out) const {
  384. *codecs_out =
  385. base::SplitString(base::TrimString(codecs, "\"", base::TRIM_ALL), ",",
  386. base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
  387. // Convert empty or all-whitespace input to 0 results.
  388. if (codecs_out->size() == 1 && (*codecs_out)[0].empty())
  389. codecs_out->clear();
  390. }
  391. void MimeUtil::StripCodecs(std::vector<std::string>* codecs) const {
  392. // Strip everything past the first '.'
  393. for (auto it = codecs->begin(); it != codecs->end(); ++it) {
  394. size_t found = it->find_first_of('.');
  395. if (found != std::string::npos)
  396. it->resize(found);
  397. }
  398. }
  399. bool MimeUtil::ParseVideoCodecString(const std::string& mime_type,
  400. const std::string& codec_id,
  401. bool* out_is_ambiguous,
  402. VideoCodec* out_codec,
  403. VideoCodecProfile* out_profile,
  404. uint8_t* out_level,
  405. VideoColorSpace* out_color_space) const {
  406. DCHECK(out_is_ambiguous);
  407. DCHECK(out_codec);
  408. DCHECK(out_profile);
  409. DCHECK(out_level);
  410. DCHECK(out_color_space);
  411. // Internal parsing API expects a vector of codecs.
  412. std::vector<ParsedCodecResult> parsed_results;
  413. std::vector<std::string> codec_strings;
  414. if (!codec_id.empty())
  415. codec_strings.push_back(codec_id);
  416. if (!ParseCodecStrings(base::ToLowerASCII(mime_type), codec_strings,
  417. &parsed_results)) {
  418. DVLOG(3) << __func__ << " Failed to parse mime/codec pair: "
  419. << (mime_type.empty() ? "<empty mime>" : mime_type) << "; "
  420. << codec_id;
  421. return false;
  422. }
  423. CHECK_EQ(1U, parsed_results.size());
  424. *out_is_ambiguous = parsed_results[0].is_ambiguous;
  425. *out_codec = MimeUtilToVideoCodec(parsed_results[0].codec);
  426. *out_profile = parsed_results[0].video_profile;
  427. *out_level = parsed_results[0].video_level;
  428. *out_color_space = parsed_results[0].video_color_space;
  429. if (*out_codec == VideoCodec::kUnknown) {
  430. DVLOG(3) << __func__ << " Codec string " << codec_id
  431. << " is not a VIDEO codec.";
  432. return false;
  433. }
  434. return true;
  435. }
  436. bool MimeUtil::ParseAudioCodecString(const std::string& mime_type,
  437. const std::string& codec_id,
  438. bool* out_is_ambiguous,
  439. AudioCodec* out_codec) const {
  440. DCHECK(out_is_ambiguous);
  441. DCHECK(out_codec);
  442. // Internal parsing API expects a vector of codecs.
  443. std::vector<ParsedCodecResult> parsed_results;
  444. std::vector<std::string> codec_strings;
  445. if (!codec_id.empty())
  446. codec_strings.push_back(codec_id);
  447. if (!ParseCodecStrings(base::ToLowerASCII(mime_type), codec_strings,
  448. &parsed_results)) {
  449. DVLOG(3) << __func__ << " Failed to parse mime/codec pair:"
  450. << (mime_type.empty() ? "<empty mime>" : mime_type) << "; "
  451. << codec_id;
  452. return false;
  453. }
  454. CHECK_EQ(1U, parsed_results.size());
  455. *out_is_ambiguous = parsed_results[0].is_ambiguous;
  456. *out_codec = MimeUtilToAudioCodec(parsed_results[0].codec);
  457. if (*out_codec == AudioCodec::kUnknown) {
  458. DVLOG(3) << __func__ << " Codec string " << codec_id
  459. << " is not an AUDIO codec.";
  460. return false;
  461. }
  462. return true;
  463. }
  464. SupportsType MimeUtil::IsSupportedMediaFormat(
  465. const std::string& mime_type,
  466. const std::vector<std::string>& codecs,
  467. bool is_encrypted) const {
  468. const std::string mime_type_lower_case = base::ToLowerASCII(mime_type);
  469. std::vector<ParsedCodecResult> parsed_results;
  470. if (!ParseCodecStrings(mime_type_lower_case, codecs, &parsed_results)) {
  471. DVLOG(3) << __func__ << " Media format unsupported; codec parsing failed "
  472. << mime_type << " " << base::JoinString(codecs, ",");
  473. return SupportsType::kNotSupported;
  474. }
  475. if (parsed_results.empty()) {
  476. NOTREACHED() << __func__ << " Successful parsing should output results.";
  477. return SupportsType::kNotSupported;
  478. }
  479. // We get here if the mime type expects to get a codecs parameter
  480. // but none was provided and no default codec was implied. In this case
  481. // the best we can do is say "maybe" because we don't have enough
  482. // information.
  483. if (codecs.empty() && parsed_results.size() == 1 &&
  484. parsed_results[0].codec == INVALID_CODEC) {
  485. DCHECK(parsed_results[0].is_ambiguous);
  486. return SupportsType::kMaybeSupported;
  487. }
  488. return AreSupportedCodecs(parsed_results, mime_type_lower_case, is_encrypted);
  489. }
  490. // static
  491. bool MimeUtil::IsCodecSupportedOnAndroid(
  492. Codec codec,
  493. const std::string& mime_type_lower_case,
  494. bool is_encrypted,
  495. VideoCodecProfile video_profile,
  496. const PlatformInfo& platform_info) {
  497. DVLOG(3) << __func__;
  498. DCHECK_NE(mime_type_lower_case, "");
  499. // NOTE: We do not account for Media Source Extensions (MSE) within these
  500. // checks since it has its own isTypeSupported() which will handle platform
  501. // specific codec rejections. See http://crbug.com/587303.
  502. switch (codec) {
  503. // ----------------------------------------------------------------------
  504. // The following codecs are never supported.
  505. // ----------------------------------------------------------------------
  506. case INVALID_CODEC:
  507. case THEORA:
  508. return false;
  509. // ----------------------------------------------------------------------
  510. // The remaining codecs may be supported depending on platform abilities.
  511. // ----------------------------------------------------------------------
  512. case AV1:
  513. return BUILDFLAG(ENABLE_AV1_DECODER);
  514. case MPEG2_AAC:
  515. // MPEG2_AAC cannot be used in HLS (mpegurl suffix), but this is enforced
  516. // in the parsing step by excluding MPEG2_AAC from the list of
  517. // valid codecs to be used with HLS mime types.
  518. DCHECK(!base::EndsWith(mime_type_lower_case, "mpegurl",
  519. base::CompareCase::SENSITIVE));
  520. [[fallthrough]];
  521. case PCM:
  522. case MP3:
  523. case MPEG4_AAC:
  524. case FLAC:
  525. case VORBIS:
  526. // These codecs are always supported; via a platform decoder (when used
  527. // with MSE/EME) or with a software decoder (the unified pipeline).
  528. return true;
  529. case MPEG4_XHE_AAC:
  530. return true;
  531. case MPEG_H_AUDIO:
  532. return false;
  533. case OPUS:
  534. // If clear, the unified pipeline can always decode Opus in software.
  535. if (!is_encrypted)
  536. return true;
  537. // Otherwise, platform support is required.
  538. if (!platform_info.has_platform_opus_decoder) {
  539. DVLOG(3) << "Platform does not support opus";
  540. return false;
  541. }
  542. return true;
  543. case H264:
  544. return true;
  545. case HEVC:
  546. #if BUILDFLAG(ENABLE_PLATFORM_HEVC)
  547. return platform_info.has_platform_hevc_decoder;
  548. #else
  549. return false;
  550. #endif // BUILDFLAG(ENABLE_PLATFORM_HEVC)
  551. case VP8:
  552. // If clear, the unified pipeline can always decode VP8 in software.
  553. return is_encrypted ? platform_info.has_platform_vp8_decoder : true;
  554. case VP9: {
  555. if (base::CommandLine::ForCurrentProcess()->HasSwitch(
  556. switches::kReportVp9AsAnUnsupportedMimeType)) {
  557. return false;
  558. }
  559. // If clear, the unified pipeline can always decode VP9.0,1 in software.
  560. // If we don't know the profile, then support is ambiguous, but default to
  561. // true for historical reasons.
  562. if (!is_encrypted && (video_profile == VP9PROFILE_PROFILE0 ||
  563. video_profile == VP9PROFILE_PROFILE1 ||
  564. video_profile == VIDEO_CODEC_PROFILE_UNKNOWN)) {
  565. return true;
  566. }
  567. if (!platform_info.has_platform_vp9_decoder)
  568. return false;
  569. return true;
  570. }
  571. case DOLBY_VISION:
  572. #if BUILDFLAG(ENABLE_PLATFORM_DOLBY_VISION)
  573. return platform_info.has_platform_dv_decoder;
  574. #else
  575. return false;
  576. #endif
  577. case AC3:
  578. case EAC3:
  579. #if BUILDFLAG(ENABLE_PLATFORM_AC3_EAC3_AUDIO)
  580. return true;
  581. #else
  582. return false;
  583. #endif
  584. case DTS:
  585. case DTSXP2:
  586. #if BUILDFLAG(ENABLE_PLATFORM_DTS_AUDIO)
  587. return true;
  588. #else
  589. return false;
  590. #endif
  591. }
  592. return false;
  593. }
  594. bool MimeUtil::ParseCodecStrings(
  595. const std::string& mime_type_lower_case,
  596. const std::vector<std::string>& codecs,
  597. std::vector<ParsedCodecResult>* out_results) const {
  598. DCHECK(out_results);
  599. // Nothing to parse.
  600. if (mime_type_lower_case.empty() && codecs.empty())
  601. return false;
  602. // When mime type is provided, it may imply a codec or only be valid with
  603. // certain codecs.
  604. const CodecSet* valid_codecs_for_mime;
  605. if (!mime_type_lower_case.empty()) {
  606. // Reject unrecognized mime types.
  607. auto it_media_format_map = media_format_map_.find(mime_type_lower_case);
  608. if (it_media_format_map == media_format_map_.end()) {
  609. DVLOG(3) << __func__
  610. << " Unrecognized mime type: " << mime_type_lower_case;
  611. return false;
  612. }
  613. valid_codecs_for_mime = &it_media_format_map->second;
  614. if (valid_codecs_for_mime->empty()) {
  615. // We get here if the mimetype does not expect a codecs parameter.
  616. if (!codecs.empty()) {
  617. DVLOG(3) << __func__
  618. << " Codecs unexpected for mime type:" << mime_type_lower_case;
  619. return false;
  620. }
  621. // Determine implied codec for mime type.
  622. ParsedCodecResult implied_result = MakeDefaultParsedCodecResult();
  623. if (!GetDefaultCodec(mime_type_lower_case, &implied_result.codec)) {
  624. NOTREACHED() << " Mime types must offer a default codec if no explicit "
  625. "codecs are expected";
  626. return false;
  627. }
  628. out_results->push_back(implied_result);
  629. return true;
  630. }
  631. if (codecs.empty()) {
  632. // We get here if the mimetype expects to get a codecs parameter,
  633. // but didn't get one. If |mime_type_lower_case| does not have a default
  634. // codec, the string is considered ambiguous.
  635. ParsedCodecResult implied_result = MakeDefaultParsedCodecResult();
  636. implied_result.is_ambiguous =
  637. !GetDefaultCodec(mime_type_lower_case, &implied_result.codec);
  638. out_results->push_back(implied_result);
  639. return true;
  640. }
  641. }
  642. // All empty cases handled above.
  643. DCHECK(!codecs.empty());
  644. for (std::string codec_string : codecs) {
  645. ParsedCodecResult result;
  646. #if BUILDFLAG(ENABLE_MSE_MPEG2TS_STREAM_PARSER)
  647. if (mime_type_lower_case == "video/mp2t")
  648. codec_string = TranslateLegacyAvc1CodecIds(codec_string);
  649. #endif
  650. if (!ParseCodecHelper(mime_type_lower_case, codec_string, &result)) {
  651. DVLOG(3) << __func__ << " Failed to parse mime/codec pair: "
  652. << (mime_type_lower_case.empty() ? "<empty mime>"
  653. : mime_type_lower_case)
  654. << "; " << codec_string;
  655. return false;
  656. }
  657. DCHECK_NE(INVALID_CODEC, result.codec);
  658. // If mime type given, fail if mime + codec is not a valid combination.
  659. if (!mime_type_lower_case.empty() &&
  660. !valid_codecs_for_mime->contains(result.codec)) {
  661. DVLOG(3) << __func__
  662. << " Incompatible mime/codec pair: " << mime_type_lower_case
  663. << "; " << codec_string;
  664. return false;
  665. }
  666. out_results->push_back(result);
  667. }
  668. return true;
  669. }
  670. bool MimeUtil::ParseCodecHelper(const std::string& mime_type_lower_case,
  671. const std::string& codec_id,
  672. ParsedCodecResult* out_result) const {
  673. DCHECK_EQ(base::ToLowerASCII(mime_type_lower_case), mime_type_lower_case);
  674. DCHECK(out_result);
  675. *out_result = MakeDefaultParsedCodecResult();
  676. // Simple codecs can be found in the codec map.
  677. auto itr = GetStringToCodecMap().find(codec_id);
  678. if (itr != GetStringToCodecMap().end()) {
  679. out_result->codec = itr->second;
  680. // Even "simple" video codecs should have an associated profile.
  681. if (MimeUtilToVideoCodec(out_result->codec) != VideoCodec::kUnknown) {
  682. switch (out_result->codec) {
  683. case Codec::VP8:
  684. out_result->video_profile = VP8PROFILE_ANY;
  685. break;
  686. case Codec::THEORA:
  687. out_result->video_profile = THEORAPROFILE_ANY;
  688. break;
  689. default:
  690. NOTREACHED();
  691. }
  692. }
  693. return true;
  694. }
  695. // Check codec string against short list of allowed ambiguous codecs.
  696. // Hard-coded to discourage expansion. DO NOT ADD TO THIS LIST. DO NOT
  697. // INCREASE PLACES WHERE |ambiguous_codec_string| = true.
  698. // NOTE: avc1/avc3.XXXXXX may be ambiguous handled after ParseAVCCodecId().
  699. if (codec_id == "avc1" || codec_id == "avc3") {
  700. out_result->codec = MimeUtil::H264;
  701. out_result->is_ambiguous = true;
  702. return true;
  703. } else if (codec_id == "mp4a.40") {
  704. out_result->codec = MimeUtil::MPEG4_AAC;
  705. out_result->is_ambiguous = true;
  706. return true;
  707. }
  708. // If |codec_id| is not in |kStringToCodecMap|, then we assume that it is
  709. // either VP9, H.264 or HEVC/H.265 codec ID because currently those are the
  710. // only ones that are not added to the |kStringToCodecMap| and require
  711. // parsing.
  712. VideoCodecProfile* out_profile = &out_result->video_profile;
  713. uint8_t* out_level = &out_result->video_level;
  714. VideoColorSpace* out_color_space = &out_result->video_color_space;
  715. if (ParseVp9CodecID(mime_type_lower_case, codec_id, out_profile, out_level,
  716. out_color_space)) {
  717. out_result->codec = MimeUtil::VP9;
  718. // Original VP9 codec string did not describe the profile.
  719. if (out_result->video_profile == VIDEO_CODEC_PROFILE_UNKNOWN) {
  720. // New VP9 string should never be ambiguous.
  721. DCHECK(!base::StartsWith(codec_id, "vp09", base::CompareCase::SENSITIVE));
  722. out_result->is_ambiguous = true;
  723. }
  724. return true;
  725. }
  726. #if BUILDFLAG(ENABLE_AV1_DECODER)
  727. if (ParseAv1CodecId(codec_id, out_profile, out_level, out_color_space)) {
  728. out_result->codec = MimeUtil::AV1;
  729. return true;
  730. }
  731. #endif
  732. if (ParseAVCCodecId(codec_id, out_profile, out_level)) {
  733. out_result->codec = MimeUtil::H264;
  734. // Allowed string ambiguity since 2014. DO NOT ADD NEW CASES FOR AMBIGUITY.
  735. out_result->is_ambiguous = !IsValidH264Level(*out_level);
  736. return true;
  737. }
  738. #if BUILDFLAG(ENABLE_PLATFORM_HEVC)
  739. if (ParseHEVCCodecId(codec_id, out_profile, out_level)) {
  740. out_result->codec = MimeUtil::HEVC;
  741. return true;
  742. }
  743. #endif
  744. #if BUILDFLAG(ENABLE_PLATFORM_DOLBY_VISION)
  745. if (ParseDolbyVisionCodecId(codec_id, out_profile, out_level)) {
  746. out_result->codec = MimeUtil::DOLBY_VISION;
  747. return true;
  748. }
  749. #endif
  750. #if BUILDFLAG(ENABLE_PLATFORM_MPEG_H_AUDIO)
  751. if (base::StartsWith(codec_id, "mhm1.", base::CompareCase::SENSITIVE) ||
  752. base::StartsWith(codec_id, "mha1.", base::CompareCase::SENSITIVE)) {
  753. out_result->codec = MimeUtil::MPEG_H_AUDIO;
  754. return true;
  755. }
  756. #endif
  757. DVLOG(2) << __func__ << ": Unrecognized codec id \"" << codec_id << "\"";
  758. return false;
  759. }
  760. SupportsType MimeUtil::IsCodecSupported(const std::string& mime_type_lower_case,
  761. Codec codec,
  762. VideoCodecProfile video_profile,
  763. uint8_t video_level,
  764. const VideoColorSpace& color_space,
  765. bool is_encrypted) const {
  766. DVLOG(3) << __func__;
  767. DCHECK_EQ(base::ToLowerASCII(mime_type_lower_case), mime_type_lower_case);
  768. DCHECK_NE(codec, INVALID_CODEC);
  769. VideoCodec video_codec = MimeUtilToVideoCodec(codec);
  770. if (video_codec != VideoCodec::kUnknown &&
  771. // Theora and VP8 do not have profiles/levels.
  772. video_codec != VideoCodec::kTheora && video_codec != VideoCodec::kVP8 &&
  773. // TODO(dalecurtis): AV1 has levels, but they aren't supported yet;
  774. // http://crbug.com/784993
  775. video_codec != VideoCodec::kAV1) {
  776. DCHECK_NE(video_profile, VIDEO_CODEC_PROFILE_UNKNOWN);
  777. DCHECK_GT(video_level, 0);
  778. }
  779. // Check for cases of ambiguous platform support.
  780. // TODO(chcunningham): DELETE THIS. Platform should know its capabilities.
  781. // Answer should come from MediaClient.
  782. bool ambiguous_platform_support = false;
  783. if (codec == MimeUtil::H264) {
  784. switch (video_profile) {
  785. // Always supported
  786. case H264PROFILE_BASELINE:
  787. case H264PROFILE_MAIN:
  788. case H264PROFILE_HIGH:
  789. break;
  790. // HIGH10PROFILE is supported through fallback to the ffmpeg decoder
  791. // which is not available on Android, or if FFMPEG is not used.
  792. #if BUILDFLAG(ENABLE_FFMPEG_VIDEO_DECODERS)
  793. case H264PROFILE_HIGH10PROFILE:
  794. // FFmpeg is not generally used for encrypted videos, so we do not
  795. // know whether 10-bit is supported.
  796. ambiguous_platform_support = is_encrypted;
  797. break;
  798. #endif
  799. default:
  800. ambiguous_platform_support = true;
  801. }
  802. }
  803. AudioCodec audio_codec = MimeUtilToAudioCodec(codec);
  804. if (audio_codec != AudioCodec::kUnknown) {
  805. AudioCodecProfile audio_profile = AudioCodecProfile::kUnknown;
  806. if (codec == MPEG4_XHE_AAC)
  807. audio_profile = AudioCodecProfile::kXHE_AAC;
  808. if (!IsSupportedAudioType({audio_codec, audio_profile, false}))
  809. return SupportsType::kNotSupported;
  810. }
  811. if (video_codec != VideoCodec::kUnknown) {
  812. if (!IsSupportedVideoType(
  813. {video_codec, video_profile, video_level, color_space})) {
  814. return SupportsType::kNotSupported;
  815. }
  816. }
  817. #if BUILDFLAG(IS_ANDROID)
  818. // TODO(chcunningham): Delete this. Android platform support should be
  819. // handled by (android specific) media::IsSupportedVideoType() above.
  820. if (!IsCodecSupportedOnAndroid(codec, mime_type_lower_case, is_encrypted,
  821. video_profile, platform_info_)) {
  822. return SupportsType::kNotSupported;
  823. }
  824. #endif
  825. return ambiguous_platform_support ? SupportsType::kMaybeSupported
  826. : SupportsType::kSupported;
  827. }
  828. bool MimeUtil::GetDefaultCodec(const std::string& mime_type,
  829. Codec* default_codec) const {
  830. // Codecs below are unambiguously implied by the mime type string. DO NOT add
  831. // default codecs for ambiguous mime types.
  832. if (mime_type == "audio/mpeg" || mime_type == "audio/mp3" ||
  833. mime_type == "audio/x-mp3") {
  834. *default_codec = MimeUtil::MP3;
  835. return true;
  836. }
  837. if (mime_type == "audio/aac") {
  838. *default_codec = MimeUtil::MPEG4_AAC;
  839. return true;
  840. }
  841. if (mime_type == "audio/flac") {
  842. *default_codec = MimeUtil::FLAC;
  843. return true;
  844. }
  845. return false;
  846. }
  847. } // namespace internal
  848. } // namespace media