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 #ifndef H263_ONLY
19
20 #include "mp4def.h"
21 #include "mp4lib_int.h"
22 #include "bitstream_io.h"
23 #include "mp4enc_lib.h"
24 #include "m4venc_oscl.h"
25
26 /* ======================================================================== */
27 /* Function : EncodeFrameDataPartMode() */
28 /* Date : 09/6/2000 */
29 /* History : */
30 /* Purpose : Encode a frame of MPEG4 bitstream in datapartitioning mode. */
31 /* In/out : */
32 /* Return : PV_SUCCESS if successful else PV_FAIL */
33 /* Modified : */
34 /* */
35 /* ======================================================================== */
EncodeFrameDataPartMode(VideoEncData * video)36 PV_STATUS EncodeFrameDataPartMode(VideoEncData *video)
37 {
38 PV_STATUS status = PV_SUCCESS;
39 Vol *currVol = video->vol[video->currLayer];
40 Vop *currVop = video->currVop;
41 VideoEncParams *encParams = video->encParams;
42 Int width = currVop->width; /* has to be Vop, for multiple of 16 */
43 Int lx = currVop->pitch; /* with padding */
44 Int offset = 0;
45 Int ind_x, ind_y;
46 Int start_packet_header = 0;
47 UChar *QPMB = video->QPMB;
48 Int QP;
49 Int mbnum = 0, slice_counter = 0;
50 Int num_bits, packet_size = encParams->ResyncPacketsize;
51 BitstreamEncVideo *bs1 = video->bitstream1;
52 BitstreamEncVideo *bs2 = video->bitstream2;
53 BitstreamEncVideo *bs3 = video->bitstream3;
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 video->QP_prev = currVop->quantizer;
62
63 numHeaderBits = BitstreamGetPos(bs1); /* Number of bits in VOP Header */
64
65 /* determine type of quantization */
66 #ifndef NO_MPEG_QUANT
67 if (currVol->quantType == 0)
68 CodeMB = &CodeMB_H263;
69 else
70 CodeMB = &CodeMB_MPEG;
71 #else
72 CodeMB = &CodeMB_H263;
73 #endif
74
75 /* determine which functions to be used, in MB-level */
76 if (currVop->predictionType == P_VOP)
77 MBVlcEncode = &MBVlcEncodeDataPar_P_VOP;
78 else if (currVop->predictionType == I_VOP)
79 MBVlcEncode = &MBVlcEncodeDataPar_I_VOP;
80 else /* B_VOP not implemented yet */
81 return PV_FAIL;
82
83 /* determine which VLC table to be used */
84 if (currVol->shortVideoHeader)
85 BlockCodeCoeff = &BlockCodeCoeff_ShortHeader;
86 #ifndef NO_RVLC
87 else if (currVol->useReverseVLC)
88 BlockCodeCoeff = &BlockCodeCoeff_RVLC;
89 #endif
90 else
91 BlockCodeCoeff = &BlockCodeCoeff_Normal;
92
93 video->usePrevQP = 0;
94
95 for (ind_y = 0; ind_y < currVol->nMBPerCol; ind_y++) /* Col MB Loop */
96 {
97
98 video->outputMB->mb_y = ind_y; /* 5/28/01 */
99
100 for (ind_x = 0; ind_x < currVol->nMBPerRow; ind_x++) /* Row MB Loop */
101 {
102 video->outputMB->mb_x = ind_x; /* 5/28/01 */
103 video->mbnum = mbnum;
104 video->sliceNo[mbnum] = slice_counter; /* Update MB slice number */
105 QP = QPMB[mbnum]; /* always read new QP */
106
107 /****************************************************************************************/
108 /* MB Prediction:Put into MC macroblock, substract from currVop, put in predMB */
109 /****************************************************************************************/
110
111 getMotionCompensatedMB(video, ind_x, ind_y, offset);
112
113 if (start_packet_header)
114 {
115 slice_counter++; /* Increment slice counter */
116 video->sliceNo[mbnum] = slice_counter; /* Update MB slice number*/
117 video->header_bits -= BitstreamGetPos(bs1); /* Header Bits */
118 video->QP_prev = currVop->quantizer; /* store QP */
119 status = EncodeVideoPacketHeader(video, mbnum, video->QP_prev, 0);
120 video->header_bits += BitstreamGetPos(bs1); /* Header Bits */
121 numHeaderBits = BitstreamGetPos(bs1);
122 start_packet_header = 0;
123 video->usePrevQP = 0;
124 }
125
126 /***********************************************/
127 /* Code_MB: DCT, Q, Q^(-1), IDCT, Motion Comp */
128 /***********************************************/
129
130 status = (*CodeMB)(video, &fastDCTfunction, (offset << 5) + QP, ncoefblck);
131
132 /************************************/
133 /* MB VLC Encode: VLC Encode MB */
134 /************************************/
135
136 MBVlcEncode(video, ncoefblck, (void*)BlockCodeCoeff);
137
138 /*************************************************************/
139 /* Assemble Packets: Assemble the MB VLC codes into Packets */
140 /*************************************************************/
141
142 /* INCLUDE VOP HEADER IN COUNT */
143
144 num_bits = BitstreamGetPos(bs1) + BitstreamGetPos(bs2) +
145 BitstreamGetPos(bs3) - numHeaderBits;
146
147 /* Assemble_Packet(video) */
148
149 if (num_bits > packet_size)
150 {
151 if (video->currVop->predictionType == I_VOP)
152 BitstreamPutGT16Bits(bs1, 19, DC_MARKER); /* Add dc_marker */
153 else
154 BitstreamPutGT16Bits(bs1, 17, MOTION_MARKER_COMB); /*Add motion_marker*/
155 BitstreamAppendEnc(bs1, bs2); /* Combine bs1 and bs2 */
156 BitstreamAppendEnc(bs1, bs3); /* Combine bs1 and bs3 */
157 video->header_bits += BitstreamMpeg4ByteAlignStuffing(bs1); /* Byte align Packet */
158
159 status = BitstreamAppendPacket(currVol->stream, bs1); /* Put Packet to Buffer */
160 /* continue even if status == PV_END_OF_BUF, to get the stats */
161
162 BitstreamEncReset(bs1); /* Initialize to 0 */
163 BitstreamEncReset(bs2);
164 BitstreamEncReset(bs3);
165 start_packet_header = 1;
166 }
167 mbnum++;
168 offset += 16;
169 } /* End of For ind_x */
170
171 offset += (lx << 4) - width;
172 } /* End of For ind_y */
173
174 if (!start_packet_header)
175 {
176 if (video->currVop->predictionType == I_VOP)
177 {
178 BitstreamPutGT16Bits(bs1, 19, DC_MARKER); /* Add dc_marker */
179 video->header_bits += 19;
180 }
181 else
182 {
183 BitstreamPutGT16Bits(bs1, 17, MOTION_MARKER_COMB); /* Add motion_marker */
184 video->header_bits += 17;
185 }
186 BitstreamAppendEnc(bs1, bs2);
187 BitstreamAppendEnc(bs1, bs3);
188 video->header_bits += BitstreamMpeg4ByteAlignStuffing(bs1); /* Byte align Packet */
189 status = BitstreamAppendPacket(currVol->stream, bs1); /* Put Packet to Buffer */
190 /* continue even if status == PV_END_OF_BUF, to get the stats */
191 BitstreamEncReset(bs1); /* Initialize to 0 */
192 BitstreamEncReset(bs2);
193 BitstreamEncReset(bs3);
194 }
195
196 return status; /* if status == PV_END_OF_BUF, this frame will be pre-skipped */
197 }
198
199 #ifndef NO_SLICE_ENCODE
200 /* ======================================================================== */
201 /* Function : EncodeSliceDataPartMode() */
202 /* Date : 04/19/2002 */
203 /* History : */
204 /* Purpose : Encode a slice of MPEG4 bitstream in DataPar mode and save */
205 /* the current MB to continue next time it is called. */
206 /* In/out : */
207 /* Return : PV_SUCCESS if successful else PV_FAIL */
208 /* Modified : */
209 /* */
210 /* ======================================================================== */
EncodeSliceDataPartMode(VideoEncData * video)211 PV_STATUS EncodeSliceDataPartMode(VideoEncData *video)
212 {
213 PV_STATUS status = PV_SUCCESS;
214 Vol *currVol = video->vol[video->currLayer];
215 Vop *currVop = video->currVop;
216 UChar mode, *Mode = video->headerInfo.Mode;
217 VideoEncParams *encParams = video->encParams;
218 Int nTotalMB = currVol->nTotalMB;
219 Int width = currVop->width; /* has to be Vop, for multiple of 16 */
220 Int lx = currVop->pitch; /* , with pading */
221 UChar *QPMB = video->QPMB;
222 Int QP;
223 Int ind_x = video->outputMB->mb_x, ind_y = video->outputMB->mb_y;
224 Int offset = video->offset; /* get current MB location */
225 Int mbnum = video->mbnum, slice_counter = video->sliceNo[mbnum]; /* get current MB location */
226 Int firstMB = mbnum;
227 Int start_packet_header = (mbnum != 0);
228 Int num_bits = 0;
229 Int packet_size = encParams->ResyncPacketsize - 1 - (currVop->predictionType == I_VOP ? 19 : 17);
230 BitstreamEncVideo *bs1 = video->bitstream1;
231 BitstreamEncVideo *bs2 = video->bitstream2;
232 BitstreamEncVideo *bs3 = video->bitstream3;
233 Int bitCount1 = 0, bitCount2 = 0, bitCount3 = 0, byteCount1 = 0, byteCount2 = 0, byteCount3 = 0;
234 Int numHeaderBits = 0;
235 approxDCT fastDCTfunction;
236 Int ncoefblck[6] = {64, 64, 64, 64, 64, 64}; /* for FastCodeMB, 5/18/2001 */
237 UChar CBP;
238 Short outputMB[6][64];
239 PV_STATUS(*CodeMB)(VideoEncData *, approxDCT *, Int, Int[]);
240 void (*MBVlcEncode)(VideoEncData*, Int[], void *);
241 void (*BlockCodeCoeff)(RunLevelBlock*, BitstreamEncVideo*, Int, Int, UChar);
242 Int k;
243
244 video->QP_prev = 31;
245
246 if (video->end_of_buf) /* left-over from previous run */
247 {
248 status = BitstreamAppendPacketNoOffset(currVol->stream, bs1);
249 if (status != PV_END_OF_BUF)
250 {
251 BitstreamEncReset(bs1);
252 video->end_of_buf = 0;
253 }
254 return status;
255 }
256
257 if (mbnum == 0) /* only do this at the start of a frame */
258 {
259 QPMB[0] = video->QP_prev = QP = currVop->quantizer;
260 video->usePrevQP = 0;
261
262 numHeaderBits = BitstreamGetPos(bs1); /* Number of bits in VOP Header */
263
264 }
265
266
267 /* Re-assign fast functions on every slice, don't have to put it in the memory */
268 QP = QPMB[mbnum];
269 if (mbnum > 0) video->QP_prev = QPMB[mbnum-1];
270
271 /* determine type of quantization */
272 #ifndef NO_MPEG_QUANT
273 if (currVol->quantType == 0)
274 CodeMB = &CodeMB_H263;
275 else
276 CodeMB = &CodeMB_MPEG;
277 #else
278 CodeMB = &CodeMB_H263;
279 #endif
280
281 /* determine which functions to be used, in MB-level */
282 if (currVop->predictionType == P_VOP)
283 MBVlcEncode = &MBVlcEncodeDataPar_P_VOP;
284 else if (currVop->predictionType == I_VOP)
285 MBVlcEncode = &MBVlcEncodeDataPar_I_VOP;
286 else /* B_VOP not implemented yet */
287 return PV_FAIL;
288
289 /* determine which VLC table to be used */
290 #ifndef NO_RVLC
291 if (currVol->useReverseVLC)
292 BlockCodeCoeff = &BlockCodeCoeff_RVLC;
293 else
294 #endif
295 BlockCodeCoeff = &BlockCodeCoeff_Normal;
296
297 if (mbnum != 0)
298 {
299 goto JUMP_IN;
300 }
301
302 for (ind_y = 0; ind_y < currVol->nMBPerCol; ind_y++) /* Col MB Loop */
303 {
304
305 video->outputMB->mb_y = ind_y; /* 5/28/01 */
306
307 for (ind_x = 0; ind_x < currVol->nMBPerRow; ind_x++) /* Row MB Loop */
308 {
309
310 video->outputMB->mb_x = ind_x; /* 5/28/01 */
311 video->mbnum = mbnum;
312 video->sliceNo[mbnum] = slice_counter; /* Update MB slice number */
313
314 /****************************************************************************************/
315 /* MB Prediction:Put into MC macroblock, substract from currVop, put in predMB */
316 /****************************************************************************************/
317 getMotionCompensatedMB(video, ind_x, ind_y, offset);
318
319 JUMP_IN:
320
321 QP = QPMB[mbnum]; /* always read new QP */
322
323 if (start_packet_header)
324 {
325 slice_counter++; /* Increment slice counter */
326 video->sliceNo[mbnum] = slice_counter; /* Update MB slice number*/
327 video->QP_prev = currVop->quantizer; /* store QP */
328 num_bits = BitstreamGetPos(bs1);
329 status = EncodeVideoPacketHeader(video, mbnum, video->QP_prev, 0);
330 numHeaderBits = BitstreamGetPos(bs1) - num_bits;
331 video->header_bits += numHeaderBits; /* Header Bits */
332 start_packet_header = 0;
333 video->usePrevQP = 0;
334 }
335 else /* don't encode the first MB in packet again */
336 {
337 /***********************************************/
338 /* Code_MB: DCT, Q, Q^(-1), IDCT, Motion Comp */
339 /***********************************************/
340
341 status = (*CodeMB)(video, &fastDCTfunction, (offset << 5) + QP, ncoefblck);
342 for (k = 0; k < 6; k++)
343 {
344 M4VENC_MEMCPY(outputMB[k], video->outputMB->block[k], sizeof(Short) << 6);
345 }
346 }
347
348 /************************************/
349 /* MB VLC Encode: VLC Encode MB */
350 /************************************/
351
352 /* save the state before VLC encoding */
353 bitCount1 = BitstreamGetPos(bs1);
354 bitCount2 = BitstreamGetPos(bs2);
355 bitCount3 = BitstreamGetPos(bs3);
356 byteCount1 = bitCount1 >> 3;
357 byteCount2 = bitCount2 >> 3;
358 byteCount3 = bitCount3 >> 3;
359 bitCount1 &= 0x7;
360 bitCount2 &= 0x7;
361 bitCount3 &= 0x7;
362 mode = Mode[mbnum];
363 CBP = video->headerInfo.CBP[mbnum];
364
365 /*************************************/
366
367 MBVlcEncode(video, ncoefblck, (void*)BlockCodeCoeff);
368
369 /*************************************************************/
370 /* Assemble Packets: Assemble the MB VLC codes into Packets */
371 /*************************************************************/
372
373 num_bits = BitstreamGetPos(bs1) + BitstreamGetPos(bs2) +
374 BitstreamGetPos(bs3);// - numHeaderBits; //include header bits
375
376 /* Assemble_Packet(video) */
377 if (num_bits > packet_size && mbnum != firstMB) /* encoding at least one more MB*/
378 {
379
380 BitstreamRepos(bs1, byteCount1, bitCount1); /* rewind one MB */
381 BitstreamRepos(bs2, byteCount2, bitCount2); /* rewind one MB */
382 BitstreamRepos(bs3, byteCount3, bitCount3); /* rewind one MB */
383
384 if (video->currVop->predictionType == I_VOP)
385 {
386 BitstreamPutGT16Bits(bs1, 19, DC_MARKER); /* Add dc_marker */
387 video->header_bits += 19;
388 }
389 else
390 {
391 BitstreamPutGT16Bits(bs1, 17, MOTION_MARKER_COMB); /*Add motion_marker*/
392 video->header_bits += 17;
393 }
394
395 status = BitstreamAppendEnc(bs1, bs2); /* Combine with bs2 */
396 status = BitstreamAppendEnc(bs1, bs3); /* Combine with bs3 */
397
398 video->header_bits += BitstreamMpeg4ByteAlignStuffing(bs1); /* Byte align Packet */
399 status = BitstreamAppendPacketNoOffset(currVol->stream, bs1);
400
401 BitstreamEncReset(bs2);
402 BitstreamEncReset(bs3);
403
404 if (status == PV_END_OF_BUF) /* if cannot fit a buffer */
405 {
406 video->end_of_buf = 1;
407 }
408 else
409 {
410 BitstreamEncReset(bs1);
411 }
412
413 start_packet_header = 1;
414
415 if (mbnum < nTotalMB || video->end_of_buf) /* return here */
416 {
417 video->mbnum = mbnum;
418 video->sliceNo[mbnum] = slice_counter;
419 video->offset = offset;
420 Mode[mbnum] = mode;
421 video->headerInfo.CBP[mbnum] = CBP;
422
423 for (k = 0; k < 6; k++)
424 {
425 M4VENC_MEMCPY(video->outputMB->block[k], outputMB[k], sizeof(Short) << 6);
426 }
427
428 return status;
429 }
430 }
431
432 offset += 16;
433 mbnum++; /* has to increment before SCD, to preserve Mode[mbnum] */
434 } /* End of For ind_x */
435
436 offset += (lx << 4) - width;
437
438 } /* End of For ind_y */
439
440 if (!start_packet_header)
441 {
442 if (video->currVop->predictionType == I_VOP)
443 {
444 BitstreamPutGT16Bits(bs1, 19, DC_MARKER); /* Add dc_marker */
445 video->header_bits += 19;
446 }
447 else
448 {
449 BitstreamPutGT16Bits(bs1, 17, MOTION_MARKER_COMB); /*Add motion_marker*/
450 video->header_bits += 17;
451 }
452
453 status = BitstreamAppendEnc(bs1, bs2); /* Combine with bs2 */
454 status = BitstreamAppendEnc(bs1, bs3); /* Combine with bs3 */
455
456 video->header_bits += BitstreamMpeg4ByteAlignStuffing(bs1); /* Byte align Packet */
457 status = BitstreamAppendPacketNoOffset(currVol->stream, bs1);
458
459 BitstreamEncReset(bs2);
460 BitstreamEncReset(bs3);
461
462 if (status == PV_END_OF_BUF)
463 {
464 video->end_of_buf = 1;
465 }
466 else
467 {
468 BitstreamEncReset(bs1);
469 }
470 }
471
472 video->mbnum = mbnum;
473 if (mbnum < nTotalMB)
474 video->sliceNo[mbnum] = slice_counter;
475 video->offset = offset;
476
477 return status;
478 }
479 #endif /* NO_SLICE_ENCODE */
480 #endif /* H263_ONLY */
481
482
483