Bug 1195723: P5. Add BitReader class. r?kamidphish draft
authorJean-Yves Avenard <jyavenard@mozilla.com>
Wed, 17 Aug 2016 15:27:43 +1000
changeset 402015 be1622185a7212cc58070ee462d8e4987b3505ea
parent 402014 f1a415ed104dcd00852553e7c1866fab8d540f07
child 402016 e2d8903e777bd65de48dad53c29b6b5afb93ce0d
push id26609
push userbmo:jyavenard@mozilla.com
push dateThu, 18 Aug 2016 00:05:41 +0000
reviewerskamidphish
bugs1195723
milestone51.0a1
Bug 1195723: P5. Add BitReader class. r?kamidphish Extracted from the H264 codec and using the stagefright one. MozReview-Commit-ID: ENjsDvB9MYp
media/libstagefright/binding/BitReader.cpp
media/libstagefright/binding/H264.cpp
media/libstagefright/binding/include/mp4_demuxer/BitReader.h
media/libstagefright/moz.build
new file mode 100644
--- /dev/null
+++ b/media/libstagefright/binding/BitReader.cpp
@@ -0,0 +1,104 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "mp4_demuxer/BitReader.h"
+#include <media/stagefright/foundation/ABitReader.h>
+
+using namespace mozilla;
+using namespace stagefright;
+
+namespace mp4_demuxer
+{
+
+BitReader::BitReader(const mozilla::MediaByteBuffer* aBuffer)
+  : mBitReader(new ABitReader(aBuffer->Elements(), aBuffer->Length()))
+  , mSize(aBuffer->Length()) {}
+
+BitReader::BitReader(const uint8_t* aBuffer, size_t aLength)
+  : mBitReader(new ABitReader(aBuffer, aLength))
+  , mSize(aLength) {}
+
+BitReader::~BitReader() {}
+
+uint32_t
+BitReader::ReadBits(size_t aNum)
+{
+  MOZ_ASSERT(aNum <= 32);
+  if (mBitReader->numBitsLeft() < aNum) {
+    return 0;
+  }
+  return mBitReader->getBits(aNum);
+}
+
+// Read unsigned integer Exp-Golomb-coded.
+uint32_t
+BitReader::ReadUE()
+{
+  uint32_t i = 0;
+
+  while (ReadBit() == 0 && i < 32) {
+    i++;
+  }
+  if (i == 32) {
+    // This can happen if the data is invalid, or if it's
+    // short, since ReadBit() will return 0 when it runs
+    // off the end of the buffer.
+    NS_WARNING("Invalid H.264 data");
+    return 0;
+  }
+  uint32_t r = ReadBits(i);
+  r += (1 << i) - 1;
+  return r;
+}
+
+// Read signed integer Exp-Golomb-coded.
+int32_t
+BitReader::ReadSE()
+{
+  int32_t r = ReadUE();
+  if (r & 1) {
+    return (r+1) / 2;
+  } else {
+    return -r / 2;
+  }
+}
+
+uint64_t
+BitReader::ReadU64()
+{
+  uint64_t hi = ReadU32();
+  uint32_t lo = ReadU32();
+  return (hi << 32) | lo;
+}
+
+uint64_t
+BitReader::ReadUTF8()
+{
+  int64_t val = ReadBits(8);
+  uint32_t top = (val & 0x80) >> 1;
+
+  if ((val & 0xc0) == 0x80 || val >= 0xFE) {
+    // error.
+    return -1;
+  }
+  while (val & top) {
+    int tmp = ReadBits(8) - 128;
+    if (tmp >> 6) {
+      // error.
+      return -1;
+    }
+    val = (val << 6) + tmp;
+    top <<= 5;
+  }
+  val &= (top << 1) - 1;
+  return val;
+}
+
+size_t
+BitReader::BitCount() const
+{
+  return mSize * 8 - mBitReader->numBitsLeft();
+}
+
+} // namespace mp4_demuxer
--- a/media/libstagefright/binding/H264.cpp
+++ b/media/libstagefright/binding/H264.cpp
@@ -1,83 +1,27 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "mozilla/ArrayUtils.h"
 #include "mozilla/PodOperations.h"
 #include "mp4_demuxer/AnnexB.h"
