diff --git a/packager/media/formats/mp2t/ac3_header.cc b/packager/media/formats/mp2t/ac3_header.cc index b12de43aba..495baa9d6a 100644 --- a/packager/media/formats/mp2t/ac3_header.cc +++ b/packager/media/formats/mp2t/ac3_header.cc @@ -40,6 +40,19 @@ const size_t kFrameSizeCodeTable[][3] = { {1920, 1393, 1280}, {1920, 1394, 1280}, }; +// Calculate the size of the frame from the sample rate code and the +// frame size code. +// @return the size of the frame (header + payload). +size_t CalcFrameSize(uint8_t fscod, uint8_t frmsizecod) { + const size_t kNumFscode = arraysize(kAc3SampleRateTable); + DCHECK_LT(fscod, kNumFscode); + DCHECK_LT(frmsizecod, arraysize(kFrameSizeCodeTable)); + // The order of frequencies are reversed in |kFrameSizeCodeTable| compared to + // |kAc3SampleRateTable|. + const int index = kNumFscode - 1 - fscod; + return kFrameSizeCodeTable[frmsizecod][index] * 2; +} + } // namespace bool Ac3Header::IsSyncWord(const uint8_t* buf) const { @@ -104,13 +117,15 @@ size_t Ac3Header::GetHeaderSize() const { } size_t Ac3Header::GetFrameSize() const { - const size_t kNumFscode = arraysize(kAc3SampleRateTable); - DCHECK_LT(fscod_, kNumFscode); - DCHECK_LT(frmsizecod_, arraysize(kFrameSizeCodeTable)); - // The order of frequencies are reversed in |kFrameSizeCodeTable| compared to - // |kAc3SampleRateTable|. - const int index = kNumFscode - 1 - fscod_; - return kFrameSizeCodeTable[frmsizecod_][index] * 2; + return CalcFrameSize(fscod_, frmsizecod_); +} + +size_t Ac3Header::GetFrameSizeWithoutParsing(const uint8_t* data, + size_t num_bytes) const { + DCHECK_GT(num_bytes, static_cast(4)); + uint8_t fscod = data[4] >> 6; + uint8_t frmsizecod = data[4] & 0x3f; + return CalcFrameSize(fscod, frmsizecod); } void Ac3Header::GetAudioSpecificConfig(std::vector* buffer) const { diff --git a/packager/media/formats/mp2t/ac3_header.h b/packager/media/formats/mp2t/ac3_header.h index 773994cb5a..81db8b04c7 100644 --- a/packager/media/formats/mp2t/ac3_header.h +++ b/packager/media/formats/mp2t/ac3_header.h @@ -32,6 +32,8 @@ class Ac3Header : public AudioHeader { bool Parse(const uint8_t* adts_frame, size_t adts_frame_size) override; size_t GetHeaderSize() const override; size_t GetFrameSize() const override; + size_t GetFrameSizeWithoutParsing(const uint8_t* data, + size_t num_bytes) const override; void GetAudioSpecificConfig(std::vector* buffer) const override; uint8_t GetObjectType() const override; uint32_t GetSamplingFrequency() const override; diff --git a/packager/media/formats/mp2t/ac3_header_unittest.cc b/packager/media/formats/mp2t/ac3_header_unittest.cc index 753b8c76df..f08a4729ff 100644 --- a/packager/media/formats/mp2t/ac3_header_unittest.cc +++ b/packager/media/formats/mp2t/ac3_header_unittest.cc @@ -74,6 +74,9 @@ TEST_F(Ac3HeaderTest, Parse44100HzSuccess) { const uint8_t kExpectedAudioSpecificConfig[] = {0x50, 0x11, 0x40}; Ac3Header ac3_header; + EXPECT_EQ(kExpectedFrameSize, + ac3_header.GetFrameSizeWithoutParsing(ac3_frame_44100_hz_.data(), + ac3_frame_44100_hz_.size())); ASSERT_TRUE( ac3_header.Parse(ac3_frame_44100_hz_.data(), ac3_frame_44100_hz_.size())); EXPECT_EQ(kExpectedFrameSize, ac3_header.GetFrameSize()); @@ -96,6 +99,9 @@ TEST_F(Ac3HeaderTest, Parse48kHzSuccess) { const uint8_t kExpectedAudioSpecificConfig[] = {0x10, 0x11, 0x40}; Ac3Header ac3_header; + EXPECT_EQ(kExpectedFrameSize, + ac3_header.GetFrameSizeWithoutParsing(ac3_frame_48k_hz_.data(), + ac3_frame_48k_hz_.size())); ASSERT_TRUE( ac3_header.Parse(ac3_frame_48k_hz_.data(), ac3_frame_48k_hz_.size())); EXPECT_EQ(kExpectedFrameSize, ac3_header.GetFrameSize()); @@ -118,6 +124,10 @@ TEST_F(Ac3HeaderTest, ParseMultiChannelSuccess) { const uint8_t kExpectedAudioSpecificConfig[] = {0x50, 0x3D, 0xE0}; Ac3Header ac3_header; + EXPECT_EQ( + kExpectedFrameSize, + ac3_header.GetFrameSizeWithoutParsing(ac3_frame_six_channels_.data(), + ac3_frame_six_channels_.size())); ASSERT_TRUE(ac3_header.Parse(ac3_frame_six_channels_.data(), ac3_frame_six_channels_.size())); EXPECT_EQ(kExpectedFrameSize, ac3_header.GetFrameSize()); diff --git a/packager/media/formats/mp2t/adts_header.cc b/packager/media/formats/mp2t/adts_header.cc index 07f11cdcc7..dda45f5336 100644 --- a/packager/media/formats/mp2t/adts_header.cc +++ b/packager/media/formats/mp2t/adts_header.cc @@ -63,8 +63,7 @@ bool AdtsHeader::Parse(const uint8_t* adts_frame, size_t adts_frame_size) { // Skip private stream bit. RCHECK(frame.SkipBits(1)); RCHECK(frame.ReadBits(3, &channel_configuration_)); - RCHECK((channel_configuration_ > 0) && - (channel_configuration_ < kAdtsNumChannelsTableSize)); + RCHECK(channel_configuration_ < kAdtsNumChannelsTableSize); // Skip originality, home and copyright info. RCHECK(frame.SkipBits(4)); RCHECK(frame.ReadBits(13, &frame_size_)); @@ -89,6 +88,13 @@ size_t AdtsHeader::GetFrameSize() const { return frame_size_; } +size_t AdtsHeader::GetFrameSizeWithoutParsing(const uint8_t* data, + size_t num_bytes) const { + DCHECK_GT(num_bytes, static_cast(5)); + return ((static_cast(data[5]) >> 5) | (static_cast(data[4]) << 3) | + ((static_cast(data[3]) & 0x3) << 11)); +} + void AdtsHeader::GetAudioSpecificConfig(std::vector* buffer) const { DCHECK(buffer); buffer->clear(); @@ -109,7 +115,6 @@ uint32_t AdtsHeader::GetSamplingFrequency() const { } uint8_t AdtsHeader::GetNumChannels() const { - DCHECK_GT(channel_configuration_, 0); DCHECK_LT(channel_configuration_, kAdtsNumChannelsTableSize); return kAdtsNumChannelsTable[channel_configuration_]; } diff --git a/packager/media/formats/mp2t/adts_header.h b/packager/media/formats/mp2t/adts_header.h index c1b6839c7b..f1c301fbb0 100644 --- a/packager/media/formats/mp2t/adts_header.h +++ b/packager/media/formats/mp2t/adts_header.h @@ -32,6 +32,8 @@ class AdtsHeader : public AudioHeader { bool Parse(const uint8_t* adts_frame, size_t adts_frame_size) override; size_t GetHeaderSize() const override; size_t GetFrameSize() const override; + size_t GetFrameSizeWithoutParsing(const uint8_t* data, + size_t num_bytes) const override; void GetAudioSpecificConfig(std::vector* buffer) const override; uint8_t GetObjectType() const override; uint32_t GetSamplingFrequency() const override; diff --git a/packager/media/formats/mp2t/adts_header_unittest.cc b/packager/media/formats/mp2t/adts_header_unittest.cc index 4a5d3b3c5d..75a6dd4432 100644 --- a/packager/media/formats/mp2t/adts_header_unittest.cc +++ b/packager/media/formats/mp2t/adts_header_unittest.cc @@ -54,6 +54,9 @@ TEST_F(AdtsHeaderTest, ParseSuccess) { const uint32_t kExpectedSamplingFrequency(44100); const uint8_t kExpectedNumChannels(2); AdtsHeader adts_header; + EXPECT_EQ(adts_frame_.size(), + adts_header.GetFrameSizeWithoutParsing(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()); diff --git a/packager/media/formats/mp2t/audio_header.h b/packager/media/formats/mp2t/audio_header.h index 2808e053fa..e018fa4ed4 100644 --- a/packager/media/formats/mp2t/audio_header.h +++ b/packager/media/formats/mp2t/audio_header.h @@ -50,6 +50,12 @@ class AudioHeader { /// @return the size of frame (header + payload). virtual size_t GetFrameSize() const = 0; + /// Obtain the size of the frame from the header data without doing a full + /// Parse. + /// @return the size of the frame (header + payload). + virtual size_t GetFrameSizeWithoutParsing(const uint8_t* data, + size_t num_bytes) const = 0; + /// Synthesize an AudioSpecificConfig record from the fields within the audio /// header. /// Should only be called after a successful Parse. diff --git a/packager/media/formats/mp2t/es_parser_audio.cc b/packager/media/formats/mp2t/es_parser_audio.cc index 9599563d73..2a8d96c3e4 100644 --- a/packager/media/formats/mp2t/es_parser_audio.cc +++ b/packager/media/formats/mp2t/es_parser_audio.cc @@ -59,17 +59,25 @@ static bool LookForSyncWord(const uint8_t* raw_es, if (!audio_header->IsSyncWord(cur_buf)) continue; - if (!audio_header->Parse(cur_buf, raw_es_size - offset)) - continue; - - // 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()])) { + const size_t frame_size = + audio_header->GetFrameSizeWithoutParsing(cur_buf, remaining_size); + if (frame_size < audio_header->GetMinFrameSize()) + // Too short to be a valid frame. + continue; + if (remaining_size < frame_size) + // Not a full frame: will resume when we have more data. + return false; + // Check whether there is another frame |size| apart from the current one. + if (remaining_size >= frame_size + kSyncWordSize && + !audio_header->IsSyncWord(&cur_buf[frame_size])) { continue; } + if (!audio_header->Parse(cur_buf, frame_size)) + continue; + *new_pos = offset; return true; }