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 /* ======================================================================== */
EncodeFrameCombinedMode(VideoEncData * video)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 /* ======================================================================== */
EncodeSliceCombinedMode(VideoEncData * video)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 
EncodeGOBHeader(VideoEncData * video,Int GOB_number,Int quant_scale,Int bs1stream)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