Add duration, language, codec data to stream info.
Change-Id: I83d221fd36adb53ccf5629c80b137ba0ec730d55
This commit is contained in:
parent
e82f0c00c1
commit
3f3d9a6b76
|
@ -6,48 +6,68 @@
|
||||||
|
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
|
||||||
|
#include "base/strings/string_number_conversions.h"
|
||||||
#include "media/base/limits.h"
|
#include "media/base/limits.h"
|
||||||
|
|
||||||
namespace media {
|
namespace media {
|
||||||
|
|
||||||
AudioStreamInfo::AudioStreamInfo(int track_id,
|
AudioStreamInfo::AudioStreamInfo(int track_id,
|
||||||
int time_scale,
|
uint32 time_scale,
|
||||||
|
uint64 duration,
|
||||||
AudioCodec codec,
|
AudioCodec codec,
|
||||||
int bytes_per_channel,
|
const std::string& codec_string,
|
||||||
int num_channels,
|
const std::string& language,
|
||||||
int samples_per_second,
|
uint8 sample_bits,
|
||||||
|
uint8 num_channels,
|
||||||
|
uint32 sampling_frequency,
|
||||||
const uint8* extra_data,
|
const uint8* extra_data,
|
||||||
size_t extra_data_size,
|
size_t extra_data_size,
|
||||||
bool is_encrypted)
|
bool is_encrypted)
|
||||||
: StreamInfo(kStreamAudio,
|
: StreamInfo(kStreamAudio,
|
||||||
track_id,
|
track_id,
|
||||||
time_scale,
|
time_scale,
|
||||||
|
duration,
|
||||||
|
codec_string,
|
||||||
|
language,
|
||||||
extra_data,
|
extra_data,
|
||||||
extra_data_size,
|
extra_data_size,
|
||||||
is_encrypted),
|
is_encrypted),
|
||||||
codec_(codec),
|
codec_(codec),
|
||||||
bytes_per_channel_(bytes_per_channel),
|
sample_bits_(sample_bits),
|
||||||
num_channels_(num_channels),
|
num_channels_(num_channels),
|
||||||
samples_per_second_(samples_per_second) {}
|
sampling_frequency_(sampling_frequency) {}
|
||||||
|
|
||||||
AudioStreamInfo::~AudioStreamInfo() {}
|
AudioStreamInfo::~AudioStreamInfo() {}
|
||||||
|
|
||||||
bool AudioStreamInfo::IsValidConfig() const {
|
bool AudioStreamInfo::IsValidConfig() const {
|
||||||
return codec_ != kUnknownAudioCodec && num_channels_ != 0 &&
|
return codec_ != kUnknownAudioCodec && num_channels_ != 0 &&
|
||||||
num_channels_ <= limits::kMaxChannels && bytes_per_channel_ > 0 &&
|
num_channels_ <= limits::kMaxChannels && sample_bits_ > 0 &&
|
||||||
bytes_per_channel_ <= limits::kMaxBytesPerSample &&
|
sample_bits_ <= limits::kMaxBitsPerSample &&
|
||||||
samples_per_second_ > 0 &&
|
sampling_frequency_ > 0 &&
|
||||||
samples_per_second_ <= limits::kMaxSampleRate;
|
sampling_frequency_ <= limits::kMaxSampleRate;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string AudioStreamInfo::ToString() {
|
std::string AudioStreamInfo::ToString() const {
|
||||||
std::ostringstream s;
|
std::ostringstream s;
|
||||||
s << "codec: " << codec_
|
s << "codec: " << codec_
|
||||||
<< " bytes_per_channel: " << bytes_per_channel_
|
<< " sample_bits: " << static_cast<int>(sample_bits_)
|
||||||
<< " num_channels: " << num_channels_
|
<< " num_channels: " << static_cast<int>(num_channels_)
|
||||||
<< " samples_per_second: " << samples_per_second_
|
<< " sampling_frequency: " << sampling_frequency_
|
||||||
<< " " << StreamInfo::ToString();
|
<< " " << StreamInfo::ToString();
|
||||||
return s.str();
|
return s.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string AudioStreamInfo::GetCodecString(AudioCodec codec,
|
||||||
|
uint8 audio_object_type) {
|
||||||
|
switch (codec) {
|
||||||
|
case kCodecVorbis:
|
||||||
|
return "vorbis";
|
||||||
|
case kCodecOpus:
|
||||||
|
return "opus";
|
||||||
|
case kCodecAAC:
|
||||||
|
return "mp4a.40." + base::UintToString(audio_object_type);
|
||||||
|
}
|
||||||
|
return "unknown";
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace media
|
} // namespace media
|
||||||
|
|
|
@ -35,11 +35,14 @@ class AudioStreamInfo : public StreamInfo {
|
||||||
// Constructs an initialized object. It is acceptable to pass in NULL for
|
// Constructs an initialized object. It is acceptable to pass in NULL for
|
||||||
// |extra_data|, otherwise the memory is copied.
|
// |extra_data|, otherwise the memory is copied.
|
||||||
AudioStreamInfo(int track_id,
|
AudioStreamInfo(int track_id,
|
||||||
int time_scale,
|
uint32 time_scale,
|
||||||
|
uint64 duration,
|
||||||
AudioCodec codec,
|
AudioCodec codec,
|
||||||
int bytes_per_channel,
|
const std::string& codec_string,
|
||||||
int num_channels,
|
const std::string& language,
|
||||||
int samples_per_second,
|
uint8 sample_bits,
|
||||||
|
uint8 num_channels,
|
||||||
|
uint32 sampling_frequency,
|
||||||
const uint8* extra_data,
|
const uint8* extra_data,
|
||||||
size_t extra_data_size,
|
size_t extra_data_size,
|
||||||
bool is_encrypted);
|
bool is_encrypted);
|
||||||
|
@ -48,23 +51,28 @@ class AudioStreamInfo : public StreamInfo {
|
||||||
|
|
||||||
// Returns true if this object has appropriate configuration values, false
|
// Returns true if this object has appropriate configuration values, false
|
||||||
// otherwise.
|
// otherwise.
|
||||||
virtual bool IsValidConfig() const;
|
virtual bool IsValidConfig() const OVERRIDE;
|
||||||
|
|
||||||
// Returns a human-readable string describing |*this|.
|
// Returns a human-readable string describing |*this|.
|
||||||
virtual std::string ToString();
|
virtual std::string ToString() const OVERRIDE;
|
||||||
|
|
||||||
AudioCodec codec() const { return codec_; }
|
AudioCodec codec() const { return codec_; }
|
||||||
int bits_per_channel() const { return bytes_per_channel_ * 8; }
|
uint8 sample_bits() const { return sample_bits_; }
|
||||||
int bytes_per_channel() const { return bytes_per_channel_; }
|
uint8 sample_bytes() const { return sample_bits_ / 8; }
|
||||||
int num_channels() const { return num_channels_; }
|
uint8 num_channels() const { return num_channels_; }
|
||||||
int samples_per_second() const { return samples_per_second_; }
|
uint32 sampling_frequency() const { return sampling_frequency_; }
|
||||||
int bytes_per_frame() const { return num_channels_ * bytes_per_channel_; }
|
uint32 bytes_per_frame() const {
|
||||||
|
return static_cast<uint32>(num_channels_) * sample_bits_ / 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns the codec string. The second parameter is only used by AAC Codec.
|
||||||
|
static std::string GetCodecString(AudioCodec codec, uint8 audio_object_type);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
AudioCodec codec_;
|
AudioCodec codec_;
|
||||||
int bytes_per_channel_;
|
uint8 sample_bits_;
|
||||||
int num_channels_;
|
uint8 num_channels_;
|
||||||
int samples_per_second_;
|
uint32 sampling_frequency_;
|
||||||
|
|
||||||
// Not using DISALLOW_COPY_AND_ASSIGN here intentionally to allow the compiler
|
// Not using DISALLOW_COPY_AND_ASSIGN here intentionally to allow the compiler
|
||||||
// generated copy constructor and assignment operator. Since the extra data is
|
// generated copy constructor and assignment operator. Since the extra data is
|
||||||
|
|
|
@ -10,13 +10,19 @@ namespace media {
|
||||||
|
|
||||||
StreamInfo::StreamInfo(StreamType stream_type,
|
StreamInfo::StreamInfo(StreamType stream_type,
|
||||||
int track_id,
|
int track_id,
|
||||||
int time_scale,
|
uint32 time_scale,
|
||||||
|
uint64 duration,
|
||||||
|
const std::string& codec_string,
|
||||||
|
const std::string& language,
|
||||||
const uint8* extra_data,
|
const uint8* extra_data,
|
||||||
size_t extra_data_size,
|
size_t extra_data_size,
|
||||||
bool is_encrypted)
|
bool is_encrypted)
|
||||||
: stream_type_(stream_type),
|
: stream_type_(stream_type),
|
||||||
track_id_(track_id),
|
track_id_(track_id),
|
||||||
time_scale_(time_scale),
|
time_scale_(time_scale),
|
||||||
|
duration_(duration),
|
||||||
|
codec_string_(codec_string),
|
||||||
|
language_(language),
|
||||||
is_encrypted_(is_encrypted) {
|
is_encrypted_(is_encrypted) {
|
||||||
|
|
||||||
CHECK((extra_data_size != 0) == (extra_data != NULL));
|
CHECK((extra_data_size != 0) == (extra_data != NULL));
|
||||||
|
@ -25,11 +31,14 @@ StreamInfo::StreamInfo(StreamType stream_type,
|
||||||
|
|
||||||
StreamInfo::~StreamInfo() {}
|
StreamInfo::~StreamInfo() {}
|
||||||
|
|
||||||
std::string StreamInfo::ToString() {
|
std::string StreamInfo::ToString() const {
|
||||||
std::ostringstream s;
|
std::ostringstream s;
|
||||||
s << "type: " << (stream_type_ == kStreamAudio ? "Audio" : "Video")
|
s << "type: " << (stream_type_ == kStreamAudio ? "Audio" : "Video")
|
||||||
<< " track_id: " << track_id_
|
<< " track_id: " << track_id_
|
||||||
<< " time_scale: " << time_scale_
|
<< " time_scale: " << time_scale_
|
||||||
|
<< " duration: " << duration_
|
||||||
|
<< " codec_string: " << codec_string_
|
||||||
|
<< " language: " << language_
|
||||||
<< " is_encrypted: " << is_encrypted_;
|
<< " is_encrypted: " << is_encrypted_;
|
||||||
return s.str();
|
return s.str();
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,7 +21,10 @@ class StreamInfo : public base::RefCountedThreadSafe<StreamInfo> {
|
||||||
public:
|
public:
|
||||||
StreamInfo(StreamType stream_type,
|
StreamInfo(StreamType stream_type,
|
||||||
int track_id,
|
int track_id,
|
||||||
int time_scale,
|
uint32 time_scale,
|
||||||
|
uint64 duration,
|
||||||
|
const std::string& codec_string,
|
||||||
|
const std::string& language,
|
||||||
const uint8* extra_data,
|
const uint8* extra_data,
|
||||||
size_t extra_data_size,
|
size_t extra_data_size,
|
||||||
bool is_encrypted);
|
bool is_encrypted);
|
||||||
|
@ -32,11 +35,14 @@ class StreamInfo : public base::RefCountedThreadSafe<StreamInfo> {
|
||||||
virtual bool IsValidConfig() const = 0;
|
virtual bool IsValidConfig() const = 0;
|
||||||
|
|
||||||
// Returns a human-readable string describing |*this|.
|
// Returns a human-readable string describing |*this|.
|
||||||
virtual std::string ToString();
|
virtual std::string ToString() const;
|
||||||
|
|
||||||
StreamType stream_type() const { return stream_type_; }
|
StreamType stream_type() const { return stream_type_; }
|
||||||
int track_id() const { return track_id_; }
|
int track_id() const { return track_id_; }
|
||||||
int time_scale() const { return time_scale_; }
|
uint32 time_scale() const { return time_scale_; }
|
||||||
|
uint64 duration() const { return duration_; }
|
||||||
|
const std::string& codec_string() const { return codec_string_; }
|
||||||
|
const std::string& language() const { return language_; }
|
||||||
|
|
||||||
bool is_encrypted() const { return is_encrypted_; }
|
bool is_encrypted() const { return is_encrypted_; }
|
||||||
|
|
||||||
|
@ -47,11 +53,18 @@ class StreamInfo : public base::RefCountedThreadSafe<StreamInfo> {
|
||||||
return extra_data_.size();
|
return extra_data_.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void set_duration(int duration) { duration_ = duration; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Whether the stream is Audio or Video.
|
// Whether the stream is Audio or Video.
|
||||||
StreamType stream_type_;
|
StreamType stream_type_;
|
||||||
int track_id_;
|
int track_id_;
|
||||||
int time_scale_;
|
// The actual time is calculated as time / time_scale_ in seconds.
|
||||||
|
uint32 time_scale_;
|
||||||
|
// Duration base on time_scale.
|
||||||
|
uint64 duration_;
|
||||||
|
std::string codec_string_;
|
||||||
|
std::string language_;
|
||||||
// Whether the stream is potentially encrypted.
|
// Whether the stream is potentially encrypted.
|
||||||
// Note that in a potentially encrypted stream, individual buffers
|
// Note that in a potentially encrypted stream, individual buffers
|
||||||
// can be encrypted or not encrypted.
|
// can be encrypted or not encrypted.
|
||||||
|
|
|
@ -6,21 +6,29 @@
|
||||||
|
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
|
||||||
|
#include "base/strings/string_number_conversions.h"
|
||||||
|
#include "base/strings/string_util.h"
|
||||||
#include "media/base/limits.h"
|
#include "media/base/limits.h"
|
||||||
|
|
||||||
namespace media {
|
namespace media {
|
||||||
|
|
||||||
VideoStreamInfo::VideoStreamInfo(int track_id,
|
VideoStreamInfo::VideoStreamInfo(int track_id,
|
||||||
int time_scale,
|
uint32 time_scale,
|
||||||
|
uint64 duration,
|
||||||
VideoCodec codec,
|
VideoCodec codec,
|
||||||
int width,
|
const std::string& codec_string,
|
||||||
int height,
|
const std::string& language,
|
||||||
|
uint16 width,
|
||||||
|
uint16 height,
|
||||||
const uint8* extra_data,
|
const uint8* extra_data,
|
||||||
size_t extra_data_size,
|
size_t extra_data_size,
|
||||||
bool is_encrypted)
|
bool is_encrypted)
|
||||||
: StreamInfo(kStreamVideo,
|
: StreamInfo(kStreamVideo,
|
||||||
track_id,
|
track_id,
|
||||||
time_scale,
|
time_scale,
|
||||||
|
duration,
|
||||||
|
codec_string,
|
||||||
|
language,
|
||||||
extra_data,
|
extra_data,
|
||||||
extra_data_size,
|
extra_data_size,
|
||||||
is_encrypted),
|
is_encrypted),
|
||||||
|
@ -36,7 +44,7 @@ bool VideoStreamInfo::IsValidConfig() const {
|
||||||
height_ > 0 && height_ <= limits::kMaxDimension;
|
height_ > 0 && height_ <= limits::kMaxDimension;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string VideoStreamInfo::ToString() {
|
std::string VideoStreamInfo::ToString() const {
|
||||||
std::ostringstream s;
|
std::ostringstream s;
|
||||||
s << "codec: " << codec_
|
s << "codec: " << codec_
|
||||||
<< " width: " << width_
|
<< " width: " << width_
|
||||||
|
@ -45,4 +53,24 @@ std::string VideoStreamInfo::ToString() {
|
||||||
return s.str();
|
return s.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string VideoStreamInfo::GetCodecString(VideoCodec codec,
|
||||||
|
uint8 profile,
|
||||||
|
uint8 compatible_profiles,
|
||||||
|
uint8 level) {
|
||||||
|
switch (codec) {
|
||||||
|
case kCodecVP8:
|
||||||
|
return "vp8";
|
||||||
|
case kCodecVP9:
|
||||||
|
return "vp9";
|
||||||
|
case kCodecH264: {
|
||||||
|
const uint8 bytes[] = {profile, compatible_profiles, level};
|
||||||
|
return "avc1."
|
||||||
|
+ StringToLowerASCII(base::HexEncode(bytes, arraysize(bytes)));
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
NOTIMPLEMENTED() << "Codec: " << codec;
|
||||||
|
return "unknown";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace media
|
} // namespace media
|
||||||
|
|
|
@ -27,10 +27,13 @@ class VideoStreamInfo : public StreamInfo {
|
||||||
// Constructs an initialized object. It is acceptable to pass in NULL for
|
// Constructs an initialized object. It is acceptable to pass in NULL for
|
||||||
// |extra_data|, otherwise the memory is copied.
|
// |extra_data|, otherwise the memory is copied.
|
||||||
VideoStreamInfo(int track_id,
|
VideoStreamInfo(int track_id,
|
||||||
int time_scale,
|
uint32 time_scale,
|
||||||
|
uint64 duration,
|
||||||
VideoCodec codec,
|
VideoCodec codec,
|
||||||
int width,
|
const std::string& codec_string,
|
||||||
int height,
|
const std::string& language,
|
||||||
|
uint16 width,
|
||||||
|
uint16 height,
|
||||||
const uint8* extra_data,
|
const uint8* extra_data,
|
||||||
size_t extra_data_size,
|
size_t extra_data_size,
|
||||||
bool is_encrypted);
|
bool is_encrypted);
|
||||||
|
@ -39,19 +42,24 @@ class VideoStreamInfo : public StreamInfo {
|
||||||
|
|
||||||
// Returns true if this object has appropriate configuration values, false
|
// Returns true if this object has appropriate configuration values, false
|
||||||
// otherwise.
|
// otherwise.
|
||||||
virtual bool IsValidConfig() const;
|
virtual bool IsValidConfig() const OVERRIDE;
|
||||||
|
|
||||||
// Returns a human-readable string describing |*this|.
|
// Returns a human-readable string describing |*this|.
|
||||||
virtual std::string ToString();
|
virtual std::string ToString() const OVERRIDE;
|
||||||
|
|
||||||
VideoCodec codec() const { return codec_; }
|
VideoCodec codec() const { return codec_; }
|
||||||
int width() const { return width_; }
|
uint16 width() const { return width_; }
|
||||||
int height() const { return height_; }
|
uint16 height() const { return height_; }
|
||||||
|
|
||||||
|
// Returns the codec string. The parameters beyond codec are only used by
|
||||||
|
// H.264 codec.
|
||||||
|
static std::string GetCodecString(VideoCodec codec, uint8 profile,
|
||||||
|
uint8 compatible_profiles, uint8 level);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
VideoCodec codec_;
|
VideoCodec codec_;
|
||||||
int width_;
|
uint16 width_;
|
||||||
int height_;
|
uint16 height_;
|
||||||
|
|
||||||
// Not using DISALLOW_COPY_AND_ASSIGN here intentionally to allow the compiler
|
// Not using DISALLOW_COPY_AND_ASSIGN here intentionally to allow the compiler
|
||||||
// generated copy constructor and assignment operator. Since the extra data is
|
// generated copy constructor and assignment operator. Since the extra data is
|
||||||
|
|
|
@ -13,13 +13,13 @@
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
// Sampling Frequency Index table, from ISO 14496-3 Table 1.16
|
// Sampling Frequency Index table, from ISO 14496-3 Table 1.16
|
||||||
static const int kSampleRates[] = {
|
static const uint32 kSampleRates[] = {
|
||||||
96000, 88200, 64000, 48000, 44100, 32000, 24000,
|
96000, 88200, 64000, 48000, 44100, 32000, 24000,
|
||||||
22050, 16000, 12000, 11025, 8000, 7350
|
22050, 16000, 12000, 11025, 8000, 7350
|
||||||
};
|
};
|
||||||
|
|
||||||
// Channel Configuration table, from ISO 14496-3 Table 1.17
|
// Channel Configuration table, from ISO 14496-3 Table 1.17
|
||||||
const uint32 kChannelConfigs[] = {0, 1, 2, 3, 4, 5, 6, 8};
|
const uint8 kChannelConfigs[] = {0, 1, 2, 3, 4, 5, 6, 8};
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
|
@ -28,46 +28,51 @@ namespace media {
|
||||||
namespace mp4 {
|
namespace mp4 {
|
||||||
|
|
||||||
AAC::AAC()
|
AAC::AAC()
|
||||||
: profile_(0), frequency_index_(0), channel_config_(0), frequency_(0),
|
: audio_object_type_(0), frequency_index_(0), channel_config_(0),
|
||||||
extension_frequency_(0), num_channels_(0) {
|
ps_present_(false), frequency_(0), extension_frequency_(0),
|
||||||
|
num_channels_(0) {
|
||||||
}
|
}
|
||||||
|
|
||||||
AAC::~AAC() {
|
AAC::~AAC() {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AAC::Parse(const std::vector<uint8>& data) {
|
bool AAC::Parse(const std::vector<uint8>& data) {
|
||||||
#if defined(OS_ANDROID)
|
|
||||||
codec_specific_data_ = data;
|
codec_specific_data_ = data;
|
||||||
#endif
|
|
||||||
if (data.empty())
|
if (data.empty())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
BitReader reader(&data[0], data.size());
|
BitReader reader(&data[0], data.size());
|
||||||
uint8 extension_type = 0;
|
uint8 extension_type = 0;
|
||||||
bool ps_present = false;
|
|
||||||
uint8 extension_frequency_index = 0xff;
|
uint8 extension_frequency_index = 0xff;
|
||||||
|
|
||||||
|
ps_present_ = false;
|
||||||
frequency_ = 0;
|
frequency_ = 0;
|
||||||
extension_frequency_ = 0;
|
extension_frequency_ = 0;
|
||||||
|
|
||||||
// The following code is written according to ISO 14496 Part 3 Table 1.13 -
|
// The following code is written according to ISO 14496 Part 3 Table 1.13 -
|
||||||
// Syntax of AudioSpecificConfig.
|
// Syntax of AudioSpecificConfig.
|
||||||
|
|
||||||
// Read base configuration
|
// Read base configuration.
|
||||||
RCHECK(reader.ReadBits(5, &profile_));
|
// Audio Object Types specified in ISO 14496-3, Table 1.15.
|
||||||
|
RCHECK(reader.ReadBits(5, &audio_object_type_));
|
||||||
|
// Audio objects type >=31 is not supported yet.
|
||||||
|
RCHECK(audio_object_type_ < 31);
|
||||||
RCHECK(reader.ReadBits(4, &frequency_index_));
|
RCHECK(reader.ReadBits(4, &frequency_index_));
|
||||||
if (frequency_index_ == 0xf)
|
if (frequency_index_ == 0xf)
|
||||||
RCHECK(reader.ReadBits(24, &frequency_));
|
RCHECK(reader.ReadBits(24, &frequency_));
|
||||||
RCHECK(reader.ReadBits(4, &channel_config_));
|
RCHECK(reader.ReadBits(4, &channel_config_));
|
||||||
|
|
||||||
// Read extension configuration.
|
// Read extension configuration.
|
||||||
if (profile_ == 5 || profile_ == 29) {
|
if (audio_object_type_ == 5 || audio_object_type_ == 29) {
|
||||||
ps_present = (profile_ == 29);
|
ps_present_ = (audio_object_type_ == 29);
|
||||||
extension_type = 5;
|
extension_type = 5;
|
||||||
RCHECK(reader.ReadBits(4, &extension_frequency_index));
|
RCHECK(reader.ReadBits(4, &extension_frequency_index));
|
||||||
if (extension_frequency_index == 0xf)
|
if (extension_frequency_index == 0xf)
|
||||||
RCHECK(reader.ReadBits(24, &extension_frequency_));
|
RCHECK(reader.ReadBits(24, &extension_frequency_));
|
||||||
RCHECK(reader.ReadBits(5, &profile_));
|
RCHECK(reader.ReadBits(5, &audio_object_type_));
|
||||||
|
// Audio objects type >=31 is not supported yet.
|
||||||
|
RCHECK(audio_object_type_ < 31);
|
||||||
}
|
}
|
||||||
|
|
||||||
RCHECK(SkipDecoderGASpecificConfig(&reader));
|
RCHECK(SkipDecoderGASpecificConfig(&reader));
|
||||||
|
@ -96,7 +101,7 @@ bool AAC::Parse(const std::vector<uint8>& data) {
|
||||||
RCHECK(reader.ReadBits(11, &sync_extension_type));
|
RCHECK(reader.ReadBits(11, &sync_extension_type));
|
||||||
if (sync_extension_type == 0x548) {
|
if (sync_extension_type == 0x548) {
|
||||||
RCHECK(reader.ReadBits(1, &ps_present_flag));
|
RCHECK(reader.ReadBits(1, &ps_present_flag));
|
||||||
ps_present = ps_present_flag != 0;
|
ps_present_ = ps_present_flag != 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -114,20 +119,15 @@ bool AAC::Parse(const std::vector<uint8>& data) {
|
||||||
extension_frequency_ = kSampleRates[extension_frequency_index];
|
extension_frequency_ = kSampleRates[extension_frequency_index];
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(kqyang): should we care about whether Parametric Stereo is on?
|
|
||||||
// When Parametric Stereo is on, mono will be played as stereo.
|
|
||||||
if (ps_present && channel_config_ == 1)
|
|
||||||
num_channels_ = 2; // CHANNEL_LAYOUT_STEREO
|
|
||||||
else {
|
|
||||||
RCHECK(channel_config_ < arraysize(kChannelConfigs));
|
RCHECK(channel_config_ < arraysize(kChannelConfigs));
|
||||||
num_channels_ = kChannelConfigs[channel_config_];
|
num_channels_ = kChannelConfigs[channel_config_];
|
||||||
|
|
||||||
|
return frequency_ != 0 && num_channels_ != 0 && audio_object_type_ >= 1 &&
|
||||||
|
audio_object_type_ <= 4 && frequency_index_ != 0xf &&
|
||||||
|
channel_config_ <= 7;
|
||||||
}
|
}
|
||||||
|
|
||||||
return frequency_ != 0 && num_channels_ != 0 && profile_ >= 1 &&
|
uint32 AAC::GetOutputSamplesPerSecond(bool sbr_in_mimetype) const {
|
||||||
profile_ <= 4 && frequency_index_ != 0xf && channel_config_ <= 7;
|
|
||||||
}
|
|
||||||
|
|
||||||
int AAC::GetOutputSamplesPerSecond(bool sbr_in_mimetype) const {
|
|
||||||
if (extension_frequency_ > 0)
|
if (extension_frequency_ > 0)
|
||||||
return extension_frequency_;
|
return extension_frequency_;
|
||||||
|
|
||||||
|
@ -139,24 +139,28 @@ int AAC::GetOutputSamplesPerSecond(bool sbr_in_mimetype) const {
|
||||||
// to SBR doubling the AAC sample rate.)
|
// to SBR doubling the AAC sample rate.)
|
||||||
// TODO(acolwell) : Extend sample rate cap to 96kHz for Level 5 content.
|
// TODO(acolwell) : Extend sample rate cap to 96kHz for Level 5 content.
|
||||||
DCHECK_GT(frequency_, 0);
|
DCHECK_GT(frequency_, 0);
|
||||||
return std::min(2 * frequency_, 48000);
|
return std::min(2 * frequency_, 48000u);
|
||||||
}
|
}
|
||||||
|
|
||||||
int AAC::GetNumChannels(bool sbr_in_mimetype) const {
|
uint8 AAC::GetNumChannels(bool sbr_in_mimetype) const {
|
||||||
// Check for implicit signalling of HE-AAC and indicate stereo output
|
// Check for implicit signalling of HE-AAC and indicate stereo output
|
||||||
// if the mono channel configuration is signalled.
|
// if the mono channel configuration is signalled.
|
||||||
// See ISO-14496-3 Section 1.6.6.1.2 for details about this special casing.
|
// See ISO-14496-3 Section 1.6.6.1.2 for details about this special casing.
|
||||||
if (sbr_in_mimetype && channel_config_ == 1)
|
if (sbr_in_mimetype && channel_config_ == 1)
|
||||||
return 2; // CHANNEL_LAYOUT_STEREO
|
return 2; // CHANNEL_LAYOUT_STEREO
|
||||||
|
|
||||||
|
// When Parametric Stereo is on, mono will be played as stereo.
|
||||||
|
if (ps_present_ && channel_config_ == 1)
|
||||||
|
return 2; // CHANNEL_LAYOUT_STEREO
|
||||||
|
|
||||||
return num_channels_;
|
return num_channels_;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AAC::ConvertToADTS(std::vector<uint8>* buffer) const {
|
bool AAC::ConvertToADTS(std::vector<uint8>* buffer) const {
|
||||||
size_t size = buffer->size() + kADTSHeaderSize;
|
size_t size = buffer->size() + kADTSHeaderSize;
|
||||||
|
|
||||||
DCHECK(profile_ >= 1 && profile_ <= 4 && frequency_index_ != 0xf &&
|
DCHECK(audio_object_type_ >= 1 && audio_object_type_ <= 4 &&
|
||||||
channel_config_ <= 7);
|
frequency_index_ != 0xf && channel_config_ <= 7);
|
||||||
|
|
||||||
// ADTS header uses 13 bits for packet size.
|
// ADTS header uses 13 bits for packet size.
|
||||||
if (size >= (1 << 13))
|
if (size >= (1 << 13))
|
||||||
|
@ -167,7 +171,7 @@ bool AAC::ConvertToADTS(std::vector<uint8>* buffer) const {
|
||||||
adts.insert(buffer->begin(), kADTSHeaderSize, 0);
|
adts.insert(buffer->begin(), kADTSHeaderSize, 0);
|
||||||
adts[0] = 0xff;
|
adts[0] = 0xff;
|
||||||
adts[1] = 0xf1;
|
adts[1] = 0xf1;
|
||||||
adts[2] = ((profile_ - 1) << 6) + (frequency_index_ << 2) +
|
adts[2] = ((audio_object_type_ - 1) << 6) + (frequency_index_ << 2) +
|
||||||
(channel_config_ >> 2);
|
(channel_config_ >> 2);
|
||||||
adts[3] = ((channel_config_ & 0x3) << 6) + (size >> 11);
|
adts[3] = ((channel_config_ & 0x3) << 6) + (size >> 11);
|
||||||
adts[4] = (size & 0x7ff) >> 3;
|
adts[4] = (size & 0x7ff) >> 3;
|
||||||
|
@ -180,7 +184,7 @@ bool AAC::ConvertToADTS(std::vector<uint8>* buffer) const {
|
||||||
// Currently this function only support GASpecificConfig defined in
|
// Currently this function only support GASpecificConfig defined in
|
||||||
// ISO 14496 Part 3 Table 4.1 - Syntax of GASpecificConfig()
|
// ISO 14496 Part 3 Table 4.1 - Syntax of GASpecificConfig()
|
||||||
bool AAC::SkipDecoderGASpecificConfig(BitReader* bit_reader) const {
|
bool AAC::SkipDecoderGASpecificConfig(BitReader* bit_reader) const {
|
||||||
switch (profile_) {
|
switch (audio_object_type_) {
|
||||||
case 1:
|
case 1:
|
||||||
case 2:
|
case 2:
|
||||||
case 3:
|
case 3:
|
||||||
|
@ -202,7 +206,7 @@ bool AAC::SkipDecoderGASpecificConfig(BitReader* bit_reader) const {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AAC::SkipErrorSpecificConfig() const {
|
bool AAC::SkipErrorSpecificConfig() const {
|
||||||
switch (profile_) {
|
switch (audio_object_type_) {
|
||||||
case 17:
|
case 17:
|
||||||
case 19:
|
case 19:
|
||||||
case 20:
|
case 20:
|
||||||
|
@ -236,16 +240,17 @@ bool AAC::SkipGASpecificConfig(BitReader* bit_reader) const {
|
||||||
RCHECK(bit_reader->ReadBits(1, &extension_flag));
|
RCHECK(bit_reader->ReadBits(1, &extension_flag));
|
||||||
RCHECK(channel_config_ != 0);
|
RCHECK(channel_config_ != 0);
|
||||||
|
|
||||||
if (profile_ == 6 || profile_ == 20)
|
if (audio_object_type_ == 6 || audio_object_type_ == 20)
|
||||||
RCHECK(bit_reader->ReadBits(3, &dummy)); // layerNr
|
RCHECK(bit_reader->ReadBits(3, &dummy)); // layerNr
|
||||||
|
|
||||||
if (extension_flag) {
|
if (extension_flag) {
|
||||||
if (profile_ == 22) {
|
if (audio_object_type_ == 22) {
|
||||||
RCHECK(bit_reader->ReadBits(5, &dummy)); // numOfSubFrame
|
RCHECK(bit_reader->ReadBits(5, &dummy)); // numOfSubFrame
|
||||||
RCHECK(bit_reader->ReadBits(11, &dummy)); // layer_length
|
RCHECK(bit_reader->ReadBits(11, &dummy)); // layer_length
|
||||||
}
|
}
|
||||||
|
|
||||||
if (profile_ == 17 || profile_ == 19 || profile_ == 20 || profile_ == 23) {
|
if (audio_object_type_ == 17 || audio_object_type_ == 19 ||
|
||||||
|
audio_object_type_ == 20 || audio_object_type_ == 23) {
|
||||||
RCHECK(bit_reader->ReadBits(3, &dummy)); // resilience flags
|
RCHECK(bit_reader->ReadBits(3, &dummy)); // resilience flags
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -30,17 +30,18 @@ class AAC {
|
||||||
// The function will parse the data and get the ElementaryStreamDescriptor,
|
// The function will parse the data and get the ElementaryStreamDescriptor,
|
||||||
// then it will parse the ElementaryStreamDescriptor to get audio stream
|
// then it will parse the ElementaryStreamDescriptor to get audio stream
|
||||||
// configurations.
|
// configurations.
|
||||||
|
// |data| is always copied to |codec_specific_data_|.
|
||||||
bool Parse(const std::vector<uint8>& data);
|
bool Parse(const std::vector<uint8>& data);
|
||||||
|
|
||||||
// Gets the output sample rate for the AAC stream.
|
// Gets the output sample rate for the AAC stream.
|
||||||
// |sbr_in_mimetype| should be set to true if the SBR mode is
|
// |sbr_in_mimetype| should be set to true if the SBR mode is
|
||||||
// signalled in the mimetype. (ie mp4a.40.5 in the codecs parameter).
|
// signalled in the mimetype. (ie mp4a.40.5 in the codecs parameter).
|
||||||
int GetOutputSamplesPerSecond(bool sbr_in_mimetype) const;
|
uint32 GetOutputSamplesPerSecond(bool sbr_in_mimetype) const;
|
||||||
|
|
||||||
// Gets number of channels for the AAC stream.
|
// Gets number of channels for the AAC stream.
|
||||||
// |sbr_in_mimetype| should be set to true if the SBR mode is
|
// |sbr_in_mimetype| should be set to true if the SBR mode is
|
||||||
// signalled in the mimetype. (ie mp4a.40.5 in the codecs parameter).
|
// signalled in the mimetype. (ie mp4a.40.5 in the codecs parameter).
|
||||||
int GetNumChannels(bool sbr_in_mimetype) const;
|
uint8 GetNumChannels(bool sbr_in_mimetype) const;
|
||||||
|
|
||||||
// This function converts a raw AAC frame into an AAC frame with an ADTS
|
// This function converts a raw AAC frame into an AAC frame with an ADTS
|
||||||
// header. On success, the function returns true and stores the converted data
|
// header. On success, the function returns true and stores the converted data
|
||||||
|
@ -48,12 +49,22 @@ class AAC {
|
||||||
// unchanged.
|
// unchanged.
|
||||||
bool ConvertToADTS(std::vector<uint8>* buffer) const;
|
bool ConvertToADTS(std::vector<uint8>* buffer) const;
|
||||||
|
|
||||||
#if defined(OS_ANDROID)
|
uint8 audio_object_type() const {
|
||||||
// Returns the codec specific data needed by android MediaCodec.
|
return audio_object_type_;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32 frequency() const {
|
||||||
|
return frequency_;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8 num_channels() const {
|
||||||
|
return num_channels_;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns the codec specific data.
|
||||||
std::vector<uint8> codec_specific_data() const {
|
std::vector<uint8> codec_specific_data() const {
|
||||||
return codec_specific_data_;
|
return codec_specific_data_;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
// Size in bytes of the ADTS header added by ConvertEsdsToADTS().
|
// Size in bytes of the ADTS header added by ConvertEsdsToADTS().
|
||||||
static const size_t kADTSHeaderSize = 7;
|
static const size_t kADTSHeaderSize = 7;
|
||||||
|
@ -65,21 +76,20 @@ class AAC {
|
||||||
|
|
||||||
// The following variables store the AAC specific configuration information
|
// The following variables store the AAC specific configuration information
|
||||||
// that are used to generate the ADTS header.
|
// that are used to generate the ADTS header.
|
||||||
uint8 profile_;
|
uint8 audio_object_type_;
|
||||||
uint8 frequency_index_;
|
uint8 frequency_index_;
|
||||||
uint8 channel_config_;
|
uint8 channel_config_;
|
||||||
|
// Is Parametric Stereo on?
|
||||||
|
bool ps_present_;
|
||||||
|
|
||||||
#if defined(OS_ANDROID)
|
|
||||||
// The codec specific data needed by the android MediaCodec.
|
|
||||||
std::vector<uint8> codec_specific_data_;
|
std::vector<uint8> codec_specific_data_;
|
||||||
#endif
|
|
||||||
|
|
||||||
// The following variables store audio configuration information.
|
// The following variables store audio configuration information.
|
||||||
// They are based on the AAC specific configuration but can be overridden
|
// They are based on the AAC specific configuration but can be overridden
|
||||||
// by extensions in elementary stream descriptor.
|
// by extensions in elementary stream descriptor.
|
||||||
int frequency_;
|
uint32 frequency_;
|
||||||
int extension_frequency_;
|
uint32 extension_frequency_;
|
||||||
int num_channels_;
|
uint8 num_channels_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace mp4
|
} // namespace mp4
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
#include "media/mp4/box_definitions.h"
|
#include "media/mp4/box_definitions.h"
|
||||||
|
|
||||||
#include "base/logging.h"
|
#include "base/logging.h"
|
||||||
|
#include "media/base/bit_reader.h"
|
||||||
#include "media/mp4/es_descriptor.h"
|
#include "media/mp4/es_descriptor.h"
|
||||||
#include "media/mp4/rcheck.h"
|
#include "media/mp4/rcheck.h"
|
||||||
|
|
||||||
|
@ -506,6 +507,13 @@ AVCDecoderConfigurationRecord::~AVCDecoderConfigurationRecord() {}
|
||||||
FourCC AVCDecoderConfigurationRecord::BoxType() const { return FOURCC_AVCC; }
|
FourCC AVCDecoderConfigurationRecord::BoxType() const { return FOURCC_AVCC; }
|
||||||
|
|
||||||
bool AVCDecoderConfigurationRecord::Parse(BoxReader* reader) {
|
bool AVCDecoderConfigurationRecord::Parse(BoxReader* reader) {
|
||||||
|
RCHECK(reader->ReadVec(&data, reader->size() - 8));
|
||||||
|
|
||||||
|
BufferReader buffer_reader(&data[0], data.size());
|
||||||
|
return ParseData(&buffer_reader);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AVCDecoderConfigurationRecord::ParseData(BufferReader* reader) {
|
||||||
RCHECK(reader->Read1(&version) && version == 1 &&
|
RCHECK(reader->Read1(&version) && version == 1 &&
|
||||||
reader->Read1(&profile_indication) &&
|
reader->Read1(&profile_indication) &&
|
||||||
reader->Read1(&profile_compatibility) &&
|
reader->Read1(&profile_compatibility) &&
|
||||||
|
@ -679,8 +687,21 @@ bool MediaHeader::Parse(BoxReader* reader) {
|
||||||
reader->Read4(×cale) &&
|
reader->Read4(×cale) &&
|
||||||
reader->Read4Into8(&duration));
|
reader->Read4Into8(&duration));
|
||||||
}
|
}
|
||||||
// Skip language information
|
|
||||||
return reader->SkipBytes(4);
|
// Read language codes into temp first then use BitReader to read the values.
|
||||||
|
// ISO-639-2/T language code: unsigned int(5)[3] language (2 bytes).
|
||||||
|
std::vector<uint8> temp;
|
||||||
|
RCHECK(reader->ReadVec(&temp, 2));
|
||||||
|
|
||||||
|
BitReader bit_reader(&temp[0], 2);
|
||||||
|
bit_reader.SkipBits(1);
|
||||||
|
for (int i = 0; i < 3; ++i) {
|
||||||
|
CHECK(bit_reader.ReadBits(5, &language[i]));
|
||||||
|
language[i] += 0x60;
|
||||||
|
}
|
||||||
|
language[3] = '\0';
|
||||||
|
|
||||||
|
return reader->SkipBytes(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
MediaInformation::MediaInformation() {}
|
MediaInformation::MediaInformation() {}
|
||||||
|
|
|
@ -145,6 +145,13 @@ struct HandlerReference : Box {
|
||||||
|
|
||||||
struct AVCDecoderConfigurationRecord : Box {
|
struct AVCDecoderConfigurationRecord : Box {
|
||||||
DECLARE_BOX_METHODS(AVCDecoderConfigurationRecord);
|
DECLARE_BOX_METHODS(AVCDecoderConfigurationRecord);
|
||||||
|
bool ParseData(BufferReader* reader);
|
||||||
|
|
||||||
|
// Contains full avc decoder configuration record as defined in iso14496-15
|
||||||
|
// 5.2.4.1, including possible extension bytes described in paragraph 3.
|
||||||
|
// Known fields defined in the spec are also parsed and included in this
|
||||||
|
// structure.
|
||||||
|
std::vector<uint8> data;
|
||||||
|
|
||||||
uint8 version;
|
uint8 version;
|
||||||
uint8 profile_indication;
|
uint8 profile_indication;
|
||||||
|
@ -307,6 +314,8 @@ struct MediaHeader : Box {
|
||||||
uint64 modification_time;
|
uint64 modification_time;
|
||||||
uint32 timescale;
|
uint32 timescale;
|
||||||
uint64 duration;
|
uint64 duration;
|
||||||
|
// 3-char language code + 1 null terminating char.
|
||||||
|
char language[4];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct MediaInformation : Box {
|
struct MediaInformation : Box {
|
||||||
|
|
|
@ -8,9 +8,7 @@
|
||||||
#include "base/callback_helpers.h"
|
#include "base/callback_helpers.h"
|
||||||
#include "base/logging.h"
|
#include "base/logging.h"
|
||||||
#include "base/memory/ref_counted.h"
|
#include "base/memory/ref_counted.h"
|
||||||
#include "base/time/time.h"
|
|
||||||
#include "media/base/audio_stream_info.h"
|
#include "media/base/audio_stream_info.h"
|
||||||
#include "media/base/buffers.h"
|
|
||||||
#include "media/base/media_sample.h"
|
#include "media/base/media_sample.h"
|
||||||
#include "media/base/video_stream_info.h"
|
#include "media/base/video_stream_info.h"
|
||||||
#include "media/mp4/box_definitions.h"
|
#include "media/mp4/box_definitions.h"
|
||||||
|
@ -21,11 +19,8 @@
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
base::TimeDelta TimeDeltaFromRational(int64 numer, int64 denom) {
|
uint64 Rescale(uint64 time_in_old_scale, uint32 old_scale, uint32 new_scale) {
|
||||||
DCHECK_LT((numer > 0 ? numer : -numer),
|
return (static_cast<double>(time_in_old_scale) / old_scale) * new_scale;
|
||||||
kint64max / base::Time::kMicrosecondsPerSecond);
|
|
||||||
return base::TimeDelta::FromMicroseconds(base::Time::kMicrosecondsPerSecond *
|
|
||||||
numer / denom);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
@ -41,8 +36,6 @@ MP4MediaParser::MP4MediaParser()
|
||||||
has_video_(false),
|
has_video_(false),
|
||||||
audio_track_id_(0),
|
audio_track_id_(0),
|
||||||
video_track_id_(0),
|
video_track_id_(0),
|
||||||
// TODO(kqyang): do we need to care about it??
|
|
||||||
has_sbr_(false),
|
|
||||||
is_audio_track_encrypted_(false),
|
is_audio_track_encrypted_(false),
|
||||||
is_video_track_encrypted_(false) {
|
is_video_track_encrypted_(false) {
|
||||||
}
|
}
|
||||||
|
@ -150,6 +143,23 @@ bool MP4MediaParser::ParseMoov(BoxReader* reader) {
|
||||||
|
|
||||||
for (std::vector<Track>::const_iterator track = moov_->tracks.begin();
|
for (std::vector<Track>::const_iterator track = moov_->tracks.begin();
|
||||||
track != moov_->tracks.end(); ++track) {
|
track != moov_->tracks.end(); ++track) {
|
||||||
|
const uint32 timescale = track->media.header.timescale;
|
||||||
|
|
||||||
|
// Calculate duration (based on timescale).
|
||||||
|
uint64 duration = 0;
|
||||||
|
if (track->media.header.duration > 0) {
|
||||||
|
duration = track->media.header.duration;
|
||||||
|
} else if (moov_->extends.header.fragment_duration > 0) {
|
||||||
|
DCHECK(moov_->header.timescale != 0);
|
||||||
|
duration = Rescale(moov_->extends.header.fragment_duration,
|
||||||
|
moov_->header.timescale, timescale);
|
||||||
|
} else if (moov_->header.duration > 0 &&
|
||||||
|
moov_->header.duration != kuint64max) {
|
||||||
|
DCHECK(moov_->header.timescale != 0);
|
||||||
|
duration = Rescale(moov_->header.duration, moov_->header.timescale,
|
||||||
|
timescale);
|
||||||
|
}
|
||||||
|
|
||||||
// TODO(strobe): Only the first audio and video track present in a file are
|
// TODO(strobe): Only the first audio and video track present in a file are
|
||||||
// used. (Track selection is better accomplished via Source IDs, though, so
|
// used. (Track selection is better accomplished via Source IDs, though, so
|
||||||
// adding support for track selection within a stream is low-priority.)
|
// adding support for track selection within a stream is low-priority.)
|
||||||
|
@ -209,22 +219,22 @@ bool MP4MediaParser::ParseMoov(BoxReader* reader) {
|
||||||
}
|
}
|
||||||
|
|
||||||
AudioCodec codec = kUnknownAudioCodec;
|
AudioCodec codec = kUnknownAudioCodec;
|
||||||
int num_channels = 0;
|
uint8 num_channels = 0;
|
||||||
int sample_per_second = 0;
|
uint32 sampling_frequency = 0;
|
||||||
|
uint8 audio_object_type = 0;
|
||||||
std::vector<uint8> extra_data;
|
std::vector<uint8> extra_data;
|
||||||
// Check if it is MPEG4 AAC defined in ISO 14496 Part 3 or
|
// Check if it is MPEG4 AAC defined in ISO 14496 Part 3 or
|
||||||
// supported MPEG2 AAC varients.
|
// supported MPEG2 AAC variants.
|
||||||
if (ESDescriptor::IsAAC(audio_type)) {
|
if (ESDescriptor::IsAAC(audio_type)) {
|
||||||
codec = kCodecAAC;
|
codec = kCodecAAC;
|
||||||
num_channels = aac.GetNumChannels(has_sbr_);
|
num_channels = aac.num_channels();
|
||||||
sample_per_second = aac.GetOutputSamplesPerSecond(has_sbr_);
|
sampling_frequency = aac.frequency();
|
||||||
#if defined(OS_ANDROID)
|
audio_object_type = aac.audio_object_type();
|
||||||
extra_data = aac.codec_specific_data();
|
extra_data = aac.codec_specific_data();
|
||||||
#endif
|
|
||||||
} else if (audio_type == kEAC3) {
|
} else if (audio_type == kEAC3) {
|
||||||
codec = kCodecEAC3;
|
codec = kCodecEAC3;
|
||||||
num_channels = entry.channelcount;
|
num_channels = entry.channelcount;
|
||||||
sample_per_second = entry.samplerate;
|
sampling_frequency = entry.samplerate;
|
||||||
} else {
|
} else {
|
||||||
LOG(ERROR) << "Unsupported audio object type 0x"
|
LOG(ERROR) << "Unsupported audio object type 0x"
|
||||||
<< std::hex << audio_type << " in esds.";
|
<< std::hex << audio_type << " in esds.";
|
||||||
|
@ -234,12 +244,16 @@ bool MP4MediaParser::ParseMoov(BoxReader* reader) {
|
||||||
is_audio_track_encrypted_ = entry.sinf.info.track_encryption.is_encrypted;
|
is_audio_track_encrypted_ = entry.sinf.info.track_encryption.is_encrypted;
|
||||||
DVLOG(1) << "is_audio_track_encrypted_: " << is_audio_track_encrypted_;
|
DVLOG(1) << "is_audio_track_encrypted_: " << is_audio_track_encrypted_;
|
||||||
streams.push_back(
|
streams.push_back(
|
||||||
new AudioStreamInfo(track->header.track_id,
|
new AudioStreamInfo(
|
||||||
track->media.header.timescale,
|
track->header.track_id,
|
||||||
|
timescale,
|
||||||
|
duration,
|
||||||
codec,
|
codec,
|
||||||
entry.samplesize / 8,
|
AudioStreamInfo::GetCodecString(codec, audio_object_type),
|
||||||
|
track->media.header.language,
|
||||||
|
entry.samplesize,
|
||||||
num_channels,
|
num_channels,
|
||||||
sample_per_second,
|
sampling_frequency,
|
||||||
extra_data.size() ? &extra_data[0] : NULL,
|
extra_data.size() ? &extra_data[0] : NULL,
|
||||||
extra_data.size(),
|
extra_data.size(),
|
||||||
is_audio_track_encrypted_));
|
is_audio_track_encrypted_));
|
||||||
|
@ -265,35 +279,31 @@ bool MP4MediaParser::ParseMoov(BoxReader* reader) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const std::string codec_string =
|
||||||
|
VideoStreamInfo::GetCodecString(
|
||||||
|
kCodecH264, entry.avcc.profile_indication,
|
||||||
|
entry.avcc.profile_compatibility, entry.avcc.avc_level);
|
||||||
|
|
||||||
is_video_track_encrypted_ = entry.sinf.info.track_encryption.is_encrypted;
|
is_video_track_encrypted_ = entry.sinf.info.track_encryption.is_encrypted;
|
||||||
DVLOG(1) << "is_video_track_encrypted_: " << is_video_track_encrypted_;
|
DVLOG(1) << "is_video_track_encrypted_: " << is_video_track_encrypted_;
|
||||||
streams.push_back(
|
streams.push_back(
|
||||||
new VideoStreamInfo(track->header.track_id,
|
new VideoStreamInfo(
|
||||||
track->media.header.timescale,
|
track->header.track_id,
|
||||||
|
timescale,
|
||||||
|
duration,
|
||||||
kCodecH264,
|
kCodecH264,
|
||||||
|
codec_string,
|
||||||
|
track->media.header.language,
|
||||||
entry.width,
|
entry.width,
|
||||||
entry.height,
|
entry.height,
|
||||||
// No decoder-specific buffer needed for AVC.
|
&entry.avcc.data[0],
|
||||||
NULL, 0,
|
entry.avcc.data.size(),
|
||||||
is_video_track_encrypted_));
|
is_video_track_encrypted_));
|
||||||
has_video_ = true;
|
has_video_ = true;
|
||||||
video_track_id_ = track->header.track_id;
|
video_track_id_ = track->header.track_id;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(kqyang): figure out how to get duration for every tracks/streams.
|
|
||||||
base::TimeDelta duration;
|
|
||||||
if (moov_->extends.header.fragment_duration > 0) {
|
|
||||||
duration = TimeDeltaFromRational(moov_->extends.header.fragment_duration,
|
|
||||||
moov_->header.timescale);
|
|
||||||
} else if (moov_->header.duration > 0 &&
|
|
||||||
moov_->header.duration != kuint64max) {
|
|
||||||
duration = TimeDeltaFromRational(moov_->header.duration,
|
|
||||||
moov_->header.timescale);
|
|
||||||
} else {
|
|
||||||
duration = kInfiniteDuration();
|
|
||||||
}
|
|
||||||
|
|
||||||
init_cb_.Run(true, streams);
|
init_cb_.Run(true, streams);
|
||||||
|
|
||||||
EmitNeedKeyIfNecessary(moov_->pssh);
|
EmitNeedKeyIfNecessary(moov_->pssh);
|
||||||
|
|
|
@ -16,13 +16,9 @@
|
||||||
|
|
||||||
namespace media {
|
namespace media {
|
||||||
|
|
||||||
class SubsampleEntry;
|
|
||||||
|
|
||||||
namespace mp4 {
|
namespace mp4 {
|
||||||
|
|
||||||
struct Movie;
|
struct Movie;
|
||||||
class AAC;
|
|
||||||
class AVCDecoderConfigurationRecord;
|
|
||||||
class BoxReader;
|
class BoxReader;
|
||||||
class ProtectionSystemSpecificHeader;
|
class ProtectionSystemSpecificHeader;
|
||||||
class TrackRunIterator;
|
class TrackRunIterator;
|
||||||
|
@ -92,7 +88,6 @@ class MP4MediaParser : public MediaParser {
|
||||||
bool has_video_;
|
bool has_video_;
|
||||||
uint32 audio_track_id_;
|
uint32 audio_track_id_;
|
||||||
uint32 video_track_id_;
|
uint32 video_track_id_;
|
||||||
bool has_sbr_;
|
|
||||||
bool is_audio_track_encrypted_;
|
bool is_audio_track_encrypted_;
|
||||||
bool is_video_track_encrypted_;
|
bool is_video_track_encrypted_;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue