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