|
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 * MPEG-4 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 "decvp_mpeg.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 /* MVE */ |
|
39 #include "MPEG4Transcoder.h" |
|
40 |
|
41 |
|
42 /* |
|
43 * Typedefs and structs |
|
44 */ |
|
45 |
|
46 /* This structure is used to indicate the expected decoding position. */ |
|
47 typedef enum { |
|
48 EDP_START_OF_FRAME, |
|
49 EDP_START_OF_VIDEO_PACKET, |
|
50 EDP_END_OF_FRAME |
|
51 } vdcExpectedDecodingPosition_t; |
|
52 |
|
53 |
|
54 /* |
|
55 * Local function prototypes |
|
56 */ |
|
57 |
|
58 extern int vdcFillImageBuffers( |
|
59 vdcInstance_t *instance, |
|
60 int numOfCodedMBs, |
|
61 vdeImb_t *imbP); |
|
62 |
|
63 |
|
64 /* |
|
65 * Global functions |
|
66 */ |
|
67 |
|
68 /* {{-output"vdcDecodeMPEGVolHeader.txt"}} */ |
|
69 /* |
|
70 * vdcDecodeMPEGVolHeader |
|
71 * |
|
72 * |
|
73 * Parameters: |
|
74 * None. |
|
75 * |
|
76 * Function: |
|
77 * This function reads the VOL Header and updates the instance data |
|
78 * with the read parameters. |
|
79 * |
|
80 * Returns: |
|
81 * >= 0 if succeeded |
|
82 * < 0 if failed |
|
83 * |
|
84 */ |
|
85 |
|
86 int vdcDecodeMPEGVolHeader(vdcHInstance_t hInstance, bibBuffer_t *inBuffer, CMPEG4Transcoder *hTranscoder) |
|
87 /* {{-output"vdcDecodeMPEGVolHeader.txt"}} */ |
|
88 { |
|
89 dphInOutParam_t pichInOut; |
|
90 int headerSuccess = 0; |
|
91 |
|
92 pichInOut.vdcInstance = (vdcInstance_t *) hInstance; |
|
93 pichInOut.inBuffer = inBuffer; |
|
94 |
|
95 headerSuccess = dphGetMPEGVolHeader(&pichInOut, hTranscoder); |
|
96 if (headerSuccess != 0) |
|
97 return VDC_ERR; |
|
98 else |
|
99 return VDC_OK; |
|
100 } |
|
101 |
|
102 |
|
103 /* {{-output"vdcDecodeMPEGVop.txt"}} */ |
|
104 /* |
|
105 * vdcDecodeMPEGVop |
|
106 * |
|
107 * |
|
108 * Parameters: |
|
109 * hInstance handle of instance data |
|
110 * |
|
111 * inBuffer pointer to bit buffer, the current position |
|
112 * of the buffer must start with a PSC |
|
113 * |
|
114 * Function: |
|
115 * The vdcDecodeMPEGVop function implements the decoding process of the MPEG-4 |
|
116 * Simple Video Object described in ISO/IEC 14496-2. |
|
117 * |
|
118 * The function decodes the next frame in the buffer (inBuffer) meaning that |
|
119 * the decoding continues until the next VOP start code or EOB is found or |
|
120 * until the end of the buffer is not reached. |
|
121 * |
|
122 * Returns: |
|
123 * VDC_OK if the function was succesful |
|
124 * VDC_OK_BUT_BIT_ERROR if bit errors were detected but |
|
125 * decoded frames are provided by concealing |
|
126 * the errors |
|
127 * VDC_OK_BUT_FRAME_USELESS if severe bit errors were detected |
|
128 * (no concealment was possible) or |
|
129 * the bitstream ended unexpectedly |
|
130 * VDC_ERR if a processing error occured, |
|
131 * the instance should be closed |
|
132 * |
|
133 */ |
|
134 int vdcDecodeMPEGVop(vdcHInstance_t hInstance, bibBuffer_t *inBuffer, bibBuffer_t *outBuffer, |
|
135 bibBufferEdit_t *bufEdit, int aColorEffect, TBool aGetDecodedFrame, |
|
136 int aStartByteIndex, int aStartBitIndex, |
|
137 CMPEG4Transcoder *hTranscoder) |
|
138 /* {{-output"vdcDecodeMPEGVop.txt"}} */ |
|
139 { |
|
140 int sncCode; /* the latest synchronization code, see |
|
141 sncCheckSync for the possible values */ |
|
142 |
|
143 int retValue = VDC_OK; /* return value of this function */ |
|
144 |
|
145 int16 error = 0; |
|
146 |
|
147 u_char |
|
148 *currYFrame = NULL, /* current P frame */ |
|
149 *currUFrame = NULL, |
|
150 *currVFrame = NULL, |
|
151 *refYFrame = NULL, /* reference frame */ |
|
152 *refUFrame = NULL, |
|
153 *refVFrame = NULL; |
|
154 |
|
155 u_char *fCodedMBs = NULL; /* Pointer to table, which indicates coded \ |
|
156 macroblocks by non-zero value */ |
|
157 int numOfCodedMBs = 0; /* The number of coded macroblocks */ |
|
158 |
|
159 int *quantParams = NULL; /* Pointer to table, in which the quantization |
|
160 parameter for each macroblock is stored */ |
|
161 |
|
162 int currMBNum = 0; /* Current macro block */ |
|
163 |
|
164 int decStatus = 0; |
|
165 int corruptedVPs = 0; |
|
166 int numberOfVPs = 1; |
|
167 int headerSuccess = 0; |
|
168 u_char fVOPHeaderCorrupted = 0, fVOPHeaderLost = 0; |
|
169 |
|
170 vdcExpectedDecodingPosition_t expectedDecodingPosition; |
|
171 /* Tells in which part of the bitstream |
|
172 the decoding should be */ |
|
173 |
|
174 vdcInstance_t *instance = (vdcInstance_t *) hInstance; |
|
175 /* instance data */ |
|
176 |
|
177 vdcAssert(instance != NULL); |
|
178 |
|
179 /* Initializations */ |
|
180 |
|
181 instance->currFrame = NULL; |
|
182 expectedDecodingPosition = EDP_START_OF_FRAME; |
|
183 |
|
184 /* Main loop */ |
|
185 for (;;) { |
|
186 int bitErrorIndication = 0; |
|
187 |
|
188 sncCode = sncCheckMpegSync(inBuffer, instance->pictureParam.fcode_forward, &error); |
|
189 |
|
190 /* If sncCheckSync failed */ |
|
191 if (error && error != ERR_BIB_NOT_ENOUGH_DATA) { |
|
192 deb1p("vdcDecodeMPEGVop: ERROR - sncCheckSync returned %d.\n", error); |
|
193 retValue = VDC_ERR; |
|
194 goto exitFunction; |
|
195 } |
|
196 |
|
197 /* If EOS was got */ |
|
198 if (sncCode == SNC_EOB) |
|
199 instance->fEOS = 1; |
|
200 |
|
201 /* If frame ends appropriately */ |
|
202 if (expectedDecodingPosition == EDP_END_OF_FRAME && |
|
203 (sncCode == SNC_VOP || sncCode == SNC_GOV || sncCode == SNC_EOB || |
|
204 sncCode == SNC_STUFFING || error == ERR_BIB_NOT_ENOUGH_DATA)) |
|
205 goto exitFunction; |
|
206 |
|
207 /* Else if frame (or stream) data ends suddenly */ |
|
208 else if (error == ERR_BIB_NOT_ENOUGH_DATA) { |
|
209 retValue = VDC_OK_BUT_BIT_ERROR; |
|
210 goto exitFunction; |
|
211 } |
|
212 |
|
213 /* Else if EOS was reached */ |
|
214 else if (sncCode == SNC_EOB) { |
|
215 /* The current frame is useless since it ends before it is complete. |
|
216 On the other hand, there is no point in concealing it since |
|
217 it is the last frame of the sequence. */ |
|
218 goto exitFunction; |
|
219 } |
|
220 |
|
221 /* Else if frame starts as expected */ |
|
222 else if (expectedDecodingPosition == EDP_START_OF_FRAME && |
|
223 ((sncCode == SNC_GOV) || (sncCode == SNC_VOP) || fVOPHeaderLost)) { |
|
224 |
|
225 dphInParam_t pichIn; |
|
226 dphInOutParam_t pichInOut; |
|
227 dphOutParam_t pichOut; |
|
228 |
|
229 if (sncCode == SNC_GOV) { |
|
230 vdxGovHeader_t govHeader; |
|
231 |
|
232 headerSuccess = vdxGetGovHeader(inBuffer, &govHeader, &bitErrorIndication); |
|
233 if ( headerSuccess < 0) { |
|
234 retValue = VDC_ERR; |
|
235 goto exitFunction; |
|
236 } else if (( headerSuccess > 0 ) || |
|
237 (govHeader.time_stamp < instance->pictureParam.mod_time_base) || |
|
238 (govHeader.time_stamp - instance->pictureParam.mod_time_base > 60)) { |
|
239 |
|
240 if(sncCheckMpegVOP(inBuffer, &error) != SNC_PSC) { |
|
241 retValue = VDC_OK_BUT_FRAME_USELESS; |
|
242 goto exitFunction; |
|
243 } |
|
244 |
|
245 } else { |
|
246 instance->pictureParam.mod_time_base = govHeader.time_stamp; |
|
247 |
|
248 /* copying the user data */ |
|
249 if (govHeader.user_data != NULL) { |
|
250 |
|
251 if (!instance->user_data) |
|
252 instance->user_data = (char *) vdcMalloc( |
|
253 MAX_USER_DATA_LENGTH); |
|
254 |
|
255 govHeader.user_data_length = |
|
256 ((instance->user_data_length + govHeader.user_data_length) >= MAX_USER_DATA_LENGTH) ? |
|
257 (MAX_USER_DATA_LENGTH - instance->user_data_length) : govHeader.user_data_length; |
|
258 memcpy( |
|
259 instance->user_data + instance->user_data_length, |
|
260 govHeader.user_data, |
|
261 govHeader.user_data_length); |
|
262 instance->user_data_length += govHeader.user_data_length; |
|
263 |
|
264 vdcDealloc(govHeader.user_data); |
|
265 } |
|
266 |
|
267 } |
|
268 } |
|
269 |
|
270 /* Start VOP decoding */ |
|
271 pichIn.fReadBits = (fVOPHeaderLost ? 0 : 1); |
|
272 pichIn.fNeedDecodedFrame = aGetDecodedFrame | hTranscoder->NeedDecodedYUVFrame(); |
|
273 pichInOut.vdcInstance = instance; |
|
274 pichInOut.inBuffer = inBuffer; |
|
275 |
|
276 /* Get VOP header */ |
|
277 headerSuccess = dphGetMPEGVopHeader(&pichIn, &pichInOut, &pichOut, &bitErrorIndication); |
|
278 |
|
279 deb1p("vdcDecodeMPEGVop: frameNum %d.\n", instance->frameNum); |
|
280 if ( headerSuccess < 0) { |
|
281 retValue = VDC_ERR; |
|
282 goto exitFunction; |
|
283 } else if ( headerSuccess > 0 ) { |
|
284 |
|
285 if (headerSuccess == DPH_OK_BUT_BIT_ERROR) { |
|
286 /* find the next resync marker, to get the number of MBs in the current VP */ |
|
287 sncCode = sncRewindAndSeekNewMPEGSync(-1, inBuffer, instance->pictureParam.fcode_forward, &error); |
|
288 if (error && error != ERR_BIB_NOT_ENOUGH_DATA) { |
|
289 retValue = VDC_ERR; |
|
290 goto exitFunction; |
|
291 } |
|
292 |
|
293 if (sncCode == SNC_VIDPACK) { |
|
294 fVOPHeaderCorrupted = 1; |
|
295 } else { |
|
296 retValue = VDC_OK_BUT_FRAME_USELESS; |
|
297 goto exitFunction; |
|
298 } |
|
299 |
|
300 } else if (headerSuccess == DPH_OK_BUT_NOT_CODED) { |
|
301 |
|
302 /* MVE */ |
|
303 /* copy VOP header to output buffer in case VOP is not coded, including the GOV */ |
|
304 bufEdit->copyMode = CopyWhole; /* copyWhole */ |
|
305 CopyStream(inBuffer,outBuffer,bufEdit, aStartByteIndex, aStartBitIndex); |
|
306 |
|
307 /* behaves the same as if the frame was useless, but it's just not coded */ |
|
308 retValue = VDC_OK_BUT_NOT_CODED; |
|
309 goto exitFunction; |
|
310 } |
|
311 } |
|
312 |
|
313 |
|
314 currYFrame = pichOut.currYFrame; |
|
315 currUFrame = pichOut.currUFrame; |
|
316 currVFrame = pichOut.currVFrame; |
|
317 |
|
318 currMBNum = 0; |
|
319 |
|
320 numOfCodedMBs = 0; |
|
321 fCodedMBs = renDriCodedMBs(instance->currFrame->imb->drawItem); |
|
322 memset(fCodedMBs, 0, renDriNumOfMBs( |
|
323 instance->currFrame->imb->drawItem) * sizeof(u_char)); |
|
324 |
|
325 /* Initialize quantization parameter array */ |
|
326 quantParams = instance->currFrame->imb->yQuantParams; |
|
327 memset(quantParams, 0, renDriNumOfMBs( |
|
328 instance->currFrame->imb->drawItem) * sizeof(int)); |
|
329 |
|
330 /* If this is the first frame and callback function has been set, report frame size */ |
|
331 if (instance->nOfDecodedFrames == 0 && instance->reportPictureSizeCallback) { |
|
332 h263dReportPictureSizeCallback_t cb = |
|
333 (h263dReportPictureSizeCallback_t)instance->reportPictureSizeCallback; |
|
334 cb(instance->hParent, instance->pictureParam.lumWidth, instance->pictureParam.lumHeight); |
|
335 } |
|
336 |
|
337 /* Decode the 1st VP segment */ |
|
338 { |
|
339 dvpVPInParam_t dvpi; |
|
340 dvpVPInOutParam_t dvpio; |
|
341 |
|
342 dvpi.pictParam = &instance->pictureParam; |
|
343 dvpi.inBuffer = inBuffer; |
|
344 dvpi.outBuffer = outBuffer; |
|
345 dvpi.bufEdit = bufEdit; |
|
346 dvpi.iColorEffect = aColorEffect; |
|
347 dvpi.iGetDecodedFrame = aGetDecodedFrame; |
|
348 |
|
349 if (fVOPHeaderLost) fVOPHeaderCorrupted = 1; |
|
350 dvpi.fVOPHeaderCorrupted = fVOPHeaderCorrupted; |
|
351 |
|
352 dvpio.currMBNum = 0; |
|
353 dvpio.quant = pichOut.pquant; |
|
354 dvpio.fCodedMBs = fCodedMBs; |
|
355 dvpio.numOfCodedMBs = numOfCodedMBs; |
|
356 dvpio.quantParams = quantParams; |
|
357 dvpio.mvcData = &instance->mvcData; |
|
358 dvpio.aicData = &instance->aicData; |
|
359 dvpio.imageStore = instance->imageStore; |
|
360 dvpio.frameNum = instance->frameNum; |
|
361 |
|
362 dvpio.refY = refYFrame; |
|
363 dvpio.refU = refUFrame; |
|
364 dvpio.refV = refVFrame; |
|
365 dvpio.currPY = currYFrame; |
|
366 dvpio.currPU = currUFrame; |
|
367 dvpio.currPV = currVFrame; |
|
368 |
|
369 /* MVE */ |
|
370 hTranscoder->VOPHeaderEnded(aStartByteIndex, aStartBitIndex, |
|
371 pichOut.pquant, instance->pictureParam.pictureType, |
|
372 instance->frameNum, headerSuccess == DPH_OK_BUT_NOT_CODED); |
|
373 /* VOP header parsing success, begin on VP */ |
|
374 hTranscoder->BeginOneVideoPacket(&dvpi); |
|
375 hTranscoder->AfterVideoPacketHeader(&dvpio); // the first VP does not have VPHeader |
|
376 |
|
377 decStatus = dvpGetAndDecodeVideoPacketContents(&dvpi, |
|
378 instance->pictureParam.pictureType != VDX_PIC_TYPE_I, |
|
379 &dvpio, hTranscoder); |
|
380 |
|
381 if (decStatus < 0) { |
|
382 retValue = VDC_ERR; |
|
383 goto exitFunction; |
|
384 } else if (decStatus > 0 ) { |
|
385 if (decStatus == DGOB_OK_BUT_FRAME_USELESS) { |
|
386 retValue = VDC_OK_BUT_FRAME_USELESS; |
|
387 goto exitFunction; |
|
388 } |
|
389 corruptedVPs ++; |
|
390 } |
|
391 |
|
392 /* MVE */ |
|
393 /* the first VP ends */ |
|
394 hTranscoder->OneVPEnded(); |
|
395 |
|
396 currMBNum = dvpio.currMBNum; |
|
397 numOfCodedMBs = dvpio.numOfCodedMBs; |
|
398 refYFrame = dvpio.refY; |
|
399 refUFrame = dvpio.refU; |
|
400 refVFrame = dvpio.refV; |
|
401 |
|
402 |
|
403 if ((decStatus == DGOB_OK && currMBNum == instance->pictureParam.numMBsInGOB) || |
|
404 (decStatus == DGOB_OK_BUT_BIT_ERROR && sncCheckMpegVOP(inBuffer, &error) == SNC_PSC)) |
|
405 expectedDecodingPosition = EDP_END_OF_FRAME; |
|
406 else |
|
407 expectedDecodingPosition = EDP_START_OF_VIDEO_PACKET; |
|
408 } |
|
409 } |
|
410 |
|
411 /* Else if Video Packet starts as expected */ |
|
412 else if (expectedDecodingPosition == EDP_START_OF_VIDEO_PACKET && |
|
413 sncCode == SNC_VIDPACK) { |
|
414 |
|
415 dvpVPInParam_t dvpi; |
|
416 dvpVPInOutParam_t dvpio; |
|
417 |
|
418 dvpi.pictParam = &instance->pictureParam; |
|
419 dvpi.inBuffer = inBuffer; |
|
420 dvpi.outBuffer = outBuffer; |
|
421 dvpi.bufEdit = bufEdit; |
|
422 dvpi.iColorEffect = aColorEffect; |
|
423 dvpi.iGetDecodedFrame = aGetDecodedFrame; |
|
424 dvpi.fVOPHeaderCorrupted = fVOPHeaderCorrupted; |
|
425 |
|
426 dvpio.currMBNum = currMBNum; |
|
427 dvpio.fCodedMBs = fCodedMBs; |
|
428 dvpio.numOfCodedMBs = numOfCodedMBs; |
|
429 dvpio.quantParams = quantParams; |
|
430 dvpio.mvcData = &instance->mvcData; |
|
431 dvpio.aicData = &instance->aicData; |
|
432 dvpio.imageStore = instance->imageStore; |
|
433 |
|
434 dvpio.refY = refYFrame; |
|
435 dvpio.refU = refUFrame; |
|
436 dvpio.refV = refVFrame; |
|
437 dvpio.currPY = currYFrame; |
|
438 dvpio.currPU = currUFrame; |
|
439 dvpio.currPV = currVFrame; |
|
440 |
|
441 /* MVE */ |
|
442 /* VOP header parsing success, begin on VP */ |
|
443 hTranscoder->BeginOneVideoPacket(&dvpi); |
|
444 |
|
445 /* if the VOP header data needs to be corrected from the HEC codes set |
|
446 inParam->fVOPHeaderCorrupted and pictParam values will be set + read |
|
447 inOutParam->frameNum into instance->frameNum */ |
|
448 decStatus = dvpGetAndDecodeVideoPacketHeader(&dvpi, &dvpio); |
|
449 |
|
450 /* MVE */ |
|
451 /* After parsing the VP header */ |
|
452 hTranscoder->AfterVideoPacketHeader(&dvpio); |
|
453 |
|
454 if (decStatus < 0) { |
|
455 retValue = VDC_ERR; |
|
456 goto exitFunction; |
|
457 } else if (decStatus > 0) { |
|
458 |
|
459 if (fVOPHeaderCorrupted) { |
|
460 /* this is also true when the whole packet with the VOP header is lost */ |
|
461 |
|
462 if (dvpio.frameNum <= instance->frameNum) { |
|
463 /* VOP header could not be recovered from HEC (there was no HEC) |
|
464 or there was an error in the VP header: in this case should we try to recover |
|
465 VOP header from the next VP instead of the exiting here? */ |
|
466 retValue = VDC_OK_BUT_FRAME_USELESS; |
|
467 goto exitFunction; |
|
468 |
|
469 } else { |
|
470 /* VOP header was succesfully recovered from HEC, |
|
471 the first VP is treated as corrupted or lost */ |
|
472 instance->frameNum = dvpio.frameNum; |
|
473 |
|
474 } |
|
475 } else if (currMBNum < dvpio.currMBNum) { |
|
476 /* when there was no bit-error in the VP header and the MB counter shows difference |
|
477 we know, that a whole VP was lost */ |
|
478 |
|
479 corruptedVPs++; |
|
480 numberOfVPs++; |
|
481 |
|
482 |
|
483 } |
|
484 } |
|
485 |
|
486 numberOfVPs++; |
|
487 |
|
488 if (!decStatus) { |
|
489 |
|
490 |
|
491 decStatus = dvpGetAndDecodeVideoPacketContents(&dvpi,0,&dvpio, hTranscoder); |
|
492 if (decStatus < 0) { |
|
493 retValue = VDC_ERR; |
|
494 goto exitFunction; |
|
495 } else if (decStatus > 0 ) { |
|
496 if (decStatus == DGOB_OK_BUT_FRAME_USELESS) { |
|
497 retValue = VDC_OK_BUT_FRAME_USELESS; |
|
498 goto exitFunction; |
|
499 } |
|
500 corruptedVPs++; |
|
501 } |
|
502 |
|
503 } |
|
504 |
|
505 /* MVE */ |
|
506 hTranscoder->OneVPEnded(); |
|
507 |
|
508 currMBNum = dvpio.currMBNum; |
|
509 numOfCodedMBs = dvpio.numOfCodedMBs; |
|
510 |
|
511 if ((decStatus == DGOB_OK && currMBNum == instance->pictureParam.numMBsInGOB) || |
|
512 (decStatus == DGOB_OK_BUT_BIT_ERROR && sncCheckMpegVOP(inBuffer, &error) == SNC_PSC)) |
|
513 expectedDecodingPosition = EDP_END_OF_FRAME; |
|
514 else { |
|
515 expectedDecodingPosition = EDP_START_OF_VIDEO_PACKET; |
|
516 if (fVOPHeaderCorrupted) fVOPHeaderCorrupted=0; |
|
517 } |
|
518 } |
|
519 |
|
520 /* Else decoding is out of sync */ |
|
521 else { |
|
522 switch (expectedDecodingPosition) { |
|
523 |
|
524 case EDP_START_OF_FRAME: |
|
525 if (sncCode == SNC_VIDPACK) { |
|
526 /* VP start code instead of VOP start code -> |
|
527 packet including VOP header is lost */ |
|
528 fVOPHeaderLost = 1; |
|
529 continue; |
|
530 } else { |
|
531 /* No start code */ |
|
532 retValue = VDC_OK_BUT_FRAME_USELESS; |
|
533 goto exitFunction; |
|
534 } |
|
535 |
|
536 case EDP_START_OF_VIDEO_PACKET: |
|
537 /* If the decoding gets out of sync, the next sync code is |
|
538 seeked in dvpGetAndDecodeVideoPacketContents. Then, if |
|
539 the frame ends instead of a new VP header, we are here. */ |
|
540 |
|
541 /* Mark the missing VP corrupted */ |
|
542 { |
|
543 numberOfVPs++; |
|
544 corruptedVPs++; |
|
545 |
|
546 } |
|
547 |
|
548 retValue = VDC_OK_BUT_BIT_ERROR; |
|
549 goto exitFunction; |
|
550 |
|
551 case EDP_END_OF_FRAME: |
|
552 /* Too much data */ |
|
553 retValue = VDC_OK_BUT_BIT_ERROR; |
|
554 goto exitFunction; |
|
555 } |
|
556 } |
|
557 } |
|
558 |
|
559 |
|
560 |
|
561 exitFunction: |
|
562 |
|
563 /* MVE */ |
|
564 hTranscoder->VOPEnded(); |
|
565 |
|
566 if (sncCheckMpegSync(inBuffer, instance->pictureParam.fcode_forward, &error) == SNC_EOB) { |
|
567 instance->fEOS = 1; |
|
568 } |
|
569 |
|
570 /* If frame(s) not useless */ |
|
571 if (retValue == VDC_OK || retValue == VDC_OK_BUT_BIT_ERROR) { |
|
572 |
|
573 /* If bit errors */ |
|
574 if (corruptedVPs) { |
|
575 retValue = VDC_OK_BUT_FRAME_USELESS; |
|
576 } |
|
577 |
|
578 if ( retValue != VDC_OK_BUT_FRAME_USELESS ) { |
|
579 |
|
580 if ( instance->nOfDecodedFrames < 0xffffffff ) |
|
581 instance->nOfDecodedFrames++; |
|
582 if (vdcFillImageBuffers(instance, numOfCodedMBs, |
|
583 instance->currFrame->imb) < 0) |
|
584 retValue = VDC_ERR; |
|
585 |
|
586 } |
|
587 } |
|
588 |
|
589 /* If a fatal error occurred */ |
|
590 if (retValue < 0) { |
|
591 /* Return frame buffers for decoded output images, |
|
592 as they are useless for the caller and |
|
593 as the caller cannot get a handle to return them */ |
|
594 if (instance->currFrame) |
|
595 vdeImsPutFree(instance->imageStore, instance->currFrame); |
|
596 } |
|
597 |
|
598 return retValue; |
|
599 } |
|
600 |
|
601 |
|
602 /* {{-output"vdcIsMPEGINTRA.txt"}} */ |
|
603 /* |
|
604 * vdcIsMPEGINTRA |
|
605 * |
|
606 * |
|
607 * Parameters: |
|
608 * hInstance handle of instance data |
|
609 * frameStart pointer to memory chunk containing a frame |
|
610 * frameLength number of bytes in frame |
|
611 * |
|
612 * Function: |
|
613 * This function returns 1 if the passed frame is an INTRA frame. |
|
614 * Otherwise the function returns 0. |
|
615 * |
|
616 * Returns: |
|
617 * See above. |
|
618 * |
|
619 * |
|
620 */ |
|
621 |
|
622 int vdcIsMPEGINTRA( |
|
623 vdcHInstance_t hInstance, |
|
624 void *frameStart, |
|
625 unsigned frameLength) |
|
626 /* {{-output"vdcIsINTRA.txt"}} */ |
|
627 { |
|
628 bibBuffer_t *tmpBitBuffer; |
|
629 int fINTRA = 0, bitErrorIndication, syncCode, vdxStatus; |
|
630 int16 error = 0; |
|
631 vdcInstance_t *instance = (vdcInstance_t *) hInstance; |
|
632 vdxGovHeader_t govHeader; |
|
633 |
|
634 vdcAssert(instance); |
|
635 |
|
636 tmpBitBuffer = bibCreate(frameStart, frameLength, &error); |
|
637 if (!tmpBitBuffer || error) |
|
638 return 0; |
|
639 |
|
640 syncCode = sncCheckMpegSync(tmpBitBuffer, instance->pictureParam.fcode_forward, &error); |
|
641 |
|
642 if ((syncCode == SNC_GOV || syncCode == SNC_VOP) && error == 0) { |
|
643 vdxGetVopHeaderInputParam_t vopIn; |
|
644 vdxVopHeader_t vopOut; |
|
645 |
|
646 if (syncCode == SNC_GOV) { |
|
647 vdxStatus = vdxGetGovHeader(tmpBitBuffer, &govHeader, |
|
648 &bitErrorIndication); |
|
649 |
|
650 if (vdxStatus < 0 || bitErrorIndication != 0) |
|
651 return fINTRA; |
|
652 } |
|
653 |
|
654 /* MVE */ |
|
655 int dummy1, dummy2, dummy3, dummy4; /* not used for any processing */ |
|
656 /* Get VOP header */ |
|
657 vopIn.time_increment_resolution = instance->pictureParam.time_increment_resolution; |
|
658 vdxStatus = vdxGetVopHeader(tmpBitBuffer, &vopIn, &vopOut, |
|
659 &dummy1, &dummy2, &dummy3, &dummy4, |
|
660 &bitErrorIndication); |
|
661 |
|
662 |
|
663 if (vdxStatus >= 0 && bitErrorIndication == 0) |
|
664 fINTRA = (vopOut.coding_type == VDX_VOP_TYPE_I); |
|
665 } |
|
666 |
|
667 bibDelete(tmpBitBuffer, &error); |
|
668 |
|
669 return fINTRA; |
|
670 } |
|
671 // End of File |