|
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 * Video packet decoding module (MPEG-4). |
|
17 * |
|
18 */ |
|
19 |
|
20 |
|
21 /* |
|
22 * Includes |
|
23 */ |
|
24 #include "h263dConfig.h" |
|
25 #include "decvp_mpeg.h" |
|
26 #include "block.h" |
|
27 #include "debug.h" |
|
28 #include "decmbs.h" |
|
29 #include "stckheap.h" |
|
30 #include "sync.h" |
|
31 #include "viddemux.h" |
|
32 #include "biblin.h" |
|
33 /* MVE */ |
|
34 #include "MPEG4Transcoder.h" |
|
35 |
|
36 /* |
|
37 * Global functions |
|
38 */ |
|
39 |
|
40 /* {{-output"dvpGetAndDecodeVideoPacketHeader.txt"}} */ |
|
41 /* |
|
42 * dvpGetAndDecodeVideoPacketHeader |
|
43 * |
|
44 * |
|
45 * Parameters: |
|
46 * inParam input parameters |
|
47 * inOutParam input/output parameters, these parameters |
|
48 * may be modified in the function |
|
49 * |
|
50 * Function: |
|
51 * This function gets and decodes a Video Packet header at the |
|
52 * current position of the bit buffer. It checks its correctness and |
|
53 * if it fits to the sequence of VPs, and does the necessary actions for |
|
54 * correction. |
|
55 * |
|
56 * Returns: |
|
57 * >= 0 the function was successful |
|
58 * < 0 an error occured |
|
59 * |
|
60 */ |
|
61 |
|
62 int dvpGetAndDecodeVideoPacketHeader( |
|
63 const dvpVPInParam_t *inParam, |
|
64 dvpVPInOutParam_t *inOutParam) |
|
65 /* {{-output"dvpGetAndDecodeVideoPacketHeader.txt"}} */ |
|
66 { |
|
67 int16 error = 0; |
|
68 vdxGetVideoPacketHeaderInputParam_t vdxParam; |
|
69 vdxVideoPacketHeader_t header; |
|
70 bibBuffer_t *inBuffer = inParam->inBuffer; |
|
71 int bitErrorIndication = 0, retVal, fLostSegment = FALSE; |
|
72 |
|
73 /* |
|
74 * Get VP header |
|
75 */ |
|
76 |
|
77 vdxParam.fcode_forward = inParam->pictParam->fcode_forward; |
|
78 vdxParam.time_increment_resolution = inParam->pictParam->time_increment_resolution; |
|
79 vdxParam.numOfMBs = inParam->pictParam->numMBsInGOB; |
|
80 |
|
81 retVal = vdxGetVideoPacketHeader(inBuffer, &vdxParam, &header, &bitErrorIndication); |
|
82 if (retVal < 0) { |
|
83 return DGOB_ERR; |
|
84 } else if (retVal > 0) { |
|
85 deb("dvpGetAndDecodeVideoPacketHeader: ERROR - vdxGetVideoPacketHeader failed.\n"); |
|
86 goto headerFailure; |
|
87 } |
|
88 |
|
89 |
|
90 /* |
|
91 * Check header validity |
|
92 */ |
|
93 |
|
94 if (header.currMBNum == 0 || header.currMBNum >= inParam->pictParam->numMBsInGOB) { |
|
95 deb("dvpGetAndDecodeVideoPacketHeader: ERROR - too big currMBNum.\n"); |
|
96 goto headerFailure; |
|
97 } |
|
98 |
|
99 /* quant can not be zero */ |
|
100 if(header.quant == 0) { |
|
101 goto headerFailure; |
|
102 } |
|
103 |
|
104 if (header.fHEC) { |
|
105 |
|
106 if (header.time_base_incr < 0 || header.time_base_incr > 60) { |
|
107 if (bitErrorIndication) { |
|
108 goto headerFailure; |
|
109 } |
|
110 } |
|
111 |
|
112 /* fcode can have only the valid values 1..7 */ |
|
113 if (header.coding_type == VDX_VOP_TYPE_P) |
|
114 if (header.fcode_forward == 0) { |
|
115 goto headerFailure; |
|
116 } |
|
117 |
|
118 if (!inParam->fVOPHeaderCorrupted) { |
|
119 |
|
120 if ((inParam->pictParam->pictureType != header.coding_type) || |
|
121 (inParam->pictParam->time_base_incr != header.time_base_incr) || |
|
122 (inParam->pictParam->time_inc != header.time_inc)) { |
|
123 deb("dvpGetAndDecodeVideoPacketHeader: ERROR - Parameter change VOP<->VP header.\n"); |
|
124 goto headerFailure; |
|
125 } |
|
126 } |
|
127 } |
|
128 if (inParam->fVOPHeaderCorrupted) { |
|
129 /* Get the coding type parameter since it is needed in the concealment before the other updates */ |
|
130 if (header.fHEC) { |
|
131 inParam->pictParam->pictureType = header.coding_type; |
|
132 } |
|
133 } |
|
134 if (header.currMBNum != inOutParam->currMBNum) { |
|
135 if ( header.currMBNum > inOutParam->currMBNum && bitErrorIndication == 0) { |
|
136 |
|
137 fLostSegment = TRUE; |
|
138 goto headerFailure; |
|
139 |
|
140 } else if (header.currMBNum < inOutParam->currMBNum) { |
|
141 deb("dvpGetAndDecodeVideoPacketHeader: ERROR - MB counting is out of sync.\n"); |
|
142 goto headerFailure; |
|
143 } |
|
144 } |
|
145 |
|
146 /* |
|
147 * Update parameters |
|
148 */ |
|
149 |
|
150 inOutParam->currMBNum = header.currMBNum; |
|
151 inOutParam->quant = header.quant; |
|
152 |
|
153 if (inParam->fVOPHeaderCorrupted) { |
|
154 if (header.fHEC) { |
|
155 inParam->pictParam->mod_time_base += inParam->pictParam->time_base_incr = header.time_base_incr; |
|
156 |
|
157 inParam->pictParam->time_inc = header.time_inc; |
|
158 |
|
159 inOutParam->frameNum = (int) ((inParam->pictParam->mod_time_base + |
|
160 ((double) header.time_inc) / ((double) inParam->pictParam->time_increment_resolution)) * |
|
161 30.0 + 0.001); |
|
162 |
|
163 inParam->pictParam->tr = inOutParam->frameNum % 256; |
|
164 inParam->pictParam->pictureType = header.coding_type; |
|
165 |
|
166 inParam->pictParam->intra_dc_vlc_thr = header.intra_dc_vlc_thr; |
|
167 |
|
168 if (header.coding_type == VDX_VOP_TYPE_P) |
|
169 if (inParam->pictParam->fcode_forward != header.fcode_forward) { |
|
170 /* Initialize once to count parameters for the mvc module */ |
|
171 int r_size, scale_factor; |
|
172 |
|
173 inParam->pictParam->fcode_forward = header.fcode_forward; |
|
174 |
|
175 inOutParam->mvcData->f_code = inParam->pictParam->fcode_forward; |
|
176 r_size = inParam->pictParam->fcode_forward - 1; |
|
177 scale_factor = (1 << r_size); |
|
178 inOutParam->mvcData->range = 160 * scale_factor; |
|
179 } |
|
180 } else { |
|
181 /* seek next PSC, VP start code is not good enough */ |
|
182 sncRewindAndSeekNewMPEGSync(-1, inBuffer, 0, &error); |
|
183 return DGOB_OK_BUT_BIT_ERROR; |
|
184 } |
|
185 } |
|
186 |
|
187 if (fLostSegment) |
|
188 return DGOB_OK_BUT_BIT_ERROR; |
|
189 else |
|
190 return DGOB_OK; |
|
191 |
|
192 headerFailure: |
|
193 sncRewindAndSeekNewMPEGSync(-1, inBuffer, inParam->pictParam->fcode_forward, &error); |
|
194 |
|
195 if (error && error != ERR_BIB_NOT_ENOUGH_DATA) |
|
196 return DGOB_ERR; |
|
197 return DGOB_OK_BUT_BIT_ERROR; |
|
198 } |
|
199 |
|
200 |
|
201 /* {{-output"dvpGetAndDecodeVideoPacketContents.txt"}} */ |
|
202 /* |
|
203 * dvpGetAndDecodeVideoPacketContents |
|
204 * |
|
205 * |
|
206 * Parameters: |
|
207 * inParam input parameters |
|
208 * fGetNewReferenceFrame non-zero if a new reference frame must be |
|
209 * requested from the image store, otherwise 0 |
|
210 * inOutParam input/output parameters, these parameters |
|
211 * may be modified in the function |
|
212 * |
|
213 * Function: |
|
214 * This function gets and decodes the contents of a Video Packet |
|
215 * after the header of the VP (either VP header or picture |
|
216 * header) is already got and processed. It works MB-by-MB or if VP |
|
217 * is data partitioned calls the corresponding decoding functions. |
|
218 * Error concealment for the missing (not decodable) MBs in a P-frame |
|
219 * is called. |
|
220 * |
|
221 * Returns: |
|
222 * >= 0 the function was successful |
|
223 * < 0 an error occured |
|
224 * |
|
225 */ |
|
226 |
|
227 int dvpGetAndDecodeVideoPacketContents( |
|
228 const dvpVPInParam_t *inParam, |
|
229 int fGetNewReferenceFrame, |
|
230 dvpVPInOutParam_t *inOutParam, CMPEG4Transcoder *hTranscoder) |
|
231 /* {{-output"dvpGetAndDecodeVideoPacketContents.txt"}} */ |
|
232 { |
|
233 int16 error = 0; |
|
234 int bitErrorIndication = 0; |
|
235 dmbPFrameMBInParam_t dpmbi; |
|
236 dmbPFrameMBInOutParam_t dpmbio; |
|
237 dmbIFrameMBInParam_t dimbi; |
|
238 dmbIFrameMBInOutParam_t dimbio; |
|
239 int yPosInMBs, xPosInMBs = 0; |
|
240 bibBuffer_t *inBuffer; |
|
241 bibBuffer_t |
|
242 *outBuffer; /* Output bit buffer instance */ |
|
243 |
|
244 bibBufferEdit_t |
|
245 *bufEdit; |
|
246 |
|
247 int colorEffect; |
|
248 TBool getDecodedFrame; |
|
249 |
|
250 |
|
251 int fSegmentCorrupted = 0; |
|
252 |
|
253 int dmbRetValue; |
|
254 int sncCode = SNC_NO_SYNC; |
|
255 int lastMBNumInVP = 0; |
|
256 int startMB = inOutParam->currMBNum; |
|
257 |
|
258 SOH_DEFINE(blcDiffMB_t, pDiffMB); /* Storage for the previous difference blocks */ |
|
259 |
|
260 SOH_ALLOC(blcDiffMB_t, pDiffMB); |
|
261 |
|
262 if (pDiffMB == NULL) { |
|
263 deb("dvpGetAndDecodeVideoPacketContents: SOH_ALLOC failed.\n"); |
|
264 goto unexpectedError; |
|
265 } |
|
266 |
|
267 pDiffMB->cbpy = 0; |
|
268 |
|
269 inBuffer = inParam->inBuffer; |
|
270 outBuffer = inParam->outBuffer; |
|
271 bufEdit = inParam->bufEdit; |
|
272 colorEffect = inParam->iColorEffect; |
|
273 getDecodedFrame = inParam->iGetDecodedFrame; |
|
274 |
|
275 /* If the reference frame changed */ |
|
276 if (fGetNewReferenceFrame) { |
|
277 vdeIms_t *store = inOutParam->imageStore; |
|
278 vdeImsItem_t *imsItem; |
|
279 vdeImb_t *imb; |
|
280 int width, height; |
|
281 |
|
282 if (vdeImsGetReference(store, VDEIMS_REF_LATEST, 0, &imsItem) < 0) { |
|
283 deb("dvpGetAndDecodeVideoPacketContents: ERROR - vdeImsGetReference " |
|
284 "failed.\n"); |
|
285 goto unexpectedError; |
|
286 } |
|
287 |
|
288 /* If no reference frame available */ |
|
289 if (!imsItem) { |
|
290 /* Treat the situation like a decoding error.*/ |
|
291 deb("dvpGetAndDecodeVideoPacketContents: Warning - no reference frame " |
|
292 "available.\n"); |
|
293 goto headerFailure; |
|
294 } |
|
295 |
|
296 if (vdeImsStoreItemToImageBuffer(imsItem, &imb) < 0) { |
|
297 deb("dvpGetAndDecodeVideoPacketContents: ERROR - vdeImsStoreItemToImageBuffer " |
|
298 "failed.\n"); |
|
299 goto unexpectedError; |
|
300 } |
|
301 |
|
302 if (vdeImbYUV(imb, &inOutParam->refY, &inOutParam->refU, |
|
303 &inOutParam->refV, &width, &height) < 0) { |
|
304 deb("dvpGetAndDecodeVideoPacketContents: ERROR - vdeImbYUV " |
|
305 "failed.\n"); |
|
306 goto unexpectedError; |
|
307 } |
|
308 } |
|
309 |
|
310 xPosInMBs = (inOutParam->currMBNum % inParam->pictParam->numMBsInMBLine); |
|
311 yPosInMBs = (inOutParam->currMBNum / inParam->pictParam->numMBsInMBLine); |
|
312 |
|
313 /* if VOP header corrupted and first VP -> exit */ |
|
314 if(inParam->fVOPHeaderCorrupted && inOutParam->currMBNum==0) { |
|
315 fSegmentCorrupted = 1; |
|
316 goto exitWhenVOPHeaderCorrupted; |
|
317 } |
|
318 |
|
319 /* in case of an I-VOP */ |
|
320 if (inParam->pictParam->pictureType == VDX_VOP_TYPE_I) { |
|
321 dimbi.inBuffer = inBuffer; |
|
322 dimbi.outBuffer = outBuffer; |
|
323 dimbi.bufEdit = bufEdit; |
|
324 dimbi.iColorEffect = colorEffect; |
|
325 dimbi.iGetDecodedFrame = getDecodedFrame; |
|
326 |
|
327 dimbi.pictParam = inParam->pictParam; |
|
328 |
|
329 dimbi.xPosInMBs = xPosInMBs; |
|
330 dimbi.yPosInMBs = yPosInMBs; |
|
331 |
|
332 dimbio.currMBNum = inOutParam->currMBNum; |
|
333 dimbio.currMBNumInVP = 0; |
|
334 |
|
335 dimbio.aicData = inOutParam->aicData; |
|
336 |
|
337 dimbio.fCodedMBs = inOutParam->fCodedMBs; |
|
338 dimbio.numOfCodedMBs = inOutParam->numOfCodedMBs; |
|
339 dimbio.quant = inOutParam->quant; |
|
340 |
|
341 /* YUV pointers */ |
|
342 { |
|
343 int32 yOffset, uvOffset; |
|
344 |
|
345 yOffset = inParam->pictParam->lumMemWidth * dimbi.yPosInMBs + dimbi.xPosInMBs; |
|
346 uvOffset = (inParam->pictParam->lumMemWidth >> 1) * dimbi.yPosInMBs + dimbi.xPosInMBs; |
|
347 |
|
348 if ( inOutParam->currPY != NULL ) |
|
349 { |
|
350 dimbio.yMBInFrame = inOutParam->currPY + (yOffset << 4); |
|
351 dimbio.uBlockInFrame = inOutParam->currPU + (uvOffset << 3); |
|
352 dimbio.vBlockInFrame = inOutParam->currPV + (uvOffset << 3); |
|
353 } |
|
354 else |
|
355 { |
|
356 dimbio.yMBInFrame = NULL; |
|
357 dimbio.uBlockInFrame = NULL; |
|
358 dimbio.vBlockInFrame = NULL; |
|
359 } |
|
360 } |
|
361 } |
|
362 /* in case of a P-VOP */ |
|
363 else { |
|
364 dpmbi.inBuffer = inBuffer; |
|
365 dpmbi.outBuffer = outBuffer; |
|
366 dpmbi.bufEdit = bufEdit; |
|
367 dpmbi.iColorEffect = colorEffect; |
|
368 dpmbi.iGetDecodedFrame = getDecodedFrame; |
|
369 |
|
370 dpmbi.pictParam = inParam->pictParam; |
|
371 |
|
372 dpmbi.xPosInMBs = xPosInMBs; |
|
373 dpmbi.yPosInMBs = yPosInMBs; |
|
374 |
|
375 dpmbi.refY = inOutParam->refY; |
|
376 dpmbi.refU = inOutParam->refU; |
|
377 dpmbi.refV = inOutParam->refV; |
|
378 dpmbi.currPY = inOutParam->currPY; |
|
379 dpmbi.currPU = inOutParam->currPU; |
|
380 dpmbi.currPV = inOutParam->currPV; |
|
381 |
|
382 dpmbio.currMBNum = inOutParam->currMBNum; |
|
383 dpmbio.currMBNumInVP = 0; |
|
384 |
|
385 dpmbio.fCodedMBs = inOutParam->fCodedMBs; |
|
386 dpmbio.numOfCodedMBs = inOutParam->numOfCodedMBs; |
|
387 dpmbio.quant = inOutParam->quant; |
|
388 |
|
389 dpmbio.aicData = inOutParam->aicData; |
|
390 |
|
391 dpmbio.mvcData = inOutParam->mvcData; |
|
392 dpmbio.diffMB = pDiffMB; |
|
393 |
|
394 /* YUV pointers */ |
|
395 { |
|
396 int32 yOffset, uvOffset; |
|
397 |
|
398 yOffset = inParam->pictParam->lumMemWidth * dpmbi.yPosInMBs + dpmbi.xPosInMBs; |
|
399 uvOffset = (inParam->pictParam->lumMemWidth >> 1) * dpmbi.yPosInMBs + dpmbi.xPosInMBs; |
|
400 |
|
401 if ( inOutParam->currPY != NULL ) |
|
402 { |
|
403 dpmbio.yMBInFrame = inOutParam->currPY + (yOffset << 4); |
|
404 dpmbio.uBlockInFrame = inOutParam->currPU + (uvOffset << 3); |
|
405 dpmbio.vBlockInFrame = inOutParam->currPV + (uvOffset << 3); |
|
406 } |
|
407 else |
|
408 { |
|
409 dimbio.yMBInFrame = NULL; |
|
410 dimbio.uBlockInFrame = NULL; |
|
411 dimbio.vBlockInFrame = NULL; |
|
412 } |
|
413 } |
|
414 } |
|
415 |
|
416 /* Decode multiple Macroblocks until a resync_marker is found or error occurs */ |
|
417 while (inParam->pictParam->numMBsInGOB != inOutParam->currMBNum && |
|
418 sncCode != SNC_VIDPACK && sncCode != SNC_VOP) { |
|
419 |
|
420 /* MVE */ |
|
421 hTranscoder->BeginOneMB((inParam->pictParam->pictureType == VDX_VOP_TYPE_I) ? dimbio.currMBNum : dpmbio.currMBNum ); |
|
422 |
|
423 /* decode an I-frame MB */ |
|
424 if (inParam->pictParam->pictureType == VDX_VOP_TYPE_I) { |
|
425 |
|
426 if(inParam->pictParam->data_partitioned) { |
|
427 |
|
428 dmbRetValue = dmbsGetAndDecodeIMBsDataPartitioned(&dimbi, &dimbio, |
|
429 inOutParam->quantParams, hTranscoder); |
|
430 |
|
431 if (dmbRetValue < 0) |
|
432 goto unexpectedError; |
|
433 |
|
434 inOutParam->currMBNum = dimbio.currMBNum; |
|
435 |
|
436 /* Video Packet corrupted */ |
|
437 if ( fSegmentCorrupted ) |
|
438 break; |
|
439 |
|
440 } else { |
|
441 |
|
442 dmbRetValue = dmbGetAndDecodeIFrameMB(&dimbi, &dimbio, 1, hTranscoder); |
|
443 |
|
444 if (dmbRetValue < 0) |
|
445 goto unexpectedError; |
|
446 else if (dmbRetValue == DMB_BIT_ERR ) { |
|
447 /* Video Packet corrupted */ |
|
448 fSegmentCorrupted = 1; |
|
449 break; |
|
450 } |
|
451 |
|
452 /* Store quantizer */ |
|
453 inOutParam->quantParams[dimbio.currMBNum] = dimbio.quant; |
|
454 |
|
455 /* increment the frame pointers and MB counters */ |
|
456 dimbio.currMBNum++; |
|
457 dimbio.currMBNumInVP++; |
|
458 |
|
459 if ( dimbio.yMBInFrame != NULL ) |
|
460 { |
|
461 dimbio.yMBInFrame += 16; |
|
462 dimbio.uBlockInFrame += 8; |
|
463 dimbio.vBlockInFrame += 8; |
|
464 } |
|
465 dimbi.xPosInMBs++; |
|
466 |
|
467 if (dimbi.xPosInMBs == inParam->pictParam->numMBsInMBLine) { |
|
468 if ( dimbio.yMBInFrame != NULL ) |
|
469 { |
|
470 dimbio.yMBInFrame += 15 * inParam->pictParam->lumMemWidth; |
|
471 dimbio.uBlockInFrame += 7 * (inParam->pictParam->lumMemWidth >> 1); |
|
472 dimbio.vBlockInFrame += 7 * (inParam->pictParam->lumMemWidth >> 1); |
|
473 } |
|
474 dimbi.xPosInMBs = 0; |
|
475 dimbi.yPosInMBs++; |
|
476 } |
|
477 |
|
478 inOutParam->currMBNum = dimbio.currMBNum; |
|
479 } |
|
480 |
|
481 /* decode a P-frame MB */ |
|
482 } else { |
|
483 |
|
484 if(inParam->pictParam->data_partitioned) { |
|
485 |
|
486 dmbRetValue = dmbsGetAndDecodePMBsDataPartitioned(&dpmbi, &dpmbio, |
|
487 inOutParam->quantParams, hTranscoder); |
|
488 |
|
489 if (dmbRetValue < 0) |
|
490 goto unexpectedError; |
|
491 |
|
492 inOutParam->currMBNum = dpmbio.currMBNum; |
|
493 lastMBNumInVP = dpmbio.currMBNumInVP; |
|
494 |
|
495 /* Video Packet corrupted */ |
|
496 if ( fSegmentCorrupted ) |
|
497 break; |
|
498 |
|
499 } else { |
|
500 |
|
501 dmbRetValue = dmbGetAndDecodePFrameMB(&dpmbi, &dpmbio, 1, hTranscoder); |
|
502 |
|
503 if (dmbRetValue < 0) |
|
504 goto unexpectedError; |
|
505 else if (dmbRetValue == DMB_BIT_ERR ) { |
|
506 /* Video Packet corrupted */ |
|
507 fSegmentCorrupted = 1; |
|
508 break; |
|
509 } |
|
510 |
|
511 /* Store quantizer */ |
|
512 inOutParam->quantParams[dpmbio.currMBNum] = dpmbio.quant; |
|
513 |
|
514 /* increment the frame pointers and MB counters */ |
|
515 dpmbio.currMBNum++; |
|
516 dpmbio.currMBNumInVP++; |
|
517 |
|
518 if ( dpmbio.yMBInFrame != NULL ) |
|
519 { |
|
520 dpmbio.yMBInFrame += 16; |
|
521 dpmbio.uBlockInFrame += 8; |
|
522 dpmbio.vBlockInFrame += 8; |
|
523 } |
|
524 dpmbi.xPosInMBs++; |
|
525 |
|
526 if (dpmbi.xPosInMBs == inParam->pictParam->numMBsInMBLine) { |
|
527 if ( dpmbio.yMBInFrame != NULL ) |
|
528 { |
|
529 dpmbio.yMBInFrame += 15 * inParam->pictParam->lumMemWidth; |
|
530 dpmbio.uBlockInFrame += 7 * (inParam->pictParam->lumMemWidth >> 1); |
|
531 dpmbio.vBlockInFrame += 7 * (inParam->pictParam->lumMemWidth >> 1); |
|
532 } |
|
533 dpmbi.xPosInMBs = 0; |
|
534 dpmbi.yPosInMBs++; |
|
535 } |
|
536 |
|
537 inOutParam->currMBNum = dpmbio.currMBNum; |
|
538 } |
|
539 } |
|
540 |
|
541 /* check for a resync_marker */ |
|
542 sncCode = sncCheckMpegSync(inBuffer, inParam->pictParam->fcode_forward, &error); |
|
543 |
|
544 /* If sncCheckMpegSync failed */ |
|
545 if (error && error != ERR_BIB_NOT_ENOUGH_DATA) { |
|
546 deb1p("dvpGetAndDecodeVideoPacketContents: ERROR - sncCheckSync returned %d.\n", error); |
|
547 goto unexpectedError; |
|
548 |
|
549 } else |
|
550 /* If buffer ends (in one-frame-per-one-buffer case) */ |
|
551 if (sncCode == SNC_EOB || |
|
552 sncCode == SNC_STUFFING || |
|
553 error == ERR_BIB_NOT_ENOUGH_DATA) { |
|
554 break; |
|
555 } |
|
556 |
|
557 } |
|
558 |
|
559 |
|
560 // <-- |
|
561 |
|
562 inOutParam->numOfCodedMBs = (inParam->pictParam->pictureType != VDX_VOP_TYPE_I) ? |
|
563 dpmbio.numOfCodedMBs : dimbio.numOfCodedMBs; |
|
564 |
|
565 if (fSegmentCorrupted) { |
|
566 u_int32 nextVPBitPos; |
|
567 |
|
568 /* find the next resync marker, to get the number of MBs in the current VP */ |
|
569 sncCode = sncRewindAndSeekNewMPEGSync(-1, inBuffer, inParam->pictParam->fcode_forward, &error); |
|
570 if (error && error != ERR_BIB_NOT_ENOUGH_DATA) { |
|
571 goto unexpectedError; |
|
572 } else if (sncCode == SNC_EOB) { |
|
573 goto exitFunction; |
|
574 } |
|
575 |
|
576 nextVPBitPos = bibNumberOfFlushedBits(inParam->inBuffer); |
|
577 |
|
578 /* if the lastMBNumInVP was not yet read */ |
|
579 if (inParam->pictParam->pictureType == VDX_VOP_TYPE_I || |
|
580 !inParam->pictParam->data_partitioned || |
|
581 lastMBNumInVP == 0) { |
|
582 |
|
583 /* if VP header is found: read it, and get last MB number in current vop */ |
|
584 if (sncCode == SNC_VIDPACK) { |
|
585 vdxVideoPacketHeader_t header; |
|
586 vdxGetVideoPacketHeaderInputParam_t vdxParam; |
|
587 int retValue; |
|
588 |
|
589 vdxParam.fcode_forward = inParam->pictParam->fcode_forward; |
|
590 vdxParam.time_increment_resolution = inParam->pictParam->time_increment_resolution; |
|
591 vdxParam.numOfMBs = inParam->pictParam->numMBsInGOB; |
|
592 |
|
593 retValue = vdxGetVideoPacketHeader(inParam->inBuffer, &vdxParam, &header, &bitErrorIndication); |
|
594 if (retValue < 0) { |
|
595 goto unexpectedError; |
|
596 } else if (retValue == VDX_OK_BUT_BIT_ERROR) { |
|
597 /* If bit error occurred */ |
|
598 goto headerFailure; |
|
599 } |
|
600 |
|
601 /* rewind the bits to the beginning of the VP header */ |
|
602 bibRewindBits(bibNumberOfFlushedBits(inParam->inBuffer) - nextVPBitPos, |
|
603 inParam->inBuffer, &error); |
|
604 |
|
605 lastMBNumInVP = header.currMBNum; |
|
606 |
|
607 } else { |
|
608 lastMBNumInVP = inParam->pictParam->numMBsInGOB; |
|
609 } |
|
610 } |
|
611 |
|
612 /* if possibly the next VP header is damaged (it gives MB index which is smaller than the start of the current one */ |
|
613 if (lastMBNumInVP <= startMB || lastMBNumInVP > inParam->pictParam->numMBsInGOB) |
|
614 goto exitFunction; |
|
615 |
|
616 /* if the MB counting due to error overran the next VP header's value */ |
|
617 if (inOutParam->currMBNum > lastMBNumInVP) |
|
618 inOutParam->currMBNum = VDC_MAX(lastMBNumInVP-3,startMB); |
|
619 |
|
620 /* if not all the MBs have been predicted due to error */ |
|
621 else if (inOutParam->currMBNum < lastMBNumInVP) |
|
622 inOutParam->currMBNum = VDC_MAX(inOutParam->currMBNum-1,startMB); |
|
623 |
|
624 |
|
625 inOutParam->currMBNum = lastMBNumInVP; |
|
626 } |
|
627 |
|
628 exitFunction: |
|
629 |
|
630 |
|
631 exitWhenVOPHeaderCorrupted: |
|
632 |
|
633 if (!fSegmentCorrupted) { |
|
634 SOH_DEALLOC(pDiffMB); |
|
635 return DGOB_OK; |
|
636 } |
|
637 else { |
|
638 SOH_DEALLOC(pDiffMB); |
|
639 return DGOB_OK_BUT_BIT_ERROR; |
|
640 } |
|
641 |
|
642 headerFailure: |
|
643 SOH_DEALLOC(pDiffMB); |
|
644 sncRewindAndSeekNewMPEGSync(-1, inBuffer, 0, &error); |
|
645 if (error && error != ERR_BIB_NOT_ENOUGH_DATA) |
|
646 return DGOB_ERR; |
|
647 return DGOB_OK_BUT_BIT_ERROR; |
|
648 |
|
649 unexpectedError: |
|
650 SOH_DEALLOC(pDiffMB); |
|
651 return DGOB_ERR; |
|
652 } |
|
653 // End of File |