Older/MediaServer/libflv/include/mpeg4-bits.h

202 lines
4.6 KiB
C
Raw Normal View History

2024-10-01 00:12:57 +08:00
#ifndef _mpeg4_bits_h_
#define _mpeg4_bits_h_
#include <stdint.h>
#include <stddef.h>
#include <assert.h>
#ifdef __cplusplus
extern "C" {
#endif
struct mpeg4_bits_t
{
uint8_t* data;
size_t size;
size_t bits; // offset bit
int error;
};
#define mpeg4_bits_read_uint8(bits, n) (uint8_t)mpeg4_bits_read_n(bits, n)
#define mpeg4_bits_read_uint16(bits, n) (uint16_t)mpeg4_bits_read_n(bits, n)
#define mpeg4_bits_read_uint32(bits, n) (uint32_t)mpeg4_bits_read_n(bits, n)
#define mpeg4_bits_read_uint64(bits, n) (uint64_t)mpeg4_bits_read_n(bits, n)
#define mpeg4_bits_write_uint8(bits, v, n) mpeg4_bits_write_n(bits, (uint64_t)v, n)
#define mpeg4_bits_write_uint16(bits, v, n) mpeg4_bits_write_n(bits, (uint64_t)v, n)
#define mpeg4_bits_write_uint32(bits, v, n) mpeg4_bits_write_n(bits, (uint64_t)v, n)
#define mpeg4_bits_write_uint64(bits, v, n) mpeg4_bits_write_n(bits, (uint64_t)v, n)
static inline void mpeg4_bits_init(struct mpeg4_bits_t* bits, void* data, size_t size)
{
bits->data = (uint8_t*)data;
bits->size = size;
bits->bits = 0;
bits->error = 0;
}
/// @return 1-error, 0-no error
static inline int mpeg4_bits_error(struct mpeg4_bits_t* bits)
{
//return bits->bits >= bits->size * 8 ? 1 : 0;
return bits->error;
}
static inline void mpeg4_bits_aligment(struct mpeg4_bits_t* bits, int n)
{
bits->bits = (bits->bits + n - 1) / n * n;
}
static inline size_t mpeg4_bits_remain(struct mpeg4_bits_t* bits)
{
return bits->error ? 0 : (bits->size * 8 - bits->bits);
}
static inline void mpeg4_bits_skip(struct mpeg4_bits_t* bits, size_t n)
{
bits->bits += n;
if (bits->bits > bits->size * 8)
{
bits->error = -1;
}
}
/// read 1-bit from bit stream(offset position)
/// @param[in] bits bit stream
/// @return -1-error, 1-value, 0-value
static inline int mpeg4_bits_read(struct mpeg4_bits_t* bits)
{
uint8_t bit;
assert(bits && bits->data && bits->size > 0);
if (bits->bits >= bits->size * 8)
{
bits->error = -1;
return 0; // throw exception
}
bit = bits->data[bits->bits/8] & (0x80U >> (bits->bits%8));
bits->bits += 1; // update offset
return bit ? 1 : 0;
}
/// read n-bit(n <= 64) from bit stream(offset position)
/// @param[in] bits bit stream
/// @return -1-error, other-value
static inline uint64_t mpeg4_bits_read_n(struct mpeg4_bits_t* bits, int n)
{
int m;
size_t i;
uint64_t v;
assert(n > 0 && n <= 64);
assert(bits && bits->data && bits->size > 0);
if (bits->bits + n > bits->size * 8 || n > 64 || n < 0)
{
bits->error = -1;
return 0; // throw exception
}
m = n;
v = bits->data[bits->bits / 8] & (0xFFU >> (bits->bits%8)); // remain valid value
if (n <= 8 - (int)(bits->bits % 8))
{
v = v >> (8 - (bits->bits % 8) - n); // shift right value
bits->bits += n;
return v;
}
n -= 8 - (int)(bits->bits % 8);
for (i = 1; n >= 8; i++)
{
assert(bits->bits / 8 + i < bits->size);
v <<= 8;
v += bits->data[bits->bits / 8 + i];
n -= 8;
}
if (n > 0)
{
v <<= n;
v += bits->data[bits->bits / 8 + i] >> (8 - n);
}
bits->bits += m;
return v;
}
// http://aomedia.org/av1/specification/conventions/#descriptors
static inline uint64_t mpeg4_bits_read_uvlc(struct mpeg4_bits_t* bits)
{
uint64_t value;
int leadingZeros;
for (leadingZeros = 0; !mpeg4_bits_read(bits); ++leadingZeros)
{
}
if (leadingZeros >= 32)
return (1ULL << 32) - 1;
value = mpeg4_bits_read_n(bits, leadingZeros);
return (1ULL << leadingZeros) - 1 + value;
}
static inline uint64_t mpeg4_bits_read_latm(struct mpeg4_bits_t* bits)
{
int len;
len = (int)mpeg4_bits_read_n(bits, 2);
return mpeg4_bits_read_n(bits, (len + 1) * 8);
}
/// write 1-bit
/// @param[in] v write 0 if v value 0, other, write 1
static inline int mpeg4_bits_write(struct mpeg4_bits_t* bits, int v)
{
assert(bits && bits->data && bits->size > 0);
if (bits->bits >= bits->size * 8)
{
bits->error = -1;
return -1; // throw exception
}
if(v)
bits->data[bits->bits / 8] |= (0x80U >> (bits->bits % 8));
bits->bits += 1; // update offset
return 0;
}
static inline int mpeg4_bits_write_n(struct mpeg4_bits_t* bits, uint64_t v, int n)
{
int m;
size_t i;
assert(n > 0 && n <= 64);
assert(bits && bits->data && bits->size > 0);
if (bits->bits + n > bits->size * 8 || n > 64 || n < 0)
{
bits->error = -1;
return -1; // throw exception
}
m = n;
v = v << (64 - n); // left shift to first bit
bits->data[bits->bits / 8] |= v >> (56 + (bits->bits % 8)); // remain valid value
v <<= 8 - (bits->bits % 8);
n -= 8 - (int)(bits->bits % 8);
for (i = 1; n > 0; i++)
{
assert(bits->bits / 8 + i < bits->size);
bits->data[bits->bits / 8 + i] = (uint8_t)(v >> 56);
v <<= 8;
n -= 8;
}
bits->bits += m;
return 0;
}
#ifdef __cplusplus
}
#endif
#endif /* !_mpeg4_bits_h_ */