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