📄 bitstream.c
字号:
assert(!bs->nbBits); BS_WriteByte(bs, (u8) ((value>>8)&0xff)); BS_WriteByte(bs, (u8) ((value)&0xff));}GF_EXPORTvoid gf_bs_write_u24(GF_BitStream *bs, u32 value){ assert(!bs->nbBits); BS_WriteByte(bs, (u8) ((value>>16)&0xff)); BS_WriteByte(bs, (u8) ((value>>8)&0xff)); BS_WriteByte(bs, (u8) ((value)&0xff));}GF_EXPORTvoid gf_bs_write_u32(GF_BitStream *bs, u32 value){ assert(!bs->nbBits); BS_WriteByte(bs, (u8) ((value>>24)&0xff)); BS_WriteByte(bs, (u8) ((value>>16)&0xff)); BS_WriteByte(bs, (u8) ((value>>8)&0xff)); BS_WriteByte(bs, (u8) ((value)&0xff));}GF_EXPORTvoid gf_bs_write_u64(GF_BitStream *bs, u64 value){ assert(!bs->nbBits); gf_bs_write_u32(bs, (u32) ((value>>32)&0xffffffff)); gf_bs_write_u32(bs, (u32) (value&0xffffffff));}GF_EXPORTvoid gf_bs_write_float(GF_BitStream *bs, Float value){ u32 i; union { float f; char sz [4]; } float_value; float_value.f = value; for (i = 0; i < 32; i++) BS_WriteBit(bs, (float_value.sz [3 - i / 8] & 1 << (7 - i % 8)) != 0);}GF_EXPORTvoid gf_bs_write_double (GF_BitStream *bs, Double value){ u32 i; union { Double d; char sz [8]; } double_value; double_value.d = value; for (i = 0; i < 64; i++) { BS_WriteBit(bs, (double_value.sz [7 - i / 8] & 1 << (7 - i % 8)) != 0); }}GF_EXPORTu32 gf_bs_write_data(GF_BitStream *bs, char *data, u32 nbBytes){ /*we need some feedback for this guy...*/ u64 begin = bs->position; if (!nbBytes) return 0; if (BS_IsAlign(bs)) { switch (bs->bsmode) { case GF_BITSTREAM_WRITE: if (bs->position+nbBytes > bs->size) return 0; memcpy(bs->original + bs->position, data, nbBytes); bs->position += nbBytes; return nbBytes; case GF_BITSTREAM_WRITE_DYN: /*need to realloc ...*/ if (bs->position+nbBytes > bs->size) { if (bs->size + nbBytes > 0xFFFFFFFF) return 0; bs->original = (char*)realloc(bs->original, sizeof(u32)*((u32) bs->size + nbBytes)); if (!bs->original) return 0; bs->size += nbBytes; } memcpy(bs->original + bs->position, data, nbBytes); bs->position += nbBytes; return nbBytes; case GF_BITSTREAM_FILE_READ: case GF_BITSTREAM_FILE_WRITE: if (fwrite(data, nbBytes, 1, bs->stream) != 1) return 0; if (bs->size == bs->position) bs->size += nbBytes; bs->position += nbBytes; return nbBytes; default: return 0; } } while (nbBytes) { gf_bs_write_int(bs, (s32) *data, 8); data++; nbBytes--; } return (u32) (bs->position - begin);}/*align return the num of bits read in READ mode, 0 in WRITE*/GF_EXPORTu8 gf_bs_align(GF_BitStream *bs){ u8 res = 8 - bs->nbBits; if ( (bs->bsmode == GF_BITSTREAM_READ) || (bs->bsmode == GF_BITSTREAM_FILE_READ)) { if (res > 0) { gf_bs_read_int(bs, res); } return res; } if (bs->nbBits > 0) { gf_bs_write_int (bs, 0, res); return res; } return 0;}/*size available in the bitstream*/GF_EXPORTu64 gf_bs_available(GF_BitStream *bs){ s64 cur, end; /*in WRITE mode only, this should not be called, but return something big in case ...*/ if ( (bs->bsmode == GF_BITSTREAM_WRITE) || (bs->bsmode == GF_BITSTREAM_WRITE_DYN) ) return (u64) -1; /*we are in MEM mode*/ if (bs->bsmode == GF_BITSTREAM_READ) { return (bs->size - bs->position); } /*FILE READ: assume size hasn't changed, otherwise the user shall call gf_bs_get_refreshed_size*/ if (bs->bsmode==GF_BITSTREAM_FILE_READ) return (bs->size - bs->position); cur = gf_f64_tell(bs->stream); gf_f64_seek(bs->stream, 0, SEEK_END); end = gf_f64_tell(bs->stream); gf_f64_seek(bs->stream, cur, SEEK_SET); return (u64) (end - cur);}/*call this funct to set the buffer size to the nb of bytes written Used only in WRITE mode, as we don't know the real size during allocation...return -1 for bad param or malloc failedreturn nbBytes cut*/static u32 BS_CutBuffer(GF_BitStream *bs){ u32 nbBytes; if ( (bs->bsmode != GF_BITSTREAM_WRITE_DYN) && (bs->bsmode != GF_BITSTREAM_WRITE)) return (u32) -1; /*Align our buffer or we're dead!*/ gf_bs_align(bs); nbBytes = (u32) (bs->size - bs->position); if (!nbBytes || (nbBytes == 0xFFFFFFFF) || (bs->position >= 0xFFFFFFFF)) return 0; bs->original = (char*)realloc(bs->original, (u32) bs->position); if (! bs->original) return (u32) -1; /*just in case, re-adjust..*/ bs->size = bs->position; return nbBytes;}/*For DYN mode, this gets the content out*/GF_EXPORTvoid gf_bs_get_content(GF_BitStream *bs, char **output, u32 *outSize){ /*only in WRITE MEM mode*/ if (bs->bsmode != GF_BITSTREAM_WRITE_DYN) return; if (!bs->position && !bs->nbBits) { *output = NULL; *outSize = 0; free(bs->original); } else { BS_CutBuffer(bs); *output = bs->original; *outSize = (u32) bs->size; } bs->original = NULL; bs->size = 0; bs->position = 0;}/* Skip nbytes. Align If READ (MEM or FILE) mode, just read n times 8 bit If WRITE (MEM or FILE) mode, write n times 0 on 8 bit*/GF_EXPORTvoid gf_bs_skip_bytes(GF_BitStream *bs, u64 nbBytes){ if (!bs || !nbBytes) return; gf_bs_align(bs); /*special case for file skipping...*/ if ((bs->bsmode == GF_BITSTREAM_FILE_WRITE) || (bs->bsmode == GF_BITSTREAM_FILE_READ)) { gf_f64_seek(bs->stream, nbBytes, SEEK_CUR); bs->position += nbBytes; return; } /*special case for reading*/ if (bs->bsmode == GF_BITSTREAM_READ) { bs->position += nbBytes; return; } /*for writing we must do it this way, otherwise pb in dynamic buffers*/ while (nbBytes) { gf_bs_write_int(bs, 0, 8); nbBytes--; }}/*Only valid for READ MEMORY*/GF_EXPORTvoid gf_bs_rewind_bits(GF_BitStream *bs, u64 nbBits){ u64 nbBytes; if (bs->bsmode != GF_BITSTREAM_READ) return; nbBits -= (bs->nbBits); nbBytes = (nbBits+8)>>3; nbBits = nbBytes*8 - nbBits; gf_bs_align(bs); assert(bs->position >= nbBytes); bs->position -= nbBytes + 1; gf_bs_read_int(bs, (u32)nbBits); return;}/*seek from begining of stream: use internally even when non aligned!*/static GF_Err BS_SeekIntern(GF_BitStream *bs, u64 offset){ u32 i; /*if mem, do it */ if ((bs->bsmode == GF_BITSTREAM_READ) || (bs->bsmode == GF_BITSTREAM_WRITE) || (bs->bsmode == GF_BITSTREAM_WRITE_DYN)) { if (offset > 0xFFFFFFFF) return GF_IO_ERR; /*0 for write, read will be done automatically*/ if (offset >= bs->size) { if ( (bs->bsmode == GF_BITSTREAM_READ) || (bs->bsmode == GF_BITSTREAM_WRITE) ) return GF_BAD_PARAM; /*in DYN, realloc ...*/ bs->original = (char*)realloc(bs->original, (u32) (offset + 1)); for (i = 0; i < (u32) (offset + 1 - bs->size); i++) { bs->original[bs->size + i] = 0; } bs->size = offset + 1; } bs->current = bs->original[offset]; bs->position = offset; bs->nbBits = (bs->bsmode == GF_BITSTREAM_READ) ? 8 : 0; return GF_OK; } gf_f64_seek(bs->stream, offset, SEEK_SET); bs->position = offset; bs->current = 0; /*setup NbBits so that next acccess to the buffer will trigger read/write*/ bs->nbBits = (bs->bsmode == GF_BITSTREAM_FILE_READ) ? 8 : 0; return GF_OK;}/*seek from begining of stream: align before anything else*/GF_EXPORTGF_Err gf_bs_seek(GF_BitStream *bs, u64 offset){ /*warning: we allow offset = bs->size for WRITE buffers*/ if (offset > bs->size) return GF_BAD_PARAM; gf_bs_align(bs); return BS_SeekIntern(bs, offset);}/*peek bits (as int!!) from orig position (ON BYTE BOUNDARIES, from 0) - only for read ...*/GF_EXPORTu32 gf_bs_peek_bits(GF_BitStream *bs, u32 numBits, u32 byte_offset){ u64 curPos; u32 curBits, ret, current; if ( (bs->bsmode != GF_BITSTREAM_READ) && (bs->bsmode != GF_BITSTREAM_FILE_READ)) return 0; if (!numBits || (bs->size < bs->position + byte_offset)) return 0; /*store our state*/ curPos = bs->position; curBits = bs->nbBits; current = bs->current; if (byte_offset) gf_bs_seek(bs, bs->position + byte_offset); ret = gf_bs_read_int(bs, numBits); /*restore our cache - position*/ gf_bs_seek(bs, curPos); /*to avoid re-reading our bits ...*/ bs->nbBits = curBits; bs->current = current; return ret;}GF_EXPORTu64 gf_bs_get_refreshed_size(GF_BitStream *bs){ s64 offset; switch (bs->bsmode) { case GF_BITSTREAM_READ: case GF_BITSTREAM_WRITE: return bs->size; default: offset = gf_f64_tell(bs->stream); gf_f64_seek(bs->stream, 0, SEEK_END); bs->size = gf_f64_tell(bs->stream); gf_f64_seek(bs->stream, offset, SEEK_SET); return bs->size; }}GF_EXPORTu64 gf_bs_get_size(GF_BitStream *bs){ return bs->size;}GF_EXPORTu64 gf_bs_get_position(GF_BitStream *bs){ return bs->position;}GF_EXPORTu8 gf_bs_bits_available(GF_BitStream *bs){ if (bs->size > bs->position) return 8; if (bs->nbBits < 8) return (8-bs->nbBits); return 0;}GF_EXPORTvoid gf_bs_set_eos_callback(GF_BitStream *bs, void (*EndOfStream)(void *par), void *par){ bs->EndOfStream = EndOfStream; bs->par = par;}GF_EXPORTu32 gf_bs_read_u32_le(GF_BitStream *bs){ u32 ret, v; ret = gf_bs_read_int(bs, 8); v = gf_bs_read_int(bs, 8); v<<=8; ret |= v; v = gf_bs_read_int(bs, 8); v<<=16; ret |= v; v = gf_bs_read_int(bs, 8); v<<=24; ret |= v; return ret;}GF_EXPORTu16 gf_bs_read_u16_le(GF_BitStream *bs){ u32 ret, v; ret = gf_bs_read_int(bs, 8); v = gf_bs_read_int(bs, 8); v<<=8; ret |= v; return ret;}GF_EXPORTvoid gf_bs_write_u32_le(GF_BitStream *bs, u32 val){ gf_bs_write_int(bs, val & 0xFF, 8); gf_bs_write_int(bs, val>>8, 8); gf_bs_write_int(bs, val>>16, 8); gf_bs_write_int(bs, val>>24, 8);}GF_EXPORTvoid gf_bs_write_u16_le(GF_BitStream *bs, u32 val){ gf_bs_write_int(bs, val & 0xFF, 8); gf_bs_write_int(bs, val>>8, 8);}GF_EXPORTu32 gf_bs_get_bit_offset(GF_BitStream *bs){ if (bs->stream) return 0; if (bs->bsmode==GF_BITSTREAM_READ) return (u32) ( (bs->position - 1) * 8 + bs->nbBits); return (u32) ( (bs->position ) * 8 + bs->nbBits);}GF_EXPORTu32 gf_bs_get_bit_position(GF_BitStream *bs){ if (bs->stream) return 0; return bs->nbBits;}u32 gf_bs_read_vluimsbf5(GF_BitStream *bs){ u32 nb_words = 0; while (gf_bs_read_int(bs, 1)) nb_words++; nb_words++; return gf_bs_read_int(bs, 4*nb_words);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -