Home | History | Annotate | Download | only in src
      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 #include "mp4def.h"
     19 #include "mp4enc_lib.h"
     20 #include "mp4lib_int.h"
     21 #include "bitstream_io.h"
     22 #include "vlc_encode.h"
     23 #include "m4venc_oscl.h"
     24 
     25 PV_STATUS EncodeGOBHeader(VideoEncData *video, Int GOB_number, Int quant_scale, Int bs1stream);
     26 
     27 /* ======================================================================== */
     28 /*  Function : EncodeFrameCombinedMode()                                    */
     29 /*  Date     : 09/01/2000                                                   */
     30 /*  History  :                                                              */
     31 /*  Purpose  : Encode a frame of MPEG4 bitstream in Combined mode.          */
     32 /*  In/out   :                                                              */
     33 /*  Return   :  PV_SUCCESS if successful else PV_FAIL                       */
     34 /*  Modified :                                                              */
     35 /*                                                                          */
     36 /* ======================================================================== */
     37 PV_STATUS EncodeFrameCombinedMode(VideoEncData *video)
     38 {
     39     PV_STATUS status = PV_SUCCESS;
     40     Vol *currVol = video->vol[video->currLayer];
     41     Vop *currVop = video->currVop;
     42     VideoEncParams *encParams = video->encParams;
     43     Int width = currVop->width; /* has to be Vop, for multiple of 16 */
     44     Int lx = currVop->pitch; /* with padding */
     45     Int offset = 0;
     46     Int ind_x, ind_y;
     47     Int start_packet_header = 0;
     48     UChar *QPMB = video->QPMB;
     49     Int QP;
     50     Int mbnum = 0, slice_counter = 0, curr_slice_counter = 0;
     51     Int num_bits, packet_size = encParams->ResyncPacketsize;
     52     Int GOB_Header_Interval = encParams->GOB_Header_Interval;
     53     BitstreamEncVideo *bs1 = video->bitstream1;
     54     Int numHeaderBits;
     55     approxDCT fastDCTfunction;
     56     Int ncoefblck[6] = {64, 64, 64, 64, 64, 64}; /* for FastCodeMB,  5/18/2001 */
     57     PV_STATUS(*CodeMB)(VideoEncData *, approxDCT *, Int, Int[]);
     58     void (*MBVlcEncode)(VideoEncData*, Int[], void *);
     59     void (*BlockCodeCoeff)(RunLevelBlock*, BitstreamEncVideo*, Int, Int, UChar);
     60 
     61     /* for H263 GOB changes */
     62 //MP4RateControlType rc_type = encParams->RC_Type;
     63 
     64     video->QP_prev = currVop->quantizer;
     65 
     66     numHeaderBits = BitstreamGetPos(bs1);
     67 
     68     /* determine type of quantization   */
     69 #ifndef NO_MPEG_QUANT
     70     if (currVol->quantType == 0)
     71         CodeMB = &CodeMB_H263;
     72     else
     73         CodeMB = &CodeMB_MPEG;
     74 #else
     75     CodeMB = &CodeMB_H263;
     76 #endif
     77 
     78     /* determine which functions to be used, in MB-level */
     79     if (currVop->predictionType == P_VOP)
     80         MBVlcEncode = &MBVlcEncodeCombined_P_VOP;
     81     else if (currVop->predictionType == I_VOP)
     82         MBVlcEncode = &MBVlcEncodeCombined_I_VOP;
     83     else /* B_VOP not implemented yet */
     84         return PV_FAIL;
     85 
     86     /* determine which VLC table to be used */
     87 #ifndef H263_ONLY
     88     if (currVol->shortVideoHeader)
     89         BlockCodeCoeff = &BlockCodeCoeff_ShortHeader;
     90 #ifndef NO_RVLC
     91     else if (currVol->useReverseVLC)
     92         BlockCodeCoeff = &BlockCodeCoeff_RVLC;
     93 #endif
     94     else
     95         BlockCodeCoeff = &BlockCodeCoeff_Normal;
     96 #else
     97     BlockCodeCoeff = &BlockCodeCoeff_ShortHeader;
     98 #endif
     99 
    100     /* gob_frame_id is the same for different vop types - the reason should be SCD */
    101     if (currVol->shortVideoHeader && currVop->gobFrameID != currVop->predictionType)
    102         currVop->gobFrameID = currVop->predictionType;
    103 
    104 
    105     video->usePrevQP = 0;
    106 
    107     for (ind_y = 0; ind_y < currVol->nMBPerCol; ind_y++)    /* Col MB Loop */
    108     {
    109 
    110         video->outputMB->mb_y = ind_y; /*  5/28/01 */
    111 
    112         if (currVol->shortVideoHeader)  /* ShortVideoHeader Mode */
    113         {
    114 
    115             if (slice_counter && GOB_Header_Interval && (ind_y % GOB_Header_Interval == 0))     /* Encode GOB Header */
    116             {
    117                 QP = QPMB[mbnum];    /* Get quant_scale */
    118                 video->header_bits -= BitstreamGetPos(currVol->stream); /* Header Bits */
    119                 status = EncodeGOBHeader(video, slice_counter, QP, 0);  //ind_y     /* Encode GOB Header */
    120                 video->header_bits += BitstreamGetPos(currVol->stream); /* Header Bits */
    121                 curr_slice_counter = slice_counter;
    122             }
    123         }
    124 
    125         for (ind_x = 0; ind_x < currVol->nMBPerRow; ind_x++)  /* Row MB Loop */
    126         {
    127             video->outputMB->mb_x = ind_x; /*  5/28/01 */
    128             video->mbnum = mbnum;
    129             QP = QPMB[mbnum];   /* always read new QP */
    130 
    131             if (GOB_Header_Interval)
    132                 video->sliceNo[mbnum] = curr_slice_counter; /* Update MB slice number */
    133             else
    134                 video->sliceNo[mbnum] = slice_counter;
    135 
    136             /****************************************************************************************/
    137             /* MB Prediction:Put into MC macroblock, substract from currVop, put in predMB */
    138             /****************************************************************************************/
    139             getMotionCompensatedMB(video, ind_x, ind_y, offset);
    140 
    141 #ifndef H263_ONLY
    142             if (start_packet_header)
    143             {
    144                 slice_counter++;                        /* Increment slice counter */
    145                 video->sliceNo[mbnum] = slice_counter;  /* Update MB slice number*/
    146                 video->header_bits -= BitstreamGetPos(bs1); /* Header Bits */
    147                 video->QP_prev = currVop->quantizer;
    148                 status = EncodeVideoPacketHeader(video, mbnum, video->QP_prev, 0);
    149                 video->header_bits += BitstreamGetPos(bs1); /* Header Bits */
    150                 numHeaderBits = BitstreamGetPos(bs1);
    151                 start_packet_header = 0;
    152                 video->usePrevQP = 0;
    153             }
    154 #endif
    155             /***********************************************/
    156             /* Code_MB:  DCT, Q, Q^(-1), IDCT, Motion Comp */
    157             /***********************************************/
    158 
    159             status = (*CodeMB)(video, &fastDCTfunction, (offset << 5) + QP, ncoefblck);
    160 
    161             /************************************/
    162             /* MB VLC Encode: VLC Encode MB     */
    163             /************************************/
    164 
    165             (*MBVlcEncode)(video, ncoefblck, (void*)BlockCodeCoeff);
    166 
    167             /*************************************************************/
    168             /* Assemble Packets:  Assemble the MB VLC codes into Packets */
    169             /*************************************************************/
    170 
    171             /* Assemble_Packet(video) */
    172 #ifndef H263_ONLY
    173             if (!currVol->shortVideoHeader) /* Not in ShortVideoHeader mode */
    174             {
    175                 if (!currVol->ResyncMarkerDisable) /* RESYNC MARKER MODE */
    176                 {
    177                     num_bits = BitstreamGetPos(bs1) - numHeaderBits;
    178                     if (num_bits > packet_size)
    179                     {
    180                         video->header_bits += BitstreamMpeg4ByteAlignStuffing(bs1); /* Byte align Packet */
    181 
    182                         status = BitstreamAppendPacket(currVol->stream, bs1); /* Put Packet to Buffer */
    183                         /* continue even if status == PV_END_OF_BUF, to get the stats */
    184 
    185                         BitstreamEncReset(bs1);
    186 
    187                         start_packet_header = 1;
    188                     }
    189                 }
    190                 else   /* NO RESYNC MARKER MODE */
    191                 {
    192                     status = BitstreamAppendEnc(currVol->stream, bs1); /* Initialize to 0 */
    193                     /* continue even if status == PV_END_OF_BUF, to get the stats */
    194 
    195                     BitstreamEncReset(bs1);
    196                 }
    197             }
    198             else
    199 #endif /* H263_ONLY */
    200             {   /* ShortVideoHeader Mode */
    201                 status = BitstreamAppendEnc(currVol->stream, bs1);  /* Initialize to 0 */
    202                 /* continue even if status == PV_END_OF_BUF, to get the stats */
    203 
    204                 BitstreamEncReset(bs1);
    205             }
    206             mbnum++;
    207             offset += 16;
    208         } /* End of For ind_x */
    209 
    210         offset += (lx << 4) - width;
    211         if (currVol->shortVideoHeader)  /* ShortVideoHeader = 1 */
    212         {
    213 
    214             if (GOB_Header_Interval)  slice_counter++;
    215         }
    216 
    217     } /* End of For ind_y */
    218 
    219     if (currVol->shortVideoHeader) /* ShortVideoHeader = 1 */
    220     {
    221 
    222         video->header_bits += BitstreamShortHeaderByteAlignStuffing(currVol->stream); /* Byte Align */
    223     }
    224 #ifndef H263_ONLY
    225     else   /* Combined Mode*/
    226     {
    227         if (!currVol->ResyncMarkerDisable) /* Resync Markers */
    228         {
    229 
    230             if (!start_packet_header)
    231             {
    232                 video->header_bits += BitstreamMpeg4ByteAlignStuffing(bs1);/* Byte Align  */
    233 
    234                 status = BitstreamAppendPacket(currVol->stream, bs1);   /* Put Packet to Buffer */
    235                 /* continue even if status == PV_END_OF_BUF, to get the stats */
    236 
    237                 BitstreamEncReset(bs1);
    238             }
    239         }
    240         else   /* No Resync Markers */
    241         {
    242             video->header_bits += BitstreamMpeg4ByteAlignStuffing(currVol->stream); /* Byte Align */
    243         }
    244     }
    245 #endif /* H263_ONLY */
    246 
    247     return status; /* if status == PV_END_OF_BUF, this frame will be pre-skipped */
    248 }
    249 
    250 #ifndef NO_SLICE_ENCODE
    251 /* ======================================================================== */
    252 /*  Function : EncodeSliceCombinedMode()                                    */
    253 /*  Date     : 04/19/2002                                                   */
    254 /*  History  :                                                              */
    255 /*  Purpose  : Encode a slice of MPEG4 bitstream in Combined mode and save  */
    256 /*              the current MB to continue next time it is called.          */
    257 /*  In/out   :                                                              */
    258 /*  Return   :  PV_SUCCESS if successful else PV_FAIL                       */
    259 /*  Modified :                                                              */
    260 /*                                                                          */
    261 /* ======================================================================== */
    262 PV_STATUS EncodeSliceCombinedMode(VideoEncData *video)
    263 {
    264     PV_STATUS status = PV_SUCCESS;
    265     Vol *currVol = video->vol[video->currLayer];
    266     Vop *currVop = video->currVop;
    267     UChar mode = MODE_INTRA;
    268     UChar *Mode = video->headerInfo.Mode;
    269     VideoEncParams *encParams = video->encParams;
    270     Int nTotalMB = currVol->nTotalMB;
    271     Int width = currVop->width; /* has to be Vop, for multiple of 16 */
    272     Int lx = currVop->pitch; /* , with padding */
    273 //  rateControl *rc = encParams->rc[video->currLayer];
    274     UChar *QPMB = video->QPMB;
    275     Int QP;
    276     Int ind_x = video->outputMB->mb_x, ind_y = video->outputMB->mb_y;
    277     Int offset = video->offset;                 /* get current MB location */
    278     Int mbnum = video->mbnum, slice_counter = video->sliceNo[mbnum]; /* get current MB location */
    279     Int firstMB = mbnum;
    280     Int start_packet_header = 0;
    281     Int num_bits = 0;
    282     Int packet_size = encParams->ResyncPacketsize - 1;
    283     Int resync_marker = ((!currVol->shortVideoHeader) && (!currVol->ResyncMarkerDisable));
    284     BitstreamEncVideo *bs1 = video->bitstream1;
    285     Int byteCount = 0, byteCount1 = 0, bitCount = 0;
    286     Int numHeaderBits = 0;
    287     approxDCT fastDCTfunction;
    288     Int ncoefblck[6] = {64, 64, 64, 64, 64, 64}; /* for FastCodeMB,  5/18/2001 */
    289     UChar CBP = 0;
    290     Short outputMB[6][64];
    291     Int k;
    292     PV_STATUS(*CodeMB)(VideoEncData *, approxDCT *, Int, Int[]);
    293     void (*MBVlcEncode)(VideoEncData*, Int[], void *);
    294     void (*BlockCodeCoeff)(RunLevelBlock*, BitstreamEncVideo*, Int, Int, UChar);
    295 
    296     video->QP_prev = 31;
    297 
    298 #define H263_GOB_CHANGES
    299 
    300 
    301     if (video->end_of_buf) /* left-over from previous run */
    302     {
    303         status = BitstreamAppendPacketNoOffset(currVol->stream, bs1);
    304         if (status != PV_END_OF_BUF)
    305         {
    306             BitstreamEncReset(bs1);
    307             video->end_of_buf = 0;
    308         }
    309         return status;
    310     }
    311 
    312 
    313     if (mbnum == 0) /* only do this at the start of a frame */
    314     {
    315         QPMB[0] = video->QP_prev = QP = currVop->quantizer;
    316         video->usePrevQP = 0;
    317 
    318         numHeaderBits = BitstreamGetPos(bs1);
    319     }
    320 
    321     /* Re-assign fast functions on every slice, don't have to put it in the memory */
    322     QP = QPMB[mbnum];
    323     if (mbnum > 0)   video->QP_prev = QPMB[mbnum-1];
    324 
    325     /* determine type of quantization   */
    326 #ifndef NO_MPEG_QUANT
    327     if (currVol->quantType == 0)
    328         CodeMB = &CodeMB_H263;
    329     else
    330         CodeMB = &CodeMB_MPEG;
    331 #else
    332     CodeMB = &CodeMB_H263;
    333 #endif
    334 
    335     /* determine which functions to be used, in MB-level */
    336     if (currVop->predictionType == P_VOP)
    337         MBVlcEncode = &MBVlcEncodeCombined_P_VOP;
    338     else if (currVop->predictionType == I_VOP)
    339         MBVlcEncode = &MBVlcEncodeCombined_I_VOP;
    340     else /* B_VOP not implemented yet */
    341         return PV_FAIL;
    342 
    343     /* determine which VLC table to be used */
    344 #ifndef H263_ONLY
    345     if (currVol->shortVideoHeader)
    346         BlockCodeCoeff = &BlockCodeCoeff_ShortHeader;
    347 #ifndef NO_RVLC
    348     else if (currVol->useReverseVLC)
    349         BlockCodeCoeff = &BlockCodeCoeff_RVLC;
    350 #endif
    351     else
    352         BlockCodeCoeff = &BlockCodeCoeff_Normal;
    353 #else
    354     BlockCodeCoeff = &BlockCodeCoeff_ShortHeader;
    355 #endif
    356 
    357     /*  (gob_frame_id is the same for different vop types) The reason should be SCD */
    358     if (currVol->shortVideoHeader && currVop->gobFrameID != currVop->predictionType)
    359         currVop->gobFrameID = currVop->predictionType;
    360 
    361 
    362     if (mbnum != 0)
    363     {
    364         if (currVol->shortVideoHeader)
    365         {
    366             /* Encode GOB Header */
    367             bitCount = BitstreamGetPos(bs1);
    368             byteCount1 = byteCount = bitCount >> 3; /* save the position before GOB header */
    369             bitCount = bitCount & 0x7;
    370 
    371 #ifdef H263_GOB_CHANGES
    372             video->header_bits -= BitstreamGetPos(bs1); /* Header Bits */
    373             status = EncodeGOBHeader(video, slice_counter, QP, 1);  //ind_y    /* Encode GOB Header */
    374             video->header_bits += BitstreamGetPos(bs1); /* Header Bits */
    375 #endif
    376             goto JUMP_IN_SH;
    377         }
    378         else if (currVol->ResyncMarkerDisable)
    379         {
    380             goto JUMP_IN_SH;
    381         }
    382         else
    383         {
    384             start_packet_header = 1;
    385             goto JUMP_IN;
    386         }
    387     }
    388 
    389     for (ind_y = 0; ind_y < currVol->nMBPerCol; ind_y++)    /* Col MB Loop */
    390     {
    391 
    392         video->outputMB->mb_y = ind_y; /*  5/28/01, do not remove */
    393 
    394         for (ind_x = 0; ind_x < currVol->nMBPerRow; ind_x++)  /* Row MB Loop */
    395         {
    396 
    397             video->outputMB->mb_x = ind_x; /*  5/28/01, do not remove */
    398             video->mbnum = mbnum;
    399             video->sliceNo[mbnum] = slice_counter;      /* Update MB slice number */
    400 JUMP_IN_SH:
    401             /****************************************************************************************/
    402             /* MB Prediction:Put into MC macroblock, substract from currVop, put in predMB */
    403             /****************************************************************************************/
    404             getMotionCompensatedMB(video, ind_x, ind_y, offset);
    405 
    406 JUMP_IN:
    407             QP = QPMB[mbnum];   /* always read new QP */
    408 #ifndef H263_ONLY
    409             if (start_packet_header)
    410             {
    411                 slice_counter++;                        /* Increment slice counter */
    412                 video->sliceNo[mbnum] = slice_counter;  /* Update MB slice number*/
    413                 video->QP_prev = currVop->quantizer;                        /* store QP */
    414                 num_bits = BitstreamGetPos(bs1);
    415                 status = EncodeVideoPacketHeader(video, mbnum, video->QP_prev, 1);
    416                 numHeaderBits = BitstreamGetPos(bs1) - num_bits;
    417                 video->header_bits += numHeaderBits; /* Header Bits */
    418                 start_packet_header = 0;
    419                 video->usePrevQP = 0;
    420             }
    421             else  /* don't encode the first MB in packet again */
    422 #endif /* H263_ONLY */
    423             {
    424                 /***********************************************/
    425                 /* Code_MB:  DCT, Q, Q^(-1), IDCT, Motion Comp */
    426                 /***********************************************/
    427                 status = (*CodeMB)(video, &fastDCTfunction, (offset << 5) + QP, ncoefblck);
    428             }
    429 
    430             /************************************/
    431             /* MB VLC Encode: VLC Encode MB     */
    432             /************************************/
    433 
    434             /* save the state before VLC encoding */
    435             if (resync_marker)
    436             {
    437                 bitCount = BitstreamGetPos(bs1);
    438                 byteCount = bitCount >> 3; /* save the state before encoding */
    439                 bitCount = bitCount & 0x7;
    440                 mode = Mode[mbnum];
    441                 CBP = video->headerInfo.CBP[mbnum];
    442                 for (k = 0; k < 6; k++)
    443                 {
    444                     M4VENC_MEMCPY(outputMB[k], video->outputMB->block[k], sizeof(Short) << 6);
    445                 }
    446             }
    447             /*************************************/
    448 
    449             (*MBVlcEncode)(video, ncoefblck, (void*)BlockCodeCoeff);
    450 
    451             /*************************************************************/
    452             /* Assemble Packets:  Assemble the MB VLC codes into Packets */
    453             /*************************************************************/
    454 
    455             /* Assemble_Packet(video) */
    456 #ifndef H263_ONLY
    457             if (!currVol->shortVideoHeader)
    458             {
    459                 if (!currVol->ResyncMarkerDisable)
    460                 {
    461                     /* Not in ShortVideoHeader mode and RESYNC MARKER MODE */
    462 
    463                     num_bits = BitstreamGetPos(bs1) ;//- numHeaderBits; // include header
    464 
    465                     /* Assemble packet and return when size reached */
    466                     if (num_bits > packet_size && mbnum != firstMB)
    467                     {
    468 
    469                         BitstreamRepos(bs1, byteCount, bitCount); /* rewind one MB */
    470 
    471                         video->header_bits += BitstreamMpeg4ByteAlignStuffing(bs1); /* Byte align Packet */
    472 
    473                         status = BitstreamAppendPacketNoOffset(currVol->stream, bs1); /* Put Packet to Buffer */
    474 
    475                         if (status == PV_END_OF_BUF)
    476                         {
    477                             video->end_of_buf = 1;
    478                         }
    479                         else
    480                         {
    481                             BitstreamEncReset(bs1);
    482                         }
    483 
    484                         start_packet_header = 1;
    485 
    486                         if (mbnum < nTotalMB || video->end_of_buf) /* return here */
    487                         {
    488                             video->mbnum = mbnum;
    489                             video->sliceNo[mbnum] = slice_counter;
    490                             video->offset = offset;
    491                             Mode[mbnum] = mode;
    492                             video->headerInfo.CBP[mbnum] = CBP;
    493 
    494                             for (k = 0; k < 6; k++)
    495                             {
    496                                 M4VENC_MEMCPY(video->outputMB->block[k], outputMB[k], sizeof(Short) << 6);
    497                             }
    498 
    499                             return status;
    500                         }
    501                     }
    502                 }
    503                 else  /* NO RESYNC MARKER , return when buffer is full*/
    504                 {
    505 
    506                     if (mbnum < nTotalMB - 1 && currVol->stream->byteCount + bs1->byteCount + 1 >= currVol->stream->bufferSize)
    507                     {
    508                         /* find maximum bytes to fit in the buffer */
    509                         byteCount = currVol->stream->bufferSize - currVol->stream->byteCount - 1;
    510 
    511                         num_bits = BitstreamGetPos(bs1) - (byteCount << 3);
    512                         BitstreamRepos(bs1, byteCount, 0);
    513                         status = BitstreamAppendPacketNoOffset(currVol->stream, bs1);
    514                         BitstreamFlushBits(bs1, num_bits);
    515 
    516                         /* move on to next MB */
    517                         mbnum++ ;
    518                         offset += 16;
    519                         video->outputMB->mb_x++;
    520                         if (video->outputMB->mb_x >= currVol->nMBPerRow)
    521                         {
    522                             video->outputMB->mb_x = 0;
    523                             video->outputMB->mb_y++;
    524                             offset += (lx << 4) - width;
    525                         }
    526                         video->mbnum = mbnum;
    527                         video->offset = offset;
    528                         video->sliceNo[mbnum] = slice_counter;
    529                         return status;
    530                     }
    531                 }
    532             }
    533 #endif /* H263_ONLY */
    534             offset += 16;
    535             mbnum++; /* has to increment before SCD, to preserve Mode[mbnum] */
    536 
    537         } /* End of For ind_x */
    538 
    539         offset += (lx << 4) - width;
    540 
    541         if (currVol->shortVideoHeader)  /* ShortVideoHeader = 1 */
    542         {
    543 #ifdef H263_GOB_CHANGES
    544             slice_counter++;
    545             video->header_bits += BitstreamShortHeaderByteAlignStuffing(bs1);
    546 #endif
    547             //video->header_bits+=BitstreamShortHeaderByteAlignStuffing(bs1);
    548 
    549             /* check if time to packetize */
    550             if (currVol->stream->byteCount + bs1->byteCount > currVol->stream->bufferSize)
    551             {
    552                 if (byteCount == byteCount1) /* a single GOB bigger than packet size */
    553                 {
    554                     status = BitstreamAppendPacketNoOffset(currVol->stream, bs1);
    555                     status = PV_END_OF_BUF;
    556                     video->end_of_buf = 1;
    557                     start_packet_header = 1;
    558                 }
    559                 else    /* for short_header scooch back to previous GOB */
    560                 {
    561                     num_bits = ((bs1->byteCount - byteCount) << 3);
    562                     //num_bits = ((bs1->byteCount<<3) + bs1->bitCount) - ((byteCount<<3) + bitCount);
    563                     BitstreamRepos(bs1, byteCount, 0);
    564                     //BitstreamRepos(bs1,byteCount,bitCount);
    565 //                  k = currVol->stream->byteCount; /* save state before appending */
    566                     status = BitstreamAppendPacketNoOffset(currVol->stream, bs1);
    567                     BitstreamFlushBits(bs1, num_bits);
    568 //                  if(mbnum == nTotalMB || k + bs1->byteCount >= currVol->stream->bufferSize){
    569                     /* last GOB or current one with larger size will be returned next run */
    570 //                      status = PV_END_OF_BUF;
    571 //                      video->end_of_buf = 1;
    572 //                  }
    573                     start_packet_header = 1;
    574                     if (mbnum == nTotalMB) /* there's one more GOB to packetize for the next round */
    575                     {
    576                         status = PV_END_OF_BUF;
    577                         video->end_of_buf = 1;
    578                     }
    579                 }
    580 
    581                 if (mbnum < nTotalMB) /* return here */
    582                 {
    583                     /* move on to next MB */
    584                     video->outputMB->mb_x = 0;
    585                     video->outputMB->mb_y++;
    586                     video->mbnum = mbnum;
    587                     video->offset = offset;
    588                     video->sliceNo[mbnum] = slice_counter;
    589                     return status;
    590                 }
    591             }
    592             else if (mbnum < nTotalMB) /* do not write GOB header if end of vop */
    593             {
    594                 bitCount = BitstreamGetPos(bs1);
    595                 byteCount = bitCount >> 3;  /* save the position before GOB header */
    596                 bitCount = bitCount & 0x7;
    597 #ifdef H263_GOB_CHANGES
    598                 video->header_bits -= BitstreamGetPos(bs1); /* Header Bits */
    599                 status = EncodeGOBHeader(video, slice_counter, QP, 1);         /* Encode GOB Header */
    600                 video->header_bits += BitstreamGetPos(bs1); /* Header Bits */
    601 #endif
    602             }
    603         }
    604 
    605     } /* End of For ind_y */
    606 #ifndef H263_ONLY
    607     if (!currVol->shortVideoHeader) /* Combined Mode*/
    608     {
    609         if (!currVol->ResyncMarkerDisable) /* Resync Markers */
    610         {
    611 
    612             if (!start_packet_header)
    613             {
    614 
    615                 video->header_bits += BitstreamMpeg4ByteAlignStuffing(bs1);/* Byte Align  */
    616 
    617                 status = BitstreamAppendPacketNoOffset(currVol->stream, bs1);   /* Put Packet to Buffer */
    618                 if (status == PV_END_OF_BUF)
    619                 {
    620                     video->end_of_buf = 1;
    621                 }
    622                 else
    623                 {
    624                     BitstreamEncReset(bs1);
    625                 }
    626             }
    627         }
    628         else   /* No Resync Markers */
    629         {
    630             video->header_bits += BitstreamMpeg4ByteAlignStuffing(bs1); /* Byte Align */
    631             status = BitstreamAppendPacketNoOffset(currVol->stream, bs1); /* Initialize to 0 */
    632             if (status == PV_END_OF_BUF)
    633             {
    634                 video->end_of_buf = 1;
    635             }
    636             else
    637             {
    638                 BitstreamEncReset(bs1);
    639             }
    640         }
    641     }
    642     else
    643 #endif /* H263_ONLY */
    644     {
    645         if (!start_packet_header) /* not yet packetized */
    646         {
    647             video->header_bits += BitstreamShortHeaderByteAlignStuffing(bs1);
    648             status = BitstreamAppendPacketNoOffset(currVol->stream, bs1);
    649             if (status == PV_END_OF_BUF)
    650             {
    651                 video->end_of_buf = 1;
    652             }
    653             else
    654             {
    655                 BitstreamEncReset(bs1);
    656                 video->end_of_buf = 0;
    657             }
    658         }
    659     }
    660 
    661     video->mbnum = mbnum;
    662     if (mbnum < nTotalMB)
    663         video->sliceNo[mbnum] = slice_counter;
    664     video->offset = offset;
    665 
    666     return status;
    667 }
    668 #endif  /* NO_SLICE_ENCODE */
    669 
    670 /* ======================================================================== */
    671 /*  Function : EncodeGOBHeader()                                            */
    672 /*  Date     : 09/05/2000                                                   */
    673 /*  History  :                                                              */
    674 /*  Purpose  : Encode a frame of MPEG4 bitstream in Combined mode.          */
    675 /*  In/out   :                                                              */
    676 /*  Return   :  PV_SUCCESS if successful else PV_FAIL                       */
    677 /*  Modified :                                                              */
    678 /*                                                                          */
    679 /* ======================================================================== */
    680 
    681 PV_STATUS EncodeGOBHeader(VideoEncData *video, Int GOB_number, Int quant_scale, Int bs1stream)
    682 {
    683     PV_STATUS status = PV_SUCCESS;
    684     BitstreamEncVideo *stream = (bs1stream ? video->bitstream1 : video->vol[video->currLayer]->stream);
    685 
    686     status = BitstreamPutGT16Bits(stream, 17, GOB_RESYNC_MARKER); /* gob_resync_marker */
    687     status = BitstreamPutBits(stream, 5, GOB_number);           /* Current gob_number */
    688     status = BitstreamPutBits(stream, 2, video->currVop->gobFrameID); /* gob_frame_id */
    689     status = BitstreamPutBits(stream, 5, quant_scale);              /* quant_scale */
    690     return status;
    691 }
    692 
    693 
    694