diff options
Diffstat (limited to 'media/libstagefright/codecs/avc/dec/src/avc_bitstream.cpp')
-rw-r--r-- | media/libstagefright/codecs/avc/dec/src/avc_bitstream.cpp | 276 |
1 files changed, 276 insertions, 0 deletions
diff --git a/media/libstagefright/codecs/avc/dec/src/avc_bitstream.cpp b/media/libstagefright/codecs/avc/dec/src/avc_bitstream.cpp new file mode 100644 index 0000000..270b664 --- /dev/null +++ b/media/libstagefright/codecs/avc/dec/src/avc_bitstream.cpp @@ -0,0 +1,276 @@ +/* ------------------------------------------------------------------ + * Copyright (C) 1998-2009 PacketVideo + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the License for the specific language governing permissions + * and limitations under the License. + * ------------------------------------------------------------------- + */ +#include "avcdec_bitstream.h" + +/* Swapping may not be needed anymore since we read one byte at a time and perform +EBSP to RBSP conversion in bitstream. */ +#ifdef LITTLE_ENDIAN +#if (WORD_SIZE==32) /* this can be replaced with assembly instructions */ +#define SWAP_BYTES(x) ((((x)&0xFF)<<24) | (((x)&0xFF00)<<8) | (((x)&0xFF0000)>>8) | (((x)&0xFF000000)>>24)) +#else /* for 16-bit */ +#define SWAP_BYTES(x) ((((x)&0xFF)<<8) | (((x)&0xFF00)>>8)) +#endif +#else +#define SWAP_BYTES(x) (x) +#endif + + +/* array for trailing bit pattern as function of number of bits */ +/* the first one is unused. */ +const static uint8 trailing_bits[9] = {0, 0x1, 0x2, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80}; + +/* ======================================================================== */ +/* Function : BitstreamInit() */ +/* Date : 11/4/2003 */ +/* Purpose : Populate bitstream structure with bitstream buffer and size */ +/* it also initializes internal data */ +/* In/out : */ +/* Return : AVCDEC_SUCCESS if successed, AVCDEC_FAIL if failed. */ +/* Modified : */ +/* ======================================================================== */ +/* |--------|--------|----~~~~~-----|---------|---------|---------| + ^ ^read_pos ^data_end_pos + bitstreamBuffer <---------> + current_word + + |xxxxxxxxxxxxx----| = current_word 32 or 16 bits + <------------> + bit_left + ======================================================================== */ + + +/* ======================================================================== */ +/* Function : BitstreamNextWord() */ +/* Date : 12/4/2003 */ +/* Purpose : Read up to machine word. */ +/* In/out : */ +/* Return : Next word with emulation prevention code removed. Everything + in the bitstream structure got modified except current_word */ +/* Modified : */ +/* ======================================================================== */ + +AVCDec_Status BitstreamInit(AVCDecBitstream *stream, uint8 *buffer, int size) +{ + EBSPtoRBSP(buffer, &size); + + stream->incnt = 0; + stream->incnt_next = 0; + stream->bitcnt = 0; + stream->curr_word = stream->next_word = 0; + stream->read_pos = 0; + + stream->bitstreamBuffer = buffer; + + stream->data_end_pos = size; + + stream->nal_size = size; + + return AVCDEC_SUCCESS; +} +/* ======================================================================== */ +/* Function : AVC_BitstreamFillCache() */ +/* Date : 1/1/2005 */ +/* Purpose : Read up to machine word. */ +/* In/out : */ +/* Return : Read in 4 bytes of input data */ +/* Modified : */ +/* ======================================================================== */ + +AVCDec_Status AVC_BitstreamFillCache(AVCDecBitstream *stream) +{ + uint8 *bitstreamBuffer = stream->bitstreamBuffer; + uint8 *v; + int num_bits, i; + + stream->curr_word |= (stream->next_word >> stream->incnt); // stream->incnt cannot be 32 + stream->next_word <<= (31 - stream->incnt); + stream->next_word <<= 1; + num_bits = stream->incnt_next + stream->incnt; + if (num_bits >= 32) + { + stream->incnt_next -= (32 - stream->incnt); + stream->incnt = 32; + return AVCDEC_SUCCESS; + } + /* this check can be removed if there is additional extra 4 bytes at the end of the bitstream */ + v = bitstreamBuffer + stream->read_pos; + + if (stream->read_pos > stream->data_end_pos - 4) + { + if (stream->data_end_pos <= stream->read_pos) + { + stream->incnt = num_bits; + stream->incnt_next = 0; + return AVCDEC_SUCCESS; + } + + stream->next_word = 0; + + for (i = 0; i < stream->data_end_pos - stream->read_pos; i++) + { + stream->next_word |= (v[i] << ((3 - i) << 3)); + } + + stream->read_pos = stream->data_end_pos; + stream->curr_word |= (stream->next_word >> num_bits); // this is safe + + stream->next_word <<= (31 - num_bits); + stream->next_word <<= 1; + num_bits = i << 3; + stream->incnt += stream->incnt_next; + stream->incnt_next = num_bits - (32 - stream->incnt); + if (stream->incnt_next < 0) + { + stream->incnt += num_bits; + stream->incnt_next = 0; + } + else + { + stream->incnt = 32; + } + return AVCDEC_SUCCESS; + } + + stream->next_word = ((uint32)v[0] << 24) | (v[1] << 16) | (v[2] << 8) | v[3]; + stream->read_pos += 4; + + stream->curr_word |= (stream->next_word >> num_bits); // this is safe + stream->next_word <<= (31 - num_bits); + stream->next_word <<= 1; + stream->incnt_next += stream->incnt; + stream->incnt = 32; + return AVCDEC_SUCCESS; + +} +/* ======================================================================== */ +/* Function : BitstreamReadBits() */ +/* Date : 11/4/2003 */ +/* Purpose : Read up to machine word. */ +/* In/out : */ +/* Return : AVCDEC_SUCCESS if successed, AVCDEC_FAIL if number of bits */ +/* is greater than the word-size, AVCDEC_PACKET_LOSS or */ +/* AVCDEC_NO_DATA if callback to get data fails. */ +/* Modified : */ +/* ======================================================================== */ +AVCDec_Status BitstreamReadBits(AVCDecBitstream *stream, int nBits, uint *code) +{ + if (stream->incnt < nBits) + { + /* frame-based decoding */ + AVC_BitstreamFillCache(stream); + } + *code = stream->curr_word >> (32 - nBits); + BitstreamFlushBits(stream, nBits); + return AVCDEC_SUCCESS; +} + + + +/* ======================================================================== */ +/* Function : BitstreamShowBits() */ +/* Date : 11/4/2003 */ +/* Purpose : Show up to machine word without advancing the pointer. */ +/* In/out : */ +/* Return : AVCDEC_SUCCESS if successed, AVCDEC_FAIL if number of bits */ +/* is greater than the word-size, AVCDEC_NO_DATA if it needs */ +/* to callback to get data. */ +/* Modified : */ +/* ======================================================================== */ +AVCDec_Status BitstreamShowBits(AVCDecBitstream *stream, int nBits, uint *code) +{ + if (stream->incnt < nBits) + { + /* frame-based decoding */ + AVC_BitstreamFillCache(stream); + } + + *code = stream->curr_word >> (32 - nBits); + + return AVCDEC_SUCCESS; +} + +/* ======================================================================== */ +/* Function : BitstreamRead1Bit() */ +/* Date : 11/4/2003 */ +/* Purpose : Read 1 bit from the bitstream. */ +/* In/out : */ +/* Return : AVCDEC_SUCCESS if successed, AVCDEC_FAIL if number of bits */ +/* is greater than the word-size, AVCDEC_PACKET_LOSS or */ +/* AVCDEC_NO_DATA if callback to get data fails. */ +/* Modified : */ +/* ======================================================================== */ + +AVCDec_Status BitstreamRead1Bit(AVCDecBitstream *stream, uint *code) +{ + if (stream->incnt < 1) + { + /* frame-based decoding */ + AVC_BitstreamFillCache(stream); + } + *code = stream->curr_word >> 31; + BitstreamFlushBits(stream, 1); + return AVCDEC_SUCCESS; +} + + + +AVCDec_Status BitstreamByteAlign(AVCDecBitstream *stream) +{ + uint n_stuffed; + + n_stuffed = (8 - (stream->bitcnt & 0x7)) & 0x7; /* 07/05/01 */ + + stream->bitcnt += n_stuffed; + stream->incnt -= n_stuffed; + + if (stream->incnt < 0) + { + stream->bitcnt += stream->incnt; + stream->incnt = 0; + } + stream->curr_word <<= n_stuffed; + return AVCDEC_SUCCESS; +} + +/* check whether there are more RBSP data. */ +/* ignore the emulation prevention code, assume it has been taken out. */ +bool more_rbsp_data(AVCDecBitstream *stream) +{ + int total_bit_left; + uint code; + + if (stream->read_pos >= stream->nal_size) + { + total_bit_left = stream->incnt_next + stream->incnt; + if (total_bit_left <= 0) + { + return FALSE; + } + else if (total_bit_left <= 8) + { + BitstreamShowBits(stream, total_bit_left, &code); + if (code == trailing_bits[total_bit_left]) + { + return FALSE; + } + } + } + + return TRUE; +} + |