combined_encode.cpp revision 59f566c4ec3dfc097ad8163523e522280b27e5c3
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
25PV_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/* ======================================================================== */
37PV_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/* ======================================================================== */
262PV_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 */
400JUMP_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
406JUMP_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
681PV_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