1/* ------------------------------------------------------------------
2 * Copyright (C) 1998-2009 PacketVideo
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
13 * express or implied.
14 * See the License for the specific language governing permissions
15 * and limitations under the License.
16 * -------------------------------------------------------------------
17 */
18#include "bitstream.h"
19#include "mp4dec_lib.h"
20
21
22#define OSCL_DISABLE_WARNING_CONDITIONAL_IS_CONSTANT
23/* to mask the n least significant bits of an integer */
24static const uint32 msk[33] =
25{
26    0x00000000, 0x00000001, 0x00000003, 0x00000007,
27    0x0000000f, 0x0000001f, 0x0000003f, 0x0000007f,
28    0x000000ff, 0x000001ff, 0x000003ff, 0x000007ff,
29    0x00000fff, 0x00001fff, 0x00003fff, 0x00007fff,
30    0x0000ffff, 0x0001ffff, 0x0003ffff, 0x0007ffff,
31    0x000fffff, 0x001fffff, 0x003fffff, 0x007fffff,
32    0x00ffffff, 0x01ffffff, 0x03ffffff, 0x07ffffff,
33    0x0fffffff, 0x1fffffff, 0x3fffffff, 0x7fffffff,
34    0xffffffff
35};
36
37
38/* ======================================================================== */
39/*  Function : BitstreamFillCache()                                         */
40/*  Date     : 08/29/2000                                                   */
41/*  Purpose  : Read more bitstream data into buffer & the 24-byte cache.    */
42/*              This function is different from BitstreamFillBuffer in      */
43/*              that the buffer is the frame-based buffer provided by       */
44/*              the application.                                            */
45/*  In/out   :                                                              */
46/*  Return   : PV_SUCCESS if successed, PV_FAIL if failed.                  */
47/*  Modified : 4/16/01  : removed return of PV_END_OF_BUFFER                */
48/* ======================================================================== */
49PV_STATUS BitstreamFillCache(BitstreamDecVideo *stream)
50{
51    uint8 *bitstreamBuffer = stream->bitstreamBuffer;
52    uint8 *v;
53    int num_bits, i;
54
55    stream->curr_word |= (stream->next_word >> stream->incnt);   // stream->incnt cannot be 32
56    stream->next_word <<= (31 - stream->incnt);
57    stream->next_word <<= 1;
58    num_bits = stream->incnt_next + stream->incnt;
59    if (num_bits >= 32)
60    {
61        stream->incnt_next -= (32 - stream->incnt);
62        stream->incnt = 32;
63        return PV_SUCCESS;
64    }
65    /* this check can be removed if there is additional extra 4 bytes at the end of the bitstream */
66    v = bitstreamBuffer + stream->read_point;
67
68    if (stream->read_point > stream->data_end_pos - 4)
69    {
70        if (stream->data_end_pos <= stream->read_point)
71        {
72            stream->incnt = num_bits;
73            stream->incnt_next = 0;
74            return PV_SUCCESS;
75        }
76
77        stream->next_word = 0;
78
79        for (i = 0; i < stream->data_end_pos - stream->read_point; i++)
80        {
81            stream->next_word |= (v[i] << ((3 - i) << 3));
82        }
83
84        stream->read_point = stream->data_end_pos;
85        stream->curr_word |= (stream->next_word >> num_bits); // this is safe
86
87        stream->next_word <<= (31 - num_bits);
88        stream->next_word <<= 1;
89        num_bits = i << 3;
90        stream->incnt += stream->incnt_next;
91        stream->incnt_next = num_bits - (32 - stream->incnt);
92        if (stream->incnt_next < 0)
93        {
94            stream->incnt +=  num_bits;
95            stream->incnt_next = 0;
96        }
97        else
98        {
99            stream->incnt = 32;
100        }
101        return PV_SUCCESS;
102    }
103
104    stream->next_word = ((uint32)v[0] << 24) | (v[1] << 16) | (v[2] << 8) | v[3];
105    stream->read_point += 4;
106
107    stream->curr_word |= (stream->next_word >> num_bits); // this is safe
108    stream->next_word <<= (31 - num_bits);
109    stream->next_word <<= 1;
110    stream->incnt_next += stream->incnt;
111    stream->incnt = 32;
112    return PV_SUCCESS;
113}
114
115
116/* ======================================================================== */
117/*  Function : BitstreamReset()                                             */
118/*  Date     : 08/29/2000                                                   */
119/*  Purpose  : Initialize the bitstream buffer for frame-based decoding.    */
120/*  In/out   :                                                              */
121/*  Return   :                                                              */
122/*  Modified :                                                              */
123/* ======================================================================== */
124void BitstreamReset(BitstreamDecVideo *stream, uint8 *buffer, int32 buffer_size)
125{
126    /* set up frame-based bitstream buffer */
127    oscl_memset(stream, 0, sizeof(BitstreamDecVideo));
128    stream->data_end_pos = buffer_size;
129    stream->bitstreamBuffer = buffer;
130}
131
132
133/* ======================================================================== */
134/*  Function : BitstreamOpen()                                              */
135/*  Purpose  : Initialize the bitstream data structure.                     */
136/*  In/out   :                                                              */
137/*  Return   :                                                              */
138/*  Modified :                                                              */
139/* ======================================================================== */
140int BitstreamOpen(BitstreamDecVideo *stream, int)
141{
142    int buffer_size = 0;
143    /* set up linear bitstream buffer */
144//  stream->currentBytePos = 0;
145    stream->data_end_pos = 0;
146
147    stream->incnt = 0;
148    stream->incnt_next = 0;
149    stream->bitcnt = 0;
150    stream->curr_word = stream->next_word = 0;
151    stream->read_point = stream->data_end_pos;
152    return buffer_size;
153}
154
155
156/* ======================================================================== */
157/*  Function : BitstreamClose()                                             */
158/*  Purpose  : Cleanup the bitstream data structure.                        */
159/*  In/out   :                                                              */
160/*  Return   :                                                              */
161/*  Modified :                                                              */
162/* ======================================================================== */
163void BitstreamClose(BitstreamDecVideo *)
164{
165    return;
166}
167
168
169/***********************************************************CommentBegin******
170*
171* -- BitstreamShowBits32HC
172* Shows 32 bits
173***********************************************************CommentEnd********/
174
175PV_STATUS BitstreamShowBits32HC(BitstreamDecVideo *stream, uint32 *code)
176{
177    PV_STATUS status = PV_SUCCESS;
178
179    if (stream->incnt < 32)
180    {
181        /* frame-based decoding */
182        status = BitstreamFillCache(stream);
183    }
184    *code = stream->curr_word;
185    return status;
186}
187
188/***********************************************************CommentBegin******
189*
190* -- BitstreamShowBits32
191* Shows upto and including 31 bits
192***********************************************************CommentEnd********/
193PV_STATUS BitstreamShowBits32(BitstreamDecVideo *stream, int nbits, uint32 *code)
194{
195    PV_STATUS status = PV_SUCCESS;
196
197    if (stream->incnt < nbits)
198    {
199        /* frame-based decoding */
200        status = BitstreamFillCache(stream);
201    }
202    *code = stream->curr_word >> (32 - nbits);
203    return status;
204}
205
206
207#ifndef PV_BS_INLINE
208/*========================================================================= */
209/*  Function:   BitstreamShowBits16()                                       */
210/*  Date:       12/18/2000                                                  */
211/*  Purpose:    To see the next "nbits"(nbits<=16) bitstream bits           */
212/*              without advancing the read pointer                          */
213/*                                                                          */
214/* =========================================================================*/
215PV_STATUS BitstreamShowBits16(BitstreamDecVideo *stream, int nbits, uint *code)
216{
217    PV_STATUS status = PV_SUCCESS;
218
219
220    if (stream->incnt < nbits)
221    {
222        /* frame-based decoding */
223        status = BitstreamFillCache(stream);
224    }
225
226    *code = stream->curr_word >> (32 - nbits);
227    return status;
228}
229
230
231/*========================================================================= */
232/*  Function:   BitstreamShow15Bits()                                       */
233/*  Date:       01/23/2001                                                  */
234/*  Purpose:    To see the next 15 bitstream bits                           */
235/*              without advancing the read pointer                          */
236/*                                                                          */
237/* =========================================================================*/
238PV_STATUS BitstreamShow15Bits(BitstreamDecVideo *stream, uint *code)
239{
240    PV_STATUS status = PV_SUCCESS;
241
242    if (stream->incnt < 15)
243    {
244        /* frame-based decoding */
245        status = BitstreamFillCache(stream);
246    }
247    *code = stream->curr_word >> 17;
248    return status;
249}
250/*========================================================================= */
251/*  Function: BitstreamShow13Bits                                           */
252/*  Date:       050923                                              */
253/*  Purpose:    Faciliate and speed up showing 13 bit from bitstream        */
254/*              used in VlcTCOEFF decoding                                  */
255/*  Modified:                            */
256/* =========================================================================*/
257PV_STATUS BitstreamShow13Bits(BitstreamDecVideo *stream, uint *code)
258{
259    PV_STATUS status = PV_SUCCESS;
260
261    if (stream->incnt < 13)
262    {
263        /* frame-based decoding */
264        status = BitstreamFillCache(stream);
265    }
266    *code = stream->curr_word >> 19;
267    return status;
268}
269
270uint BitstreamReadBits16_INLINE(BitstreamDecVideo *stream, int nbits)
271{
272    uint code;
273    PV_STATUS status;
274
275    if (stream->incnt < nbits)
276    {
277        /* frame-based decoding */
278        status = BitstreamFillCache(stream);
279    }
280    code = stream->curr_word >> (32 - nbits);
281    PV_BitstreamFlushBits(stream, nbits);
282    return code;
283}
284
285
286uint BitstreamRead1Bits_INLINE(BitstreamDecVideo *stream)
287{
288    PV_STATUS status = PV_SUCCESS;
289    uint    code;
290
291
292    if (stream->incnt < 1)
293    {
294        /* frame-based decoding */
295        status = BitstreamFillCache(stream);
296    }
297    code = stream->curr_word >> 31;
298    PV_BitstreamFlushBits(stream, 1);
299
300    return code;
301}
302
303#endif
304
305/* ======================================================================== */
306/*  Function : BitstreamReadBits16()                                        */
307/*  Purpose  : Read bits (nbits <=16) from bitstream buffer.                */
308/*  In/out   :                                                              */
309/*  Return   :                                                              */
310/* ======================================================================== */
311uint BitstreamReadBits16(BitstreamDecVideo *stream, int nbits)
312{
313    uint code;
314
315    if (stream->incnt < nbits)
316    {
317        /* frame-based decoding */
318        BitstreamFillCache(stream);
319    }
320    code = stream->curr_word >> (32 - nbits);
321    PV_BitstreamFlushBits(stream, nbits);
322    return code;
323}
324
325/* ======================================================================== */
326/*  Function : BitstreamRead1Bits()                                         */
327/*  Date     : 10/23/2000                                                   */
328/*  Purpose  : Faciliate and speed up reading 1 bit from bitstream.         */
329/*  In/out   :                                                              */
330/*  Return   :                                                              */
331/* ======================================================================== */
332
333uint BitstreamRead1Bits(BitstreamDecVideo *stream)
334{
335    uint    code;
336
337    if (stream->incnt < 1)
338    {
339        /* frame-based decoding */
340        BitstreamFillCache(stream);
341    }
342    code = stream->curr_word >> 31;
343    PV_BitstreamFlushBits(stream, 1);
344
345    return code;
346}
347
348/* ======================================================================== */
349/*  Function : PV_BitstreamFlushBitsCheck()                                 */
350/*  Purpose  : Flush nbits bits from bitstream buffer. Check for cache      */
351/*  In/out   :                                                              */
352/*  Return   :                                                              */
353/*  Modified :                                                              */
354/* ======================================================================== */
355PV_STATUS PV_BitstreamFlushBitsCheck(BitstreamDecVideo *stream, int nbits)
356{
357    PV_STATUS status = PV_SUCCESS;
358
359    stream->bitcnt += nbits;
360    stream->incnt -= nbits;
361    if (stream->incnt < 0)
362    {
363        /* frame-based decoding */
364        status = BitstreamFillCache(stream);
365
366        if (stream->incnt < 0)
367        {
368            stream->bitcnt += stream->incnt;
369            stream->incnt = 0;
370        }
371    }
372    stream->curr_word <<= nbits;
373    return status;
374}
375
376/* ======================================================================== */
377/*  Function : BitstreamReadBits32()                                        */
378/*  Purpose  : Read bits from bitstream buffer.                             */
379/*  In/out   :                                                              */
380/*  Return   :                                                              */
381/* ======================================================================== */
382uint32 BitstreamReadBits32(BitstreamDecVideo *stream, int nbits)
383{
384    uint32 code;
385
386    if (stream->incnt < nbits)
387    {
388        /* frame-based decoding */
389        BitstreamFillCache(stream);
390    }
391    code = stream->curr_word >> (32 - nbits);
392    PV_BitstreamFlushBits(stream, nbits);
393    return code;
394}
395
396uint32 BitstreamReadBits32HC(BitstreamDecVideo *stream)
397{
398    uint32 code;
399
400    BitstreamShowBits32HC(stream, &code);
401    stream->bitcnt += 32;
402    stream->incnt = 0;
403    stream->curr_word = 0;
404    return code;
405}
406
407/* ======================================================================== */
408/*  Function : BitstreamCheckEndBuffer()                                    */
409/*  Date     : 03/30/2001                                                   */
410/*  Purpose  : Check to see if we are at the end of buffer                  */
411/*  In/out   :                                                              */
412/*  Return   :                                                              */
413/*  Modified :                                                              */
414/* ======================================================================== */
415PV_STATUS BitstreamCheckEndBuffer(BitstreamDecVideo *stream)
416{
417    if (stream->read_point >= stream->data_end_pos && stream->incnt <= 0) return PV_END_OF_VOP;
418    return PV_SUCCESS;
419}
420
421
422PV_STATUS PV_BitstreamShowBitsByteAlign(BitstreamDecVideo *stream, int nbits, uint32 *code)
423{
424    PV_STATUS status = PV_SUCCESS;
425
426    int n_stuffed;
427
428    n_stuffed = 8 - (stream->bitcnt & 0x7); /*  07/05/01 */
429
430    if (stream->incnt < (nbits + n_stuffed))
431    {
432        /* frame-based decoding */
433        status = BitstreamFillCache(stream);
434    }
435
436    *code = (stream->curr_word << n_stuffed) >> (32 - nbits);
437    return status;
438}
439
440#ifdef PV_ANNEX_IJKT_SUPPORT
441PV_STATUS PV_BitstreamShowBitsByteAlignNoForceStuffing(BitstreamDecVideo *stream, int nbits, uint32 *code)
442{
443    PV_STATUS status = PV_SUCCESS;
444
445    int n_stuffed;
446
447    n_stuffed = (8 - (stream->bitcnt & 0x7)) & 7;
448
449    if (stream->incnt < (nbits + n_stuffed))
450    {
451        /* frame-based decoding */
452        status = BitstreamFillCache(stream);
453    }
454
455    *code = (stream->curr_word << n_stuffed) >> (32 - nbits);
456    return status;
457}
458#endif
459
460PV_STATUS PV_BitstreamByteAlign(BitstreamDecVideo *stream)
461{
462    PV_STATUS status = PV_SUCCESS;
463    int n_stuffed;
464
465    n_stuffed = 8 - (stream->bitcnt & 0x7); /*  07/05/01 */
466
467    /* We have to make sure we have enough bits in the cache.   08/15/2000 */
468    if (stream->incnt < n_stuffed)
469    {
470        /* frame-based decoding */
471        status = BitstreamFillCache(stream);
472    }
473
474
475    stream->bitcnt += n_stuffed;
476    stream->incnt -= n_stuffed;
477    stream->curr_word <<= n_stuffed;
478    if (stream->incnt < 0)
479    {
480        stream->bitcnt += stream->incnt;
481        stream->incnt = 0;
482    }
483    return status;
484}
485
486
487PV_STATUS BitstreamByteAlignNoForceStuffing(BitstreamDecVideo *stream)
488{
489    uint n_stuffed;
490
491    n_stuffed = (8 - (stream->bitcnt & 0x7)) & 0x7; /*  07/05/01 */
492
493    stream->bitcnt += n_stuffed;
494    stream->incnt -= n_stuffed;
495
496    if (stream->incnt < 0)
497    {
498        stream->bitcnt += stream->incnt;
499        stream->incnt = 0;
500    }
501    stream->curr_word <<= n_stuffed;
502    return PV_SUCCESS;
503}
504
505
506/* ==================================================================== */
507/*  Function : getPointer()                                             */
508/*  Date     : 10/98                                                    */
509/*  Purpose  : get current position of file pointer                     */
510/*  In/out   :                                                          */
511/*  Return   :                                                          */
512/* ==================================================================== */
513int32 getPointer(BitstreamDecVideo *stream)
514{
515    return stream->bitcnt;
516}
517
518
519
520
521/* ====================================================================== /
522Function : movePointerTo()
523Date     : 05/14/2004
524Purpose  : move bitstream pointer to a desired position
525In/out   :
526Return   :
527Modified :
528/ ====================================================================== */
529PV_STATUS movePointerTo(BitstreamDecVideo *stream, int32 pos)
530{
531    int32 byte_pos;
532    if (pos < 0)
533    {
534        pos = 0;
535    }
536
537    byte_pos = pos >> 3;
538
539    if (byte_pos > stream->data_end_pos)
540    {
541        byte_pos = stream->data_end_pos;
542    }
543
544    stream->read_point = byte_pos & -4;
545    stream->bitcnt = stream->read_point << 3;;
546    stream->curr_word = 0;
547    stream->next_word = 0;
548    stream->incnt = 0;
549    stream->incnt_next = 0;
550    BitstreamFillCache(stream);
551    PV_BitstreamFlushBits(stream, ((pos & 0x7) + ((byte_pos & 0x3) << 3)));
552    return PV_SUCCESS;
553}
554
555
556/* ======================================================================== */
557/*  Function : validStuffing()                                              */
558/*  Date     : 04/11/2000                                                   */
559/*  Purpose  : Check whether we have valid stuffing at current position.    */
560/*  In/out   :                                                              */
561/*  Return   : PV_TRUE if successed, PV_FALSE if failed.                    */
562/*  Modified : 12/18/2000 : changed the pattern type to uint    */
563/*             04/01/2001 : removed PV_END_OF_BUFFER                        */
564/* ======================================================================== */
565Bool validStuffing(BitstreamDecVideo *stream)
566{
567    uint n_stuffed;
568    uint pattern;
569
570
571    n_stuffed = 8 - (stream->bitcnt & 0x7);
572    BitstreamShowBits16(stream, n_stuffed, &pattern);
573    if (pattern == msk[n_stuffed-1]) return PV_TRUE;
574    return PV_FALSE;
575}
576#ifdef PV_ANNEX_IJKT_SUPPORT
577Bool validStuffing_h263(BitstreamDecVideo *stream)
578{
579    uint n_stuffed;
580    uint pattern;
581
582
583    n_stuffed = (8 - (stream->bitcnt & 0x7)) & 7;  //  stream->incnt % 8
584    if (n_stuffed == 0)
585    {
586        return PV_TRUE;
587    }
588    BitstreamShowBits16(stream, n_stuffed, &pattern);
589    if (pattern == 0) return PV_TRUE;
590    return PV_FALSE;
591}
592#endif
593
594
595/* ======================================================================== */
596/*  Function : PVSearchNextH263Frame()                                      */
597/*  Date     : 04/08/2005                                                   */
598/*  Purpose  : search for 0x00 0x00 0x80                                    */
599/*  In/out   :                                                              */
600/*  Return   : PV_SUCCESS if succeeded  or PV_END_OF_VOP if failed          */
601/*  Modified :                                                              */
602/* ======================================================================== */
603PV_STATUS PVSearchNextH263Frame(BitstreamDecVideo *stream)
604{
605    PV_STATUS status = PV_SUCCESS;
606    uint8 *ptr;
607    int32 i;
608    int32 initial_byte_aligned_position = (stream->bitcnt + 7) >> 3;
609
610    ptr = stream->bitstreamBuffer + initial_byte_aligned_position;
611
612    i = PVLocateH263FrameHeader(ptr, stream->data_end_pos - initial_byte_aligned_position);
613    if (stream->data_end_pos <= initial_byte_aligned_position + i)
614    {
615        status = PV_END_OF_VOP;
616    }
617    (void)movePointerTo(stream, ((i + initial_byte_aligned_position) << 3)); /* ptr + i */
618    return status;
619}
620
621
622/* ======================================================================== */
623/*  Function : PVSearchNextM4VFrame()                                       */
624/*  Date     : 04/08/2005                                                   */
625/*  Purpose  : search for 0x00 0x00 0x01 and move the pointer to the        */
626/*  beginning of the start code                                             */
627/*  In/out   :                                                              */
628/*  Return   : PV_SUCCESS if succeeded  or PV_END_OF_VOP if failed          */
629/*  Modified :                                                              */
630/* ======================================================================== */
631
632PV_STATUS PVSearchNextM4VFrame(BitstreamDecVideo *stream)
633{
634    PV_STATUS status = PV_SUCCESS;
635    uint8 *ptr;
636    int32 i;
637    int32 initial_byte_aligned_position = (stream->bitcnt + 7) >> 3;
638
639    ptr = stream->bitstreamBuffer + initial_byte_aligned_position;
640
641    i = PVLocateFrameHeader(ptr, stream->data_end_pos - initial_byte_aligned_position);
642    if (stream->data_end_pos <= initial_byte_aligned_position + i)
643    {
644        status = PV_END_OF_VOP;
645    }
646    (void)movePointerTo(stream, ((i + initial_byte_aligned_position) << 3)); /* ptr + i */
647    return status;
648}
649
650
651
652void PVLocateM4VFrameBoundary(BitstreamDecVideo *stream)
653{
654    uint8 *ptr;
655    int32 byte_pos = (stream->bitcnt >> 3);
656
657    stream->searched_frame_boundary = 1;
658    ptr = stream->bitstreamBuffer + byte_pos;
659
660    stream->data_end_pos = PVLocateFrameHeader(ptr, (int32)stream->data_end_pos - byte_pos) + byte_pos;
661}
662
663void PVLocateH263FrameBoundary(BitstreamDecVideo *stream)
664{
665    uint8 *ptr;
666    int32 byte_pos = (stream->bitcnt >> 3);
667
668    stream->searched_frame_boundary = 1;
669    ptr = stream->bitstreamBuffer + byte_pos;
670
671    stream->data_end_pos = PVLocateH263FrameHeader(ptr, (int32)stream->data_end_pos - byte_pos) + byte_pos;
672}
673
674/* ======================================================================== */
675/*  Function : quickSearchVideoPacketHeader()               */
676/*  Date     : 05/08/2000                           */
677/*  Purpose  : Quick search for the next video packet header        */
678/*  In/out   :                              */
679/*  Return   : PV_TRUE if successed, PV_FALSE if failed.            */
680/*  Modified :                              */
681/* ======================================================================== */
682PV_STATUS quickSearchVideoPacketHeader(BitstreamDecVideo *stream, int marker_length)
683{
684    PV_STATUS status = PV_SUCCESS;
685    uint32 tmpvar;
686
687
688    if (stream->searched_frame_boundary == 0)
689    {
690        PVLocateM4VFrameBoundary(stream);
691    }
692
693    do
694    {
695        status = BitstreamCheckEndBuffer(stream);
696        if (status == PV_END_OF_VOP) break;
697        PV_BitstreamShowBitsByteAlign(stream, marker_length, &tmpvar);
698        if (tmpvar == RESYNC_MARKER) break;
699        PV_BitstreamFlushBits(stream, 8);
700    }
701    while (status == PV_SUCCESS);
702
703    return status;
704}
705#ifdef PV_ANNEX_IJKT_SUPPORT
706PV_STATUS quickSearchH263SliceHeader(BitstreamDecVideo *stream)
707{
708    PV_STATUS status = PV_SUCCESS;
709    uint32 tmpvar;
710
711
712    if (stream->searched_frame_boundary == 0)
713    {
714        PVLocateH263FrameBoundary(stream);
715    }
716
717    do
718    {
719        status = BitstreamCheckEndBuffer(stream);
720        if (status == PV_END_OF_VOP) break;
721        PV_BitstreamShowBitsByteAlignNoForceStuffing(stream, 17, &tmpvar);
722        if (tmpvar == RESYNC_MARKER) break;
723        PV_BitstreamFlushBits(stream, 8);
724    }
725    while (status == PV_SUCCESS);
726
727    return status;
728}
729#endif
730/* ======================================================================== */
731/*          The following functions are for Error Concealment.              */
732/* ======================================================================== */
733
734/****************************************************/
735//  01/22/99 Quick search of Resync Marker
736// (actually the first part of it, i.e. 16 0's and a 1.
737
738/* We are not using the fastest algorithm possible. What this function does is
739to locate 11 consecutive 0's and then check if the 5 bits before them and
740the 1 bit after them are all 1's.
741*/
742
743//  Table used for quick search of markers. Gives the last `1' in
744// 4 bits. The MSB is bit #1, the LSB is bit #4.
745const int lastOne[] =
746{
747    0,  4,  3,  4,  2,  4,  3,  4,
748    1,  4,  3,  4,  2,  4,  3,  4
749};
750
751//  Table used for quick search of markers. Gives the last `0' in
752// 4 bits. The MSB is bit #1, the LSB is bit #4.
753/*const int lastZero[]=
754{
755    4,  3,  4,  2,  4,  3,  4,  1,
756        4,  3,  4,  2,  4,  3,  4,  0
757};
758*/
759//  Table used for quick search of markers. Gives the first `0' in
760// 4 bits. The MSB is bit #1, the LSB is bit #4.
761const int firstZero[] =
762{
763    1, 1, 1, 1, 1, 1, 1, 1,
764    2, 2, 2, 2, 3, 3, 4, 0
765};
766
767//  Table used for quick search of markers. Gives the first `1' in
768// 4 bits. The MSB is bit #1, the LSB is bit #4.
769const int firstOne[] =
770{
771    0, 4, 3, 3, 2, 2, 2, 2,
772    1, 1, 1, 1, 1, 1, 1, 1
773};
774
775
776/* ======================================================================== */
777/*  Function : quickSearchMarkers()                                         */
778/*  Date     : 01/25/99                                                     */
779/*  Purpose  : Quick search for Motion marker                               */
780/*  In/out   :                                                              */
781/*  Return   : Boolean true of false                                        */
782/*  Modified : 12/18/2000 : 32-bit version                    */
783/* ======================================================================== */
784PV_STATUS quickSearchMotionMarker(BitstreamDecVideo *stream)
785// MM: (11111000000000001)
786{
787    PV_STATUS status;
788    uint32 tmpvar, tmpvar2;
789
790    if (stream->searched_frame_boundary == 0)
791    {
792        PVLocateM4VFrameBoundary(stream);
793    }
794
795    while (TRUE)
796    {
797        status = BitstreamCheckEndBuffer(stream);
798        if (status == PV_END_OF_VOP) return PV_END_OF_VOP;
799
800        BitstreamShowBits32(stream, 17, &tmpvar);
801        if (!tmpvar) return PV_FAIL;
802
803        if (tmpvar & 1) //  Check if the 17th bit from the curr bit pos is a '1'
804        {
805            if (tmpvar == MOTION_MARKER_COMB)
806            {
807                return PV_SUCCESS; //  Found
808            }
809            else
810            {
811                tmpvar >>= 1;
812                tmpvar &= 0xF;
813                PV_BitstreamFlushBits(stream, (int)(12 + firstZero[tmpvar]));
814            }
815        }
816        else
817        {
818            //  01/25/99 Get the first 16 bits
819            tmpvar >>= 1;
820            tmpvar2 = tmpvar & 0xF;
821
822            //  01/26/99 Check bits #13 ~ #16
823            if (tmpvar2)
824            {
825                PV_BitstreamFlushBits(stream, (int)(7 + lastOne[tmpvar2]));
826            }
827            else
828            {
829                tmpvar >>= 4;
830                tmpvar2 = tmpvar & 0xF;
831
832                //  01/26/99 Check bits #9 ~ #12
833                if (tmpvar2)
834                {
835                    PV_BitstreamFlushBits(stream, (int)(3 + lastOne[tmpvar2]));
836                }
837                else
838                {
839                    tmpvar >>= 4;
840                    tmpvar2 = tmpvar & 0xF;
841
842                    //  01/26/99 Check bits #5 ~ #8
843                    // We don't need to check further
844                    // for the first 5 bits should be all 1's
845                    if (lastOne[tmpvar2] < 2)
846                    {
847                        /* we already have too many consecutive 0's. */
848                        /* Go directly pass the last of the 17 bits. */
849                        PV_BitstreamFlushBits(stream, 17);
850                    }
851                    else
852                    {
853                        PV_BitstreamFlushBits(stream, (int)(lastOne[tmpvar2] - 1));
854                    }
855                }
856            }
857        }
858
859    }
860}
861
862/* ======================================================================== */
863/*  Function : quickSearchDCM()                                             */
864/*  Date     : 01/22/99                                                     */
865/*  Purpose  : Quick search for DC Marker                                   */
866/*              We are not using the fastest algorithm possible.  What this */
867/*              function does is to locate 11 consecutive 0's and then      */
868/*              check if the 7 bits before them and the 1 bit after them    */
869/*              are correct.  (actually the first part of it, i.e. 16 0's   */
870/*              and a 1.                                                    */
871/*  In/out   :                                                              */
872/*  Return   : Boolean true of false                                        */
873/*  Modified : 12/18/2000 : 32-bit version                    */
874/* ======================================================================== */
875PV_STATUS quickSearchDCM(BitstreamDecVideo *stream)
876// DCM: (110 1011 0000 0000 0001)
877{
878    PV_STATUS status;
879    uint32 tmpvar, tmpvar2;
880
881    if (stream->searched_frame_boundary == 0)
882    {
883        PVLocateM4VFrameBoundary(stream);
884    }
885
886    while (TRUE)
887    {
888        status = BitstreamCheckEndBuffer(stream);
889        if (status == PV_END_OF_VOP) return PV_END_OF_VOP;
890        BitstreamShowBits32(stream, 19, &tmpvar);
891
892        if (tmpvar & 1) //  Check if the 17th bit from the curr bit pos is a '1'
893        {
894            if (tmpvar == DC_MARKER)
895            {
896                return PV_SUCCESS; //  Found
897            }
898            else
899            {
900                //  01/25/99 We treat the last of the 19 bits as its 7th bit (which is
901                // also a `1'
902                PV_BitstreamFlushBits(stream, 12);
903            }
904        }
905        else
906        {
907            tmpvar >>= 1;
908            tmpvar2 = tmpvar & 0xF;
909
910            if (tmpvar2)
911            {
912                PV_BitstreamFlushBits(stream, (int)(7 + lastOne[tmpvar2]));
913            }
914            else
915            {
916                tmpvar >>= 4;
917                tmpvar2 = tmpvar & 0xF;
918                if (tmpvar2)
919                {
920                    PV_BitstreamFlushBits(stream, (int)(3 + lastOne[tmpvar2]));
921                }
922                else
923                {
924                    tmpvar >>= 4;
925                    tmpvar2 = tmpvar & 0xF;
926                    if (lastOne[tmpvar2] < 2)
927                    {
928                        /* we already have too many consecutive 0's. */
929                        /* Go directly pass the last of the 17 bits. */
930                        PV_BitstreamFlushBits(stream, 19);
931                    }
932                    else
933                    {
934                        PV_BitstreamFlushBits(stream, (int)(lastOne[tmpvar2] - 1));
935                    }
936                }
937            }
938        }
939    }
940}
941
942/* ======================================================================== */
943/*  Function : quickSearchGOBHeader()   0000 0000 0000 0000 1               */
944/*  Date     : 07/06/01                                                     */
945/*  Purpose  : Quick search of GOBHeader (not byte aligned)                 */
946/*  In/out   :                                                              */
947/*  Return   : Integer value indicates type of marker found                 */
948/*  Modified :                                                              */
949/* ======================================================================== */
950PV_STATUS quickSearchGOBHeader(BitstreamDecVideo *stream)
951{
952    PV_STATUS status;
953    int byte0, byte1, byte2, shift, tmpvar;
954
955    BitstreamByteAlignNoForceStuffing(stream);
956
957    if (stream->searched_frame_boundary == 0)
958    {
959        PVLocateH263FrameBoundary(stream);
960    }
961
962    while (TRUE)
963    {
964        status = BitstreamCheckEndBuffer(stream);
965        if (status == PV_END_OF_VOP) return PV_END_OF_VOP;
966
967        if (stream->incnt < 24)
968        {
969            status = BitstreamFillCache(stream);
970        }
971
972
973        byte1 = (stream->curr_word << 8) >> 24;
974        if (byte1 == 0)
975        {
976            byte2 = (stream->curr_word << 16) >> 24;
977            if (byte2)
978            {
979                tmpvar = byte2 >> 4;
980
981                if (tmpvar)
982                {
983                    shift = 9 - firstOne[tmpvar];
984                }
985                else
986                {
987                    shift = 5 - firstOne[byte2];
988                }
989                byte0 = stream->curr_word >> 24;
990                if ((byte0 & msk[shift]) == 0)
991                {
992                    PV_BitstreamFlushBits(stream, 8 - shift);
993                    return PV_SUCCESS;
994                }
995                PV_BitstreamFlushBits(stream, 8);    /* third_byte is not zero */
996            }
997        }
998
999        PV_BitstreamFlushBits(stream, 8);
1000    }
1001}
1002