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 /* Date: 8/02/04                                                                */
19 /* Description:                                                                 */
20 /*  Change the bitstream parsing algorithm. Use temporary word of 2 or 4 bytes  */
21 /*  before writing it to the bitstream buffer.                                  */
22 /*  Note byteCount doesn't have to be multiple of 2 or 4                        */
23 /*********************************************************************************/
24 
25 #include "bitstream_io.h"
26 #include "m4venc_oscl.h"
27 #include <stdlib.h>
28 
29 static const UChar Mask[ ] =
30 {
31     0x00, 0x01, 0x03, 0x07, 0x0F, 0x1F, 0x3F, 0x7F, 0xFF
32 };
33 
34 #define WORD_SIZE   4   /* for 32-bit machine */
35 
36 /*Note:
37     1. There is a problem when output the last bits(which can not form a byte yet
38     so when you output, you need to stuff to make sure it is a byte
39     2.  I now hard coded byte to be 8 bits*/
40 
41 
42 /* ======================================================================== */
43 /*  Function : BitStreamCreateEnc(Int bufferSize )                          */
44 /*  Date     : 08/29/2000                                                   */
45 /*  Purpose  : Create a bitstream to hold one encoded video packet or frame */
46 /*  In/out   :                                                              */
47 /*      bufferSize  :   size of the bitstream buffer in bytes               */
48 /*  Return   : Pointer to the BitstreamEncVideo                             */
49 /*  Modified :                                                              */
50 /* ======================================================================== */
51 
BitStreamCreateEnc(Int bufferSize)52 BitstreamEncVideo *BitStreamCreateEnc(Int bufferSize)
53 {
54     BitstreamEncVideo *stream;
55     stream = (BitstreamEncVideo *) M4VENC_MALLOC(sizeof(BitstreamEncVideo));
56     if (stream == NULL)
57     {
58         return NULL;
59     }
60     stream->bufferSize = bufferSize;
61     stream->bitstreamBuffer = (UChar *) M4VENC_MALLOC(stream->bufferSize * sizeof(UChar));
62     if (stream->bitstreamBuffer == NULL)
63     {
64         M4VENC_FREE(stream);
65         stream = NULL;
66         return NULL;
67     }
68     M4VENC_MEMSET(stream->bitstreamBuffer, 0, stream->bufferSize*sizeof(UChar));
69     stream->word = 0;
70 #if WORD_SIZE==4
71     stream->bitLeft = 32;
72 #else
73     stream->bitLeft = 16;
74 #endif
75     stream->byteCount = 0;
76 
77     stream->overrunBuffer = NULL;
78     stream->oBSize = 0;
79 
80     return stream;
81 }
82 
83 /* ======================================================================== */
84 /*  Function : BitstreamCloseEnc( )                                         */
85 /*  Date     : 08/29/2000                                                   */
86 /*  Purpose  : close a bitstream                                            */
87 /*  In/out   :
88         stream  :   the bitstream to be closed                              */
89 /*  Return   :                                                              */
90 /*  Modified :                                                              */
91 /* ======================================================================== */
92 
BitstreamCloseEnc(BitstreamEncVideo * stream)93 Void  BitstreamCloseEnc(BitstreamEncVideo *stream)
94 {
95     if (stream)
96     {
97         if (stream->bitstreamBuffer)
98         {
99             M4VENC_FREE(stream->bitstreamBuffer);
100         }
101 
102         M4VENC_FREE(stream);
103     }
104 }
105 
106 
107 /* ======================================================================== */
108 /*  Function : BitstreamPutBits(BitstreamEncVideo *stream, Int Length,
109                          Int Value)                                         */
110 /*  Date     : 08/29/2000                                                   */
111 /*  Purpose  : put Length (1-16) number of bits to the stream               */
112 /*            for 32-bit machine this function can do upto 32 bit input     */
113 /*  In/out   :                                                              */
114 /*      stream      the bitstream where the bits are put in                 */
115 /*      Length      bits length (should belong to 1 to 16)                  */
116 /*      Value       those bits value                                        */
117 /*  Return   :  PV_STATUS                                                   */
118 /*  Modified :                                                              */
119 /* ======================================================================== */
BitstreamPutBits(BitstreamEncVideo * stream,Int Length,UInt Value)120 PV_STATUS BitstreamPutBits(BitstreamEncVideo *stream, Int Length, UInt Value)
121 {
122     PV_STATUS status;
123 
124     if (stream->bitLeft > Length)
125     {
126         stream->word <<= Length;
127         stream->word |= Value;  /* assuming Value is not larger than Length */
128         stream->bitLeft -= Length;
129         return PV_SUCCESS;
130     }
131     else
132     {
133 
134         stream->word <<= stream->bitLeft;
135         Length -= stream->bitLeft;
136         stream->word |= ((UInt)Value >> Length);
137 
138         status = BitstreamSaveWord(stream);
139         if (status != PV_SUCCESS)
140         {
141             return status;
142         }
143 
144         /* we got new Length and Value */
145         /* note that Value is not "clean" because of msb are not masked out */
146         stream->word = Value;
147         stream->bitLeft -= Length;
148         /* assuming that Length is no more than 16 bits */
149         /* stream->bitLeft should be greater than zero at this point */
150         //if(stream->bitLeft<=0)
151         //  exit(-1);
152         return PV_SUCCESS;
153     }
154 }
155 
156 /* ======================================================================== */
157 /*  Function : BitstreamPutGT16Bits(BitstreamEncVideo *stream, Int Length, UInt32 Value)    */
158 /*  Date     : 08/29/2000                                                   */
159 /*  Purpose  : Use this function to put Length (17-32) number of bits to    */
160 /*              for 16-bit machine  the stream.                             */
161 /*  In/out   :                                                              */
162 /*      stream      the bitstream where the bits are put in                 */
163 /*      Length      bits length (should belong to 17 to 32)                 */
164 /*      Value       those bits value                                        */
165 /*  Return   :  PV_STATUS                                                   */
166 /*  Modified :                                                              */
167 /* ======================================================================== */
BitstreamPutGT16Bits(BitstreamEncVideo * stream,Int Length,ULong Value)168 PV_STATUS BitstreamPutGT16Bits(BitstreamEncVideo *stream, Int Length, ULong Value)
169 {
170     PV_STATUS status;
171     UInt topValue;
172     Int topLength;
173 
174     topValue = (Value >> 16);
175     topLength = Length - 16;
176 
177     if (topLength > 0)
178     {
179         status = BitstreamPutBits(stream, topLength, topValue);
180 
181         if (status != PV_SUCCESS)
182         {
183             return status;
184         }
185 
186         status = BitstreamPutBits(stream, 16, (UInt)(Value & 0xFFFF));
187 
188         return status;
189     }
190     else
191     {
192         status = BitstreamPutBits(stream, Length, (UInt)Value);
193         return status;
194     }
195 }
196 
197 /* ======================================================================== */
198 /*  Function : BitstreamSaveWord                                            */
199 /*  Date     : 08/03/2004                                                   */
200 /*  Purpose  : save written word into the bitstream buffer.                 */
201 /*  In/out   :                                                              */
202 /*      stream      the bitstream where the bits are put in                 */
203 /*  Return   :  PV_STATUS                                                   */
204 /*  Modified :                                                              */
205 /* ======================================================================== */
206 
BitstreamSaveWord(BitstreamEncVideo * stream)207 PV_STATUS BitstreamSaveWord(BitstreamEncVideo *stream)
208 {
209     UChar *ptr;
210     UInt word;
211 
212     /* assume that stream->bitLeft is always zero when this function is called */
213     if (stream->byteCount + WORD_SIZE > stream->bufferSize)
214     {
215         if (PV_SUCCESS != BitstreamUseOverrunBuffer(stream, WORD_SIZE))
216         {
217             stream->byteCount += WORD_SIZE;
218             return PV_FAIL;
219         }
220     }
221 
222     ptr = stream->bitstreamBuffer + stream->byteCount;
223     word = stream->word;
224     stream->word = 0; /* important to reset to zero */
225 
226     /* NOTE: byteCount does not have to be multiple of 2 or 4 */
227 #if (WORD_SIZE == 4)
228     *ptr++ = word >> 24;
229     *ptr++ = 0xFF & (word >> 16);
230 #endif
231 
232     *ptr++ = 0xFF & (word >> 8);
233     *ptr = 0xFF & word;
234 
235 #if (WORD_SIZE == 4)
236     stream->byteCount += 4;
237     stream->bitLeft = 32;
238 #else
239     stream->byteCount += 2;
240     stream->bitLeft = 16;
241 #endif
242 
243     return PV_SUCCESS;
244 }
245 
246 
247 /* ======================================================================== */
248 /*  Function : BitstreamSavePartial                                         */
249 /*  Date     : 08/03/2004                                                   */
250 /*  Purpose  : save unfinished written word into the bitstream buffer.      */
251 /*  In/out   :                                                              */
252 /*      stream      the bitstream where the bits are put in                 */
253 /*  Return   :  PV_STATUS                                                   */
254 /*  Modified :                                                              */
255 /* ======================================================================== */
256 
BitstreamSavePartial(BitstreamEncVideo * stream,Int * fraction)257 PV_STATUS BitstreamSavePartial(BitstreamEncVideo *stream, Int *fraction)
258 {
259     UChar *ptr;
260     UInt word, shift;
261     Int numbyte, bitleft, bitused;
262 
263     bitleft = stream->bitLeft;
264     bitused = (WORD_SIZE << 3) - bitleft; /* number of bits used */
265     numbyte = bitused >> 3; /* number of byte fully used */
266 
267     if (stream->byteCount + numbyte > stream->bufferSize)
268     {
269         if (PV_SUCCESS != BitstreamUseOverrunBuffer(stream, numbyte))
270         {
271             stream->byteCount += numbyte;
272             return PV_FAIL;
273         }
274     }
275 
276     ptr = stream->bitstreamBuffer + stream->byteCount;
277     word = stream->word;
278     word <<= bitleft;   /* word is not all consumed */
279     bitleft = bitused - (numbyte << 3); /* number of bits used (fraction) */
280     stream->byteCount += numbyte;
281     if (bitleft)
282     {
283         *fraction = 1;
284     }
285     else
286     {
287         *fraction = 0;
288     }
289     bitleft = (WORD_SIZE << 3) - bitleft;
290     /* save new value */
291     stream->bitLeft = bitleft;
292 
293     shift = ((WORD_SIZE - 1) << 3);
294     while (numbyte)
295     {
296         *ptr++ = (UChar)((word >> shift) & 0xFF);
297         word <<= 8;
298         numbyte--;
299     }
300 
301     if (*fraction)
302     {// this could lead to buffer overrun when ptr is already out of bound.
303         //  *ptr = (UChar)((word>>shift)&0xFF); /* need to do it for the last fractional byte */
304     }
305 
306     /* save new values */
307     stream->word = word >> bitleft;
308 
309     /* note we don't update byteCount, bitLeft and word */
310     /* so that encoder can continue PutBits if they don't */
311 
312     return PV_SUCCESS;
313 }
314 
315 
316 /* ======================================================================== */
317 /*  Function : BitstreamShortHeaderByteAlignStuffing(                       */
318 /*                                      BitstreamEncVideo *stream)          */
319 /*  Date     : 08/29/2000                                                   */
320 /*  Purpose  : bit stuffing for next start code in short video header       */
321 /*  In/out   :                                                              */
322 /*  Return   :  number of bits to be stuffed                                */
323 /*  Modified :                                                              */
324 /* ======================================================================== */
325 
BitstreamShortHeaderByteAlignStuffing(BitstreamEncVideo * stream)326 Int BitstreamShortHeaderByteAlignStuffing(BitstreamEncVideo *stream)
327 {
328     UInt restBits;
329     Int fraction;
330 
331     restBits = (stream->bitLeft & 0x7); /* modulo 8 */
332 
333     if (restBits)  /*short_video_header[0] is 1 in h263 baseline*/
334     {
335         /* H.263 style stuffing */
336         BitstreamPutBits(stream, restBits, 0);
337     }
338 
339     if (stream->bitLeft != (WORD_SIZE << 3))
340     {
341         BitstreamSavePartial(stream, &fraction);
342     }
343 
344     return restBits;
345 }
346 
347 /* ======================================================================== */
348 /*  Function : BitstreamMpeg4ByteAlignStuffing(BitstreamEncVideo *stream)   */
349 /*  Date     : 08/29/2000                                                   */
350 /*  Purpose  : bit stuffing for next start code in MPEG-4                  */
351 /*  In/out   :                                                              */
352 /*  Return   :  number of bits to be stuffed                                */
353 /*  Modified :                                                              */
354 /* ======================================================================== */
BitstreamMpeg4ByteAlignStuffing(BitstreamEncVideo * stream)355 Int BitstreamMpeg4ByteAlignStuffing(BitstreamEncVideo *stream)
356 {
357 
358     UInt restBits;
359     Int fraction;
360     /* Question: in MPEG-4 , short_video_header[0]==0 => even already byte aligned, will still stuff 8 bits
361        need to check with  */
362     /*if (!(getPointerENC(index1, index2)%8) && short_video_header[0]) return 0;*/
363 
364     /* need stuffing bits, */
365     BitstreamPutBits(stream, 1, 0);
366 
367     restBits = (stream->bitLeft & 0x7); /* modulo 8 */
368 
369     if (restBits)  /*short_video_header[0] is 1 in h263 baseline*/
370     {
371         /* need stuffing bits, */
372         BitstreamPutBits(stream, restBits, Mask[restBits]);
373     }
374 
375     if (stream->bitLeft != (WORD_SIZE << 3))
376     {
377         BitstreamSavePartial(stream, &fraction);
378     }
379 
380     return (restBits);
381 }
382 
383 /*does bit stuffing for next resync marker*/
384 /*  does bit stuffing for next resync marker
385  *                                            "0"
386  *                                           "01"
387  *                                          "011"
388  *                                         "0111"
389  *                                        "01111"
390  *                                       "011111"
391  *                                      "0111111"
392  *                                     "01111111"   (8-bit codeword)
393  */
394 
395 /*Int BitstreamNextResyncMarkerEnc(BitstreamEncVideo *stream)
396 {
397   Int count;
398   BitstreamPut1Bits(stream,0);
399   count=8-stream->totalBits & 8;
400   BitstreamPutBits(stream,count,Mask[count]);
401   return count;
402 }*/
403 
404 /* ======================================================================== */
405 /*  Function : BitstreamAppendEnc( BitstreamEncVideo *bitstream1,           */
406 /*                                      BitstreamEncVideo *bitstream2   )   */
407 /*  Date     : 08/29/2000                                                   */
408 /*  Purpose  : Append the intermediate bitstream (bitstream2) to the end of */
409 /*                              output bitstream(bitstream1)                */
410 /*  In/out   :                                                              */
411 /*  Return   :                                                              */
412 /*  Modified :                                                              */
413 /* ======================================================================== */
414 
415 
BitstreamAppendEnc(BitstreamEncVideo * bitstream1,BitstreamEncVideo * bitstream2)416 PV_STATUS BitstreamAppendEnc(BitstreamEncVideo *bitstream1, BitstreamEncVideo *bitstream2)
417 {
418     PV_STATUS status;
419     UChar *ptrBS2, *ptrBS1;
420     UChar byteBS2, byteBS1;
421     Int  numbyte2;
422     Int bitused, bitleft, offset, fraction;
423 
424     status = BitstreamSavePartial(bitstream1, &fraction);
425     if (status != PV_SUCCESS)
426     {
427         return status;
428     }
429 
430     offset = fraction;
431     status = BitstreamSavePartial(bitstream2, &fraction);
432     if (status != PV_SUCCESS)
433     {
434         return status;
435     }
436 
437     if (!offset) /* bitstream1 is byte-aligned */
438     {
439         return BitstreamAppendPacket(bitstream1, bitstream2);
440     }
441 
442     offset += fraction;
443 
444     /* since bitstream1 doesn't have to be byte-aligned, we have to process byte by byte */
445     /* we read one byte from bitstream2 and use BitstreamPutBits to do the job */
446     if (bitstream1->byteCount + bitstream2->byteCount + offset > bitstream1->bufferSize)
447     {
448         if (PV_SUCCESS != BitstreamUseOverrunBuffer(bitstream1, bitstream2->byteCount + offset))
449         {
450             bitstream1->byteCount += (bitstream2->byteCount + offset);
451             return PV_FAIL;
452         }
453     }
454 
455     ptrBS1 = bitstream1->bitstreamBuffer + bitstream1->byteCount; /* move ptr bs1*/
456     ptrBS2 = bitstream2->bitstreamBuffer;
457 
458     bitused = (WORD_SIZE << 3) - bitstream1->bitLeft; /* this must be between 1-7 */
459     bitleft = 8 - bitused;
460 
461     numbyte2 = bitstream2->byteCount;   /* number of byte to copy from bs2 */
462     bitstream1->byteCount += numbyte2;  /* new byteCount */
463 
464     byteBS1 = ((UChar) bitstream1->word) << bitleft;    /* fraction byte from bs1 */
465 
466     while (numbyte2)
467     {
468         byteBS2 = *ptrBS2++;
469         byteBS1 |= (byteBS2 >> bitused);
470         *ptrBS1++ = byteBS1;
471         byteBS1 = byteBS2 << bitleft;
472         numbyte2--;
473     }
474 
475     bitstream1->word = byteBS1 >> bitleft;  /* bitstream->bitLeft remains the same */
476 
477     /* now save bs2->word in bs1 */
478     status = BitstreamPutBits(bitstream1, (WORD_SIZE << 3) - bitstream2->bitLeft, bitstream2->word);
479 
480     return status;
481 }
482 
483 /* ======================================================================== */
484 /*  Function : BitstreamAppendPacket( BitstreamEncVideo *bitstream1,        */
485 /*                                      BitstreamEncVideo *bitstream2   )   */
486 /*  Date     : 05/31/2001                                                   */
487 /*  Purpose  : Append the intermediate bitstream (bitstream2) to the end of */
488 /*              output bitstream(bitstream1) knowing that bitstream1 is byte-aligned*/
489 /*  In/out   :                                                              */
490 /*  Return   :                                                              */
491 /*  Modified :                                                              */
492 /* ======================================================================== */
BitstreamAppendPacket(BitstreamEncVideo * bitstream1,BitstreamEncVideo * bitstream2)493 PV_STATUS BitstreamAppendPacket(BitstreamEncVideo *bitstream1, BitstreamEncVideo *bitstream2)
494 {
495     UChar *ptrBS2, *ptrBS1;
496     Int  numbyte2;
497 
498     if (bitstream1->byteCount + bitstream2->byteCount  > bitstream1->bufferSize)
499     {
500         if (PV_SUCCESS != BitstreamUseOverrunBuffer(bitstream1, bitstream2->byteCount))
501         {
502             bitstream1->byteCount += bitstream2->byteCount; /* legacy, to keep track of total bytes */
503             return PV_FAIL;
504         }
505     }
506 
507     ptrBS1 = bitstream1->bitstreamBuffer + bitstream1->byteCount; /* move ptr bs1*/
508     ptrBS2 = bitstream2->bitstreamBuffer;
509 
510     numbyte2 = bitstream2->byteCount;
511     bitstream1->byteCount += numbyte2; /* new byteCount */
512 
513     /*copy all the bytes in bitstream2*/
514     M4VENC_MEMCPY(ptrBS1, ptrBS2, sizeof(UChar)*numbyte2);
515 
516     bitstream1->word = bitstream2->word;  /* bitstream1->bitLeft is the same */
517     bitstream1->bitLeft = bitstream2->bitLeft;
518 
519     return PV_SUCCESS;
520 }
521 
522 /* ======================================================================== */
523 /*  Function : BitstreamAppendPacketNoOffset( BitstreamEncVideo *bitstream1,*/
524 /*                                      BitstreamEncVideo *bitstream2   )   */
525 /*  Date     : 04/23/2002                                                   */
526 /*  Purpose  : Append the intermediate bitstream (bitstream2) to the end of */
527 /*              output bitstream(bitstream1) , for slice-based coding only */
528 /*  In/out   :                                                              */
529 /*  Return   :                                                              */
530 /*  Modified :                                                              */
531 /* ======================================================================== */
BitstreamAppendPacketNoOffset(BitstreamEncVideo * bitstream1,BitstreamEncVideo * bitstream2)532 PV_STATUS BitstreamAppendPacketNoOffset(BitstreamEncVideo *bitstream1, BitstreamEncVideo *bitstream2)
533 {
534     PV_STATUS status = PV_SUCCESS;
535     UChar *ptrBS2, *ptrBS1;
536     Int  numbyte2;
537     Int  byteleft;
538 
539     numbyte2 = bitstream2->byteCount;
540 
541     if (bitstream1->byteCount + bitstream2->byteCount > bitstream1->bufferSize)
542     {
543         numbyte2 =  bitstream1->bufferSize - bitstream1->byteCount;
544         status =  PV_END_OF_BUF;    /* signal end of buffer */
545     }
546 
547     ptrBS1 = bitstream1->bitstreamBuffer; /* move ptr bs1*/
548     ptrBS2 = bitstream2->bitstreamBuffer;
549 
550     bitstream1->byteCount += numbyte2; /* should be equal to bufferSize */
551 
552     /*copy all the bytes in bitstream2*/
553     M4VENC_MEMCPY(ptrBS1, ptrBS2, sizeof(UChar)*numbyte2);
554     bitstream1->word = 0;
555     bitstream1->bitLeft = (WORD_SIZE << 3);
556 
557     if (status == PV_END_OF_BUF) /* re-position bitstream2 */
558     {
559         byteleft = bitstream2->byteCount - numbyte2;
560 
561         M4VENC_MEMCPY(ptrBS2, ptrBS2 + numbyte2, sizeof(UChar)*byteleft);
562 
563         bitstream2->byteCount = byteleft;
564         /* bitstream2->word and bitstream->bitLeft are unchanged.
565            they should be 0 and (WORD_SIZE<<3) */
566     }
567 
568     return status;
569 }
570 
571 #ifndef NO_SLICE_ENCODE
572 /* ======================================================================== */
573 /*  Function : BitstreamRepos( BitstreamEncVideo *bitstream,                */
574 /*                                      Int byteCount, Int bitCount)        */
575 /*  Date     : 04/28/2002                                                   */
576 /*  Purpose  : Reposition the size of the buffer content (curtail)          */
577 /*  In/out   :                                                              */
578 /*  Return   :                                                              */
579 /*  Modified :                                                              */
580 /* ======================================================================== */
BitstreamRepos(BitstreamEncVideo * bitstream,Int byteCount,Int bitCount)581 PV_STATUS   BitstreamRepos(BitstreamEncVideo *bitstream, Int byteCount, Int bitCount)
582 {
583     UChar *ptr, byte;
584     UInt word;
585     Int fraction;
586 
587     BitstreamSavePartial(bitstream, &fraction);
588 
589     bitstream->byteCount = byteCount;
590     ptr = bitstream->bitstreamBuffer + byteCount; /* get fraction of the byte */
591     if (bitCount)
592     {
593         bitstream->bitLeft = (WORD_SIZE << 3) - bitCount; /* bitCount should be 0-31 */
594         word = *ptr++;
595         byte = *ptr++;
596         word = byte | (word << 8);
597 #if (WORD_SIZE == 4)
598         byte = *ptr++;
599         word = byte | (word << 8);
600         byte = *ptr++;
601         word = byte | (word << 8);
602 #endif
603         bitstream->word = word >> (bitstream->bitLeft);
604     }
605     else
606     {
607         bitstream->word = 0;
608         bitstream->bitLeft = (WORD_SIZE << 3);
609     }
610 
611     return PV_SUCCESS;
612 }
613 
614 /* ======================================================================== */
615 /*  Function : BitstreamFlushBits(BitstreamEncVideo *bitstream1,            */
616 /*                              Int num_bit_left)                           */
617 /*  Date     : 04/24/2002                                                   */
618 /*  Purpose  : Flush buffer except the last num_bit_left bits.              */
619 /*  In/out   :                                                              */
620 /*  Return   :                                                              */
621 /*  Modified :                                                              */
622 /* ======================================================================== */
623 
624 
BitstreamFlushBits(BitstreamEncVideo * bitstream1,Int num_bit_left)625 PV_STATUS BitstreamFlushBits(BitstreamEncVideo *bitstream1, Int num_bit_left)
626 {
627     Int i;
628     UChar *ptrDst, *ptrSrc;
629     Int leftover, bitused;
630     Int new_byte = (num_bit_left >> 3);
631     Int new_bit = num_bit_left - (new_byte << 3); /* between 0-7 */
632 
633     ptrSrc = bitstream1->bitstreamBuffer + bitstream1->byteCount;
634     ptrDst = bitstream1->bitstreamBuffer;
635 
636     bitused = (WORD_SIZE << 3) - bitstream1->bitLeft;
637 
638     leftover = 8 - bitused; /* bitused should be between 0-7 */
639 
640     bitstream1->byteCount = new_byte;
641     bitstream1->bitLeft = (WORD_SIZE << 3) - new_bit;
642 
643     if (!bitused) /* byte aligned */
644     {
645         M4VENC_MEMCPY(ptrDst, ptrSrc, new_byte + 1);
646     }
647     else
648     {
649         /*copy all the bytes in bitstream2*/
650         for (i = 0; i < new_byte; i++)
651         {
652             *ptrDst++ = (ptrSrc[0] << bitused) | (ptrSrc[1] >> leftover);
653             ptrSrc++;
654         }
655         /* copy for the last byte of ptrSrc, copy extra bits doesn't hurt */
656         if (new_bit)
657         {
658             *ptrDst++ = (ptrSrc[0] << bitused) | (ptrSrc[1] >> leftover);
659             ptrSrc++;
660         }
661     }
662     if (new_bit)
663     {
664         ptrSrc = bitstream1->bitstreamBuffer + new_byte;
665         bitstream1->word = (*ptrSrc) >> (8 - new_bit);
666     }
667 
668     return PV_SUCCESS;
669 }
670 
671 /* ======================================================================== */
672 /*  Function : BitstreamPrependPacket( BitstreamEncVideo *bitstream1,       */
673 /*                                      BitstreamEncVideo *bitstream2   )   */
674 /*  Date     : 04/26/2002                                                   */
675 /*  Purpose  : Prepend the intermediate bitstream (bitstream2) to the beginning of */
676 /*              output bitstream(bitstream1) */
677 /*  In/out   :                                                              */
678 /*  Return   :                                                              */
679 /*  Modified :                                                              */
680 /* ======================================================================== */
BitstreamPrependPacket(BitstreamEncVideo * bitstream1,BitstreamEncVideo * bitstream2)681 PV_STATUS BitstreamPrependPacket(BitstreamEncVideo *bitstream1, BitstreamEncVideo *bitstream2)
682 {
683     UChar *pSrc, *pDst, byte;
684     Int     movebyte, bitused, leftover, i, fraction;
685 
686     BitstreamSavePartial(bitstream2, &fraction); /* make sure only fraction of byte left */
687     BitstreamSavePartial(bitstream1, &fraction);
688 
689     if (bitstream1->byteCount + bitstream2->byteCount >= bitstream1->bufferSize)
690     {
691         bitstream1->byteCount += bitstream2->byteCount;
692         return PV_END_OF_BUF;
693     }
694 
695     movebyte = bitstream1->byteCount;
696     if (movebyte < bitstream2->byteCount)
697         movebyte = bitstream2->byteCount;
698     movebyte++;
699 
700     /* shift bitstream1 to the right by movebyte */
701     pSrc = bitstream1->bitstreamBuffer;
702     pDst = pSrc + movebyte;
703 
704     M4VENC_MEMCPY(pDst, pSrc, bitstream1->byteCount + 1);
705 
706     /* copy bitstream2 to the beginning of bitstream1 */
707     M4VENC_MEMCPY(pSrc, bitstream2->bitstreamBuffer, bitstream2->byteCount + 1);
708 
709     /* now shift back previous bitstream1 buffer to the end */
710     pSrc = pDst;
711     pDst = bitstream1->bitstreamBuffer + bitstream2->byteCount;
712 
713     bitused = (WORD_SIZE << 3) - bitstream2->bitLeft;
714     leftover = 8 - bitused;     /* bitused should be 0-7 */
715 
716     byte = (bitstream2->word) << leftover;
717 
718     *pDst++ = byte | (pSrc[0] >> bitused);
719 
720     for (i = 0; i < bitstream1->byteCount + 1; i++)
721     {
722         *pDst++ = ((pSrc[0] << leftover) | (pSrc[1] >> bitused));
723         pSrc++;
724     }
725 
726     bitstream1->byteCount += bitstream2->byteCount;
727     //bitstream1->bitCount += bitstream2->bitCount;
728     bitused = (WORD_SIZE << 4) - (bitstream1->bitLeft + bitstream2->bitLeft);
729 
730     if (bitused >= 8)
731     {
732         bitused -= 8;
733         bitstream1->byteCount++;
734     }
735 
736     bitstream1->bitLeft = (WORD_SIZE << 3) - bitused;
737 
738     bitstream2->byteCount = bitstream2->word = 0;
739     bitstream2->bitLeft = (WORD_SIZE << 3);
740 
741     pSrc = bitstream1->bitstreamBuffer + bitstream1->byteCount;
742     leftover = 8 - bitused;
743     //*pSrc = (pSrc[0]>>leftover)<<leftover; /* make sure the rest of bits are zeros */
744 
745     bitstream1->word = (UInt)((pSrc[0]) >> leftover);
746 
747     return PV_SUCCESS;
748 }
749 #endif  /* NO_SLICE_ENCODE */
750 
751 
752 /* ======================================================================== */
753 /*  Function : BitstreamGetPos( BitstreamEncVideo *stream                   */
754 /*  Date     : 08/05/2004                                                   */
755 /*  Purpose  : Get the bit position.                                        */
756 /*  In/out   :                                                              */
757 /*  Return   :                                                              */
758 /*  Modified :                                                              */
759 /* ======================================================================== */
BitstreamGetPos(BitstreamEncVideo * stream)760 Int BitstreamGetPos(BitstreamEncVideo *stream)
761 {
762 
763     return stream->byteCount*8 + (WORD_SIZE << 3) - stream->bitLeft;
764 }
765 
BitstreamEncReset(BitstreamEncVideo * stream)766 void BitstreamEncReset(BitstreamEncVideo *stream)
767 {
768     stream->bitLeft = (WORD_SIZE << 3);
769     stream->word = 0;
770     stream->byteCount = 0;
771     return ;
772 }
773 
774 /* This function set the overrun buffer, and VideoEncData context for callback to reallocate
775 overrun buffer.  */
BitstreamSetOverrunBuffer(BitstreamEncVideo * stream,UChar * overrunBuffer,Int oBSize,VideoEncData * video)776 Void  BitstreamSetOverrunBuffer(BitstreamEncVideo* stream, UChar* overrunBuffer, Int oBSize, VideoEncData *video)
777 {
778     stream->overrunBuffer = overrunBuffer;
779     stream->oBSize = oBSize;
780     stream->video = video;
781 
782     return ;
783 }
784 
785 
786 /* determine whether overrun buffer can be used or not */
BitstreamUseOverrunBuffer(BitstreamEncVideo * stream,Int numExtraBytes)787 PV_STATUS BitstreamUseOverrunBuffer(BitstreamEncVideo* stream, Int numExtraBytes)
788 {
789     VideoEncData *video = stream->video;
790 
791     if (stream->overrunBuffer != NULL) // overrunBuffer is set
792     {
793         if (stream->bitstreamBuffer != stream->overrunBuffer) // not already used
794         {
795             if (stream->byteCount + numExtraBytes >= stream->oBSize)
796             {
797                 stream->oBSize = stream->byteCount + numExtraBytes + 100;
798                 stream->oBSize &= (~0x3); // make it multiple of 4
799 
800                 // allocate new overrun Buffer
801                 if (video->overrunBuffer)
802                 {
803                     M4VENC_FREE(video->overrunBuffer);
804                 }
805                 video->oBSize = stream->oBSize;
806                 video->overrunBuffer = (UChar*) M4VENC_MALLOC(sizeof(UChar) * stream->oBSize);
807                 stream->overrunBuffer = video->overrunBuffer;
808                 if (stream->overrunBuffer == NULL)
809                 {
810                     return PV_FAIL;
811                 }
812             }
813 
814             // copy everything to overrun buffer and start using it.
815             memcpy(stream->overrunBuffer, stream->bitstreamBuffer, stream->byteCount);
816             stream->bitstreamBuffer = stream->overrunBuffer;
817             stream->bufferSize = stream->oBSize;
818         }
819         else // overrun buffer is already used
820         {
821             if (stream->byteCount + numExtraBytes >= stream->oBSize)
822             {
823                 stream->oBSize = stream->byteCount + numExtraBytes + 100;
824             }
825 
826             // allocate new overrun buffer
827             stream->oBSize &= (~0x3); // make it multiple of 4
828             video->oBSize = stream->oBSize;
829             video->overrunBuffer = (UChar*) M4VENC_MALLOC(sizeof(UChar) * stream->oBSize);
830             if (video->overrunBuffer == NULL)
831             {
832                 return PV_FAIL;
833             }
834 
835             // copy from the old buffer to new buffer
836             memcpy(video->overrunBuffer, stream->overrunBuffer, stream->byteCount);
837             // free old buffer
838             M4VENC_FREE(stream->overrunBuffer);
839             // assign pointer to new buffer
840             stream->overrunBuffer = video->overrunBuffer;
841             stream->bitstreamBuffer = stream->overrunBuffer;
842             stream->bufferSize = stream->oBSize;
843         }
844 
845         return PV_SUCCESS;
846     }
847     else // overrunBuffer is not enable.
848     {
849         return PV_FAIL;
850     }
851 
852 }
853 
854 
855 
856 
857 
858 
859 
860