#ifdef UNSAFE_BUFFERS_BUILD
#pragma allow_unsafe_buffers
#endif
#include "media/filters/stream_parser_factory.h"
#include <stddef.h>
#include <algorithm>
#include "base/command_line.h"
#include "base/containers/span.h"
#include "base/memory/ptr_util.h"
#include "base/memory/raw_ptr_exclusion.h"
#include "base/metrics/histogram_macros.h"
#include "base/strings/pattern.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_split.h"
#include "base/strings/string_util.h"
#include "build/build_config.h"
#include "media/base/audio_decoder_config.h"
#include "media/base/media.h"
#include "media/base/media_switches.h"
#include "media/base/media_util.h"
#include "media/base/video_codecs.h"
#include "media/base/video_decoder_config.h"
#include "media/formats/mp4/mp4_stream_parser.h"
#include "media/formats/mpeg/adts_stream_parser.h"
#include "media/formats/mpeg/mpeg1_audio_stream_parser.h"
#include "media/formats/webcodecs/webcodecs_encoded_chunk_stream_parser.h"
#include "media/formats/webm/webm_stream_parser.h"
#include "media/media_buildflags.h"
#if BUILDFLAG(IS_ANDROID)
#include "media/base/android/media_codec_util.h"
#endif
#if BUILDFLAG(USE_PROPRIETARY_CODECS)
#include "media/formats/mp4/es_descriptor.h"
#if BUILDFLAG(ENABLE_MSE_MPEG2TS_STREAM_PARSER)
#include "media/formats/mp2t/mp2t_stream_parser.h"
#endif
#endif
namespace media {
CodecIDValidatorFunction;
struct CodecInfo { … };
ParserFactoryFunction;
struct SupportedTypeInfo { … };
static const CodecInfo kVP8CodecInfo = …;
static const CodecInfo kLegacyVP9CodecInfo = …;
static const CodecInfo kVP9CodecInfo = …;
static const CodecInfo kVorbisCodecInfo = …;
static const CodecInfo kOpusCodecInfo = …;
static const CodecInfo kOpusCodecInfo2 = …;
#if BUILDFLAG(ENABLE_AV1_DECODER)
static const CodecInfo kAV1CodecInfo = …;
#endif
static const CodecInfo* const kVideoWebMCodecs[] = …;
static const CodecInfo* const kAudioWebMCodecs[] = …;
static StreamParser* BuildWebMParser(base::span<const std::string> codecs,
MediaLog* media_log) { … }
#if BUILDFLAG(USE_PROPRIETARY_CODECS)
static int GetMP4AudioObjectType(std::string_view codec_id,
MediaLog* media_log) {
std::vector<std::string_view> tokens = base::SplitStringPiece(
codec_id, ".", base::KEEP_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
if (tokens.size() == 3 && tokens[0] == "mp4a" && tokens[1] == "40") {
int audio_object_type;
if (base::StringToInt(tokens[2], &audio_object_type))
return audio_object_type;
}
MEDIA_LOG(DEBUG, media_log)
<< "Malformed mimetype codec '" << codec_id << "'";
return -1;
}
constexpr int kAACLCObjectType = 2;
constexpr int kAACSBRObjectType = 5;
constexpr int kAACPSObjectType = 29;
constexpr int kAACXHEObjectType = 42;
bool ValidateMP4ACodecID(std::string_view codec_id, MediaLog* media_log) {
int audio_object_type = GetMP4AudioObjectType(codec_id, media_log);
if (audio_object_type == kAACLCObjectType ||
audio_object_type == kAACSBRObjectType ||
audio_object_type == kAACPSObjectType ||
audio_object_type == kAACXHEObjectType) {
return true;
}
MEDIA_LOG(DEBUG, media_log)
<< "Unsupported audio object type " << audio_object_type << " in codec '"
<< codec_id << "'";
return false;
}
static const CodecInfo kH264AVC1CodecInfo = {
"avc1.*", CodecInfo::VIDEO, nullptr, CodecInfo::HISTOGRAM_H264};
static const CodecInfo kH264AVC3CodecInfo = {
"avc3.*", CodecInfo::VIDEO, nullptr, CodecInfo::HISTOGRAM_H264};
#if BUILDFLAG(ENABLE_PLATFORM_HEVC)
static const CodecInfo kHEVCHEV1CodecInfo = {
"hev1.*", CodecInfo::VIDEO, nullptr, CodecInfo::HISTOGRAM_HEVC};
static const CodecInfo kHEVCHVC1CodecInfo = {
"hvc1.*", CodecInfo::VIDEO, nullptr, CodecInfo::HISTOGRAM_HEVC};
#endif
#if BUILDFLAG(ENABLE_PLATFORM_DOLBY_VISION)
static const CodecInfo kDolbyVisionAVCCodecInfo1 = {
"dva1.*", CodecInfo::VIDEO, nullptr, CodecInfo::HISTOGRAM_DOLBYVISION};
static const CodecInfo kDolbyVisionAVCCodecInfo2 = {
"dvav.*", CodecInfo::VIDEO, nullptr, CodecInfo::HISTOGRAM_DOLBYVISION};
#if BUILDFLAG(ENABLE_PLATFORM_HEVC)
static const CodecInfo kDolbyVisionHEVCCodecInfo1 = {
"dvh1.*", CodecInfo::VIDEO, nullptr, CodecInfo::HISTOGRAM_DOLBYVISION};
static const CodecInfo kDolbyVisionHEVCCodecInfo2 = {
"dvhe.*", CodecInfo::VIDEO, nullptr, CodecInfo::HISTOGRAM_DOLBYVISION};
#endif
#endif
static const CodecInfo kMPEG4AACCodecInfo = {"mp4a.40.*", CodecInfo::AUDIO,
&ValidateMP4ACodecID,
CodecInfo::HISTOGRAM_MPEG4AAC};
static const CodecInfo kMPEG2AACLCCodecInfo = {
"mp4a.67", CodecInfo::AUDIO, nullptr, CodecInfo::HISTOGRAM_MPEG2AAC};
#if BUILDFLAG(ENABLE_PLATFORM_AC3_EAC3_AUDIO)
static const CodecInfo kAC3CodecInfo1 = {"ac-3", CodecInfo::AUDIO, nullptr,
CodecInfo::HISTOGRAM_AC3};
static const CodecInfo kAC3CodecInfo2 = {"mp4a.a5", CodecInfo::AUDIO, nullptr,
CodecInfo::HISTOGRAM_AC3};
static const CodecInfo kAC3CodecInfo3 = {"mp4a.A5", CodecInfo::AUDIO, nullptr,
CodecInfo::HISTOGRAM_AC3};
static const CodecInfo kEAC3CodecInfo1 = {"ec-3", CodecInfo::AUDIO, nullptr,
CodecInfo::HISTOGRAM_EAC3};
static const CodecInfo kEAC3CodecInfo2 = {"mp4a.a6", CodecInfo::AUDIO, nullptr,
CodecInfo::HISTOGRAM_EAC3};
static const CodecInfo kEAC3CodecInfo3 = {"mp4a.A6", CodecInfo::AUDIO, nullptr,
CodecInfo::HISTOGRAM_EAC3};
#endif
#if BUILDFLAG(ENABLE_PLATFORM_AC4_AUDIO)
static const CodecInfo kAC4CodecInfo1 = {"ac-4.*", CodecInfo::AUDIO, nullptr,
CodecInfo::HISTOGRAM_AC4};
static const CodecInfo kAC4CodecInfo2 = {"mp4a.ae.*", CodecInfo::AUDIO, nullptr,
CodecInfo::HISTOGRAM_AC4};
static const CodecInfo kAC4CodecInfo3 = {"mp4a.AE.*", CodecInfo::AUDIO, nullptr,
CodecInfo::HISTOGRAM_AC4};
static const CodecInfo kAC4CodecInfo4 = {"ac-4", CodecInfo::AUDIO, nullptr,
CodecInfo::HISTOGRAM_AC4};
static const CodecInfo kAC4CodecInfo5 = {"mp4a.ae", CodecInfo::AUDIO, nullptr,
CodecInfo::HISTOGRAM_AC4};
static const CodecInfo kAC4CodecInfo6 = {"mp4a.AE", CodecInfo::AUDIO, nullptr,
CodecInfo::HISTOGRAM_AC4};
#endif
#if BUILDFLAG(ENABLE_PLATFORM_DTS_AUDIO)
static const CodecInfo kDTSCodecInfo1 = {"dtsc", CodecInfo::AUDIO, nullptr,
CodecInfo::HISTOGRAM_DTS};
static const CodecInfo kDTSCodecInfo2 = {"mp4a.a9", CodecInfo::AUDIO, nullptr,
CodecInfo::HISTOGRAM_DTS};
static const CodecInfo kDTSCodecInfo3 = {"mp4a.A9", CodecInfo::AUDIO, nullptr,
CodecInfo::HISTOGRAM_DTS};
static const CodecInfo kDTSXCodecInfo1 = {"dtsx", CodecInfo::AUDIO, nullptr,
CodecInfo::HISTOGRAM_DTSXP2};
static const CodecInfo kDTSXCodecInfo2 = {"mp4a.b2", CodecInfo::AUDIO, nullptr,
CodecInfo::HISTOGRAM_DTSXP2};
static const CodecInfo kDTSXCodecInfo3 = {"mp4a.B2", CodecInfo::AUDIO, nullptr,
CodecInfo::HISTOGRAM_DTSXP2};
static const CodecInfo kDTSECodecInfo1 = {"dtse", CodecInfo::AUDIO, nullptr,
CodecInfo::HISTOGRAM_DTSE};
static const CodecInfo kDTSECodecInfo2 = {"mp4a.ac", CodecInfo::AUDIO, nullptr,
CodecInfo::HISTOGRAM_DTSE};
static const CodecInfo kDTSECodecInfo3 = {"mp4a.AC", CodecInfo::AUDIO, nullptr,
CodecInfo::HISTOGRAM_DTSE};
#endif
#if BUILDFLAG(ENABLE_PLATFORM_MPEG_H_AUDIO)
static const CodecInfo kMpegHAudioCodecInfo1 = {
"mhm1.*", CodecInfo::AUDIO, nullptr, CodecInfo::HISTOGRAM_MPEG_H_AUDIO};
static const CodecInfo kMpegHAudioCodecInfo2 = {
"mha1.*", CodecInfo::AUDIO, nullptr, CodecInfo::HISTOGRAM_MPEG_H_AUDIO};
#endif
#endif
static const CodecInfo kMP3CodecInfo = …;
static const CodecInfo* const kAudioMP3Codecs[] = …;
static StreamParser* BuildMP3Parser(base::span<const std::string> codecs,
MediaLog* media_log) { … }
static const CodecInfo kMPEG4VP09CodecInfo = …;
static const CodecInfo kMPEG4FLACCodecInfo = …;
static const CodecInfo kMPEG4FLACCodecInfo2 = …;
#if BUILDFLAG(ENABLE_PLATFORM_IAMF_AUDIO)
static const CodecInfo kIAMFCodecInfo1 = {"iamf", CodecInfo::AUDIO, nullptr,
CodecInfo::HISTOGRAM_IAMF};
static const CodecInfo kIAMFCodecInfo2 = {"iamf.*", CodecInfo::AUDIO, nullptr,
CodecInfo::HISTOGRAM_IAMF};
#endif
static const CodecInfo* const kVideoMP4Codecs[] = …;
static const CodecInfo* const kAudioMP4Codecs[] = …;
static StreamParser* BuildMP4Parser(base::span<const std::string> codecs,
MediaLog* media_log) { … }
#if BUILDFLAG(USE_PROPRIETARY_CODECS)
static const CodecInfo kADTSCodecInfo = {nullptr, CodecInfo::AUDIO, nullptr,
CodecInfo::HISTOGRAM_MPEG4AAC};
static const CodecInfo* const kAudioADTSCodecs[] = {&kADTSCodecInfo, nullptr};
static StreamParser* BuildADTSParser(base::span<const std::string> codecs,
MediaLog* media_log) {
return new ADTSStreamParser();
}
#if BUILDFLAG(ENABLE_MSE_MPEG2TS_STREAM_PARSER)
static const CodecInfo kMPEG2TS_MP3CodecInfo1 = {
"mp4a.69", CodecInfo::AUDIO, nullptr, CodecInfo::HISTOGRAM_MP3};
static const CodecInfo kMPEG2TS_MP3CodecInfo2 = {
"mp4a.6B", CodecInfo::AUDIO, nullptr, CodecInfo::HISTOGRAM_MP3};
static const CodecInfo* const kVideoMP2TCodecs[] = {&kH264AVC1CodecInfo,
&kH264AVC3CodecInfo,
&kMPEG2TS_MP3CodecInfo1,
&kMPEG2TS_MP3CodecInfo2,
&kMPEG4AACCodecInfo,
&kMPEG2AACLCCodecInfo,
nullptr};
static StreamParser* BuildMP2TParser(base::span<const std::string> codecs,
MediaLog* media_log) {
bool has_sbr = false;
for (const auto& codec_id : codecs) {
if (base::MatchPattern(codec_id, kMPEG4AACCodecInfo.pattern)) {
int audio_object_type = GetMP4AudioObjectType(codec_id, media_log);
if (audio_object_type == kAACSBRObjectType ||
audio_object_type == kAACPSObjectType) {
has_sbr = true;
}
}
}
return new media::mp2t::Mp2tStreamParser(codecs, has_sbr);
}
#endif
#endif
static const SupportedTypeInfo kSupportedTypeInfo[] = …;
#if BUILDFLAG(ENABLE_HLS_DEMUXER)
std::unique_ptr<StreamParser> StreamParserFactory::CreateRelaxedParser(
RelaxedParserSupportedType mime) {
const bool enable_mp4 = base::FeatureList::IsEnabled(kBuiltInHlsMP4);
switch (mime) {
case RelaxedParserSupportedType::kMP2T: {
return std::make_unique<mp2t::Mp2tStreamParser>(std::nullopt, false);
}
case RelaxedParserSupportedType::kAAC: {
return std::make_unique<ADTSStreamParser>();
}
case RelaxedParserSupportedType::kMP4: {
return enable_mp4 ? std::make_unique<mp4::MP4StreamParser>(
std::nullopt, false, true, false, false)
: nullptr;
}
}
}
#endif
static bool VerifyCodec(const CodecInfo* codec_info,
std::vector<CodecInfo::HistogramTag>* audio_codecs,
std::vector<CodecInfo::HistogramTag>* video_codecs) { … }
static SupportsType CheckTypeAndCodecs(
std::string_view type,
base::span<const std::string> codecs,
MediaLog* media_log,
ParserFactoryFunction* factory_function,
std::vector<CodecInfo::HistogramTag>* audio_codecs,
std::vector<CodecInfo::HistogramTag>* video_codecs) { … }
SupportsType StreamParserFactory::IsTypeSupported(
std::string_view type,
base::span<const std::string> codecs) { … }
std::unique_ptr<StreamParser> StreamParserFactory::Create(
std::string_view type,
base::span<const std::string> codecs,
MediaLog* media_log) { … }
std::unique_ptr<StreamParser> StreamParserFactory::Create(
std::unique_ptr<AudioDecoderConfig> audio_config) { … }
std::unique_ptr<StreamParser> StreamParserFactory::Create(
std::unique_ptr<VideoDecoderConfig> video_config) { … }
}