Merge "Added ADTS header parsing, removal, and conversion to AudioSpecificConfig. Hooked up mp2t media parser, audio transmux now working."
This commit is contained in:
commit
faa12bd191
|
@ -15,6 +15,7 @@
|
|||
#include "media/base/media_stream.h"
|
||||
#include "media/base/stream_info.h"
|
||||
#include "media/file/file.h"
|
||||
#include "media/formats/mp2t/mp2t_media_parser.h"
|
||||
#include "media/formats/mp4/mp4_media_parser.h"
|
||||
|
||||
namespace {
|
||||
|
@ -58,6 +59,9 @@ Status Demuxer::Initialize() {
|
|||
case CONTAINER_MOV:
|
||||
parser_.reset(new mp4::MP4MediaParser());
|
||||
break;
|
||||
case CONTAINER_MPEG2TS:
|
||||
parser_.reset(new mp2t::MediaParser());
|
||||
break;
|
||||
default:
|
||||
NOTIMPLEMENTED();
|
||||
return Status(error::UNIMPLEMENTED, "Container not supported.");
|
||||
|
|
|
@ -36,8 +36,8 @@
|
|||
'h264_parser_unittest.cc',
|
||||
],
|
||||
'dependencies': [
|
||||
'../../media/base/media_base.gyp:base',
|
||||
'../../testing/gtest.gyp:gtest',
|
||||
'../../testing/gtest.gyp:gtest_main',
|
||||
'../test/media_test.gyp:media_test_support',
|
||||
'filters',
|
||||
],
|
||||
|
|
|
@ -0,0 +1,114 @@
|
|||
// Copyright 2014 Google Inc. All rights reserved.
|
||||
//
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file or at
|
||||
// https://developers.google.com/open-source/licenses/bsd
|
||||
|
||||
#include "adts_header.h"
|
||||
|
||||
#include "media/base/bit_reader.h"
|
||||
#include "media/formats/mp2t/mp2t_common.h"
|
||||
#include "media/formats/mpeg/adts_constants.h"
|
||||
|
||||
namespace media {
|
||||
namespace mp2t {
|
||||
|
||||
AdtsHeader::AdtsHeader()
|
||||
: valid_config_(false),
|
||||
profile_(0),
|
||||
sampling_frequency_index_(0),
|
||||
channel_configuration_(0) {}
|
||||
|
||||
size_t AdtsHeader::GetAdtsFrameSize(const uint8* data, size_t num_bytes) {
|
||||
if (num_bytes < 6)
|
||||
return 0;
|
||||
return ((static_cast<int>(data[5]) >> 5) |
|
||||
(static_cast<int>(data[4]) << 3) |
|
||||
((static_cast<int>(data[3]) & 0x3) << 11));
|
||||
}
|
||||
|
||||
size_t AdtsHeader::GetAdtsHeaderSize(const uint8* data, size_t num_bytes) {
|
||||
if (num_bytes < 2)
|
||||
return 0;
|
||||
if (data[1] & 0x01)
|
||||
return kAdtsHeaderMinSize;
|
||||
return kAdtsHeaderMinSize + sizeof(uint16); // Header + CRC.
|
||||
}
|
||||
|
||||
bool AdtsHeader::Parse(
|
||||
const uint8* adts_frame, size_t adts_frame_size) {
|
||||
CHECK(adts_frame);
|
||||
|
||||
valid_config_ = false;
|
||||
|
||||
BitReader frame(adts_frame, adts_frame_size);
|
||||
// Verify frame starts with sync bits (0xfff).
|
||||
uint32 sync;
|
||||
RCHECK(frame.ReadBits(12, &sync));
|
||||
RCHECK(sync == 0xfff);
|
||||
// Skip MPEG version and layer.
|
||||
RCHECK(frame.SkipBits(3));
|
||||
// Get "protection absent" flag.
|
||||
bool protection_absent;
|
||||
RCHECK(frame.ReadBits(1, &protection_absent));
|
||||
// Get profile.
|
||||
RCHECK(frame.ReadBits(2, &profile_));
|
||||
// Get sampling frequency.
|
||||
RCHECK(frame.ReadBits(4, &sampling_frequency_index_));
|
||||
RCHECK(sampling_frequency_index_ < kAdtsFrequencyTableSize);
|
||||
// Skip private stream bit.
|
||||
RCHECK(frame.SkipBits(1));
|
||||
// Get number of audio channels.
|
||||
RCHECK(frame.ReadBits(3, &channel_configuration_));
|
||||
RCHECK((channel_configuration_ > 0) &&
|
||||
(channel_configuration_ < kAdtsNumChannelsTableSize));
|
||||
// Skip originality, home and copyright info.
|
||||
RCHECK(frame.SkipBits(4));
|
||||
// Verify that the frame size matches input parameters.
|
||||
uint16 frame_size;
|
||||
RCHECK(frame.ReadBits(13, &frame_size));
|
||||
RCHECK(frame_size == adts_frame_size);
|
||||
// Skip buffer fullness indicator.
|
||||
RCHECK(frame.SkipBits(11));
|
||||
uint8 num_blocks_minus_1;
|
||||
RCHECK(frame.ReadBits(2, &num_blocks_minus_1));
|
||||
if (num_blocks_minus_1) {
|
||||
NOTIMPLEMENTED() << "ADTS frames with more than one data block "
|
||||
"not supported.";
|
||||
return false;
|
||||
}
|
||||
|
||||
valid_config_ = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool AdtsHeader::GetAudioSpecificConfig(
|
||||
std::vector<uint8>* buffer) const {
|
||||
DCHECK(buffer);
|
||||
if (!valid_config_)
|
||||
return false;
|
||||
|
||||
buffer->resize(2);
|
||||
(*buffer)[0] = ((profile_ + 1) << 3) | (sampling_frequency_index_ >> 1);
|
||||
(*buffer)[1] = ((sampling_frequency_index_ & 1) << 7) |
|
||||
(channel_configuration_ << 3);
|
||||
return true;
|
||||
}
|
||||
|
||||
uint8 AdtsHeader::GetObjectType() const {
|
||||
return profile_ + 1;
|
||||
}
|
||||
|
||||
uint32 AdtsHeader::GetSamplingFrequency() const {
|
||||
DCHECK_LT(sampling_frequency_index_, kAdtsFrequencyTableSize);
|
||||
return kAdtsFrequencyTable[sampling_frequency_index_];
|
||||
}
|
||||
|
||||
uint8 AdtsHeader::GetNumChannels() const {
|
||||
DCHECK_GT(channel_configuration_, 0);
|
||||
DCHECK_LT(channel_configuration_, kAdtsNumChannelsTableSize);
|
||||
return kAdtsNumChannelsTable[channel_configuration_];
|
||||
}
|
||||
|
||||
} // namespace mp2t
|
||||
} // namespace media
|
|
@ -0,0 +1,72 @@
|
|||
// Copyright 2014 Google Inc. All rights reserved.
|
||||
//
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file or at
|
||||
// https://developers.google.com/open-source/licenses/bsd
|
||||
|
||||
#ifndef MEDIA_FORMATS_MP2T_ADTS_HEADER_H_
|
||||
#define MEDIA_FORMATS_MP2T_ADTS_HEADER_H_
|
||||
|
||||
#include "base/basictypes.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace media {
|
||||
namespace mp2t {
|
||||
|
||||
/// Class which parses ADTS headers and synthesizes AudioSpecificConfig
|
||||
/// and audio mime type from ADTS header contents.
|
||||
class AdtsHeader {
|
||||
public:
|
||||
AdtsHeader();
|
||||
~AdtsHeader() {}
|
||||
|
||||
/// Get the size of the ADTS frame from a partial or complete frame.
|
||||
/// @param data is a pointer to the beginning of the ADTS frame.
|
||||
/// @param num_bytes is the number of data bytes at @a data.
|
||||
/// @return Size of the ADTS frame (header + payload) if successful, or
|
||||
/// zero otherwise.
|
||||
static size_t GetAdtsFrameSize(const uint8* data, size_t num_bytes);
|
||||
|
||||
/// Get the size of the ADTS header from a partial or complete frame.
|
||||
/// @param data is a pointer to the beginning of the ADTS frame.
|
||||
/// @param num_bytes is the number of data bytes at @a data.
|
||||
/// @return Size of the ADTS header if successful, or zero otherwise.
|
||||
static size_t GetAdtsHeaderSize(const uint8* data, size_t num_bytes);
|
||||
|
||||
/// Parse an ADTS header, extracting the fields within.
|
||||
/// @param adts_frame is an input parameter pointing to the ADTS header
|
||||
/// of an ADTS-framed audio sample.
|
||||
/// @param adts_frame_size is the size, in bytes of the input ADTS frame.
|
||||
/// @return true if successful, false otherwise.
|
||||
bool Parse(const uint8* adts_frame, size_t adts_frame_size);
|
||||
|
||||
/// Synthesize an AudioSpecificConfig record from the fields within the ADTS
|
||||
/// header.
|
||||
/// @param [out] buffer is a pointer to a vector to contain the
|
||||
/// AudioSpecificConfig.
|
||||
/// @return true if successful, false otherwise.
|
||||
bool GetAudioSpecificConfig(std::vector<uint8>* buffer) const;
|
||||
|
||||
/// @return The audio profile for this ADTS frame.
|
||||
uint8 GetObjectType() const;
|
||||
|
||||
/// @return The sampling frequency for this ADTS frame.
|
||||
uint32 GetSamplingFrequency() const;
|
||||
|
||||
/// @return Number of channels for this AAC config.
|
||||
uint8 GetNumChannels() const;
|
||||
|
||||
private:
|
||||
bool valid_config_;
|
||||
uint8 profile_;
|
||||
uint8 sampling_frequency_index_;
|
||||
uint8 channel_configuration_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(AdtsHeader);
|
||||
};
|
||||
|
||||
} // namespace mp2t
|
||||
} // namespace media
|
||||
|
||||
#endif // MEDIA_FORMATS_MP2T_ADTS_HEADER_H_
|
|
@ -0,0 +1,91 @@
|
|||
// Copyright 2014 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 "base/logging.h"
|
||||
#include "base/strings/string_number_conversions.h"
|
||||
#include "media/formats/mp2t/adts_header.h"
|
||||
#include "testing/gtest/include/gtest/gtest.h"
|
||||
|
||||
namespace {
|
||||
|
||||
const char kValidAdtsFrame[] =
|
||||
"fff15080429ffcda004c61766335332e33352e30004258892a5361062403"
|
||||
"d040000000001ff9055e9fe77ac56eb1677484e0ef0c3102a39daa8355a5"
|
||||
"37ecab2b156e4ba73ceedb24ea51194e57c9385fa67eca8edc914902e852"
|
||||
"3185b52299516e679fb3768aa9f13ccac5b257410080282c9a50318ec94e"
|
||||
"ba24ea305bafab2b2beab16557ef9ecaa8f17bedea84788c8d42e4b3c65b"
|
||||
"1e7ecae7528b909bc46c76cca73b906ec980ed9f32b25ecd28f43f9516de"
|
||||
"3ff249f23bb9c93e64c4808195f284653c40592c1a8dc847f5f11791fd80"
|
||||
"b18e02c1e1ed9f82c62a1f8ea0f5b6dbf2112c2202973b00de71bb49f906"
|
||||
"ed1bc63768dda378c8f9c6ed1bb48f68dda378c9f68dda3768dda3768de3"
|
||||
"23da3768de31bb492a5361062403d040000000001ff9055e9fe77ac56eb1"
|
||||
"677484e0ef0c3102a39daa8355a537ecab2b156e4ba73ceedb24ea51194e"
|
||||
"57c9385fa67eca8edc914902e8523185b52299516e679fb3768aa9f13cca"
|
||||
"c5b257410080282c9a50318ec94eba24ea305bafab2b2beab16557ef9eca"
|
||||
"a8f17bedea84788c8d42e4b3c65b1e7ecae7528b909bc46c76cca73b906e"
|
||||
"c980ed9f32b25ecd28f43f9516de3ff249f23bb9c93e64c4808195f28465"
|
||||
"3c40592c1a8dc847f5f11791fd80b18e02c1e1ed9f82c62a1f8ea0f5b6db"
|
||||
"f2112c2202973b00de71bb49f906ed1bc63768dda378c8f9c6ed1bb48f68"
|
||||
"dda378c9f68dda3768dda3768de323da3768de31bb4e";
|
||||
|
||||
const uint8 kExpectedAudioSpecificConfig[] = { 0x12, 0x10 };
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
namespace media {
|
||||
namespace mp2t {
|
||||
|
||||
class AdtsHeaderTest : public testing::Test {
|
||||
public:
|
||||
virtual void SetUp() OVERRIDE {
|
||||
ASSERT_TRUE(base::HexStringToBytes(kValidAdtsFrame, &adts_frame_));
|
||||
}
|
||||
|
||||
protected:
|
||||
std::vector<uint8> adts_frame_;
|
||||
};
|
||||
|
||||
TEST_F(AdtsHeaderTest, ParseSuccess) {
|
||||
const uint8 kExpectedObjectType(2);
|
||||
const uint32 kExpectedSamplingFrequency(44100);
|
||||
const uint8 kExpectedNumChannels(2);
|
||||
AdtsHeader adts_header;
|
||||
EXPECT_TRUE(adts_header.Parse(adts_frame_.data(), adts_frame_.size()));
|
||||
EXPECT_EQ(kExpectedObjectType, adts_header.GetObjectType());
|
||||
EXPECT_EQ(kExpectedSamplingFrequency, adts_header.GetSamplingFrequency());
|
||||
EXPECT_EQ(kExpectedNumChannels, adts_header.GetNumChannels());
|
||||
std::vector<uint8> audio_specific_config;
|
||||
ASSERT_TRUE(adts_header.GetAudioSpecificConfig(&audio_specific_config));
|
||||
EXPECT_EQ(arraysize(kExpectedAudioSpecificConfig),
|
||||
audio_specific_config.size());
|
||||
EXPECT_EQ(
|
||||
std::vector<uint8>(
|
||||
kExpectedAudioSpecificConfig,
|
||||
kExpectedAudioSpecificConfig + arraysize(kExpectedAudioSpecificConfig)),
|
||||
audio_specific_config);
|
||||
}
|
||||
|
||||
TEST_F(AdtsHeaderTest, ParseFailFrameSize) {
|
||||
|
||||
AdtsHeader adts_header;
|
||||
EXPECT_FALSE(adts_header.Parse(adts_frame_.data(), adts_frame_.size() - 1));
|
||||
EXPECT_FALSE(adts_header.Parse(adts_frame_.data(), adts_frame_.size() + 1));
|
||||
EXPECT_FALSE(adts_header.Parse(adts_frame_.data(), 1));
|
||||
}
|
||||
|
||||
TEST_F(AdtsHeaderTest, GetFrameSizeSuccess) {
|
||||
EXPECT_EQ(adts_frame_.size(),
|
||||
AdtsHeader::GetAdtsFrameSize(adts_frame_.data(),
|
||||
adts_frame_.size()));
|
||||
}
|
||||
|
||||
TEST_F(AdtsHeaderTest, GetHeaderSizeSuccess) {
|
||||
const size_t kExpectedHeaderSize(7);
|
||||
EXPECT_EQ(kExpectedHeaderSize,
|
||||
AdtsHeader::GetAdtsHeaderSize(adts_frame_.data(),
|
||||
adts_frame_.size()));
|
||||
}
|
||||
|
||||
} // Namespace mp2t
|
||||
} // namespace media
|
|
@ -13,26 +13,12 @@
|
|||
#include "media/base/bit_reader.h"
|
||||
#include "media/base/media_sample.h"
|
||||
#include "media/base/timestamp.h"
|
||||
#include "media/formats/mp2t/adts_header.h"
|
||||
#include "media/formats/mp2t/mp2t_common.h"
|
||||
#include "media/formats/mpeg/adts_constants.h"
|
||||
|
||||
namespace media {
|
||||
|
||||
static int ExtractAdtsFrameSize(const uint8* adts_header) {
|
||||
return ((static_cast<int>(adts_header[5]) >> 5) |
|
||||
(static_cast<int>(adts_header[4]) << 3) |
|
||||
((static_cast<int>(adts_header[3]) & 0x3) << 11));
|
||||
}
|
||||
|
||||
static size_t ExtractAdtsFrequencyIndex(const uint8* adts_header) {
|
||||
return ((adts_header[2] >> 2) & 0xf);
|
||||
}
|
||||
|
||||
static size_t ExtractAdtsChannelConfig(const uint8* adts_header) {
|
||||
return (((adts_header[3] >> 6) & 0x3) |
|
||||
((adts_header[2] & 0x1) << 2));
|
||||
}
|
||||
|
||||
// Return true if buf corresponds to an ADTS syncword.
|
||||
// |buf| size must be at least 2.
|
||||
static bool isAdtsSyncWord(const uint8* buf) {
|
||||
|
@ -72,7 +58,8 @@ static bool LookForSyncWord(const uint8* raw_es, int raw_es_size,
|
|||
// The layer field (2 bits) must be set to 0.
|
||||
continue;
|
||||
|
||||
int frame_size = ExtractAdtsFrameSize(cur_buf);
|
||||
int frame_size =
|
||||
mp2t::AdtsHeader::GetAdtsFrameSize(cur_buf, kAdtsHeaderMinSize);
|
||||
if (frame_size < kAdtsHeaderMinSize) {
|
||||
// Too short to be an ADTS frame.
|
||||
continue;
|
||||
|
@ -131,21 +118,24 @@ bool EsParserAdts::Parse(const uint8* buf, int size, int64 pts, int64 dts) {
|
|||
int frame_size;
|
||||
while (LookForSyncWord(raw_es, raw_es_size, es_position,
|
||||
&es_position, &frame_size)) {
|
||||
const uint8* frame_ptr = raw_es + es_position;
|
||||
DVLOG(LOG_LEVEL_ES)
|
||||
<< "ADTS syncword @ pos=" << es_position
|
||||
<< " frame_size=" << frame_size;
|
||||
DVLOG(LOG_LEVEL_ES)
|
||||
<< "ADTS header: "
|
||||
<< base::HexEncode(&raw_es[es_position], kAdtsHeaderMinSize);
|
||||
<< base::HexEncode(frame_ptr, kAdtsHeaderMinSize);
|
||||
|
||||
// Do not process the frame if this one is a partial frame.
|
||||
int remaining_size = raw_es_size - es_position;
|
||||
if (frame_size > remaining_size)
|
||||
break;
|
||||
|
||||
size_t header_size = AdtsHeader::GetAdtsHeaderSize(frame_ptr, frame_size);
|
||||
|
||||
// Update the audio configuration if needed.
|
||||
DCHECK_GE(frame_size, kAdtsHeaderMinSize);
|
||||
if (!UpdateAudioConfiguration(&raw_es[es_position]))
|
||||
if (!UpdateAudioConfiguration(frame_ptr, frame_size))
|
||||
return false;
|
||||
|
||||
// Get the PTS & the duration of this access unit.
|
||||
|
@ -164,8 +154,8 @@ bool EsParserAdts::Parse(const uint8* buf, int size, int64 pts, int64 dts) {
|
|||
|
||||
scoped_refptr<MediaSample> sample =
|
||||
MediaSample::CopyFrom(
|
||||
&raw_es[es_position],
|
||||
frame_size,
|
||||
frame_ptr + header_size,
|
||||
frame_size - header_size,
|
||||
is_key_frame);
|
||||
sample->set_pts(current_pts);
|
||||
sample->set_dts(current_pts);
|
||||
|
@ -194,37 +184,34 @@ void EsParserAdts::Reset() {
|
|||
last_audio_decoder_config_ = scoped_refptr<AudioStreamInfo>();
|
||||
}
|
||||
|
||||
bool EsParserAdts::UpdateAudioConfiguration(const uint8* adts_header) {
|
||||
bool EsParserAdts::UpdateAudioConfiguration(const uint8* adts_frame,
|
||||
size_t adts_frame_size) {
|
||||
|
||||
const uint8 kAacSampleSizeBits(16);
|
||||
|
||||
AdtsHeader adts_header;
|
||||
if (!adts_header.Parse(adts_frame, adts_frame_size)) {
|
||||
LOG(ERROR) << "Error parsing ADTS frame header.";
|
||||
return false;
|
||||
}
|
||||
std::vector<uint8> audio_specific_config;
|
||||
if (!adts_header.GetAudioSpecificConfig(&audio_specific_config))
|
||||
return false;
|
||||
|
||||
if (last_audio_decoder_config_) {
|
||||
// Varying audio configurations currently not supported. Just assume that
|
||||
// the audio configuration has not changed.
|
||||
return true;
|
||||
}
|
||||
|
||||
size_t frequency_index = ExtractAdtsFrequencyIndex(adts_header);
|
||||
if (frequency_index >= kAdtsFrequencyTableSize) {
|
||||
// Frequency index 13 & 14 are reserved
|
||||
// while 15 means that the frequency is explicitly written
|
||||
// (not supported).
|
||||
// Verify that the audio decoder config has not changed.
|
||||
if (last_audio_decoder_config_->extra_data() == audio_specific_config) {
|
||||
// Audio configuration has not changed.
|
||||
return true;
|
||||
}
|
||||
NOTIMPLEMENTED() << "Varying audio configurations are not supported.";
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t channel_configuration = ExtractAdtsChannelConfig(adts_header);
|
||||
if (channel_configuration == 0 ||
|
||||
channel_configuration >= kAdtsNumChannelsTableSize) {
|
||||
// TODO(damienv): Add support for inband channel configuration.
|
||||
return false;
|
||||
}
|
||||
|
||||
// TODO(damienv): support HE-AAC frequency doubling (SBR)
|
||||
// based on the incoming ADTS profile.
|
||||
int samples_per_second = kAdtsFrequencyTable[frequency_index];
|
||||
int adts_profile = (adts_header[2] >> 6) & 0x3;
|
||||
|
||||
// The following code is written according to ISO 14496 Part 3 Table 1.11 and
|
||||
// Table 1.22. (Table 1.11 refers to the capping to 48000, Table 1.22 refers
|
||||
// to SBR doubling the AAC sample rate.)
|
||||
// TODO(damienv) : Extend sample rate cap to 96kHz for Level 5 content.
|
||||
int samples_per_second = adts_header.GetSamplingFrequency();
|
||||
int extended_samples_per_second = sbr_in_mimetype_
|
||||
? std::min(2 * samples_per_second, 48000)
|
||||
: samples_per_second;
|
||||
|
@ -235,19 +222,20 @@ bool EsParserAdts::UpdateAudioConfiguration(const uint8* adts_header) {
|
|||
kMpeg2Timescale,
|
||||
kInfiniteDuration,
|
||||
kCodecAAC,
|
||||
std::string(), // TODO(tinskip): calculate codec string.
|
||||
AudioStreamInfo::GetCodecString(kCodecAAC,
|
||||
adts_header.GetObjectType()),
|
||||
std::string(),
|
||||
16,
|
||||
kAdtsNumChannelsTable[channel_configuration],
|
||||
samples_per_second,
|
||||
NULL, // TODO(tinskip): calculate AudioSpecificConfig.
|
||||
0,
|
||||
kAacSampleSizeBits,
|
||||
adts_header.GetNumChannels(),
|
||||
extended_samples_per_second,
|
||||
audio_specific_config.data(),
|
||||
audio_specific_config.size(),
|
||||
false));
|
||||
|
||||
DVLOG(1) << "Sampling frequency: " << samples_per_second;
|
||||
DVLOG(1) << "Extended sampling frequency: " << extended_samples_per_second;
|
||||
DVLOG(1) << "Channel config: " << channel_configuration;
|
||||
DVLOG(1) << "Adts profile: " << adts_profile;
|
||||
DVLOG(1) << "Channel config: " << adts_header.GetNumChannels();
|
||||
DVLOG(1) << "Object type: " << adts_header.GetObjectType();
|
||||
// Reset the timestamp helper to use a new sampling frequency.
|
||||
if (audio_timestamp_helper_) {
|
||||
int64 base_timestamp = audio_timestamp_helper_->GetTimestamp();
|
||||
|
@ -256,7 +244,7 @@ bool EsParserAdts::UpdateAudioConfiguration(const uint8* adts_header) {
|
|||
audio_timestamp_helper_->SetBaseTimestamp(base_timestamp);
|
||||
} else {
|
||||
audio_timestamp_helper_.reset(
|
||||
new AudioTimestampHelper(kMpeg2Timescale, samples_per_second));
|
||||
new AudioTimestampHelper(kMpeg2Timescale, extended_samples_per_second));
|
||||
}
|
||||
|
||||
// Audio config notification.
|
||||
|
|
|
@ -46,7 +46,7 @@ class EsParserAdts : public EsParser {
|
|||
// Signal any audio configuration change (if any).
|
||||
// Return false if the current audio config is not
|
||||
// a supported ADTS audio config.
|
||||
bool UpdateAudioConfiguration(const uint8* adts_header);
|
||||
bool UpdateAudioConfiguration(const uint8* adts_frame, size_t frame_size);
|
||||
|
||||
// Discard some bytes from the ES stream.
|
||||
void DiscardEs(int nbytes);
|
||||
|
|
|
@ -19,6 +19,8 @@
|
|||
'target_name': 'mp2t',
|
||||
'type': '<(component)',
|
||||
'sources': [
|
||||
'adts_header.cc',
|
||||
'adts_header.h',
|
||||
'es_parser.h',
|
||||
'es_parser_adts.cc',
|
||||
'es_parser_adts.h',
|
||||
|
@ -45,6 +47,7 @@
|
|||
'target_name': 'mp2t_unittest',
|
||||
'type': '<(gtest_target_type)',
|
||||
'sources': [
|
||||
'adts_header_unittest.cc',
|
||||
'es_parser_h264_unittest.cc',
|
||||
'mp2t_media_parser_unittest.cc',
|
||||
],
|
||||
|
|
|
@ -27,7 +27,10 @@
|
|||
'dependencies': [
|
||||
'media/event/media_event.gyp:media_event',
|
||||
'media/file/file.gyp:file',
|
||||
'media/filters/filters.gyp:filters',
|
||||
'media/formats/mp2t/mp2t.gyp:mp2t',
|
||||
'media/formats/mp4/mp4.gyp:mp4',
|
||||
'media/formats/mpeg/mpeg.gyp:mpeg',
|
||||
'third_party/gflags/gflags.gyp:gflags',
|
||||
],
|
||||
},
|
||||
|
@ -52,7 +55,10 @@
|
|||
],
|
||||
'dependencies': [
|
||||
'media/file/file.gyp:file',
|
||||
'media/filters/filters.gyp:filters',
|
||||
'media/formats/mp2t/mp2t.gyp:mp2t',
|
||||
'media/formats/mp4/mp4.gyp:mp4',
|
||||
'media/formats/mpeg/mpeg.gyp:mpeg',
|
||||
'media/test/media_test.gyp:media_test_support',
|
||||
'testing/gtest.gyp:gtest',
|
||||
],
|
||||
|
@ -64,6 +70,7 @@
|
|||
'media/base/media_base.gyp:*',
|
||||
'media/event/media_event.gyp:*',
|
||||
'media/file/file.gyp:*',
|
||||
'media/formats/mp2t/mp2t.gyp:*',
|
||||
'media/formats/mp4/mp4.gyp:*',
|
||||
'mpd/mpd.gyp:*',
|
||||
],
|
||||
|
|
Loading…
Reference in New Issue