Revert "[M120 Migration]Fix for crash during chrome exit"
[platform/framework/web/chromium-efl.git] / media / filters / stream_parser_factory.cc
1 // Copyright 2013 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "media/filters/stream_parser_factory.h"
6
7 #include <stddef.h>
8
9 #include <algorithm>
10
11 #include "base/command_line.h"
12 #include "base/containers/span.h"
13 #include "base/memory/raw_ptr_exclusion.h"
14 #include "base/metrics/histogram_macros.h"
15 #include "base/strings/pattern.h"
16 #include "base/strings/string_number_conversions.h"
17 #include "base/strings/string_piece.h"
18 #include "base/strings/string_split.h"
19 #include "base/strings/string_util.h"
20 #include "build/build_config.h"
21 #include "media/base/audio_decoder_config.h"
22 #include "media/base/media.h"
23 #include "media/base/media_switches.h"
24 #include "media/base/media_util.h"
25 #include "media/base/video_codecs.h"
26 #include "media/base/video_decoder_config.h"
27 #include "media/formats/mp4/mp4_stream_parser.h"
28 #include "media/formats/mpeg/adts_stream_parser.h"
29 #include "media/formats/mpeg/mpeg1_audio_stream_parser.h"
30 #include "media/formats/webcodecs/webcodecs_encoded_chunk_stream_parser.h"
31 #include "media/formats/webm/webm_stream_parser.h"
32 #include "media/media_buildflags.h"
33
34 #if BUILDFLAG(IS_ANDROID)
35 #include "media/base/android/media_codec_util.h"
36 #endif
37
38 #if BUILDFLAG(USE_PROPRIETARY_CODECS)
39 #include "media/formats/mp4/es_descriptor.h"
40 #if BUILDFLAG(ENABLE_MSE_MPEG2TS_STREAM_PARSER)
41 #include "media/formats/mp2t/mp2t_stream_parser.h"
42 #endif
43 #endif
44
45 namespace media {
46
47 typedef bool (*CodecIDValidatorFunction)(base::StringPiece codecs_id,
48                                          MediaLog* media_log);
49
50 struct CodecInfo {
51   enum Type { UNKNOWN, AUDIO, VIDEO };
52
53   // Update tools/metrics/histograms/enums.xml if new values are added.
54   enum HistogramTag {
55     HISTOGRAM_UNKNOWN,
56     HISTOGRAM_VP8,
57     HISTOGRAM_VP9,
58     HISTOGRAM_VORBIS,
59     HISTOGRAM_H264,
60     HISTOGRAM_MPEG2AAC,
61     HISTOGRAM_MPEG4AAC,
62     HISTOGRAM_EAC3,
63     HISTOGRAM_MP3,
64     HISTOGRAM_OPUS,
65     HISTOGRAM_HEVC,
66     HISTOGRAM_AC3,
67     HISTOGRAM_DOLBYVISION,
68     HISTOGRAM_FLAC,
69     HISTOGRAM_AV1,
70     HISTOGRAM_MPEG_H_AUDIO,
71     HISTOGRAM_DTS,
72     HISTOGRAM_DTSXP2,
73     HISTOGRAM_DTSE,
74     HISTOGRAM_MAX = HISTOGRAM_DTSE  // Must be equal to largest logged entry.
75   };
76
77   const char* pattern;
78   Type type;
79   CodecIDValidatorFunction validator;
80   HistogramTag tag;
81 };
82
83 typedef StreamParser* (*ParserFactoryFunction)(
84     base::span<const std::string> codecs,
85     MediaLog* media_log);
86
87 struct SupportedTypeInfo {
88   const char* type;
89   const ParserFactoryFunction factory_function;
90   // This field is not a raw_ptr<> because it was filtered by the rewriter for:
91   // #global-scope
92   RAW_PTR_EXCLUSION const CodecInfo* const* codecs;
93 };
94
95 static const CodecInfo kVP8CodecInfo = {"vp8", CodecInfo::VIDEO, nullptr,
96                                         CodecInfo::HISTOGRAM_VP8};
97 static const CodecInfo kLegacyVP9CodecInfo = {"vp9*", CodecInfo::VIDEO, nullptr,
98                                               CodecInfo::HISTOGRAM_VP9};
99 static const CodecInfo kVP9CodecInfo = {"vp09.*", CodecInfo::VIDEO, nullptr,
100                                         CodecInfo::HISTOGRAM_VP9};
101 static const CodecInfo kVorbisCodecInfo = {"vorbis", CodecInfo::AUDIO, nullptr,
102                                            CodecInfo::HISTOGRAM_VORBIS};
103 static const CodecInfo kOpusCodecInfo = {"opus", CodecInfo::AUDIO, nullptr,
104                                          CodecInfo::HISTOGRAM_OPUS};
105 static const CodecInfo kOpusCodecInfo2 = {"Opus", CodecInfo::AUDIO, nullptr,
106                                           CodecInfo::HISTOGRAM_OPUS};
107
108 #if BUILDFLAG(ENABLE_AV1_DECODER)
109 // Note: Validation of the codec string is handled by the caller.
110 static const CodecInfo kAV1CodecInfo = {"av01.*", CodecInfo::VIDEO, nullptr,
111                                         CodecInfo::HISTOGRAM_AV1};
112 #endif
113
114 static const CodecInfo* const kVideoWebMCodecs[] = {
115     &kVP8CodecInfo,  &kLegacyVP9CodecInfo, &kVP9CodecInfo, &kVorbisCodecInfo,
116     &kOpusCodecInfo, &kOpusCodecInfo2,
117 #if BUILDFLAG(ENABLE_AV1_DECODER)
118     &kAV1CodecInfo,
119 #endif
120     nullptr};
121
122 static const CodecInfo* const kAudioWebMCodecs[] = {
123     &kVorbisCodecInfo, &kOpusCodecInfo, &kOpusCodecInfo2, nullptr};
124
125 static StreamParser* BuildWebMParser(base::span<const std::string> codecs,
126                                      MediaLog* media_log) {
127   return new WebMStreamParser();
128 }
129
130 #if BUILDFLAG(USE_PROPRIETARY_CODECS)
131 static int GetMP4AudioObjectType(base::StringPiece codec_id,
132                                  MediaLog* media_log) {
133   // From RFC 6381 section 3.3 (ISO Base Media File Format Name Space):
134   // When the first element of a ['codecs' parameter value] is 'mp4a' ...,
135   // the second element is a hexadecimal representation of the MP4 Registration
136   // Authority ObjectTypeIndication (OTI). Note that MP4RA uses a leading "0x"
137   // with these values, which is omitted here and hence implied.
138   std::vector<base::StringPiece> tokens = base::SplitStringPiece(
139       codec_id, ".", base::KEEP_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
140   if (tokens.size() == 3 && tokens[0] == "mp4a" && tokens[1] == "40") {
141     // From RFC 6381 section 3.3:
142     // One of the OTI values for 'mp4a' is 40 (identifying MPEG-4 audio). For
143     // this value, the third element identifies the audio ObjectTypeIndication
144     // (OTI) ... expressed as a decimal number.
145     int audio_object_type;
146     if (base::StringToInt(tokens[2], &audio_object_type))
147       return audio_object_type;
148   }
149
150   MEDIA_LOG(DEBUG, media_log)
151       << "Malformed mimetype codec '" << codec_id << "'";
152   return -1;
153 }
154
155 // AAC Object Type IDs that Chrome supports.
156 constexpr int kAACLCObjectType = 2;
157 constexpr int kAACSBRObjectType = 5;
158 constexpr int kAACPSObjectType = 29;
159 constexpr int kAACXHEObjectType = 42;
160
161 bool ValidateMP4ACodecID(base::StringPiece codec_id, MediaLog* media_log) {
162   int audio_object_type = GetMP4AudioObjectType(codec_id, media_log);
163   if (audio_object_type == kAACLCObjectType ||
164       audio_object_type == kAACSBRObjectType ||
165       audio_object_type == kAACPSObjectType ||
166       audio_object_type == kAACXHEObjectType) {
167     return true;
168   }
169
170   MEDIA_LOG(DEBUG, media_log)
171       << "Unsupported audio object type " << audio_object_type << " in codec '"
172       << codec_id << "'";
173   return false;
174 }
175
176 static const CodecInfo kH264AVC1CodecInfo = {
177     "avc1.*", CodecInfo::VIDEO, nullptr, CodecInfo::HISTOGRAM_H264};
178 static const CodecInfo kH264AVC3CodecInfo = {
179     "avc3.*", CodecInfo::VIDEO, nullptr, CodecInfo::HISTOGRAM_H264};
180
181 #if BUILDFLAG(ENABLE_PLATFORM_HEVC)
182 static const CodecInfo kHEVCHEV1CodecInfo = {
183     "hev1.*", CodecInfo::VIDEO, nullptr, CodecInfo::HISTOGRAM_HEVC};
184 static const CodecInfo kHEVCHVC1CodecInfo = {
185     "hvc1.*", CodecInfo::VIDEO, nullptr, CodecInfo::HISTOGRAM_HEVC};
186 #endif  // BUILDFLAG(ENABLE_PLATFORM_HEVC)
187 #if BUILDFLAG(ENABLE_PLATFORM_DOLBY_VISION)
188 static const CodecInfo kDolbyVisionAVCCodecInfo1 = {
189     "dva1.*", CodecInfo::VIDEO, nullptr, CodecInfo::HISTOGRAM_DOLBYVISION};
190 static const CodecInfo kDolbyVisionAVCCodecInfo2 = {
191     "dvav.*", CodecInfo::VIDEO, nullptr, CodecInfo::HISTOGRAM_DOLBYVISION};
192 #if BUILDFLAG(ENABLE_PLATFORM_HEVC)
193 static const CodecInfo kDolbyVisionHEVCCodecInfo1 = {
194     "dvh1.*", CodecInfo::VIDEO, nullptr, CodecInfo::HISTOGRAM_DOLBYVISION};
195 static const CodecInfo kDolbyVisionHEVCCodecInfo2 = {
196     "dvhe.*", CodecInfo::VIDEO, nullptr, CodecInfo::HISTOGRAM_DOLBYVISION};
197 #endif  // BUILDFLAG(ENABLE_PLATFORM_HEVC)
198 #endif  // BUILDFLAG(ENABLE_PLATFORM_DOLBY_VISION)
199 static const CodecInfo kMPEG4AACCodecInfo = {"mp4a.40.*", CodecInfo::AUDIO,
200                                              &ValidateMP4ACodecID,
201                                              CodecInfo::HISTOGRAM_MPEG4AAC};
202 static const CodecInfo kMPEG2AACLCCodecInfo = {
203     "mp4a.67", CodecInfo::AUDIO, nullptr, CodecInfo::HISTOGRAM_MPEG2AAC};
204
205 #if BUILDFLAG(ENABLE_PLATFORM_AC3_EAC3_AUDIO)
206 // The 'ac-3' and 'ec-3' are mime codec ids for AC3 and EAC3 according to
207 // http://www.mp4ra.org/codecs.html
208 // The object types for AC3 and EAC3 in MP4 container are 0xa5 and 0xa6, so
209 // according to RFC 6381 this corresponds to codec ids 'mp4a.A5' and 'mp4a.A6'.
210 // Codec ids with lower case oti (mp4a.a5 and mp4a.a6) are supported for
211 // backward compatibility.
212 static const CodecInfo kAC3CodecInfo1 = {"ac-3", CodecInfo::AUDIO, nullptr,
213                                          CodecInfo::HISTOGRAM_AC3};
214 static const CodecInfo kAC3CodecInfo2 = {"mp4a.a5", CodecInfo::AUDIO, nullptr,
215                                          CodecInfo::HISTOGRAM_AC3};
216 static const CodecInfo kAC3CodecInfo3 = {"mp4a.A5", CodecInfo::AUDIO, nullptr,
217                                          CodecInfo::HISTOGRAM_AC3};
218 static const CodecInfo kEAC3CodecInfo1 = {"ec-3", CodecInfo::AUDIO, nullptr,
219                                           CodecInfo::HISTOGRAM_EAC3};
220 static const CodecInfo kEAC3CodecInfo2 = {"mp4a.a6", CodecInfo::AUDIO, nullptr,
221                                           CodecInfo::HISTOGRAM_EAC3};
222 static const CodecInfo kEAC3CodecInfo3 = {"mp4a.A6", CodecInfo::AUDIO, nullptr,
223                                           CodecInfo::HISTOGRAM_EAC3};
224 #endif  // BUILDFLAG(ENABLE_PLATFORM_AC3_EAC3_AUDIO)
225
226 #if BUILDFLAG(ENABLE_PLATFORM_DTS_AUDIO)
227 // The 'dtsc' and 'dtsx' are mime codec ids for DTS and DTSX according to
228 // http://mp4ra.org/#/codecs
229 // The object types for DTS and DTSX in MP4 container are 0xa9 and 0xb2, so
230 // according to RFC 6381 this corresponds to codec ids 'mp4a.A9' and 'mp4a.B2'.
231 // Codec ids with lower case oti (mp4a.a9 and mp4a.b2) are supported for
232 // backward compatibility.
233 static const CodecInfo kDTSCodecInfo1 = {"dtsc", CodecInfo::AUDIO, nullptr,
234                                          CodecInfo::HISTOGRAM_DTS};
235 static const CodecInfo kDTSCodecInfo2 = {"mp4a.a9", CodecInfo::AUDIO, nullptr,
236                                          CodecInfo::HISTOGRAM_DTS};
237 static const CodecInfo kDTSCodecInfo3 = {"mp4a.A9", CodecInfo::AUDIO, nullptr,
238                                          CodecInfo::HISTOGRAM_DTS};
239 static const CodecInfo kDTSXCodecInfo1 = {"dtsx", CodecInfo::AUDIO, nullptr,
240                                           CodecInfo::HISTOGRAM_DTSXP2};
241 static const CodecInfo kDTSXCodecInfo2 = {"mp4a.b2", CodecInfo::AUDIO, nullptr,
242                                           CodecInfo::HISTOGRAM_DTSXP2};
243 static const CodecInfo kDTSXCodecInfo3 = {"mp4a.B2", CodecInfo::AUDIO, nullptr,
244                                           CodecInfo::HISTOGRAM_DTSXP2};
245 static const CodecInfo kDTSECodecInfo1 = {"dtse", CodecInfo::AUDIO, nullptr,
246                                           CodecInfo::HISTOGRAM_DTSE};
247 static const CodecInfo kDTSECodecInfo2 = {"mp4a.ac", CodecInfo::AUDIO, nullptr,
248                                           CodecInfo::HISTOGRAM_DTSE};
249 static const CodecInfo kDTSECodecInfo3 = {"mp4a.AC", CodecInfo::AUDIO, nullptr,
250                                           CodecInfo::HISTOGRAM_DTSE};
251 #endif  // BUILDFLAG(ENABLE_PLATFORM_DTS_AUDIO)
252
253 #if BUILDFLAG(ENABLE_PLATFORM_MPEG_H_AUDIO)
254 static const CodecInfo kMpegHAudioCodecInfo1 = {
255     "mhm1.*", CodecInfo::AUDIO, nullptr, CodecInfo::HISTOGRAM_MPEG_H_AUDIO};
256 static const CodecInfo kMpegHAudioCodecInfo2 = {
257     "mha1.*", CodecInfo::AUDIO, nullptr, CodecInfo::HISTOGRAM_MPEG_H_AUDIO};
258 #endif
259
260 #endif  // BUILDFLAG(USE_PROPRIETARY_CODECS)
261
262 static const CodecInfo kMP3CodecInfo = {nullptr, CodecInfo::AUDIO, nullptr,
263                                         CodecInfo::HISTOGRAM_MP3};
264 static const CodecInfo* const kAudioMP3Codecs[] = {&kMP3CodecInfo, nullptr};
265
266 static StreamParser* BuildMP3Parser(base::span<const std::string> codecs,
267                                     MediaLog* media_log) {
268   return new MPEG1AudioStreamParser();
269 }
270
271 static const CodecInfo kMPEG4VP09CodecInfo = {
272     "vp09.*", CodecInfo::VIDEO, nullptr, CodecInfo::HISTOGRAM_VP9};
273 static const CodecInfo kMPEG4FLACCodecInfo = {"flac", CodecInfo::AUDIO, nullptr,
274                                               CodecInfo::HISTOGRAM_FLAC};
275 static const CodecInfo kMPEG4FLACCodecInfo2 = {
276     "fLaC", CodecInfo::AUDIO, nullptr, CodecInfo::HISTOGRAM_FLAC};
277
278 static const CodecInfo* const kVideoMP4Codecs[] = {&kMPEG4FLACCodecInfo,
279                                                    &kMPEG4FLACCodecInfo2,
280                                                    &kOpusCodecInfo,
281                                                    &kOpusCodecInfo2,
282                                                    &kMPEG4VP09CodecInfo,
283 #if BUILDFLAG(USE_PROPRIETARY_CODECS)
284                                                    &kH264AVC1CodecInfo,
285                                                    &kH264AVC3CodecInfo,
286 #if BUILDFLAG(ENABLE_PLATFORM_HEVC)
287                                                    &kHEVCHEV1CodecInfo,
288                                                    &kHEVCHVC1CodecInfo,
289 #endif
290 #if BUILDFLAG(ENABLE_PLATFORM_DOLBY_VISION)
291                                                    &kDolbyVisionAVCCodecInfo1,
292                                                    &kDolbyVisionAVCCodecInfo2,
293 #if BUILDFLAG(ENABLE_PLATFORM_HEVC)
294                                                    &kDolbyVisionHEVCCodecInfo1,
295                                                    &kDolbyVisionHEVCCodecInfo2,
296 #endif
297 #endif
298                                                    &kMPEG4AACCodecInfo,
299                                                    &kMPEG2AACLCCodecInfo,
300 #if BUILDFLAG(ENABLE_PLATFORM_MPEG_H_AUDIO)
301                                                    &kMpegHAudioCodecInfo1,
302                                                    &kMpegHAudioCodecInfo2,
303 #endif
304 #endif  // BUILDFLAG(USE_PROPRIETARY_CODECS)
305 #if BUILDFLAG(ENABLE_AV1_DECODER)
306                                                    &kAV1CodecInfo,
307 #endif
308                                                    nullptr};
309
310 static const CodecInfo* const kAudioMP4Codecs[] = {&kMPEG4FLACCodecInfo,
311                                                    &kMPEG4FLACCodecInfo2,
312                                                    &kOpusCodecInfo,
313                                                    &kOpusCodecInfo2,
314 #if BUILDFLAG(USE_PROPRIETARY_CODECS)
315                                                    &kMPEG4AACCodecInfo,
316                                                    &kMPEG2AACLCCodecInfo,
317 #if BUILDFLAG(ENABLE_PLATFORM_MPEG_H_AUDIO)
318                                                    &kMpegHAudioCodecInfo1,
319                                                    &kMpegHAudioCodecInfo2,
320 #endif
321 #if BUILDFLAG(ENABLE_PLATFORM_AC3_EAC3_AUDIO)
322                                                    &kAC3CodecInfo1,
323                                                    &kAC3CodecInfo2,
324                                                    &kAC3CodecInfo3,
325                                                    &kEAC3CodecInfo1,
326                                                    &kEAC3CodecInfo2,
327                                                    &kEAC3CodecInfo3,
328 #endif  // BUILDFLAG(ENABLE_PLATFORM_AC3_EAC3_AUDIO)
329 #if BUILDFLAG(ENABLE_PLATFORM_DTS_AUDIO)
330                                                    &kDTSCodecInfo1,
331                                                    &kDTSCodecInfo2,
332                                                    &kDTSCodecInfo3,
333                                                    &kDTSXCodecInfo1,
334                                                    &kDTSXCodecInfo2,
335                                                    &kDTSXCodecInfo3,
336                                                    &kDTSECodecInfo1,
337                                                    &kDTSECodecInfo2,
338                                                    &kDTSECodecInfo3,
339 #endif  // BUILDFLAG(ENABLE_PLATFORM_DTS_AUDIO)
340 #endif  // BUILDFLAG(USE_PROPRIETARY_CODECS)
341                                                    nullptr};
342
343 static StreamParser* BuildMP4Parser(base::span<const std::string> codecs,
344                                     MediaLog* media_log) {
345   std::set<int> audio_object_types;
346   bool has_sbr = false;
347
348   // The draft version 0.0.4 FLAC-in-ISO spec
349   // (https://github.com/xiph/flac/blob/master/doc/isoflac.txt) does not define
350   // any encapsulation using MP4AudioSampleEntry with objectTypeIndication.
351   // Rather, it uses a FLAC-specific "fLaC" codingname in the sample entry along
352   // with a "dfLa" FLACSpecificBox. We still need to tell our parser to
353   // conditionally expect a FLAC stream, hence |has_flac|.
354   bool has_flac = false;
355
356   for (const auto& codec_id : codecs) {
357     if (base::MatchPattern(codec_id, kMPEG4FLACCodecInfo.pattern) ||
358         base::MatchPattern(codec_id, kMPEG4FLACCodecInfo2.pattern)) {
359       has_flac = true;
360 #if BUILDFLAG(USE_PROPRIETARY_CODECS)
361     } else if (base::MatchPattern(codec_id, kMPEG2AACLCCodecInfo.pattern)) {
362       audio_object_types.insert(mp4::kISO_13818_7_AAC_LC);
363     } else if (base::MatchPattern(codec_id, kMPEG4AACCodecInfo.pattern)) {
364       int audio_object_type = GetMP4AudioObjectType(codec_id, media_log);
365       DCHECK_GT(audio_object_type, 0);
366
367       audio_object_types.insert(mp4::kISO_14496_3);
368
369       if (audio_object_type == kAACSBRObjectType ||
370           audio_object_type == kAACPSObjectType) {
371         has_sbr = true;
372         break;
373       }
374 #if BUILDFLAG(ENABLE_PLATFORM_AC3_EAC3_AUDIO)
375     } else if (base::MatchPattern(codec_id, kAC3CodecInfo1.pattern) ||
376                base::MatchPattern(codec_id, kAC3CodecInfo2.pattern) ||
377                base::MatchPattern(codec_id, kAC3CodecInfo3.pattern)) {
378       audio_object_types.insert(mp4::kAC3);
379     } else if (base::MatchPattern(codec_id, kEAC3CodecInfo1.pattern) ||
380                base::MatchPattern(codec_id, kEAC3CodecInfo2.pattern) ||
381                base::MatchPattern(codec_id, kEAC3CodecInfo3.pattern)) {
382       audio_object_types.insert(mp4::kEAC3);
383 #endif  // BUILDFLAG(ENABLE_PLATFORM_AC3_EAC3_AUDIO)
384 #if BUILDFLAG(ENABLE_PLATFORM_DTS_AUDIO)
385     } else if (base::MatchPattern(codec_id, kDTSCodecInfo1.pattern) ||
386                base::MatchPattern(codec_id, kDTSCodecInfo2.pattern) ||
387                base::MatchPattern(codec_id, kDTSCodecInfo3.pattern)) {
388       audio_object_types.insert(mp4::kDTS);
389     } else if (base::MatchPattern(codec_id, kDTSXCodecInfo1.pattern) ||
390                base::MatchPattern(codec_id, kDTSXCodecInfo2.pattern) ||
391                base::MatchPattern(codec_id, kDTSXCodecInfo3.pattern)) {
392       audio_object_types.insert(mp4::kDTSX);
393     } else if (base::MatchPattern(codec_id, kDTSECodecInfo1.pattern) ||
394                base::MatchPattern(codec_id, kDTSECodecInfo2.pattern) ||
395                base::MatchPattern(codec_id, kDTSECodecInfo3.pattern)) {
396       audio_object_types.insert(mp4::kDTSE);
397 #endif  // BUILDFLAG(ENABLE_PLATFORM_DTS_AUDIO)
398 #endif  // BUILDFLAG(USE_PROPRIETARY_CODECS)
399     }
400   }
401
402   return new mp4::MP4StreamParser(audio_object_types, has_sbr, has_flac);
403 }
404 #if BUILDFLAG(USE_PROPRIETARY_CODECS)
405 static const CodecInfo kADTSCodecInfo = {nullptr, CodecInfo::AUDIO, nullptr,
406                                          CodecInfo::HISTOGRAM_MPEG4AAC};
407 static const CodecInfo* const kAudioADTSCodecs[] = {&kADTSCodecInfo, nullptr};
408
409 static StreamParser* BuildADTSParser(base::span<const std::string> codecs,
410                                      MediaLog* media_log) {
411   return new ADTSStreamParser();
412 }
413
414 #if BUILDFLAG(ENABLE_MSE_MPEG2TS_STREAM_PARSER)
415 // These codec ids correspond to object types registered with MP4RA and are the
416 // same as MP3 audio codec ids in media/base/mime_util_internal.cc.
417 // From http://www.mp4ra.org/object.html:
418 // 69   Audio ISO/IEC 13818-3
419 // 6B   Audio ISO/IEC 11172-3
420 static const CodecInfo kMPEG2TS_MP3CodecInfo1 = {
421     "mp4a.69", CodecInfo::AUDIO, nullptr, CodecInfo::HISTOGRAM_MP3};
422 static const CodecInfo kMPEG2TS_MP3CodecInfo2 = {
423     "mp4a.6B", CodecInfo::AUDIO, nullptr, CodecInfo::HISTOGRAM_MP3};
424
425 static const CodecInfo* const kVideoMP2TCodecs[] = {&kH264AVC1CodecInfo,
426                                                     &kH264AVC3CodecInfo,
427                                                     &kMPEG2TS_MP3CodecInfo1,
428                                                     &kMPEG2TS_MP3CodecInfo2,
429                                                     &kMPEG4AACCodecInfo,
430                                                     &kMPEG2AACLCCodecInfo,
431                                                     nullptr};
432
433 static StreamParser* BuildMP2TParser(base::span<const std::string> codecs,
434                                      MediaLog* media_log) {
435   bool has_sbr = false;
436   for (const auto& codec_id : codecs) {
437     if (base::MatchPattern(codec_id, kMPEG4AACCodecInfo.pattern)) {
438       int audio_object_type = GetMP4AudioObjectType(codec_id, media_log);
439       if (audio_object_type == kAACSBRObjectType ||
440           audio_object_type == kAACPSObjectType) {
441         has_sbr = true;
442       }
443     }
444   }
445
446   return new media::mp2t::Mp2tStreamParser(codecs, has_sbr);
447 }
448 #endif  // ENABLE_MSE_MPEG2TS_STREAM_PARSER
449 #endif  // BUILDFLAG(USE_PROPRIETARY_CODECS)
450
451 static const SupportedTypeInfo kSupportedTypeInfo[] = {
452     {"video/webm", &BuildWebMParser, kVideoWebMCodecs},
453     {"audio/webm", &BuildWebMParser, kAudioWebMCodecs},
454     {"audio/mpeg", &BuildMP3Parser, kAudioMP3Codecs},
455     // NOTE: Including proprietary MP4 codecs is gated by build flags above.
456     {"video/mp4", &BuildMP4Parser, kVideoMP4Codecs},
457     {"audio/mp4", &BuildMP4Parser, kAudioMP4Codecs},
458 #if BUILDFLAG(USE_PROPRIETARY_CODECS)
459     {"audio/aac", &BuildADTSParser, kAudioADTSCodecs},
460 #if BUILDFLAG(ENABLE_MSE_MPEG2TS_STREAM_PARSER)
461     {"video/mp2t", &BuildMP2TParser, kVideoMP2TCodecs},
462 #endif
463 #endif
464 };
465
466 // Verify that |codec_info| is supported on this platform.
467 //
468 // Returns true if |codec_info| is a valid audio/video codec and is allowed.
469 // |audio_codecs| has |codec_info|.tag added to its list if |codec_info| is an
470 // audio codec. |audio_codecs| may be nullptr, in which case it is not updated.
471 // |video_codecs| has |codec_info|.tag added to its list if |codec_info| is a
472 // video codec. |video_codecs| may be nullptr, in which case it is not updated.
473 //
474 // Returns false otherwise, and |audio_codecs| and |video_codecs| not touched.
475 static bool VerifyCodec(const CodecInfo* codec_info,
476                         std::vector<CodecInfo::HistogramTag>* audio_codecs,
477                         std::vector<CodecInfo::HistogramTag>* video_codecs) {
478   switch (codec_info->type) {
479     case CodecInfo::AUDIO:
480       if (audio_codecs)
481         audio_codecs->push_back(codec_info->tag);
482       return true;
483     case CodecInfo::VIDEO:
484       if (video_codecs)
485         video_codecs->push_back(codec_info->tag);
486       return true;
487     default:
488       // Not audio or video, so skip it.
489       DVLOG(1) << "CodecInfo type of " << codec_info->type
490                << " should not be specified in a SupportedTypes list";
491       return false;
492   }
493 }
494
495 // Checks to see if the specified |type| and |codecs| list are supported.
496 // Returns kNotSupported if |type| and |codecs| are definitively not supported.
497 // The values of |factory_function|, |audio_codecs|, and |video_codecs| are
498 // undefined in this case.
499 // Returns kSupported if |type| and all codecs listed in |codecs| are
500 // supported, any non-empty codecs requirement is met for |type|, and all of
501 // |codecs| are supported for |type|.
502 // Returns kMaybeSupported if |type| is supported, but requires a codecs
503 // parameter that is missing.
504 // For both kSupported and kMaybeSupported results, |factory_function| is
505 // updated to be a function that can build a StreamParser for this type,
506 // |audio_codecs| is updated with the appropriate HistogramTags for matching
507 // audio codecs specified in |codecs|, and |video_codecs| is updated with the
508 // appropriate HistogramTags for matching video codecs specified in |codecs|.
509 // The value of each of |factory_function|, |audio_codecs| and |video_codecs| is
510 // not updated if it was nullptr initially.
511 static SupportsType CheckTypeAndCodecs(
512     base::StringPiece type,
513     base::span<const std::string> codecs,
514     MediaLog* media_log,
515     ParserFactoryFunction* factory_function,
516     std::vector<CodecInfo::HistogramTag>* audio_codecs,
517     std::vector<CodecInfo::HistogramTag>* video_codecs) {
518   // Search for the SupportedTypeInfo for |type|.
519   for (const auto& type_info : kSupportedTypeInfo) {
520     if (type == type_info.type) {
521       if (codecs.empty()) {
522         const CodecInfo* codec_info = type_info.codecs[0];
523         if (codec_info && !codec_info->pattern &&
524             VerifyCodec(codec_info, audio_codecs, video_codecs)) {
525           // If there was no specified codec parameter, and if the major/minor
526           // type is supported, specific and requires no codec parameter (such
527           // as audio/mpeg is specific to MP3), then populate the expected
528           // specific codec value and factory function and return definitive
529           // support.
530           if (factory_function)
531             *factory_function = type_info.factory_function;
532           return SupportsType::kSupported;
533         }
534
535         MEDIA_LOG(DEBUG, media_log)
536             << "A codecs parameter must be provided for '" << type
537             << "' to determine definitive support proactively.";
538         return SupportsType::kMaybeSupported;
539       }
540
541       // Make sure all the codecs specified in |codecs| are
542       // in the supported type info.
543       for (const auto& codec_id : codecs) {
544         // Search the type info for a match.
545         bool found_codec = false;
546         for (int i = 0; type_info.codecs[i]; ++i) {
547           // Only check a codec pattern if there is one to check. Some types,
548           // like audio/mpeg and audio/aac require there be no codecs parameter,
549           // and instead have implicit codec. If a codec is provided for such a
550           // type then it is not supported by MSE. We don't check any other
551           // potential matches because none should be configured.
552           if (!type_info.codecs[i]->pattern) {
553             DCHECK(i == 0 && !type_info.codecs[1])
554                 << "For a type with implicit codec, then only one codec must "
555                    "be configured";
556             break;
557           }
558
559           if (base::MatchPattern(codec_id, type_info.codecs[i]->pattern) &&
560               (!type_info.codecs[i]->validator ||
561                type_info.codecs[i]->validator(codec_id, media_log))) {
562             found_codec =
563                 VerifyCodec(type_info.codecs[i], audio_codecs, video_codecs);
564             break;  // Since only 1 pattern will match, no need to check others.
565           }
566         }
567
568         if (!found_codec) {
569           MEDIA_LOG(DEBUG, media_log)
570               << "Codec '" << codec_id << "' is not supported for '" << type
571               << "'";
572           // Though the major/minor type is supported, a codecs parameter value
573           // was found to not be supported.
574           return SupportsType::kNotSupported;
575         }
576       }
577
578       if (factory_function)
579         *factory_function = type_info.factory_function;
580
581       // There was a non-empty |codecs| for this supported |type|, and all of
582       // |codecs| are supported for this |type|.
583       return SupportsType::kSupported;
584     }
585   }
586
587   // |type| didn't match any of the supported types.
588   return SupportsType::kNotSupported;
589 }
590
591 // static
592 SupportsType StreamParserFactory::IsTypeSupported(
593     base::StringPiece type,
594     base::span<const std::string> codecs) {
595   // TODO(wolenetz): Questionable MediaLog usage, http://crbug.com/712310
596   NullMediaLog media_log;
597   return CheckTypeAndCodecs(type, codecs, &media_log, nullptr, nullptr,
598                             nullptr);
599 }
600
601 // static
602 std::unique_ptr<StreamParser> StreamParserFactory::Create(
603     base::StringPiece type,
604     base::span<const std::string> codecs,
605     MediaLog* media_log,
606     bool* has_audio,
607     bool* has_video) {
608   std::unique_ptr<StreamParser> stream_parser;
609   ParserFactoryFunction factory_function;
610   std::vector<CodecInfo::HistogramTag> audio_codecs;
611   std::vector<CodecInfo::HistogramTag> video_codecs;
612
613   // TODO(crbug.com/535738): Relax the requirement for specific codecs (allow
614   // kMaybeSupported here), and relocate the logging to the parser configuration
615   // callback. This creation method is called in AddId(), and also in
616   // CanChangeType() and ChangeType(), so potentially overlogs codecs leading to
617   // disproportion versus actually parsed codec configurations from
618   // initialization segments. For this work and also recording when implicit
619   // codec switching occurs (without explicit ChangeType), see
620   // https://crbug.com/535738.
621   SupportsType supportsType = CheckTypeAndCodecs(
622       type, codecs, media_log, &factory_function, &audio_codecs, &video_codecs);
623
624   if (SupportsType::kSupported == supportsType) {
625     // Log the expected codecs.
626     for (size_t i = 0; i < audio_codecs.size(); ++i) {
627       UMA_HISTOGRAM_ENUMERATION("Media.MSE.AudioCodec", audio_codecs[i],
628                                 CodecInfo::HISTOGRAM_MAX + 1);
629     }
630     for (size_t i = 0; i < video_codecs.size(); ++i) {
631       UMA_HISTOGRAM_ENUMERATION("Media.MSE.VideoCodec", video_codecs[i],
632                                 CodecInfo::HISTOGRAM_MAX + 1);
633       if (type == "video/mp4") {
634         UMA_HISTOGRAM_ENUMERATION("Media.MSE.VideoCodec.MP4", video_codecs[i],
635                                   CodecInfo::HISTOGRAM_MAX + 1);
636       } else if (type == "video/webm") {
637         UMA_HISTOGRAM_ENUMERATION("Media.MSE.VideoCodec.WebM", video_codecs[i],
638                                   CodecInfo::HISTOGRAM_MAX + 1);
639       }
640     }
641
642     *has_audio = !audio_codecs.empty();
643     *has_video = !video_codecs.empty();
644     stream_parser.reset(factory_function(codecs, media_log));
645   }
646
647   return stream_parser;
648 }
649
650 // static
651 std::unique_ptr<StreamParser> StreamParserFactory::Create(
652     std::unique_ptr<AudioDecoderConfig> audio_config) {
653   DCHECK(audio_config);
654
655   // TODO(crbug.com/1144908): Histogram-log the codec used for buffering
656   // WebCodecs in MSE?
657
658   return std::make_unique<media::WebCodecsEncodedChunkStreamParser>(
659       std::move(audio_config));
660 }
661
662 // static
663 std::unique_ptr<StreamParser> StreamParserFactory::Create(
664     std::unique_ptr<VideoDecoderConfig> video_config) {
665   DCHECK(video_config);
666
667   // TODO(crbug.com/1144908): Histogram-log the codec used for buffering
668   // WebCodecs in MSE?
669
670   return std::make_unique<media::WebCodecsEncodedChunkStreamParser>(
671       std::move(video_config));
672 }
673
674 }  // namespace media