1 /* |
|
2 * Copyright (c) 2010 Ixonos Plc. |
|
3 * All rights reserved. |
|
4 * This component and the accompanying materials are made available |
|
5 * under the terms of the "Eclipse Public License v1.0" |
|
6 * which accompanies this distribution, and is available |
|
7 * at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 * |
|
9 * Initial Contributors: |
|
10 * Nokia Corporation - Initial contribution |
|
11 * |
|
12 * Contributors: |
|
13 * Ixonos Plc |
|
14 * |
|
15 * Description: |
|
16 * Implementation for MPEG4(H263) video transcoder. Operations may include: |
|
17 * 1. Bitstream Copying |
|
18 * 2. BlackAndWhite Effect |
|
19 * 3. MPEG4 to VDT_RESYN (Simple profile) |
|
20 * 4. H.263 -> MPEG4 (Open Loop structure, no MV refinement) |
|
21 * 5. MPEG4 -> H263, partial implemented |
|
22 * |
|
23 * We call functions 2~5 as transcoding functions since they involve MB level data processing |
|
24 * |
|
25 * Note: |
|
26 * When RVLC is used and errors occur during forward decoding, |
|
27 * We don't do backward transcoding, the rest of the data is discarded, |
|
28 * |
|
29 */ |
|
30 |
|
31 |
|
32 |
|
33 /* |
|
34 * Includes |
|
35 */ |
|
36 #include "MPEG4Transcoder.h" |
|
37 #include "debug.h" |
|
38 |
|
39 /* Print macro */ |
|
40 #ifdef _DEBUG |
|
41 #include <e32svr.h> |
|
42 #define PRINT(x) RDebug::Print x |
|
43 #else |
|
44 #define PRINT(x) |
|
45 #endif |
|
46 |
|
47 /* |
|
48 * Defines and Typedefs |
|
49 */ |
|
50 typedef unsigned int uint32; |
|
51 |
|
52 #define EInternalAssertionFailure 1000 |
|
53 #define VDT_NO_DATA(a, b, c, d) ((a) == (c) && (b) == (d)) |
|
54 |
|
55 const int KDataNotValid = -1; |
|
56 const int KMpeg4VopTimeIncrementResolutionLength = 16; |
|
57 const int KOutputMpeg4TimeIncResolution = 30000; |
|
58 const int KShortHeaderMpeg4VosSize = 14; |
|
59 const int KH263ToMpeg4VosSize = 28; |
|
60 |
|
61 |
|
62 |
|
63 /*Bit stream formating*/ |
|
64 #define WRITE32(op, x) sPutBits((op), 16, ((uint32)(x)) >> 16); \ |
|
65 sPutBits((op), 16, (x) & 0x0000ffff) |
|
66 |
|
67 /* |
|
68 * Constants |
|
69 */ |
|
70 #ifdef _DEBUG |
|
71 const TUint KInitialBufferSize = 200000; /* MPEG4 Simple Visual Profile (Levels 0,1,2,3) initial frame data buffer size vga support */ |
|
72 #endif |
|
73 /* |
|
74 * Function Declarations |
|
75 */ |
|
76 |
|
77 //Static Functions |
|
78 |
|
79 static void sStuffBitsH263(bibBuffer_t *outBuffer); |
|
80 static TVedVideoBitstreamMode sGetMPEG4Mode(int error_resilience_disable, int dp, int rvlc); |
|
81 static int sFindCBP(int *mbdata, int fUseIntraDCVLC); |
|
82 |
|
83 |
|
84 |
|
85 void vdtPutInterMBCMT(bibBuffer_t *outBuffer, int coeffStart, int *coeff, int *numTextureBits, int svh); |
|
86 void vdtPutIntraMBCMT(bibBuffer_t *outBuffer, int *coeff, int *numTextureBits, int index, int skipDC, int skipAC); |
|
87 void vbmEncodeMVDifferential(int32 mvdx, int32 mvdy, int32 fCode, bibBuffer_t *outBuffer); |
|
88 void vbmGetH263IMCBPC(int lDQuant, int vopCodingType, int colorEffect, int cbpy, int& mcbpcVal, int& len); |
|
89 void vbmGetH263PMCBPC(int lDQuant, int colorEffect, int cbpy, int& mcbpcVal, int& len); |
|
90 tBool vbmMVOutsideBound(tMBPosition *mbPos, tMotionVector* bestMV, tBool halfPixel); |
|
91 void vbmMvPrediction(tMBInfo *mbi, int32 mBCnt, tMotionVector *predMV, int32 mbinWidth); |
|
92 void vbmPutInterMB(tMBPosition* mbPos, bibBuffer_t *outBuf, dmdPParam_t *paramMB, tMotionVector *initPred, |
|
93 int32 noOfPredictors, u_int32 vopWidth, u_int32 vopHeight, int32 searchRange, |
|
94 int32 mbNo, int32* numTextureBits, int16 colorEffect, tMBInfo *mbsinfo); |
|
95 |
|
96 void sPutBits (bibBuffer_t *buf, int numBits, unsigned int value); //forward decl |
|
97 |
|
98 /* |
|
99 * Function Definitions |
|
100 */ |
|
101 |
|
102 /* |
|
103 * sStuffBitsH263 |
|
104 * |
|
105 * Parameters: |
|
106 * outBuffer output buffer |
|
107 * |
|
108 * Function: |
|
109 * This function stuffs bits for H.263 format |
|
110 * Returns: |
|
111 * None |
|
112 * Error codes: |
|
113 * None. |
|
114 * |
|
115 */ |
|
116 static void sStuffBitsH263(bibBuffer_t *outBuffer) |
|
117 { |
|
118 const int stuffingBits[8][2] = { {1,0}, {2,0}, {3,0}, {4,0}, {5,0}, {6,0}, {7,0}, {0,0} }; |
|
119 |
|
120 VDTASSERT(outBuffer->baseAddr); |
|
121 |
|
122 /* find the number of stuffing bits to insert in the output buffer */ |
|
123 int bi = outBuffer->bitIndex; |
|
124 int newNumBits = stuffingBits[bi][0]; |
|
125 int newValue = stuffingBits[bi][1]; |
|
126 sPutBits(outBuffer, newNumBits, newValue); |
|
127 |
|
128 return; |
|
129 } |
|
130 |
|
131 |
|
132 |
|
133 /* |
|
134 * sGetMPEG4Mode |
|
135 * |
|
136 * Parameters: |
|
137 * |
|
138 * |
|
139 * Function: |
|
140 * This function gets the mode of the MPEG-4 bitstream |
|
141 * Returns: |
|
142 * Nothing |
|
143 * Error codes: |
|
144 * None. |
|
145 * |
|
146 */ |
|
147 static TVedVideoBitstreamMode sGetMPEG4Mode(int error_resilience_disable, int dp, int rvlc) |
|
148 { |
|
149 TVedVideoBitstreamMode mode = EVedVideoBitstreamModeUnknown; |
|
150 int combination = ((!error_resilience_disable) << 2) | (dp << 1) | rvlc; |
|
151 switch (combination) |
|
152 { |
|
153 case 0: |
|
154 mode = EVedVideoBitstreamModeMPEG4Regular; |
|
155 break; |
|
156 case 2: |
|
157 mode = EVedVideoBitstreamModeMPEG4DP; |
|
158 break; |
|
159 case 3: |
|
160 mode = EVedVideoBitstreamModeMPEG4DP_RVLC; |
|
161 break; |
|
162 case 4: |
|
163 mode = EVedVideoBitstreamModeMPEG4Resyn; |
|
164 break; |
|
165 case 6: |
|
166 mode = EVedVideoBitstreamModeMPEG4Resyn_DP; |
|
167 break; |
|
168 case 7: |
|
169 mode = EVedVideoBitstreamModeMPEG4Resyn_DP_RVLC; |
|
170 break; |
|
171 default: |
|
172 mode = EVedVideoBitstreamModeUnknown; |
|
173 } |
|
174 |
|
175 return mode; |
|
176 } |
|
177 |
|
178 |
|
179 /* {{-output"vdtGetVideoBitstreamInfo.txt"}} */ |
|
180 /* |
|
181 * sFindCBP |
|
182 * |
|
183 * Parameters: |
|
184 * mbdata Contains the actual MB data to be quantized |
|
185 * fUseIntraDCVLC ON for INTRA, OFF for INTER |
|
186 * |
|
187 * Function: |
|
188 * This function finds the coded bit pattern of the MB |
|
189 * Returns: |
|
190 * Coded Block Pattern. |
|
191 * Error codes: |
|
192 * None. |
|
193 * |
|
194 */ |
|
195 static int sFindCBP(int *mbdata, int fUseIntraDCVLC) |
|
196 { |
|
197 int coeffCnt; |
|
198 int *block; |
|
199 int blkCnt; |
|
200 int cbpFlag = 0; |
|
201 int codedBlockPattern = 0; |
|
202 |
|
203 for (blkCnt = 0; blkCnt < 6; blkCnt++) |
|
204 { |
|
205 cbpFlag = 0; |
|
206 codedBlockPattern <<= 1; |
|
207 block = &mbdata[blkCnt * BLOCK_COEFF_SIZE]; |
|
208 for (coeffCnt = fUseIntraDCVLC; coeffCnt < BLOCK_COEFF_SIZE; |
|
209 coeffCnt++) |
|
210 { |
|
211 if (block[coeffCnt]) |
|
212 { |
|
213 cbpFlag = 1; |
|
214 codedBlockPattern |= cbpFlag; |
|
215 break; |
|
216 } |
|
217 } |
|
218 } |
|
219 |
|
220 return codedBlockPattern; |
|
221 } |
|
222 |
|
223 |
|
224 |
|
225 |
|
226 |
|
227 |
|
228 /* {{-output"sPutBits.txt"}} */ |
|
229 /* |
|
230 * sPutBits |
|
231 * |
|
232 * Parameters: |
|
233 * outBuf output buffer |
|
234 * numBits number of bits to output |
|
235 * value new value |
|
236 * |
|
237 * Function: |
|
238 * This function puts some bits to the output buffer |
|
239 * Returns: |
|
240 * Nothing. |
|
241 * Error codes: |
|
242 * None. |
|
243 * |
|
244 */ |
|
245 void sPutBits (bibBuffer_t *buf, int numBits, unsigned int value) |
|
246 { |
|
247 |
|
248 bibEditParams_t edParam; |
|
249 |
|
250 edParam.curNumBits = edParam.newNumBits = numBits; |
|
251 edParam.StartByteIndex = edParam.StartBitIndex = 0; /* used for source buffer only */ |
|
252 edParam.newValue = value; /* use value 128, encoded as codeword "1111 1111" = 255 */ |
|
253 |
|
254 CopyBufferEdit((bibBuffer_t*)NULL, buf, &edParam, 0); |
|
255 } |
|
256 |
|
257 |
|
258 |
|
259 /* |
|
260 * GetTimeIncPosition |
|
261 * |
|
262 * |
|
263 * Parameters: |
|
264 * hInstance instance handle |
|
265 * |
|
266 * Function: |
|
267 * Calculates the time increment position for the current VOP. |
|
268 * |
|
269 * Returns: |
|
270 * VDX error codes |
|
271 * |
|
272 */ |
|
273 |
|
274 int GetTimeIncPosition( |
|
275 bibBuffer_t *inBuffer, |
|
276 const vdxGetVopHeaderInputParam_t *inpParam, |
|
277 vdxVopHeader_t *header, |
|
278 int * ModuloByteIndex, |
|
279 int * ModuloBitIndex, |
|
280 int * ByteIndex, |
|
281 int * BitIndex, |
|
282 int *bitErrorIndication) |
|
283 /* {{-output"vdxGetVopHeader.txt"}} */ |
|
284 { |
|
285 /* Get VOP header */ |
|
286 int ret = vdxGetVopHeader(inBuffer, inpParam, header, |
|
287 ModuloByteIndex, ModuloBitIndex, ByteIndex, BitIndex, |
|
288 bitErrorIndication); |
|
289 |
|
290 return ret; |
|
291 |
|
292 } |
|
293 |
|
294 |
|
295 |
|
296 /* |
|
297 * CopyEditVop |
|
298 * |
|
299 * |
|
300 * Parameters: |
|
301 * hInstance instance handle |
|
302 * |
|
303 * Function: |
|
304 * This function copies the VOP header with edited time stamps of the VOP. |
|
305 * |
|
306 * Returns: |
|
307 * TX error codes |
|
308 */ |
|
309 |
|
310 int CopyEditVop(vdeHInstance_t hInstance, int aNrOfBytesToSkip, bibBuffer_t * inBuffer, |
|
311 vdeDecodeParamters_t *aDecoderInfo) |
|
312 { |
|
313 PRINT((_L("CopyEditVop() begin"))); |
|
314 int StartByteIndex = 0; |
|
315 int StartBitIndex = 7; |
|
316 int16 error; |
|
317 int sncCode; |
|
318 int timeIncByteIndex, timeIncBitIndex; |
|
319 int moduloBaseByteIndex, moduloBaseBitIndex; |
|
320 int vopheaderBitLeft; |
|
321 int numBitChange = 0; |
|
322 int increaseBytes = 0; |
|
323 int stuffingLength = 0; |
|
324 |
|
325 tMPEG4TimeParameter * timeStamp = aDecoderInfo->aMPEG4TimeStamp; |
|
326 MPEG4TimeParameter CurNewTimeCode; |
|
327 |
|
328 int outTirDecreased = 0; |
|
329 int outputTimeResolution = *aDecoderInfo->aMPEG4TargetTimeResolution; |
|
330 int numOutputTrBits; |
|
331 for (numOutputTrBits = 1; ((outputTimeResolution-1) >> numOutputTrBits) != 0; numOutputTrBits++) |
|
332 { |
|
333 } |
|
334 |
|
335 int num_bits; |
|
336 vdxGetVopHeaderInputParam_t inpParam; |
|
337 vdxVopHeader_t vopheader; |
|
338 int bitErrorIndication; |
|
339 vdeInstance_t * vdeTemp = (vdeInstance_t *)hInstance; |
|
340 bibBuffer_t *outBuffer = vdeTemp->outBuffer; |
|
341 bibBufferEdit_t * bufEdit = vdeTemp->bufEdit; |
|
342 |
|
343 int FrameSizeInByte = outBuffer->numBytesRead; |
|
344 bibRewindBits(bibNumberOfFlushedBits(inBuffer),inBuffer,&error); |
|
345 bibRewindBits(bibNumberOfFlushedBits(outBuffer),outBuffer,&error); |
|
346 if ( aNrOfBytesToSkip > 0 ) |
|
347 { |
|
348 // VOS header is already in the beginning of the output buffer |
|
349 bibForwardBits(aNrOfBytesToSkip<<3, outBuffer); |
|
350 // need to also skip the VOS header from input |
|
351 } |
|
352 bufEdit->copyMode = CopyWhole; /* CopyWhole - default */ |
|
353 |
|
354 /* record position */ |
|
355 StartByteIndex = inBuffer->numBytesRead; |
|
356 StartBitIndex = inBuffer->bitIndex; |
|
357 |
|
358 /* get time increment resolution */ |
|
359 vdcInstance_t * vdcTemp = (vdcInstance_t *)(vdeTemp->vdcHInstance); |
|
360 int currentTimeIncResolution = vdcTemp->pictureParam.time_increment_resolution > 0? vdcTemp->pictureParam.time_increment_resolution : outputTimeResolution; |
|
361 inpParam.time_increment_resolution = currentTimeIncResolution; |
|
362 |
|
363 /* find the next vop start code */ |
|
364 do |
|
365 { |
|
366 sncCode = sncSeekMPEGStartCode(inBuffer, vdcTemp->pictureParam.fcode_forward, vdcTemp->pictureParam.error_res_disable, 0, &error); |
|
367 bibForwardBits(32,inBuffer); // one start code is found, move on |
|
368 if(inBuffer->bitsLeft <= 0) |
|
369 { |
|
370 return TX_ERR; // did not find any sync code --- vop is corrupted |
|
371 } |
|
372 } |
|
373 while (sncCode != SNC_VOP); |
|
374 bibRewindBits(32,inBuffer, &error); // go back |
|
375 |
|
376 // if we have VOS header in the input, we are now just after it. If aNrOfBytesToSkip > 0, we should not copy it |
|
377 // however, aNrOfBytesToSkip refers to output buffer, so we should not use it when skipping the input |
|
378 if ( aNrOfBytesToSkip > 0 ) |
|
379 { |
|
380 StartByteIndex = inBuffer->numBytesRead; |
|
381 StartBitIndex = inBuffer->bitIndex; |
|
382 } |
|
383 |
|
384 /* read vop header */ |
|
385 GetTimeIncPosition(inBuffer, &inpParam, &vopheader, |
|
386 &moduloBaseByteIndex, &moduloBaseBitIndex, &timeIncByteIndex, |
|
387 &timeIncBitIndex, &bitErrorIndication); |
|
388 |
|
389 /* record the header end; */ |
|
390 vopheaderBitLeft = inBuffer->bitsLeft; |
|
391 |
|
392 /* copy-edit the part from the begin to the end of modulo base */ |
|
393 CurNewTimeCode = *timeStamp; |
|
394 |
|
395 if (CurNewTimeCode.modulo_time_base != vopheader.time_base_incr) |
|
396 { |
|
397 if (!bufEdit->editParams) |
|
398 { |
|
399 bufEdit->editParams = (bibEditParams_t *) malloc(sizeof(bibEditParams_t)); |
|
400 if(!bufEdit->editParams) |
|
401 { |
|
402 //Memory not available |
|
403 return TX_ERR; //indicating error; |
|
404 } |
|
405 else |
|
406 { |
|
407 bufEdit->numChanges = 1; |
|
408 } |
|
409 } |
|
410 bufEdit->copyMode = CopyWithEdit; /* CopyWithEdit */ |
|
411 bufEdit->editParams->curNumBits = vopheader.time_base_incr + 1; |
|
412 bufEdit->editParams->newNumBits = CurNewTimeCode.modulo_time_base + 1; |
|
413 bufEdit->editParams->newValue = ((1 << CurNewTimeCode.modulo_time_base) - 1) << 1; |
|
414 bufEdit->editParams->StartByteIndex = moduloBaseByteIndex; |
|
415 bufEdit->editParams->StartBitIndex = moduloBaseBitIndex; |
|
416 numBitChange += bufEdit->editParams->newNumBits - bufEdit->editParams->curNumBits; |
|
417 } |
|
418 else |
|
419 { |
|
420 bufEdit->copyMode = CopyWhole; /* CopyWithEdit */ |
|
421 } |
|
422 /* set the end of copy point */ |
|
423 bibRewindBits((inBuffer->numBytesRead<<3)+7-inBuffer->bitIndex,inBuffer,&error); |
|
424 bibForwardBits((moduloBaseByteIndex<<3)+7-moduloBaseBitIndex+vopheader.time_base_incr+2, inBuffer); |
|
425 |
|
426 /* copy data */ |
|
427 CopyStream(inBuffer,outBuffer,bufEdit,StartByteIndex,StartBitIndex); |
|
428 StartByteIndex=inBuffer->getIndex; |
|
429 StartBitIndex=inBuffer->bitIndex; |
|
430 bufEdit->copyMode = CopyWhole; /* CopyWhole */ |
|
431 |
|
432 /* copy and edit until the end of Vop header */ |
|
433 if (currentTimeIncResolution != outputTimeResolution /* && volheader.time_increment_resolution != 30 */ |
|
434 || vopheader.time_inc != CurNewTimeCode.time_inc) |
|
435 { |
|
436 for (num_bits = 1; ((currentTimeIncResolution-1) >> num_bits) != 0; num_bits++) |
|
437 { |
|
438 } |
|
439 /* prepare editing position */ |
|
440 if (!bufEdit->editParams) |
|
441 { |
|
442 bufEdit->editParams = (bibEditParams_t *) malloc(sizeof(bibEditParams_t)); |
|
443 if(!bufEdit->editParams) |
|
444 { |
|
445 //Memory not available |
|
446 return TX_ERR; //indicating error no memory; |
|
447 } |
|
448 else |
|
449 { |
|
450 bufEdit->numChanges = 1; |
|
451 } |
|
452 |
|
453 } |
|
454 bufEdit->copyMode = CopyWithEdit; /* CopyWithEdit */ |
|
455 bufEdit->editParams->StartByteIndex = timeIncByteIndex; |
|
456 bufEdit->editParams->StartBitIndex = timeIncBitIndex; |
|
457 bufEdit->editParams->curNumBits = num_bits; |
|
458 bufEdit->editParams->newNumBits = numOutputTrBits; |
|
459 bufEdit->editParams->newValue = vopheader.time_inc; |
|
460 |
|
461 /* update time increment */ |
|
462 if (vopheader.time_inc != CurNewTimeCode.time_inc) |
|
463 { |
|
464 /*bufEdit->editParams->newValue = (int)(vopheader.time_inc * (float)outputTimeResolution / |
|
465 (float)currentTimeIncResolution + 0.5); //CurNewTimeCode.time_inc; |
|
466 */ |
|
467 bufEdit->editParams->newValue = CurNewTimeCode.time_inc; |
|
468 } |
|
469 numBitChange += bufEdit->editParams->newNumBits - bufEdit->editParams->curNumBits; |
|
470 } |
|
471 |
|
472 /* set the copy end point to the end of vop header */ |
|
473 bibForwardBits(inBuffer->bitsLeft - vopheaderBitLeft, inBuffer); |
|
474 |
|
475 /* copy data */ |
|
476 CopyStream(inBuffer,outBuffer,bufEdit,StartByteIndex,StartBitIndex); |
|
477 StartByteIndex=inBuffer->getIndex; |
|
478 StartBitIndex=inBuffer->bitIndex; |
|
479 |
|
480 if ( vdcTemp->pictureParam.error_res_disable && (inBuffer->bitsLeft > 40) ) // 40 as below to avoid negative values below |
|
481 { |
|
482 // there are no VP headers => no need to search for VP start codes => can jump to the end. |
|
483 // 40 = 5 bytes; in the end there is a start code that has 4 bytes |
|
484 bibForwardBits( inBuffer->bitsLeft-40 ,inBuffer); |
|
485 } |
|
486 |
|
487 PRINT((_L("CopyEditVop() seek sync"))); |
|
488 /* find the next resync marker */ |
|
489 sncCode = sncSeekMPEGStartCode(inBuffer, vopheader.fcode_forward, vdcTemp->pictureParam.error_res_disable, 0, &error); |
|
490 if ( sncCode == SNC_NO_SYNC ) |
|
491 { |
|
492 PRINT((_L("CopyEditVop() sync NOT found, interrupt the copying and return"))); |
|
493 return TX_ERR; |
|
494 } |
|
495 PRINT((_L("CopyEditVop() sync found"))); |
|
496 |
|
497 /* record next resync position */ |
|
498 int resyncBitsLeft = inBuffer->bitsLeft; |
|
499 |
|
500 /* rewind stuffing bits */ |
|
501 sncRewindStuffing(inBuffer, &error); |
|
502 |
|
503 if (!bufEdit->editParams) |
|
504 { |
|
505 bufEdit->editParams = (bibEditParams_t *) malloc(sizeof(bibEditParams_t)); |
|
506 if(!bufEdit->editParams) |
|
507 { |
|
508 //Memory not available |
|
509 return TX_ERR; //indicating error no memory; |
|
510 } |
|
511 else |
|
512 { |
|
513 bufEdit->numChanges = 1; |
|
514 } |
|
515 } |
|
516 |
|
517 /* record position */ |
|
518 bufEdit->editParams->StartByteIndex = inBuffer->getIndex; |
|
519 bufEdit->editParams->StartBitIndex = inBuffer->bitIndex; |
|
520 |
|
521 /* calculate new stuffing bits */ |
|
522 bufEdit->editParams->curNumBits = inBuffer->bitsLeft - resyncBitsLeft; |
|
523 /* calculate number of bits/bytes changed */ |
|
524 if (numBitChange<0) |
|
525 { |
|
526 outTirDecreased = 1; |
|
527 numBitChange = -numBitChange; |
|
528 } |
|
529 int numByteChange = numBitChange >> 3; |
|
530 |
|
531 if (outTirDecreased) |
|
532 { |
|
533 increaseBytes -= numByteChange; |
|
534 stuffingLength = bufEdit->editParams->curNumBits + (numBitChange - (numByteChange << 3)); |
|
535 if (stuffingLength > 8) |
|
536 { |
|
537 stuffingLength -= 8; |
|
538 increaseBytes --; |
|
539 } |
|
540 } |
|
541 else |
|
542 { |
|
543 increaseBytes += numByteChange; |
|
544 stuffingLength = bufEdit->editParams->curNumBits - (numBitChange - (numByteChange << 3)); |
|
545 if (stuffingLength <= 0) |
|
546 { |
|
547 stuffingLength += 8; |
|
548 increaseBytes ++; |
|
549 } |
|
550 } |
|
551 |
|
552 /* adjust the output buffer size */ |
|
553 if (increaseBytes != 0) |
|
554 { |
|
555 outBuffer->size += increaseBytes; |
|
556 if (increaseBytes>=0) |
|
557 { |
|
558 outBuffer->bitsLeft += (increaseBytes << 3); |
|
559 } |
|
560 else |
|
561 { |
|
562 outBuffer->bitsLeft -= ((-increaseBytes) << 3); |
|
563 } |
|
564 } |
|
565 |
|
566 /* update edit statistics */ |
|
567 bufEdit->editParams->newNumBits = stuffingLength; |
|
568 bufEdit->editParams->newValue = stuffingLength>0?(1<<(stuffingLength-1))-1:0; |
|
569 if (stuffingLength != bufEdit->editParams->curNumBits) |
|
570 { |
|
571 bufEdit->copyMode = CopyWithEdit; |
|
572 } |
|
573 |
|
574 bibForwardBits(bufEdit->editParams->curNumBits, inBuffer); |
|
575 /* copy data */ |
|
576 CopyStream(inBuffer,outBuffer,bufEdit,StartByteIndex,StartBitIndex); |
|
577 /* record position */ |
|
578 StartByteIndex = inBuffer->getIndex; |
|
579 StartBitIndex = inBuffer->bitIndex; |
|
580 |
|
581 do |
|
582 { |
|
583 /* if it is the start of a video packet, copy it with edit */ |
|
584 if (sncCode == SNC_VIDPACK ) |
|
585 { |
|
586 /* copy video packet with edit */ |
|
587 int retVal = CopyEditVideoPacket(inBuffer, outBuffer, bufEdit, vdcTemp, aDecoderInfo, &vopheader, |
|
588 &sncCode, &StartByteIndex, &StartBitIndex); |
|
589 if(retVal<0) |
|
590 { |
|
591 //error inside function return error |
|
592 return TX_ERR; |
|
593 } |
|
594 } |
|
595 else if (sncCode == SNC_EOB || sncCode == SNC_EOS || sncCode == SNC_GOV) |
|
596 { |
|
597 // since it is EOB, so end of sequence has occurred, so no more data, so exit |
|
598 break; |
|
599 } |
|
600 } |
|
601 while(sncCode != SNC_VOP); |
|
602 |
|
603 /* copy the rest of bits */ |
|
604 if ((int)inBuffer->numBytesRead < FrameSizeInByte) |
|
605 { |
|
606 bufEdit->copyMode = CopyWhole; |
|
607 bibForwardBits((FrameSizeInByte-StartByteIndex)<<3, inBuffer); |
|
608 CopyStream(inBuffer,outBuffer,bufEdit,StartByteIndex,StartBitIndex); |
|
609 } |
|
610 |
|
611 PRINT((_L("CopyEditVop() end"))); |
|
612 return TX_OK; |
|
613 } |
|
614 |
|
615 |
|
616 /* |
|
617 * CopyEditVideoPacket |
|
618 * |
|
619 * |
|
620 * Parameters: |
|
621 * |
|
622 * Function: |
|
623 * This function copies the video packet with edited time stamps, if HEC is enabled |
|
624 * |
|
625 * Returns: |
|
626 * TX error codes |
|
627 */ |
|
628 |
|
629 int CopyEditVideoPacket(bibBuffer_t* aInBuffer, |
|
630 bibBuffer_t* aOutBuffer, |
|
631 bibBufferEdit_t* aBufEdit, |
|
632 vdcInstance_t * aVdcTemp, |
|
633 vdeDecodeParamters_t* aDecoderInfo, |
|
634 vdxVopHeader_t* aVopheader, |
|
635 int* aSncCode, |
|
636 int* aStartByteIndex, |
|
637 int* aStartBitIndex) |
|
638 { |
|
639 int16 error = 0; |
|
640 int value = 0; |
|
641 int bitsGot = 0; |
|
642 int num_bits = 0; |
|
643 int *bitErrorIndication = 0; |
|
644 int numOutputTrBits = 0; |
|
645 int resyncMarkerLength = 0; |
|
646 int numMBs = 0; |
|
647 int mbNumberLength = 0; |
|
648 int startByteIndex = *aStartByteIndex; |
|
649 int startBitIndex = *aStartBitIndex; |
|
650 int currentTimeIncResolution = 0; |
|
651 int outputTimeResolution = 0; |
|
652 MPEG4TimeParameter curNewTimeCode; |
|
653 MPEG4TimeParameter* timeStamp = aDecoderInfo->aMPEG4TimeStamp; |
|
654 |
|
655 int numBitChange = 0; |
|
656 int increaseBytes = 0; |
|
657 int stuffingLength = 0; |
|
658 int outTirDecreased = 0; |
|
659 |
|
660 currentTimeIncResolution = aVdcTemp->pictureParam.time_increment_resolution > 0? aVdcTemp->pictureParam.time_increment_resolution : 30000; |
|
661 outputTimeResolution = *aDecoderInfo->aMPEG4TargetTimeResolution; |
|
662 for (numOutputTrBits=1; ((outputTimeResolution-1)>>numOutputTrBits)!=0; numOutputTrBits++) |
|
663 { |
|
664 } |
|
665 /* evaluate resync marker length */ |
|
666 resyncMarkerLength = (aVopheader->coding_type == 0 ? 17 : 16+aVopheader->fcode_forward); |
|
667 /* evaluate MB number length */ |
|
668 numMBs = ((aVdcTemp->pictureParam.lumWidth+15)>>4) * ((aVdcTemp->pictureParam.lumHeight+15)>>4); |
|
669 for (mbNumberLength = 1; ((numMBs-1) >> mbNumberLength) != 0; mbNumberLength++) |
|
670 { |
|
671 } |
|
672 |
|
673 value = bibGetBits(resyncMarkerLength, aInBuffer, &bitsGot, bitErrorIndication, &error); // resync marker |
|
674 value = bibGetBits(mbNumberLength, aInBuffer, &bitsGot, bitErrorIndication, &error); // mb number |
|
675 value = bibGetBits(5, aInBuffer, &bitsGot, bitErrorIndication, &error); // quant scale |
|
676 value = bibGetBits(1, aInBuffer, &bitsGot, bitErrorIndication, &error); // header extension code |
|
677 |
|
678 /* if HEC enabled, copy edit time increment fields in the video packet */ |
|
679 if (value == 1) |
|
680 { |
|
681 /* copy-edit the part from the begin to the end of modulo base */ |
|
682 curNewTimeCode = *timeStamp; |
|
683 |
|
684 if (curNewTimeCode.modulo_time_base != aVopheader->time_base_incr) |
|
685 { |
|
686 if (!aBufEdit->editParams) |
|
687 { |
|
688 aBufEdit->editParams = (bibEditParams_t *) malloc(sizeof(bibEditParams_t)); |
|
689 if(!aBufEdit->editParams) |
|
690 { |
|
691 //Memory not available |
|
692 return TX_ERR; //indicating error no memory; |
|
693 } |
|
694 else |
|
695 { |
|
696 aBufEdit->numChanges = 1; |
|
697 } |
|
698 } |
|
699 aBufEdit->copyMode = CopyWithEdit; /* CopyWithEdit */ |
|
700 aBufEdit->editParams->curNumBits = aVopheader->time_base_incr + 1; |
|
701 aBufEdit->editParams->newNumBits = curNewTimeCode.modulo_time_base + 1; |
|
702 aBufEdit->editParams->newValue = ((1 << curNewTimeCode.modulo_time_base) - 1) << 1; |
|
703 aBufEdit->editParams->StartByteIndex = aInBuffer->getIndex; |
|
704 aBufEdit->editParams->StartBitIndex = aInBuffer->bitIndex; |
|
705 numBitChange += aBufEdit->editParams->newNumBits - aBufEdit->editParams->curNumBits; |
|
706 } |
|
707 else |
|
708 { |
|
709 aBufEdit->copyMode = CopyWhole; /* CopyWithEdit */ |
|
710 } |
|
711 /* set the end of copy point */ |
|
712 bibForwardBits(aVopheader->time_base_incr+2, aInBuffer); // includes one bit for Marker |
|
713 |
|
714 /* copy data */ |
|
715 CopyStream(aInBuffer,aOutBuffer,aBufEdit,startByteIndex,startBitIndex); |
|
716 startByteIndex = aInBuffer->getIndex; |
|
717 startBitIndex = aInBuffer->bitIndex; |
|
718 aBufEdit->copyMode = CopyWhole; /* CopyWhole */ |
|
719 |
|
720 /* copy and edit 'time increment' field */ |
|
721 if (currentTimeIncResolution != outputTimeResolution /* && volheader.time_increment_resolution != 30 */ |
|
722 || aVopheader->time_inc != curNewTimeCode.time_inc) |
|
723 { |
|
724 for (num_bits = 1; ((currentTimeIncResolution-1) >> num_bits) != 0; num_bits++) |
|
725 { |
|
726 } |
|
727 |
|
728 /* prepare editing position */ |
|
729 if (!aBufEdit->editParams) |
|
730 { |
|
731 aBufEdit->editParams = (bibEditParams_t *) malloc(sizeof(bibEditParams_t)); |
|
732 if(!aBufEdit->editParams) |
|
733 { |
|
734 //Memory not available |
|
735 return TX_ERR; //indicating error no memory; |
|
736 } |
|
737 else |
|
738 { |
|
739 aBufEdit->numChanges = 1; |
|
740 } |
|
741 } |
|
742 aBufEdit->copyMode = CopyWithEdit; /* CopyWithEdit */ |
|
743 aBufEdit->editParams->StartByteIndex = aInBuffer->getIndex; |
|
744 aBufEdit->editParams->StartBitIndex = aInBuffer->bitIndex; |
|
745 aBufEdit->editParams->curNumBits = num_bits; |
|
746 aBufEdit->editParams->newNumBits = numOutputTrBits; |
|
747 aBufEdit->editParams->newValue = aDecoderInfo->aMPEG4TimeStamp->time_inc; |
|
748 |
|
749 /* move to end position of 'time increment' field */ |
|
750 bibForwardBits(num_bits, aInBuffer); // move to end of 'time increment' field |
|
751 /* update time increment */ |
|
752 if (aVopheader->time_inc != curNewTimeCode.time_inc) |
|
753 { |
|
754 aBufEdit->editParams->newValue = curNewTimeCode.time_inc; |
|
755 } |
|
756 numBitChange += aBufEdit->editParams->newNumBits - aBufEdit->editParams->curNumBits; |
|
757 } |
|
758 |
|
759 /* copy time increment field with edit */ |
|
760 CopyStream(aInBuffer,aOutBuffer,aBufEdit,startByteIndex,startBitIndex); |
|
761 startByteIndex=aInBuffer->getIndex; |
|
762 startBitIndex=aInBuffer->bitIndex; |
|
763 |
|
764 } |
|
765 |
|
766 /* copy rest of video packet */ |
|
767 |
|
768 /* find the next resync marker */ |
|
769 *aSncCode = sncSeekMPEGStartCode(aInBuffer, aVopheader->fcode_forward, 0 /* VPs used*/, 0, &error); |
|
770 |
|
771 /* record next resync position */ |
|
772 int resyncBitsLeft = aInBuffer->bitsLeft; |
|
773 |
|
774 /* rewind stuffing bits */ |
|
775 sncRewindStuffing(aInBuffer, &error); |
|
776 |
|
777 if (!aBufEdit->editParams) |
|
778 { |
|
779 aBufEdit->editParams = (bibEditParams_t *) malloc(sizeof(bibEditParams_t)); |
|
780 if(!aBufEdit->editParams) |
|
781 { |
|
782 //Memory not available |
|
783 return TX_ERR; //indicating error no memory; |
|
784 } |
|
785 else |
|
786 { |
|
787 aBufEdit->numChanges = 1; |
|
788 } |
|
789 } |
|
790 |
|
791 /* record position */ |
|
792 aBufEdit->editParams->StartByteIndex = aInBuffer->getIndex; |
|
793 aBufEdit->editParams->StartBitIndex = aInBuffer->bitIndex; |
|
794 |
|
795 /* calculate new stuffing bits */ |
|
796 aBufEdit->editParams->curNumBits = aInBuffer->bitsLeft - resyncBitsLeft; |
|
797 |
|
798 /* calculate number of bits/bytes changed */ |
|
799 if (numBitChange<0) |
|
800 { |
|
801 outTirDecreased = 1; |
|
802 numBitChange = -numBitChange; |
|
803 } |
|
804 int numByteChange = numBitChange >> 3; |
|
805 |
|
806 /* evaluate change in buffer size */ |
|
807 if (outTirDecreased) |
|
808 { |
|
809 increaseBytes -= numByteChange; |
|
810 stuffingLength = aBufEdit->editParams->curNumBits + (numBitChange - (numByteChange << 3)); |
|
811 if (stuffingLength > 8) |
|
812 { |
|
813 stuffingLength -= 8; |
|
814 increaseBytes --; |
|
815 } |
|
816 } |
|
817 else |
|
818 { |
|
819 increaseBytes += numByteChange; |
|
820 stuffingLength = aBufEdit->editParams->curNumBits - (numBitChange - (numByteChange << 3)); |
|
821 if (stuffingLength <= 0) |
|
822 { |
|
823 stuffingLength += 8; |
|
824 increaseBytes ++; |
|
825 } |
|
826 } |
|
827 |
|
828 /* adjust the output buffer size */ |
|
829 if (increaseBytes != 0) |
|
830 { |
|
831 aOutBuffer->size += increaseBytes; |
|
832 if (increaseBytes>=0) |
|
833 { |
|
834 aOutBuffer->bitsLeft += (increaseBytes << 3); |
|
835 } |
|
836 else |
|
837 { |
|
838 aOutBuffer->bitsLeft -= ((-increaseBytes) << 3); |
|
839 } |
|
840 } |
|
841 /* update edit statistics */ |
|
842 aBufEdit->editParams->newNumBits = stuffingLength; |
|
843 aBufEdit->editParams->newValue = stuffingLength>0?(1<<(stuffingLength-1))-1:0; |
|
844 if (stuffingLength != aBufEdit->editParams->curNumBits) |
|
845 { |
|
846 aBufEdit->copyMode = CopyWithEdit; // copy with edit |
|
847 } |
|
848 else |
|
849 { |
|
850 aBufEdit->copyMode = CopyWhole; // copy whole |
|
851 } |
|
852 |
|
853 bibForwardBits(aBufEdit->editParams->curNumBits, aInBuffer); |
|
854 /* copy video packet with stuffing bits edited */ |
|
855 CopyStream(aInBuffer, aOutBuffer, aBufEdit, startByteIndex, startBitIndex); |
|
856 /* record position */ |
|
857 startByteIndex = aInBuffer->getIndex; |
|
858 startBitIndex = aInBuffer->bitIndex; |
|
859 |
|
860 /* update position for return */ |
|
861 *aStartByteIndex = startByteIndex; |
|
862 *aStartBitIndex = startBitIndex; |
|
863 |
|
864 return TX_OK; |
|
865 } |
|
866 |
|
867 |
|
868 /* |
|
869 * sPutBits |
|
870 * |
|
871 * Parameters: |
|
872 * outBuf output buffer |
|
873 * numBits number of bits to output |
|
874 * value new value |
|
875 * |
|
876 * Function: |
|
877 * Wrapper to sPutBits |
|
878 * Returns: |
|
879 * None. |
|
880 * Error codes: |
|
881 * None. |
|
882 * |
|
883 */ |
|
884 void vdtPutBits (void *buf, int numBits, unsigned int value) |
|
885 { |
|
886 /* must be in this type! "void" is used here only because of the interface with vlb.cpp */ |
|
887 sPutBits ((bibBuffer_t *)(buf), numBits, value); |
|
888 } |
|
889 |
|
890 |
|
891 |
|
892 /* {{-output"vdtCopyBuffer.txt"}} */ |
|
893 /* |
|
894 * vdtCopyBuffer |
|
895 * |
|
896 * Parameters: |
|
897 * |
|
898 * Function: |
|
899 * This function copies some data from source buffer to destination buffer |
|
900 * Returns: |
|
901 * None. |
|
902 * Error codes: |
|
903 * None. |
|
904 * |
|
905 */ |
|
906 void vdtCopyBuffer(bibBuffer_t *SrcBuffer,bibBuffer_t *DestBuffer, |
|
907 int ByteStart,int BitStart, int ByteEnd, int BitEnd) |
|
908 { |
|
909 int startByteIndex = SrcBuffer->getIndex; |
|
910 int startBitIndex = SrcBuffer->bitIndex; |
|
911 int bitsLeft = SrcBuffer->bitsLeft; |
|
912 int numBytesRead = SrcBuffer->numBytesRead; |
|
913 |
|
914 CopyBuffer(SrcBuffer,DestBuffer, ByteStart, BitStart, ByteEnd, BitEnd); |
|
915 |
|
916 /* recover the postion */ |
|
917 SrcBuffer->getIndex = startByteIndex ; |
|
918 SrcBuffer->bitIndex = startBitIndex; |
|
919 SrcBuffer->bitsLeft = bitsLeft; |
|
920 SrcBuffer->numBytesRead = numBytesRead; |
|
921 } |
|
922 |
|
923 |
|
924 |
|
925 |
|
926 /* {{-output"vdtStuffBitsMPEG4.txt"}} */ |
|
927 /* |
|
928 * vdtStuffBitsMPEG4 |
|
929 * |
|
930 * Parameters: |
|
931 * outBuf output buffer |
|
932 * |
|
933 * Function: |
|
934 * This function puts some stuffing bits to the output buffer |
|
935 * bits need to be stuffed in the output buffer at the end of vp in all cases (bw or not) |
|
936 * Returns: |
|
937 * None. |
|
938 * Error codes: |
|
939 * None. |
|
940 * |
|
941 */ |
|
942 void vdtStuffBitsMPEG4(bibBuffer_t *outBuffer) |
|
943 { |
|
944 const int stuffingBits[8][2] = { {1,0}, {2,1}, {3,3}, {4,7}, {5,15}, {6,31}, {7,63}, {8,127} }; |
|
945 VDTASSERT(outBuffer->baseAddr); |
|
946 |
|
947 /* find the number of stuffing bits to insert in the output buffer */ |
|
948 int bi = outBuffer->bitIndex; |
|
949 int newNumBits = stuffingBits[bi][0]; |
|
950 int newValue = stuffingBits[bi][1]; |
|
951 sPutBits(outBuffer, newNumBits, newValue); |
|
952 |
|
953 return; |
|
954 } |
|
955 |
|
956 |
|
957 /*************************************************************/ |
|
958 |
|
959 |
|
960 /* {{-output"sResetH263IntraDcUV.txt"}} */ |
|
961 /* |
|
962 * sResetH263IntraDcUV |
|
963 * |
|
964 * Parameters: output buffer |
|
965 * uValue |
|
966 * vValue |
|
967 * |
|
968 * Function: |
|
969 * This function reset the chrominace INTRADC when black and white color effect is applied |
|
970 * Returns: |
|
971 * none |
|
972 * Error codes: |
|
973 * None. |
|
974 * |
|
975 */ |
|
976 inline void sResetH263IntraDcUV(bibBuffer_t *DestBuffer, TInt uValue, TInt vValue) |
|
977 { |
|
978 /* For the Color Effects Fill the U and V buffers with the |
|
979 corresponding color values */ |
|
980 |
|
981 sPutBits(DestBuffer, 8, uValue); |
|
982 sPutBits(DestBuffer, 8, vValue); |
|
983 } |
|
984 |
|
985 |
|
986 /* {{-output"vdtGetPMBBlackAndWhiteMCBPC.txt"}} */ |
|
987 /* |
|
988 * vdtGetPMBBlackAndWhiteMCBPC |
|
989 * |
|
990 * Parameters: |
|
991 * |
|
992 * Function: |
|
993 * This function compute the new mcbpc for black and white effect * |
|
994 * Returns: |
|
995 * the length of the input mcbpc. |
|
996 * Error codes: |
|
997 * None. |
|
998 * |
|
999 */ |
|
1000 int vdtGetPMBBlackAndWhiteMCBPC(int& new_len, int& new_val, int mcbpc) |
|
1001 { |
|
1002 int cur_index, new_index, cur_len; |
|
1003 |
|
1004 const tVLCTable sCBPCPType[21] = |
|
1005 { |
|
1006 {1, 1}, {3, 4}, {2, 4}, {5, 6}, |
|
1007 {3, 3}, {7, 7}, {6, 7}, {5, 9}, |
|
1008 {2, 3}, {5, 7}, {4, 7}, {5, 8}, |
|
1009 {3, 5}, {4, 8}, {3, 8}, {3, 7}, |
|
1010 {4, 6}, {4, 9}, {3, 9}, {2, 9}, |
|
1011 {1, 9} |
|
1012 }; |
|
1013 |
|
1014 /* evaluate MCBPC parameters */ |
|
1015 int cur_cbpc = mcbpc & 3; |
|
1016 int new_cbpc = 0; // cpbc=0 indicates chroma is 0 |
|
1017 int mbType; |
|
1018 |
|
1019 mbType = mcbpc / 4; |
|
1020 /* evaluate indices in table */ |
|
1021 cur_index = mbType * 4 + cur_cbpc; |
|
1022 new_index = mbType * 4 + new_cbpc; |
|
1023 |
|
1024 /* retrieve values */ |
|
1025 cur_len = sCBPCPType[cur_index].length; |
|
1026 new_len = sCBPCPType[new_index].length; |
|
1027 new_val = sCBPCPType[new_index].code; |
|
1028 |
|
1029 return cur_len; |
|
1030 } |
|
1031 |
|
1032 |
|
1033 /* {{-output"vdtGetIMBBlackAndWhiteMCBPC.txt"}} */ |
|
1034 /* |
|
1035 * vdtGetIMBBlackAndWhiteMCBPC |
|
1036 * |
|
1037 * Parameters: None |
|
1038 * |
|
1039 * Function: |
|
1040 * This function compute the new mcbpc for black and white effect |
|
1041 * Returns: |
|
1042 * the length of the input mcbpc. |
|
1043 * Error codes: |
|
1044 * None. |
|
1045 * |
|
1046 */ |
|
1047 int vdtGetIMBBlackAndWhiteMCBPC(int& new_len, int& new_val, int mcbpc) |
|
1048 { |
|
1049 int cur_index, new_index, cur_len; |
|
1050 |
|
1051 const tVLCTable sCBPCIType[9] = |
|
1052 { |
|
1053 {1, 1}, {1, 3}, {2, 3}, {3, 3}, {1, 4}, |
|
1054 {1, 6}, {2, 6}, {3, 6}, {1, 9} |
|
1055 }; |
|
1056 |
|
1057 /* evaluate MCBPC parameters */ |
|
1058 int cur_cbpc = mcbpc & 3; |
|
1059 int new_cbpc = 0; // cpbc=0 indicates chroma is 0 |
|
1060 int mbType = (mcbpc <4)?3:4; |
|
1061 |
|
1062 /* evaluate indices in table */ |
|
1063 cur_index = (mbType == 3 ? 0 : 4) + cur_cbpc; |
|
1064 new_index = (mbType == 3 ? 0 : 4) + new_cbpc; |
|
1065 |
|
1066 /* retrieve values */ |
|
1067 cur_len = sCBPCIType[cur_index].length; |
|
1068 new_len = sCBPCIType[new_index].length; |
|
1069 new_val = sCBPCIType[new_index].code; |
|
1070 |
|
1071 return cur_len; |
|
1072 } |
|
1073 |
|
1074 |
|
1075 |
|
1076 |
|
1077 |
|
1078 /* {{-output"vdtGetVideoBitstreamInfo.txt"}} */ |
|
1079 /* |
|
1080 * vdtGetVideoBitstreamInfo |
|
1081 * |
|
1082 * Parameters: |
|
1083 * |
|
1084 * Function: |
|
1085 * This function provides the bitstream info to the processor * |
|
1086 * Returns: |
|
1087 * VDE error codes |
|
1088 * Error codes: |
|
1089 * None. |
|
1090 * |
|
1091 */ |
|
1092 int vdtGetVideoBitstreamInfo(bibBuffer_t *inBuffer, vdeDecodeParamters_t *aInfoOut, int *aByteIndex, int *aBitIndex) |
|
1093 { |
|
1094 int numBitsGot, |
|
1095 bitErrorIndication = 0; |
|
1096 int16 error = 0; |
|
1097 u_int32 bits; |
|
1098 int timeResolution = 0; |
|
1099 TVedVideoBitstreamMode streamMode = EVedVideoBitstreamModeUnknown; |
|
1100 vdxVolHeader_t volHeader; |
|
1101 volHeader.user_data = NULL; |
|
1102 |
|
1103 bits = bibShowBits(32, inBuffer, &numBitsGot, &bitErrorIndication, &error); |
|
1104 if (error) |
|
1105 { |
|
1106 streamMode = EVedVideoBitstreamModeUnknown; |
|
1107 goto exitFunction; |
|
1108 } |
|
1109 /* If PSC */ |
|
1110 if ((bits >> 10) == 32) { |
|
1111 streamMode = EVedVideoBitstreamModeH263; |
|
1112 } |
|
1113 |
|
1114 /* Else check for Visual Sequence, Visual Object or Video Object start code */ |
|
1115 else if ((bits == MP4_VOS_START_CODE) || |
|
1116 (bits == MP4_VO_START_CODE) || |
|
1117 ((bits >> MP4_VID_ID_CODE_LENGTH) == MP4_VID_START_CODE) || |
|
1118 ((bits >> MP4_VOL_ID_CODE_LENGTH) == MP4_VOL_START_CODE)) |
|
1119 { |
|
1120 |
|
1121 /* read the Stream headers from the bitstream */ |
|
1122 if ((vdxGetVolHeader(inBuffer, &volHeader, &bitErrorIndication, 1, aByteIndex, aBitIndex, NULL) != 0) || |
|
1123 (bitErrorIndication != 0)) |
|
1124 { |
|
1125 goto exitFunction; |
|
1126 } |
|
1127 |
|
1128 timeResolution = volHeader.time_increment_resolution; |
|
1129 streamMode = sGetMPEG4Mode(volHeader.error_res_disable, volHeader.data_partitioned, volHeader.reversible_vlc); |
|
1130 bits = bibShowBits(22, inBuffer, &numBitsGot, &bitErrorIndication, &error); |
|
1131 if (error) |
|
1132 goto exitFunction; |
|
1133 |
|
1134 /* Check if H.263 PSC follows the VOL header, in which case this is |
|
1135 MPEG-4 with short header and is decoded as H.263 */ |
|
1136 if ( bits == 32 ) |
|
1137 { |
|
1138 streamMode = EVedVideoBitstreamModeMPEG4ShortHeader; |
|
1139 } |
|
1140 } |
|
1141 |
|
1142 /* Else no H.263 and no MPEG-4 start code detected */ |
|
1143 else { |
|
1144 streamMode = EVedVideoBitstreamModeUnknown; |
|
1145 } |
|
1146 |
|
1147 exitFunction: |
|
1148 /* copy the got user data to the core data structure */ |
|
1149 if (volHeader.user_data != NULL) |
|
1150 { |
|
1151 free(volHeader.user_data); |
|
1152 } |
|
1153 |
|
1154 bibRewindBits( bibNumberOfFlushedBits( inBuffer ), inBuffer, &error ); |
|
1155 aInfoOut->streamMode = streamMode; |
|
1156 aInfoOut->iTimeIncrementResolution = timeResolution; |
|
1157 return TX_OK; |
|
1158 } |
|
1159 |
|
1160 |
|
1161 |
|
1162 |
|
1163 |
|
1164 /* {{-output"vdtGetVideoBitstreamInfo.txt"}} */ |
|
1165 /* |
|
1166 * sQuantizeMB |
|
1167 * |
|
1168 * Parameters: |
|
1169 * mbdata Contains the actual MB data to be quantized |
|
1170 * oldQuant: |
|
1171 * newQuant: |
|
1172 * intra |
|
1173 * |
|
1174 * Function: |
|
1175 * This function requantizes the AC/DCT data for one MB, used in MPEG4 -> H263 transcoding |
|
1176 * Returns: |
|
1177 * Coded Block Pattern. |
|
1178 * Error codes: |
|
1179 * None. |
|
1180 * |
|
1181 */ |
|
1182 static void sQuantizeMB(int *mbdata, int oldQuant, int newQuant, int intra, int colorEffect) |
|
1183 { |
|
1184 #define SIGN(x) (((x)<0) ? -1:1 ) |
|
1185 int coeffCnt; |
|
1186 int *block; |
|
1187 int blkCnt; |
|
1188 |
|
1189 for (blkCnt = 0; blkCnt < (colorEffect ? 4 : 6); blkCnt++) |
|
1190 { |
|
1191 block = &mbdata[blkCnt * BLOCK_COEFF_SIZE]; |
|
1192 for (coeffCnt = (intra == VDX_MB_INTRA); coeffCnt < BLOCK_COEFF_SIZE; |
|
1193 coeffCnt++) |
|
1194 { |
|
1195 if (block[coeffCnt]) |
|
1196 { |
|
1197 int level = abs(block[coeffCnt]); |
|
1198 int sign = SIGN(block[coeffCnt]); |
|
1199 int rcoeff; |
|
1200 // dequantize |
|
1201 if ((oldQuant % 2) == 1) |
|
1202 rcoeff = oldQuant * ((level << 1) + 1); |
|
1203 else |
|
1204 rcoeff = oldQuant * ((level << 1) + 1) - 1; |
|
1205 |
|
1206 rcoeff = min (2047, max (-2048, sign * rcoeff)); |
|
1207 |
|
1208 // requantize |
|
1209 if (intra == VDX_MB_INTRA) |
|
1210 { |
|
1211 level = (abs (rcoeff)) / (newQuant << 1); |
|
1212 } |
|
1213 else |
|
1214 { |
|
1215 level = (abs (rcoeff) - (newQuant >> 1)) / (newQuant << 1); |
|
1216 /* clipping to [-127,+127] */ |
|
1217 } |
|
1218 |
|
1219 /* clipping to [-127,+127] */ |
|
1220 block[coeffCnt] = min (127, max (-127, sign * level)); |
|
1221 } |
|
1222 else |
|
1223 { |
|
1224 /* Nothing */ |
|
1225 } |
|
1226 } |
|
1227 } |
|
1228 return ; |
|
1229 } |
|
1230 |
|
1231 |
|
1232 |
|
1233 |
|
1234 /* {{-output"vdtGetVideoBitstreamInfo.txt"}} */ |
|
1235 /* |
|
1236 * vdtChangeVosHeaderRegResyncL |
|
1237 * |
|
1238 * Parameters: |
|
1239 * |
|
1240 * Function: |
|
1241 * This function finds the error resillence bit and change it if necessary |
|
1242 * to make it Regular Resynchronization mode |
|
1243 * Returns: |
|
1244 * ETrue if buffer changed. |
|
1245 * Error codes: |
|
1246 * None |
|
1247 * |
|
1248 */ |
|
1249 TBool vdtChangeVosHeaderRegResyncL(TPtrC8& aInputBuffer, TUint aBufferSize) |
|
1250 { |
|
1251 int16 errorCode = 0; /* return code for bib functions */ |
|
1252 bibBuffer_t *buffer; /* input buffer */ |
|
1253 |
|
1254 /* Create bit buffer */ |
|
1255 buffer = bibCreate((TAny*)aInputBuffer.Ptr(), aBufferSize, &errorCode); |
|
1256 if (!buffer || errorCode) |
|
1257 return EFalse; |
|
1258 |
|
1259 int startByte = 0, startBit = 7; |
|
1260 vdeDecodeParamters_t decInfo; |
|
1261 vdtGetVideoBitstreamInfo(buffer, &decInfo, &startByte, &startBit); |
|
1262 |
|
1263 if (decInfo.streamMode == EVedVideoBitstreamModeMPEG4Regular) |
|
1264 { |
|
1265 char *temp = (char *) (TAny*)aInputBuffer.Ptr(); |
|
1266 unsigned char patern[8] = {0xFE,0xFD,0xFB,0xF7,0xEF,0xDF,0xBF,0x7F}; |
|
1267 temp[startByte] &= patern[startBit]; // change the error resillence bit to 0; |
|
1268 |
|
1269 /* Delete bit buffer */ |
|
1270 bibDelete(buffer, &errorCode); |
|
1271 return ETrue; |
|
1272 } |
|
1273 else |
|
1274 { |
|
1275 /* Delete bit buffer */ |
|
1276 bibDelete(buffer, &errorCode); |
|
1277 return EFalse; |
|
1278 } |
|
1279 } |
|
1280 |
|
1281 /* |
|
1282 * CMPEG4Transcoder |
|
1283 * |
|
1284 * Parameters: |
|
1285 * |
|
1286 * Function: |
|
1287 * Constructor |
|
1288 * |
|
1289 */ |
|
1290 CMPEG4Transcoder::CMPEG4Transcoder(const vdeInstance_t *aVDEInstance, bibBuffer_t *aInBuffer, bibBuffer_t *aOutBuffer) |
|
1291 { |
|
1292 VDTASSERT(aVDEInstance); |
|
1293 VDTASSERT(aInBuffer); |
|
1294 VDTASSERT(aOutBuffer); |
|
1295 |
|
1296 /* passing the arguments */ |
|
1297 iVDEInstance = aVDEInstance; |
|
1298 iInBuffer = aInBuffer; |
|
1299 iOutBuffer = aOutBuffer; |
|
1300 |
|
1301 /* Color Toning */ |
|
1302 iMBType = NULL; |
|
1303 iCurQuant = 0; |
|
1304 iColorEffect = aVDEInstance->iColorEffect; |
|
1305 iColorToneU = aVDEInstance->iColorToneU; |
|
1306 iColorToneV = aVDEInstance->iColorToneV; |
|
1307 iRefQuant = aVDEInstance->iRefQp; |
|
1308 iDcScaler = GetMpeg4DcScalerUV(iRefQuant); |
|
1309 |
|
1310 iDoModeTranscoding = EFalse; |
|
1311 iDoTranscoding = (iColorEffect || iDoModeTranscoding); |
|
1312 iTargetFormat = EVedVideoTypeMPEG4SimpleProfile; |
|
1313 iStuffingBitsUsed = 0; |
|
1314 |
|
1315 /* default values */ |
|
1316 iLastMBNum = -1; |
|
1317 iCurMBNum = 0; |
|
1318 |
|
1319 /* initialize here but will be changed later to proper value */ |
|
1320 iOutputMpeg4TimeIncResolution = KOutputMpeg4TimeIncResolution; |
|
1321 |
|
1322 iNumMBsInOneVOP = (iVDEInstance->lumHeight * iVDEInstance->lumWidth) >> 8; // /256 |
|
1323 iMBsinWidth = iVDEInstance->lumWidth >> 4; |
|
1324 iNumMBsInGOB = iVDEInstance->lumWidth >> 4; |
|
1325 |
|
1326 |
|
1327 iMBList = NULL; |
|
1328 iH263DCData = NULL; |
|
1329 h263mbi = NULL; |
|
1330 |
|
1331 |
|
1332 iH263MBVPNum = NULL; |
|
1333 iErrorResilienceStartByteIndex = KDataNotValid; |
|
1334 iErrorResilienceStartBitIndex = KDataNotValid; |
|
1335 |
|
1336 iVideoPacketNumInMPEG4 = 0; // the video packet number this MB belongs to, NOTE: the first GOB doesn't have a GOB header |
|
1337 iCurMBNumInVP = -1; |
|
1338 fFirstFrameInH263 = EFalse; |
|
1339 |
|
1340 return; |
|
1341 } |
|
1342 |
|
1343 /* |
|
1344 * ~CMPEG4Transcoder |
|
1345 * |
|
1346 * Parameters: |
|
1347 * |
|
1348 * Function: |
|
1349 * Destructor |
|
1350 * |
|
1351 */ |
|
1352 CMPEG4Transcoder::~CMPEG4Transcoder() |
|
1353 { |
|
1354 if (iCurIMBinstance) |
|
1355 { |
|
1356 free(iCurIMBinstance); |
|
1357 } |
|
1358 if (iCurPMBinstance) |
|
1359 { |
|
1360 free(iCurPMBinstance); |
|
1361 } |
|
1362 if (bufEdit.editParams) |
|
1363 { |
|
1364 free(bufEdit.editParams); |
|
1365 } |
|
1366 |
|
1367 // for H263 |
|
1368 if (iH263MBVPNum) |
|
1369 { |
|
1370 free(iH263MBVPNum); |
|
1371 } |
|
1372 |
|
1373 // for color toning |
|
1374 if (iMBType) |
|
1375 { |
|
1376 free(iMBType); |
|
1377 } |
|
1378 |
|
1379 |
|
1380 |
|
1381 if (iH263DCData) |
|
1382 { |
|
1383 for (int i = 0; i < iNumMBsInOneVOP; i++) |
|
1384 { |
|
1385 free(iH263DCData[i]); |
|
1386 } |
|
1387 free(iH263DCData); |
|
1388 } |
|
1389 |
|
1390 if ( ( (iTargetFormat == EVedVideoTypeH263Profile0Level10) || |
|
1391 (iTargetFormat == EVedVideoTypeH263Profile0Level45) ) && |
|
1392 iBitStreamMode != EVedVideoBitstreamModeMPEG4ShortHeader && |
|
1393 iBitStreamMode != EVedVideoBitstreamModeH263 && |
|
1394 h263mbi) |
|
1395 { |
|
1396 free(h263mbi); |
|
1397 } |
|
1398 |
|
1399 if ( iOutBuffer ) |
|
1400 { |
|
1401 |
|
1402 PRINT((_L("CMPEG4Transcoder: finish one frame successfully, buffer size %d"), |
|
1403 iOutBuffer->getIndex)); |
|
1404 } |
|
1405 |
|
1406 #ifdef _DEBUG |
|
1407 if (iOutBuffer->getIndex > KInitialBufferSize) |
|
1408 { |
|
1409 PRINT((_L("CMPEG4Transcoder: Output buffer size from engine is not big enough! check KInitialBufferSize"))); |
|
1410 |
|
1411 } |
|
1412 #endif |
|
1413 if ( iOutBuffer ) |
|
1414 { |
|
1415 VDTASSERT(iOutBuffer->getIndex < KInitialBufferSize); |
|
1416 } |
|
1417 } |
|
1418 |
|
1419 /* |
|
1420 * H263EscapeCoding |
|
1421 * |
|
1422 * Parameters: |
|
1423 * |
|
1424 * Function: |
|
1425 * Indicates whether escape vlc coding is used in one block |
|
1426 * Returns: |
|
1427 * None |
|
1428 * Error codes: |
|
1429 * None |
|
1430 * |
|
1431 */ |
|
1432 void CMPEG4Transcoder::H263EscapeCoding(int aIndex, int fEscapeCodeUsed) |
|
1433 { |
|
1434 iEscapeCodeUsed[aIndex] = fEscapeCodeUsed; |
|
1435 } |
|
1436 |
|
1437 /* |
|
1438 * SetTranscoding |
|
1439 * |
|
1440 * Parameters: |
|
1441 * |
|
1442 * Function: |
|
1443 * Indicates whether we need to do MPEG4 bitstream transcoding |
|
1444 * Returns: |
|
1445 * TX error codes |
|
1446 * Error codes: |
|
1447 * None |
|
1448 * |
|
1449 */ |
|
1450 int CMPEG4Transcoder::SetTranscoding(vdeDecodeParamters_t *aDecoderInfo) |
|
1451 { |
|
1452 iColorEffect = aDecoderInfo->aColorEffect; |
|
1453 iColorToneU = aDecoderInfo->aColorToneU; |
|
1454 iColorToneV = aDecoderInfo->aColorToneV; |
|
1455 iBitStreamMode = (TVedVideoBitstreamMode)aDecoderInfo->streamMode; |
|
1456 |
|
1457 iTargetFormat = aDecoderInfo->aOutputVideoFormat; |
|
1458 iDoModeTranscoding = aDecoderInfo->fModeChanged ? ETrue: EFalse; |
|
1459 iDoTranscoding = (iColorEffect || iDoModeTranscoding); |
|
1460 |
|
1461 /* set to proper value */ |
|
1462 iOutputMpeg4TimeIncResolution = *(aDecoderInfo->aMPEG4TargetTimeResolution); |
|
1463 |
|
1464 /* allocate buffer for MPEG4 - > H263 transcoding */ |
|
1465 /* the following is used if spatial domain processing is not done */ |
|
1466 |
|
1467 if ( ( (iTargetFormat == EVedVideoTypeH263Profile0Level10) || |
|
1468 (iTargetFormat == EVedVideoTypeH263Profile0Level45) ) && |
|
1469 iBitStreamMode != EVedVideoBitstreamModeMPEG4ShortHeader && |
|
1470 iBitStreamMode != EVedVideoBitstreamModeH263) |
|
1471 { |
|
1472 h263mbi = (tMBInfo*) malloc (sizeof(tMBInfo) * iNumMBsInOneVOP); |
|
1473 if (!h263mbi) |
|
1474 { |
|
1475 PRINT((_L("CMPEG4Transcoder::SetTranscoding - h263mbi creation failed"))); |
|
1476 deb("CMPEG4Transcoder::SetTranscoding - h263mbi creation failed\n"); |
|
1477 |
|
1478 return TX_ERR; |
|
1479 } |
|
1480 memset(h263mbi, 0, sizeof(tMBInfo) * iNumMBsInOneVOP); |
|
1481 } |
|
1482 |
|
1483 return TX_OK; |
|
1484 } |
|
1485 |
|
1486 |
|
1487 |
|
1488 |
|
1489 /* |
|
1490 * BeginOneVideoPacket |
|
1491 * |
|
1492 * Parameters: |
|
1493 * |
|
1494 * Function: |
|
1495 * Records the position before one Video packet is processed |
|
1496 * Returns: |
|
1497 * None |
|
1498 * Error codes: |
|
1499 * None |
|
1500 * |
|
1501 */ |
|
1502 void CMPEG4Transcoder::BeginOneVideoPacket(dvpVPInParam_t *aVPin) |
|
1503 { |
|
1504 VDTASSERT(iInBuffer); |
|
1505 VDTASSERT(aVPin); |
|
1506 |
|
1507 iCurVPIn = aVPin; |
|
1508 iVPStartByteIndex = iInBuffer->getIndex; |
|
1509 iVPStartBitIndex = iInBuffer->bitIndex; |
|
1510 |
|
1511 iCurMBNumInVP = -1; |
|
1512 |
|
1513 iStuffingBitsUsed = 0; |
|
1514 |
|
1515 iVopCodingType = aVPin->pictParam->pictureType; |
|
1516 iBitStreamMode = sGetMPEG4Mode(aVPin->pictParam->error_res_disable, |
|
1517 aVPin->pictParam->data_partitioned, aVPin->pictParam->reversible_vlc); |
|
1518 } |
|
1519 |
|
1520 |
|
1521 /* |
|
1522 * sConstructH263PicHeader |
|
1523 * |
|
1524 * Parameters: |
|
1525 * lBitOut output buffer |
|
1526 * quant quant value to be put in header |
|
1527 * picType VDX_VOP_TYPE_P or VDX_VOP_TYPE_I |
|
1528 * tr time increament |
|
1529 * Function: |
|
1530 * Writes the pic header into bit-stream for one MPEG4 frame |
|
1531 * Returns: |
|
1532 * None |
|
1533 * Error codes: |
|
1534 * None |
|
1535 * |
|
1536 */ |
|
1537 void sConstructH263PicHeader(bibBuffer_t *lBitOut, int picType, int quant, int tr, int aVOPNotCoded, int aFormat) |
|
1538 |
|
1539 { |
|
1540 if (aVOPNotCoded) |
|
1541 { |
|
1542 return; |
|
1543 } |
|
1544 /* ShortVideoStartMarker */ |
|
1545 sPutBits(lBitOut, 22, SHORT_VIDEO_START_MARKER); |
|
1546 /* TemporalReference */ |
|
1547 sPutBits(lBitOut, 8, (tr & 0x000000ff)); |
|
1548 /* Marker Bit */ |
|
1549 sPutBits(lBitOut, 1, MARKER_BIT); |
|
1550 /* Zero Bit */ |
|
1551 sPutBits(lBitOut, 1, 0); |
|
1552 /* SplitScreenIndicator = 0 */ |
|
1553 sPutBits(lBitOut, 1, 0); |
|
1554 /* DocumentCameraIndicator = 0 */ |
|
1555 sPutBits(lBitOut, 1, 0); |
|
1556 /* FullPictureFreezeRelease = 0 */ |
|
1557 sPutBits(lBitOut, 1, 0); |
|
1558 /* Source Fromat */ |
|
1559 sPutBits(lBitOut, 3, aFormat); |
|
1560 /* PictureCodingType 0 for intra, 1 for inter */ |
|
1561 sPutBits(lBitOut, 1, picType == VDX_VOP_TYPE_P); |
|
1562 /* UMV= 0 */ |
|
1563 sPutBits(lBitOut, 1, 0); |
|
1564 /* SAC = 0 */ |
|
1565 sPutBits(lBitOut, 1, 0); |
|
1566 /* Advanced Prediction = 0 */ |
|
1567 sPutBits(lBitOut, 1, 0); |
|
1568 /* PB frame = 0 */ |
|
1569 sPutBits(lBitOut, 1, 0); |
|
1570 /* VOPQuant */ |
|
1571 sPutBits(lBitOut, 5, quant); |
|
1572 /* ZeroBIt */ |
|
1573 sPutBits(lBitOut, 1, 0); |
|
1574 /* Pei = 0 */ |
|
1575 sPutBits(lBitOut, 1, 0); |
|
1576 } |
|
1577 |
|
1578 |
|
1579 /* |
|
1580 * VOPHeaderEnded |
|
1581 * |
|
1582 * Parameters: |
|
1583 * |
|
1584 * Function: |
|
1585 * Copy the VOP Header to output buffer |
|
1586 * Returns: |
|
1587 * None |
|
1588 * Error codes: |
|
1589 * None |
|
1590 * |
|
1591 */ |
|
1592 void CMPEG4Transcoder::VOPHeaderEnded(int aStartByteIndex, int aStartBitIndex, |
|
1593 int aQuant, int aPicType, int aFrameNum, int aVOPNotCoded) |
|
1594 { |
|
1595 const int KNumMbInSqcif = 48; |
|
1596 const int KNumMbInQcif = 99; |
|
1597 const int KNumMbInCif = 396; |
|
1598 |
|
1599 if (iTargetFormat == EVedVideoTypeH263Profile0Level10 || iTargetFormat == EVedVideoTypeH263Profile0Level45) |
|
1600 { |
|
1601 int sourceFormat = 2; // qcif |
|
1602 /* note: other formate not supported */ |
|
1603 if (iNumMBsInOneVOP == KNumMbInSqcif) /* sqcif */ |
|
1604 { |
|
1605 sourceFormat = 1; // sqcif |
|
1606 } |
|
1607 else if (iNumMBsInOneVOP == KNumMbInQcif) /* qcif */ |
|
1608 { |
|
1609 sourceFormat = 2; // qcif |
|
1610 } |
|
1611 else if (iNumMBsInOneVOP == KNumMbInCif) /* cif */ |
|
1612 { |
|
1613 sourceFormat = 3; // cif |
|
1614 } |
|
1615 sConstructH263PicHeader(iOutBuffer, aPicType, aQuant, 0, aVOPNotCoded, sourceFormat); |
|
1616 PRINT((_L("CMPEG4Transcoder: MPEG4 -> H263: picture header generated"))); |
|
1617 } |
|
1618 /* Copy the VOP header */ |
|
1619 else |
|
1620 { |
|
1621 bufEdit.copyMode = CopyWhole; // whole |
|
1622 CopyStream(iInBuffer,iOutBuffer,&bufEdit,aStartByteIndex,aStartBitIndex); |
|
1623 } |
|
1624 iPreQuant = aQuant; |
|
1625 iStuffingBitsUsed = 0; |
|
1626 |
|
1627 iCurQuant = aQuant; |
|
1628 /* Color Toning */ |
|
1629 if (!aFrameNum || !iRefQuant) |
|
1630 { |
|
1631 iRefQuant = iCurQuant; |
|
1632 iDcScaler = GetMpeg4DcScalerUV(iRefQuant); |
|
1633 } |
|
1634 |
|
1635 } |
|
1636 |
|
1637 |
|
1638 /* |
|
1639 * VOPEnded |
|
1640 * |
|
1641 * Parameters: |
|
1642 * |
|
1643 * Function: |
|
1644 * This function is called when one VOP has ended |
|
1645 * Returns: |
|
1646 * None |
|
1647 * Error codes: |
|
1648 * None |
|
1649 * |
|
1650 */ |
|
1651 void CMPEG4Transcoder::VOPEnded() |
|
1652 { |
|
1653 /* check if MBs are lost */ |
|
1654 int dataPartitioned = (iBitStreamMode == EVedVideoBitstreamModeMPEG4DP_RVLC || iBitStreamMode == EVedVideoBitstreamModeMPEG4Resyn_DP_RVLC |
|
1655 || iBitStreamMode == EVedVideoBitstreamModeMPEG4DP || iBitStreamMode == EVedVideoBitstreamModeMPEG4Resyn_DP); |
|
1656 |
|
1657 if (iLastMBNum != iNumMBsInOneVOP - 1 && !(dataPartitioned && !iDoModeTranscoding)) |
|
1658 { |
|
1659 for (int i = iLastMBNum+1; i < iNumMBsInOneVOP; i++) |
|
1660 { |
|
1661 /* output 1 bit COD */ |
|
1662 sPutBits (iOutBuffer, 1, 1); |
|
1663 } |
|
1664 } |
|
1665 |
|
1666 iLastMBNum = iNumMBsInOneVOP - 1; |
|
1667 /* bits need to be stuffed in the output buffer at the end VOP */ |
|
1668 if (!dataPartitioned && iTargetFormat == EVedVideoTypeMPEG4SimpleProfile) |
|
1669 { |
|
1670 if (!iStuffingBitsUsed) |
|
1671 { |
|
1672 vdtStuffBitsMPEG4(iOutBuffer); |
|
1673 } |
|
1674 iStuffingBitsUsed = 1; |
|
1675 } |
|
1676 else if (iTargetFormat == EVedVideoTypeH263Profile0Level10 || iTargetFormat == EVedVideoTypeH263Profile0Level45) |
|
1677 { |
|
1678 sStuffBitsH263(iOutBuffer); |
|
1679 } |
|
1680 |
|
1681 PRINT((_L("CMPEG4Transcoder: VOPEnded. color effect: %d, format convert %d, do transcoding: %d streammode: %d, outputformat: %d "), |
|
1682 iColorEffect, iDoModeTranscoding, iDoTranscoding, iBitStreamMode, iTargetFormat)); |
|
1683 } |
|
1684 |
|
1685 /* |
|
1686 * AfterOneVideoPacketHeader |
|
1687 * |
|
1688 * Parameters: |
|
1689 * |
|
1690 * Function: |
|
1691 * This function is called after retreiving the VP |
|
1692 * Records the position before the content of the video packet is processed |
|
1693 * Returns: |
|
1694 * None |
|
1695 * Error codes: |
|
1696 * None |
|
1697 * |
|
1698 */ |
|
1699 void CMPEG4Transcoder::AfterVideoPacketHeader(dvpVPInOutParam_t *aVPInfo) |
|
1700 { |
|
1701 VDTASSERT(aVPInfo); |
|
1702 iCurVPInOut = aVPInfo; |
|
1703 |
|
1704 iVPHeaderEndByteIndex = iInBuffer->getIndex; |
|
1705 iVPHeaderEndBitIndex = iInBuffer->bitIndex; |
|
1706 |
|
1707 /* Color Toning */ |
|
1708 iCurQuant = aVPInfo->quant; |
|
1709 |
|
1710 /* Copy the VP header to output stream. Note; the first VP does not have a VP header */ |
|
1711 if (iTargetFormat == EVedVideoTypeMPEG4SimpleProfile) |
|
1712 { |
|
1713 bufEdit.copyMode = CopyWhole; /* whole */ |
|
1714 CopyStream(iInBuffer,iOutBuffer,&bufEdit,iVPStartByteIndex,iVPStartBitIndex); |
|
1715 } |
|
1716 } |
|
1717 |
|
1718 |
|
1719 /* |
|
1720 * OneVPEnded |
|
1721 * |
|
1722 * Parameters: |
|
1723 * |
|
1724 * Function: |
|
1725 * This function is called after one VP contents are retrieved |
|
1726 * Returns: |
|
1727 * None |
|
1728 * Error codes: |
|
1729 * None |
|
1730 * |
|
1731 */ |
|
1732 void CMPEG4Transcoder::OneVPEnded() |
|
1733 { |
|
1734 if (!iDoTranscoding) |
|
1735 { |
|
1736 /* no transcoding, copy whole content VP */ |
|
1737 bufEdit.copyMode = CopyWhole; |
|
1738 CopyStream(iInBuffer,iOutBuffer,&bufEdit,iVPHeaderEndByteIndex,iVPHeaderEndBitIndex); |
|
1739 iStuffingBitsUsed = 1;// also stuffing is copied |
|
1740 } |
|
1741 else |
|
1742 { |
|
1743 int dataPartitioned = (iBitStreamMode == EVedVideoBitstreamModeMPEG4DP_RVLC || iBitStreamMode == EVedVideoBitstreamModeMPEG4Resyn_DP_RVLC |
|
1744 || iBitStreamMode == EVedVideoBitstreamModeMPEG4DP || iBitStreamMode == EVedVideoBitstreamModeMPEG4Resyn_DP); |
|
1745 int nextExpectedMBNum = iCurVPInOut->currMBNum; |
|
1746 |
|
1747 if (dataPartitioned && !iDoModeTranscoding) |
|
1748 { |
|
1749 /* if data is partitioned and we are not doing format transcoding, |
|
1750 not coded MBs info is already in data partition 1 |
|
1751 */ |
|
1752 } |
|
1753 else |
|
1754 { |
|
1755 /* MBs are lost or not coded, */ |
|
1756 for (int i = iLastMBNum+1; i < nextExpectedMBNum; i++) |
|
1757 { |
|
1758 /* output 1 bit COD */ |
|
1759 sPutBits (iOutBuffer, 1, 1); |
|
1760 } |
|
1761 } |
|
1762 |
|
1763 iLastMBNum = nextExpectedMBNum - 1; |
|
1764 /* bits need to be stuffed in the output buffer at the end of vp in all cases (bw or not) */ |
|
1765 if (iTargetFormat == EVedVideoTypeMPEG4SimpleProfile) |
|
1766 { |
|
1767 if (!iStuffingBitsUsed) |
|
1768 { |
|
1769 vdtStuffBitsMPEG4(iOutBuffer); |
|
1770 } |
|
1771 iStuffingBitsUsed = 1; |
|
1772 } |
|
1773 } |
|
1774 } |
|
1775 |
|
1776 |
|
1777 |
|
1778 /* |
|
1779 * BeginOneMB |
|
1780 * |
|
1781 * Parameters: |
|
1782 * |
|
1783 * Function: |
|
1784 * Records the position before one MB is processed |
|
1785 * Returns: |
|
1786 * None |
|
1787 * Error codes: |
|
1788 * None |
|
1789 * |
|
1790 */ |
|
1791 void CMPEG4Transcoder::BeginOneMB(int aMBNum) |
|
1792 { |
|
1793 VDTASSERT(iInBuffer); |
|
1794 |
|
1795 iMBStartByteIndex = iInBuffer->getIndex; |
|
1796 iMBStartBitIndex = iInBuffer->bitIndex; |
|
1797 iCurMBNum = aMBNum; |
|
1798 |
|
1799 // Color Toning |
|
1800 iCurMBNumInVP++; |
|
1801 |
|
1802 if ((iBitStreamMode == EVedVideoBitstreamModeMPEG4ShortHeader || iBitStreamMode == EVedVideoBitstreamModeH263) && iDoModeTranscoding) |
|
1803 { |
|
1804 /* H263 -> MPEG4 */ |
|
1805 VDTASSERT(iH263MBVPNum); |
|
1806 iH263MBVPNum[iCurMBNum]= iVideoPacketNumInMPEG4; |
|
1807 } |
|
1808 } |
|
1809 |
|
1810 /* |
|
1811 * BeginOneBlock |
|
1812 * |
|
1813 * Parameters: |
|
1814 * |
|
1815 * Function: |
|
1816 * Records the position before one block in MB is processed |
|
1817 * Returns: |
|
1818 * None |
|
1819 * Error codes: |
|
1820 * None |
|
1821 * |
|
1822 */ |
|
1823 void CMPEG4Transcoder::BeginOneBlock(int aBlockIndex) |
|
1824 { |
|
1825 VDTASSERT(aBlockIndex >= 0 && aBlockIndex < 6); |
|
1826 |
|
1827 iBlockStartByteIndex[aBlockIndex] = iInBuffer->getIndex; |
|
1828 iBlockStartBitIndex[aBlockIndex] = iInBuffer->bitIndex; |
|
1829 } |
|
1830 |
|
1831 |
|
1832 /* |
|
1833 * OneIMBDataStarted |
|
1834 * |
|
1835 * Parameters: |
|
1836 * |
|
1837 * Function: |
|
1838 * This function is called after the MB header is read; start one IMB, |
|
1839 * Returns: |
|
1840 * None |
|
1841 * Error codes: |
|
1842 * None |
|
1843 * |
|
1844 */ |
|
1845 void CMPEG4Transcoder::OneIMBDataStarted(vdxIMBListItem_t *aMBInstance) |
|
1846 { |
|
1847 VDTASSERT(aMBInstance); |
|
1848 VDTASSERT(iCurIMBinstance); |
|
1849 iMBCodingType = VDX_MB_INTRA; |
|
1850 iVopCodingType = VDX_VOP_TYPE_I; |
|
1851 iMBType[iCurMBNum] = iMBCodingType; |
|
1852 |
|
1853 |
|
1854 memcpy(iCurIMBinstance, aMBInstance, sizeof(vdxIMBListItem_t)); |
|
1855 } |
|
1856 |
|
1857 /* |
|
1858 * OnePMBDataStarted |
|
1859 * |
|
1860 * Parameters: |
|
1861 * |
|
1862 * Function: |
|
1863 * This function is called after the MB header is read; start one PMB, |
|
1864 * Returns: |
|
1865 * None |
|
1866 * Error codes: |
|
1867 * None |
|
1868 * |
|
1869 */ |
|
1870 void CMPEG4Transcoder::OnePMBDataStarted(vdxPMBListItem_t *aMBInstance) |
|
1871 { |
|
1872 VDTASSERT(aMBInstance); |
|
1873 VDTASSERT(iCurPMBinstance); |
|
1874 |
|
1875 iMBCodingType = aMBInstance->mbClass; |
|
1876 iVopCodingType = VDX_VOP_TYPE_P; |
|
1877 iMBType[iCurMBNum] = iMBCodingType; |
|
1878 |
|
1879 memcpy(iCurPMBinstance, aMBInstance, sizeof(vdxPMBListItem_t)); |
|
1880 } |
|
1881 |
|
1882 |
|
1883 |
|
1884 /* |
|
1885 * OneIMBDataStartedDataPartitioned |
|
1886 * |
|
1887 * Parameters: |
|
1888 * |
|
1889 * Function: |
|
1890 * Add one IMB instance, It is done after parsing Part1 and Part2 before the block data for current MB |
|
1891 * Returns: |
|
1892 * None |
|
1893 * Error codes: |
|
1894 * None |
|
1895 * |
|
1896 */ |
|
1897 void CMPEG4Transcoder::OneIMBDataStartedDataPartitioned(vdxIMBListItem_t *aMBInstance, dlst_t *aMBList, int aCurrMBNumInVP, int aMBNum) |
|
1898 { |
|
1899 VDTASSERT(aMBInstance); // at this point, the instance should not be null |
|
1900 VDTASSERT(aMBList); |
|
1901 |
|
1902 memcpy(iCurIMBinstance, aMBInstance, sizeof(vdxIMBListItem_t)); |
|
1903 iCurMBNumInVP = aCurrMBNumInVP; |
|
1904 iCurMBNum = aMBNum; |
|
1905 iMBList = aMBList; |
|
1906 iMBCodingType = VDX_MB_INTRA; |
|
1907 iVopCodingType = VDX_VOP_TYPE_I; |
|
1908 iMBType[iCurMBNum] = iMBCodingType; |
|
1909 |
|
1910 if (!iCurMBNumInVP && iDoTranscoding) |
|
1911 { |
|
1912 if (!iDoModeTranscoding) |
|
1913 { |
|
1914 /* We are not doing bitstream transcoding, |
|
1915 we have color effect here and need to reconstruct data partitions. |
|
1916 */ |
|
1917 ReconstructIMBPartitions(); |
|
1918 } |
|
1919 } |
|
1920 } |
|
1921 |
|
1922 /* |
|
1923 * OnePMBDataStartedDataPartitioned |
|
1924 * |
|
1925 * Parameters: |
|
1926 * |
|
1927 * Function: |
|
1928 * Add one IMB instance, It is done after parsing Part1 and Part2 before the block data for current MB |
|
1929 * Note: PMB may be INTRA coded. |
|
1930 * Returns: |
|
1931 * None |
|
1932 * Error codes: |
|
1933 * None |
|
1934 * |
|
1935 */ |
|
1936 void CMPEG4Transcoder::OnePMBDataStartedDataPartitioned(vdxPMBListItem_t *aMBInstance, dlst_t *aMBList, int aCurrMBNumInVP, int aMBNum) |
|
1937 { |
|
1938 VDTASSERT(aMBInstance); /* at this point, the instance should not be null */ |
|
1939 VDTASSERT(aMBList); |
|
1940 |
|
1941 memcpy(iCurPMBinstance, aMBInstance, sizeof(vdxPMBListItem_t)); |
|
1942 iCurMBNumInVP = aCurrMBNumInVP; |
|
1943 iCurMBNum = aMBNum; |
|
1944 iMBList = aMBList; |
|
1945 iMBCodingType = aMBInstance->mbClass; |
|
1946 iVopCodingType = VDX_VOP_TYPE_P; |
|
1947 iMBType[iCurMBNum] = iMBCodingType; |
|
1948 |
|
1949 if (!aMBInstance->fCodedMB && iDoModeTranscoding) |
|
1950 { |
|
1951 /* this MB is not coded and need to be converted to target mode, |
|
1952 out put the possible MB stuffing bits and COD |
|
1953 */ |
|
1954 /* MB stuffing bits if they exsit */ |
|
1955 vdtCopyBuffer(iInBuffer, iOutBuffer, |
|
1956 aMBInstance->DataItemStartByteIndex[11], aMBInstance->DataItemStartBitIndex[11], |
|
1957 aMBInstance->DataItemEndByteIndex[11], aMBInstance->DataItemEndBitIndex[11]); |
|
1958 /* It is a not-coded MB, output 1 bit COD (it always exists in P frame) */ |
|
1959 sPutBits (iOutBuffer, 1, 1); |
|
1960 iLastMBNum = iCurMBNum; |
|
1961 } |
|
1962 else if (!iCurMBNumInVP && iDoTranscoding) |
|
1963 { |
|
1964 if (!iDoModeTranscoding) |
|
1965 { |
|
1966 /* We are not doing bitstream transcoding, |
|
1967 we have color effect here and need to reconstruct data partitions. |
|
1968 */ |
|
1969 ReconstructPMBPartitions(); |
|
1970 } |
|
1971 } |
|
1972 } |
|
1973 |
|
1974 |
|
1975 |
|
1976 /* |
|
1977 * TranscodingOneMB |
|
1978 * |
|
1979 * Parameters: |
|
1980 * |
|
1981 * Function: |
|
1982 * Transcoding one MB, which may include dequantization, requantization , and re-encoding |
|
1983 * Returns: |
|
1984 * DMD error codes since called from decmbdct |
|
1985 * |
|
1986 */ |
|
1987 int CMPEG4Transcoder::TranscodingOneMB(dmdPParam_t *aParam = NULL) |
|
1988 { |
|
1989 /* Because it has block data, this MB must be a coded MB, |
|
1990 which means the position indicated by iMBStartByteIndex and iMBStartBitIndex starts with a MCBPC |
|
1991 */ |
|
1992 VDTASSERT(!(!iCurPMBinstance->fCodedMB && iMBCodingType == VDX_MB_INTER)); |
|
1993 |
|
1994 if (!iDoTranscoding) |
|
1995 { |
|
1996 iLastMBNum = iCurMBNum; // need to update the variable to avoid marking this as noncoded MB |
|
1997 return TX_OK; |
|
1998 } |
|
1999 |
|
2000 int dataPartitioned = (iBitStreamMode == EVedVideoBitstreamModeMPEG4DP_RVLC || iBitStreamMode == EVedVideoBitstreamModeMPEG4Resyn_DP_RVLC |
|
2001 || iBitStreamMode == EVedVideoBitstreamModeMPEG4DP || iBitStreamMode == EVedVideoBitstreamModeMPEG4Resyn_DP); |
|
2002 |
|
2003 if (dataPartitioned) |
|
2004 { |
|
2005 /* since we need to handle MB stuffing bits, which are handle outside the transcoder in other modes, |
|
2006 not coded MBs and MB stuffing bits are handled in OnePMBDataStartedDataPartitioned, |
|
2007 ReconstuctI/PMBPartitios or ConstructRegularMPEG4MBData |
|
2008 */ |
|
2009 } |
|
2010 else if(iCurMBNum != iLastMBNum + 1 ) |
|
2011 { |
|
2012 /* if previous MBs are lost or not coded, we copy one MB with COD = 1; */ |
|
2013 for (int i = 0 ; i < iCurMBNum - iLastMBNum - 1; i++) |
|
2014 { |
|
2015 /* output 1 bit COD */ |
|
2016 sPutBits (iOutBuffer, 1, 1); |
|
2017 } |
|
2018 } |
|
2019 |
|
2020 int newMCBPCLen = 0; |
|
2021 int newMCBPC = 0; |
|
2022 int oldMCBPCLen = 0; |
|
2023 |
|
2024 /* determine whether to change mcbpc */ |
|
2025 if (iColorEffect) |
|
2026 { |
|
2027 if (iVopCodingType == VDX_VOP_TYPE_P) |
|
2028 { |
|
2029 oldMCBPCLen = vdtGetPMBBlackAndWhiteMCBPC(newMCBPCLen, newMCBPC, iCurPMBinstance->mcbpc); |
|
2030 } |
|
2031 else |
|
2032 { |
|
2033 oldMCBPCLen = vdtGetIMBBlackAndWhiteMCBPC(newMCBPCLen, newMCBPC, iCurIMBinstance->mcbpc); |
|
2034 } |
|
2035 } |
|
2036 |
|
2037 |
|
2038 |
|
2039 if (iDoModeTranscoding && ( (iTargetFormat == EVedVideoTypeH263Profile0Level10) || |
|
2040 (iTargetFormat == EVedVideoTypeH263Profile0Level45) ) ) |
|
2041 { |
|
2042 if ( ConstructH263MBData(aParam, newMCBPCLen, newMCBPC) != VDC_OK ) |
|
2043 { |
|
2044 return TX_ERR; |
|
2045 } |
|
2046 } |
|
2047 else /* possible H263->MPEG4 transcoding */ |
|
2048 |
|
2049 { |
|
2050 /* MPEG4 with VDT_RESYN and VDT_REGULAR, we only do bitstream copying */ |
|
2051 if ( iBitStreamMode == EVedVideoBitstreamModeMPEG4Resyn || iBitStreamMode == EVedVideoBitstreamModeMPEG4Regular || |
|
2052 ((iBitStreamMode ==EVedVideoBitstreamModeMPEG4ShortHeader || iBitStreamMode == EVedVideoBitstreamModeH263) && !iDoModeTranscoding) ) |
|
2053 { |
|
2054 /* the MB stuffing is taken card of outside in file viddemux.cpp |
|
2055 we only need to output COD, MCBPC |
|
2056 */ |
|
2057 int mcbpcStartByteIndex, mcbpcStartBitIndex; |
|
2058 |
|
2059 if (iVopCodingType == VDX_VOP_TYPE_I) |
|
2060 { |
|
2061 mcbpcStartByteIndex = iCurIMBinstance->DataItemStartByteIndex[0]; |
|
2062 mcbpcStartBitIndex = iCurIMBinstance->DataItemStartBitIndex[0]; |
|
2063 } |
|
2064 else |
|
2065 { |
|
2066 mcbpcStartByteIndex = iCurPMBinstance->DataItemStartByteIndex[0]; |
|
2067 mcbpcStartBitIndex = iCurPMBinstance->DataItemStartBitIndex[0]; |
|
2068 /* It is a coded MB, output 1 bit COD (it always exists in P frame) */ |
|
2069 sPutBits (iOutBuffer, 1, 0); |
|
2070 } |
|
2071 |
|
2072 if (!iColorEffect) |
|
2073 { |
|
2074 bufEdit.copyMode = CopyWhole; /* whole */ |
|
2075 CopyStream(iInBuffer,iOutBuffer,&bufEdit,mcbpcStartByteIndex,mcbpcStartBitIndex); |
|
2076 } |
|
2077 else |
|
2078 { |
|
2079 /* modify mcbpc and copy only the Y data */ |
|
2080 bufEdit.copyMode = CopyWithEdit; // copy with edit |
|
2081 bufEdit.editParams[0].StartByteIndex = mcbpcStartByteIndex; |
|
2082 bufEdit.editParams[0].StartBitIndex = mcbpcStartBitIndex; |
|
2083 bufEdit.editParams[0].curNumBits = oldMCBPCLen; |
|
2084 bufEdit.editParams[0].newNumBits = newMCBPCLen; |
|
2085 bufEdit.editParams[0].newValue = newMCBPC; |
|
2086 CopyStream(iInBuffer,iOutBuffer,&bufEdit,mcbpcStartByteIndex,mcbpcStartBitIndex); |
|
2087 |
|
2088 /* disgard the UV data */ |
|
2089 int16 errorCode = 0; |
|
2090 int bitsToRewind = ((iInBuffer->getIndex << 3) + 7 - iInBuffer->bitIndex) |
|
2091 - ((iBlockStartByteIndex[4] << 3) + 7 - iBlockStartBitIndex[4]); |
|
2092 bibRewindBits(bitsToRewind, iOutBuffer, &errorCode ); |
|
2093 |
|
2094 if (iMBCodingType == VDX_MB_INTRA) |
|
2095 { |
|
2096 if (iBitStreamMode == EVedVideoBitstreamModeMPEG4ShortHeader || iBitStreamMode == EVedVideoBitstreamModeH263) |
|
2097 { |
|
2098 sResetH263IntraDcUV(iOutBuffer, iColorToneU, iColorToneV); |
|
2099 } |
|
2100 else |
|
2101 { |
|
2102 ResetMPEG4IntraDcUV(); |
|
2103 } |
|
2104 } |
|
2105 } |
|
2106 } |
|
2107 |
|
2108 else if ((iBitStreamMode == EVedVideoBitstreamModeMPEG4ShortHeader || iBitStreamMode == EVedVideoBitstreamModeH263) && iDoModeTranscoding) |
|
2109 { |
|
2110 H263ToMPEG4MBData(newMCBPCLen, newMCBPC); |
|
2111 } |
|
2112 |
|
2113 else /* data partitioned */ |
|
2114 { |
|
2115 if (iDoModeTranscoding) |
|
2116 { |
|
2117 /* for data partitioned bitstream, we do the bitstream rearrangement */ |
|
2118 ConstructRegularMPEG4MBData(newMCBPCLen, newMCBPC); |
|
2119 } |
|
2120 else |
|
2121 { |
|
2122 /* copy the ACs or DCTs */ |
|
2123 bufEdit.copyMode = CopyWhole; // whole |
|
2124 CopyStream(iInBuffer,iOutBuffer,&bufEdit,iBlockStartByteIndex[0],iBlockStartBitIndex[0]); |
|
2125 if (iColorEffect) |
|
2126 { |
|
2127 /* discard U V data */ |
|
2128 int16 errorCode = 0; |
|
2129 int bitsToRewind = ((iInBuffer->getIndex << 3) + 7 - iInBuffer->bitIndex) |
|
2130 - ((iBlockStartByteIndex[4] << 3) + 7 - iBlockStartBitIndex[4]); |
|
2131 bibRewindBits(bitsToRewind, iOutBuffer, &errorCode ); |
|
2132 } |
|
2133 } |
|
2134 } |
|
2135 |
|
2136 } |
|
2137 iLastMBNum = iCurMBNum; |
|
2138 return TX_OK; |
|
2139 } |
|
2140 |
|
2141 |
|
2142 |
|
2143 |
|
2144 /* |
|
2145 * ReconstructIMBPartitions |
|
2146 * |
|
2147 * Parameters: |
|
2148 * |
|
2149 * Function: |
|
2150 * Recontruct the partitions for color effect when we are not doing format transcoding |
|
2151 * Returns: |
|
2152 * None |
|
2153 * Error codes: |
|
2154 * None |
|
2155 * |
|
2156 */ |
|
2157 void CMPEG4Transcoder::ReconstructIMBPartitions() |
|
2158 { |
|
2159 vdxIMBListItem_t *MBinstance; |
|
2160 int *dataItemStartByteIndex; |
|
2161 int *dataItemStartBitIndex; |
|
2162 int *dataItemEndByteIndex; |
|
2163 int *dataItemEndBitIndex; |
|
2164 int newMCBPCLen = 0; |
|
2165 int newMCBPC = 0; |
|
2166 |
|
2167 VDTASSERT(iMBList); |
|
2168 |
|
2169 for (dlstHead(iMBList, (void **) &MBinstance); |
|
2170 MBinstance != NULL; |
|
2171 dlstNext(iMBList, (void **) &MBinstance)) |
|
2172 { |
|
2173 dataItemStartByteIndex = MBinstance->DataItemStartByteIndex; |
|
2174 dataItemStartBitIndex = MBinstance->DataItemStartBitIndex; |
|
2175 dataItemEndByteIndex = MBinstance->DataItemEndByteIndex; |
|
2176 dataItemEndBitIndex = MBinstance->DataItemEndBitIndex; |
|
2177 // MB stuffing bits if they exsit |
|
2178 vdtCopyBuffer(iInBuffer, iOutBuffer, dataItemStartByteIndex[11], dataItemStartBitIndex[11], |
|
2179 dataItemEndByteIndex[11], dataItemEndBitIndex[11]); |
|
2180 |
|
2181 /* MCBPC */ |
|
2182 if (iColorEffect) |
|
2183 { |
|
2184 /* MCBPC Changed. Ignore the old value (not used) */ |
|
2185 vdtGetIMBBlackAndWhiteMCBPC(newMCBPCLen, newMCBPC, MBinstance->mcbpc); |
|
2186 sPutBits(iOutBuffer, newMCBPCLen, newMCBPC); |
|
2187 } |
|
2188 else |
|
2189 { |
|
2190 vdtCopyBuffer(iInBuffer, iOutBuffer, |
|
2191 dataItemStartByteIndex[0], dataItemStartBitIndex[0], |
|
2192 dataItemEndByteIndex[0], dataItemEndBitIndex[0]); |
|
2193 } |
|
2194 |
|
2195 /* DQUANT, if it exsits */ |
|
2196 vdtCopyBuffer(iInBuffer, iOutBuffer, |
|
2197 dataItemStartByteIndex[1], dataItemStartBitIndex[1], |
|
2198 dataItemEndByteIndex[1], dataItemEndBitIndex[1]); |
|
2199 |
|
2200 /* INTRA DCs */ |
|
2201 if (!iColorEffect) |
|
2202 { |
|
2203 vdtCopyBuffer(iInBuffer, iOutBuffer, |
|
2204 dataItemStartByteIndex[4], dataItemStartBitIndex[4], |
|
2205 dataItemEndByteIndex[4], dataItemEndBitIndex[4]); |
|
2206 } |
|
2207 else |
|
2208 { |
|
2209 if (!(VDT_NO_DATA(dataItemStartByteIndex[4], dataItemStartBitIndex[4], |
|
2210 dataItemEndByteIndex[4], dataItemEndBitIndex[4]))) |
|
2211 { |
|
2212 vdtCopyBuffer(iInBuffer, iOutBuffer, |
|
2213 dataItemStartByteIndex[4], dataItemStartBitIndex[4], |
|
2214 dataItemStartByteIndex[8], dataItemStartBitIndex[8]); |
|
2215 ResetMPEG4IntraDcUV(); |
|
2216 } |
|
2217 } |
|
2218 } |
|
2219 |
|
2220 /* DC marker */ |
|
2221 sPutBits(iOutBuffer, DC_MARKER_LENGTH, DC_MARKER); |
|
2222 |
|
2223 for (dlstHead(iMBList, (void **) &MBinstance); |
|
2224 MBinstance != NULL; |
|
2225 dlstNext(iMBList, (void **) &MBinstance)) |
|
2226 { |
|
2227 dataItemStartByteIndex = MBinstance->DataItemStartByteIndex; |
|
2228 dataItemStartBitIndex = MBinstance->DataItemStartBitIndex; |
|
2229 dataItemEndByteIndex = MBinstance->DataItemEndByteIndex; |
|
2230 dataItemEndBitIndex = MBinstance->DataItemEndBitIndex; |
|
2231 |
|
2232 /* ac_pred_flag */ |
|
2233 vdtCopyBuffer(iInBuffer, iOutBuffer, |
|
2234 dataItemStartByteIndex[3], dataItemStartBitIndex[3], |
|
2235 dataItemEndByteIndex[3], dataItemEndBitIndex[3]); |
|
2236 |
|
2237 /* CBPY */ |
|
2238 vdtCopyBuffer(iInBuffer, iOutBuffer, |
|
2239 dataItemStartByteIndex[2], dataItemStartBitIndex[2], |
|
2240 dataItemEndByteIndex[2], dataItemEndBitIndex[2]); |
|
2241 } |
|
2242 |
|
2243 /* make sure the head of the list is reset */ |
|
2244 dlstHead(iMBList, (void **) &MBinstance); |
|
2245 } |
|
2246 |
|
2247 /* |
|
2248 * ReconstructPMBPartitions |
|
2249 * |
|
2250 * Parameters: |
|
2251 * |
|
2252 * Function: |
|
2253 * Recontruct the partitions for color effect when we are not doing format transcoding |
|
2254 * Returns: |
|
2255 * None |
|
2256 * Error codes: |
|
2257 * None |
|
2258 * |
|
2259 */ |
|
2260 void CMPEG4Transcoder::ReconstructPMBPartitions() |
|
2261 { |
|
2262 vdxPMBListItem_t *MBinstance; |
|
2263 int *dataItemStartByteIndex; |
|
2264 int *dataItemStartBitIndex; |
|
2265 int *dataItemEndByteIndex; |
|
2266 int *dataItemEndBitIndex; |
|
2267 int newMCBPCLen = 0; |
|
2268 int newMCBPC = 0; |
|
2269 |
|
2270 VDTASSERT(iMBList); |
|
2271 |
|
2272 for (dlstHead(iMBList, (void **) &MBinstance); |
|
2273 MBinstance != NULL; |
|
2274 dlstNext(iMBList, (void **) &MBinstance)) |
|
2275 { |
|
2276 dataItemStartByteIndex = MBinstance->DataItemStartByteIndex; |
|
2277 dataItemStartBitIndex = MBinstance->DataItemStartBitIndex; |
|
2278 dataItemEndByteIndex = MBinstance->DataItemEndByteIndex; |
|
2279 dataItemEndBitIndex = MBinstance->DataItemEndBitIndex; |
|
2280 |
|
2281 /* MB stuffing bits if they exsit */ |
|
2282 vdtCopyBuffer(iInBuffer, iOutBuffer, dataItemStartByteIndex[11], dataItemStartBitIndex[11], |
|
2283 dataItemEndByteIndex[11], dataItemEndBitIndex[11]); |
|
2284 |
|
2285 if (MBinstance->fCodedMB) |
|
2286 { |
|
2287 /* output 1 bit COD, coded */ |
|
2288 sPutBits (iOutBuffer, 1, 0); |
|
2289 |
|
2290 /* MCBPC */ |
|
2291 if (iColorEffect) |
|
2292 { |
|
2293 /* MCBPC Changed, ignore the return value */ |
|
2294 vdtGetPMBBlackAndWhiteMCBPC(newMCBPCLen, newMCBPC, MBinstance->mcbpc); |
|
2295 sPutBits(iOutBuffer, newMCBPCLen, newMCBPC); |
|
2296 } |
|
2297 else |
|
2298 { |
|
2299 vdtCopyBuffer(iInBuffer, iOutBuffer, |
|
2300 dataItemStartByteIndex[0], dataItemStartBitIndex[0], |
|
2301 dataItemEndByteIndex[0], dataItemEndBitIndex[0]); |
|
2302 } |
|
2303 |
|
2304 /* MVs, if they exist */ |
|
2305 vdtCopyBuffer(iInBuffer, iOutBuffer, |
|
2306 dataItemStartByteIndex[10], dataItemStartBitIndex[10], |
|
2307 dataItemEndByteIndex[10], dataItemEndBitIndex[10]); |
|
2308 } |
|
2309 else |
|
2310 { |
|
2311 /* output 1 bit COD, not coded */ |
|
2312 sPutBits (iOutBuffer, 1, 1); |
|
2313 } |
|
2314 } |
|
2315 |
|
2316 /* MM marker */ |
|
2317 sPutBits(iOutBuffer, MOTION_MARKER_LENGTH, MOTION_MARKER); |
|
2318 |
|
2319 for (dlstHead(iMBList, (void **) &MBinstance); |
|
2320 MBinstance != NULL; |
|
2321 dlstNext(iMBList, (void **) &MBinstance)) |
|
2322 { |
|
2323 if (MBinstance->fCodedMB) |
|
2324 { |
|
2325 dataItemStartByteIndex = MBinstance->DataItemStartByteIndex; |
|
2326 dataItemStartBitIndex = MBinstance->DataItemStartBitIndex; |
|
2327 dataItemEndByteIndex = MBinstance->DataItemEndByteIndex; |
|
2328 dataItemEndBitIndex = MBinstance->DataItemEndBitIndex; |
|
2329 |
|
2330 /* ac_pred_flag, if it exsits */ |
|
2331 vdtCopyBuffer(iInBuffer, iOutBuffer, |
|
2332 dataItemStartByteIndex[3], dataItemStartBitIndex[3], |
|
2333 dataItemEndByteIndex[3], dataItemEndBitIndex[3]); |
|
2334 |
|
2335 /* CBPY, */ |
|
2336 vdtCopyBuffer(iInBuffer, iOutBuffer, |
|
2337 dataItemStartByteIndex[2], dataItemStartBitIndex[2], |
|
2338 dataItemEndByteIndex[2], dataItemEndBitIndex[2]); |
|
2339 /* DQUANT, if it exsits */ |
|
2340 vdtCopyBuffer(iInBuffer, iOutBuffer, |
|
2341 dataItemStartByteIndex[1], dataItemStartBitIndex[1], |
|
2342 dataItemEndByteIndex[1], dataItemEndBitIndex[1]); |
|
2343 |
|
2344 /* INTRA DCs, if they exsit */ |
|
2345 if (!iColorEffect) |
|
2346 { |
|
2347 vdtCopyBuffer(iInBuffer, iOutBuffer, |
|
2348 dataItemStartByteIndex[4], dataItemStartBitIndex[4], |
|
2349 dataItemEndByteIndex[4], dataItemEndBitIndex[4]); |
|
2350 } |
|
2351 else |
|
2352 { |
|
2353 if (!(VDT_NO_DATA(dataItemStartByteIndex[4], dataItemStartBitIndex[4], |
|
2354 dataItemEndByteIndex[4], dataItemEndBitIndex[4]))) |
|
2355 { |
|
2356 vdtCopyBuffer(iInBuffer, iOutBuffer, |
|
2357 dataItemStartByteIndex[4], dataItemStartBitIndex[4], |
|
2358 dataItemStartByteIndex[8], dataItemStartBitIndex[8]); |
|
2359 ResetMPEG4IntraDcUV(); |
|
2360 } |
|
2361 } |
|
2362 } |
|
2363 } |
|
2364 |
|
2365 /* make sure the head of the list is reset */ |
|
2366 dlstHead(iMBList, (void **) &MBinstance); |
|
2367 } |
|
2368 |
|
2369 /* |
|
2370 * ResetMPEG4IntraDcUV |
|
2371 * |
|
2372 * Parameters: |
|
2373 * |
|
2374 * Function: |
|
2375 * This function resets the DCc for U V block in INTRA MB. |
|
2376 * Inputs are valid only with Color Effect |
|
2377 * Returns: |
|
2378 * None |
|
2379 * Error codes: |
|
2380 * None |
|
2381 * |
|
2382 */ |
|
2383 void CMPEG4Transcoder::ResetMPEG4IntraDcUV() |
|
2384 { |
|
2385 /* set INTRADC for u,v in the output buffer */ |
|
2386 TInt sizeU, sizeCodeU, sizeCodeLengthU, valueU, valueCodeU, valueCodeLengthU; |
|
2387 TInt sizeV, sizeCodeV, sizeCodeLengthV, valueV, valueCodeV, valueCodeLengthV; |
|
2388 TInt curDcScaler, delta; |
|
2389 TReal realDelta, realVal; |
|
2390 TInt mbh, mbv, mbd; // previous MB in the horizontal, vertical and diagonal directions |
|
2391 TInt codeMB; |
|
2392 |
|
2393 // initialize for codewords |
|
2394 sizeU = sizeCodeU = sizeCodeLengthU = valueCodeU = valueCodeLengthU = 0; |
|
2395 sizeV = sizeCodeV = sizeCodeLengthV = valueCodeV = valueCodeLengthV = 0; |
|
2396 |
|
2397 // initialize for prediction |
|
2398 mbh = mbv = mbd = VDX_MB_INTER; |
|
2399 codeMB = 0; |
|
2400 |
|
2401 // NOTE: VDX_MB_INTER=1, VDX_MB_INTRA=2, NOT-CODED MB has a value of 0 |
|
2402 if (iVopCodingType == VDX_VOP_TYPE_I) |
|
2403 { |
|
2404 /* encode intra DC coefficients for INTRA MBs of I-VOP if |
|
2405 either of the following is true: |
|
2406 - |
|
2407 - |
|
2408 else, do not encode intra DC |
|
2409 (because rest of MBs have differential intra DC, which is zero) |
|
2410 */ |
|
2411 if (!iCurMBNumInVP || |
|
2412 (!(iCurMBNum%iMBsinWidth) && (iCurMBNumInVP<iMBsinWidth))) |
|
2413 { |
|
2414 codeMB = 1; |
|
2415 } |
|
2416 } |
|
2417 else if (iVopCodingType == VDX_VOP_TYPE_P) |
|
2418 { |
|
2419 if (iCurMBNumInVP>iMBsinWidth) |
|
2420 { |
|
2421 if (iCurMBNum%iMBsinWidth) |
|
2422 { |
|
2423 mbh = iMBType[iCurMBNum-1]; |
|
2424 mbd = iMBType[iCurMBNum-iMBsinWidth-1]; |
|
2425 } |
|
2426 mbv = iMBType[iCurMBNum-iMBsinWidth]; |
|
2427 } |
|
2428 else if (iCurMBNumInVP==iMBsinWidth) |
|
2429 { |
|
2430 if (iCurMBNum%iMBsinWidth) |
|
2431 { |
|
2432 mbh = iMBType[iCurMBNum-1]; |
|
2433 } |
|
2434 mbv = iMBType[iCurMBNum-iMBsinWidth]; |
|
2435 } |
|
2436 else if (iCurMBNumInVP>0) |
|
2437 { |
|
2438 if (iCurMBNum%iMBsinWidth) |
|
2439 { |
|
2440 mbh = iMBType[iCurMBNum-1]; |
|
2441 } |
|
2442 } |
|
2443 |
|
2444 // |
|
2445 if ((mbh<VDX_MB_INTRA && mbv<VDX_MB_INTRA) || |
|
2446 (mbd==VDX_MB_INTRA && ((mbh==VDX_MB_INTRA && mbv<VDX_MB_INTRA) || |
|
2447 (mbh<VDX_MB_INTRA && mbv==VDX_MB_INTRA)))) |
|
2448 { |
|
2449 codeMB = 1; |
|
2450 } |
|
2451 } |
|
2452 |
|
2453 if (codeMB) // if IntraDC need to be coded |
|
2454 { |
|
2455 // color-toned U,V values |
|
2456 valueU = iColorToneU; |
|
2457 valueV = iColorToneV; |
|
2458 |
|
2459 // compensate for different QP than original |
|
2460 if (iCurQuant != iRefQuant) |
|
2461 { |
|
2462 // calculate change in dc value |
|
2463 curDcScaler = GetMpeg4DcScalerUV(iCurQuant); |
|
2464 realDelta = TReal(iDcScaler-curDcScaler)/TReal(curDcScaler); |
|
2465 if (realDelta != 0.0) |
|
2466 { |
|
2467 // U |
|
2468 realVal = realDelta*TReal(valueU); |
|
2469 delta = TInt(realVal + ((realVal<0) ? (-0.5) : (0.5))); |
|
2470 valueU += delta; |
|
2471 // V |
|
2472 realVal = realDelta*TReal(valueV); |
|
2473 delta = TInt(realVal + ((realVal<0) ? (-0.5) : (0.5))); |
|
2474 valueV += delta; |
|
2475 } |
|
2476 } |
|
2477 |
|
2478 // get codewords |
|
2479 GetMPEG4IntraDcCoeffUV(valueU, sizeU, sizeCodeU, sizeCodeLengthU, |
|
2480 valueCodeU, valueCodeLengthU); |
|
2481 GetMPEG4IntraDcCoeffUV(valueV, sizeV, sizeCodeV, sizeCodeLengthV, |
|
2482 valueCodeV, valueCodeLengthV); |
|
2483 |
|
2484 // code codewords |
|
2485 // U |
|
2486 sPutBits(iOutBuffer, sizeCodeLengthU, sizeCodeU); // dct_dc_coeff size |
|
2487 if (sizeCodeU != 3) // size=0 |
|
2488 { |
|
2489 sPutBits(iOutBuffer, valueCodeLengthU, valueCodeU); // dct_dc_coeff differential |
|
2490 if (valueCodeLengthU>8) |
|
2491 sPutBits(iOutBuffer, 1, 1); // marker bit |
|
2492 } |
|
2493 |
|
2494 // V |
|
2495 sPutBits(iOutBuffer, sizeCodeLengthV, sizeCodeV); // dct_dc_coeff size |
|
2496 if (sizeCodeV != 3) // size=0 |
|
2497 { |
|
2498 sPutBits(iOutBuffer, valueCodeLengthV, valueCodeV); // dct_dc_coeff differential |
|
2499 if (valueCodeLengthV>8) |
|
2500 sPutBits(iOutBuffer, 1, 1); // marker bit |
|
2501 } |
|
2502 } |
|
2503 else |
|
2504 { |
|
2505 sPutBits (iOutBuffer, 2, 3); /* U */ |
|
2506 sPutBits (iOutBuffer, 2, 3); /* V */ |
|
2507 } |
|
2508 } |
|
2509 |
|
2510 |
|
2511 /* |
|
2512 * GetMPEG4IntraDcCoeffUV |
|
2513 * |
|
2514 * Parameters: |
|
2515 * aValue coefficient value |
|
2516 * aDCAC pointer the reconstructed coefficients |
|
2517 * Function: |
|
2518 * This function fills the reconstructed DCAC values for INTRA block. |
|
2519 * Inputs are valid only with Color Effect |
|
2520 * Returns: |
|
2521 * None |
|
2522 * Error codes: |
|
2523 * None |
|
2524 * |
|
2525 */ |
|
2526 void CMPEG4Transcoder::GetMPEG4IntraDcCoeffUV(TInt aValue, TInt& aSize, |
|
2527 TInt& aSizeCode, TInt& aSizeCodeLength, TInt& aValueCode, TInt& aValueCodeLength) |
|
2528 { |
|
2529 int absVal = (aValue>=0 ? aValue : -aValue); |
|
2530 // size of aValueCode |
|
2531 for (aSize=0; absVal|0; absVal>>=1, aSize++) ; |
|
2532 if (aSize) |
|
2533 { |
|
2534 // codeword for aSize |
|
2535 if (aSize==1) |
|
2536 { |
|
2537 aSizeCode = 2; |
|
2538 aSizeCodeLength = 2; |
|
2539 } |
|
2540 else |
|
2541 { |
|
2542 aSizeCode = 1; |
|
2543 aSizeCodeLength = aSize; |
|
2544 } |
|
2545 |
|
2546 // codeword for aValue |
|
2547 aValueCode = aValue; |
|
2548 if (aValue<0) |
|
2549 aValueCode += ((1<<aSize)-1); |
|
2550 aValueCodeLength = aSize; |
|
2551 } |
|
2552 else |
|
2553 { |
|
2554 // codeword for aSize |
|
2555 aSizeCode = 3; // codeword for size=0 |
|
2556 aSizeCodeLength = 2; |
|
2557 // no codeword for aValue |
|
2558 aValueCode = aValueCodeLength = 0; |
|
2559 } |
|
2560 } |
|
2561 |
|
2562 |
|
2563 /* |
|
2564 * AddOneBlockDCACrecon |
|
2565 * |
|
2566 * Parameters: |
|
2567 * aIndex block index |
|
2568 * aDCAC pointer the reconstructed coefficients |
|
2569 * Function: |
|
2570 * This function fills the reconstructed DCAC values for INTRA block. |
|
2571 * Inputs are valid only with Color Effect |
|
2572 * Returns: |
|
2573 * None |
|
2574 * Error codes: |
|
2575 * None |
|
2576 * |
|
2577 */ |
|
2578 void CMPEG4Transcoder::AddOneBlockDCACrecon(int aIndex, int *aDCAC) |
|
2579 { |
|
2580 VDTASSERT(aIndex >= 0 && aIndex < 6); |
|
2581 |
|
2582 if (aDCAC && iDoModeTranscoding && (iTargetFormat == EVedVideoTypeH263Profile0Level10 || |
|
2583 iTargetFormat == EVedVideoTypeH263Profile0Level45)) |
|
2584 { |
|
2585 /* we only need the reconstructed DCACs for MPEG4 -> H263 */ |
|
2586 /* It is a coded block */ |
|
2587 memcpy(iDCTBlockData + (aIndex << 6), aDCAC, sizeof(int) * BLOCK_COEFF_SIZE); |
|
2588 } |
|
2589 } |
|
2590 |
|
2591 /* |
|
2592 * ConstructH263MBData |
|
2593 * |
|
2594 * Parameters: |
|
2595 * aNewMCBPCLen new length of mcbpc |
|
2596 * aNewMCBPC new mcbpc |
|
2597 * Function: |
|
2598 * This function creates a new H263 MB |
|
2599 * Inputs are valid only with Color Effect |
|
2600 * Returns: |
|
2601 * VDC error codes |
|
2602 * |
|
2603 */ |
|
2604 int CMPEG4Transcoder::ConstructH263MBData(dmdPParam_t *aParam, int /*aNewMCBPCLen*/, int /*aNewMCBPC*/) |
|
2605 { |
|
2606 /* MB data part1: output MCBPC, CBPY, DQuant, MV, intra DC etc */ |
|
2607 int *dataItemStartByteIndex; |
|
2608 int *dataItemStartBitIndex; |
|
2609 int *dataItemEndByteIndex; |
|
2610 int *dataItemEndBitIndex; |
|
2611 int quant, dquant; |
|
2612 int codedBlockPattern = 0; |
|
2613 |
|
2614 const unsigned int sDquant[5] = |
|
2615 { |
|
2616 1, 0, (unsigned int)65536, 2, 3 |
|
2617 }; |
|
2618 |
|
2619 if (iVopCodingType == VDX_VOP_TYPE_P) |
|
2620 { |
|
2621 dataItemStartByteIndex = iCurPMBinstance->DataItemStartByteIndex; |
|
2622 dataItemStartBitIndex = iCurPMBinstance->DataItemStartBitIndex; |
|
2623 dataItemEndByteIndex = iCurPMBinstance->DataItemEndByteIndex; |
|
2624 dataItemEndBitIndex = iCurPMBinstance->DataItemEndBitIndex; |
|
2625 quant = iCurPMBinstance->quant; |
|
2626 dquant = iCurPMBinstance->dquant; |
|
2627 } |
|
2628 else |
|
2629 { |
|
2630 dataItemStartByteIndex = iCurIMBinstance->DataItemStartByteIndex; |
|
2631 dataItemStartBitIndex = iCurIMBinstance->DataItemStartBitIndex; |
|
2632 dataItemEndByteIndex = iCurIMBinstance->DataItemEndByteIndex; |
|
2633 dataItemEndBitIndex = iCurIMBinstance->DataItemEndBitIndex; |
|
2634 quant = iCurIMBinstance->quant; |
|
2635 dquant = iCurIMBinstance->dquant; |
|
2636 } |
|
2637 |
|
2638 if (iPreQuant != quant - dquant) |
|
2639 { |
|
2640 /* last quant in MPEG4 and H263 is different, dquant and VLCs may not be reused */ |
|
2641 if (abs(quant - iPreQuant) > 2) |
|
2642 { |
|
2643 /* VLCs cannot be reused, obtain the new ones */ |
|
2644 sQuantizeMB(iDCTBlockData, quant, iPreQuant, |
|
2645 iMBCodingType, iColorEffect); |
|
2646 quant = iPreQuant; |
|
2647 dquant = 0; |
|
2648 } |
|
2649 else |
|
2650 { |
|
2651 /* VLCs can be reused, but need to change dquant and MCBPC */ |
|
2652 dquant = quant - iPreQuant; |
|
2653 } |
|
2654 } |
|
2655 |
|
2656 /* MB stuffing bits if they exsit */ |
|
2657 vdtCopyBuffer(iInBuffer, iOutBuffer, dataItemStartByteIndex[11], dataItemStartBitIndex[11], |
|
2658 dataItemEndByteIndex[11], dataItemEndBitIndex[11]); |
|
2659 |
|
2660 if (iMBCodingType == VDX_MB_INTER) |
|
2661 { |
|
2662 VDTASSERT(aParam); |
|
2663 tMBPosition mbPos; |
|
2664 tMotionVector mvTestOutside; |
|
2665 mbPos.x = aParam->xPosInMBs * 16; |
|
2666 mbPos.y = aParam->yPosInMBs * 16; |
|
2667 mbPos.LeftBound = 0; |
|
2668 mbPos.RightBound = iVDEInstance->lumWidth << 1; |
|
2669 mbPos.TopBound = 0; |
|
2670 mbPos.BottomBound = iVDEInstance->lumHeight << 1; |
|
2671 mvTestOutside.mvx = (int16) ((aParam->mvx[0] << 1) / 10); |
|
2672 mvTestOutside.mvy = (int16) ((aParam->mvy[0] << 1) / 10); |
|
2673 |
|
2674 /* Three cases for MVs. 1): 4MVs -> need mapping 2). 1 outside frame MV 3) rounding type = 1 */ |
|
2675 vdcInstance_t * vdcTemp = (vdcInstance_t *)(iVDEInstance->vdcHInstance); |
|
2676 |
|
2677 /* Two cases for MVs. 1): 4MVs -> need mapping 2). 1 outside frame MV */ |
|
2678 if (iCurPMBinstance->numMVs == 4 || (iCurPMBinstance->numMVs == 1 && |
|
2679 vbmMVOutsideBound(&mbPos, &mvTestOutside, 1)) || vdcTemp->pictureParam.rtype) |
|
2680 { |
|
2681 int32 numTextureBits; |
|
2682 int32 searchRange = 16; |
|
2683 tMotionVector *initPred; |
|
2684 (h263mbi+iCurMBNum)->QuantScale = (int16) quant; |
|
2685 (h263mbi+iCurMBNum)->dQuant = (int16) dquant; |
|
2686 |
|
2687 /* note: this buffer is also used in the diamond search and half-pixel search !!!!! |
|
2688 which needs at least 8 points |
|
2689 */ |
|
2690 initPred = (tMotionVector*) malloc(8 * sizeof (tMotionVector)); |
|
2691 if(!initPred) |
|
2692 { |
|
2693 //Memory not available |
|
2694 return TX_ERR; |
|
2695 } |
|
2696 |
|
2697 |
|
2698 for (int i = 0; i < iCurPMBinstance->numMVs ; i++) |
|
2699 { |
|
2700 (initPred + i)->mvx = (int16) (aParam->mvx[i] / 10); /* the recorded mv is multipied by 10, */ |
|
2701 (initPred + i)->mvy = (int16) (aParam->mvy[i] / 10); /* the recorded mv is multipied by 10, */ |
|
2702 } |
|
2703 int32 noOfPredictors = iCurPMBinstance->numMVs; |
|
2704 |
|
2705 /* perform the 4MVs -> 1MV mapping, and output this MB */ |
|
2706 vbmPutInterMB(&mbPos, |
|
2707 iOutBuffer,aParam, |
|
2708 initPred, noOfPredictors, |
|
2709 (u_int32) iVDEInstance->lumWidth, (u_int32) iVDEInstance->lumHeight, |
|
2710 searchRange, iCurMBNum, &numTextureBits, |
|
2711 (int16)iColorEffect, h263mbi); |
|
2712 /* the MVs buffer is updated inside vbmPutInterMB */ |
|
2713 |
|
2714 if (initPred) |
|
2715 free(initPred); |
|
2716 } |
|
2717 else |
|
2718 { |
|
2719 /* Here, for Inter MB with One inside Frame MV, we simply reuse the DCTs */ |
|
2720 VDTASSERT(iCurPMBinstance->numMVs == 1); |
|
2721 |
|
2722 /* It is a coded MB, output 1 bit COD (it always exists in P frame) */ |
|
2723 sPutBits (iOutBuffer, 1, 0); |
|
2724 int cbpy; |
|
2725 int mcbpcVal; |
|
2726 int len; |
|
2727 |
|
2728 codedBlockPattern = sFindCBP(iDCTBlockData, OFF); |
|
2729 mcbpcVal = iColorEffect? 0 : (codedBlockPattern & 3); |
|
2730 cbpy = ((codedBlockPattern >> 2) & 0xf); |
|
2731 vbmGetH263PMCBPC(dquant, iColorEffect, cbpy, mcbpcVal, len); |
|
2732 sPutBits(iOutBuffer, len, mcbpcVal); //MCBPC, CBPY |
|
2733 |
|
2734 /* DQUANT, if it exsits */ |
|
2735 if (dquant) |
|
2736 { |
|
2737 sPutBits(iOutBuffer, 2, sDquant[dquant + 2]); |
|
2738 } |
|
2739 /* recode MVs, one more indice exists in the MV VLC table in MPEG4 |
|
2740 moreover, vop_fcode can be larger than 1 (although it may rarely happens), |
|
2741 so it is better to redo the VLC coding |
|
2742 */ |
|
2743 /* the recorded mv is multipied by 10, in pixel unit */ |
|
2744 int16 mvx = (int16) ((aParam->mvx[0] << 1) / 10); |
|
2745 int16 mvy = (int16) ((aParam->mvy[0] << 1) / 10); |
|
2746 |
|
2747 tMotionVector lPredMV[4]; |
|
2748 tMBInfo *mbi = h263mbi + iCurMBNum; |
|
2749 |
|
2750 /* get the new predicted MV */ |
|
2751 vbmMvPrediction(mbi, iCurMBNum, lPredMV, (u_int32)iMBsinWidth); |
|
2752 |
|
2753 vbmEncodeMVDifferential(mvx - lPredMV[0].mvx, mvy - lPredMV[0].mvy, 1, iOutBuffer); |
|
2754 cbpy = 32; |
|
2755 /* following is the block level data */ |
|
2756 for (int i = 0; i < (iColorEffect? 4 : 6); i++) |
|
2757 { |
|
2758 int fBlockCoded = cbpy & codedBlockPattern; |
|
2759 if (fBlockCoded) |
|
2760 { |
|
2761 /* here we do the VLC coding again */ |
|
2762 int numTextureBits = 0; |
|
2763 vdtPutInterMBCMT(iOutBuffer,0, iDCTBlockData + i * BLOCK_COEFF_SIZE, &numTextureBits, ON); |
|
2764 } |
|
2765 cbpy >>= 1; |
|
2766 } |
|
2767 |
|
2768 /* update the MVs buffer */ |
|
2769 (h263mbi + iCurMBNum)->MV[0][0] = (int16) ((aParam->mvx[0] << 1) / 10); /* the recorded mv is multipied by 10 */ |
|
2770 (h263mbi + iCurMBNum)->MV[0][1] = (int16) ((aParam->mvy[0] << 1) / 10); /* the recorded mv is multipied by 10 */ |
|
2771 |
|
2772 } /* end of if 4MVs */ |
|
2773 } |
|
2774 else /* INTRA MB */ |
|
2775 { |
|
2776 /* update the MVs buffer */ |
|
2777 (h263mbi + iCurMBNum)->MV[0][0] = 0; |
|
2778 (h263mbi + iCurMBNum)->MV[0][1] = 0; |
|
2779 /* MPEG4 and H263 use different methods for INTRA MB, redo the VLC coding */ |
|
2780 int cbpy; |
|
2781 int mcbpcVal; |
|
2782 int len; |
|
2783 |
|
2784 codedBlockPattern = sFindCBP(iDCTBlockData, ON); |
|
2785 mcbpcVal = iColorEffect? 0 : (codedBlockPattern & 3); |
|
2786 cbpy = ((codedBlockPattern >> 2) & 0xf); |
|
2787 vbmGetH263IMCBPC(dquant, (iVopCodingType == VDX_VOP_TYPE_P), iColorEffect, cbpy, mcbpcVal, len); |
|
2788 sPutBits(iOutBuffer, len, mcbpcVal); //COD, MCBPC, CBPY |
|
2789 |
|
2790 /* DQUANT, if it exsits */ |
|
2791 if (dquant) |
|
2792 { |
|
2793 sPutBits(iOutBuffer, 2, sDquant[dquant + 2]); |
|
2794 } |
|
2795 cbpy = 32; |
|
2796 |
|
2797 /* following is the block level data */ |
|
2798 for (int i = 0; i < (iColorEffect? 4 : 6); i++) |
|
2799 { |
|
2800 /* requantize INTRA DC */ |
|
2801 /* DC Quantization */ |
|
2802 int coeff = (iDCTBlockData + i * BLOCK_COEFF_SIZE)[0] >> 3; |
|
2803 |
|
2804 if(coeff < 1) coeff = 1; |
|
2805 if(coeff > 254) coeff = 254; |
|
2806 if(coeff == 128) |
|
2807 { |
|
2808 sPutBits(iOutBuffer, 8, 255); |
|
2809 } |
|
2810 else |
|
2811 { |
|
2812 sPutBits(iOutBuffer, 8, coeff); |
|
2813 } |
|
2814 |
|
2815 (iDCTBlockData + i * BLOCK_COEFF_SIZE)[0] = coeff; |
|
2816 if(cbpy & codedBlockPattern) |
|
2817 { |
|
2818 int numTextureBits = 0; |
|
2819 vdtPutInterMBCMT(iOutBuffer,1, iDCTBlockData + i * BLOCK_COEFF_SIZE, &numTextureBits, ON); |
|
2820 } |
|
2821 cbpy >>= 1; |
|
2822 } |
|
2823 } |
|
2824 |
|
2825 if (iColorEffect && (iMBCodingType == VDX_MB_INTRA)) |
|
2826 { |
|
2827 ResetH263IntraDcUV(iOutBuffer, iColorToneU, iColorToneV); |
|
2828 } |
|
2829 iPreQuant = quant; |
|
2830 |
|
2831 return TX_OK; |
|
2832 } |
|
2833 |
|
2834 /* |
|
2835 * ConstructRegularMPEG4MBData |
|
2836 * |
|
2837 * Parameters: |
|
2838 * aNewMCBPCLen new length of mcbpc |
|
2839 * aNewMCBPC new mcbpc |
|
2840 * Function: |
|
2841 * This function rearranges the data for bitstream with data partitioning |
|
2842 * Only valid in Data Partitioned mode |
|
2843 * Inputs are valid only with Color Effect |
|
2844 * Returns: |
|
2845 * None |
|
2846 * Error codes: |
|
2847 * None |
|
2848 * |
|
2849 */ |
|
2850 void CMPEG4Transcoder::ConstructRegularMPEG4MBData(int aNewMCBPCLen, int aNewMCBPC) |
|
2851 { |
|
2852 /* MB data part1: output MCBPC, CBPY, DQuant, MV, intra DC etc */ |
|
2853 int *dataItemStartByteIndex; |
|
2854 int *dataItemStartBitIndex; |
|
2855 int *dataItemEndByteIndex; |
|
2856 int *dataItemEndBitIndex; |
|
2857 |
|
2858 if (iVopCodingType == VDX_VOP_TYPE_P) |
|
2859 { |
|
2860 dataItemStartByteIndex = iCurPMBinstance->DataItemStartByteIndex; |
|
2861 dataItemStartBitIndex = iCurPMBinstance->DataItemStartBitIndex; |
|
2862 dataItemEndByteIndex = iCurPMBinstance->DataItemEndByteIndex; |
|
2863 dataItemEndBitIndex = iCurPMBinstance->DataItemEndBitIndex; |
|
2864 } |
|
2865 else |
|
2866 { |
|
2867 dataItemStartByteIndex = iCurIMBinstance->DataItemStartByteIndex; |
|
2868 dataItemStartBitIndex = iCurIMBinstance->DataItemStartBitIndex; |
|
2869 dataItemEndByteIndex = iCurIMBinstance->DataItemEndByteIndex; |
|
2870 dataItemEndBitIndex = iCurIMBinstance->DataItemEndBitIndex; |
|
2871 } |
|
2872 |
|
2873 /* MB stuffing bits if they exsit */ |
|
2874 vdtCopyBuffer(iInBuffer, iOutBuffer, dataItemStartByteIndex[11], dataItemStartBitIndex[11], |
|
2875 dataItemEndByteIndex[11], dataItemEndBitIndex[11]); |
|
2876 |
|
2877 if (iVopCodingType == VDX_VOP_TYPE_P) |
|
2878 { |
|
2879 /* It is a coded MB, output 1 bit COD (it always exists in P frame) */ |
|
2880 sPutBits (iOutBuffer, 1, 0); |
|
2881 } |
|
2882 |
|
2883 /* MCBPC. NOTE: the positions do not include MCBPC stuffing bits !! */ |
|
2884 if (iColorEffect) |
|
2885 { |
|
2886 /* MCBPC Changed */ |
|
2887 sPutBits(iOutBuffer, aNewMCBPCLen, aNewMCBPC); |
|
2888 } |
|
2889 else |
|
2890 { |
|
2891 vdtCopyBuffer(iInBuffer, iOutBuffer, dataItemStartByteIndex[0], dataItemStartBitIndex[0], |
|
2892 dataItemEndByteIndex[0], dataItemEndBitIndex[0]); |
|
2893 } |
|
2894 /* ac_pred_flag, if it exsits */ |
|
2895 vdtCopyBuffer(iInBuffer, iOutBuffer, dataItemStartByteIndex[3], dataItemStartBitIndex[3], |
|
2896 dataItemEndByteIndex[3], dataItemEndBitIndex[3]); |
|
2897 |
|
2898 /* CBPY */ |
|
2899 vdtCopyBuffer(iInBuffer, iOutBuffer, dataItemStartByteIndex[2], dataItemStartBitIndex[2], |
|
2900 dataItemEndByteIndex[2], dataItemEndBitIndex[2]); |
|
2901 |
|
2902 /* DQUANT, if it exsits */ |
|
2903 vdtCopyBuffer(iInBuffer, iOutBuffer, dataItemStartByteIndex[1], dataItemStartBitIndex[1], |
|
2904 dataItemEndByteIndex[1], dataItemEndBitIndex[1]); |
|
2905 |
|
2906 if (iMBCodingType == VDX_MB_INTER) |
|
2907 { |
|
2908 /* MVs, if they exsit */ |
|
2909 vdtCopyBuffer(iInBuffer, iOutBuffer, dataItemStartByteIndex[10], dataItemStartBitIndex[10], |
|
2910 dataItemEndByteIndex[10], dataItemEndBitIndex[10]); |
|
2911 } |
|
2912 |
|
2913 /* following is the block level data */ |
|
2914 for (int i = 0; i < (iColorEffect? 4 : 6); i++) |
|
2915 { |
|
2916 /* INTRA DC, if it exsits */ |
|
2917 vdtCopyBuffer(iInBuffer, iOutBuffer, dataItemStartByteIndex[i + 4], dataItemStartBitIndex[i + 4], |
|
2918 dataItemEndByteIndex[i + 4], dataItemEndBitIndex[i + 4]); |
|
2919 |
|
2920 /* block data part2, AC or DCT coefficients */ |
|
2921 if (iBitStreamMode == EVedVideoBitstreamModeMPEG4DP_RVLC || iBitStreamMode == EVedVideoBitstreamModeMPEG4Resyn_DP_RVLC) |
|
2922 { |
|
2923 /* remember for data partitioning, the positions only indicate the |
|
2924 AC or DCTs coefficients |
|
2925 */ |
|
2926 if (VDT_NO_DATA(iBlockStartByteIndex[i], iBlockStartBitIndex[i], |
|
2927 iBlockEndByteIndex[i], iBlockEndBitIndex[i])) |
|
2928 { |
|
2929 /* no coefficients,skip this block */ |
|
2930 continue; |
|
2931 } |
|
2932 else |
|
2933 { |
|
2934 /* for RVLC coding, we transform the block data back to VLC */ |
|
2935 int numTextureBits = 0; |
|
2936 /* redo the entropy coding, RVLC -> VLC |
|
2937 only for AC (IMB) or DCT (PMB) coefficients |
|
2938 */ |
|
2939 if (iMBCodingType == VDX_MB_INTRA) |
|
2940 { |
|
2941 vdtPutIntraMBCMT(iOutBuffer,iDCTBlockData + i * BLOCK_COEFF_SIZE, &numTextureBits, i, 1, 0); |
|
2942 } |
|
2943 else |
|
2944 { |
|
2945 vdtPutInterMBCMT(iOutBuffer,0, iDCTBlockData + i * BLOCK_COEFF_SIZE, &numTextureBits, OFF); |
|
2946 } |
|
2947 } |
|
2948 } |
|
2949 else /* ouput the AC or DCT coefficients */ |
|
2950 { |
|
2951 bufEdit.copyMode = CopyWhole; /* CopyWhole */ |
|
2952 vdtCopyBuffer(iInBuffer,iOutBuffer, |
|
2953 iBlockStartByteIndex[i],iBlockStartBitIndex[i], |
|
2954 iBlockEndByteIndex[i],iBlockEndBitIndex[i]); |
|
2955 } |
|
2956 } |
|
2957 if (iColorEffect && (iMBCodingType == VDX_MB_INTRA)) |
|
2958 { |
|
2959 ResetMPEG4IntraDcUV(); |
|
2960 } |
|
2961 } |
|
2962 |
|
2963 |
|
2964 |
|
2965 /* |
|
2966 * AddOneBlockDataToMB |
|
2967 * |
|
2968 * Parameters: |
|
2969 * blockData block data before VLC coding, in ZigZag order |
|
2970 * Function: |
|
2971 * This function input one block data to current MB |
|
2972 * only here the whole MB data is retrieved (COD=0) |
|
2973 * Returns: |
|
2974 * None |
|
2975 * Error codes: |
|
2976 * None |
|
2977 * |
|
2978 */ |
|
2979 void CMPEG4Transcoder::AddOneBlockDataToMB(int aBlockIndex, int *aBlockData) |
|
2980 { |
|
2981 VDTASSERT(aBlockIndex >= 0 && aBlockIndex < 6); |
|
2982 |
|
2983 |
|
2984 if (aBlockData && iDoModeTranscoding) |
|
2985 { |
|
2986 /* iDCTBlockData is only used when we need to convert the bitstream to MPEG4_RESYN |
|
2987 It is a coded block |
|
2988 */ |
|
2989 if (iMBCodingType == VDX_MB_INTRA && (iTargetFormat == EVedVideoTypeH263Profile0Level10 || |
|
2990 iTargetFormat == EVedVideoTypeH263Profile0Level45)) |
|
2991 { |
|
2992 /* we only need the reconstructed DCACs, skipped */ |
|
2993 } |
|
2994 else |
|
2995 { |
|
2996 memcpy(iDCTBlockData + (aBlockIndex << 6), aBlockData, sizeof(int) * BLOCK_COEFF_SIZE); |
|
2997 } |
|
2998 } |
|
2999 else |
|
3000 { |
|
3001 memset(iDCTBlockData + (aBlockIndex << 6), 0, sizeof(int) * BLOCK_COEFF_SIZE); |
|
3002 } |
|
3003 |
|
3004 |
|
3005 |
|
3006 iBlockEndByteIndex[aBlockIndex] = iInBuffer->getIndex; |
|
3007 iBlockEndBitIndex[aBlockIndex] = iInBuffer->bitIndex; |
|
3008 } |
|
3009 |
|
3010 /* |
|
3011 * ErrorResilienceInfo |
|
3012 * |
|
3013 * Parameters: |
|
3014 * header VOL Header data |
|
3015 * Function: |
|
3016 * This function records the position of resnc_marker_disable bit |
|
3017 * Returns: |
|
3018 * None |
|
3019 * Error codes: |
|
3020 * None |
|
3021 * |
|
3022 */ |
|
3023 void CMPEG4Transcoder::ErrorResilienceInfo(vdxVolHeader_t *header, int aByte, int aBit) |
|
3024 { |
|
3025 if (header) |
|
3026 { |
|
3027 |
|
3028 memcpy(&iVOLHeader, header, sizeof(vdxVolHeader_t)); // save the header info |
|
3029 |
|
3030 } |
|
3031 else |
|
3032 { |
|
3033 iErrorResilienceStartByteIndex = aByte; /* save the bits position */ |
|
3034 iErrorResilienceStartBitIndex = aBit; |
|
3035 } |
|
3036 } |
|
3037 |
|
3038 |
|
3039 |
|
3040 /* |
|
3041 * MPEG4TimerResolution |
|
3042 * |
|
3043 * Parameters: |
|
3044 * |
|
3045 * Function: |
|
3046 * This function records the position of vop_time_increment_resolution bit |
|
3047 * Returns: |
|
3048 * None |
|
3049 * Error codes: |
|
3050 * None |
|
3051 * |
|
3052 */ |
|
3053 void CMPEG4Transcoder::MPEG4TimerResolution(int aStartByteIndex, int aStartBitIndex) |
|
3054 { |
|
3055 iTimeResolutionByteIndex = aStartByteIndex; |
|
3056 iTimeResolutionBitIndex = aStartBitIndex; |
|
3057 } |
|
3058 |
|
3059 |
|
3060 |
|
3061 void CMPEG4Transcoder::ConstructVOSHeader(int aMPEG4, vdeDecodeParamters_t *aDecoderInfo) |
|
3062 { |
|
3063 if (!aMPEG4 ) |
|
3064 { |
|
3065 /* for H263 and MPEG4 shortheader, no vos generated */ |
|
3066 if (iErrorResilienceStartByteIndex == KDataNotValid && |
|
3067 iErrorResilienceStartBitIndex == KDataNotValid) |
|
3068 { |
|
3069 iBitStreamMode = EVedVideoBitstreamModeH263; // pure H.263 |
|
3070 aDecoderInfo->vosHeaderSize = aDecoderInfo->fModeChanged? KH263ToMpeg4VosSize : 0; |
|
3071 } |
|
3072 else |
|
3073 { |
|
3074 /* we went into the VOL layer. It is a MPEG4 bitstream with short header */ |
|
3075 iBitStreamMode = EVedVideoBitstreamModeMPEG4ShortHeader; /* MPEG4 shortheader */ |
|
3076 iShortHeaderEndByteIndex = iInBuffer->getIndex; |
|
3077 iShortHeaderEndBitIndex = iInBuffer->bitIndex; |
|
3078 aDecoderInfo->vosHeaderSize = aDecoderInfo->fModeChanged? KH263ToMpeg4VosSize : KShortHeaderMpeg4VosSize; |
|
3079 } |
|
3080 fFirstFrameInH263 = ETrue; |
|
3081 } |
|
3082 else |
|
3083 { |
|
3084 iNumMBsInOneVOP = (iVDEInstance->lumHeight * iVDEInstance->lumWidth) / 256; |
|
3085 |
|
3086 /* even iBitStreamMode is given outside, we renew it here anyway */ |
|
3087 iBitStreamMode = sGetMPEG4Mode(iVOLHeader.error_res_disable, |
|
3088 iVOLHeader.data_partitioned, iVOLHeader.reversible_vlc); |
|
3089 |
|
3090 if (iTargetFormat != EVedVideoTypeH263Profile0Level10 && |
|
3091 iTargetFormat != EVedVideoTypeH263Profile0Level45) /* EVedVideoTypeMPEG4SimpleProfile or None */ |
|
3092 { |
|
3093 /* copy from the begining of the input buffer */ |
|
3094 vdtCopyBuffer(iInBuffer,iOutBuffer,0,7, iTimeResolutionByteIndex, iTimeResolutionBitIndex); |
|
3095 /* it is 16 bits */ |
|
3096 sPutBits (iOutBuffer, KMpeg4VopTimeIncrementResolutionLength, *aDecoderInfo->aMPEG4TargetTimeResolution); |
|
3097 |
|
3098 int startByteIndex, startBitIndex; |
|
3099 startByteIndex = iTimeResolutionByteIndex + 2; |
|
3100 startBitIndex = iTimeResolutionBitIndex; |
|
3101 |
|
3102 sPutBits(iOutBuffer, 1, MARKER_BIT); |
|
3103 /* close fixed_vop_rate */ |
|
3104 sPutBits (iOutBuffer, 1, 0); /* it is 1 bit */ |
|
3105 |
|
3106 int num_bits = 0; |
|
3107 vdcInstance_t * vdcTemp = (vdcInstance_t *)(iVDEInstance->vdcHInstance); |
|
3108 if (vdcTemp->pictureParam.fixed_vop_rate) |
|
3109 { |
|
3110 for (num_bits = 1; ((vdcTemp->pictureParam.time_increment_resolution-1) >> num_bits) != 0; num_bits++) |
|
3111 { |
|
3112 } |
|
3113 } |
|
3114 num_bits += 2; |
|
3115 |
|
3116 /* following is to skip the fixed_vop_rate */ |
|
3117 int bitsRemain, bitShift = 0; |
|
3118 int bitsToMove = 0 ; |
|
3119 /* complete the byte */ |
|
3120 if (startBitIndex != 7) |
|
3121 { |
|
3122 bitShift = startBitIndex + 1; |
|
3123 bitsToMove = (num_bits < bitShift) ? num_bits : bitShift; |
|
3124 /* update statistics to take care of bit addition or byte completion */ |
|
3125 if (num_bits < bitShift) |
|
3126 { |
|
3127 /* bits skipped but byte not completed */ |
|
3128 startBitIndex -= bitsToMove; |
|
3129 } |
|
3130 else |
|
3131 { |
|
3132 /* byte completed */ |
|
3133 startByteIndex ++; |
|
3134 startBitIndex = 7; |
|
3135 } |
|
3136 } |
|
3137 /* full bytes to skip */ |
|
3138 startByteIndex += ((num_bits - bitsToMove) >> 3); |
|
3139 bitsRemain = (num_bits - bitsToMove) % 8; |
|
3140 |
|
3141 /* the remaining bits */ |
|
3142 startBitIndex = ( bitsRemain != 0) ? 7 - bitsRemain : startBitIndex; |
|
3143 |
|
3144 |
|
3145 /* check if we have user data in the end of VOL; it cannot be copied as such but needs to be byte aligned */ |
|
3146 /* first need to rewind the input buffer to be able to seek in it */ |
|
3147 int16 error = 0; |
|
3148 int curByteIndex = iInBuffer->getIndex; |
|
3149 int curBitIndex = iInBuffer->bitIndex; |
|
3150 int bits = ((curByteIndex - iTimeResolutionByteIndex)<<3) + (7-curBitIndex); |
|
3151 bibRewindBits(bits, iInBuffer, &error); |
|
3152 int sncCode = sncSeekMPEGStartCode(iInBuffer, |
|
3153 vdcTemp->pictureParam.fcode_forward, 1 /* don't check VOPs */, 1 /* check for user data*/, &error); |
|
3154 |
|
3155 /* record next resync position */ |
|
3156 int resyncByteIndex = iInBuffer->getIndex; |
|
3157 |
|
3158 int stuffBits = 0; |
|
3159 int userDataExists = 0; |
|
3160 if ( sncCode == SNC_USERDATA ) |
|
3161 { |
|
3162 /* copy only until this sync code, and copy the rest separately in the end. */ |
|
3163 userDataExists = 1; |
|
3164 } |
|
3165 else |
|
3166 { |
|
3167 /* No UD */ |
|
3168 /* restore the original pointers in iInBuffer */ |
|
3169 iInBuffer->getIndex = curByteIndex; |
|
3170 iInBuffer->bitIndex = curBitIndex; |
|
3171 } |
|
3172 |
|
3173 if (iDoModeTranscoding || aDecoderInfo->fHaveDifferentModes) |
|
3174 { |
|
3175 /* close the error resilience tools, change the bitstream to regular MPEG4 with resyn marker */ |
|
3176 int numBits = iVOLHeader.data_partitioned ? 3 : 2; |
|
3177 |
|
3178 bufEdit.copyMode = CopyWithEdit; |
|
3179 bufEdit.editParams[0].StartByteIndex = iErrorResilienceStartByteIndex; |
|
3180 bufEdit.editParams[0].StartBitIndex = iErrorResilienceStartBitIndex; |
|
3181 bufEdit.editParams[0].curNumBits = numBits; |
|
3182 bufEdit.editParams[0].newNumBits = 2; |
|
3183 bufEdit.editParams[0].newValue = 0; /* new codeword: resyn, no dp, no rvlc */ |
|
3184 CopyStream(iInBuffer,iOutBuffer,&bufEdit, startByteIndex,startBitIndex); /* copy from vop_time_increment_resolution */ |
|
3185 |
|
3186 /* rewind stuffing bits */ |
|
3187 int16 error; |
|
3188 sncRewindStuffing(iOutBuffer, &error); |
|
3189 |
|
3190 // stuff bits in outbuffer for next start code |
|
3191 vdtStuffBitsMPEG4(iOutBuffer); |
|
3192 } |
|
3193 else |
|
3194 { |
|
3195 |
|
3196 /* rewind stuffing bits */ |
|
3197 sncRewindStuffing(iInBuffer, &error); |
|
3198 |
|
3199 /* record the number of bits rewinded - can be from 0 to 8 */ |
|
3200 /* note that iInBuffer must be byte aligned before rewinding */ |
|
3201 if (iInBuffer->bitIndex == 7) // full byte rewind |
|
3202 { |
|
3203 stuffBits = ( (int)(iInBuffer->getIndex) < resyncByteIndex) ? 8 : 0; |
|
3204 } |
|
3205 else |
|
3206 { |
|
3207 stuffBits = iInBuffer->bitIndex + 1; |
|
3208 } |
|
3209 |
|
3210 /* copy the rest of VOS until the first VOP (or UD) */ |
|
3211 bufEdit.copyMode = CopyWhole; |
|
3212 vdtCopyBuffer(iInBuffer,iOutBuffer, startByteIndex,startBitIndex, |
|
3213 resyncByteIndex, iInBuffer->bitIndex); |
|
3214 |
|
3215 // stuff bits in outbuffer for next start code |
|
3216 vdtStuffBitsMPEG4(iOutBuffer); |
|
3217 |
|
3218 // move inbuffer pointer back to original value |
|
3219 bibForwardBits(stuffBits, iInBuffer); |
|
3220 } |
|
3221 |
|
3222 |
|
3223 if ( userDataExists ) |
|
3224 { |
|
3225 /* seek for VOP start code */ |
|
3226 int sncCode = sncSeekMPEGStartCode(iInBuffer, |
|
3227 vdcTemp->pictureParam.fcode_forward, vdcTemp->pictureParam.error_res_disable, 0, &error); |
|
3228 |
|
3229 /* rewind stuffing bits */ |
|
3230 sncRewindStuffing(iInBuffer, &error); |
|
3231 |
|
3232 // record the number of bits rewinded - can be from 0 to 8 |
|
3233 // note that iInBuffer must be byte aligned before rewinding |
|
3234 if (iInBuffer->bitIndex == 7) // full byte rewind |
|
3235 { |
|
3236 stuffBits = ( (int)(iInBuffer->getIndex) < resyncByteIndex) ? 8 : 0; |
|
3237 } |
|
3238 else |
|
3239 { |
|
3240 stuffBits = iInBuffer->bitIndex + 1; |
|
3241 } |
|
3242 |
|
3243 bufEdit.copyMode = CopyWhole; |
|
3244 vdtCopyBuffer(iInBuffer,iOutBuffer, resyncByteIndex, 7, |
|
3245 iInBuffer->getIndex, iInBuffer->bitIndex); |
|
3246 |
|
3247 // stuff bits in outbuffer for next start code |
|
3248 vdtStuffBitsMPEG4(iOutBuffer); |
|
3249 |
|
3250 // move inbuffer pointer back to original value |
|
3251 bibForwardBits(stuffBits, iInBuffer); |
|
3252 |
|
3253 |
|
3254 |
|
3255 } |
|
3256 |
|
3257 aDecoderInfo->vosHeaderSize = iOutBuffer->getIndex; |
|
3258 } |
|
3259 |
|
3260 PRINT((_L("CMPEG4Transcoder: ConstructVOSHeader. resyn: %d, data partitioned: %d, rvlc: %d, resolution: %d"), |
|
3261 iVOLHeader.error_res_disable, iVOLHeader.data_partitioned, iVOLHeader.reversible_vlc, |
|
3262 aDecoderInfo->iTimeIncrementResolution)); |
|
3263 } |
|
3264 PRINT((_L("CMPEG4Transcoder: streammode: %d, outputformat: %d, vos size : %d"), |
|
3265 iBitStreamMode, iTargetFormat, aDecoderInfo->vosHeaderSize)); |
|
3266 } |
|
3267 |
|
3268 |
|
3269 |
|
3270 |
|
3271 /**************************************************************** |
|
3272 * * |
|
3273 * Functions for H.263, or H.263 -> MPEG4 (only baseline H.263) * |
|
3274 * * |
|
3275 *****************************************************************/ |
|
3276 |
|
3277 |
|
3278 /* Luminance block dc-scaler value corresponding to QP values of 0-31 */ |
|
3279 const u_int8 sLumDCScalerTbl[32] = |
|
3280 { |
|
3281 0, 8, 8, 8, 8, 10, 12, 14, |
|
3282 16, 17, 18, 19, 20, 21, 22, 23, |
|
3283 24, 25, 26, 27, 28, 29, 30, 31, |
|
3284 32, 34, 36, 38, 40, 42, 44, 46 |
|
3285 }; |
|
3286 |
|
3287 /* Chrominance block dc-scaler value corresponding to QP values of 0-31 */ |
|
3288 const u_int8 sChrDCScalerTbl[32] = |
|
3289 { |
|
3290 0, 8, 8, 8, 8, 9, 9, 10, |
|
3291 10, 11, 11, 12, 12, 13, 13, 14, |
|
3292 14, 15, 15, 16, 16, 17, 17, 18, |
|
3293 18, 19, 20, 21, 22, 23, 24, 25 |
|
3294 }; |
|
3295 |
|
3296 /* |
|
3297 * sGetMPEG4INTRADCValue |
|
3298 * |
|
3299 * Parameters: |
|
3300 * intraDC reconstructed intra DC from H263 |
|
3301 * QP quantion factor |
|
3302 * blockNum block number (0 to 5) |
|
3303 * currMBNum current MB number |
|
3304 * mbinWidth number of MBs in picure width |
|
3305 * dcData matrix to store the INTRA DC values |
|
3306 * mbVPNumber matrix recording the video packet number for each MB |
|
3307 * |
|
3308 * Function: |
|
3309 * This function gets the new intra DC for MPEG4 |
|
3310 * Returns: |
|
3311 * INTRA DC to put into MPEG4 bitstream |
|
3312 * Error codes: |
|
3313 * None |
|
3314 * |
|
3315 */ |
|
3316 int sGetMPEG4INTRADCValue(int intraDC, int blockNum, int currMBNum, |
|
3317 int32 QP, int32 mbinWidth, int **dcData, int *mbVPNumber) |
|
3318 { |
|
3319 int tempDCScaler; |
|
3320 int blockA = 0, blockB = 0, blockC = 0; |
|
3321 int gradHor, gradVer, predDC; |
|
3322 |
|
3323 VDTASSERT(currMBNum >= 0); |
|
3324 VDTASSERT(QP <= 31); |
|
3325 |
|
3326 /* Prediction blocks A (left), B (above-left), and C (above) */ |
|
3327 switch (blockNum) |
|
3328 { |
|
3329 case 0: |
|
3330 case 4: |
|
3331 case 5: |
|
3332 /* Y0, U, and V blocks */ |
|
3333 if (((currMBNum % mbinWidth) == 0) || /* Left edge */ |
|
3334 (mbVPNumber[currMBNum - 1] != mbVPNumber[currMBNum])) |
|
3335 { |
|
3336 blockA = 1024; /* fixed value for H263 */ |
|
3337 } |
|
3338 else |
|
3339 { |
|
3340 blockA = dcData[currMBNum - 1][blockNum > 3? blockNum : 1]; |
|
3341 } |
|
3342 |
|
3343 if (((currMBNum / mbinWidth) == 0) || /* Top Edge */ |
|
3344 ((currMBNum % mbinWidth) == 0) || /* Left Edge */ |
|
3345 (mbVPNumber[currMBNum - mbinWidth - 1] != mbVPNumber[currMBNum])) |
|
3346 { |
|
3347 blockB = 1024; |
|
3348 } |
|
3349 else |
|
3350 { |
|
3351 blockB = dcData[currMBNum - mbinWidth - 1][blockNum > 3? blockNum : 3]; |
|
3352 } |
|
3353 |
|
3354 if (((currMBNum / mbinWidth) == 0) || /* Top Edge */ |
|
3355 (mbVPNumber[currMBNum - mbinWidth] != mbVPNumber[currMBNum])) |
|
3356 { |
|
3357 blockC = 1024; |
|
3358 } |
|
3359 else |
|
3360 { |
|
3361 blockC = dcData[currMBNum - mbinWidth][blockNum > 3? blockNum : 2]; |
|
3362 } |
|
3363 break; |
|
3364 |
|
3365 case 1: |
|
3366 /* Y1 block */ |
|
3367 blockA = dcData[currMBNum][0]; |
|
3368 |
|
3369 if (((currMBNum / mbinWidth) == 0) || /* Top Edge */ |
|
3370 (mbVPNumber[currMBNum - mbinWidth] != mbVPNumber[currMBNum])) |
|
3371 { |
|
3372 blockB = 1024; |
|
3373 blockC = 1024; |
|
3374 } |
|
3375 else |
|
3376 { |
|
3377 blockB = dcData[currMBNum - mbinWidth][2]; |
|
3378 blockC = dcData[currMBNum - mbinWidth][3]; |
|
3379 } |
|
3380 break; |
|
3381 |
|
3382 case 2: |
|
3383 /* Y2 block */ |
|
3384 |
|
3385 if (((currMBNum % mbinWidth) == 0) || /* Left Edge */ |
|
3386 (mbVPNumber[currMBNum - 1] != mbVPNumber[currMBNum])) |
|
3387 { |
|
3388 blockA = 1024; |
|
3389 blockB = 1024; |
|
3390 } |
|
3391 else |
|
3392 { |
|
3393 blockA = dcData[currMBNum - 1][3]; |
|
3394 blockB = dcData[currMBNum - 1][1]; |
|
3395 } |
|
3396 |
|
3397 blockC = dcData[currMBNum][0]; |
|
3398 break; |
|
3399 |
|
3400 case 3: |
|
3401 /* Y3 block */ |
|
3402 |
|
3403 blockA = dcData[currMBNum][2]; |
|
3404 blockB = dcData[currMBNum][0]; |
|
3405 blockC = dcData[currMBNum][1]; |
|
3406 break; |
|
3407 |
|
3408 default: |
|
3409 break; |
|
3410 } |
|
3411 |
|
3412 gradHor = blockB - blockC; |
|
3413 gradVer = blockA - blockB; |
|
3414 |
|
3415 if ((abs(gradVer)) < (abs(gradHor))) |
|
3416 { |
|
3417 /* Vertical prediction (from C) */ |
|
3418 predDC = blockC; |
|
3419 } |
|
3420 else |
|
3421 { |
|
3422 /* Horizontal prediction (from A) */ |
|
3423 predDC = blockA; |
|
3424 } |
|
3425 |
|
3426 /* DC quantization */ |
|
3427 if (blockNum < 4) /* Luminance Block */ |
|
3428 { |
|
3429 intraDC += (sLumDCScalerTbl[QP] >> 1); |
|
3430 intraDC /= sLumDCScalerTbl[QP]; |
|
3431 |
|
3432 /* update the DC data matrix |
|
3433 note: for INTER MB, the entry is already preset to 1024!! |
|
3434 */ |
|
3435 dcData[currMBNum][blockNum] = intraDC * sLumDCScalerTbl[QP]; |
|
3436 } |
|
3437 else /* Chrominance block */ |
|
3438 { |
|
3439 intraDC += (sChrDCScalerTbl[QP] >> 1); |
|
3440 intraDC /= sChrDCScalerTbl[QP]; |
|
3441 /* update the DC data matrix |
|
3442 note: for INTER MB, the entry is already preset to 1024!! |
|
3443 */ |
|
3444 dcData[currMBNum][blockNum] = intraDC * sChrDCScalerTbl[QP]; |
|
3445 } |
|
3446 /* DC prediction */ |
|
3447 tempDCScaler = (blockNum<4)? sLumDCScalerTbl[QP] : sChrDCScalerTbl[QP]; |
|
3448 |
|
3449 return (intraDC - ((predDC + tempDCScaler/2) / tempDCScaler)); |
|
3450 } |
|
3451 |
|
3452 /* |
|
3453 * sPutVOLHeader |
|
3454 * |
|
3455 * Parameters: |
|
3456 * bitOut pointer to the output buffer |
|
3457 * aWidth picture width |
|
3458 * aHeight picture height |
|
3459 * aTimerResolution timer resolution for MPEG4 |
|
3460 * |
|
3461 * Function: |
|
3462 * This function writes the VOL header into bit-stream |
|
3463 * Returns: |
|
3464 * None |
|
3465 * Error codes: |
|
3466 * None |
|
3467 * |
|
3468 */ |
|
3469 inline void sPutVOLHeader(bibBuffer_t* bitOut, int aWidth, int aHeight, int aTimerResolution) |
|
3470 { |
|
3471 bibBuffer_t *lBitOut; |
|
3472 uint32 vop_time_increment_resolution; |
|
3473 |
|
3474 lBitOut = bitOut; |
|
3475 WRITE32(lBitOut, (uint32)VIDEO_OBJECT_LAYER_START_CODE); |
|
3476 /* RandomAccessibleVol == 1 means all VOP's can be decoded independently */ |
|
3477 sPutBits(lBitOut, 1, 0); |
|
3478 /* VideoObjectTypeIndication = SIMPLE OBJECT */ |
|
3479 sPutBits(lBitOut, 8, SIMPLE_OBJECT); |
|
3480 /* IsObjectLayerIdentifier */ |
|
3481 sPutBits(lBitOut, 1, 0); |
|
3482 /* AspectRatioInfo */ |
|
3483 sPutBits(lBitOut, 4, ASPECT_RATIO_INFO); |
|
3484 /* vol_control_parameters = 1 */ |
|
3485 sPutBits(lBitOut, 1, 1); |
|
3486 /* Chroma Format */ |
|
3487 sPutBits(lBitOut, 2, CHROMA_FORMAT); |
|
3488 /* LowDelay = 1; */ |
|
3489 sPutBits(lBitOut, 1, 1); |
|
3490 /* vbvParameters = 0; */ |
|
3491 sPutBits(lBitOut, 1, 0); |
|
3492 /* VideoObjectLayerShape == RECTANGULAR */ |
|
3493 sPutBits(lBitOut, 2, RECTANGULAR); |
|
3494 /* Marker Bit */ |
|
3495 sPutBits(lBitOut, 1, MARKER_BIT); |
|
3496 /* VopTimeIncrementResolution */ |
|
3497 vop_time_increment_resolution = aTimerResolution; |
|
3498 sPutBits(lBitOut, 16, vop_time_increment_resolution); |
|
3499 /* Marker Bit */ |
|
3500 sPutBits(lBitOut, 1, MARKER_BIT); |
|
3501 /* FixedVOPRate = 0, not fixed */ |
|
3502 sPutBits(lBitOut, 1, 0); |
|
3503 /* Marker Bit */ |
|
3504 sPutBits(lBitOut, 1, MARKER_BIT); |
|
3505 /* VideoObjectLayerWidth */ |
|
3506 sPutBits(lBitOut, 13, aWidth); |
|
3507 /* Marker Bit */ |
|
3508 sPutBits(lBitOut, 1, MARKER_BIT); |
|
3509 /* VideoObjectLayerHeight */ |
|
3510 sPutBits(lBitOut, 13, aHeight); |
|
3511 /* Marker Bit */ |
|
3512 sPutBits(lBitOut, 1, MARKER_BIT); |
|
3513 /* Interlaced = 0 */ |
|
3514 sPutBits(lBitOut, 1, 0); |
|
3515 /* ObmcDisable= 1 */ |
|
3516 sPutBits(lBitOut, 1, 1); |
|
3517 /* SpriteEnable = 0 */ |
|
3518 sPutBits(lBitOut, 1, 0); |
|
3519 /* Not8Bit = 0 */ |
|
3520 sPutBits(lBitOut, 1, 0); |
|
3521 /* QuantType = H263 (0) */ |
|
3522 sPutBits(lBitOut, 1, H263); |
|
3523 /* Complexity Estimation Disable = 1 */ |
|
3524 sPutBits(lBitOut, 1, 1); |
|
3525 /* ResyncMarkerDisable */ |
|
3526 sPutBits(lBitOut, 1, 0); /* H263 is converted to resyn_marker MPEG4 in video editor */ |
|
3527 /* DataPartioned */ |
|
3528 sPutBits(lBitOut, 1, 0); /* always 0 for H263 */ |
|
3529 /* Reversible VLC closed */ |
|
3530 /* Scalability = 0 */ |
|
3531 sPutBits(lBitOut, 1, 0); |
|
3532 vdtStuffBitsMPEG4(lBitOut); |
|
3533 |
|
3534 return; |
|
3535 } |
|
3536 |
|
3537 |
|
3538 /* |
|
3539 * sPutGOVHeader |
|
3540 * |
|
3541 * Parameters: |
|
3542 * bitOut pointer to the output buffer |
|
3543 * aModuloTimeBase time base for MPEG4 |
|
3544 * |
|
3545 * Function: |
|
3546 * This function writes the group of VOP(GOV) header into bit-stream |
|
3547 * Returns: |
|
3548 * None |
|
3549 * Error codes: |
|
3550 * None |
|
3551 * |
|
3552 */ |
|
3553 inline void sPutGOVHeader(bibBuffer_t *bitOut, int aModuloTimeBase) |
|
3554 { |
|
3555 int32 time_code_hours; |
|
3556 int32 time_code_minutes; |
|
3557 int32 time_code_seconds; |
|
3558 |
|
3559 WRITE32(bitOut, (uint32)GROUP_OF_VOP_START_CODE); |
|
3560 time_code_seconds = aModuloTimeBase; |
|
3561 time_code_minutes = time_code_seconds / 60; |
|
3562 time_code_hours = time_code_minutes / 60; |
|
3563 time_code_minutes = time_code_minutes - (time_code_hours * 60); |
|
3564 time_code_seconds = time_code_seconds - (time_code_minutes * 60) |
|
3565 - (time_code_hours * 3600); |
|
3566 |
|
3567 sPutBits(bitOut, 5, time_code_hours); |
|
3568 sPutBits(bitOut, 6, time_code_minutes); |
|
3569 sPutBits(bitOut, 1, MARKER_BIT); |
|
3570 sPutBits(bitOut, 6, time_code_seconds); |
|
3571 |
|
3572 /* ClosedGov */ |
|
3573 sPutBits(bitOut, 1, 0); |
|
3574 /* Broken Link */ |
|
3575 sPutBits(bitOut, 1, 0); |
|
3576 |
|
3577 /* Stuff bits */ |
|
3578 vdtStuffBitsMPEG4(bitOut); |
|
3579 |
|
3580 return; |
|
3581 } |
|
3582 |
|
3583 /* |
|
3584 * sConstructMPEG4VOSHeaderForH263 |
|
3585 * |
|
3586 * Parameters: |
|
3587 * bitOut pointer to the output buffer |
|
3588 * aWidth picture width |
|
3589 * aHeight picture height |
|
3590 * |
|
3591 * Function: |
|
3592 * This function writes the MPEG4 VOS header into bit-stream |
|
3593 * Returns: |
|
3594 * None |
|
3595 * Error codes: |
|
3596 * None |
|
3597 * |
|
3598 */ |
|
3599 void sConstructMPEG4VOSHeaderForH263(bibBuffer_t *bitOut, int aWidth, int aHeight, int aOutputMpeg4TimeRes) |
|
3600 { |
|
3601 /* visual object sequence header */ |
|
3602 WRITE32(bitOut, (uint32)VISUAL_OBJECT_SEQUENCE_START_CODE); |
|
3603 |
|
3604 /* This is for testing for level 0,3 */ |
|
3605 uint32 level = 8; /* level 0 for QCIF or less */ |
|
3606 if(aWidth > 176 || aHeight > 144) /* level 2 for greater than QCIF */ |
|
3607 level = 2; |
|
3608 sPutBits(bitOut, 8, level); /* simple profile, level 0 for H263 */ |
|
3609 |
|
3610 /* visual object header begins */ |
|
3611 WRITE32(bitOut, (uint32)VISUAL_OBJECT_START_CODE); |
|
3612 /* IsVisualObjectIdentifier = 0 */ |
|
3613 sPutBits(bitOut, 1, 0); |
|
3614 /* VisualObjectType = VIDEO_OBJECT */ |
|
3615 sPutBits(bitOut, 4, VISUAL_OBJECT); |
|
3616 /* VideoSignalType = 0 */ |
|
3617 sPutBits(bitOut, 1, 0); |
|
3618 |
|
3619 vdtStuffBitsMPEG4(bitOut); |
|
3620 WRITE32(bitOut, (uint32)VIDEO_OBJECT_START_CODE); |
|
3621 |
|
3622 /* Writes the VOL header into bit-stream , for baseline H263 TR is marked with 29.97fps. ->? */ |
|
3623 sPutVOLHeader(bitOut, aWidth, aHeight, aOutputMpeg4TimeRes); |
|
3624 |
|
3625 /* Writes GOV , time base is 0 */ |
|
3626 sPutGOVHeader(bitOut, 0); |
|
3627 |
|
3628 return; |
|
3629 } |
|
3630 |
|
3631 |
|
3632 /* |
|
3633 * sPutVideoPacketHeader |
|
3634 * |
|
3635 * Parameters: |
|
3636 * lBitOut output buffer |
|
3637 * mbNo Macroblock number |
|
3638 * quantiserScale quant value to be put in header |
|
3639 * aMBsInVOP # of MBs in one VOP |
|
3640 * |
|
3641 * Function: |
|
3642 * This function writes the video packet header information into bit-stream |
|
3643 * Returns: |
|
3644 * None |
|
3645 * Error codes: |
|
3646 * None |
|
3647 * |
|
3648 */ |
|
3649 inline void sPutVideoPacketHeader(bibBuffer_t *lBitOut, int32 mbNo, |
|
3650 int16 quantiserScale, |
|
3651 int aMBsInVOP) |
|
3652 { |
|
3653 int32 lResyncMarkerLength = 17; |
|
3654 int32 lMBNoResolution; |
|
3655 |
|
3656 /* ResyncMarker */ |
|
3657 int fCode = 1; /*always 1 for H263 */ |
|
3658 lResyncMarkerLength = 16 + fCode; |
|
3659 sPutBits(lBitOut, lResyncMarkerLength, 1); |
|
3660 |
|
3661 --aMBsInVOP; |
|
3662 lMBNoResolution = 1; |
|
3663 while( (aMBsInVOP = |
|
3664 aMBsInVOP >> 1) > 0 ) |
|
3665 { |
|
3666 lMBNoResolution++; |
|
3667 } |
|
3668 sPutBits(lBitOut, lMBNoResolution, mbNo); |
|
3669 |
|
3670 /* QuantScale */ |
|
3671 sPutBits(lBitOut, 5, quantiserScale); |
|
3672 /* HEC */ |
|
3673 sPutBits(lBitOut, 1, 0); /* always 0 for H263 */ |
|
3674 |
|
3675 return; |
|
3676 } |
|
3677 |
|
3678 /* |
|
3679 * sConstructVOPHeaderForH263 |
|
3680 * |
|
3681 * Parameters: |
|
3682 * lBitOut output buffer |
|
3683 * prevQuant quant value to be put in header |
|
3684 * aVOPType picture coding type |
|
3685 * aVOPTimeIncrement time increament |
|
3686 * |
|
3687 * Function: |
|
3688 * This function writes the VOP header into bit-stream for one H263 frame |
|
3689 * Returns: |
|
3690 * None |
|
3691 * Error codes: |
|
3692 * None |
|
3693 * |
|
3694 */ |
|
3695 |
|
3696 void sConstructVOPHeaderForH263(bibBuffer_t *lBitOut, int prevQuant, int aVOPType, int aVOPTimeIncrement,int aOutputMpeg4TimeRes) |
|
3697 { |
|
3698 WRITE32(lBitOut, (uint32)VOP_START_CODE); |
|
3699 /* VOPType, 0 for Intra and 1 for inter */ |
|
3700 sPutBits(lBitOut, 2, aVOPType); |
|
3701 |
|
3702 /* H263 TR is marked with 29.97fps */ |
|
3703 /* Modulo Time Base */ |
|
3704 int outputTimerResolution = aOutputMpeg4TimeRes; |
|
3705 while ((unsigned)aVOPTimeIncrement >= (unsigned) outputTimerResolution) |
|
3706 { |
|
3707 sPutBits(lBitOut, 1, 1); |
|
3708 aVOPTimeIncrement -= outputTimerResolution; |
|
3709 } |
|
3710 sPutBits(lBitOut, 1, 0); |
|
3711 /* Marker Bit */ |
|
3712 sPutBits(lBitOut, 1, MARKER_BIT); |
|
3713 /* VopTimeIncrement */ |
|
3714 int numOutputTrBits; |
|
3715 for (numOutputTrBits = 1; ((outputTimerResolution-1) >> numOutputTrBits) != 0; numOutputTrBits++) |
|
3716 { |
|
3717 } |
|
3718 int VOPIncrementResolutionLength = numOutputTrBits; |
|
3719 sPutBits(lBitOut, VOPIncrementResolutionLength, aVOPTimeIncrement); |
|
3720 /* Marker Bit */ |
|
3721 sPutBits(lBitOut, 1, MARKER_BIT); |
|
3722 /* VOPCoded */ |
|
3723 sPutBits(lBitOut, 1, 1); /* always 1 for H263 */ |
|
3724 /* VOPRoundingType */ |
|
3725 if(aVOPType == P_VOP) |
|
3726 { |
|
3727 sPutBits(lBitOut, 1, 0); /* always 0 for H263 */ |
|
3728 } |
|
3729 /* IntraDCVLCThreshold */ |
|
3730 sPutBits(lBitOut, 3, 0); /* always 0 for H263 */ |
|
3731 /* VOPQuant */ |
|
3732 sPutBits(lBitOut, 5, prevQuant); |
|
3733 /* VOPFcodeForwad */ |
|
3734 if(aVOPType == P_VOP) |
|
3735 { |
|
3736 sPutBits(lBitOut, 3, 1); /* always 1 for H263 */ |
|
3737 } |
|
3738 |
|
3739 return; |
|
3740 } |
|
3741 |
|
3742 |
|
3743 |
|
3744 /* |
|
3745 * H263PictureHeaderEndedL |
|
3746 * |
|
3747 * Parameters: |
|
3748 * |
|
3749 * Function: |
|
3750 * This function is called after one H263 picture header is parsed |
|
3751 * Note: the input header is only valid inside this function |
|
3752 * Returns: |
|
3753 * VDC error codes |
|
3754 * Error codes: |
|
3755 * None |
|
3756 * |
|
3757 */ |
|
3758 int CMPEG4Transcoder::H263PictureHeaderEnded(dphOutParam_t *aH263PicHeader, dphInOutParam_t *aInfo) |
|
3759 { |
|
3760 VDTASSERT(aH263PicHeader); |
|
3761 |
|
3762 // asad |
|
3763 if (!aInfo->vdcInstance->frameNum || !iRefQuant) |
|
3764 { |
|
3765 iRefQuant = aH263PicHeader->pquant; |
|
3766 iDcScaler = GetMpeg4DcScalerUV(iRefQuant); |
|
3767 } |
|
3768 |
|
3769 if (!iDoModeTranscoding ) |
|
3770 { |
|
3771 |
|
3772 /* Copy the header to output stream */ |
|
3773 bufEdit.copyMode = CopyWhole; /* CopyWhole */ |
|
3774 |
|
3775 if ( (iTargetFormat == EVedVideoTypeH263Profile0Level10 || iTargetFormat == EVedVideoTypeH263Profile0Level45) && |
|
3776 fFirstFrameInH263 && iBitStreamMode == EVedVideoBitstreamModeMPEG4ShortHeader) |
|
3777 { |
|
3778 /* we don't need the VOS header, remove it */ |
|
3779 PRINT((_L("CMPEG4Transcoder: MPEG4 shortheader VOS removed"))); |
|
3780 |
|
3781 CopyStream(iInBuffer,iOutBuffer,&bufEdit,iShortHeaderEndByteIndex,iShortHeaderEndBitIndex); |
|
3782 fFirstFrameInH263 = EFalse; |
|
3783 } |
|
3784 else |
|
3785 { |
|
3786 /* copy from the begining of the input buffer, |
|
3787 including the VOS header for MPEG4 shortheader if its mode is not being changed |
|
3788 */ |
|
3789 CopyStream(iInBuffer,iOutBuffer,&bufEdit,0,7); |
|
3790 } |
|
3791 } |
|
3792 |
|
3793 |
|
3794 |
|
3795 else |
|
3796 { |
|
3797 /* H263 Picture Header -> MPEG4 VOP Header mapping |
|
3798 information about this frame |
|
3799 */ |
|
3800 iMBsinWidth = aInfo->vdcInstance->pictureParam.lumWidth >> 4; |
|
3801 |
|
3802 iNumMBsInOneVOP = (aInfo->vdcInstance->pictureParam.lumWidth >> 4) * |
|
3803 (aInfo->vdcInstance->pictureParam.lumHeight >> 4); |
|
3804 |
|
3805 iNumMBsInGOB = aInfo->vdcInstance->pictureParam.numMBsInGOB; |
|
3806 |
|
3807 /* create the intraDC matrix for DC prediction */ |
|
3808 VDTASSERT(!iH263DCData); |
|
3809 VDTASSERT(!iH263MBVPNum); |
|
3810 |
|
3811 iH263DCData = (int **)malloc(iNumMBsInOneVOP * sizeof(int)); |
|
3812 if (!iH263DCData) |
|
3813 { |
|
3814 deb("CMPEG4Transcoder::ERROR - iH263DCData creation failed\n"); |
|
3815 return TX_ERR; |
|
3816 } |
|
3817 |
|
3818 for (int i = 0; i < iNumMBsInOneVOP; i++) |
|
3819 { |
|
3820 iH263DCData[i] = (int *) malloc(6 * sizeof(int)); /* six blocks in one MB */ |
|
3821 VDTASSERT(iH263DCData[i]); |
|
3822 if (!iH263DCData[i]) |
|
3823 { |
|
3824 deb("CMPEG4Transcoder::ERROR - iH263DCData[i] creation failed\n"); |
|
3825 |
|
3826 for(int k=0; k<i; k++) |
|
3827 { |
|
3828 free (iH263DCData[k]); |
|
3829 } |
|
3830 if (iH263DCData) |
|
3831 { |
|
3832 free(iH263DCData); |
|
3833 } |
|
3834 |
|
3835 return TX_ERR; |
|
3836 } |
|
3837 |
|
3838 |
|
3839 /* initialize each entry to 1024 for DC prediction */ |
|
3840 for (int j = 0; j < 6; j++) |
|
3841 { |
|
3842 iH263DCData[i][j] = 1024; |
|
3843 } |
|
3844 } |
|
3845 |
|
3846 iH263MBVPNum = (int *) malloc(iNumMBsInOneVOP * sizeof(int)); |
|
3847 if (!iH263MBVPNum) |
|
3848 { |
|
3849 deb("CMPEG4Transcoder::ERROR - iH263MBVPNum creation failed\n"); |
|
3850 return TX_ERR; |
|
3851 } |
|
3852 |
|
3853 memset(iH263MBVPNum, 0, iNumMBsInOneVOP * sizeof(int)); |
|
3854 int pictureType = aInfo->vdcInstance->pictureParam.pictureType == VDX_PIC_TYPE_I? I_VOP : P_VOP; |
|
3855 |
|
3856 if (fFirstFrameInH263) |
|
3857 { |
|
3858 /* first frame, construct the VOS header */ |
|
3859 sConstructMPEG4VOSHeaderForH263(iOutBuffer, |
|
3860 aInfo->vdcInstance->pictureParam.lumWidth, |
|
3861 aInfo->vdcInstance->pictureParam.lumHeight, |
|
3862 iOutputMpeg4TimeIncResolution); |
|
3863 fFirstFrameInH263 = EFalse; |
|
3864 |
|
3865 PRINT((_L("CMPEG4Transcoder: H263 -> MPEG VOS generated"))); |
|
3866 } |
|
3867 sConstructVOPHeaderForH263(iOutBuffer, aH263PicHeader->pquant, pictureType, aH263PicHeader->trp == -1 ? 0 : aH263PicHeader->trp,iOutputMpeg4TimeIncResolution); |
|
3868 |
|
3869 |
|
3870 PRINT((_L("CMPEG4Transcoder: H263 -> MPEG4: transcoding one picture"))); |
|
3871 } |
|
3872 |
|
3873 |
|
3874 PRINT((_L("CMPEG4Transcoder: H263PictureHeaderEndedL. color effect: %d, format convert %d, do transcoding: %d streammode: %d, outputformat: %d "), |
|
3875 iColorEffect, iDoModeTranscoding, iDoTranscoding, |
|
3876 iBitStreamMode, iTargetFormat)); |
|
3877 |
|
3878 return TX_OK; |
|
3879 } |
|
3880 |
|
3881 /* |
|
3882 * H263GOBSliceHeaderEnded |
|
3883 * |
|
3884 * Parameters: |
|
3885 * |
|
3886 * Function: |
|
3887 * This function is called after one H263 GOB or Slice header is parsed |
|
3888 * Returns: |
|
3889 * None |
|
3890 * Error codes: |
|
3891 * None |
|
3892 * |
|
3893 */ |
|
3894 void CMPEG4Transcoder::H263GOBSliceHeaderEnded(vdxGOBHeader_t *aH263GOBHeader, vdxSliceHeader_t */*aH263SliceHeader*/) |
|
3895 { |
|
3896 iGOBSliceHeaderEndByteIndex = iInBuffer->getIndex; |
|
3897 iGOBSliceHeaderEndBitIndex = iInBuffer->bitIndex; |
|
3898 |
|
3899 if (aH263GOBHeader) |
|
3900 { |
|
3901 /* not the first GOB (no header), we have stuffing bits ahead |
|
3902 since we only store the position of GBSC not including |
|
3903 the stuffing bits, we may need to insert the stuffing bits here |
|
3904 if we have color effect, we have done the stuffing at the end of last GOB |
|
3905 see functin: H263OneGOBSliceWithHeaderEnded |
|
3906 */ |
|
3907 sStuffBitsH263(iOutBuffer); |
|
3908 } |
|
3909 |
|
3910 if (!iDoModeTranscoding) |
|
3911 { |
|
3912 /* Copy the header to output stream */ |
|
3913 bufEdit.copyMode = CopyWhole; // whole |
|
3914 CopyStream(iInBuffer,iOutBuffer,&bufEdit,iGOBSliceStartByteIndex,iGOBSliceStartBitIndex); |
|
3915 |
|
3916 } |
|
3917 |
|
3918 else |
|
3919 { |
|
3920 /* H263 GOB (Slice) Header -> MPEG4 VP Header mapping */ |
|
3921 if (!VDT_NO_DATA((int)iInBuffer->getIndex, iInBuffer->bitIndex, iGOBSliceStartByteIndex, iGOBSliceStartBitIndex) && |
|
3922 aH263GOBHeader) |
|
3923 { |
|
3924 /* sPutVideoPacketHeader */ |
|
3925 sPutVideoPacketHeader(iOutBuffer, aH263GOBHeader->gn * iNumMBsInGOB, (short)aH263GOBHeader->gquant, iNumMBsInOneVOP); |
|
3926 } |
|
3927 } |
|
3928 |
|
3929 // one slice ended, new video packet starting |
|
3930 iCurMBNumInVP = -1; |
|
3931 |
|
3932 } |
|
3933 |
|
3934 |
|
3935 /* |
|
3936 * H263GOBSliceHeaderBegin |
|
3937 * |
|
3938 * Parameters: |
|
3939 * |
|
3940 * Function: |
|
3941 * This function is called before one H263 GOB or Slice header is parsed |
|
3942 * Returns: |
|
3943 * None |
|
3944 * Error codes: |
|
3945 * None |
|
3946 * |
|
3947 */ |
|
3948 void CMPEG4Transcoder::H263GOBSliceHeaderBegin() |
|
3949 { |
|
3950 /* position not include the stuffing bits ahead of the GBSC ! */ |
|
3951 iGOBSliceStartByteIndex = iInBuffer->getIndex; |
|
3952 iGOBSliceStartBitIndex = iInBuffer->bitIndex; |
|
3953 iStuffingBitsUsed = 0; |
|
3954 } |
|
3955 |
|
3956 |
|
3957 /* |
|
3958 * H263GOBSliceHeaderBegin |
|
3959 * |
|
3960 * Parameters: |
|
3961 * |
|
3962 * Function: |
|
3963 * This function is called after one H263 GOB or Slice ends |
|
3964 * Returns: |
|
3965 * None |
|
3966 * Error codes: |
|
3967 * None |
|
3968 * |
|
3969 */ |
|
3970 void CMPEG4Transcoder::H263OneGOBSliceEnded(int nextExpectedMBNum) |
|
3971 { |
|
3972 if (iDoTranscoding) |
|
3973 { |
|
3974 /* MBs are lost or not coded, for H263 and H263->MPEG4 both */ |
|
3975 for (int i = iLastMBNum+1; i < nextExpectedMBNum; i++) |
|
3976 { |
|
3977 /* output 1 bit COD */ |
|
3978 sPutBits (iOutBuffer, 1, 1); |
|
3979 } |
|
3980 iLastMBNum = nextExpectedMBNum - 1; |
|
3981 } |
|
3982 } |
|
3983 |
|
3984 |
|
3985 /* |
|
3986 * H263OneGOBSliceWithHeaderEnded |
|
3987 * |
|
3988 * Parameters: |
|
3989 * |
|
3990 * Function: |
|
3991 * This function is called after GOB (Slice) that has GOB header (except the first GOB) ends |
|
3992 * Returns: |
|
3993 * None |
|
3994 * Error codes: |
|
3995 * None |
|
3996 * |
|
3997 */ |
|
3998 void CMPEG4Transcoder::H263OneGOBSliceWithHeaderEnded() |
|
3999 { |
|
4000 if (!iDoTranscoding) |
|
4001 { |
|
4002 bufEdit.copyMode = CopyWhole; /* CopyWhole */ |
|
4003 CopyStream(iInBuffer,iOutBuffer,&bufEdit, |
|
4004 iGOBSliceHeaderEndByteIndex,iGOBSliceHeaderEndBitIndex); |
|
4005 } |
|
4006 else |
|
4007 { |
|
4008 |
|
4009 if (iDoModeTranscoding) |
|
4010 { |
|
4011 /* for H263 to MPEG4, it implies that one video packet is finished */ |
|
4012 vdtStuffBitsMPEG4(iOutBuffer); |
|
4013 } |
|
4014 else |
|
4015 |
|
4016 { |
|
4017 /* stuffing occurs outside at the end of one GOB/slice withe header or end of frame, check in file core.cpp */ |
|
4018 sStuffBitsH263(iOutBuffer); |
|
4019 } |
|
4020 iVideoPacketNumInMPEG4 ++; |
|
4021 } |
|
4022 |
|
4023 // one slice ended, new video packet starting |
|
4024 iCurMBNumInVP = -1; // 0 |
|
4025 |
|
4026 } |
|
4027 |
|
4028 |
|
4029 |
|
4030 /* |
|
4031 * H263ToMPEG4MBData |
|
4032 * |
|
4033 * Parameters: |
|
4034 * |
|
4035 * Function: |
|
4036 * This function transcodes one H263 MB to one MPEG4 MB |
|
4037 * Returns: |
|
4038 * None |
|
4039 * Error codes: |
|
4040 * None |
|
4041 * |
|
4042 */ |
|
4043 void CMPEG4Transcoder::H263ToMPEG4MBData(int aNewMCBPCLen, int aNewMCBPC) |
|
4044 { |
|
4045 /* MB data part1: output MCBPC, CBPY, DQuant, MV, intra DC etc */ |
|
4046 int *dataItemStartByteIndex; |
|
4047 int *dataItemStartBitIndex; |
|
4048 int *dataItemEndByteIndex; |
|
4049 int *dataItemEndBitIndex; |
|
4050 int quant, cbpy, cbpc; |
|
4051 |
|
4052 if (iVopCodingType == VDX_VOP_TYPE_P) |
|
4053 { |
|
4054 dataItemStartByteIndex = iCurPMBinstance->DataItemStartByteIndex; |
|
4055 dataItemStartBitIndex = iCurPMBinstance->DataItemStartBitIndex; |
|
4056 dataItemEndByteIndex = iCurPMBinstance->DataItemEndByteIndex; |
|
4057 dataItemEndBitIndex = iCurPMBinstance->DataItemEndBitIndex; |
|
4058 quant = iCurPMBinstance->quant; |
|
4059 cbpy = iCurPMBinstance->cbpy; |
|
4060 cbpc = iCurPMBinstance->cbpc; |
|
4061 } |
|
4062 else |
|
4063 { |
|
4064 dataItemStartByteIndex = iCurIMBinstance->DataItemStartByteIndex; |
|
4065 dataItemStartBitIndex = iCurIMBinstance->DataItemStartBitIndex; |
|
4066 dataItemEndByteIndex = iCurIMBinstance->DataItemEndByteIndex; |
|
4067 dataItemEndBitIndex = iCurIMBinstance->DataItemEndBitIndex; |
|
4068 quant = iCurIMBinstance->quant; |
|
4069 cbpy = iCurIMBinstance->cbpy; |
|
4070 cbpc = iCurIMBinstance->cbpc; |
|
4071 } |
|
4072 |
|
4073 /* COD and MCBPC, (for I frame, it is MCBPC, for P frame it is COD and MCBPC) */ |
|
4074 if (iVopCodingType == VDX_VOP_TYPE_P) |
|
4075 { |
|
4076 /* It is a coded MB, output 1 bit COD (it always exists in P frame) */ |
|
4077 sPutBits (iOutBuffer, 1, 0); |
|
4078 } |
|
4079 |
|
4080 if (iColorEffect) |
|
4081 { |
|
4082 /* MCBPC Changed */ |
|
4083 sPutBits(iOutBuffer, aNewMCBPCLen, aNewMCBPC); |
|
4084 } |
|
4085 else |
|
4086 { |
|
4087 /* remember the positions do not include the possible stuffing MCBPC bits */ |
|
4088 vdtCopyBuffer(iInBuffer, iOutBuffer, |
|
4089 dataItemStartByteIndex[0], dataItemStartBitIndex[0], |
|
4090 dataItemEndByteIndex[0], dataItemEndBitIndex[0]); |
|
4091 } |
|
4092 |
|
4093 /* ac_pred_flag */ |
|
4094 if (iMBCodingType == VDX_MB_INTRA) |
|
4095 { |
|
4096 sPutBits(iOutBuffer, 1, 0);// it is closed for H263 INTRA MB |
|
4097 } |
|
4098 |
|
4099 /* CBPY */ |
|
4100 vdtCopyBuffer(iInBuffer, iOutBuffer, |
|
4101 dataItemStartByteIndex[2], dataItemStartBitIndex[2], |
|
4102 dataItemEndByteIndex[2], dataItemEndBitIndex[2]); |
|
4103 |
|
4104 /* DQUANT, if it exsits */ |
|
4105 vdtCopyBuffer(iInBuffer, iOutBuffer, |
|
4106 dataItemStartByteIndex[1], dataItemStartBitIndex[1], |
|
4107 dataItemEndByteIndex[1], dataItemEndBitIndex[1]); |
|
4108 |
|
4109 if (iMBCodingType == VDX_MB_INTER) |
|
4110 { |
|
4111 /* MVs, if they exsit */ |
|
4112 vdtCopyBuffer(iInBuffer, iOutBuffer, |
|
4113 dataItemStartByteIndex[10], dataItemStartBitIndex[10], |
|
4114 dataItemEndByteIndex[10], dataItemEndBitIndex[10]); |
|
4115 } |
|
4116 |
|
4117 /* following is the block level data */ |
|
4118 for (int i = 0; i < (iColorEffect? 4 : 6); i++) |
|
4119 { |
|
4120 if (iMBCodingType == VDX_MB_INTRA) |
|
4121 { |
|
4122 int fBlockCoded = 0; |
|
4123 if (i < 4) |
|
4124 { |
|
4125 fBlockCoded = vdxIsYCoded(cbpy, i + 1); |
|
4126 } |
|
4127 else if (i == 4) |
|
4128 { |
|
4129 fBlockCoded = vdxIsUCoded(cbpc); |
|
4130 } |
|
4131 else |
|
4132 { |
|
4133 fBlockCoded = vdxIsVCoded(cbpc); |
|
4134 } |
|
4135 |
|
4136 /* Difference between H263 and MPEG4 : |
|
4137 0. DC quantization is different, DC need to be dequantized and requantized |
|
4138 Note: for ACs, here we only support H263 quantization in MPEG4, we can copy them |
|
4139 1. DC prediction is used in MPEG4 |
|
4140 2. They use different VLC table for INTRA AC coefficient |
|
4141 */ |
|
4142 /* reconstuct INTRA DC */ |
|
4143 int intraDC = (iDCTBlockData + i * BLOCK_COEFF_SIZE)[0]; /* it is already dequantized in funcion vdxGetIntraDCTBlock */ |
|
4144 |
|
4145 /* INTRA quantization and prediction */ |
|
4146 (iDCTBlockData + i * BLOCK_COEFF_SIZE)[0] = sGetMPEG4INTRADCValue(intraDC, |
|
4147 i, iCurMBNum, quant, iMBsinWidth,iH263DCData, iH263MBVPNum); |
|
4148 |
|
4149 /* recoding the INTRA block */ |
|
4150 int numTextureBits = 0; |
|
4151 |
|
4152 vdtPutIntraMBCMT(iOutBuffer,iDCTBlockData + i * BLOCK_COEFF_SIZE, &numTextureBits, i, 0, 1); /* DC coding */ |
|
4153 |
|
4154 if (fBlockCoded) |
|
4155 { |
|
4156 vdtPutIntraMBCMT(iOutBuffer,iDCTBlockData + i * BLOCK_COEFF_SIZE, &numTextureBits, i, 1, 0); /*encode ACs */ |
|
4157 } |
|
4158 |
|
4159 } |
|
4160 |
|
4161 else if (!(VDT_NO_DATA(iBlockStartByteIndex[i], iBlockStartBitIndex[i], |
|
4162 iBlockEndByteIndex[i], iBlockEndBitIndex[i]))) |
|
4163 { |
|
4164 |
|
4165 /* 4. same VLC table for DCTs in H263 and MPEG4, but with different Escape Coding type. |
|
4166 see 7.4.1.3. in MPEG4 draft |
|
4167 */ |
|
4168 if (iEscapeCodeUsed[i]) |
|
4169 { |
|
4170 int numTextureBits = 0; |
|
4171 vdtPutInterMBCMT(iOutBuffer,0, iDCTBlockData + i * BLOCK_COEFF_SIZE, &numTextureBits, OFF); |
|
4172 } |
|
4173 else |
|
4174 { |
|
4175 bufEdit.copyMode = CopyWhole; /* CopyWhole */ |
|
4176 vdtCopyBuffer(iInBuffer,iOutBuffer, |
|
4177 iBlockStartByteIndex[i],iBlockStartBitIndex[i], |
|
4178 iBlockEndByteIndex[i],iBlockEndBitIndex[i]); |
|
4179 } |
|
4180 } |
|
4181 } |
|
4182 |
|
4183 if (iColorEffect && (iMBCodingType == VDX_MB_INTRA)) |
|
4184 { |
|
4185 ResetMPEG4IntraDcUV(); |
|
4186 } |
|
4187 } |
|
4188 |
|
4189 |
|
4190 |
|
4191 /* |
|
4192 * NeedDecodedYUVFrame |
|
4193 * |
|
4194 * Parameters: |
|
4195 * |
|
4196 * Function: |
|
4197 * This function indicates if whether we need the decoded frame |
|
4198 * Returns: |
|
4199 * ETrue if we need the decoded frame |
|
4200 * Error codes: |
|
4201 * None |
|
4202 * |
|
4203 */ |
|
4204 int CMPEG4Transcoder::NeedDecodedYUVFrame() |
|
4205 { |
|
4206 if ( (iTargetFormat == EVedVideoTypeH263Profile0Level10 || iTargetFormat == EVedVideoTypeH263Profile0Level45) && |
|
4207 iBitStreamMode !=EVedVideoBitstreamModeMPEG4ShortHeader && iBitStreamMode != EVedVideoBitstreamModeH263) |
|
4208 return ETrue; |
|
4209 else |
|
4210 return EFalse; |
|
4211 } |
|
4212 |
|
4213 /* |
|
4214 * NewL |
|
4215 * |
|
4216 * Parameters: |
|
4217 * |
|
4218 * Function: |
|
4219 * Symbian two-phased constructor |
|
4220 * Returns: |
|
4221 * pointer to constructed object, or NULL |
|
4222 * Error codes: |
|
4223 * None |
|
4224 * |
|
4225 */ |
|
4226 CMPEG4Transcoder* CMPEG4Transcoder::NewL(const vdeInstance_t *aVDEInstance, bibBuffer_t *aInBuffer, bibBuffer_t *aOutBuffer) |
|
4227 { |
|
4228 CMPEG4Transcoder *self = new (ELeave) CMPEG4Transcoder(aVDEInstance, aInBuffer, aOutBuffer); |
|
4229 CleanupStack::PushL(self); |
|
4230 self->ConstructL(); |
|
4231 CleanupStack::Pop(self); |
|
4232 |
|
4233 return self; |
|
4234 } |
|
4235 |
|
4236 |
|
4237 /* |
|
4238 * ConstructL |
|
4239 * |
|
4240 * Parameters: |
|
4241 * |
|
4242 * Function: |
|
4243 * Symbian 2nd phase constructor (can leave) |
|
4244 * Returns: |
|
4245 * None |
|
4246 * Error codes: |
|
4247 * None |
|
4248 * |
|
4249 */ |
|
4250 void CMPEG4Transcoder::ConstructL() |
|
4251 { |
|
4252 |
|
4253 /* Create one IMB Instance */ |
|
4254 iCurIMBinstance = (vdxIMBListItem_t *) malloc(sizeof(vdxIMBListItem_t)); |
|
4255 if (!iCurIMBinstance) |
|
4256 { |
|
4257 deb("CMPEG4Transcoder::ERROR - iCurIMBinstance creation failed\n"); |
|
4258 User::Leave(KErrNoMemory); |
|
4259 |
|
4260 } |
|
4261 memset(iCurIMBinstance, 0, sizeof(vdxIMBListItem_t)); |
|
4262 |
|
4263 /* Create one PMBInstance */ |
|
4264 iCurPMBinstance = (vdxPMBListItem_t *) malloc(sizeof(vdxPMBListItem_t)); |
|
4265 if (!iCurPMBinstance) |
|
4266 { |
|
4267 deb("CMPEG4Transcoder::ERROR - iCurPMBinstance creation failed\n"); |
|
4268 User::Leave(KErrNoMemory); |
|
4269 |
|
4270 } |
|
4271 memset(iCurPMBinstance, 0, sizeof(vdxPMBListItem_t)); |
|
4272 |
|
4273 /* initialize the edit buffer */ |
|
4274 bufEdit.editParams = (bibEditParams_t *) malloc(sizeof(bibEditParams_t)); |
|
4275 VDTASSERT(bufEdit.editParams); |
|
4276 if (!bufEdit.editParams) |
|
4277 { |
|
4278 deb("CMPEG4Transcoder::ERROR - bufEdit.editParams creation failed\n"); |
|
4279 User::Leave(KErrNoMemory); |
|
4280 |
|
4281 }else{ |
|
4282 bufEdit.numChanges = 1; |
|
4283 } |
|
4284 |
|
4285 if (!iMBType) |
|
4286 { |
|
4287 iMBType = (u_char *) malloc(iNumMBsInOneVOP * sizeof(u_char)); |
|
4288 if (!iMBType) |
|
4289 { |
|
4290 deb("CMPEG4Transcoder::ERROR - iMBType creation failed\n"); |
|
4291 User::Leave(KErrNoMemory); |
|
4292 } |
|
4293 memset(iMBType, VDX_MB_INTER, iNumMBsInOneVOP * sizeof(u_char)); |
|
4294 } |
|
4295 |
|
4296 } |
|
4297 |
|
4298 |
|
4299 /* |
|
4300 * GetMpeg4DcScaler |
|
4301 * |
|
4302 * Parameters: |
|
4303 * |
|
4304 * aQP Quantization parameter |
|
4305 * |
|
4306 * Function: |
|
4307 * Evaluates Chrominance DC Scaler from QP for MPEG4 |
|
4308 * Returns: |
|
4309 * int DC scaler value |
|
4310 * Error codes: |
|
4311 * None |
|
4312 * |
|
4313 */ |
|
4314 int CMPEG4Transcoder::GetMpeg4DcScalerUV(int aQP) |
|
4315 { |
|
4316 if (aQP>=1 && aQP<=4) |
|
4317 return (8); |
|
4318 else if (aQP>=5 && aQP<=24) |
|
4319 return ((aQP+13)/2); |
|
4320 else if (aQP>=25 && aQP<=31) |
|
4321 return (aQP-6); |
|
4322 else |
|
4323 return (0); // error |
|
4324 } |
|
4325 |
|
4326 |
|
4327 void CMPEG4Transcoder::AfterMBLayer(int aUpdatedQp) |
|
4328 { |
|
4329 iCurQuant = aUpdatedQp; |
|
4330 } |
|
4331 |
|
4332 |
|
4333 |
|
4334 |
|
4335 /* End of File */ |
|