Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

198 строки
4.6KB

  1. #ifndef _mpeg4_bits_h_
  2. #define _mpeg4_bits_h_
  3. #include <stdint.h>
  4. #include <stddef.h>
  5. #include <assert.h>
  6. #ifdef __cplusplus
  7. extern "C" {
  8. #endif
  9. struct mpeg4_bits_t
  10. {
  11. uint8_t* data;
  12. size_t size;
  13. size_t bits; // offset bit
  14. int error;
  15. };
  16. #define mpeg4_bits_read_uint8(bits, n) (uint8_t)mpeg4_bits_read_n(bits, n)
  17. #define mpeg4_bits_read_uint16(bits, n) (uint16_t)mpeg4_bits_read_n(bits, n)
  18. #define mpeg4_bits_read_uint32(bits, n) (uint32_t)mpeg4_bits_read_n(bits, n)
  19. #define mpeg4_bits_read_uint64(bits, n) (uint64_t)mpeg4_bits_read_n(bits, n)
  20. #define mpeg4_bits_write_uint8(bits, v, n) mpeg4_bits_write_n(bits, (uint64_t)v, n)
  21. #define mpeg4_bits_write_uint16(bits, v, n) mpeg4_bits_write_n(bits, (uint64_t)v, n)
  22. #define mpeg4_bits_write_uint32(bits, v, n) mpeg4_bits_write_n(bits, (uint64_t)v, n)
  23. #define mpeg4_bits_write_uint64(bits, v, n) mpeg4_bits_write_n(bits, (uint64_t)v, n)
  24. static inline void mpeg4_bits_init(struct mpeg4_bits_t* bits, void* data, size_t size)
  25. {
  26. bits->data = (uint8_t*)data;
  27. bits->size = size;
  28. bits->bits = 0;
  29. bits->error = 0;
  30. }
  31. /// @return 1-error, 0-no error
  32. static inline int mpeg4_bits_error(struct mpeg4_bits_t* bits)
  33. {
  34. //return bits->bits >= bits->size * 8 ? 1 : 0;
  35. return bits->error;
  36. }
  37. static inline void mpeg4_bits_aligment(struct mpeg4_bits_t* bits, int n)
  38. {
  39. bits->bits = (bits->bits + n - 1) / n * n;
  40. }
  41. static inline size_t mpeg4_bits_remain(struct mpeg4_bits_t* bits)
  42. {
  43. return bits->error ? 0 : (bits->size * 8 - bits->bits);
  44. }
  45. static inline void mpeg4_bits_skip(struct mpeg4_bits_t* bits, size_t n)
  46. {
  47. bits->bits += n;
  48. }
  49. /// read 1-bit from bit stream(offset position)
  50. /// @param[in] bits bit stream
  51. /// @return -1-error, 1-value, 0-value
  52. static inline int mpeg4_bits_read(struct mpeg4_bits_t* bits)
  53. {
  54. uint8_t bit;
  55. assert(bits && bits->data && bits->size > 0);
  56. if (bits->bits >= bits->size * 8)
  57. {
  58. bits->error = -1;
  59. return 0; // throw exception
  60. }
  61. bit = bits->data[bits->bits/8] & (0x80U >> (bits->bits%8));
  62. bits->bits += 1; // update offset
  63. return bit ? 1 : 0;
  64. }
  65. /// read n-bit(n <= 64) from bit stream(offset position)
  66. /// @param[in] bits bit stream
  67. /// @return -1-error, other-value
  68. static inline uint64_t mpeg4_bits_read_n(struct mpeg4_bits_t* bits, int n)
  69. {
  70. int m;
  71. size_t i;
  72. uint64_t v;
  73. assert(n > 0 && n <= 64);
  74. assert(bits && bits->data && bits->size > 0);
  75. if (bits->bits + n > bits->size * 8 || n > 64 || n < 0)
  76. {
  77. bits->error = -1;
  78. return 0; // throw exception
  79. }
  80. m = n;
  81. v = bits->data[bits->bits / 8] & (0xFFU >> (bits->bits%8)); // remain valid value
  82. if (n <= 8 - (int)(bits->bits % 8))
  83. {
  84. v = v >> (8 - (bits->bits % 8) - n); // shift right value
  85. bits->bits += n;
  86. return v;
  87. }
  88. n -= 8 - (int)(bits->bits % 8);
  89. for (i = 1; n >= 8; i++)
  90. {
  91. assert(bits->bits / 8 + i < bits->size);
  92. v <<= 8;
  93. v += bits->data[bits->bits / 8 + i];
  94. n -= 8;
  95. }
  96. if (n > 0)
  97. {
  98. v <<= n;
  99. v += bits->data[bits->bits / 8 + i] >> (8 - n);
  100. }
  101. bits->bits += m;
  102. return v;
  103. }
  104. // http://aomedia.org/av1/specification/conventions/#descriptors
  105. static inline uint64_t mpeg4_bits_read_uvlc(struct mpeg4_bits_t* bits)
  106. {
  107. uint64_t value;
  108. int leadingZeros;
  109. for (leadingZeros = 0; !mpeg4_bits_read(bits); ++leadingZeros)
  110. {
  111. }
  112. if (leadingZeros >= 32)
  113. return (1ULL << 32) - 1;
  114. value = mpeg4_bits_read_n(bits, leadingZeros);
  115. return (1ULL << leadingZeros) - 1 + value;
  116. }
  117. static inline uint64_t mpeg4_bits_read_latm(struct mpeg4_bits_t* bits)
  118. {
  119. int len;
  120. len = (int)mpeg4_bits_read_n(bits, 2);
  121. return mpeg4_bits_read_n(bits, (len + 1) * 8);
  122. }
  123. /// write 1-bit
  124. /// @param[in] v write 0 if v value 0, other, write 1
  125. static inline int mpeg4_bits_write(struct mpeg4_bits_t* bits, int v)
  126. {
  127. assert(bits && bits->data && bits->size > 0);
  128. if (bits->bits >= bits->size * 8)
  129. {
  130. bits->error = -1;
  131. return -1; // throw exception
  132. }
  133. if(v)
  134. bits->data[bits->bits / 8] |= (0x80U >> (bits->bits % 8));
  135. bits->bits += 1; // update offset
  136. return 0;
  137. }
  138. static inline int mpeg4_bits_write_n(struct mpeg4_bits_t* bits, uint64_t v, int n)
  139. {
  140. int m;
  141. size_t i;
  142. assert(n > 0 && n <= 64);
  143. assert(bits && bits->data && bits->size > 0);
  144. if (bits->bits + n > bits->size * 8 || n > 64 || n < 0)
  145. {
  146. bits->error = -1;
  147. return -1; // throw exception
  148. }
  149. m = n;
  150. v = v << (64 - n); // left shift to first bit
  151. bits->data[bits->bits / 8] |= v >> (56 + (bits->bits % 8)); // remain valid value
  152. v <<= 8 - (bits->bits % 8);
  153. n -= 8 - (int)(bits->bits % 8);
  154. for (i = 1; n > 0; i++)
  155. {
  156. assert(bits->bits / 8 + i < bits->size);
  157. bits->data[bits->bits / 8 + i] = (uint8_t)(v >> 56);
  158. v <<= 8;
  159. n -= 8;
  160. }
  161. bits->bits += m;
  162. return 0;
  163. }
  164. #ifdef __cplusplus
  165. }
  166. #endif
  167. #endif /* !_mpeg4_bits_h_ */