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 * Picture header decoding functions (MPEG-4). |
|
17 * |
|
18 */ |
|
19 |
|
20 |
|
21 |
|
22 #include "h263dConfig.h" |
|
23 #include "mpegcons.h" |
|
24 #include "sync.h" |
|
25 #include "decpich.h" |
|
26 #include "debug.h" |
|
27 #include "vdeims.h" |
|
28 #include "vdeimb.h" |
|
29 #include "viddemux.h" |
|
30 |
|
31 |
|
32 /* |
|
33 * Global functions |
|
34 */ |
|
35 |
|
36 /* |
|
37 * dphGetMPEGVolHeader |
|
38 * |
|
39 * |
|
40 * Parameters: |
|
41 * hInstance instance data |
|
42 * |
|
43 * Function: |
|
44 * This function decodes the Video Object Header and the VOL Header |
|
45 * and initializes the fields of vdcInstance which are set in these |
|
46 * headers. Check and reports (generating error messages) if the header |
|
47 * shows a configuration on feature which is not supported by the |
|
48 * Simple Video Object Profile of MPEG4 |
|
49 * |
|
50 * Returns: |
|
51 * VDE_OK if the function was successful |
|
52 * VDE_ERROR if a fatal error, from which the decoder |
|
53 * cannot be restored, has occured |
|
54 * |
|
55 */ |
|
56 |
|
57 int dphGetMPEGVolHeader(dphInOutParam_t *inOutParam, CMPEG4Transcoder *hTranscoder) |
|
58 { |
|
59 vdcInstance_t *instance = inOutParam->vdcInstance; |
|
60 bibBuffer_t *inBuffer = inOutParam->inBuffer; |
|
61 int bitErrorIndication = 0; |
|
62 vdxVolHeader_t volHeader; |
|
63 |
|
64 /* read the Stream headers from the bitstream */ |
|
65 if ((vdxGetVolHeader(inBuffer, &volHeader, &bitErrorIndication, 0, 0, 0, hTranscoder) != VDX_OK) || |
|
66 (bitErrorIndication != 0)) { |
|
67 return DPH_ERR; |
|
68 } |
|
69 |
|
70 /* copy the useful VOL parameters to pictureParam or the core data structure */ |
|
71 instance->pictureParam.vo_id = volHeader.vo_id; |
|
72 instance->pictureParam.vol_id = volHeader.vol_id; |
|
73 instance->pictureParam.time_increment_resolution = volHeader.time_increment_resolution; |
|
74 |
|
75 /* MVE */ |
|
76 instance->pictureParam.fixed_vop_rate = volHeader.fixed_vop_rate; |
|
77 |
|
78 instance->pictureParam.lumWidth = volHeader.lumWidth; |
|
79 instance->pictureParam.lumHeight = volHeader.lumHeight; |
|
80 |
|
81 if (volHeader.lumWidth%16) |
|
82 instance->pictureParam.lumMemWidth = (((volHeader.lumWidth >>4/*/16*/) + 1) <<4/** 16*/); |
|
83 else |
|
84 instance->pictureParam.lumMemWidth = volHeader.lumWidth; |
|
85 |
|
86 if (volHeader.lumHeight%16) |
|
87 instance->pictureParam.lumMemHeight = (((volHeader.lumHeight >>4/*/16*/) + 1) <<4/** 16*/); |
|
88 else |
|
89 instance->pictureParam.lumMemHeight = volHeader.lumHeight; |
|
90 |
|
91 instance->pictureParam.error_res_disable = volHeader.error_res_disable; |
|
92 instance->pictureParam.data_partitioned = volHeader.data_partitioned; |
|
93 instance->pictureParam.reversible_vlc = volHeader.reversible_vlc; |
|
94 |
|
95 /* copy the got user data to the core data structure */ |
|
96 if (volHeader.user_data != NULL) { |
|
97 instance->user_data = (char *) malloc(MAX_USER_DATA_LENGTH); |
|
98 |
|
99 volHeader.user_data_length = |
|
100 ((instance->user_data_length + volHeader.user_data_length) >= MAX_USER_DATA_LENGTH) ? |
|
101 (MAX_USER_DATA_LENGTH - instance->user_data_length) : volHeader.user_data_length; |
|
102 |
|
103 memcpy( |
|
104 instance->user_data + instance->user_data_length, |
|
105 volHeader.user_data, |
|
106 volHeader.user_data_length); |
|
107 |
|
108 instance->user_data_length += volHeader.user_data_length; |
|
109 |
|
110 free(volHeader.user_data); |
|
111 } |
|
112 |
|
113 return DPH_OK; |
|
114 } |
|
115 |
|
116 /* {{-output"dphGetMPEGVopHeader.txt"}} */ |
|
117 /* |
|
118 * dphGetMPEGVopHeader |
|
119 * |
|
120 * |
|
121 * Parameters: |
|
122 * inOutParam input/output parameters, these parameters |
|
123 * may be modified in the function |
|
124 * outParam output parameters |
|
125 * bitErrorIndication bit error indication, see biterr.h for |
|
126 * the possible values |
|
127 * |
|
128 * Function: |
|
129 * This function gets and decodes an MPEG Vop header which should start |
|
130 * with a VOP start_code at the current position of the bit buffer. |
|
131 * At first, the function reads the picture header fields from the bitstream. |
|
132 * Then, it checks whether the values of the fields are supported. |
|
133 * An unsupported value is interpreted as a bit error. Finally, |
|
134 * the function updates VDC instance data and output parameters |
|
135 * (according to the new picture header). |
|
136 * |
|
137 * Returns: |
|
138 * >= 0 the function was successful |
|
139 * < 0 an error occured |
|
140 * |
|
141 */ |
|
142 |
|
143 int dphGetMPEGVopHeader( |
|
144 const dphInParam_t *inParam, |
|
145 dphInOutParam_t *inOutParam, |
|
146 dphOutParam_t *outParam, |
|
147 int *bitErrorIndication) |
|
148 /* {{-output"dphGetMPEGVopHeader.txt"}} */ |
|
149 { |
|
150 bibBuffer_t *inBuffer = inOutParam->inBuffer; |
|
151 u_char fPrevIntraGot; /* Non-zero if an INTRA frame has been decoded |
|
152 before the current frame */ |
|
153 vdxGetVopHeaderInputParam_t picHdrIn; |
|
154 vdxVopHeader_t picHeader; |
|
155 vdcInstance_t *instance = inOutParam->vdcInstance; |
|
156 vdcPictureParam_t *pictureParam = &instance->pictureParam; |
|
157 int fInterFrame; /* non-zero = INTER frame, 0 = INTRA frame */ |
|
158 int ret = DPH_OK, curr_mod_time_base=0; |
|
159 int16 error = 0; |
|
160 int32 currFrameNum=0; |
|
161 |
|
162 /* In normal case read the picture header from the bitstream. |
|
163 This function can be also called just to initialize the default |
|
164 picture header parameters and allocate image buffers, but not read |
|
165 the picture header from bitstream. This is used when the picture |
|
166 header has been lost (e.g. packet loss) but decoding is continued */ |
|
167 |
|
168 if (inParam->fReadBits) { |
|
169 |
|
170 /* |
|
171 * Get picture header |
|
172 */ |
|
173 |
|
174 picHdrIn.time_increment_resolution = pictureParam->time_increment_resolution; |
|
175 |
|
176 /* MVE */ |
|
177 int dummy1, dummy2, dummy3, dummy4; /* not used for processing */ |
|
178 ret = vdxGetVopHeader(inBuffer, &picHdrIn, &picHeader, |
|
179 &dummy1, &dummy2, &dummy3, &dummy4, |
|
180 bitErrorIndication); |
|
181 |
|
182 if ( ret < 0 ) |
|
183 return DPH_ERR; |
|
184 else if ( ret > 0 ) { |
|
185 ret = DPH_OK_BUT_BIT_ERROR; |
|
186 goto updateInstanceData; |
|
187 } else { |
|
188 ret = DPH_OK; |
|
189 } |
|
190 |
|
191 /* |
|
192 * Check picture header validity |
|
193 */ |
|
194 |
|
195 /* Local parameters needed in validity check (and possibly afterwards) */ |
|
196 fPrevIntraGot = instance->fIntraGot; |
|
197 fInterFrame = (picHeader.coding_type == VDX_VOP_TYPE_P); |
|
198 |
|
199 |
|
200 if (picHeader.time_base_incr < 0 || picHeader.time_base_incr > 60) { |
|
201 if ( *bitErrorIndication ) { |
|
202 ret = DPH_OK_BUT_BIT_ERROR; |
|
203 goto updateInstanceData; |
|
204 } |
|
205 } |
|
206 |
|
207 curr_mod_time_base = pictureParam->mod_time_base + picHeader.time_base_incr; |
|
208 |
|
209 currFrameNum = (int) ((curr_mod_time_base + |
|
210 ((double) picHeader.time_inc) / ((double) pictureParam->time_increment_resolution)) * |
|
211 30.0 + 0.001); |
|
212 |
|
213 if ((currFrameNum <= instance->frameNum) && |
|
214 (instance->frameNum > 0)) { |
|
215 if (*bitErrorIndication) { |
|
216 ret = DPH_OK_BUT_BIT_ERROR; |
|
217 goto updateInstanceData; |
|
218 } else { |
|
219 /* this can happen if a previous picture header is lost and it had |
|
220 mod_time_base increase information. */ |
|
221 int i; |
|
222 int32 tryFrameNum=0; |
|
223 for (i=1;i<5;i++) { |
|
224 tryFrameNum = (int) (((curr_mod_time_base+i) + |
|
225 ((double) picHeader.time_inc) / ((double) pictureParam->time_increment_resolution)) * |
|
226 30.0 + 0.001); |
|
227 if (tryFrameNum > instance->frameNum) { |
|
228 currFrameNum = tryFrameNum; |
|
229 curr_mod_time_base += i; |
|
230 ret = DPH_OK; |
|
231 break; |
|
232 } |
|
233 } |
|
234 if (i==5) { |
|
235 ret = DPH_OK_BUT_BIT_ERROR; |
|
236 goto updateInstanceData; |
|
237 } |
|
238 } |
|
239 } |
|
240 |
|
241 /* If no INTRA frame has ever been decoded and the current frame is INTER */ |
|
242 if (!fPrevIntraGot && fInterFrame) { |
|
243 deb("ERROR. No I-vop before a P-vop\n"); |
|
244 return DPH_ERR_NO_INTRA; |
|
245 |
|
246 } |
|
247 |
|
248 /* fcode can have only the valid values 1..7 */ |
|
249 if(picHeader.fcode_forward == 0) { |
|
250 ret = DPH_OK_BUT_BIT_ERROR; |
|
251 goto updateInstanceData; |
|
252 } |
|
253 |
|
254 /* quant can not be zero */ |
|
255 if(picHeader.quant == 0) { |
|
256 ret = DPH_OK_BUT_BIT_ERROR; |
|
257 goto updateInstanceData; |
|
258 } |
|
259 |
|
260 } /* end fReadBits */ |
|
261 |
|
262 /* Now, the picture header is considered to be error-free, |
|
263 and its contents are used to manipulate instance data */ |
|
264 |
|
265 updateInstanceData: |
|
266 |
|
267 /* |
|
268 * Update instance data and output parameters |
|
269 */ |
|
270 |
|
271 /* some parameters need to be set if error has been detected, for initializing */ |
|
272 if (!inParam->fReadBits || (ret == DPH_OK_BUT_BIT_ERROR)) { |
|
273 picHeader.rounding_type = 0; |
|
274 picHeader.fcode_forward = 1; |
|
275 picHeader.coding_type = 1; |
|
276 } else { |
|
277 /* Update frame numbers */ |
|
278 pictureParam->time_base_incr = picHeader.time_base_incr; |
|
279 pictureParam->mod_time_base = curr_mod_time_base; |
|
280 pictureParam->time_inc = picHeader.time_inc; |
|
281 instance->frameNum = currFrameNum; |
|
282 } |
|
283 |
|
284 /* Update picture parameters */ |
|
285 pictureParam->trd = (instance->frameNum % 256) - pictureParam->tr; |
|
286 pictureParam->tr = instance->frameNum % 256; |
|
287 |
|
288 pictureParam->pictureType = picHeader.coding_type; |
|
289 |
|
290 if (!picHeader.vop_coded) { |
|
291 return DPH_OK_BUT_NOT_CODED; |
|
292 } |
|
293 |
|
294 /* NO reference picture selection */ |
|
295 outParam->trp = -1; |
|
296 |
|
297 /* No PB Frames allowed */ |
|
298 instance->frameNumForBFrame = -1; |
|
299 |
|
300 /* Note: If no INTRA has been got the function has already returned */ |
|
301 instance->fIntraGot = 1; |
|
302 |
|
303 pictureParam->intra_dc_vlc_thr = picHeader.intra_dc_vlc_thr; |
|
304 pictureParam->fcode_forward = picHeader.fcode_forward; |
|
305 |
|
306 outParam->pquant = picHeader.quant; |
|
307 |
|
308 /* Initialize for only 1 GOB */ |
|
309 pictureParam->numMBLinesInGOB = pictureParam->lumMemHeight / 16; |
|
310 pictureParam->numMBsInMBLine = pictureParam->lumMemWidth / 16; |
|
311 |
|
312 pictureParam->numGOBs = 1; |
|
313 pictureParam->fLastGOBSizeDifferent = 0; |
|
314 pictureParam->numMBsInGOB = |
|
315 pictureParam->numMBsInMBLine * pictureParam->numMBLinesInGOB; |
|
316 pictureParam->numMBsInLastGOB = pictureParam->numMBsInGOB; |
|
317 |
|
318 /* Rounding type */ |
|
319 pictureParam->rtype = picHeader.rounding_type; |
|
320 |
|
321 /* NO channel Multiplexing */ |
|
322 pictureParam->fSplitScreenIndicator = 0; |
|
323 pictureParam->fDocumentCameraIndicator = 0; |
|
324 pictureParam->fFullPictureFreezeRelease = 0; |
|
325 pictureParam->fPLUSPTYPE = 0; |
|
326 pictureParam->cpm = 0; |
|
327 |
|
328 /* All the Annexes are switched off */ |
|
329 pictureParam->fSAC = 0; |
|
330 pictureParam->fRPR = 0; |
|
331 pictureParam->fRRU = 0; |
|
332 pictureParam->fCustomSourceFormat = 0; |
|
333 pictureParam->fAIC = 0; |
|
334 pictureParam->fDF = 0; |
|
335 pictureParam->fSS = 0; |
|
336 pictureParam->fRPS = 0; |
|
337 pictureParam->fISD = 0; |
|
338 pictureParam->fAIV = 0; |
|
339 pictureParam->fMQ = 0; |
|
340 pictureParam->fUMVLimited = 0; |
|
341 |
|
342 /* Unrestricted MV allowed |
|
343 OBMC NOT allowed */ |
|
344 pictureParam->fUMV = 1; |
|
345 pictureParam->fAP = 0; |
|
346 pictureParam->fMVsOverPictureBoundaries = 1; |
|
347 |
|
348 /* Initialize motion vector count module */ |
|
349 mvcStart( &instance->mvcData, |
|
350 ((instance->pictureParam.lumMemWidth >>4 /*/ 16*/) - 1), |
|
351 pictureParam->lumWidth, |
|
352 pictureParam->lumHeight, &error); |
|
353 /* Note: This assumes that the memory for frame->mvcData is filled with 0 |
|
354 in the first time the function is called. |
|
355 (This is ensured by setting the instance data to zero when it is |
|
356 initialized in vdcOpen.) */ |
|
357 if (error) { |
|
358 deb("mvcStart failed.\n"); |
|
359 return DPH_ERR; |
|
360 } |
|
361 |
|
362 /* Initialize once to count parameters for the mvc module */ |
|
363 { |
|
364 int r_size, scale_factor; |
|
365 |
|
366 instance->mvcData.f_code = pictureParam->fcode_forward; |
|
367 r_size = pictureParam->fcode_forward - 1; |
|
368 scale_factor = (1 << r_size); |
|
369 instance->mvcData.range = 160 * scale_factor; |
|
370 } |
|
371 |
|
372 /* Start, initialize the Advanced Intra Coding module */ |
|
373 aicStart(&instance->aicData, pictureParam->numMBsInMBLine, &error); |
|
374 if (error) { |
|
375 deb("aicStart failed.\n"); |
|
376 return DPH_ERR; |
|
377 } |
|
378 |
|
379 /* Get image buffers */ |
|
380 { |
|
381 vdeIms_t *store = instance->imageStore; |
|
382 vdeImsItem_t *imsItem; |
|
383 vdeImb_t *imb; |
|
384 int width, height; |
|
385 |
|
386 vdeImsSetYUVNeed(store, inParam->fNeedDecodedFrame); |
|
387 |
|
388 if (vdeImsGetFree(store, instance->pictureParam.lumMemWidth, |
|
389 instance->pictureParam.lumMemHeight, |
|
390 &instance->currFrame) < 0) |
|
391 goto errGetFreeP; |
|
392 imsItem = instance->currFrame; |
|
393 |
|
394 if (vdeImsStoreItemToImageBuffer(imsItem, &imb) < 0) |
|
395 goto errAfterGetFreeP; |
|
396 |
|
397 if (vdeImbYUV(imb, &outParam->currYFrame, |
|
398 &outParam->currUFrame, &outParam->currVFrame, |
|
399 &width, &height) < 0) |
|
400 goto errAfterGetFreeP; |
|
401 } |
|
402 |
|
403 return ret; |
|
404 |
|
405 /* Error condition handling, |
|
406 release everything in reverse order */ |
|
407 errAfterGetFreeP: |
|
408 |
|
409 vdeImsPutFree(instance->imageStore, instance->currFrame); |
|
410 errGetFreeP: |
|
411 |
|
412 instance->currFrame = NULL; |
|
413 instance->bFrame = NULL; |
|
414 |
|
415 return DPH_ERR; |
|
416 } |
|
417 // End of File |
|