From 2a2493ec2eac9e2050ef89017dc74285335b384a Mon Sep 17 00:00:00 2001 From: KongQun Yang Date: Sun, 22 Oct 2017 22:27:27 -0700 Subject: [PATCH] Refactor EsParserAdts to handle other audio Rename will happen in next CL Change-Id: I28df29bb264eea7a6225b0a4a2eb38de7968f9d6 --- packager/media/formats/mp2t/adts_header.cc | 65 +++++------ packager/media/formats/mp2t/adts_header.h | 71 +++++------- .../formats/mp2t/adts_header_unittest.cc | 38 +++---- packager/media/formats/mp2t/audio_header.h | 79 +++++++++++++ packager/media/formats/mp2t/es_parser_adts.cc | 104 ++++++++---------- packager/media/formats/mp2t/es_parser_adts.h | 9 +- packager/media/formats/mp2t/mp2t.gyp | 1 + .../media/formats/wvm/wvm_media_parser.cc | 16 +-- 8 files changed, 202 insertions(+), 181 deletions(-) create mode 100644 packager/media/formats/mp2t/audio_header.h diff --git a/packager/media/formats/mp2t/adts_header.cc b/packager/media/formats/mp2t/adts_header.cc index 73d05c6a03..ef64e0fc1e 100644 --- a/packager/media/formats/mp2t/adts_header.cc +++ b/packager/media/formats/mp2t/adts_header.cc @@ -7,6 +7,7 @@ #include "packager/media/formats/mp2t/adts_header.h" #include "packager/media/base/bit_reader.h" +#include "packager/media/base/bit_writer.h" #include "packager/media/formats/mp2t/mp2t_common.h" #include "packager/media/formats/mpeg/adts_constants.h" @@ -14,32 +15,19 @@ namespace shaka { namespace media { namespace mp2t { -AdtsHeader::AdtsHeader() - : valid_config_(false), - profile_(0), - sampling_frequency_index_(0), - channel_configuration_(0) {} - -size_t AdtsHeader::GetAdtsFrameSize(const uint8_t* data, size_t num_bytes) { - if (num_bytes < 6) - return 0; - return ((static_cast(data[5]) >> 5) | - (static_cast(data[4]) << 3) | - ((static_cast(data[3]) & 0x3) << 11)); +bool AdtsHeader::IsSyncWord(const uint8_t* buf) const { + return (buf[0] == 0xff) && ((buf[1] & 0xf6) == 0xf0); } -size_t AdtsHeader::GetAdtsHeaderSize(const uint8_t* data, size_t num_bytes) { - if (num_bytes < 2) - return 0; - if (data[1] & 0x01) - return kAdtsHeaderMinSize; - return kAdtsHeaderMinSize + sizeof(uint16_t); // Header + CRC. +size_t AdtsHeader::GetMinFrameSize() const { + return kAdtsHeaderMinSize + 1; } bool AdtsHeader::Parse(const uint8_t* adts_frame, size_t adts_frame_size) { CHECK(adts_frame); - valid_config_ = false; + if (adts_frame_size < kAdtsHeaderMinSize) + return false; BitReader frame(adts_frame, adts_frame_size); // Verify frame starts with sync bits (0xfff). @@ -48,26 +36,18 @@ bool AdtsHeader::Parse(const uint8_t* adts_frame, size_t adts_frame_size) { RCHECK(sync == 0xfff); // Skip MPEG version and layer. RCHECK(frame.SkipBits(3)); - // Get "protection absent" flag. - uint8_t protection_absent; - RCHECK(frame.ReadBits(1, &protection_absent)); - // Get profile. + RCHECK(frame.ReadBits(1, &protection_absent_)); 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_t frame_size; - RCHECK(frame.ReadBits(13, &frame_size)); - RCHECK(frame_size == adts_frame_size); + RCHECK(frame.ReadBits(13, &frame_size_)); // Skip buffer fullness indicator. RCHECK(frame.SkipBits(11)); uint8_t num_blocks_minus_1; @@ -77,21 +57,26 @@ bool AdtsHeader::Parse(const uint8_t* adts_frame, size_t adts_frame_size) { "not supported."; return false; } - - valid_config_ = true; return true; } -bool AdtsHeader::GetAudioSpecificConfig(std::vector* buffer) const { - DCHECK(buffer); - if (!valid_config_) - return false; +size_t AdtsHeader::GetHeaderSize() const { + const size_t kCrcSize = sizeof(uint16_t); + return kAdtsHeaderMinSize + (protection_absent_ ? 0 : kCrcSize); +} - buffer->resize(2); - (*buffer)[0] = ((profile_ + 1) << 3) | (sampling_frequency_index_ >> 1); - (*buffer)[1] = ((sampling_frequency_index_ & 1) << 7) | - (channel_configuration_ << 3); - return true; +size_t AdtsHeader::GetFrameSize() const { + return frame_size_; +} + +void AdtsHeader::GetAudioSpecificConfig(std::vector* buffer) const { + DCHECK(buffer); + buffer->clear(); + BitWriter config(buffer); + config.WriteBits(GetObjectType(), 5); + config.WriteBits(sampling_frequency_index_, 4); + config.WriteBits(channel_configuration_, 4); + config.Flush(); } uint8_t AdtsHeader::GetObjectType() const { diff --git a/packager/media/formats/mp2t/adts_header.h b/packager/media/formats/mp2t/adts_header.h index 777da1c981..feb8f85706 100644 --- a/packager/media/formats/mp2t/adts_header.h +++ b/packager/media/formats/mp2t/adts_header.h @@ -11,62 +11,41 @@ #include -#include "packager/base/macros.h" +#include "packager/media/formats/mp2t/audio_header.h" namespace shaka { namespace media { namespace mp2t { -/// Class which parses ADTS headers and synthesizes AudioSpecificConfig -/// and audio mime type from ADTS header contents. -class AdtsHeader { +/// Class which parses ADTS frame (header / metadata) and synthesizes +/// AudioSpecificConfig from audio frame content. +class AdtsHeader : public AudioHeader { public: - AdtsHeader(); - ~AdtsHeader() {} + AdtsHeader() = default; + ~AdtsHeader() override = default; - /// 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_t* 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_t* 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_t* 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* buffer) const; - - /// @return The audio profile for this ADTS frame. - uint8_t GetObjectType() const; - - /// @return The sampling frequency for this ADTS frame. - uint32_t GetSamplingFrequency() const; - - /// @return Number of channels for this AAC config. - uint8_t GetNumChannels() const; + /// @name AudioHeader implementation overrides. + /// @{ + bool IsSyncWord(const uint8_t* buf) const override; + size_t GetMinFrameSize() const override; + bool Parse(const uint8_t* adts_frame, size_t adts_frame_size) override; + size_t GetHeaderSize() const override; + size_t GetFrameSize() const override; + void GetAudioSpecificConfig(std::vector* buffer) const override; + uint8_t GetObjectType() const override; + uint32_t GetSamplingFrequency() const override; + uint8_t GetNumChannels() const override; + /// @} private: - bool valid_config_; - uint8_t profile_; - uint8_t sampling_frequency_index_; - uint8_t channel_configuration_; + AdtsHeader(const AdtsHeader&) = delete; + AdtsHeader& operator=(const AdtsHeader&) = delete; - DISALLOW_COPY_AND_ASSIGN(AdtsHeader); + uint8_t protection_absent_ = 0; + uint16_t frame_size_ = 0; + uint8_t profile_ = 0; + uint8_t sampling_frequency_index_ = 0; + uint8_t channel_configuration_ = 0; }; } // namespace mp2t diff --git a/packager/media/formats/mp2t/adts_header_unittest.cc b/packager/media/formats/mp2t/adts_header_unittest.cc index f1c422787b..4a5d3b3c5d 100644 --- a/packager/media/formats/mp2t/adts_header_unittest.cc +++ b/packager/media/formats/mp2t/adts_header_unittest.cc @@ -4,7 +4,6 @@ #include -#include "packager/base/compiler_specific.h" #include "packager/base/logging.h" #include "packager/base/strings/string_number_conversions.h" #include "packager/media/formats/mp2t/adts_header.h" @@ -50,16 +49,19 @@ class AdtsHeaderTest : public testing::Test { }; TEST_F(AdtsHeaderTest, ParseSuccess) { + const size_t kExpectedHeaderSize(7); const uint8_t kExpectedObjectType(2); const uint32_t kExpectedSamplingFrequency(44100); const uint8_t kExpectedNumChannels(2); AdtsHeader adts_header; - EXPECT_TRUE(adts_header.Parse(adts_frame_.data(), adts_frame_.size())); + ASSERT_TRUE(adts_header.Parse(adts_frame_.data(), adts_frame_.size())); + EXPECT_EQ(adts_frame_.size(), adts_header.GetFrameSize()); + EXPECT_EQ(kExpectedHeaderSize, adts_header.GetHeaderSize()); EXPECT_EQ(kExpectedObjectType, adts_header.GetObjectType()); EXPECT_EQ(kExpectedSamplingFrequency, adts_header.GetSamplingFrequency()); EXPECT_EQ(kExpectedNumChannels, adts_header.GetNumChannels()); std::vector audio_specific_config; - ASSERT_TRUE(adts_header.GetAudioSpecificConfig(&audio_specific_config)); + adts_header.GetAudioSpecificConfig(&audio_specific_config); EXPECT_EQ(arraysize(kExpectedAudioSpecificConfig), audio_specific_config.size()); EXPECT_EQ(std::vector(kExpectedAudioSpecificConfig, @@ -68,25 +70,21 @@ TEST_F(AdtsHeaderTest, ParseSuccess) { audio_specific_config); } -TEST_F(AdtsHeaderTest, ParseFailFrameSize) { - +TEST_F(AdtsHeaderTest, ParseVariousDataSize) { 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)); + + // Parse succeeds as long as the full header is provided. + EXPECT_TRUE(adts_header.Parse(adts_frame_.data(), adts_frame_.size() - 1)); + const size_t header_size = adts_header.GetHeaderSize(); + EXPECT_EQ(adts_frame_.size(), adts_header.GetFrameSize()); + + EXPECT_TRUE(adts_header.Parse(adts_frame_.data(), header_size)); + EXPECT_EQ(adts_frame_.size(), adts_header.GetFrameSize()); + EXPECT_EQ(header_size, adts_header.GetHeaderSize()); + + // Parse fails if there is not enough data (no full header). 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())); + EXPECT_FALSE(adts_header.Parse(adts_frame_.data(), header_size - 1)); } } // Namespace mp2t diff --git a/packager/media/formats/mp2t/audio_header.h b/packager/media/formats/mp2t/audio_header.h new file mode 100644 index 0000000000..20660162c3 --- /dev/null +++ b/packager/media/formats/mp2t/audio_header.h @@ -0,0 +1,79 @@ +// Copyright 2017 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 PACKAGER_MEDIA_FORMATS_MP2T_AUDIO_HEADER_H_ +#define PACKAGER_MEDIA_FORMATS_MP2T_AUDIO_HEADER_H_ + +#include +#include + +#include + +namespace shaka { +namespace media { +namespace mp2t { + +class AudioHeader { + public: + AudioHeader() = default; + virtual ~AudioHeader() = default; + + /// Check if the leading word (2 bytes) is sync signal. + /// @param buf points to the buffer to be checked. Must be at least 2 bytes. + /// @return true if corresponds to a syncword. + virtual bool IsSyncWord(const uint8_t* buf) const = 0; + + /// @return The minium frame size. + virtual size_t GetMinFrameSize() const = 0; + + /// Parse a partial audio frame, extracting the fields within. Only audio + /// frame header / metadata is parsed. The audio_frame_size must contain the + /// full header / metadata. + /// @param audio_frame is an input parameter pointing to an audio frame. + /// @param audio_frame_size is the size, in bytes of the input data. It can be + /// smaller than the actual frame size, but it should not be smaller + /// than the header size. + /// @return true if successful, false otherwise. + virtual bool Parse(const uint8_t* audio_frame, size_t audio_frame_size) = 0; + + /// Should only be called after a successful Parse. + /// @return The size of audio header. + virtual size_t GetHeaderSize() const = 0; + + /// Should only be called after a successful Parse. + /// @return the size of frame (header + payload). + virtual size_t GetFrameSize() const = 0; + + /// Synthesize an AudioSpecificConfig record from the fields within the audio + /// header. + /// Should only be called after a successful Parse. + /// @param [out] buffer is a pointer to a vector to contain the + /// AudioSpecificConfig. + /// @return true if successful, false otherwise. + virtual void GetAudioSpecificConfig(std::vector* buffer) const = 0; + + /// Should only be called after a successful Parse. + /// @return The audio profile for this frame. Only meaningful for AAC. + virtual uint8_t GetObjectType() const = 0; + + /// Should only be called after a successful Parse. + /// @return The sampling frequency for this frame. + virtual uint32_t GetSamplingFrequency() const = 0; + + /// Should only be called after a successful Parse. + /// @return Number of channels for this frame. + virtual uint8_t GetNumChannels() const = 0; + + private: + AudioHeader(const AudioHeader&) = delete; + AudioHeader& operator=(const AudioHeader&) = delete; +}; + +} // namespace mp2t +} // namespace media +} // namespace shaka + +#endif // PACKAGER_MEDIA_FORMATS_MP2T_AUDIO_HEADER_H_ diff --git a/packager/media/formats/mp2t/es_parser_adts.cc b/packager/media/formats/mp2t/es_parser_adts.cc index 4aa81989e4..14b7f14b41 100644 --- a/packager/media/formats/mp2t/es_parser_adts.cc +++ b/packager/media/formats/mp2t/es_parser_adts.cc @@ -21,29 +21,26 @@ namespace shaka { namespace media { +namespace mp2t { -// Return true if buf corresponds to an ADTS syncword. -// |buf| size must be at least 2. -static bool isAdtsSyncWord(const uint8_t* buf) { - return (buf[0] == 0xff) && ((buf[1] & 0xf6) == 0xf0); -} - -// Look for an ADTS syncword. +// Look for a syncword. // |new_pos| returns -// - either the byte position of the ADTS frame (if found) +// - either the byte position of the frame (if found) // - or the byte position of 1st byte that was not processed (if not found). // In every case, the returned value in |new_pos| is such that new_pos >= pos -// |frame_sz| returns the size of the ADTS frame (if found). +// |audio_header| is updated with the new audio frame info if a syncword is +// found. // Return whether a syncword was found. static bool LookForSyncWord(const uint8_t* raw_es, int raw_es_size, int pos, int* new_pos, - int* frame_sz) { + AudioHeader* audio_header) { DCHECK_GE(pos, 0); DCHECK_LE(pos, raw_es_size); - int max_offset = raw_es_size - kAdtsHeaderMinSize; + const int max_offset = + raw_es_size - static_cast(audio_header->GetMinFrameSize()); if (pos >= max_offset) { // Do not change the position if: // - max_offset < 0: not enough bytes to get a full header @@ -58,28 +55,21 @@ static bool LookForSyncWord(const uint8_t* raw_es, for (int offset = pos; offset < max_offset; offset++) { const uint8_t* cur_buf = &raw_es[offset]; - if (!isAdtsSyncWord(cur_buf)) - // The first 12 bits must be 1. - // The layer field (2 bits) must be set to 0. + if (!audio_header->IsSyncWord(cur_buf)) continue; - int frame_size = static_cast( - mp2t::AdtsHeader::GetAdtsFrameSize(cur_buf, kAdtsHeaderMinSize)); - if (frame_size < kAdtsHeaderMinSize) { - // Too short to be an ADTS frame. + if (!audio_header->Parse(cur_buf, raw_es_size - offset)) continue; - } - // Check whether there is another frame - // |size| apart from the current one. - int remaining_size = raw_es_size - offset; - if (remaining_size >= frame_size + 2 && - !isAdtsSyncWord(&cur_buf[frame_size])) { + // Check whether there is another frame |size| apart from the current one. + const size_t remaining_size = static_cast(raw_es_size - offset); + const int kSyncWordSize = 2; + if (remaining_size >= audio_header->GetFrameSize() + kSyncWordSize && + !audio_header->IsSyncWord(&cur_buf[audio_header->GetFrameSize()])) { continue; } *new_pos = offset; - *frame_sz = frame_size; return true; } @@ -87,17 +77,15 @@ static bool LookForSyncWord(const uint8_t* raw_es, return false; } -namespace mp2t { - EsParserAdts::EsParserAdts(uint32_t pid, const NewStreamInfoCB& new_stream_info_cb, const EmitSampleCB& emit_sample_cb, bool sbr_in_mimetype) : EsParser(pid), + audio_header_(new AdtsHeader), new_stream_info_cb_(new_stream_info_cb), emit_sample_cb_(emit_sample_cb), - sbr_in_mimetype_(sbr_in_mimetype) { -} + sbr_in_mimetype_(sbr_in_mimetype) {} EsParserAdts::~EsParserAdts() { } @@ -120,29 +108,24 @@ bool EsParserAdts::Parse(const uint8_t* buf, es_byte_queue_.Push(buf, static_cast(size)); es_byte_queue_.Peek(&raw_es, &raw_es_size); - // Look for every ADTS frame in the ES buffer starting at offset = 0 + // Look for every frame in the ES buffer starting at offset = 0 int es_position = 0; - int frame_size; - while (LookForSyncWord(raw_es, raw_es_size, es_position, - &es_position, &frame_size)) { + while (LookForSyncWord(raw_es, raw_es_size, es_position, &es_position, + audio_header_.get())) { const uint8_t* 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(frame_ptr, kAdtsHeaderMinSize); + DVLOG(LOG_LEVEL_ES) << "syncword @ pos=" << es_position + << " frame_size=" << audio_header_->GetFrameSize(); + DVLOG(LOG_LEVEL_ES) << "header: " + << base::HexEncode(frame_ptr, + audio_header_->GetHeaderSize()); // 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) + if (static_cast(audio_header_->GetFrameSize()) > 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(frame_ptr, frame_size)) + if (!UpdateAudioConfiguration(*audio_header_)) return false; // Get the PTS & the duration of this access unit. @@ -160,7 +143,9 @@ bool EsParserAdts::Parse(const uint8_t* buf, bool is_key_frame = true; std::shared_ptr sample = MediaSample::CopyFrom( - frame_ptr + header_size, frame_size - header_size, is_key_frame); + frame_ptr + audio_header_->GetHeaderSize(), + audio_header_->GetFrameSize() - audio_header_->GetHeaderSize(), + is_key_frame); sample->set_pts(current_pts); sample->set_dts(current_pts); sample->set_duration(frame_duration); @@ -170,7 +155,7 @@ bool EsParserAdts::Parse(const uint8_t* buf, audio_timestamp_helper_->AddFrames(kSamplesPerAACFrame); // Skip the current frame. - es_position += frame_size; + es_position += static_cast(audio_header_->GetFrameSize()); } // Discard all the bytes that have been processed. @@ -188,18 +173,11 @@ void EsParserAdts::Reset() { last_audio_decoder_config_ = std::shared_ptr(); } -bool EsParserAdts::UpdateAudioConfiguration(const uint8_t* adts_frame, - size_t adts_frame_size) { +bool EsParserAdts::UpdateAudioConfiguration(const AudioHeader& audio_header) { const uint8_t 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 audio_specific_config; - if (!adts_header.GetAudioSpecificConfig(&audio_specific_config)) - return false; + audio_header.GetAudioSpecificConfig(&audio_specific_config); if (last_audio_decoder_config_) { // Verify that the audio decoder config has not changed. @@ -214,23 +192,27 @@ bool EsParserAdts::UpdateAudioConfiguration(const uint8_t* adts_frame, // 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.) - int samples_per_second = adts_header.GetSamplingFrequency(); + int samples_per_second = audio_header.GetSamplingFrequency(); + // TODO(kqyang): Review if it makes sense to have |sbr_in_mimetype_| in + // es_parser. int extended_samples_per_second = sbr_in_mimetype_ ? std::min(2 * samples_per_second, 48000) : samples_per_second; + const Codec codec = kCodecAAC; last_audio_decoder_config_ = std::make_shared( - pid(), kMpeg2Timescale, kInfiniteDuration, kCodecAAC, - AudioStreamInfo::GetCodecString(kCodecAAC, adts_header.GetObjectType()), + pid(), kMpeg2Timescale, kInfiniteDuration, codec, + AudioStreamInfo::GetCodecString(codec, audio_header.GetObjectType()), audio_specific_config.data(), audio_specific_config.size(), - kAacSampleSizeBits, adts_header.GetNumChannels(), + kAacSampleSizeBits, audio_header.GetNumChannels(), extended_samples_per_second, 0 /* seek preroll */, 0 /* codec delay */, 0 /* max bitrate */, 0 /* avg bitrate */, std::string(), false); DVLOG(1) << "Sampling frequency: " << samples_per_second; DVLOG(1) << "Extended sampling frequency: " << extended_samples_per_second; - DVLOG(1) << "Channel config: " << adts_header.GetNumChannels(); - DVLOG(1) << "Object type: " << adts_header.GetObjectType(); + DVLOG(1) << "Channel config: " + << static_cast(audio_header.GetNumChannels()); + DVLOG(1) << "Object type: " << static_cast(audio_header.GetObjectType()); // Reset the timestamp helper to use a new sampling frequency. if (audio_timestamp_helper_) { int64_t base_timestamp = audio_timestamp_helper_->GetTimestamp(); diff --git a/packager/media/formats/mp2t/es_parser_adts.h b/packager/media/formats/mp2t/es_parser_adts.h index e0e6b0b109..4428a543d8 100644 --- a/packager/media/formats/mp2t/es_parser_adts.h +++ b/packager/media/formats/mp2t/es_parser_adts.h @@ -22,6 +22,8 @@ class BitReader; namespace mp2t { +class AudioHeader; + class EsParserAdts : public EsParser { public: EsParserAdts(uint32_t pid, @@ -41,13 +43,14 @@ class EsParserAdts : public EsParser { typedef std::list EsPtsList; // 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_t* adts_frame, size_t frame_size); + // Return false if the current audio config is not a supported audio config. + bool UpdateAudioConfiguration(const AudioHeader& audio_header); // Discard some bytes from the ES stream. void DiscardEs(int nbytes); + std::unique_ptr audio_header_; + // Callbacks: // - to signal a new audio configuration, // - to send ES buffers. diff --git a/packager/media/formats/mp2t/mp2t.gyp b/packager/media/formats/mp2t/mp2t.gyp index 71bca4d8e2..43e0c37798 100644 --- a/packager/media/formats/mp2t/mp2t.gyp +++ b/packager/media/formats/mp2t/mp2t.gyp @@ -15,6 +15,7 @@ 'sources': [ 'adts_header.cc', 'adts_header.h', + 'audio_header.h', 'continuity_counter.cc', 'continuity_counter.h', 'es_parser_adts.cc', diff --git a/packager/media/formats/wvm/wvm_media_parser.cc b/packager/media/formats/wvm/wvm_media_parser.cc index 089d7dd515..ac5b382b20 100644 --- a/packager/media/formats/wvm/wvm_media_parser.cc +++ b/packager/media/formats/wvm/wvm_media_parser.cc @@ -48,7 +48,6 @@ const uint32_t kPesStreamIdVideo = 0xE0; const uint32_t kPesStreamIdAudioMask = 0xE0; const uint32_t kPesStreamIdAudio = 0xC0; const uint32_t kVersion4 = 4; -const size_t kAdtsHeaderMinSize = 7; const uint8_t kAacSampleSizeBits = 16; // Applies to all video streams. const uint8_t kNaluLengthSize = 4; // unit is bytes. @@ -904,17 +903,15 @@ bool WvmMediaParser::Output(bool output_encrypted_sample) { } else if ((prev_pes_stream_id_ & kPesStreamIdAudioMask) == kPesStreamIdAudio) { // Set data on the audio stream. - int frame_size = static_cast(mp2t::AdtsHeader::GetAdtsFrameSize( - sample_data_.data(), kAdtsHeaderMinSize)); mp2t::AdtsHeader adts_header; const uint8_t* frame_ptr = sample_data_.data(); - if (!adts_header.Parse(frame_ptr, frame_size)) { + if (!adts_header.Parse(frame_ptr, sample_data_.size())) { LOG(ERROR) << "Could not parse ADTS header"; return false; } - size_t header_size = adts_header.GetAdtsHeaderSize(frame_ptr, - frame_size); - media_sample_->SetData(frame_ptr + header_size, frame_size - header_size); + media_sample_->SetData( + frame_ptr + adts_header.GetHeaderSize(), + adts_header.GetFrameSize() - adts_header.GetHeaderSize()); if (!is_initialized_) { for (uint32_t i = 0; i < stream_infos_.size(); i++) { if (stream_infos_[i]->stream_type() == kStreamAudio && @@ -927,10 +924,7 @@ bool WvmMediaParser::Output(bool output_encrypted_sample) { audio_stream_info->set_sampling_frequency( adts_header.GetSamplingFrequency()); std::vector audio_specific_config; - if (!adts_header.GetAudioSpecificConfig(&audio_specific_config)) { - LOG(ERROR) << "Could not compute AACAudiospecificconfig"; - return false; - } + adts_header.GetAudioSpecificConfig(&audio_specific_config); audio_stream_info->set_codec_config(audio_specific_config); audio_stream_info->set_codec_string( AudioStreamInfo::GetCodecString(