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 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 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 /* ======================================================================== */ 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 /* ======================================================================== */ 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 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 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 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 /* ======================================================================== */ 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 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 /* ======================================================================== */ 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 /* ======================================================================== */ 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 /* ======================================================================== */ 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 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 /* ======================================================================== */ 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 /* ======================================================================== */ 760 Int BitstreamGetPos(BitstreamEncVideo *stream) 761 { 762 763 return stream->byteCount*8 + (WORD_SIZE << 3) - stream->bitLeft; 764 } 765 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. */ 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 */ 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