|
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 * H.263 decoder core functions. |
|
17 * |
|
18 */ |
|
19 |
|
20 |
|
21 /* |
|
22 * Includes |
|
23 */ |
|
24 #include "h263dConfig.h" |
|
25 #include "vdc263.h" |
|
26 #include "core.h" |
|
27 #include "debug.h" |
|
28 #include "decblock.h" /* for dblFree and dblLoad */ |
|
29 #include "decgob.h" |
|
30 #include "decpich.h" |
|
31 #include "h263dapi.h" /* for H263D_BC_MUX_MODE_SEPARATE_CHANNEL and H263D_ERD_ */ |
|
32 #include "stckheap.h" |
|
33 #include "sync.h" |
|
34 #include "vdeims.h" |
|
35 #include "vdeimb.h" |
|
36 #include "viddemux.h" |
|
37 #include "biblin.h" |
|
38 #include "MPEG4Transcoder.h" |
|
39 |
|
40 |
|
41 /* |
|
42 * Typedefs and structs |
|
43 */ |
|
44 |
|
45 /* This structure is used to indicate the expected decoding position. */ |
|
46 typedef enum { |
|
47 EDP_START_OF_FRAME, |
|
48 EDP_START_OF_GOB_SEGMENT, |
|
49 EDP_START_OF_SLICE_SEGMENT, |
|
50 EDP_END_OF_FRAME |
|
51 } vdcExpectedDecodingPosition_t; |
|
52 |
|
53 |
|
54 /* |
|
55 * Local function prototypes |
|
56 */ |
|
57 |
|
58 int vdcFillImageBuffers( |
|
59 vdcInstance_t *instance, |
|
60 int numOfCodedMBs, |
|
61 vdeImb_t *imbP); |
|
62 |
|
63 |
|
64 /* |
|
65 * Global functions |
|
66 */ |
|
67 |
|
68 /* {{-output"vdcClose.txt"}} */ |
|
69 /* |
|
70 * vdcClose |
|
71 * |
|
72 * |
|
73 * Parameters: |
|
74 * hInstance handle of instance data |
|
75 * |
|
76 * Function: |
|
77 * This function closes the instance. The function frees all the resources |
|
78 * allocated for the instance. The instance handle is no longer valid |
|
79 * after calling this function. |
|
80 * |
|
81 * Returns: |
|
82 * >= 0 if the function was successful |
|
83 * < 0 if an error occured |
|
84 * |
|
85 */ |
|
86 |
|
87 int vdcClose(vdcHInstance_t hInstance) |
|
88 /* {{-output"vdcClose.txt"}} */ |
|
89 { |
|
90 vdcInstance_t *instance = (vdcInstance_t *) hInstance; |
|
91 int retValue = VDC_OK; |
|
92 |
|
93 if (instance == NULL) |
|
94 return retValue; |
|
95 |
|
96 mvcFree(&instance->mvcData); |
|
97 |
|
98 if ( instance->prevPicHeader != NULL ) |
|
99 free( instance->prevPicHeader ); |
|
100 |
|
101 aicFree(&instance->aicData); |
|
102 |
|
103 |
|
104 if ( instance->user_data != NULL ) |
|
105 free( instance->user_data ); |
|
106 |
|
107 |
|
108 vdcDealloc(instance); |
|
109 |
|
110 return retValue; |
|
111 } |
|
112 |
|
113 |
|
114 /* {{-output"vdcDecodeFrame.txt"}} */ |
|
115 /* |
|
116 * vdcDecodeFrame |
|
117 * |
|
118 * |
|
119 * Parameters: |
|
120 * hInstance handle of instance data |
|
121 * |
|
122 * inBuffer pointer to bit buffer, the current position |
|
123 * of the buffer must start with a PSC |
|
124 * |
|
125 * Function: |
|
126 * The vdcDecodeFrame function implements the decoding process described |
|
127 * in the H.263 recommendation (version 2). However, it does not support |
|
128 * the following features of the recommendation: |
|
129 * decoding using the H.261 standard (bit 2 in PTYPE), |
|
130 * source format changes during a video sequence. |
|
131 * |
|
132 * The function decodes the next frame in |
|
133 * the buffer (inBuffer) meaning that the decoding continues until the next |
|
134 * PSC or EOS is found or until the end of the buffer is not reached. |
|
135 * |
|
136 * Returns: |
|
137 * VDC_OK if the function was succesful |
|
138 * VDC_OK_BUT_BIT_ERROR if bit errors were detected but |
|
139 * decoded frames are provided by concealing |
|
140 * the errors |
|
141 * VDC_OK_BUT_FRAME_USELESS if severe bit errors were detected |
|
142 * (no concealment was possible) or |
|
143 * the bitstream ended unexpectedly |
|
144 * VDC_ERR if a processing error occured, |
|
145 * the instance should be closed |
|
146 * |
|
147 */ |
|
148 |
|
149 |
|
150 int vdcDecodeFrame(vdcHInstance_t hInstance, bibBuffer_t *inBuffer, bibBuffer_t *outBuffer, |
|
151 bibBufferEdit_t *bufEdit, int aColorEffect, TBool aGetDecodedFrame, |
|
152 CMPEG4Transcoder *hTranscoder) |
|
153 |
|
154 /* {{-output"vdcDecodeFrame.txt"}} */ |
|
155 { |
|
156 int prevGN = -1; /* GOB number of the latest decoded GOB */ |
|
157 int prevGNWithHeader = -1; /* GOB number of the latest decoded GOB with |
|
158 a GOB header */ |
|
159 |
|
160 int numStuffBits; /* Number of stuffing bits before the sync code */ |
|
161 |
|
162 int sncCode; /* the latest synchronization code, see |
|
163 sncCheckSync for the possible values */ |
|
164 |
|
165 int rtr = -1; /* reference tr, 0.. */ |
|
166 int trp = -1; /* tr for prediction, -1 if not indicated in |
|
167 the bitstream */ |
|
168 |
|
169 int retValue = VDC_OK; /* return value of this function */ |
|
170 |
|
171 |
|
172 int16 error = 0; /* Used to pass error codes from the sync module */ |
|
173 |
|
174 u_char |
|
175 *currYFrame = NULL, /* current P frame */ |
|
176 *currUFrame = NULL, |
|
177 *currVFrame = NULL, |
|
178 *refYFrame = NULL, /* reference frame */ |
|
179 *refUFrame = NULL, |
|
180 *refVFrame = NULL; |
|
181 |
|
182 u_char *fCodedMBs = NULL; /* Pointer to table, which indicates coded \ |
|
183 macroblocks by non-zero value */ |
|
184 int numOfCodedMBs = 0; /* The number of coded macroblocks */ |
|
185 |
|
186 int *quantParams = NULL; /* Pointer to table, in which the quantization |
|
187 parameter for each macroblock is stored */ |
|
188 |
|
189 int decStatus = 0; /* Decoding status, returned from decgob.c */ |
|
190 int corruptedSegments = 0; /* counter for corrupted segments */ |
|
191 int decodedSegments = 0; /* counter for decoded segments (used in slice mode) */ |
|
192 int headerSuccess = 0; /* success of picture header */ |
|
193 int numDecodedMBs = 0; /* Total number of decoded MBs */ |
|
194 int numMBsInFrame = 0; /* Number of MBs in frame */ |
|
195 |
|
196 |
|
197 vdcExpectedDecodingPosition_t expectedDecodingPosition; |
|
198 /* Tells in which part of the bitstream |
|
199 the decoding should be */ |
|
200 |
|
201 vdcInstance_t *instance = (vdcInstance_t *) hInstance; |
|
202 /* instance data */ |
|
203 |
|
204 vdcAssert(instance != NULL); |
|
205 |
|
206 /* Initializations */ |
|
207 |
|
208 instance->currFrame = NULL; |
|
209 expectedDecodingPosition = EDP_START_OF_FRAME; |
|
210 instance->pictureParam.prevTR = instance->pictureParam.tr; |
|
211 |
|
212 /* Main loop */ |
|
213 for (;;) { |
|
214 int bitErrorIndication = 0; |
|
215 |
|
216 sncCode = sncCheckSync(inBuffer, &numStuffBits, &error); |
|
217 |
|
218 /* If sncCheckSync failed */ |
|
219 if (error && error != ERR_BIB_NOT_ENOUGH_DATA) { |
|
220 deb1p("vdcDecodeFrame: ERROR - sncCheckSync returned %d.\n", error); |
|
221 retValue = VDC_ERR; |
|
222 goto exitFunction; |
|
223 } |
|
224 |
|
225 /* If EOS was got */ |
|
226 if (sncCode == SNC_EOS) |
|
227 instance->fEOS = 1; |
|
228 |
|
229 /* If frame ends appropriately */ |
|
230 if (expectedDecodingPosition == EDP_END_OF_FRAME && |
|
231 (sncCode == SNC_PSC || sncCode == SNC_EOS || |
|
232 sncCode == SNC_STUFFING || error == ERR_BIB_NOT_ENOUGH_DATA )) { |
|
233 goto exitFunction; |
|
234 } |
|
235 |
|
236 /* Else if frame (or stream) data ends suddenly */ |
|
237 else if (error == ERR_BIB_NOT_ENOUGH_DATA) { |
|
238 retValue = VDC_OK_BUT_BIT_ERROR; |
|
239 goto exitFunction; |
|
240 } |
|
241 |
|
242 /* Else if EOS was reached */ |
|
243 else if (sncCode == SNC_EOS) { |
|
244 /* The current frame is useless since it ends before it is complete. |
|
245 On the other hand, there is no point in concealing it since |
|
246 it is the last frame of the sequence. */ |
|
247 retValue = VDC_OK_BUT_FRAME_USELESS; |
|
248 goto exitFunction; |
|
249 } |
|
250 |
|
251 /* Else if frame starts as expected */ |
|
252 else if (expectedDecodingPosition == EDP_START_OF_FRAME && |
|
253 sncCode == SNC_PSC) { |
|
254 |
|
255 dphInParam_t pichIn; |
|
256 dphInOutParam_t pichInOut; |
|
257 dphOutParam_t pichOut; |
|
258 |
|
259 pichIn.numStuffBits = numStuffBits; |
|
260 pichIn.fNeedDecodedFrame = aGetDecodedFrame | hTranscoder->NeedDecodedYUVFrame(); |
|
261 |
|
262 pichIn.fReadBits = 1; |
|
263 pichInOut.vdcInstance = instance; |
|
264 pichInOut.inBuffer = inBuffer; |
|
265 |
|
266 if ( instance->fRPS ) { |
|
267 /* Store the previous TR for VRC needs */ |
|
268 if ( instance->nOfDecodedFrames > 0 ) |
|
269 trp = instance->pictureParam.tr; |
|
270 else |
|
271 trp = -1; |
|
272 } |
|
273 /* Get picture header */ |
|
274 headerSuccess = dphGetPictureHeader(&pichIn, &pichInOut, &pichOut, &bitErrorIndication); |
|
275 |
|
276 if (headerSuccess != DPH_OK) { |
|
277 |
|
278 deb("vdcDecodeFrame: Header decoding unsuccessful due to errors, picture will be discarded.\n"); |
|
279 retValue = VDC_OK_BUT_FRAME_USELESS; |
|
280 goto exitFunction; |
|
281 } |
|
282 |
|
283 numMBsInFrame = renDriNumOfMBs(instance->currFrame->imb->drawItem); |
|
284 |
|
285 currYFrame = pichOut.currYFrame; |
|
286 currUFrame = pichOut.currUFrame; |
|
287 currVFrame = pichOut.currVFrame; |
|
288 |
|
289 numOfCodedMBs = 0; |
|
290 fCodedMBs = renDriCodedMBs(instance->currFrame->imb->drawItem); |
|
291 memset(fCodedMBs, 0, numMBsInFrame * sizeof(u_char)); |
|
292 |
|
293 /* Initialize quantization parameter array */ |
|
294 quantParams = instance->currFrame->imb->yQuantParams; |
|
295 memset(quantParams, 0, numMBsInFrame * sizeof(int)); |
|
296 |
|
297 /* If this is the first frame and callback function has been set, report frame size */ |
|
298 if (instance->nOfDecodedFrames == 0 && instance->reportPictureSizeCallback) { |
|
299 h263dReportPictureSizeCallback_t cb = |
|
300 (h263dReportPictureSizeCallback_t)instance->reportPictureSizeCallback; |
|
301 cb(instance->hParent, instance->pictureParam.lumWidth, instance->pictureParam.lumHeight); |
|
302 } |
|
303 |
|
304 /* If picture header was ok */ |
|
305 if (headerSuccess == DPH_OK) |
|
306 { |
|
307 /* Get and decode Supplemental Enhancement Information */ |
|
308 int seiSuccess = dphGetSEI(instance, inBuffer, &bitErrorIndication); |
|
309 |
|
310 /* If fatal error while reading SEI */ |
|
311 if (seiSuccess < 0) { |
|
312 retValue = VDC_ERR; |
|
313 deb("vdcDecodeFrame: dphGetSEI failed.\n"); |
|
314 goto exitFunction; |
|
315 } |
|
316 |
|
317 /* Else if bit error while reading SEI */ |
|
318 else if (seiSuccess == DPH_OK_BUT_BIT_ERROR) { |
|
319 /* We can't trust that the 1st segment can be decoded. |
|
320 Thus, let's continue with the 2nd segment. */ |
|
321 if ( instance->pictureParam.fSS ) |
|
322 expectedDecodingPosition = EDP_START_OF_SLICE_SEGMENT; |
|
323 else |
|
324 expectedDecodingPosition = EDP_START_OF_GOB_SEGMENT; |
|
325 sncCode = sncSeekSync(inBuffer, &error); |
|
326 if (error && error != ERR_BIB_NOT_ENOUGH_DATA) { |
|
327 retValue = VDC_ERR; |
|
328 deb("vdcDecodeFrame: sncSeekSync failed.\n"); |
|
329 goto exitFunction; |
|
330 } |
|
331 continue; |
|
332 } |
|
333 |
|
334 |
|
335 } |
|
336 |
|
337 if ( hTranscoder->H263PictureHeaderEnded(&pichOut, &pichInOut) != VDC_OK ) |
|
338 { |
|
339 retValue = VDC_ERR; |
|
340 goto exitFunction; |
|
341 } |
|
342 |
|
343 if (instance->pictureParam.fSS) |
|
344 /* Decode the 1st Slice segment - not supported */ |
|
345 { |
|
346 retValue = VDC_OK_BUT_FRAME_USELESS; |
|
347 goto exitFunction; |
|
348 } |
|
349 else |
|
350 /* Decode the 1st GOB segment */ |
|
351 { |
|
352 dgobGOBSegmentInParam_t dgobi; |
|
353 dgobGOBSegmentInOutParam_t dgobio; |
|
354 |
|
355 dgobi.numStuffBits = 0; |
|
356 dgobi.pictParam = &instance->pictureParam; |
|
357 dgobi.inBuffer = inBuffer; |
|
358 |
|
359 dgobi.outBuffer = outBuffer; |
|
360 dgobi.bufEdit = bufEdit; |
|
361 |
|
362 dgobi.iColorEffect = aColorEffect; |
|
363 dgobi.iGetDecodedFrame=aGetDecodedFrame; |
|
364 dgobio.StartByteIndex=0; |
|
365 dgobio.StartBitIndex=7; |
|
366 |
|
367 /* fGFIDShouldChange not relevant here */ |
|
368 |
|
369 dgobio.prevGNWithHeader = 0; |
|
370 dgobio.prevGN = 0; |
|
371 /* dgobio.gfid, not relevant here */ |
|
372 dgobio.fCodedMBs = fCodedMBs; |
|
373 dgobio.numOfCodedMBs = numOfCodedMBs; |
|
374 dgobio.quantParams = quantParams; |
|
375 dgobio.mvcData = &instance->mvcData; |
|
376 dgobio.imageStore = instance->imageStore; |
|
377 dgobio.trp = pichOut.trp; |
|
378 dgobio.rtr = 0; /* not relevant since no reference frame exists yet */ |
|
379 dgobio.refY = refYFrame; |
|
380 dgobio.refU = refUFrame; |
|
381 dgobio.refV = refVFrame; |
|
382 dgobio.currPY = currYFrame; |
|
383 dgobio.currPU = currUFrame; |
|
384 dgobio.currPV = currVFrame; |
|
385 |
|
386 /* the first GOB doesn't have a header */ |
|
387 hTranscoder->H263GOBSliceHeaderBegin(); |
|
388 hTranscoder->H263GOBSliceHeaderEnded(NULL, NULL); |
|
389 |
|
390 decStatus = dgobGetAndDecodeGOBSegmentContents(&dgobi, |
|
391 instance->pictureParam.pictureType != VDX_PIC_TYPE_I, |
|
392 pichOut.pquant, &dgobio, hTranscoder); |
|
393 |
|
394 if (decStatus < 0) { |
|
395 retValue = VDC_ERR; |
|
396 goto exitFunction; |
|
397 } |
|
398 |
|
399 hTranscoder->H263OneGOBSliceWithHeaderEnded(); |
|
400 |
|
401 prevGNWithHeader = dgobio.prevGNWithHeader; |
|
402 prevGN = dgobio.prevGN; |
|
403 numOfCodedMBs = dgobio.numOfCodedMBs; |
|
404 trp = dgobio.trp; |
|
405 rtr = dgobio.rtr; |
|
406 refYFrame = dgobio.refY; |
|
407 refUFrame = dgobio.refU; |
|
408 refVFrame = dgobio.refV; |
|
409 if (prevGN == instance->pictureParam.numGOBs - 1) |
|
410 expectedDecodingPosition = EDP_END_OF_FRAME; |
|
411 else |
|
412 expectedDecodingPosition = EDP_START_OF_GOB_SEGMENT; |
|
413 } |
|
414 } |
|
415 |
|
416 /* Else if GOB segment starts as expected */ |
|
417 else if (expectedDecodingPosition == EDP_START_OF_GOB_SEGMENT && |
|
418 sncCode == SNC_GBSC) { |
|
419 |
|
420 dgobGOBSegmentInParam_t dgobi; |
|
421 dgobGOBSegmentInOutParam_t dgobio; |
|
422 |
|
423 dgobi.numStuffBits = numStuffBits; |
|
424 dgobi.pictParam = &instance->pictureParam; |
|
425 dgobi.inBuffer = inBuffer; |
|
426 |
|
427 dgobi.outBuffer = outBuffer; |
|
428 dgobi.bufEdit = bufEdit; |
|
429 |
|
430 dgobi.iColorEffect = aColorEffect; |
|
431 dgobi.iGetDecodedFrame= aGetDecodedFrame; |
|
432 if(prevGN==-1) |
|
433 { |
|
434 dgobio.StartByteIndex=0; |
|
435 dgobio.StartBitIndex=7; |
|
436 } |
|
437 else |
|
438 { |
|
439 dgobio.StartByteIndex=dgobi.inBuffer->getIndex; |
|
440 dgobio.StartBitIndex=dgobi.inBuffer->bitIndex; |
|
441 } |
|
442 |
|
443 |
|
444 /* fGFIDShouldChange, see below */ |
|
445 |
|
446 dgobio.prevGNWithHeader = prevGNWithHeader; |
|
447 dgobio.prevGN = prevGN; |
|
448 /* dgobio.gfid, see below */ |
|
449 dgobio.fCodedMBs = fCodedMBs; |
|
450 dgobio.numOfCodedMBs = numOfCodedMBs; |
|
451 dgobio.quantParams = quantParams; |
|
452 dgobio.mvcData = &instance->mvcData; |
|
453 dgobio.imageStore = instance->imageStore; |
|
454 dgobio.trp = trp; |
|
455 dgobio.rtr = rtr; |
|
456 dgobio.refY = refYFrame; |
|
457 dgobio.refU = refUFrame; |
|
458 dgobio.refV = refVFrame; |
|
459 dgobio.currPY = currYFrame; |
|
460 dgobio.currPU = currUFrame; |
|
461 dgobio.currPV = currVFrame; |
|
462 |
|
463 dgobi.fGFIDShouldChange = instance->fGFIDShouldChange; |
|
464 dgobio.gfid = instance->gfid; |
|
465 |
|
466 /* Get and decode GOB segment */ |
|
467 decStatus = dgobGetAndDecodeGOBSegment(&dgobi, &dgobio, hTranscoder); |
|
468 |
|
469 if (decStatus == DGOB_ERR) { |
|
470 retValue = VDC_ERR; |
|
471 goto exitFunction; |
|
472 } |
|
473 if ( instance->fGFIDShouldChange ) { |
|
474 instance->gfid = dgobio.gfid; |
|
475 instance->fGFIDShouldChange = 0; |
|
476 } |
|
477 |
|
478 prevGNWithHeader = dgobio.prevGNWithHeader; |
|
479 prevGN = dgobio.prevGN; |
|
480 numOfCodedMBs = dgobio.numOfCodedMBs; |
|
481 trp = dgobio.trp; |
|
482 |
|
483 |
|
484 rtr = dgobio.rtr; |
|
485 |
|
486 refYFrame = dgobio.refY; |
|
487 refUFrame = dgobio.refU; |
|
488 refVFrame = dgobio.refV; |
|
489 |
|
490 if (prevGN == instance->pictureParam.numGOBs - 1) |
|
491 expectedDecodingPosition = EDP_END_OF_FRAME; |
|
492 else |
|
493 expectedDecodingPosition = EDP_START_OF_GOB_SEGMENT; |
|
494 } |
|
495 |
|
496 /* Else if Slice segment starts as expected */ |
|
497 else if (expectedDecodingPosition == EDP_START_OF_SLICE_SEGMENT && |
|
498 sncCode == SNC_GBSC) { |
|
499 /* slides not supported */ |
|
500 retValue = VDC_OK_BUT_FRAME_USELESS; |
|
501 goto exitFunction; |
|
502 |
|
503 } |
|
504 |
|
505 /* Else decoding is out of sync */ |
|
506 else { |
|
507 switch (expectedDecodingPosition) { |
|
508 |
|
509 case EDP_START_OF_FRAME: |
|
510 /* No PSC */ |
|
511 /* Check if GFID could be used to recover the picture header */ |
|
512 { |
|
513 dphInParam_t pichIn; |
|
514 dphInOutParam_t pichInOut; |
|
515 dphOutParam_t pichOut; |
|
516 |
|
517 pichIn.numStuffBits = numStuffBits; |
|
518 pichIn.fReadBits = 0; |
|
519 |
|
520 pichInOut.vdcInstance = instance; |
|
521 pichInOut.inBuffer = inBuffer; |
|
522 |
|
523 headerSuccess = dphGetPictureHeader(&pichIn, &pichInOut, &pichOut, &bitErrorIndication); |
|
524 if ( headerSuccess == DPH_OK) { |
|
525 /* Header recovery was successful, start decoding from the next GOB available */ |
|
526 if ( instance->pictureParam.fSS ) { |
|
527 expectedDecodingPosition = EDP_START_OF_SLICE_SEGMENT; |
|
528 /* decSlice does not increment these */ |
|
529 decodedSegments++; |
|
530 corruptedSegments++; |
|
531 } |
|
532 else |
|
533 expectedDecodingPosition = EDP_START_OF_GOB_SEGMENT; |
|
534 deb1p("vdcDecodeFrame: Header successfully recovered after PSC loss. FrameNum %d\n",instance->frameNum); |
|
535 currYFrame = pichOut.currYFrame; |
|
536 currUFrame = pichOut.currUFrame; |
|
537 currVFrame = pichOut.currVFrame; |
|
538 numMBsInFrame = renDriNumOfMBs(instance->currFrame->imb->drawItem); |
|
539 numOfCodedMBs = 0; |
|
540 numDecodedMBs = 0; |
|
541 fCodedMBs = renDriCodedMBs(instance->currFrame->imb->drawItem); |
|
542 memset(fCodedMBs, 0, numMBsInFrame * sizeof(u_char)); |
|
543 |
|
544 /* Initialize quantization parameter array */ |
|
545 quantParams = instance->currFrame->imb->yQuantParams; |
|
546 memset(quantParams, 0, numMBsInFrame * sizeof(int)); |
|
547 |
|
548 /* If this is the first frame and callback function has been set, report frame size */ |
|
549 if (instance->nOfDecodedFrames == 0 && instance->reportPictureSizeCallback) { |
|
550 h263dReportPictureSizeCallback_t cb = |
|
551 (h263dReportPictureSizeCallback_t)instance->reportPictureSizeCallback; |
|
552 cb(instance->hParent, instance->pictureParam.lumWidth, instance->pictureParam.lumHeight); |
|
553 } |
|
554 |
|
555 continue; |
|
556 } |
|
557 else { |
|
558 retValue = VDC_OK_BUT_FRAME_USELESS; |
|
559 deb1p("vdcDecodeFrame: Header recovery unsuccessful after PSC loss. FrameNum %d\n",instance->frameNum); |
|
560 goto exitFunction; |
|
561 } |
|
562 } |
|
563 case EDP_START_OF_GOB_SEGMENT: |
|
564 if ( sncCode == SNC_PSC ) { |
|
565 retValue = VDC_OK_BUT_BIT_ERROR; |
|
566 goto exitFunction; |
|
567 } |
|
568 else { |
|
569 /* |
|
570 * Picture header recovery used next picture header |
|
571 * => we are not at the position of GBSC => search the next one |
|
572 * This is caused by a erdRestorePictureHeader that does not synchronize |
|
573 * bit buffer to GOB headers that have bitErrorIndication != 0. |
|
574 * This may be considered as a , and it might be good to change it later on. |
|
575 * This seeking should solve the problem, although maybe not in the most elegant way |
|
576 */ |
|
577 sncSeekSync( inBuffer, &error ); |
|
578 continue; |
|
579 } |
|
580 default : |
|
581 { |
|
582 |
|
583 retValue = VDC_OK_BUT_FRAME_USELESS; |
|
584 goto exitFunction; |
|
585 } |
|
586 |
|
587 } |
|
588 } |
|
589 } |
|
590 |
|
591 exitFunction: |
|
592 |
|
593 |
|
594 /* If frame(s) not useless */ |
|
595 if (retValue == VDC_OK || retValue == VDC_OK_BUT_BIT_ERROR) { |
|
596 |
|
597 if (!corruptedSegments && (numDecodedMBs > 0 || prevGN > 0 || instance->pictureParam.numGOBs == 1)) |
|
598 retValue = VDC_OK; |
|
599 else { |
|
600 retValue = VDC_OK_BUT_FRAME_USELESS; |
|
601 deb1p("vdcDecodeFrame: Frame useless, too many corrupted segments. FrameNum %d\n",instance->frameNum); |
|
602 } |
|
603 } |
|
604 |
|
605 /* If decoding ok and frame not useless */ |
|
606 if ( retValue == VDC_OK || retValue == VDC_OK_BUT_BIT_ERROR ) { |
|
607 |
|
608 |
|
609 /* stuff bits here 'END OF FRAME' -->*/ |
|
610 bibStuffBits(outBuffer); |
|
611 /* <-- */ |
|
612 |
|
613 if ( instance->nOfDecodedFrames < 0xffffffff ) |
|
614 instance->nOfDecodedFrames++; |
|
615 |
|
616 if (vdcFillImageBuffers( |
|
617 instance, |
|
618 numOfCodedMBs, |
|
619 instance->currFrame->imb) < 0) |
|
620 retValue = VDC_ERR; |
|
621 |
|
622 |
|
623 |
|
624 } |
|
625 if ( retValue == VDC_OK_BUT_FRAME_USELESS ) { |
|
626 /* GFID of the next frame can be whatever, since this frame was useless */ |
|
627 instance->gfid = -1; |
|
628 } |
|
629 if ( instance->fGFIDShouldChange |
|
630 && ( (instance->pictureParam.fSS && decodedSegments == 1) |
|
631 || (!instance->pictureParam.fSS && prevGNWithHeader <= 0) |
|
632 ) |
|
633 ) |
|
634 { |
|
635 /* GFID of the next frame can be whatever, since this frame didn't have any GFID's and GFID was supposed to change */ |
|
636 instance->gfid = -1; |
|
637 } |
|
638 |
|
639 /* If a fatal error occurred */ |
|
640 if (retValue < 0) { |
|
641 /* Return frame buffers for decoded output images, |
|
642 as they are useless for the caller and |
|
643 as the caller cannot get a handle to return them */ |
|
644 if (instance->currFrame) |
|
645 vdeImsPutFree(instance->imageStore, instance->currFrame); |
|
646 } |
|
647 |
|
648 return retValue; |
|
649 } |
|
650 |
|
651 |
|
652 /* {{-output"vdcDecodePictureHeader.txt"}} */ |
|
653 /* |
|
654 * vdcDecodePictureHeader |
|
655 * |
|
656 * Parameters: |
|
657 * hInstance I: handle of instance data |
|
658 * (May set instance->errorVar if bit errors.) |
|
659 * |
|
660 * Function: |
|
661 * |
|
662 * |
|
663 * Note: |
|
664 * This function does not recover corrupted picture headers (by means of |
|
665 * GFID or redundant picture header copies). |
|
666 * |
|
667 * Returns: |
|
668 * See above. |
|
669 */ |
|
670 |
|
671 int vdcDecodePictureHeader( |
|
672 vdcHInstance_t hInstance, |
|
673 bibBuffer_t *inBuffer, |
|
674 vdxPictureHeader_t *header, |
|
675 vdxSEI_t *sei) |
|
676 { |
|
677 int |
|
678 retValue = VDC_OK, |
|
679 sncCode, |
|
680 numStuffBits, |
|
681 bitErrorIndication = 0; |
|
682 |
|
683 int16 |
|
684 error = 0; |
|
685 |
|
686 u_int32 |
|
687 pictureStartPosition; |
|
688 |
|
689 vdcInstance_t |
|
690 *instance = (vdcInstance_t *) hInstance; |
|
691 |
|
692 /* The function is implemented by calling stateless Video Demultiplexer |
|
693 (vdx) functions. Consequently, the function does not have sophisticated |
|
694 logic to track illegal/corrupted parameters based on the previous |
|
695 picture header. It cannot recover corrupted picture headers either. |
|
696 |
|
697 Alternatively, the function could have been implemented by creating |
|
698 an identical copy of the Video Decoder Core instance and by using |
|
699 "Decode Picture Header" (dph) module functions. However, as there is |
|
700 no instance copying functions implemented, the former alternative |
|
701 was chosen. |
|
702 |
|
703 This function was targeted for getting the picture type and |
|
704 Nokia-proprietary Annex N scalability layer information encapsulated |
|
705 in Supplemental Enhancement Information in an error-free situation. |
|
706 For this purpose, the former and simpler solution is more than |
|
707 adequate. */ |
|
708 |
|
709 pictureStartPosition = bibNumberOfFlushedBits(inBuffer); |
|
710 sncCode = sncCheckSync(inBuffer, &numStuffBits, &error); |
|
711 |
|
712 /* If sncCheckSync failed */ |
|
713 if (error) { |
|
714 deb1p("vdcDecodeFrame: ERROR - sncCheckSync returned %d.\n", error); |
|
715 retValue = VDC_ERR; |
|
716 goto exitFunction; |
|
717 } |
|
718 |
|
719 /* Else if EOS was got */ |
|
720 else if (sncCode == SNC_EOS) { |
|
721 retValue = VDC_OK_BUT_FRAME_USELESS; |
|
722 goto exitFunction; |
|
723 } |
|
724 |
|
725 /* Else if frame starts as expected */ |
|
726 else if (sncCode == SNC_PSC) { |
|
727 int |
|
728 picHdrStatus, |
|
729 seiStatus; |
|
730 |
|
731 vdxGetPictureHeaderInputParam_t |
|
732 picHdrIn; |
|
733 |
|
734 picHdrIn.numStuffBits = numStuffBits; |
|
735 picHdrIn.fCustomPCF = 0; |
|
736 picHdrIn.fScalabilityMode = 0; |
|
737 picHdrIn.fRPS = instance->fRPS; |
|
738 picHdrIn.flushBits = bibFlushBits; |
|
739 picHdrIn.getBits = bibGetBits; |
|
740 picHdrIn.showBits = bibShowBits; |
|
741 |
|
742 /* Get picture header */ |
|
743 picHdrStatus = vdxGetPictureHeader( |
|
744 inBuffer, |
|
745 &picHdrIn, |
|
746 header, |
|
747 &bitErrorIndication); |
|
748 |
|
749 /* If the header was not successfully retrieved */ |
|
750 if (picHdrStatus < 0) { |
|
751 retValue = VDC_ERR; |
|
752 goto exitFunction; |
|
753 } |
|
754 else if (picHdrStatus != VDX_OK) { |
|
755 retValue = VDC_OK_BUT_BIT_ERROR; |
|
756 goto exitFunction; |
|
757 } |
|
758 |
|
759 /* Get and decode Supplemental Enhancement Information */ |
|
760 seiStatus = vdxGetAndParseSEI( |
|
761 inBuffer, |
|
762 instance->pictureParam.fPLUSPTYPE, |
|
763 instance->numAnnexNScalabilityLayers, |
|
764 sei, |
|
765 &bitErrorIndication); |
|
766 |
|
767 /* If error while reading SEI */ |
|
768 if (seiStatus < 0) { |
|
769 retValue = VDC_ERR; |
|
770 goto exitFunction; |
|
771 } |
|
772 else if (seiStatus != VDX_OK) { |
|
773 retValue = VDC_OK_BUT_BIT_ERROR; |
|
774 goto exitFunction; |
|
775 } |
|
776 } |
|
777 |
|
778 /* Else no valid frame start */ |
|
779 else |
|
780 retValue = VDC_OK_BUT_FRAME_USELESS; |
|
781 |
|
782 exitFunction: |
|
783 |
|
784 /* Reset the bit buffer to its original position */ |
|
785 bibRewindBits( |
|
786 bibNumberOfFlushedBits(inBuffer) - pictureStartPosition, |
|
787 inBuffer, &error); |
|
788 |
|
789 if (error) |
|
790 retValue = VDC_ERR; |
|
791 |
|
792 return retValue; |
|
793 } |
|
794 |
|
795 |
|
796 /* {{-output"vdcFree.txt"}} */ |
|
797 /* |
|
798 * vdcFree |
|
799 * |
|
800 * |
|
801 * Parameters: |
|
802 * None. |
|
803 * |
|
804 * Function: |
|
805 * This function deinitializes the Video Decoder Core module. |
|
806 * Any functions of this module must not be called after vdcFree (except |
|
807 * vdcLoad). |
|
808 * |
|
809 * Returns: |
|
810 * >= 0 if succeeded |
|
811 * < 0 if failed |
|
812 * |
|
813 * |
|
814 */ |
|
815 |
|
816 int vdcFree(void) |
|
817 /* {{-output"vdcFree.txt"}} */ |
|
818 { |
|
819 if (dblFree() < 0) |
|
820 return VDC_ERR; |
|
821 |
|
822 return VDC_OK; |
|
823 } |
|
824 |
|
825 |
|
826 /* {{-output"vdcGetImsItem.txt"}} */ |
|
827 /* |
|
828 * vdcGetImsItem |
|
829 * |
|
830 * |
|
831 * Parameters: |
|
832 * hInstance handle of instance data |
|
833 * index output frame number, |
|
834 * should be 0 for I and P frames |
|
835 * |
|
836 * Function: |
|
837 * This function returns a pointer to the requested output frame. |
|
838 * |
|
839 * Returns: |
|
840 * a pointer to a image store item which corresponds to the passed output |
|
841 * frame index, or |
|
842 * NULL if the function fails |
|
843 * |
|
844 */ |
|
845 |
|
846 vdeImsItem_t *vdcGetImsItem(vdcHInstance_t hInstance, int index) |
|
847 /* {{-output"vdcGetImsItem.txt"}} */ |
|
848 { |
|
849 vdcInstance_t *instance = (vdcInstance_t *) hInstance; |
|
850 int numOutputFrames = vdcGetNumberOfOutputFrames(hInstance); |
|
851 |
|
852 vdcAssert(instance); |
|
853 vdcAssert(index >= 0); |
|
854 |
|
855 if (index >= numOutputFrames) |
|
856 return NULL; |
|
857 |
|
858 return instance->currFrame; |
|
859 } |
|
860 |
|
861 |
|
862 /* {{-output"vdcGetNumberOfAnnexNScalabilityLayers.txt"}} */ |
|
863 /* |
|
864 * vdcGetNumberOfAnnexNScalabilityLayers |
|
865 * |
|
866 * Parameters: |
|
867 * hInstance I: handle of instance data |
|
868 * |
|
869 * Function: |
|
870 * Returns the number of Nokia-proprietary Annex N temporal scalability |
|
871 * layers. |
|
872 * |
|
873 * Returns: |
|
874 * See above. |
|
875 */ |
|
876 |
|
877 int vdcGetNumberOfAnnexNScalabilityLayers( |
|
878 vdcHInstance_t hInstance) |
|
879 /* {{-output"vdcGetNumberOfAnnexNScalabilityLayers.txt"}} */ |
|
880 { |
|
881 vdcInstance_t *instance = (vdcInstance_t *) hInstance; |
|
882 |
|
883 vdcAssert(instance); |
|
884 |
|
885 return instance->numAnnexNScalabilityLayers; |
|
886 } |
|
887 |
|
888 |
|
889 /* {{-output"vdcGetNumberOfOutputFrames.txt"}} */ |
|
890 /* |
|
891 * vdcGetNumberOfOutputFrames |
|
892 * |
|
893 * |
|
894 * Parameters: |
|
895 * hInstance handle of instance data |
|
896 * |
|
897 * Function: |
|
898 * This function returns the number of output frames which were produced |
|
899 * during the latest vdcDecodeFrame. |
|
900 * |
|
901 * Returns: |
|
902 * 0 if vdcDecodeFrame failed to produce any output frames |
|
903 * 1 for I and P frames |
|
904 * |
|
905 */ |
|
906 |
|
907 int vdcGetNumberOfOutputFrames(vdcHInstance_t hInstance) |
|
908 /* {{-output"vdcGetNumberOfOutputFrames.txt"}} */ |
|
909 { |
|
910 vdcInstance_t *instance = (vdcInstance_t *) hInstance; |
|
911 |
|
912 vdcAssert(instance); |
|
913 |
|
914 return ((instance->currFrame) ? 1 : 0); |
|
915 } |
|
916 |
|
917 |
|
918 /* {{-output"vdcGetTR.txt"}} */ |
|
919 /* |
|
920 * vdcGetTR |
|
921 * |
|
922 * |
|
923 * Parameters: |
|
924 * inpBuffer buffer containing the frame data, |
|
925 * must start with a PSC |
|
926 * tr temporal reference |
|
927 * |
|
928 * Function: |
|
929 * Gets the temporal reference field from the input buffer. |
|
930 * Notice that the validity of the bitstream is not checked. |
|
931 * This function does not support enhanced temporal reference |
|
932 * (ETR) defined in section 5.1.8 of the H.263 recommendation. |
|
933 * |
|
934 * Returns: |
|
935 * Nothing |
|
936 * |
|
937 * |
|
938 */ |
|
939 |
|
940 void vdcGetTR(void *inpBuffer, u_int8 *tr) |
|
941 /* {{-output"vdcGetTR.txt"}} */ |
|
942 { |
|
943 const u_char |
|
944 *tmpBuffer = (u_char *) inpBuffer; |
|
945 |
|
946 *tr = (u_int8) (((tmpBuffer[2] & 2) << 6) | ((tmpBuffer[3] & 252) >> 2)); |
|
947 } |
|
948 |
|
949 |
|
950 /* {{-output"vdcIsEOSReached.txt"}} */ |
|
951 /* |
|
952 * vdcIsEOSReached |
|
953 * |
|
954 * |
|
955 * Parameters: |
|
956 * hInstance handle of instance data |
|
957 * |
|
958 * Function: |
|
959 * This function returns 1 if the EOS code has been reached during |
|
960 * the decoding. Otherwise, it returns 0. |
|
961 * |
|
962 * Returns: |
|
963 * See above. |
|
964 * |
|
965 */ |
|
966 |
|
967 int vdcIsEOSReached(vdcHInstance_t hInstance) |
|
968 /* {{-output"vdcIsEOSReached.txt"}} */ |
|
969 { |
|
970 vdcInstance_t *instance = (vdcInstance_t *) hInstance; |
|
971 |
|
972 vdcAssert(instance); |
|
973 |
|
974 return instance->fEOS; |
|
975 } |
|
976 |
|
977 |
|
978 /* {{-output"vdcIsINTRA.txt"}} */ |
|
979 /* |
|
980 * vdcIsINTRA |
|
981 * |
|
982 * |
|
983 * Parameters: |
|
984 * hInstance handle of instance data |
|
985 * frameStart pointer to memory chunk containing a frame |
|
986 * frameLength number of bytes in frame |
|
987 * |
|
988 * Function: |
|
989 * This function returns 1 if the passed frame is an INTRA frame. |
|
990 * Otherwise the function returns 0. |
|
991 * |
|
992 * Returns: |
|
993 * See above. |
|
994 * |
|
995 * |
|
996 */ |
|
997 |
|
998 int vdcIsINTRA( |
|
999 vdcHInstance_t hInstance, |
|
1000 void *frameStart, |
|
1001 unsigned frameLength) |
|
1002 /* {{-output"vdcIsINTRA.txt"}} */ |
|
1003 { |
|
1004 bibBuffer_t *tmpBitBuffer; |
|
1005 int fINTRA = 0, bitErrorIndication, syncCode, vdxStatus; |
|
1006 int16 error = 0; |
|
1007 vdcInstance_t *instance = (vdcInstance_t *) hInstance; |
|
1008 vdxGetPictureHeaderInputParam_t vdxIn; |
|
1009 vdxPictureHeader_t vdxOut; |
|
1010 |
|
1011 vdcAssert(instance); |
|
1012 |
|
1013 tmpBitBuffer = bibCreate(frameStart, frameLength, &error); |
|
1014 if (!tmpBitBuffer || error) |
|
1015 return 0; |
|
1016 |
|
1017 syncCode = sncCheckSync(tmpBitBuffer, &(vdxIn.numStuffBits), &error); |
|
1018 |
|
1019 if (syncCode == SNC_PSC && error == 0) { |
|
1020 |
|
1021 /* Note: Needs to be changed when support for custom PCF or scalability mode |
|
1022 is added */ |
|
1023 vdxIn.fCustomPCF = 0; |
|
1024 vdxIn.fScalabilityMode = 0; |
|
1025 vdxIn.fRPS = instance->fRPS; |
|
1026 vdxIn.flushBits = bibFlushBits; |
|
1027 vdxIn.getBits = bibGetBits; |
|
1028 vdxIn.showBits = bibShowBits; |
|
1029 |
|
1030 vdxStatus = vdxGetPictureHeader(tmpBitBuffer, &vdxIn, &vdxOut, |
|
1031 &bitErrorIndication); |
|
1032 |
|
1033 if (vdxStatus >= 0 && bitErrorIndication == 0) |
|
1034 fINTRA = (vdxOut.pictureType == VDX_PIC_TYPE_I); |
|
1035 } |
|
1036 |
|
1037 bibDelete(tmpBitBuffer, &error); |
|
1038 |
|
1039 return fINTRA; |
|
1040 } |
|
1041 |
|
1042 |
|
1043 /* {{-output"vdcIsINTRAGot.txt"}} */ |
|
1044 /* |
|
1045 * vdcIsINTRAGot |
|
1046 * |
|
1047 * |
|
1048 * Parameters: |
|
1049 * hInstance handle of instance data |
|
1050 * |
|
1051 * Function: |
|
1052 * This function returns 1 if the an INTRA frame has been decoded |
|
1053 * during the lifetime of the instance. Otherwise, it returns 0. |
|
1054 * |
|
1055 * Returns: |
|
1056 * See above. |
|
1057 * |
|
1058 * |
|
1059 */ |
|
1060 |
|
1061 int vdcIsINTRAGot(vdcHInstance_t hInstance) |
|
1062 /* {{-output"vdcIsEOSReached.txt"}} */ |
|
1063 { |
|
1064 vdcInstance_t *instance = (vdcInstance_t *) hInstance; |
|
1065 |
|
1066 vdcAssert(instance); |
|
1067 |
|
1068 return instance->fIntraGot; |
|
1069 } |
|
1070 |
|
1071 |
|
1072 /* {{-output"vdcLoad.txt"}} */ |
|
1073 /* |
|
1074 * vdcLoad |
|
1075 * |
|
1076 * |
|
1077 * Parameters: |
|
1078 * None. |
|
1079 * |
|
1080 * Function: |
|
1081 * This function initializes the Video Decoder Core module meaning |
|
1082 * all the data common to all Video Decoder Core instances. |
|
1083 * vdcLoad has to be called before any other function of this module |
|
1084 * is used. |
|
1085 * |
|
1086 * Returns: |
|
1087 * >= 0 if succeeded |
|
1088 * < 0 if failed |
|
1089 * |
|
1090 * |
|
1091 */ |
|
1092 |
|
1093 int vdcLoad(void) |
|
1094 /* {{-output"vdcLoad.txt"}} */ |
|
1095 { |
|
1096 if (dblLoad() < 0) |
|
1097 return VDC_ERR; |
|
1098 |
|
1099 return VDC_OK; |
|
1100 } |
|
1101 |
|
1102 |
|
1103 /* {{-output"vdcOpen.txt"}} */ |
|
1104 /* |
|
1105 * vdcOpen |
|
1106 * |
|
1107 * |
|
1108 * Parameters: |
|
1109 * imageStore pointer to image store instance |
|
1110 * numReferenceFrames 1 if the Reference Picture Selection (RPS) |
|
1111 * mode (Annex N) should not be used, |
|
1112 * >1 tells how many reference images |
|
1113 * are stored in the RPS mode |
|
1114 * fudInstance pointer to Fast Update module instance |
|
1115 * hParent handle of Video Decoder Engine instance |
|
1116 * that created this VDC instance |
|
1117 * |
|
1118 * Function: |
|
1119 * This function creates and initializes a new Video Decoder Core instance. |
|
1120 * |
|
1121 * Returns: |
|
1122 * a handle to the created instance, |
|
1123 * or NULL if the function fails |
|
1124 * |
|
1125 * |
|
1126 */ |
|
1127 |
|
1128 vdcHInstance_t vdcOpen( |
|
1129 vdeIms_t *imageStore, |
|
1130 int numReferenceFrames, |
|
1131 void *hParent) |
|
1132 { |
|
1133 vdcInstance_t *instance; |
|
1134 |
|
1135 vdcAssert(numReferenceFrames >= 1); |
|
1136 |
|
1137 instance = (vdcInstance_t *) vdcMalloc(sizeof(vdcInstance_t)); |
|
1138 if (!instance) |
|
1139 return NULL; |
|
1140 memset(instance, 0, sizeof(vdcInstance_t)); |
|
1141 |
|
1142 instance->prevPicHeader = (vdxPictureHeader_t *)vdcMalloc( sizeof( vdxPictureHeader_t )); |
|
1143 if ( instance->prevPicHeader == NULL ) { |
|
1144 deb("vdcOpen, MALLOC for prevPicHeader failed.\n"); |
|
1145 goto errPHOpen; |
|
1146 } |
|
1147 instance->fPrevPicHeaderReliable = 1; |
|
1148 |
|
1149 instance->imageStore = imageStore; |
|
1150 |
|
1151 instance->numAnnexNScalabilityLayers = -1; /* Indicates no decoded frames */ |
|
1152 |
|
1153 instance->fGFIDShouldChange = 0; |
|
1154 instance->gfid = -1; |
|
1155 |
|
1156 instance->nOfDecodedFrames = 0; |
|
1157 |
|
1158 instance->hParent = hParent; |
|
1159 instance->snapshotStatus = -1; |
|
1160 |
|
1161 return (vdcHInstance_t) instance; |
|
1162 |
|
1163 /* Error cases: release everything in reverse order */ |
|
1164 errPHOpen: |
|
1165 |
|
1166 vdcDealloc(instance); |
|
1167 return NULL; |
|
1168 } |
|
1169 /* {{-output"vdcOpen.txt"}} */ |
|
1170 |
|
1171 |
|
1172 /* {{-output"vdcRestartVideo.txt"}} */ |
|
1173 /* |
|
1174 * vdcRestartVideo |
|
1175 * |
|
1176 * |
|
1177 * Parameters: |
|
1178 * hInstance handle of instance data |
|
1179 * |
|
1180 * Function: |
|
1181 * Resets the instance data but does not deallocate the allocated buffers. |
|
1182 * After this function vdcDecodeFrame can be called as if no data for this |
|
1183 * instance has been decoded. |
|
1184 * |
|
1185 * Note: |
|
1186 * This function is obsolete and not used anymore. If it is needed again, |
|
1187 * it should be re-implemented. |
|
1188 * |
|
1189 * Returns: |
|
1190 * Nothing |
|
1191 * |
|
1192 * |
|
1193 */ |
|
1194 |
|
1195 void vdcRestartVideo(vdcHInstance_t hInstance) |
|
1196 /* {{-output"vdcRestartVideo.txt"}} */ |
|
1197 { |
|
1198 vdcInstance_t *instance = (vdcInstance_t *) hInstance; |
|
1199 |
|
1200 if (instance) |
|
1201 memset(instance, 0, sizeof(vdcInstance_t)); |
|
1202 } |
|
1203 |
|
1204 |
|
1205 |
|
1206 |
|
1207 |
|
1208 /* |
|
1209 * Local functions |
|
1210 */ |
|
1211 |
|
1212 /* |
|
1213 * vdcFillCommonPartsOfImb |
|
1214 * |
|
1215 * |
|
1216 * Parameters: |
|
1217 * instance instance data |
|
1218 * numOfCodedMBs number of coded macroblocks |
|
1219 * imb pointer to image buffer to fill |
|
1220 * |
|
1221 * Function: |
|
1222 * This function fills the passed image buffer according to the latest |
|
1223 * decoding results. Only those parts of the image buffer are filled |
|
1224 * which can be composed with the presence of another image buffer, |
|
1225 * e.g. the P image buffer corresponding to the B image buffer. |
|
1226 * |
|
1227 * Returns: |
|
1228 * Nothing |
|
1229 * |
|
1230 * |
|
1231 */ |
|
1232 |
|
1233 static void vdcFillCommonPartsOfImb( |
|
1234 vdcInstance_t *instance, |
|
1235 int numOfCodedMBs, |
|
1236 vdeImb_t *imb) |
|
1237 { |
|
1238 vdcAssert(imb); |
|
1239 vdcAssert(instance); |
|
1240 |
|
1241 imb->drawItem->param.dwFlags = 0; |
|
1242 imb->drawItem->param.lTime = instance->frameNum; |
|
1243 |
|
1244 /* Note: for now, convert whole frame */ |
|
1245 imb->drawItem->extParam.flags = 0; |
|
1246 /* Else one could convert just coded MBs as follows: */ |
|
1247 /* imb->drawItem->extParam.flags = (fBPart) ? 0 : REN_EXTDRAW_NEW_SOURCE; */ |
|
1248 |
|
1249 imb->drawItem->extParam.rate = 30000; |
|
1250 imb->drawItem->extParam.scale = 1001; |
|
1251 imb->drawItem->extParam.numOfCodedMBs = numOfCodedMBs; |
|
1252 |
|
1253 /* imb->drawItem->retFrame and imb->drawItem->retFrameParam are set by |
|
1254 the caller */ |
|
1255 |
|
1256 imb->fReferenced = 1; |
|
1257 imb->tr = instance->pictureParam.tr; |
|
1258 } |
|
1259 |
|
1260 |
|
1261 /* |
|
1262 * vdcFillImageBuffers |
|
1263 * |
|
1264 * |
|
1265 * Parameters: |
|
1266 * instance instance data |
|
1267 * numOfCodedMBs number of coded macroblocks |
|
1268 * imbP pointer to image buffer of P or I frame |
|
1269 * |
|
1270 * Function: |
|
1271 * This function fills the passed image buffers according to the latest |
|
1272 * decoding results. |
|
1273 * |
|
1274 * Returns: |
|
1275 * >= 0 if the function was successful |
|
1276 * < 0 if an error occured |
|
1277 * |
|
1278 * |
|
1279 */ |
|
1280 |
|
1281 /* Codec and renderer dependent */ |
|
1282 int vdcFillImageBuffers( |
|
1283 vdcInstance_t *instance, |
|
1284 int numOfCodedMBs, |
|
1285 vdeImb_t *imbP) |
|
1286 { |
|
1287 /* Table to convert from lumiance quantization parameter to chrominance |
|
1288 quantization parameter if Modified Quantization (Annex T) is in use. */ |
|
1289 static const int yToUVQuantizer[32] = |
|
1290 {0,1,2,3,4,5,6,6,7,8,9,9,10,10,11,11,12, |
|
1291 12,12,13,13,13,14,14,14,14,14,15,15,15, |
|
1292 15,15}; |
|
1293 |
|
1294 int |
|
1295 firstQPIndex, /* the index of the first non-zero quantizer */ |
|
1296 |
|
1297 *yQuantParams = imbP->yQuantParams, |
|
1298 /* array of Y quantizers in scan-order */ |
|
1299 |
|
1300 *uvQuantParams = imbP->uvQuantParams, |
|
1301 /* array of UV quantizers in scan-order */ |
|
1302 |
|
1303 numMBsInPicture, /* number of macroblocks in the image */ |
|
1304 |
|
1305 i; /* loop variable */ |
|
1306 |
|
1307 vdcAssert(imbP); |
|
1308 vdcAssert(instance); |
|
1309 |
|
1310 /* |
|
1311 * Fill basic stuff |
|
1312 */ |
|
1313 |
|
1314 vdcFillCommonPartsOfImb(instance, numOfCodedMBs, imbP); |
|
1315 |
|
1316 /* |
|
1317 * Calculate quantizer arrays for loop/post-filtering |
|
1318 */ |
|
1319 |
|
1320 numMBsInPicture = instance->pictureParam.lumMemWidth * |
|
1321 instance->pictureParam.lumMemHeight / 256; |
|
1322 |
|
1323 /* Get the index of the first non-zero quantizer in scan-order */ |
|
1324 for (firstQPIndex = 0; firstQPIndex < numMBsInPicture; firstQPIndex++) { |
|
1325 if (yQuantParams[firstQPIndex] > 0) |
|
1326 break; |
|
1327 } |
|
1328 |
|
1329 /* Assert that at least one macroblock is decoded successfully */ |
|
1330 vdcAssert(firstQPIndex < numMBsInPicture); |
|
1331 |
|
1332 /* Replace the first zero quantizers with the first non-zero quantizer |
|
1333 (in scan-order) */ |
|
1334 for (i = 0; i < firstQPIndex; i++) |
|
1335 yQuantParams[i] = yQuantParams[firstQPIndex]; |
|
1336 |
|
1337 /* Replace all other zero quantizers with the predecessor (in scan-order) */ |
|
1338 for (i = firstQPIndex; i < numMBsInPicture; i++) { |
|
1339 if (yQuantParams[i] == 0) |
|
1340 yQuantParams[i] = yQuantParams[i - 1]; |
|
1341 } |
|
1342 |
|
1343 /* If Modified Quantization is in use */ |
|
1344 if (instance->pictureParam.fMQ) { |
|
1345 /* Convert Y quantizers to UV quantizers */ |
|
1346 for (i = 0; i < numMBsInPicture; i++) |
|
1347 uvQuantParams[i] = yToUVQuantizer[yQuantParams[i]]; |
|
1348 } |
|
1349 else |
|
1350 /* Copy Y quantizers to UV quantizers */ |
|
1351 memcpy(uvQuantParams, yQuantParams, numMBsInPicture * sizeof(int)); |
|
1352 |
|
1353 |
|
1354 return VDC_OK; |
|
1355 } |
|
1356 |
|
1357 // End of File |