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 * GOB decoding functions. |
|
17 * |
|
18 */ |
|
19 |
|
20 |
|
21 /* |
|
22 * Includes |
|
23 */ |
|
24 #include "h263dConfig.h" |
|
25 #include "decgob.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 /* |
|
38 * Global functions |
|
39 */ |
|
40 |
|
41 /* {{-output"dgobGetAndDecodeGOBSegment.txt"}} */ |
|
42 /* |
|
43 * dgobGetAndDecodeGOBSegment |
|
44 * |
|
45 * |
|
46 * Parameters: |
|
47 * inParam input parameters |
|
48 * inOutParam input/output parameters, these parameters |
|
49 * may be modified in the function |
|
50 * |
|
51 * Function: |
|
52 * This function gets and decodes a GOB segment which should start |
|
53 * with a GBSC at the current position of the bit buffer. |
|
54 * |
|
55 * Returns: |
|
56 * >= 0 the function was successful |
|
57 * < 0 an error occured |
|
58 * |
|
59 */ |
|
60 |
|
61 int dgobGetAndDecodeGOBSegment( |
|
62 const dgobGOBSegmentInParam_t *inParam, |
|
63 dgobGOBSegmentInOutParam_t *inOutParam, |
|
64 CMPEG4Transcoder *hTranscoder) |
|
65 /* {{-output"dgobGetAndDecodeGOBSegment.txt"}} */ |
|
66 { |
|
67 bibBuffer_t |
|
68 *inBuffer; /* Input bit buffer instance */ |
|
69 |
|
70 int |
|
71 retValue, /* Value returned from this function */ |
|
72 |
|
73 fGetNewReferenceFrame, |
|
74 /* 1 if the reference picture has changed from |
|
75 the previous one */ |
|
76 |
|
77 bitErrorIndication = 0, |
|
78 /* Carries bit error indication information returned |
|
79 by the video demultiplexer module */ |
|
80 |
|
81 intraGobsMissing = 0; |
|
82 /* Flag to indicate if INTRA coded GOBs are missing */ |
|
83 |
|
84 u_int32 |
|
85 segmStart = bibNumberOfFlushedBits( inParam->inBuffer ); |
|
86 /* Start bit buffer position of the GOB segment */ |
|
87 |
|
88 vdxGetGOBHeaderInputParam_t |
|
89 vdxParam; /* Input parameters for vdxGetGOBHeader */ |
|
90 |
|
91 vdxGOBHeader_t |
|
92 header; /* GOB header data */ |
|
93 |
|
94 inBuffer = inParam->inBuffer; |
|
95 |
|
96 /* |
|
97 * Get GOB header |
|
98 */ |
|
99 |
|
100 vdxParam.numStuffBits = inParam->numStuffBits; |
|
101 vdxParam.fCustomPCF = inParam->pictParam->fCustomPCF; |
|
102 vdxParam.fCPM = inParam->pictParam->cpm; |
|
103 vdxParam.fRPS = inParam->pictParam->fRPS; |
|
104 |
|
105 if (vdxGetGOBHeader(inBuffer, &vdxParam, &header, &bitErrorIndication, |
|
106 inParam->iColorEffect, &inOutParam->StartByteIndex, &inOutParam->StartBitIndex, hTranscoder) < 0) { |
|
107 |
|
108 deb("dgobGetAndDecodeGOBSegment: ERROR - vdxGetGOBHeader failed.\n"); |
|
109 goto unexpectedError; |
|
110 } |
|
111 |
|
112 /* |
|
113 * Check header validity |
|
114 */ |
|
115 |
|
116 if (header.gn >= inParam->pictParam->numGOBs) { |
|
117 deb("dgobGetAndDecodeGOBSegment: ERROR - too big GN.\n"); |
|
118 goto unexpectedError; |
|
119 } |
|
120 |
|
121 /* If TRP present and TRP is not 8-bit if only 8-bit TRs have existed. |
|
122 Note: The following condition assumes that only 8-bit TRs are allowed. */ |
|
123 if (header.trpi && header.trp > 255) { |
|
124 deb("dgobGetAndDecodeGOBSegment: ERROR - too big TRP.\n"); |
|
125 goto unexpectedError; |
|
126 } |
|
127 |
|
128 /* If GFID is not as expected */ |
|
129 if (inOutParam->gfid >= 0 && bitErrorIndication != 0 && |
|
130 ((inParam->fGFIDShouldChange && inOutParam->gfid == header.gfid) || |
|
131 (!inParam->fGFIDShouldChange && inOutParam->gfid != header.gfid))) { |
|
132 deb("dgobGetAndDecodeGOBSegment: ERROR - illegal GFID.\n"); |
|
133 goto unexpectedError; |
|
134 } |
|
135 |
|
136 inOutParam->prevGN = inOutParam->prevGNWithHeader = header.gn; |
|
137 /* GFID was valid, and in the next GOB the gfidShouldChange flag should be 0 and GFID should be |
|
138 the same as the current one */ |
|
139 inOutParam->gfid = header.gfid; |
|
140 |
|
141 fGetNewReferenceFrame = 0; |
|
142 if (inParam->pictParam->fRPS) { |
|
143 /* If TRP has changed */ |
|
144 if ((header.trpi && header.trp != inOutParam->trp) || |
|
145 (!header.trpi && inOutParam->trp >= 0)) |
|
146 fGetNewReferenceFrame = 1; |
|
147 |
|
148 if (header.trpi) |
|
149 inOutParam->trp = header.trp; |
|
150 else |
|
151 inOutParam->trp = -1; |
|
152 } |
|
153 |
|
154 /* MVE */ |
|
155 hTranscoder->H263GOBSliceHeaderEnded(&header, NULL); |
|
156 |
|
157 |
|
158 /* |
|
159 * Decode GOB contents |
|
160 */ |
|
161 |
|
162 retValue = dgobGetAndDecodeGOBSegmentContents(inParam, fGetNewReferenceFrame, |
|
163 header.gquant, inOutParam, hTranscoder); |
|
164 |
|
165 /* MVE */ |
|
166 hTranscoder->H263OneGOBSliceWithHeaderEnded(); |
|
167 |
|
168 |
|
169 if ( intraGobsMissing && retValue == 0 ) |
|
170 return DGOB_OK_BUT_BIT_ERROR; |
|
171 else |
|
172 return retValue; |
|
173 |
|
174 unexpectedError: |
|
175 return DGOB_ERR; |
|
176 } |
|
177 |
|
178 |
|
179 /* {{-output"dgobGetAndDecodeGOBSegmentContents.txt"}} */ |
|
180 /* |
|
181 * dgobGetAndDecodeGOBSegmentContents |
|
182 * |
|
183 * |
|
184 * Parameters: |
|
185 * inParam input parameters |
|
186 * fGetNewReferenceFrame non-zero if a new reference frame must be |
|
187 * requested from the image store, otherwise 0 |
|
188 * quant initial quantization parameter |
|
189 * inOutParam input/output parameters, these parameters |
|
190 * may be modified in the function |
|
191 * |
|
192 * Function: |
|
193 * This function gets and decodes the contents of a GOB segment |
|
194 * meaning that the header of the GOB (either GOB header or picture |
|
195 * header) is already got and processed and the macroblocks belonging |
|
196 * to the GOB segment are decoded. |
|
197 * |
|
198 * Returns: |
|
199 * >= 0 the function was successful |
|
200 * < 0 an error occured |
|
201 * |
|
202 */ |
|
203 |
|
204 int dgobGetAndDecodeGOBSegmentContents( |
|
205 const dgobGOBSegmentInParam_t *inParam, |
|
206 int fGetNewReferenceFrame, |
|
207 int quant, |
|
208 dgobGOBSegmentInOutParam_t *inOutParam, |
|
209 CMPEG4Transcoder *hTranscoder) |
|
210 /* {{-output"dgobGetAndDecodeGOBSegmentContents.txt"}} */ |
|
211 { |
|
212 bibBuffer_t |
|
213 *inBuffer; /* Input bit buffer instance */ |
|
214 |
|
215 |
|
216 bibBuffer_t |
|
217 *outBuffer; /* Output bit buffer instance */ |
|
218 |
|
219 bibBufferEdit_t |
|
220 *bufEdit; |
|
221 |
|
222 int colorEffect; |
|
223 TBool getDecodedFrame; |
|
224 |
|
225 |
|
226 /* decmbs input and output parameters */ |
|
227 dmbPFrameMBInParam_t dpmbi; |
|
228 dmbPFrameMBInOutParam_t dpmbio; |
|
229 dmbIFrameMBInParam_t dimbi; |
|
230 dmbIFrameMBInOutParam_t dimbio; |
|
231 |
|
232 int |
|
233 *pYPosInMBs, /* Pointer to variable containing the y-position |
|
234 of the current macroblock in macroblocks |
|
235 (starting from zero in the top row) */ |
|
236 fSegmentCorrupted = 0; |
|
237 /* Flag to indicate if the current GOB segment |
|
238 is corrupted */ |
|
239 |
|
240 int16 |
|
241 error = 0; /* Used to pass error codes from snc and erd modules */ |
|
242 |
|
243 /* Pointers to pointers pointing to the top-left corner of the current |
|
244 GOB (inside the current frame) */ |
|
245 u_char **pYGOB, **pUGOB, **pVGOB; |
|
246 |
|
247 SOH_DEFINE(blcDiffMB_t, pDiffMB); |
|
248 /* Storage for the previous difference blocks */ |
|
249 |
|
250 inBuffer = inParam->inBuffer; |
|
251 |
|
252 outBuffer = inParam->outBuffer; |
|
253 bufEdit = inParam->bufEdit; |
|
254 colorEffect = inParam->iColorEffect; |
|
255 getDecodedFrame = inParam->iGetDecodedFrame; |
|
256 |
|
257 |
|
258 SOH_ALLOC(blcDiffMB_t, pDiffMB); |
|
259 |
|
260 if (pDiffMB == NULL) { |
|
261 deb("dgobGetAndDecodeGOBSegmentContents: SOH_ALLOC failed.\n"); |
|
262 goto unexpectedError; |
|
263 } |
|
264 |
|
265 pDiffMB->cbpy = 0; |
|
266 |
|
267 /* If the reference frame changed */ |
|
268 if (fGetNewReferenceFrame) { |
|
269 vdeIms_t *store = inOutParam->imageStore; |
|
270 vdeImsItem_t *imsItem; |
|
271 vdeImb_t *imb; |
|
272 int width, height; |
|
273 |
|
274 /* Get the reference frame */ |
|
275 if (inOutParam->trp >= 0) { |
|
276 if (vdeImsGetReference(store, VDEIMS_REF_TR, inOutParam->trp, &imsItem) < 0) { |
|
277 deb("dgobGetAndDecodeGOBSegment: ERROR - vdeImsGetReference " |
|
278 "failed.\n"); |
|
279 goto unexpectedError; |
|
280 } |
|
281 } |
|
282 |
|
283 else { |
|
284 if (vdeImsGetReference(store, VDEIMS_REF_LATEST, 0, &imsItem) < 0) { |
|
285 deb("dgobGetAndDecodeGOBSegment: ERROR - vdeImsGetReference " |
|
286 "failed.\n"); |
|
287 goto unexpectedError; |
|
288 } |
|
289 } |
|
290 |
|
291 /* If no reference frame available */ |
|
292 if (!imsItem) { |
|
293 |
|
294 /* Treat the situation like a decoding error. |
|
295 This should cause error concealment and |
|
296 a NACK message if Annex N is used. */ |
|
297 deb("dgobGetAndDecodeGOBSegment: Warning - no reference frame " |
|
298 "available.\n"); |
|
299 |
|
300 goto unexpectedError; |
|
301 } |
|
302 |
|
303 if (vdeImsStoreItemToImageBuffer(imsItem, &imb) < 0) { |
|
304 deb("dgobGetAndDecodeGOBSegment: ERROR - vdeImsStoreItemToImageBuffer " |
|
305 "failed.\n"); |
|
306 goto unexpectedError; |
|
307 } |
|
308 |
|
309 inOutParam->rtr = imb->tr; |
|
310 |
|
311 if (vdeImbYUV(imb, &inOutParam->refY, &inOutParam->refU, |
|
312 &inOutParam->refV, &width, &height) < 0) { |
|
313 deb("dgobGetAndDecodeGOBSegment: ERROR - vdeImbYUV " |
|
314 "failed.\n"); |
|
315 goto unexpectedError; |
|
316 } |
|
317 } |
|
318 |
|
319 /* Preset structures for multiple macroblock decoding */ |
|
320 if (inParam->pictParam->pictureType == VDX_PIC_TYPE_I) { |
|
321 dimbi.inBuffer = inBuffer; |
|
322 |
|
323 |
|
324 dimbi.outBuffer = outBuffer; |
|
325 dimbi.bufEdit = bufEdit; |
|
326 dimbi.iColorEffect = colorEffect; |
|
327 dimbi.iGetDecodedFrame = getDecodedFrame; |
|
328 dimbio.StartByteIndex = inOutParam->StartByteIndex; |
|
329 dimbio.StartBitIndex = inOutParam->StartBitIndex; |
|
330 |
|
331 |
|
332 dimbi.xPosInMBs = 0; |
|
333 /* yPosInMBs set inside the loop (below) */ |
|
334 dimbi.pictParam = inParam->pictParam; |
|
335 dimbi.fGOBHeaderPresent = 1; |
|
336 |
|
337 dimbio.fCodedMBs = inOutParam->fCodedMBs; |
|
338 dimbio.numOfCodedMBs = inOutParam->numOfCodedMBs; |
|
339 dimbio.quant = quant; |
|
340 |
|
341 /* YUV pointers set iside the loop (below) */ |
|
342 |
|
343 pYPosInMBs = &dimbi.yPosInMBs; |
|
344 pYGOB = &dimbio.yMBInFrame; |
|
345 pUGOB = &dimbio.uBlockInFrame; |
|
346 pVGOB = &dimbio.vBlockInFrame; |
|
347 } |
|
348 |
|
349 else { |
|
350 dpmbi.inBuffer = inBuffer; |
|
351 |
|
352 |
|
353 dpmbi.outBuffer = outBuffer; |
|
354 dpmbi.bufEdit = bufEdit; |
|
355 dpmbi.iColorEffect = colorEffect; |
|
356 dpmbi.iGetDecodedFrame = getDecodedFrame; |
|
357 dpmbio.StartByteIndex = inOutParam->StartByteIndex; |
|
358 dpmbio.StartBitIndex = inOutParam->StartBitIndex; |
|
359 |
|
360 |
|
361 dpmbi.xPosInMBs = 0; |
|
362 /* yPosInMBs set inside the loop (below) */ |
|
363 dpmbi.pictParam = inParam->pictParam; |
|
364 dpmbi.fGOBHeaderPresent = 1; |
|
365 dpmbi.refY = inOutParam->refY; |
|
366 dpmbi.refU = inOutParam->refU; |
|
367 dpmbi.refV = inOutParam->refV; |
|
368 dpmbi.currPY = inOutParam->currPY; |
|
369 dpmbi.currPU = inOutParam->currPU; |
|
370 dpmbi.currPV = inOutParam->currPV; |
|
371 |
|
372 dpmbio.fCodedMBs = inOutParam->fCodedMBs; |
|
373 dpmbio.numOfCodedMBs = inOutParam->numOfCodedMBs; |
|
374 dpmbio.quant = quant; |
|
375 |
|
376 /* YUV pointers set iside the loop (below) */ |
|
377 dpmbio.mvcData = inOutParam->mvcData; |
|
378 dpmbio.diffMB = pDiffMB; |
|
379 |
|
380 pYPosInMBs = &dpmbi.yPosInMBs; |
|
381 pYGOB = &dpmbio.yMBInFrame; |
|
382 pUGOB = &dpmbio.uBlockInFrame; |
|
383 pVGOB = &dpmbio.vBlockInFrame; |
|
384 } |
|
385 |
|
386 /* Loop forever (until the GOB segment ends) */ |
|
387 for (;;) { |
|
388 int dmbsRetValue; |
|
389 int numMBsInCurrGOB; |
|
390 int sncCode; |
|
391 int numStuffBits; |
|
392 int mbNumberInScanOrder; |
|
393 |
|
394 if ((inOutParam->prevGN == inParam->pictParam->numGOBs - 1) && |
|
395 (inParam->pictParam->fLastGOBSizeDifferent)) |
|
396 numMBsInCurrGOB = inParam->pictParam->numMBsInLastGOB; |
|
397 else |
|
398 numMBsInCurrGOB = inParam->pictParam->numMBsInGOB; |
|
399 |
|
400 *pYPosInMBs = inOutParam->prevGN * inParam->pictParam->numMBLinesInGOB; |
|
401 |
|
402 mbNumberInScanOrder = *pYPosInMBs * inParam->pictParam->numMBsInMBLine; |
|
403 |
|
404 /* Set pointers for the GOB (inside frame(s)) */ |
|
405 if ( inOutParam->currPY != NULL ) |
|
406 { |
|
407 int32 yOffset, uvOffset; |
|
408 |
|
409 yOffset = *pYPosInMBs * 16 * inParam->pictParam->lumMemWidth; |
|
410 |
|
411 *pYGOB = inOutParam->currPY + yOffset; |
|
412 |
|
413 uvOffset = yOffset / 4; |
|
414 *pUGOB = inOutParam->currPU + uvOffset; |
|
415 *pVGOB = inOutParam->currPV + uvOffset; |
|
416 |
|
417 } |
|
418 else |
|
419 { |
|
420 *pYGOB = NULL; |
|
421 *pUGOB = NULL; |
|
422 *pVGOB = NULL; |
|
423 } |
|
424 |
|
425 /* Decode macroblocks of the current GOB */ |
|
426 if (inParam->pictParam->pictureType == VDX_PIC_TYPE_I) { |
|
427 dimbi.numMBsInSegment = numMBsInCurrGOB; |
|
428 dmbsRetValue = dmbsGetAndDecodeIMBsInScanOrder(&dimbi, |
|
429 &dimbio, &inOutParam->quantParams[mbNumberInScanOrder], hTranscoder); |
|
430 |
|
431 inOutParam->StartByteIndex = dimbio.StartByteIndex; |
|
432 inOutParam->StartBitIndex = dimbio.StartBitIndex; |
|
433 |
|
434 |
|
435 } |
|
436 else { |
|
437 dpmbi.numMBsInSegment = numMBsInCurrGOB; |
|
438 dmbsRetValue = dmbsGetAndDecodePMBsInScanOrder(&dpmbi, |
|
439 &dpmbio, &inOutParam->quantParams[mbNumberInScanOrder], hTranscoder); |
|
440 |
|
441 inOutParam->StartByteIndex = dpmbio.StartByteIndex; |
|
442 inOutParam->StartBitIndex = dpmbio.StartBitIndex; |
|
443 } |
|
444 |
|
445 if (dmbsRetValue < 0) |
|
446 goto unexpectedError; |
|
447 |
|
448 /* Some bit errors were found inside the segment |
|
449 (dpmbi/dimbi fSegmentCorrupted have the same address as fSegmentCorrupted) |
|
450 Note that if no suspicious/corrupted blocks was found, but there was crc-error, |
|
451 this flag is not set. However, that case will be checked if no sync code is found */ |
|
452 if ( fSegmentCorrupted ) |
|
453 break; |
|
454 |
|
455 /* Check if there is a synchronization code in the current bitstream |
|
456 position */ |
|
457 sncCode = sncCheckSync(inBuffer, &numStuffBits, &error); |
|
458 |
|
459 /* If buffer ends (in one-frame-per-one-buffer case) */ |
|
460 if (error == ERR_BIB_NOT_ENOUGH_DATA) |
|
461 break; |
|
462 |
|
463 if (error) |
|
464 goto unexpectedError; |
|
465 |
|
466 /* If there is a synchronization code */ |
|
467 if (sncCode != SNC_NO_SYNC ) |
|
468 break; |
|
469 |
|
470 |
|
471 if (inOutParam->prevGN + 1 < inParam->pictParam->numGOBs) |
|
472 inOutParam->prevGN++; |
|
473 |
|
474 else { |
|
475 deb("dgobGetAndDecodeGOBSegment: ERROR - too much frame data.\n"); |
|
476 fSegmentCorrupted = 1; |
|
477 break; |
|
478 } |
|
479 |
|
480 dpmbi.fGOBHeaderPresent = 0; |
|
481 dimbi.fGOBHeaderPresent = 0; |
|
482 } |
|
483 |
|
484 /* Update coded macroblock counter */ |
|
485 if (inParam->pictParam->pictureType == VDX_PIC_TYPE_I) |
|
486 inOutParam->numOfCodedMBs = dimbio.numOfCodedMBs; |
|
487 else |
|
488 inOutParam->numOfCodedMBs = dpmbio.numOfCodedMBs; |
|
489 |
|
490 if (!fSegmentCorrupted) { |
|
491 SOH_DEALLOC(pDiffMB); |
|
492 if (inOutParam->trp >= 0) { |
|
493 } |
|
494 |
|
495 return DGOB_OK; |
|
496 } |
|
497 else { |
|
498 |
|
499 return DGOB_OK_BUT_BIT_ERROR; |
|
500 } |
|
501 |
|
502 unexpectedError: |
|
503 SOH_DEALLOC(pDiffMB); |
|
504 return DGOB_ERR; |
|
505 } |
|
506 |
|
507 |
|
508 // End of File |
|