h264_bitstream_buffer.cc 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. // Copyright 2014 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "media/filters/h264_bitstream_buffer.h"
  5. #include "base/bits.h"
  6. #include "base/sys_byteorder.h"
  7. namespace media {
  8. H264BitstreamBuffer::H264BitstreamBuffer() : data_(nullptr) {
  9. Reset();
  10. }
  11. H264BitstreamBuffer::~H264BitstreamBuffer() {
  12. free(data_);
  13. data_ = nullptr;
  14. }
  15. void H264BitstreamBuffer::Reset() {
  16. free(data_);
  17. data_ = nullptr;
  18. capacity_ = 0;
  19. pos_ = 0;
  20. bits_in_buffer_ = 0;
  21. reg_ = 0;
  22. Grow();
  23. bits_left_in_reg_ = kRegBitSize;
  24. }
  25. void H264BitstreamBuffer::Grow() {
  26. data_ = static_cast<uint8_t*>(realloc(data_, capacity_ + kGrowBytes));
  27. CHECK(data_) << "Failed growing the buffer";
  28. capacity_ += kGrowBytes;
  29. }
  30. void H264BitstreamBuffer::FlushReg() {
  31. // Flush all bytes that have at least one bit cached, but not more
  32. // (on Flush(), reg_ may not be full).
  33. size_t bits_in_reg = kRegBitSize - bits_left_in_reg_;
  34. if (bits_in_reg == 0)
  35. return;
  36. size_t bytes_in_reg = base::bits::AlignUp(bits_in_reg, size_t{8}) / 8;
  37. reg_ <<= (kRegBitSize - bits_in_reg);
  38. // Convert to MSB and append as such to the stream.
  39. reg_ = base::HostToNet64(reg_);
  40. // Make sure we have enough space. Grow() will CHECK() on allocation failure.
  41. if (pos_ + bytes_in_reg > capacity_)
  42. Grow();
  43. memcpy(data_ + pos_, &reg_, bytes_in_reg);
  44. bits_in_buffer_ = pos_ * 8 + bits_in_reg;
  45. pos_ += bytes_in_reg;
  46. reg_ = 0;
  47. bits_left_in_reg_ = kRegBitSize;
  48. }
  49. void H264BitstreamBuffer::AppendU64(size_t num_bits, uint64_t val) {
  50. CHECK_LE(num_bits, kRegBitSize);
  51. while (num_bits > 0) {
  52. if (bits_left_in_reg_ == 0)
  53. FlushReg();
  54. uint64_t bits_to_write =
  55. num_bits > bits_left_in_reg_ ? bits_left_in_reg_ : num_bits;
  56. uint64_t val_to_write = (val >> (num_bits - bits_to_write));
  57. if (bits_to_write < 64)
  58. val_to_write &= ((1ull << bits_to_write) - 1);
  59. reg_ <<= bits_to_write;
  60. reg_ |= val_to_write;
  61. num_bits -= bits_to_write;
  62. bits_left_in_reg_ -= bits_to_write;
  63. }
  64. }
  65. void H264BitstreamBuffer::AppendBool(bool val) {
  66. if (bits_left_in_reg_ == 0)
  67. FlushReg();
  68. reg_ <<= 1;
  69. reg_ |= (static_cast<uint64_t>(val) & 1);
  70. --bits_left_in_reg_;
  71. }
  72. void H264BitstreamBuffer::AppendSE(int val) {
  73. if (val > 0)
  74. AppendUE(val * 2 - 1);
  75. else
  76. AppendUE(-val * 2);
  77. }
  78. void H264BitstreamBuffer::AppendUE(unsigned int val) {
  79. size_t num_zeros = 0;
  80. unsigned int v = val + 1;
  81. while (v > 1) {
  82. v >>= 1;
  83. ++num_zeros;
  84. }
  85. AppendBits(num_zeros, 0);
  86. AppendBits(num_zeros + 1, val + 1);
  87. }
  88. #define DCHECK_FINISHED() \
  89. DCHECK_EQ(bits_left_in_reg_, kRegBitSize) << "Pending bits not yet written " \
  90. "to the buffer, call " \
  91. "FinishNALU() first."
  92. void H264BitstreamBuffer::BeginNALU(H264NALU::Type nalu_type, int nal_ref_idc) {
  93. DCHECK_FINISHED();
  94. DCHECK_LE(nalu_type, H264NALU::kEOStream);
  95. DCHECK_GE(nal_ref_idc, 0);
  96. DCHECK_LE(nal_ref_idc, 3);
  97. AppendBits(32, 0x00000001);
  98. AppendBits(1, 0); // forbidden_zero_bit
  99. AppendBits(2, nal_ref_idc);
  100. AppendBits(5, nalu_type);
  101. }
  102. void H264BitstreamBuffer::FinishNALU() {
  103. // RBSP stop one bit.
  104. AppendBits(1, 1);
  105. // Byte-alignment zero bits.
  106. AppendBits(bits_left_in_reg_ % 8, 0);
  107. Flush();
  108. }
  109. void H264BitstreamBuffer::Flush() {
  110. if (bits_left_in_reg_ != kRegBitSize)
  111. FlushReg();
  112. }
  113. size_t H264BitstreamBuffer::BitsInBuffer() const {
  114. return bits_in_buffer_;
  115. }
  116. size_t H264BitstreamBuffer::BytesInBuffer() const {
  117. DCHECK_FINISHED();
  118. return pos_;
  119. }
  120. const uint8_t* H264BitstreamBuffer::data() const {
  121. DCHECK(data_);
  122. DCHECK_FINISHED();
  123. return data_;
  124. }
  125. } // namespace media