diff options
author | xiaomings@google.com <xiaomings@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-07-19 19:43:45 +0000 |
---|---|---|
committer | xiaomings@google.com <xiaomings@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-07-19 19:43:45 +0000 |
commit | 279a07fae05681f3d40f1466e3c4aa8e3e67028b (patch) | |
tree | 1081535465632787800ab0fd933e69dd88f2c051 /media/base | |
parent | 968ff687d1cd2608cfbe8af26b8f352587074f40 (diff) | |
download | chromium_src-279a07fae05681f3d40f1466e3c4aa8e3e67028b.zip chromium_src-279a07fae05681f3d40f1466e3c4aa8e3e67028b.tar.gz chromium_src-279a07fae05681f3d40f1466e3c4aa8e3e67028b.tar.bz2 |
Add HE AAC support to ISO BMFF.
Was https://chromiumcodereview.appspot.com/10753005/.
The original cl also includes abstraction of BitReader class used by H264Parser. It includes bugs that break the H264Parser.
In this cl I removed the abstraction and make the BitReader used by H264Parser independent to the one used by esds parser because of:
1. The original cl introduce bugs.
2. Even if we fix the bugs, we may not be able to make the generalized class as fast as the old one while keeping the abstraction.
3. The H264 bit stream use very special syntax on escaping and trailing zero bits, which might not be a good candidate for abstraction.
BUG=134445
TEST=BitReaderTest, AACTest
Review URL: https://chromiumcodereview.appspot.com/10780026
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@147511 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'media/base')
-rw-r--r-- | media/base/bit_reader.cc | 52 | ||||
-rw-r--r-- | media/base/bit_reader.h | 68 | ||||
-rw-r--r-- | media/base/bit_reader_unittest.cc | 48 |
3 files changed, 168 insertions, 0 deletions
diff --git a/media/base/bit_reader.cc b/media/base/bit_reader.cc new file mode 100644 index 0000000..2ddb8d4 --- /dev/null +++ b/media/base/bit_reader.cc @@ -0,0 +1,52 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "media/base/bit_reader.h" + +namespace media { + +BitReader::BitReader(const uint8* data, off_t size) + : data_(data), bytes_left_(size), num_remaining_bits_in_curr_byte_(0) { + DCHECK(data_ != NULL && bytes_left_ > 0); + + UpdateCurrByte(); +} + +BitReader::~BitReader() {} + +bool BitReader::ReadBitsInternal(int num_bits, uint64* out) { + DCHECK_LE(num_bits, 64); + + *out = 0; + + while (num_remaining_bits_in_curr_byte_ != 0 && num_bits != 0) { + int bits_to_take = std::min(num_remaining_bits_in_curr_byte_, num_bits); + + *out <<= bits_to_take; + *out += curr_byte_ >> (num_remaining_bits_in_curr_byte_ - bits_to_take); + num_bits -= bits_to_take; + num_remaining_bits_in_curr_byte_ -= bits_to_take; + curr_byte_ &= (1 << num_remaining_bits_in_curr_byte_) - 1; + + if (num_remaining_bits_in_curr_byte_ == 0) + UpdateCurrByte(); + } + + return num_bits == 0; +} + +void BitReader::UpdateCurrByte() { + DCHECK_EQ(num_remaining_bits_in_curr_byte_, 0); + + if (bytes_left_ == 0) + return; + + // Load a new byte and advance pointers. + curr_byte_ = *data_; + ++data_; + --bytes_left_; + num_remaining_bits_in_curr_byte_ = 8; +} + +} // namespace media diff --git a/media/base/bit_reader.h b/media/base/bit_reader.h new file mode 100644 index 0000000..1becf91 --- /dev/null +++ b/media/base/bit_reader.h @@ -0,0 +1,68 @@ +// Copyright (c) 2012 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. + +#ifndef MEDIA_BASE_BIT_READER_H_ +#define MEDIA_BASE_BIT_READER_H_ + +#include <sys/types.h> + +#include "base/basictypes.h" +#include "base/logging.h" +#include "media/base/media_export.h" + +namespace media { + +// A class to read bit streams. +class MEDIA_EXPORT BitReader { + public: + // Initialize the reader to start reading at |data|, |size| being size + // of |data| in bytes. + BitReader(const uint8* data, off_t size); + ~BitReader(); + + // Read |num_bits| next bits from stream and return in |*out|, first bit + // from the stream starting at |num_bits| position in |*out|. + // |num_bits| cannot be larger than the bits the type can hold. + // Return false if the given number of bits cannot be read (not enough + // bits in the stream), true otherwise. When return false, the stream will + // enter a state where further ReadBits/SkipBits operations will always + // return false unless |num_bits| is 0. The type |T| has to be a primitive + // integer type. + template<typename T> bool ReadBits(int num_bits, T *out) { + DCHECK_LE(num_bits, static_cast<int>(sizeof(T) * 8)); + uint64 temp; + bool ret = ReadBitsInternal(num_bits, &temp); + *out = static_cast<T>(temp); + return ret; + } + + private: + // Help function used by ReadBits to avoid inlining the bit reading logic. + bool ReadBitsInternal(int num_bits, uint64* out); + + // Advance to the next byte, loading it into curr_byte_. + // If the num_remaining_bits_in_curr_byte_ is 0 after this function returns, + // the stream has reached the end. + void UpdateCurrByte(); + + // Pointer to the next unread (not in curr_byte_) byte in the stream. + const uint8* data_; + + // Bytes left in the stream (without the curr_byte_). + off_t bytes_left_; + + // Contents of the current byte; first unread bit starting at position + // 8 - num_remaining_bits_in_curr_byte_ from MSB. + uint8 curr_byte_; + + // Number of bits remaining in curr_byte_ + int num_remaining_bits_in_curr_byte_; + + private: + DISALLOW_COPY_AND_ASSIGN(BitReader); +}; + +} // namespace media + +#endif // MEDIA_BASE_BIT_READER_H_ diff --git a/media/base/bit_reader_unittest.cc b/media/base/bit_reader_unittest.cc new file mode 100644 index 0000000..48e8c5e --- /dev/null +++ b/media/base/bit_reader_unittest.cc @@ -0,0 +1,48 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "media/base/bit_reader.h" + +#include "testing/gtest/include/gtest/gtest.h" + +namespace media { + +TEST(BitReaderTest, NormalOperationTest) { + uint8 value8; + uint64 value64; + // 0101 0101 1001 1001 repeats 4 times + uint8 buffer[] = {0x55, 0x99, 0x55, 0x99, 0x55, 0x99, 0x55, 0x99}; + BitReader reader1(buffer, 6); // Initialize with 6 bytes only + + EXPECT_TRUE(reader1.ReadBits(1, &value8)); + EXPECT_EQ(value8, 0); + EXPECT_TRUE(reader1.ReadBits(8, &value8)); + EXPECT_EQ(value8, 0xab); // 1010 1011 + EXPECT_TRUE(reader1.ReadBits(7, &value64)); + EXPECT_TRUE(reader1.ReadBits(32, &value64)); + EXPECT_EQ(value64, 0x55995599u); + EXPECT_FALSE(reader1.ReadBits(1, &value8)); + value8 = 0xff; + EXPECT_TRUE(reader1.ReadBits(0, &value8)); + EXPECT_EQ(value8, 0); + + BitReader reader2(buffer, 8); + EXPECT_TRUE(reader2.ReadBits(64, &value64)); + EXPECT_EQ(value64, 0x5599559955995599ull); + EXPECT_FALSE(reader2.ReadBits(1, &value8)); + EXPECT_TRUE(reader2.ReadBits(0, &value8)); +} + +TEST(BitReaderTest, ReadBeyondEndTest) { + uint8 value8; + uint8 buffer[] = {0x12}; + BitReader reader1(buffer, sizeof(buffer)); + + EXPECT_TRUE(reader1.ReadBits(4, &value8)); + EXPECT_FALSE(reader1.ReadBits(5, &value8)); + EXPECT_FALSE(reader1.ReadBits(1, &value8)); + EXPECT_TRUE(reader1.ReadBits(0, &value8)); +} + +} // namespace media |