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
29static 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
52BitstreamEncVideo *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
93Void  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/* ======================================================================== */
120PV_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/* ======================================================================== */
168PV_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
207PV_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
257PV_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
326Int 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/* ======================================================================== */
355Int 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
416PV_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/* ======================================================================== */
493PV_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/* ======================================================================== */
532PV_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/* ======================================================================== */
581PV_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
625PV_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/* ======================================================================== */
681PV_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/* ======================================================================== */
760Int BitstreamGetPos(BitstreamEncVideo *stream)
761{
762
763    return stream->byteCount*8 + (WORD_SIZE << 3) - stream->bitLeft;
764}
765
766void 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
775overrun buffer.  */
776Void  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 */
787PV_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