+#include "mp4_demuxer/BitReader.h"
 #include "mp4_demuxer/ByteReader.h"
 #include "mp4_demuxer/ByteWriter.h"
 #include "mp4_demuxer/H264.h"
 #include <media/stagefright/foundation/ABitReader.h>
 #include <limits>
 
 using namespace mozilla;
 
 namespace mp4_demuxer
 {
 
-class BitReader
-{
-public:
-  explicit BitReader(const mozilla::MediaByteBuffer* aBuffer)
-    : mBitReader(aBuffer->Elements(), aBuffer->Length())
-  {
-  }
-
-  uint32_t ReadBits(size_t aNum)
-  {
-    MOZ_ASSERT(aNum <= 32);
-    if (mBitReader.numBitsLeft() < aNum) {
-      return 0;
-    }
-    return mBitReader.getBits(aNum);
-  }
-
-  uint32_t ReadBit()
-  {
-    return ReadBits(1);
-  }
-
-  // Read unsigned integer Exp-Golomb-coded.
-  uint32_t ReadUE()
-  {
-    uint32_t i = 0;
-
-    while (ReadBit() == 0 && i < 32) {
-      i++;
-    }
-    if (i == 32) {
-      // This can happen if the data is invalid, or if it's
-      // short, since ReadBit() will return 0 when it runs
-      // off the end of the buffer.
-      NS_WARNING("Invalid H.264 data");
-      return 0;
-    }
-    uint32_t r = ReadBits(i);
-    r += (1 << i) - 1;
-    return r;
-  }
-
-  // Read signed integer Exp-Golomb-coded.
-  int32_t ReadSE()
-  {
-    int32_t r = ReadUE();
-    if (r & 1) {
-      return (r+1) / 2;
-    } else {
-      return -r / 2;
-    }
-  }
-
-private:
-  stagefright::ABitReader mBitReader;
-};
-
 SPSData::SPSData()
 {
   PodZero(this);
   // Default values when they aren't defined as per ITU-T H.264 (2014/02).
   chroma_format_idc = 1;
   video_format = 5;
   colour_primaries = 2;
   transfer_characteristics = 2;
new file mode 100644
--- /dev/null
+++ b/media/libstagefright/binding/include/mp4_demuxer/BitReader.h
@@ -0,0 +1,45 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef BIT_READER_H_
+#define BIT_READER_H_
+
+#include "nsAutoPtr.h"
+#include "MediaData.h"
+
+namespace stagefright { class ABitReader; }
+
+namespace mp4_demuxer
+{
+
+class BitReader
+{
+public:
+  explicit BitReader(const mozilla::MediaByteBuffer* aBuffer);
+  BitReader(const uint8_t* aBuffer, size_t aLength);
+  ~BitReader();
+  uint32_t ReadBits(size_t aNum);
+  uint32_t ReadBit() { return ReadBits(1); }
+  uint32_t ReadU32() { return ReadBits(32); }
+  uint64_t ReadU64();
+
+  // Read the UTF-8 sequence and convert it to its 64-bit UCS-4 encoded form.
+  // Return 0xfffffffffffffff if sequence was invalid.
+  uint64_t ReadUTF8();
+  // Read unsigned integer Exp-Golomb-coded.
+  uint32_t ReadUE();
+  // Read signed integer Exp-Golomb-coded.
+  int32_t ReadSE();
+
+  // Return the number of bits parsed so far;
+  size_t BitCount() const;
+
+private:
+  nsAutoPtr<stagefright::ABitReader> mBitReader;
+  const size_t mSize;
+};
+
+} // namespace mp4_demuxer
+
+#endif // BIT_READER_H_
\ No newline at end of file
--- a/media/libstagefright/moz.build
+++ b/media/libstagefright/moz.build
@@ -47,16 +47,17 @@ if CONFIG['OS_TARGET'] != 'Android':
         'system/core/liblog/logprint.c',
     ]
 
 EXPORTS.mp4_demuxer += [
     'binding/include/mp4_demuxer/Adts.h',
     'binding/include/mp4_demuxer/AnnexB.h',
     'binding/include/mp4_demuxer/Atom.h',
     'binding/include/mp4_demuxer/AtomType.h',
+    'binding/include/mp4_demuxer/BitReader.h',
     'binding/include/mp4_demuxer/BufferStream.h',
     'binding/include/mp4_demuxer/ByteReader.h',
     'binding/include/mp4_demuxer/ByteWriter.h',
     'binding/include/mp4_demuxer/DecoderData.h',
     'binding/include/mp4_demuxer/H264.h',
     'binding/include/mp4_demuxer/Index.h',
     'binding/include/mp4_demuxer/Interval.h',
     'binding/include/mp4_demuxer/MoofParser.h',
@@ -82,16 +83,17 @@ SOURCES += [
 if CONFIG['MOZ_RUST']:
     EXPORTS += [
         'binding/include/mp4parse.h',
     ]
 
 UNIFIED_SOURCES += [
     'binding/Adts.cpp',
     'binding/AnnexB.cpp',
+    'binding/BitReader.cpp',
     'binding/Box.cpp',
     'binding/BufferStream.cpp',
     'binding/DecoderData.cpp',
     'binding/H264.cpp',
     'binding/Index.cpp',
     'binding/MoofParser.cpp',
     'binding/MP4Metadata.cpp',
     'binding/ResourceStream.cpp',