| Index: media/filters/stream_parser_factory.cc
|
| diff --git a/media/filters/stream_parser_factory.cc b/media/filters/stream_parser_factory.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..0cd8b9a0b435ba1fecc4ddb07cc2d8ee848ea2cc
|
| --- /dev/null
|
| +++ b/media/filters/stream_parser_factory.cc
|
| @@ -0,0 +1,256 @@
|
| +// Copyright (c) 2013 The Chromium Authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +#include "media/filters/stream_parser_factory.h"
|
| +
|
| +#include "base/string_number_conversions.h"
|
| +#include "base/string_util.h"
|
| +#include "media/base/media_log.h"
|
| +#include "media/webm/webm_stream_parser.h"
|
| +
|
| +#if defined(GOOGLE_CHROME_BUILD) || defined(USE_PROPRIETARY_CODECS)
|
| +#include "media/mp4/es_descriptor.h"
|
| +#include "media/mp4/mp4_stream_parser.h"
|
| +#endif
|
| +
|
| +namespace media {
|
| +
|
| +typedef bool (*CodecIDValidatorFunction)(
|
| + const std::string& codecs_id, const media::LogCB& log_cb);
|
| +
|
| +struct CodecInfo {
|
| + enum Type {
|
| + UNKNOWN,
|
| + AUDIO,
|
| + VIDEO
|
| + };
|
| +
|
| + const char* pattern;
|
| + Type type;
|
| + CodecIDValidatorFunction validator;
|
| +};
|
| +
|
| +typedef media::StreamParser* (*ParserFactoryFunction)(
|
| + const std::vector<std::string>& codecs,
|
| + const media::LogCB& log_cb);
|
| +
|
| +struct SupportedTypeInfo {
|
| + const char* type;
|
| + const ParserFactoryFunction factory_function;
|
| + const CodecInfo** codecs;
|
| +};
|
| +
|
| +static const CodecInfo kVP8CodecInfo = { "vp8", CodecInfo::VIDEO, NULL };
|
| +static const CodecInfo kVorbisCodecInfo = { "vorbis", CodecInfo::AUDIO, NULL };
|
| +
|
| +static const CodecInfo* kVideoWebMCodecs[] = {
|
| + &kVP8CodecInfo,
|
| + &kVorbisCodecInfo,
|
| + NULL
|
| +};
|
| +
|
| +static const CodecInfo* kAudioWebMCodecs[] = {
|
| + &kVorbisCodecInfo,
|
| + NULL
|
| +};
|
| +
|
| +static media::StreamParser* BuildWebMParser(
|
| + const std::vector<std::string>& codecs,
|
| + const media::LogCB& log_cb) {
|
| +#if defined(OS_ANDROID)
|
| + return NULL;
|
| +#else
|
| + return new media::WebMStreamParser();
|
| +#endif
|
| +}
|
| +
|
| +#if defined(GOOGLE_CHROME_BUILD) || defined(USE_PROPRIETARY_CODECS)
|
| +// AAC Object Type IDs that Chrome supports.
|
| +static const int kAACLCObjectType = 2;
|
| +static const int kAACSBRObjectType = 5;
|
| +
|
| +static int GetMP4AudioObjectType(const std::string& codec_id,
|
| + const media::LogCB& log_cb) {
|
| + int audio_object_type;
|
| + std::vector<std::string> tokens;
|
| + if (Tokenize(codec_id, ".", &tokens) != 3 ||
|
| + tokens[0] != "mp4a" || tokens[1] != "40" ||
|
| + !base::HexStringToInt(tokens[2], &audio_object_type)) {
|
| + MEDIA_LOG(log_cb) << "Malformed mimetype codec '" << codec_id << "'";
|
| + return -1;
|
| + }
|
| +
|
| +
|
| + return audio_object_type;
|
| +}
|
| +
|
| +bool ValidateMP4ACodecID(const std::string& codec_id,
|
| + const media::LogCB& log_cb) {
|
| + int audio_object_type = GetMP4AudioObjectType(codec_id, log_cb);
|
| + if (audio_object_type == kAACLCObjectType ||
|
| + audio_object_type == kAACSBRObjectType) {
|
| + return true;
|
| + }
|
| +
|
| + MEDIA_LOG(log_cb) << "Unsupported audio object type "
|
| + << "0x" << std::hex << audio_object_type
|
| + << " in codec '" << codec_id << "'";
|
| + return false;
|
| +}
|
| +
|
| +static const CodecInfo kH264CodecInfo = { "avc1.*", CodecInfo::VIDEO, NULL };
|
| +static const CodecInfo kMPEG4AACCodecInfo = {
|
| + "mp4a.40.*", CodecInfo::AUDIO, &ValidateMP4ACodecID
|
| +};
|
| +
|
| +static const CodecInfo kMPEG2AACLCCodecInfo = {
|
| + "mp4a.67", CodecInfo::AUDIO, NULL
|
| +};
|
| +
|
| +static const CodecInfo* kVideoMP4Codecs[] = {
|
| + &kH264CodecInfo,
|
| + &kMPEG4AACCodecInfo,
|
| + &kMPEG2AACLCCodecInfo,
|
| + NULL
|
| +};
|
| +
|
| +static const CodecInfo* kAudioMP4Codecs[] = {
|
| + &kMPEG4AACCodecInfo,
|
| + &kMPEG2AACLCCodecInfo,
|
| + NULL
|
| +};
|
| +
|
| +static media::StreamParser* BuildMP4Parser(
|
| + const std::vector<std::string>& codecs, const media::LogCB& log_cb) {
|
| +#if defined(OS_ANDROID)
|
| + return NULL;
|
| +#else
|
| + std::set<int> audio_object_types;
|
| + bool has_sbr = false;
|
| + for (size_t i = 0; i < codecs.size(); ++i) {
|
| + std::string codec_id = codecs[i];
|
| + if (MatchPattern(codec_id, kMPEG2AACLCCodecInfo.pattern)) {
|
| + audio_object_types.insert(media::mp4::kISO_13818_7_AAC_LC);
|
| + } else if (MatchPattern(codec_id, kMPEG4AACCodecInfo.pattern)) {
|
| + int audio_object_type = GetMP4AudioObjectType(codec_id, log_cb);
|
| + DCHECK_GT(audio_object_type, 0);
|
| +
|
| + audio_object_types.insert(media::mp4::kISO_14496_3);
|
| +
|
| + if (audio_object_type == kAACSBRObjectType) {
|
| + has_sbr = true;
|
| + break;
|
| + }
|
| + }
|
| + }
|
| +
|
| + return new media::mp4::MP4StreamParser(audio_object_types, has_sbr);
|
| +#endif
|
| +}
|
| +#endif
|
| +
|
| +static const SupportedTypeInfo kSupportedTypeInfo[] = {
|
| + { "video/webm", &BuildWebMParser, kVideoWebMCodecs },
|
| + { "audio/webm", &BuildWebMParser, kAudioWebMCodecs },
|
| +#if defined(GOOGLE_CHROME_BUILD) || defined(USE_PROPRIETARY_CODECS)
|
| + { "video/mp4", &BuildMP4Parser, kVideoMP4Codecs },
|
| + { "audio/mp4", &BuildMP4Parser, kAudioMP4Codecs },
|
| +#endif
|
| +};
|
| +
|
| +// Checks to see if the specified |type| and |codecs| list are supported.
|
| +// Returns true if |type| and all codecs listed in |codecs| are supported.
|
| +// |factory_function| contains a function that can build a StreamParser
|
| +// for this type.
|
| +// |has_audio| is true if an audio codec was specified.
|
| +// |has_video| is true if a video codec was specified.
|
| +// Returns false otherwise. The values of |factory_function|, |has_audio|,
|
| +// and |has_video| are undefined.
|
| +static bool IsSupported(const std::string& type,
|
| + const std::vector<std::string>& codecs,
|
| + const media::LogCB& log_cb,
|
| + ParserFactoryFunction* factory_function,
|
| + bool* has_audio,
|
| + bool* has_video) {
|
| + DCHECK_GT(codecs.size(), 0u);
|
| + *factory_function = NULL;
|
| + *has_audio = false;
|
| + *has_video = false;
|
| +
|
| + // Search for the SupportedTypeInfo for |type|.
|
| + for (size_t i = 0; i < arraysize(kSupportedTypeInfo); ++i) {
|
| + const SupportedTypeInfo& type_info = kSupportedTypeInfo[i];
|
| + if (type == type_info.type) {
|
| + // Make sure all the codecs specified in |codecs| are
|
| + // in the supported type info.
|
| + for (size_t j = 0; j < codecs.size(); ++j) {
|
| + // Search the type info for a match.
|
| + bool found_codec = false;
|
| + CodecInfo::Type codec_type = CodecInfo::UNKNOWN;
|
| + std::string codec_id = codecs[j];
|
| + for (int k = 0; type_info.codecs[k]; ++k) {
|
| + if (MatchPattern(codec_id, type_info.codecs[k]->pattern) &&
|
| + (!type_info.codecs[k]->validator ||
|
| + type_info.codecs[k]->validator(codec_id, log_cb))) {
|
| + found_codec = true;
|
| + codec_type = type_info.codecs[k]->type;
|
| + break;
|
| + }
|
| + }
|
| +
|
| + if (!found_codec) {
|
| + MEDIA_LOG(log_cb) << "Codec '" << codec_id
|
| + <<"' is not supported for '" << type << "'";
|
| + return false;
|
| + }
|
| +
|
| + switch (codec_type) {
|
| + case CodecInfo::AUDIO:
|
| + *has_audio = true;
|
| + break;
|
| + case CodecInfo::VIDEO:
|
| + *has_video = true;
|
| + break;
|
| + default:
|
| + MEDIA_LOG(log_cb) << "Unsupported codec type '"<< codec_type
|
| + << "' for " << codec_id;
|
| + return false;
|
| + }
|
| + }
|
| +
|
| + *factory_function = type_info.factory_function;
|
| +
|
| + // All codecs were supported by this |type|.
|
| + return true;
|
| + }
|
| + }
|
| +
|
| + // |type| didn't match any of the supported types.
|
| + return false;
|
| +}
|
| +
|
| +bool StreamParserFactory::IsTypeSupported(
|
| + const std::string& type, const std::vector<std::string>& codecs) {
|
| + bool has_audio;
|
| + bool has_video;
|
| + ParserFactoryFunction factory_function;
|
| + return IsSupported(type, codecs, media::LogCB(), &factory_function,
|
| + &has_audio, &has_video);
|
| +}
|
| +
|
| +scoped_ptr<media::StreamParser> StreamParserFactory::Create(
|
| + const std::string& type, const std::vector<std::string>& codecs,
|
| + const media::LogCB& log_cb, bool* has_audio, bool* has_video) {
|
| + scoped_ptr<media::StreamParser> stream_parser;
|
| + ParserFactoryFunction factory_function;
|
| + if (IsSupported(type, codecs, log_cb, &factory_function,
|
| + has_audio, has_video)) {
|
| + stream_parser.reset(factory_function(codecs, log_cb));
|
| + }
|
| +
|
| + return stream_parser.Pass();
|
| +}
|
| +
|
| +
|
| +} // namespace media
|
|
|