summaryrefslogtreecommitdiffstats
path: root/media/base
diff options
context:
space:
mode:
authorxiaomings@google.com <xiaomings@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2012-07-06 21:59:25 +0000
committerxiaomings@google.com <xiaomings@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2012-07-06 21:59:25 +0000
commit0b27daac396b790fcc5f7366465e27dd2b9f91f3 (patch)
treeca510596e4c40c316bcb63e9396990eee7d28f12 /media/base
parent2c1e6e5a9eeb002ec26b23e7d9d86ca795f240b1 (diff)
downloadchromium_src-0b27daac396b790fcc5f7366465e27dd2b9f91f3.zip
chromium_src-0b27daac396b790fcc5f7366465e27dd2b9f91f3.tar.gz
chromium_src-0b27daac396b790fcc5f7366465e27dd2b9f91f3.tar.bz2
Add HE AAC support to ISO BMFF.
1. Parse esds box to get HE AAC config. 2. Send audio config from AAC header to decoder instead of the one embedded in SampleDescription. 3. Convert raw audio data into ADTS before sending to decoder. 4. Abstract general bit stream code from H264BitReader into media::BitReader. BUG=134445 TEST=BitReaderTest, AACTest Review URL: https://chromiumcodereview.appspot.com/10710002 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@145617 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'media/base')
-rw-r--r--media/base/bit_reader.cc74
-rw-r--r--media/base/bit_reader.h110
-rw-r--r--media/base/bit_reader_unittest.cc110
3 files changed, 294 insertions, 0 deletions
diff --git a/media/base/bit_reader.cc b/media/base/bit_reader.cc
new file mode 100644
index 0000000..e4106fa
--- /dev/null
+++ b/media/base/bit_reader.cc
@@ -0,0 +1,74 @@
+// 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()
+ : data_(NULL),
+ bytes_left_(0),
+ position_(0),
+ curr_byte_(0),
+ num_remaining_bits_in_curr_byte_(0) {
+}
+
+BitReader::BitReader(const uint8* data, off_t size) {
+ Initialize(data, size);
+}
+
+BitReader::~BitReader() {}
+
+void BitReader::Initialize(const uint8* data, off_t size) {
+ DCHECK(data != NULL || size == 0); // Data cannot be NULL if size is not 0.
+
+ data_ = data;
+ bytes_left_ = size;
+ position_ = 0;
+ num_remaining_bits_in_curr_byte_ = 0;
+
+ UpdateCurrByte();
+}
+
+void BitReader::UpdateCurrByte() {
+ DCHECK_EQ(num_remaining_bits_in_curr_byte_, 0);
+
+ if (bytes_left_ < 1)
+ return;
+
+ // Load a new byte and advance pointers.
+ curr_byte_ = *data_;
+ ++data_;
+ --bytes_left_;
+ num_remaining_bits_in_curr_byte_ = 8;
+}
+
+bool BitReader::SkipBits(int num_bits) {
+ int dummy;
+ const int kDummySize = static_cast<int>(sizeof(dummy)) * 8;
+
+ while (num_bits > kDummySize) {
+ if (ReadBits(kDummySize, &dummy)) {
+ num_bits -= kDummySize;
+ } else {
+ return false;
+ }
+ }
+
+ return ReadBits(num_bits, &dummy);
+}
+
+off_t BitReader::Tell() const {
+ return position_;
+}
+
+off_t BitReader::NumBitsLeft() const {
+ return (num_remaining_bits_in_curr_byte_ + bytes_left_ * 8);
+}
+
+bool BitReader::HasMoreData() const {
+ return num_remaining_bits_in_curr_byte_ != 0;
+}
+
+} // namespace media
diff --git a/media/base/bit_reader.h b/media/base/bit_reader.h
new file mode 100644
index 0000000..35c62a9
--- /dev/null
+++ b/media/base/bit_reader.h
@@ -0,0 +1,110 @@
+// 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 <algorithm>
+#include <climits>
+
+#include "base/basictypes.h"
+#include "base/logging.h"
+#include "media/base/media_export.h"
+
+
+namespace media {
+
+// A class to read bit streams.
+// Classes inherited this class can override its UpdateCurrByte function
+// to support specific escape mechanism, which is widely used by streaming
+// formats like H.264 Annex B.
+class MEDIA_EXPORT BitReader {
+ public:
+ BitReader();
+ BitReader(const uint8* data, off_t size);
+ virtual ~BitReader();
+
+ // Initialize the reader to start reading at |data|, |size| being size
+ // of |data| in bytes.
+ void Initialize(const uint8* data, off_t size);
+
+ // 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 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(num_bits <= static_cast<int>(sizeof(T) * CHAR_BIT));
+
+ *out = 0;
+ position_ += num_bits;
+
+ 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 = (*out << bits_to_take) +
+ (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();
+ }
+
+ if (num_bits == 0)
+ return true;
+
+ *out = 0;
+ num_remaining_bits_in_curr_byte_ = 0;
+ bytes_left_ = 0;
+
+ return false;
+ }
+
+ bool SkipBits(int num_bits);
+
+ // Return the current position in the stream in unit of bit.
+ // This includes the skipped escape bytes if there are any.
+ off_t Tell() const;
+
+ // Return the number of bits left in the stream.
+ // This doesn't take any escape sequence into account.
+ off_t NumBitsLeft() const;
+
+ bool HasMoreData() const;
+
+ protected:
+ // Advance to the next byte, loading it into curr_byte_.
+ // This function can be overridden to support specific escape mechanism.
+ // If the num_remaining_bits_in_curr_byte_ is 0 after this function returns,
+ // the stream has reached the end.
+ virtual 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_;
+
+ // Current position in bits.
+ off_t position_;
+
+ // 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..00d425f
--- /dev/null
+++ b/media/base/bit_reader_unittest.cc
@@ -0,0 +1,110 @@
+// 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, EmptyStreamTest) {
+ BitReader reader(NULL, 0);
+ uint8 value8 = 0xff;
+
+ ASSERT_FALSE(reader.HasMoreData());
+ ASSERT_EQ(reader.Tell(), 0);
+ ASSERT_TRUE(reader.ReadBits(0, &value8));
+ ASSERT_TRUE(reader.SkipBits(0));
+ ASSERT_EQ(reader.Tell(), 0);
+ ASSERT_FALSE(reader.HasMoreData());
+ ASSERT_FALSE(reader.ReadBits(1, &value8));
+ ASSERT_FALSE(reader.SkipBits(1));
+ ASSERT_EQ(value8, 0);
+}
+
+TEST(BitReaderTest, NormalOperationTest) {
+ // 0101 0101 1001 1001 repeats 4 times
+ uint8 buffer[] = {0x55, 0x99, 0x55, 0x99, 0x55, 0x99, 0x55, 0x99};
+ BitReader reader(buffer, 6); // Initialize with 6 bytes only
+ uint8 value8;
+ uint64 value64;
+
+ ASSERT_TRUE(reader.HasMoreData());
+ ASSERT_EQ(reader.Tell(), 0);
+ ASSERT_TRUE(reader.ReadBits(1, &value8));
+ ASSERT_EQ(value8, 0);
+ ASSERT_TRUE(reader.ReadBits(8, &value8));
+ ASSERT_EQ(value8, 0xab); // 1010 1011
+ ASSERT_EQ(reader.Tell(), 9);
+ ASSERT_TRUE(reader.HasMoreData());
+ ASSERT_TRUE(reader.SkipBits(7));
+ ASSERT_EQ(reader.Tell(), 16);
+ ASSERT_TRUE(reader.ReadBits(32, &value64));
+ ASSERT_EQ(value64, 0x55995599u);
+ ASSERT_EQ(reader.Tell(), 48);
+ ASSERT_FALSE(reader.HasMoreData());
+ ASSERT_FALSE(reader.SkipBits(1));
+ ASSERT_FALSE(reader.ReadBits(1, &value8));
+ ASSERT_TRUE(reader.SkipBits(0));
+ value8 = 0xff;
+ ASSERT_TRUE(reader.ReadBits(0, &value8));
+ ASSERT_EQ(value8, 0);
+
+ reader.Initialize(buffer, 8);
+ ASSERT_TRUE(reader.ReadBits(64, &value64));
+ EXPECT_EQ(value64, 0x5599559955995599ull);
+ EXPECT_FALSE(reader.HasMoreData());
+ EXPECT_EQ(reader.Tell(), 64);
+ EXPECT_FALSE(reader.ReadBits(1, &value8));
+ EXPECT_FALSE(reader.SkipBits(1));
+ EXPECT_TRUE(reader.ReadBits(0, &value8));
+ EXPECT_TRUE(reader.SkipBits(0));
+}
+
+TEST(BitReaderTest, LongSkipTest) {
+ uint8 buffer[] = {
+ 0x12, 0x34, 0x56, 0x78, 0x12, 0x34, 0x56, 0x78, // 64 * 1
+ 0x12, 0x34, 0x56, 0x78, 0x12, 0x34, 0x56, 0x78, // 64 * 2
+ 0x12, 0x34, 0x56, 0x78, 0x12, 0x34, 0x56, 0x78, // 64 * 3
+ 0x12, 0x34, 0x56, 0x78, 0x12, 0x34, 0x56, 0x78, // 64 * 4
+ 0x12, 0x34, 0x56, 0x78, 0x12, 0x34, 0x56, 0x78, // 64 * 5
+ 0x12, 0x34, 0x56, 0x78, 0x12, 0x34, 0x56, 0x78, // 64 * 6
+ 0x12, 0x34, 0x56, 0x78, 0x12, 0x34, 0x56, 0x78, // 64 * 7
+ 0x12, 0x34, 0x56, 0x78, 0x12, 0x34, 0x56, 0x78, // 64 * 8
+ 0x87, 0x65
+ };
+ BitReader reader(buffer, sizeof(buffer));
+ uint8 value8;
+
+ EXPECT_TRUE(reader.SkipBits(64 * 8 + 8));
+ EXPECT_EQ(reader.Tell(), 64 * 8 + 8);
+ EXPECT_TRUE(reader.ReadBits(8, &value8));
+ EXPECT_EQ(value8, 0x65);
+ EXPECT_EQ(reader.Tell(), 64 * 8 + 16);
+ EXPECT_FALSE(reader.HasMoreData());
+ EXPECT_EQ(reader.NumBitsLeft(), 0);
+}
+
+TEST(BitReaderTest, ReadBeyondEndTest) {
+ uint8 buffer[] = {0x12};
+ BitReader reader(buffer, sizeof(buffer));
+ uint8 value8;
+
+ EXPECT_TRUE(reader.SkipBits(4));
+ EXPECT_FALSE(reader.ReadBits(5, &value8));
+ EXPECT_FALSE(reader.ReadBits(1, &value8));
+ EXPECT_FALSE(reader.SkipBits(1));
+ EXPECT_TRUE(reader.ReadBits(0, &value8));
+ EXPECT_TRUE(reader.SkipBits(0));
+
+ reader.Initialize(buffer, sizeof(buffer));
+ EXPECT_TRUE(reader.SkipBits(4));
+ EXPECT_FALSE(reader.SkipBits(5));
+ EXPECT_FALSE(reader.ReadBits(1, &value8));
+ EXPECT_FALSE(reader.SkipBits(1));
+ EXPECT_TRUE(reader.ReadBits(0, &value8));
+ EXPECT_TRUE(reader.SkipBits(0));
+}
+
+} // namespace media