• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 */
24 static 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 /* ======================================================================== */
BitstreamFillCache(BitstreamDecVideo * stream)49 PV_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 /* ======================================================================== */
BitstreamReset(BitstreamDecVideo * stream,uint8 * buffer,int32 buffer_size)124 void 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 /* ======================================================================== */
BitstreamOpen(BitstreamDecVideo * stream,int)140 int 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 /* ======================================================================== */
BitstreamClose(BitstreamDecVideo *)163 void BitstreamClose(BitstreamDecVideo *)
164 {
165     return;
166 }
167 
168 
169 /***********************************************************CommentBegin******
170 *
171 * -- BitstreamShowBits32HC
172 * Shows 32 bits
173 ***********************************************************CommentEnd********/
174 
BitstreamShowBits32HC(BitstreamDecVideo * stream,uint32 * code)175 PV_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********/
BitstreamShowBits32(BitstreamDecVideo * stream,int nbits,uint32 * code)193 PV_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 /* =========================================================================*/
BitstreamShowBits16(BitstreamDecVideo * stream,int nbits,uint * code)215 PV_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 /* =========================================================================*/
BitstreamShow15Bits(BitstreamDecVideo * stream,uint * code)238 PV_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 /* =========================================================================*/
BitstreamShow13Bits(BitstreamDecVideo * stream,uint * code)257 PV_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 
BitstreamReadBits16_INLINE(BitstreamDecVideo * stream,int nbits)270 uint 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 
BitstreamRead1Bits_INLINE(BitstreamDecVideo * stream)286 uint 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 /* ======================================================================== */
BitstreamReadBits16(BitstreamDecVideo * stream,int nbits)311 uint 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 
BitstreamRead1Bits(BitstreamDecVideo * stream)333 uint 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 /* ======================================================================== */
PV_BitstreamFlushBitsCheck(BitstreamDecVideo * stream,int nbits)355 PV_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 /* ======================================================================== */
BitstreamReadBits32(BitstreamDecVideo * stream,int nbits)382 uint32 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 
BitstreamReadBits32HC(BitstreamDecVideo * stream)396 uint32 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 /* ======================================================================== */
BitstreamCheckEndBuffer(BitstreamDecVideo * stream)415 PV_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 
PV_BitstreamShowBitsByteAlign(BitstreamDecVideo * stream,int nbits,uint32 * code)422 PV_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
PV_BitstreamShowBitsByteAlignNoForceStuffing(BitstreamDecVideo * stream,int nbits,uint32 * code)441 PV_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 
PV_BitstreamByteAlign(BitstreamDecVideo * stream)460 PV_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 
BitstreamByteAlignNoForceStuffing(BitstreamDecVideo * stream)487 PV_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 /* ==================================================================== */
getPointer(BitstreamDecVideo * stream)513 int32 getPointer(BitstreamDecVideo *stream)
514 {
515     return stream->bitcnt;
516 }
517 
518 
519 
520 
521 /* ====================================================================== /
522 Function : movePointerTo()
523 Date     : 05/14/2004
524 Purpose  : move bitstream pointer to a desired position
525 In/out   :
526 Return   :
527 Modified :
528 / ====================================================================== */
movePointerTo(BitstreamDecVideo * stream,int32 pos)529 PV_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 /* ======================================================================== */
validStuffing(BitstreamDecVideo * stream)565 Bool 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
validStuffing_h263(BitstreamDecVideo * stream)577 Bool 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 /* ======================================================================== */
PVSearchNextH263Frame(BitstreamDecVideo * stream)603 PV_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 
PVSearchNextM4VFrame(BitstreamDecVideo * stream)632 PV_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 
PVLocateM4VFrameBoundary(BitstreamDecVideo * stream)652 PV_STATUS PVLocateM4VFrameBoundary(BitstreamDecVideo *stream)
653 {
654     PV_STATUS status = BitstreamCheckEndBuffer(stream);
655     if (status == PV_END_OF_VOP) return status;
656 
657     uint8 *ptr;
658     int32 byte_pos = (stream->bitcnt >> 3);
659 
660     stream->searched_frame_boundary = 1;
661     ptr = stream->bitstreamBuffer + byte_pos;
662 
663     stream->data_end_pos = PVLocateFrameHeader(ptr, (int32)stream->data_end_pos - byte_pos) + byte_pos;
664     return PV_SUCCESS;
665 }
666 
PVLocateH263FrameBoundary(BitstreamDecVideo * stream)667 PV_STATUS PVLocateH263FrameBoundary(BitstreamDecVideo *stream)
668 {
669     PV_STATUS status = BitstreamCheckEndBuffer(stream);
670     if (status == PV_END_OF_VOP) return status;
671 
672     uint8 *ptr;
673     int32 byte_pos = (stream->bitcnt >> 3);
674 
675     stream->searched_frame_boundary = 1;
676     ptr = stream->bitstreamBuffer + byte_pos;
677 
678     stream->data_end_pos = PVLocateH263FrameHeader(ptr, (int32)stream->data_end_pos - byte_pos) + byte_pos;
679     return PV_SUCCESS;
680 }
681 
682 /* ======================================================================== */
683 /*  Function : quickSearchVideoPacketHeader()               */
684 /*  Date     : 05/08/2000                           */
685 /*  Purpose  : Quick search for the next video packet header        */
686 /*  In/out   :                              */
687 /*  Return   : PV_TRUE if successed, PV_FALSE if failed.            */
688 /*  Modified :                              */
689 /* ======================================================================== */
quickSearchVideoPacketHeader(BitstreamDecVideo * stream,int marker_length)690 PV_STATUS quickSearchVideoPacketHeader(BitstreamDecVideo *stream, int marker_length)
691 {
692     PV_STATUS status = PV_SUCCESS;
693     uint32 tmpvar;
694 
695 
696     if (stream->searched_frame_boundary == 0)
697     {
698         status = PVLocateM4VFrameBoundary(stream);
699         if (status != PV_SUCCESS) return status;
700     }
701 
702     do
703     {
704         status = BitstreamCheckEndBuffer(stream);
705         if (status == PV_END_OF_VOP) break;
706         PV_BitstreamShowBitsByteAlign(stream, marker_length, &tmpvar);
707         if (tmpvar == RESYNC_MARKER) break;
708         PV_BitstreamFlushBits(stream, 8);
709     }
710     while (status == PV_SUCCESS);
711 
712     return status;
713 }
714 #ifdef PV_ANNEX_IJKT_SUPPORT
quickSearchH263SliceHeader(BitstreamDecVideo * stream)715 PV_STATUS quickSearchH263SliceHeader(BitstreamDecVideo *stream)
716 {
717     PV_STATUS status = PV_SUCCESS;
718     uint32 tmpvar;
719 
720 
721     if (stream->searched_frame_boundary == 0)
722     {
723         status = PVLocateH263FrameBoundary(stream);
724         if (status != PV_SUCCESS) return status;
725     }
726 
727     do
728     {
729         status = BitstreamCheckEndBuffer(stream);
730         if (status == PV_END_OF_VOP) break;
731         PV_BitstreamShowBitsByteAlignNoForceStuffing(stream, 17, &tmpvar);
732         if (tmpvar == RESYNC_MARKER) break;
733         PV_BitstreamFlushBits(stream, 8);
734     }
735     while (status == PV_SUCCESS);
736 
737     return status;
738 }
739 #endif
740 /* ======================================================================== */
741 /*          The following functions are for Error Concealment.              */
742 /* ======================================================================== */
743 
744 /****************************************************/
745 //  01/22/99 Quick search of Resync Marker
746 // (actually the first part of it, i.e. 16 0's and a 1.
747 
748 /* We are not using the fastest algorithm possible. What this function does is
749 to locate 11 consecutive 0's and then check if the 5 bits before them and
750 the 1 bit after them are all 1's.
751 */
752 
753 //  Table used for quick search of markers. Gives the last `1' in
754 // 4 bits. The MSB is bit #1, the LSB is bit #4.
755 const int lastOne[] =
756 {
757     0,  4,  3,  4,  2,  4,  3,  4,
758     1,  4,  3,  4,  2,  4,  3,  4
759 };
760 
761 //  Table used for quick search of markers. Gives the last `0' in
762 // 4 bits. The MSB is bit #1, the LSB is bit #4.
763 /*const int lastZero[]=
764 {
765     4,  3,  4,  2,  4,  3,  4,  1,
766         4,  3,  4,  2,  4,  3,  4,  0
767 };
768 */
769 //  Table used for quick search of markers. Gives the first `0' in
770 // 4 bits. The MSB is bit #1, the LSB is bit #4.
771 const int firstZero[] =
772 {
773     1, 1, 1, 1, 1, 1, 1, 1,
774     2, 2, 2, 2, 3, 3, 4, 0
775 };
776 
777 //  Table used for quick search of markers. Gives the first `1' in
778 // 4 bits. The MSB is bit #1, the LSB is bit #4.
779 const int firstOne[] =
780 {
781     0, 4, 3, 3, 2, 2, 2, 2,
782     1, 1, 1, 1, 1, 1, 1, 1
783 };
784 
785 
786 /* ======================================================================== */
787 /*  Function : quickSearchMarkers()                                         */
788 /*  Date     : 01/25/99                                                     */
789 /*  Purpose  : Quick search for Motion marker                               */
790 /*  In/out   :                                                              */
791 /*  Return   : Boolean true of false                                        */
792 /*  Modified : 12/18/2000 : 32-bit version                    */
793 /* ======================================================================== */
quickSearchMotionMarker(BitstreamDecVideo * stream)794 PV_STATUS quickSearchMotionMarker(BitstreamDecVideo *stream)
795 // MM: (11111000000000001)
796 {
797     PV_STATUS status;
798     uint32 tmpvar, tmpvar2;
799 
800     if (stream->searched_frame_boundary == 0)
801     {
802         status = PVLocateM4VFrameBoundary(stream);
803         if (status != PV_SUCCESS) return status;
804     }
805 
806     while (TRUE)
807     {
808         status = BitstreamCheckEndBuffer(stream);
809         if (status == PV_END_OF_VOP) return PV_END_OF_VOP;
810 
811         BitstreamShowBits32(stream, 17, &tmpvar);
812         if (!tmpvar) return PV_FAIL;
813 
814         if (tmpvar & 1) //  Check if the 17th bit from the curr bit pos is a '1'
815         {
816             if (tmpvar == MOTION_MARKER_COMB)
817             {
818                 return PV_SUCCESS; //  Found
819             }
820             else
821             {
822                 tmpvar >>= 1;
823                 tmpvar &= 0xF;
824                 PV_BitstreamFlushBits(stream, (int)(12 + firstZero[tmpvar]));
825             }
826         }
827         else
828         {
829             //  01/25/99 Get the first 16 bits
830             tmpvar >>= 1;
831             tmpvar2 = tmpvar & 0xF;
832 
833             //  01/26/99 Check bits #13 ~ #16
834             if (tmpvar2)
835             {
836                 PV_BitstreamFlushBits(stream, (int)(7 + lastOne[tmpvar2]));
837             }
838             else
839             {
840                 tmpvar >>= 4;
841                 tmpvar2 = tmpvar & 0xF;
842 
843                 //  01/26/99 Check bits #9 ~ #12
844                 if (tmpvar2)
845                 {
846                     PV_BitstreamFlushBits(stream, (int)(3 + lastOne[tmpvar2]));
847                 }
848                 else
849                 {
850                     tmpvar >>= 4;
851                     tmpvar2 = tmpvar & 0xF;
852 
853                     //  01/26/99 Check bits #5 ~ #8
854                     // We don't need to check further
855                     // for the first 5 bits should be all 1's
856                     if (lastOne[tmpvar2] < 2)
857                     {
858                         /* we already have too many consecutive 0's. */
859                         /* Go directly pass the last of the 17 bits. */
860                         PV_BitstreamFlushBits(stream, 17);
861                     }
862                     else
863                     {
864                         PV_BitstreamFlushBits(stream, (int)(lastOne[tmpvar2] - 1));
865                     }
866                 }
867             }
868         }
869 
870     }
871 }
872 
873 /* ======================================================================== */
874 /*  Function : quickSearchDCM()                                             */
875 /*  Date     : 01/22/99                                                     */
876 /*  Purpose  : Quick search for DC Marker                                   */
877 /*              We are not using the fastest algorithm possible.  What this */
878 /*              function does is to locate 11 consecutive 0's and then      */
879 /*              check if the 7 bits before them and the 1 bit after them    */
880 /*              are correct.  (actually the first part of it, i.e. 16 0's   */
881 /*              and a 1.                                                    */
882 /*  In/out   :                                                              */
883 /*  Return   : Boolean true of false                                        */
884 /*  Modified : 12/18/2000 : 32-bit version                    */
885 /* ======================================================================== */
quickSearchDCM(BitstreamDecVideo * stream)886 PV_STATUS quickSearchDCM(BitstreamDecVideo *stream)
887 // DCM: (110 1011 0000 0000 0001)
888 {
889     PV_STATUS status;
890     uint32 tmpvar, tmpvar2;
891 
892     if (stream->searched_frame_boundary == 0)
893     {
894         status = PVLocateM4VFrameBoundary(stream);
895         if (status != PV_SUCCESS) return status;
896     }
897 
898     while (TRUE)
899     {
900         status = BitstreamCheckEndBuffer(stream);
901         if (status == PV_END_OF_VOP) return PV_END_OF_VOP;
902         BitstreamShowBits32(stream, 19, &tmpvar);
903 
904         if (tmpvar & 1) //  Check if the 17th bit from the curr bit pos is a '1'
905         {
906             if (tmpvar == DC_MARKER)
907             {
908                 return PV_SUCCESS; //  Found
909             }
910             else
911             {
912                 //  01/25/99 We treat the last of the 19 bits as its 7th bit (which is
913                 // also a `1'
914                 PV_BitstreamFlushBits(stream, 12);
915             }
916         }
917         else
918         {
919             tmpvar >>= 1;
920             tmpvar2 = tmpvar & 0xF;
921 
922             if (tmpvar2)
923             {
924                 PV_BitstreamFlushBits(stream, (int)(7 + lastOne[tmpvar2]));
925             }
926             else
927             {
928                 tmpvar >>= 4;
929                 tmpvar2 = tmpvar & 0xF;
930                 if (tmpvar2)
931                 {
932                     PV_BitstreamFlushBits(stream, (int)(3 + lastOne[tmpvar2]));
933                 }
934                 else
935                 {
936                     tmpvar >>= 4;
937                     tmpvar2 = tmpvar & 0xF;
938                     if (lastOne[tmpvar2] < 2)
939                     {
940                         /* we already have too many consecutive 0's. */
941                         /* Go directly pass the last of the 17 bits. */
942                         PV_BitstreamFlushBits(stream, 19);
943                     }
944                     else
945                     {
946                         PV_BitstreamFlushBits(stream, (int)(lastOne[tmpvar2] - 1));
947                     }
948                 }
949             }
950         }
951     }
952 }
953 
954 /* ======================================================================== */
955 /*  Function : quickSearchGOBHeader()   0000 0000 0000 0000 1               */
956 /*  Date     : 07/06/01                                                     */
957 /*  Purpose  : Quick search of GOBHeader (not byte aligned)                 */
958 /*  In/out   :                                                              */
959 /*  Return   : Integer value indicates type of marker found                 */
960 /*  Modified :                                                              */
961 /* ======================================================================== */
quickSearchGOBHeader(BitstreamDecVideo * stream)962 PV_STATUS quickSearchGOBHeader(BitstreamDecVideo *stream)
963 {
964     PV_STATUS status;
965     int byte0, byte1, byte2, shift, tmpvar;
966 
967     BitstreamByteAlignNoForceStuffing(stream);
968 
969     if (stream->searched_frame_boundary == 0)
970     {
971         status = PVLocateH263FrameBoundary(stream);
972         if (status != PV_SUCCESS) return status;
973     }
974 
975     while (TRUE)
976     {
977         status = BitstreamCheckEndBuffer(stream);
978         if (status == PV_END_OF_VOP) return PV_END_OF_VOP;
979 
980         if (stream->incnt < 24)
981         {
982             status = BitstreamFillCache(stream);
983         }
984 
985 
986         byte1 = (stream->curr_word << 8) >> 24;
987         if (byte1 == 0)
988         {
989             byte2 = (stream->curr_word << 16) >> 24;
990             if (byte2)
991             {
992                 tmpvar = byte2 >> 4;
993 
994                 if (tmpvar)
995                 {
996                     shift = 9 - firstOne[tmpvar];
997                 }
998                 else
999                 {
1000                     shift = 5 - firstOne[byte2];
1001                 }
1002                 byte0 = stream->curr_word >> 24;
1003                 if ((byte0 & msk[shift]) == 0)
1004                 {
1005                     PV_BitstreamFlushBits(stream, 8 - shift);
1006                     return PV_SUCCESS;
1007                 }
1008                 PV_BitstreamFlushBits(stream, 8);    /* third_byte is not zero */
1009             }
1010         }
1011 
1012         PV_BitstreamFlushBits(stream, 8);
1013     }
1014 }
1015