| /* ------------------------------------------------------------------ |
| * 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 "bitstream.h" |
| #include "mp4dec_lib.h" |
| |
| |
| #define OSCL_DISABLE_WARNING_CONDITIONAL_IS_CONSTANT |
| /* to mask the n least significant bits of an integer */ |
| static const uint32 msk[33] = |
| { |
| 0x00000000, 0x00000001, 0x00000003, 0x00000007, |
| 0x0000000f, 0x0000001f, 0x0000003f, 0x0000007f, |
| 0x000000ff, 0x000001ff, 0x000003ff, 0x000007ff, |
| 0x00000fff, 0x00001fff, 0x00003fff, 0x00007fff, |
| 0x0000ffff, 0x0001ffff, 0x0003ffff, 0x0007ffff, |
| 0x000fffff, 0x001fffff, 0x003fffff, 0x007fffff, |
| 0x00ffffff, 0x01ffffff, 0x03ffffff, 0x07ffffff, |
| 0x0fffffff, 0x1fffffff, 0x3fffffff, 0x7fffffff, |
| 0xffffffff |
| }; |
| |
| |
| /* ======================================================================== */ |
| /* Function : BitstreamFillCache() */ |
| /* Date : 08/29/2000 */ |
| /* Purpose : Read more bitstream data into buffer & the 24-byte cache. */ |
| /* This function is different from BitstreamFillBuffer in */ |
| /* that the buffer is the frame-based buffer provided by */ |
| /* the application. */ |
| /* In/out : */ |
| /* Return : PV_SUCCESS if successed, PV_FAIL if failed. */ |
| /* Modified : 4/16/01 : removed return of PV_END_OF_BUFFER */ |
| /* ======================================================================== */ |
| PV_STATUS BitstreamFillCache(BitstreamDecVideo *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 PV_SUCCESS; |
| } |
| /* this check can be removed if there is additional extra 4 bytes at the end of the bitstream */ |
| v = bitstreamBuffer + stream->read_point; |
| |
| if (stream->read_point > stream->data_end_pos - 4) |
| { |
| if (stream->data_end_pos <= stream->read_point) |
| { |
| stream->incnt = num_bits; |
| stream->incnt_next = 0; |
| return PV_SUCCESS; |
| } |
| |
| stream->next_word = 0; |
| |
| for (i = 0; i < stream->data_end_pos - stream->read_point; i++) |
| { |
| stream->next_word |= (v[i] << ((3 - i) << 3)); |
| } |
| |
| stream->read_point = 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 PV_SUCCESS; |
| } |
| |
| stream->next_word = ((uint32)v[0] << 24) | (v[1] << 16) | (v[2] << 8) | v[3]; |
| stream->read_point += 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 PV_SUCCESS; |
| } |
| |
| |
| /* ======================================================================== */ |
| /* Function : BitstreamReset() */ |
| /* Date : 08/29/2000 */ |
| /* Purpose : Initialize the bitstream buffer for frame-based decoding. */ |
| /* In/out : */ |
| /* Return : */ |
| /* Modified : */ |
| /* ======================================================================== */ |
| void BitstreamReset(BitstreamDecVideo *stream, uint8 *buffer, int32 buffer_size) |
| { |
| /* set up frame-based bitstream buffer */ |
| oscl_memset(stream, 0, sizeof(BitstreamDecVideo)); |
| stream->data_end_pos = buffer_size; |
| stream->bitstreamBuffer = buffer; |
| } |
| |
| |
| /* ======================================================================== */ |
| /* Function : BitstreamOpen() */ |
| /* Purpose : Initialize the bitstream data structure. */ |
| /* In/out : */ |
| /* Return : */ |
| /* Modified : */ |
| /* ======================================================================== */ |
| int BitstreamOpen(BitstreamDecVideo *stream, int) |
| { |
| int buffer_size = 0; |
| /* set up linear bitstream buffer */ |
| // stream->currentBytePos = 0; |
| stream->data_end_pos = 0; |
| |
| stream->incnt = 0; |
| stream->incnt_next = 0; |
| stream->bitcnt = 0; |
| stream->curr_word = stream->next_word = 0; |
| stream->read_point = stream->data_end_pos; |
| return buffer_size; |
| } |
| |
| |
| /* ======================================================================== */ |
| /* Function : BitstreamClose() */ |
| /* Purpose : Cleanup the bitstream data structure. */ |
| /* In/out : */ |
| /* Return : */ |
| /* Modified : */ |
| /* ======================================================================== */ |
| void BitstreamClose(BitstreamDecVideo *) |
| { |
| return; |
| } |
| |
| |
| /***********************************************************CommentBegin****** |
| * |
| * -- BitstreamShowBits32HC |
| * Shows 32 bits |
| ***********************************************************CommentEnd********/ |
| |
| PV_STATUS BitstreamShowBits32HC(BitstreamDecVideo *stream, uint32 *code) |
| { |
| PV_STATUS status = PV_SUCCESS; |
| |
| if (stream->incnt < 32) |
| { |
| /* frame-based decoding */ |
| status = BitstreamFillCache(stream); |
| } |
| *code = stream->curr_word; |
| return status; |
| } |
| |
| /***********************************************************CommentBegin****** |
| * |
| * -- BitstreamShowBits32 |
| * Shows upto and including 31 bits |
| ***********************************************************CommentEnd********/ |
| PV_STATUS BitstreamShowBits32(BitstreamDecVideo *stream, int nbits, uint32 *code) |
| { |
| PV_STATUS status = PV_SUCCESS; |
| |
| if (stream->incnt < nbits) |
| { |
| /* frame-based decoding */ |
| status = BitstreamFillCache(stream); |
| } |
| *code = stream->curr_word >> (32 - nbits); |
| return status; |
| } |
| |
| |
| #ifndef PV_BS_INLINE |
| /*========================================================================= */ |
| /* Function: BitstreamShowBits16() */ |
| /* Date: 12/18/2000 */ |
| /* Purpose: To see the next "nbits"(nbits<=16) bitstream bits */ |
| /* without advancing the read pointer */ |
| /* */ |
| /* =========================================================================*/ |
| PV_STATUS BitstreamShowBits16(BitstreamDecVideo *stream, int nbits, uint *code) |
| { |
| PV_STATUS status = PV_SUCCESS; |
| |
| |
| if (stream->incnt < nbits) |
| { |
| /* frame-based decoding */ |
| status = BitstreamFillCache(stream); |
| } |
| |
| *code = stream->curr_word >> (32 - nbits); |
| return status; |
| } |
| |
| |
| /*========================================================================= */ |
| /* Function: BitstreamShow15Bits() */ |
| /* Date: 01/23/2001 */ |
| /* Purpose: To see the next 15 bitstream bits */ |
| /* without advancing the read pointer */ |
| /* */ |
| /* =========================================================================*/ |
| PV_STATUS BitstreamShow15Bits(BitstreamDecVideo *stream, uint *code) |
| { |
| PV_STATUS status = PV_SUCCESS; |
| |
| if (stream->incnt < 15) |
| { |
| /* frame-based decoding */ |
| status = BitstreamFillCache(stream); |
| } |
| *code = stream->curr_word >> 17; |
| return status; |
| } |
| /*========================================================================= */ |
| /* Function: BitstreamShow13Bits */ |
| /* Date: 050923 */ |
| /* Purpose: Faciliate and speed up showing 13 bit from bitstream */ |
| /* used in VlcTCOEFF decoding */ |
| /* Modified: */ |
| /* =========================================================================*/ |
| PV_STATUS BitstreamShow13Bits(BitstreamDecVideo *stream, uint *code) |
| { |
| PV_STATUS status = PV_SUCCESS; |
| |
| if (stream->incnt < 13) |
| { |
| /* frame-based decoding */ |
| status = BitstreamFillCache(stream); |
| } |
| *code = stream->curr_word >> 19; |
| return status; |
| } |
| |
| uint BitstreamReadBits16_INLINE(BitstreamDecVideo *stream, int nbits) |
| { |
| uint code; |
| PV_STATUS status; |
| |
| if (stream->incnt < nbits) |
| { |
| /* frame-based decoding */ |
| status = BitstreamFillCache(stream); |
| } |
| code = stream->curr_word >> (32 - nbits); |
| PV_BitstreamFlushBits(stream, nbits); |
| return code; |
| } |
| |
| |
| uint BitstreamRead1Bits_INLINE(BitstreamDecVideo *stream) |
| { |
| PV_STATUS status = PV_SUCCESS; |
| uint code; |
| |
| |
| if (stream->incnt < 1) |
| { |
| /* frame-based decoding */ |
| status = BitstreamFillCache(stream); |
| } |
| code = stream->curr_word >> 31; |
| PV_BitstreamFlushBits(stream, 1); |
| |
| return code; |
| } |
| |
| #endif |
| |
| /* ======================================================================== */ |
| /* Function : BitstreamReadBits16() */ |
| /* Purpose : Read bits (nbits <=16) from bitstream buffer. */ |
| /* In/out : */ |
| /* Return : */ |
| /* ======================================================================== */ |
| uint BitstreamReadBits16(BitstreamDecVideo *stream, int nbits) |
| { |
| uint code; |
| |
| if (stream->incnt < nbits) |
| { |
| /* frame-based decoding */ |
| BitstreamFillCache(stream); |
| } |
| code = stream->curr_word >> (32 - nbits); |
| PV_BitstreamFlushBits(stream, nbits); |
| return code; |
| } |
| |
| /* ======================================================================== */ |
| /* Function : BitstreamRead1Bits() */ |
| /* Date : 10/23/2000 */ |
| /* Purpose : Faciliate and speed up reading 1 bit from bitstream. */ |
| /* In/out : */ |
| /* Return : */ |
| /* ======================================================================== */ |
| |
| uint BitstreamRead1Bits(BitstreamDecVideo *stream) |
| { |
| uint code; |
| |
| if (stream->incnt < 1) |
| { |
| /* frame-based decoding */ |
| BitstreamFillCache(stream); |
| } |
| code = stream->curr_word >> 31; |
| PV_BitstreamFlushBits(stream, 1); |
| |
| return code; |
| } |
| |
| /* ======================================================================== */ |
| /* Function : PV_BitstreamFlushBitsCheck() */ |
| /* Purpose : Flush nbits bits from bitstream buffer. Check for cache */ |
| /* In/out : */ |
| /* Return : */ |
| /* Modified : */ |
| /* ======================================================================== */ |
| PV_STATUS PV_BitstreamFlushBitsCheck(BitstreamDecVideo *stream, int nbits) |
| { |
| PV_STATUS status = PV_SUCCESS; |
| |
| stream->bitcnt += nbits; |
| stream->incnt -= nbits; |
| if (stream->incnt < 0) |
| { |
| /* frame-based decoding */ |
| status = BitstreamFillCache(stream); |
| |
| if (stream->incnt < 0) |
| { |
| stream->bitcnt += stream->incnt; |
| stream->incnt = 0; |
| } |
| } |
| stream->curr_word <<= nbits; |
| return status; |
| } |
| |
| /* ======================================================================== */ |
| /* Function : BitstreamReadBits32() */ |
| /* Purpose : Read bits from bitstream buffer. */ |
| /* In/out : */ |
| /* Return : */ |
| /* ======================================================================== */ |
| uint32 BitstreamReadBits32(BitstreamDecVideo *stream, int nbits) |
| { |
| uint32 code; |
| |
| if (stream->incnt < nbits) |
| { |
| /* frame-based decoding */ |
| BitstreamFillCache(stream); |
| } |
| code = stream->curr_word >> (32 - nbits); |
| PV_BitstreamFlushBits(stream, nbits); |
| return code; |
| } |
| |
| uint32 BitstreamReadBits32HC(BitstreamDecVideo *stream) |
| { |
| uint32 code; |
| |
| BitstreamShowBits32HC(stream, &code); |
| stream->bitcnt += 32; |
| stream->incnt = 0; |
| stream->curr_word = 0; |
| return code; |
| } |
| |
| /* ======================================================================== */ |
| /* Function : BitstreamCheckEndBuffer() */ |
| /* Date : 03/30/2001 */ |
| /* Purpose : Check to see if we are at the end of buffer */ |
| /* In/out : */ |
| /* Return : */ |
| /* Modified : */ |
| /* ======================================================================== */ |
| PV_STATUS BitstreamCheckEndBuffer(BitstreamDecVideo *stream) |
| { |
| if (stream->read_point >= stream->data_end_pos && stream->incnt <= 0) return PV_END_OF_VOP; |
| return PV_SUCCESS; |
| } |
| |
| |
| PV_STATUS PV_BitstreamShowBitsByteAlign(BitstreamDecVideo *stream, int nbits, uint32 *code) |
| { |
| PV_STATUS status = PV_SUCCESS; |
| |
| int n_stuffed; |
| |
| n_stuffed = 8 - (stream->bitcnt & 0x7); /* 07/05/01 */ |
| |
| if (stream->incnt < (nbits + n_stuffed)) |
| { |
| /* frame-based decoding */ |
| status = BitstreamFillCache(stream); |
| } |
| |
| *code = (stream->curr_word << n_stuffed) >> (32 - nbits); |
| return status; |
| } |
| |
| #ifdef PV_ANNEX_IJKT_SUPPORT |
| PV_STATUS PV_BitstreamShowBitsByteAlignNoForceStuffing(BitstreamDecVideo *stream, int nbits, uint32 *code) |
| { |
| PV_STATUS status = PV_SUCCESS; |
| |
| int n_stuffed; |
| |
| n_stuffed = (8 - (stream->bitcnt & 0x7)) & 7; |
| |
| if (stream->incnt < (nbits + n_stuffed)) |
| { |
| /* frame-based decoding */ |
| status = BitstreamFillCache(stream); |
| } |
| |
| *code = (stream->curr_word << n_stuffed) >> (32 - nbits); |
| return status; |
| } |
| #endif |
| |
| PV_STATUS PV_BitstreamByteAlign(BitstreamDecVideo *stream) |
| { |
| PV_STATUS status = PV_SUCCESS; |
| int n_stuffed; |
| |
| n_stuffed = 8 - (stream->bitcnt & 0x7); /* 07/05/01 */ |
| |
| /* We have to make sure we have enough bits in the cache. 08/15/2000 */ |
| if (stream->incnt < n_stuffed) |
| { |
| /* frame-based decoding */ |
| status = BitstreamFillCache(stream); |
| } |
| |
| |
| stream->bitcnt += n_stuffed; |
| stream->incnt -= n_stuffed; |
| stream->curr_word <<= n_stuffed; |
| if (stream->incnt < 0) |
| { |
| stream->bitcnt += stream->incnt; |
| stream->incnt = 0; |
| } |
| return status; |
| } |
| |
| |
| PV_STATUS BitstreamByteAlignNoForceStuffing(BitstreamDecVideo *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 PV_SUCCESS; |
| } |
| |
| |
| /* ==================================================================== */ |
| /* Function : getPointer() */ |
| /* Date : 10/98 */ |
| /* Purpose : get current position of file pointer */ |
| /* In/out : */ |
| /* Return : */ |
| /* ==================================================================== */ |
| int32 getPointer(BitstreamDecVideo *stream) |
| { |
| return stream->bitcnt; |
| } |
| |
| |
| |
| |
| /* ====================================================================== / |
| Function : movePointerTo() |
| Date : 05/14/2004 |
| Purpose : move bitstream pointer to a desired position |
| In/out : |
| Return : |
| Modified : |
| / ====================================================================== */ |
| PV_STATUS movePointerTo(BitstreamDecVideo *stream, int32 pos) |
| { |
| int32 byte_pos; |
| if (pos < 0) |
| { |
| pos = 0; |
| } |
| |
| byte_pos = pos >> 3; |
| |
| if (byte_pos > stream->data_end_pos) |
| { |
| byte_pos = stream->data_end_pos; |
| } |
| |
| stream->read_point = byte_pos & -4; |
| stream->bitcnt = stream->read_point << 3;; |
| stream->curr_word = 0; |
| stream->next_word = 0; |
| stream->incnt = 0; |
| stream->incnt_next = 0; |
| BitstreamFillCache(stream); |
| PV_BitstreamFlushBits(stream, ((pos & 0x7) + ((byte_pos & 0x3) << 3))); |
| return PV_SUCCESS; |
| } |
| |
| |
| /* ======================================================================== */ |
| /* Function : validStuffing() */ |
| /* Date : 04/11/2000 */ |
| /* Purpose : Check whether we have valid stuffing at current position. */ |
| /* In/out : */ |
| /* Return : PV_TRUE if successed, PV_FALSE if failed. */ |
| /* Modified : 12/18/2000 : changed the pattern type to uint */ |
| /* 04/01/2001 : removed PV_END_OF_BUFFER */ |
| /* ======================================================================== */ |
| Bool validStuffing(BitstreamDecVideo *stream) |
| { |
| uint n_stuffed; |
| uint pattern; |
| |
| |
| n_stuffed = 8 - (stream->bitcnt & 0x7); |
| BitstreamShowBits16(stream, n_stuffed, &pattern); |
| if (pattern == msk[n_stuffed-1]) return PV_TRUE; |
| return PV_FALSE; |
| } |
| #ifdef PV_ANNEX_IJKT_SUPPORT |
| Bool validStuffing_h263(BitstreamDecVideo *stream) |
| { |
| uint n_stuffed; |
| uint pattern; |
| |
| |
| n_stuffed = (8 - (stream->bitcnt & 0x7)) & 7; // stream->incnt % 8 |
| if (n_stuffed == 0) |
| { |
| return PV_TRUE; |
| } |
| BitstreamShowBits16(stream, n_stuffed, &pattern); |
| if (pattern == 0) return PV_TRUE; |
| return PV_FALSE; |
| } |
| #endif |
| |
| |
| /* ======================================================================== */ |
| /* Function : PVSearchNextH263Frame() */ |
| /* Date : 04/08/2005 */ |
| /* Purpose : search for 0x00 0x00 0x80 */ |
| /* In/out : */ |
| /* Return : PV_SUCCESS if succeeded or PV_END_OF_VOP if failed */ |
| /* Modified : */ |
| /* ======================================================================== */ |
| PV_STATUS PVSearchNextH263Frame(BitstreamDecVideo *stream) |
| { |
| PV_STATUS status = PV_SUCCESS; |
| uint8 *ptr; |
| int32 i; |
| int32 initial_byte_aligned_position = (stream->bitcnt + 7) >> 3; |
| |
| ptr = stream->bitstreamBuffer + initial_byte_aligned_position; |
| |
| i = PVLocateH263FrameHeader(ptr, stream->data_end_pos - initial_byte_aligned_position); |
| if (stream->data_end_pos <= initial_byte_aligned_position + i) |
| { |
| status = PV_END_OF_VOP; |
| } |
| (void)movePointerTo(stream, ((i + initial_byte_aligned_position) << 3)); /* ptr + i */ |
| return status; |
| } |
| |
| |
| /* ======================================================================== */ |
| /* Function : PVSearchNextM4VFrame() */ |
| /* Date : 04/08/2005 */ |
| /* Purpose : search for 0x00 0x00 0x01 and move the pointer to the */ |
| /* beginning of the start code */ |
| /* In/out : */ |
| /* Return : PV_SUCCESS if succeeded or PV_END_OF_VOP if failed */ |
| /* Modified : */ |
| /* ======================================================================== */ |
| |
| PV_STATUS PVSearchNextM4VFrame(BitstreamDecVideo *stream) |
| { |
| PV_STATUS status = PV_SUCCESS; |
| uint8 *ptr; |
| int32 i; |
| int32 initial_byte_aligned_position = (stream->bitcnt + 7) >> 3; |
| |
| ptr = stream->bitstreamBuffer + initial_byte_aligned_position; |
| |
| i = PVLocateFrameHeader(ptr, stream->data_end_pos - initial_byte_aligned_position); |
| if (stream->data_end_pos <= initial_byte_aligned_position + i) |
| { |
| status = PV_END_OF_VOP; |
| } |
| (void)movePointerTo(stream, ((i + initial_byte_aligned_position) << 3)); /* ptr + i */ |
| return status; |
| } |
| |
| |
| |
| void PVLocateM4VFrameBoundary(BitstreamDecVideo *stream) |
| { |
| uint8 *ptr; |
| int32 byte_pos = (stream->bitcnt >> 3); |
| |
| stream->searched_frame_boundary = 1; |
| ptr = stream->bitstreamBuffer + byte_pos; |
| |
| stream->data_end_pos = PVLocateFrameHeader(ptr, (int32)stream->data_end_pos - byte_pos) + byte_pos; |
| } |
| |
| void PVLocateH263FrameBoundary(BitstreamDecVideo *stream) |
| { |
| uint8 *ptr; |
| int32 byte_pos = (stream->bitcnt >> 3); |
| |
| stream->searched_frame_boundary = 1; |
| ptr = stream->bitstreamBuffer + byte_pos; |
| |
| stream->data_end_pos = PVLocateH263FrameHeader(ptr, (int32)stream->data_end_pos - byte_pos) + byte_pos; |
| } |
| |
| /* ======================================================================== */ |
| /* Function : quickSearchVideoPacketHeader() */ |
| /* Date : 05/08/2000 */ |
| /* Purpose : Quick search for the next video packet header */ |
| /* In/out : */ |
| /* Return : PV_TRUE if successed, PV_FALSE if failed. */ |
| /* Modified : */ |
| /* ======================================================================== */ |
| PV_STATUS quickSearchVideoPacketHeader(BitstreamDecVideo *stream, int marker_length) |
| { |
| PV_STATUS status = PV_SUCCESS; |
| uint32 tmpvar; |
| |
| |
| if (stream->searched_frame_boundary == 0) |
| { |
| PVLocateM4VFrameBoundary(stream); |
| } |
| |
| do |
| { |
| status = BitstreamCheckEndBuffer(stream); |
| if (status == PV_END_OF_VOP) break; |
| PV_BitstreamShowBitsByteAlign(stream, marker_length, &tmpvar); |
| if (tmpvar == RESYNC_MARKER) break; |
| PV_BitstreamFlushBits(stream, 8); |
| } |
| while (status == PV_SUCCESS); |
| |
| return status; |
| } |
| #ifdef PV_ANNEX_IJKT_SUPPORT |
| PV_STATUS quickSearchH263SliceHeader(BitstreamDecVideo *stream) |
| { |
| PV_STATUS status = PV_SUCCESS; |
| uint32 tmpvar; |
| |
| |
| if (stream->searched_frame_boundary == 0) |
| { |
| PVLocateH263FrameBoundary(stream); |
| } |
| |
| do |
| { |
| status = BitstreamCheckEndBuffer(stream); |
| if (status == PV_END_OF_VOP) break; |
| PV_BitstreamShowBitsByteAlignNoForceStuffing(stream, 17, &tmpvar); |
| if (tmpvar == RESYNC_MARKER) break; |
| PV_BitstreamFlushBits(stream, 8); |
| } |
| while (status == PV_SUCCESS); |
| |
| return status; |
| } |
| #endif |
| /* ======================================================================== */ |
| /* The following functions are for Error Concealment. */ |
| /* ======================================================================== */ |
| |
| /****************************************************/ |
| // 01/22/99 Quick search of Resync Marker |
| // (actually the first part of it, i.e. 16 0's and a 1. |
| |
| /* We are not using the fastest algorithm possible. What this function does is |
| to locate 11 consecutive 0's and then check if the 5 bits before them and |
| the 1 bit after them are all 1's. |
| */ |
| |
| // Table used for quick search of markers. Gives the last `1' in |
| // 4 bits. The MSB is bit #1, the LSB is bit #4. |
| const int lastOne[] = |
| { |
| 0, 4, 3, 4, 2, 4, 3, 4, |
| 1, 4, 3, 4, 2, 4, 3, 4 |
| }; |
| |
| // Table used for quick search of markers. Gives the last `0' in |
| // 4 bits. The MSB is bit #1, the LSB is bit #4. |
| /*const int lastZero[]= |
| { |
| 4, 3, 4, 2, 4, 3, 4, 1, |
| 4, 3, 4, 2, 4, 3, 4, 0 |
| }; |
| */ |
| // Table used for quick search of markers. Gives the first `0' in |
| // 4 bits. The MSB is bit #1, the LSB is bit #4. |
| const int firstZero[] = |
| { |
| 1, 1, 1, 1, 1, 1, 1, 1, |
| 2, 2, 2, 2, 3, 3, 4, 0 |
| }; |
| |
| // Table used for quick search of markers. Gives the first `1' in |
| // 4 bits. The MSB is bit #1, the LSB is bit #4. |
| const int firstOne[] = |
| { |
| 0, 4, 3, 3, 2, 2, 2, 2, |
| 1, 1, 1, 1, 1, 1, 1, 1 |
| }; |
| |
| |
| /* ======================================================================== */ |
| /* Function : quickSearchMarkers() */ |
| /* Date : 01/25/99 */ |
| /* Purpose : Quick search for Motion marker */ |
| /* In/out : */ |
| /* Return : Boolean true of false */ |
| /* Modified : 12/18/2000 : 32-bit version */ |
| /* ======================================================================== */ |
| PV_STATUS quickSearchMotionMarker(BitstreamDecVideo *stream) |
| // MM: (11111000000000001) |
| { |
| PV_STATUS status; |
| uint32 tmpvar, tmpvar2; |
| |
| if (stream->searched_frame_boundary == 0) |
| { |
| PVLocateM4VFrameBoundary(stream); |
| } |
| |
| while (TRUE) |
| { |
| status = BitstreamCheckEndBuffer(stream); |
| if (status == PV_END_OF_VOP) return PV_END_OF_VOP; |
| |
| BitstreamShowBits32(stream, 17, &tmpvar); |
| if (!tmpvar) return PV_FAIL; |
| |
| if (tmpvar & 1) // Check if the 17th bit from the curr bit pos is a '1' |
| { |
| if (tmpvar == MOTION_MARKER_COMB) |
| { |
| return PV_SUCCESS; // Found |
| } |
| else |
| { |
| tmpvar >>= 1; |
| tmpvar &= 0xF; |
| PV_BitstreamFlushBits(stream, (int)(12 + firstZero[tmpvar])); |
| } |
| } |
| else |
| { |
| // 01/25/99 Get the first 16 bits |
| tmpvar >>= 1; |
| tmpvar2 = tmpvar & 0xF; |
| |
| // 01/26/99 Check bits #13 ~ #16 |
| if (tmpvar2) |
| { |
| PV_BitstreamFlushBits(stream, (int)(7 + lastOne[tmpvar2])); |
| } |
| else |
| { |
| tmpvar >>= 4; |
| tmpvar2 = tmpvar & 0xF; |
| |
| // 01/26/99 Check bits #9 ~ #12 |
| if (tmpvar2) |
| { |
| PV_BitstreamFlushBits(stream, (int)(3 + lastOne[tmpvar2])); |
| } |
| else |
| { |
| tmpvar >>= 4; |
| tmpvar2 = tmpvar & 0xF; |
| |
| // 01/26/99 Check bits #5 ~ #8 |
| // We don't need to check further |
| // for the first 5 bits should be all 1's |
| if (lastOne[tmpvar2] < 2) |
| { |
| /* we already have too many consecutive 0's. */ |
| /* Go directly pass the last of the 17 bits. */ |
| PV_BitstreamFlushBits(stream, 17); |
| } |
| else |
| { |
| PV_BitstreamFlushBits(stream, (int)(lastOne[tmpvar2] - 1)); |
| } |
| } |
| } |
| } |
| |
| } |
| } |
| |
| /* ======================================================================== */ |
| /* Function : quickSearchDCM() */ |
| /* Date : 01/22/99 */ |
| /* Purpose : Quick search for DC Marker */ |
| /* We are not using the fastest algorithm possible. What this */ |
| /* function does is to locate 11 consecutive 0's and then */ |
| /* check if the 7 bits before them and the 1 bit after them */ |
| /* are correct. (actually the first part of it, i.e. 16 0's */ |
| /* and a 1. */ |
| /* In/out : */ |
| /* Return : Boolean true of false */ |
| /* Modified : 12/18/2000 : 32-bit version */ |
| /* ======================================================================== */ |
| PV_STATUS quickSearchDCM(BitstreamDecVideo *stream) |
| // DCM: (110 1011 0000 0000 0001) |
| { |
| PV_STATUS status; |
| uint32 tmpvar, tmpvar2; |
| |
| if (stream->searched_frame_boundary == 0) |
| { |
| PVLocateM4VFrameBoundary(stream); |
| } |
| |
| while (TRUE) |
| { |
| status = BitstreamCheckEndBuffer(stream); |
| if (status == PV_END_OF_VOP) return PV_END_OF_VOP; |
| BitstreamShowBits32(stream, 19, &tmpvar); |
| |
| if (tmpvar & 1) // Check if the 17th bit from the curr bit pos is a '1' |
| { |
| if (tmpvar == DC_MARKER) |
| { |
| return PV_SUCCESS; // Found |
| } |
| else |
| { |
| // 01/25/99 We treat the last of the 19 bits as its 7th bit (which is |
| // also a `1' |
| PV_BitstreamFlushBits(stream, 12); |
| } |
| } |
| else |
| { |
| tmpvar >>= 1; |
| tmpvar2 = tmpvar & 0xF; |
| |
| if (tmpvar2) |
| { |
| PV_BitstreamFlushBits(stream, (int)(7 + lastOne[tmpvar2])); |
| } |
| else |
| { |
| tmpvar >>= 4; |
| tmpvar2 = tmpvar & 0xF; |
| if (tmpvar2) |
| { |
| PV_BitstreamFlushBits(stream, (int)(3 + lastOne[tmpvar2])); |
| } |
| else |
| { |
| tmpvar >>= 4; |
| tmpvar2 = tmpvar & 0xF; |
| if (lastOne[tmpvar2] < 2) |
| { |
| /* we already have too many consecutive 0's. */ |
| /* Go directly pass the last of the 17 bits. */ |
| PV_BitstreamFlushBits(stream, 19); |
| } |
| else |
| { |
| PV_BitstreamFlushBits(stream, (int)(lastOne[tmpvar2] - 1)); |
| } |
| } |
| } |
| } |
| } |
| } |
| |
| /* ======================================================================== */ |
| /* Function : quickSearchGOBHeader() 0000 0000 0000 0000 1 */ |
| /* Date : 07/06/01 */ |
| /* Purpose : Quick search of GOBHeader (not byte aligned) */ |
| /* In/out : */ |
| /* Return : Integer value indicates type of marker found */ |
| /* Modified : */ |
| /* ======================================================================== */ |
| PV_STATUS quickSearchGOBHeader(BitstreamDecVideo *stream) |
| { |
| PV_STATUS status; |
| int byte0, byte1, byte2, shift, tmpvar; |
| |
| BitstreamByteAlignNoForceStuffing(stream); |
| |
| if (stream->searched_frame_boundary == 0) |
| { |
| PVLocateH263FrameBoundary(stream); |
| } |
| |
| while (TRUE) |
| { |
| status = BitstreamCheckEndBuffer(stream); |
| if (status == PV_END_OF_VOP) return PV_END_OF_VOP; |
| |
| if (stream->incnt < 24) |
| { |
| status = BitstreamFillCache(stream); |
| } |
| |
| |
| byte1 = (stream->curr_word << 8) >> 24; |
| if (byte1 == 0) |
| { |
| byte2 = (stream->curr_word << 16) >> 24; |
| if (byte2) |
| { |
| tmpvar = byte2 >> 4; |
| |
| if (tmpvar) |
| { |
| shift = 9 - firstOne[tmpvar]; |
| } |
| else |
| { |
| shift = 5 - firstOne[byte2]; |
| } |
| byte0 = stream->curr_word >> 24; |
| if ((byte0 & msk[shift]) == 0) |
| { |
| PV_BitstreamFlushBits(stream, 8 - shift); |
| return PV_SUCCESS; |
| } |
| PV_BitstreamFlushBits(stream, 8); /* third_byte is not zero */ |
| } |
| } |
| |
| PV_BitstreamFlushBits(stream, 8); |
| } |
| } |