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