[svn] / branches / Isibaar / xvidcore / src / divx4.c Repository:
ViewVC logotype

Annotation of /branches/Isibaar/xvidcore/src/divx4.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 143 - (view) (download)
Original Path: trunk/xvidcore/src/divx4.c

1 : Isibaar 3 /**************************************************************************
2 :     *
3 :     * XVID MPEG-4 VIDEO CODEC
4 : edgomez 143 * OpenDivx API wrapper
5 : Isibaar 3 *
6 :     * This program is an implementation of a part of one or more MPEG-4
7 :     * Video tools as specified in ISO/IEC 14496-2 standard. Those intending
8 :     * to use this software module in hardware or software products are
9 :     * advised that its use may infringe existing patents or copyrights, and
10 :     * any such use would be at such party's own risk. The original
11 :     * developer of this software module and his/her company, and subsequent
12 :     * editors and their companies, will have no liability for use of this
13 :     * software or modifications or derivatives thereof.
14 :     *
15 :     * This program is free software; you can redistribute it and/or modify
16 :     * it under the terms of the GNU General Public License as published by
17 :     * the Free Software Foundation; either version 2 of the License, or
18 :     * (at your option) any later version.
19 :     *
20 :     * This program is distributed in the hope that it will be useful,
21 :     * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 :     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 :     * GNU General Public License for more details.
24 :     *
25 :     * You should have received a copy of the GNU General Public License
26 :     * along with this program; if not, write to the Free Software
27 :     * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
28 :     *
29 :     *************************************************************************/
30 :    
31 :     /**************************************************************************
32 :     *
33 :     * History:
34 :     *
35 :     * 26.02.2001 fixed dec_csp bugs
36 :     * 26.12.2001 xvid_init() support
37 :     * 22.12.2001 removed some compiler warnings
38 :     * 16.12.2001 inital version; (c)2001 peter ross <pross@cs.rmit.edu.au>
39 :     *
40 :     *************************************************************************/
41 :    
42 : knhor 129 #include <stdlib.h>
43 : edgomez 143 #include <string.h>
44 : Isibaar 3
45 :     #include "xvid.h"
46 :     #include "divx4.h"
47 :     #include "decoder.h"
48 :     #include "encoder.h"
49 :    
50 :     #define EMULATED_DIVX_VERSION 20011001
51 :    
52 : edgomez 143 /**************************************************************************
53 :     * Divx Instance Structure
54 :     *
55 :     * This chain list datatype allows XviD do instanciate multiples divx4
56 :     * sessions.
57 :     *
58 :     * ToDo : The way this chain list is used does not guarantee reentrance
59 :     * because they are not protected by any kind of mutex to allow
60 :     * only one modifier. We should add a mutex for each element in
61 :     * the chainlist.
62 :     *************************************************************************/
63 : Isibaar 3
64 :    
65 :     typedef struct DINST
66 :     {
67 :     unsigned long key;
68 :     struct DINST * next;
69 :    
70 :     void * handle;
71 :     XVID_DEC_FRAME xframe;
72 :    
73 :     } DINST;
74 :    
75 : edgomez 143 /**************************************************************************
76 :     * Global data (needed to emulate correctly exported symbols from divx4)
77 :     *************************************************************************/
78 : Isibaar 3
79 : edgomez 143 /* This is not used in this module but is required by some divx4 encoders*/
80 :     int quiet_encore = 1;
81 : Isibaar 3
82 : edgomez 143 /**************************************************************************
83 :     * Local data
84 :     *************************************************************************/
85 : Isibaar 3
86 : edgomez 143 /* The Divx4 instance chainlist */
87 :     static DINST * dhead = NULL;
88 : Isibaar 3
89 : edgomez 143 /* Divx4 quality to XviD encoder motion flag presets */
90 :     static int const divx4_motion_presets[7] = {
91 :     0,
92 : Isibaar 3
93 : edgomez 143 PMV_QUICKSTOP16,
94 : Isibaar 3
95 : edgomez 143 PMV_EARLYSTOP16,
96 : Isibaar 3
97 : edgomez 143 PMV_EARLYSTOP16 | PMV_HALFPELREFINE16,
98 : Isibaar 3
99 : edgomez 143 PMV_EARLYSTOP16 | PMV_HALFPELREFINE16 |
100 :     PMV_EARLYSTOP8 | PMV_HALFPELDIAMOND8,
101 : Isibaar 3
102 : edgomez 143 PMV_EARLYSTOP16 | PMV_HALFPELREFINE16 |
103 :     PMV_EARLYSTOP8 | PMV_HALFPELDIAMOND8,
104 : Isibaar 3
105 : edgomez 143 PMV_EARLYSTOP16 | PMV_HALFPELREFINE16 |
106 :     PMV_EXTSEARCH16 | PMV_EARLYSTOP8 |
107 :     PMV_HALFPELREFINE8 | PMV_HALFPELDIAMOND8
108 :     };
109 : Isibaar 3
110 :    
111 : edgomez 143 /* Divx4 quality to general encoder flag presets */
112 :     static int const divx4_general_presets[7] = {
113 :     0,
114 :     XVID_H263QUANT,
115 :     XVID_H263QUANT,
116 :     XVID_H263QUANT | XVID_HALFPEL,
117 :     XVID_H263QUANT | XVID_INTER4V | XVID_HALFPEL,
118 :     XVID_H263QUANT | XVID_INTER4V | XVID_HALFPEL,
119 :     XVID_H263QUANT | XVID_INTER4V | XVID_HALFPEL
120 :     };
121 : Isibaar 3
122 : edgomez 143 /*
123 :     * Current divx4 encoder quality
124 :     * ToDo : this data should not be shared between encoder instances
125 :     */
126 :     static int quality;
127 : Isibaar 3
128 : edgomez 143 /**************************************************************************
129 :     * Local Prototypes
130 :     *************************************************************************/
131 : Isibaar 3
132 : edgomez 143 /* Chain list helper functions */
133 :     static DINST * dinst_find(unsigned long key);
134 :     static DINST * dinst_add(unsigned long key);
135 :     static void dinst_remove(unsigned long key);
136 : Isibaar 3
137 : edgomez 143 /* Converts divx4 colorspaces codes to xvid codes */
138 :     static int xvid_to_opendivx_dec_csp(int csp);
139 :     static int xvid_to_opendivx_enc_csp(int csp);
140 : Isibaar 3
141 : edgomez 143 /**************************************************************************
142 :     * decore part
143 :     *
144 :     * decore is the divx4 entry point used to decompress the mpeg4 bitstream
145 :     * into a user defined image format.
146 :     *************************************************************************/
147 : Isibaar 3
148 : edgomez 143 int
149 :     decore(unsigned long key, unsigned long opt, void * param1, void * param2)
150 : Isibaar 3 {
151 : edgomez 143
152 : Isibaar 3 int xerr;
153 :    
154 : edgomez 143 switch (opt) {
155 :    
156 :     case DEC_OPT_MEMORY_REQS :
157 : Isibaar 3 {
158 : edgomez 143 memset(param2, 0, sizeof(DEC_MEM_REQS));
159 :     return DEC_OK;
160 :     }
161 :    
162 :     case DEC_OPT_INIT :
163 :     {
164 :     XVID_INIT_PARAM xinit;
165 :     XVID_DEC_PARAM xparam;
166 :     DINST * dcur;
167 :     DEC_PARAM * dparam = (DEC_PARAM *)param1;
168 :    
169 :     /* Find the divx4 instance */
170 :     if ((dcur = dinst_find(key)) == NULL)
171 : Isibaar 3 {
172 : edgomez 143 dcur = dinst_add(key);
173 : Isibaar 3 }
174 :    
175 : edgomez 143 /*
176 :     * XviD initialization
177 :     * XviD will detect the host cpu type and activate optimized
178 :     * functions according to the host cpu features.
179 :     */
180 :     xinit.cpu_flags = 0;
181 :     xvid_init(NULL, 0, &xinit, NULL);
182 : Isibaar 3
183 : edgomez 143 /* XviD decoder initialization for this instance */
184 :     xparam.width = dparam->x_dim;
185 :     xparam.height = dparam->y_dim;
186 :     dcur->xframe.colorspace =
187 :     xvid_to_opendivx_dec_csp(dparam->output_format);
188 : Isibaar 3
189 : edgomez 143 xerr = decoder_create(&xparam);
190 : Isibaar 3
191 : edgomez 143 /* Store the xvid handle into the divx4 instance chainlist */
192 :     dcur->handle = xparam.handle;
193 : Isibaar 3
194 : edgomez 143 break;
195 :     }
196 : Isibaar 3
197 :     case DEC_OPT_RELEASE :
198 : edgomez 143 {
199 :     DINST * dcur;
200 :    
201 :     /* Find the divx4 instance into the chain list */
202 :     if ((dcur = dinst_find(key)) == NULL)
203 : Isibaar 3 {
204 : edgomez 143 return DEC_EXIT;
205 :     }
206 : Isibaar 3
207 : edgomez 143 /* Destroy the XviD decoder attached to this divx4 instance */
208 :     xerr = decoder_destroy(dcur->handle);
209 : Isibaar 3
210 : edgomez 143 /* Remove the divx4 instance from the chainlist */
211 :     dinst_remove(key);
212 : Isibaar 3
213 : edgomez 143 break;
214 :     }
215 : Isibaar 3
216 :     case DEC_OPT_SETPP :
217 : edgomez 143 {
218 :     DINST * dcur;
219 :    
220 :     /* Find the divx4 instance into the chain list */
221 :     if ((dcur = dinst_find(key)) == NULL)
222 : Isibaar 3 {
223 : edgomez 143 return DEC_EXIT;
224 :     }
225 : Isibaar 3
226 : edgomez 143 /*
227 :     * We return DEC_OK but XviD has no postprocessing implemented
228 :     * in core.
229 :     */
230 :     return DEC_OK;
231 :     }
232 : Isibaar 3
233 : edgomez 143 case DEC_OPT_SETOUT :
234 :     {
235 :     DINST * dcur;
236 :     DEC_PARAM * dparam = (DEC_PARAM *)param1;
237 : Isibaar 3
238 : edgomez 143 if ((dcur = dinst_find(key)) == NULL)
239 : Isibaar 3 {
240 : edgomez 143 return DEC_EXIT;
241 :     }
242 : Isibaar 3
243 : edgomez 143 /* Change the output colorspace */
244 :     dcur->xframe.colorspace =
245 :     xvid_to_opendivx_dec_csp(dparam->output_format);
246 : Isibaar 3
247 : edgomez 143 return DEC_OK;
248 :     }
249 : Isibaar 3
250 :     case DEC_OPT_FRAME:
251 : edgomez 143 {
252 :     int csp_tmp = 0;
253 :     DINST * dcur;
254 :     DEC_FRAME * dframe = (DEC_FRAME *)param1;
255 :    
256 :     if ((dcur = dinst_find(key)) == NULL)
257 : Isibaar 3 {
258 : edgomez 143 return DEC_EXIT;
259 :     }
260 : edgomez 19
261 : edgomez 143 /* Copy the divx4 fields to the XviD decoder structure */
262 :     dcur->xframe.bitstream = dframe->bitstream;
263 :     dcur->xframe.length = dframe->length;
264 :     dcur->xframe.image = dframe->bmp;
265 :     dcur->xframe.stride = dframe->stride;
266 : Isibaar 3
267 : edgomez 143 /* Does the frame need to be skipped ? */
268 :     if (!dframe->render_flag)
269 :     {
270 :     /*
271 :     * Then we use the null colorspace to force XviD to
272 :     * skip the frame. The original colorspace will be
273 :     * restored after the decoder call
274 :     */
275 :     csp_tmp = dcur->xframe.colorspace;
276 :     dcur->xframe.colorspace = XVID_CSP_NULL;
277 :     }
278 : Isibaar 3
279 : edgomez 143 /* Decode the bitstream */
280 :     xerr = decoder_decode(dcur->handle, &dcur->xframe);
281 : Isibaar 3
282 : edgomez 143 /* Restore the real colorspace for this instance */
283 :     if (!dframe->render_flag)
284 :     {
285 :     dcur->xframe.colorspace = csp_tmp;
286 : Isibaar 3 }
287 :    
288 : edgomez 143 break;
289 :     }
290 : Isibaar 3
291 :     case DEC_OPT_FRAME_311 :
292 : edgomez 143 /* XviD does not handle Divx ;-) 3.11 yet */
293 : Isibaar 3 return DEC_EXIT;
294 :    
295 :     case DEC_OPT_VERSION:
296 :     return EMULATED_DIVX_VERSION;
297 : edgomez 143
298 : Isibaar 3 default :
299 :     return DEC_EXIT;
300 :     }
301 :    
302 :    
303 : edgomez 143 /* XviD error code -> Divx4 */
304 : Isibaar 3 switch(xerr)
305 :     {
306 : edgomez 143 case XVID_ERR_OK :
307 :     return DEC_OK;
308 :     case XVID_ERR_MEMORY :
309 :     return DEC_MEMORY;
310 :     case XVID_ERR_FORMAT :
311 :     return DEC_BAD_FORMAT;
312 :     default :
313 : Isibaar 3 return DEC_EXIT;
314 :     }
315 :     }
316 :    
317 : edgomez 143 /**************************************************************************
318 :     * Encore Part
319 :     *
320 :     * encore is the divx4 entry point used to compress a frame to a mpeg4
321 :     * bitstream.
322 :     *************************************************************************/
323 : Isibaar 3
324 :     #define FRAMERATE_INCR 1001
325 :    
326 : edgomez 143 int
327 :     encore(void * handle, int opt, void * param1, void * param2)
328 :     {
329 : Isibaar 9
330 : Isibaar 3 int xerr;
331 :    
332 : edgomez 143 switch(opt) {
333 :     case ENC_OPT_INIT :
334 : Isibaar 3 {
335 : edgomez 143 ENC_PARAM * eparam = (ENC_PARAM *)param1;
336 :     XVID_INIT_PARAM xinit;
337 :     XVID_ENC_PARAM xparam;
338 : Isibaar 3
339 : edgomez 143 /* Init XviD which will detect host cpu features */
340 :     xinit.cpu_flags = 0;
341 :     xvid_init(NULL, 0, &xinit, NULL);
342 : Isibaar 3
343 : edgomez 143 /* Settings are copied to the XviD encoder structure */
344 :     xparam.width = eparam->x_dim;
345 :     xparam.height = eparam->y_dim;
346 :     if ((eparam->framerate - (int)eparam->framerate) == 0)
347 :     {
348 :     xparam.fincr = 1;
349 :     xparam.fbase = (int)eparam->framerate;
350 :     }
351 :     else
352 :     {
353 :     xparam.fincr = FRAMERATE_INCR;
354 :     xparam.fbase = (int)(FRAMERATE_INCR * eparam->framerate);
355 :     }
356 :     xparam.rc_bitrate = eparam->bitrate;
357 :     xparam.rc_reaction_delay_factor = 16;
358 :     xparam.rc_averaging_period = 100;
359 :     xparam.rc_buffer = 100;
360 :     xparam.min_quantizer = eparam->min_quantizer;
361 :     xparam.max_quantizer = eparam->max_quantizer;
362 :     xparam.max_key_interval = eparam->max_key_interval;
363 :     quality = eparam->quality;
364 : Isibaar 3
365 : edgomez 143 /* Create the encoder session */
366 :     xerr = encoder_create(&xparam);
367 : Isibaar 3
368 : edgomez 143 eparam->handle = xparam.handle;
369 : Isibaar 3
370 : edgomez 143 break;
371 :     }
372 : Isibaar 3
373 :     case ENC_OPT_RELEASE :
374 : edgomez 143 {
375 :     xerr = encoder_destroy((Encoder *) handle);
376 :     break;
377 :     }
378 : Isibaar 3
379 :     case ENC_OPT_ENCODE :
380 :     case ENC_OPT_ENCODE_VBR :
381 : edgomez 143 {
382 :     ENC_FRAME * eframe = (ENC_FRAME *)param1;
383 :     ENC_RESULT * eresult = (ENC_RESULT *)param2;
384 :     XVID_ENC_FRAME xframe;
385 :     XVID_ENC_STATS xstats;
386 : Isibaar 3
387 : edgomez 143 /* Copy the divx4 info into the xvid structure */
388 :     xframe.bitstream = eframe->bitstream;
389 :     xframe.length = eframe->length;
390 : Isibaar 3
391 : edgomez 143 xframe.motion = divx4_motion_presets[quality];
392 :     xframe.general = divx4_general_presets[quality];
393 : Isibaar 9
394 : edgomez 143 xframe.image = eframe->image;
395 :     xframe.colorspace =
396 :     xvid_to_opendivx_enc_csp(eframe->colorspace);
397 : Isibaar 3
398 : edgomez 143 if (opt == ENC_OPT_ENCODE_VBR)
399 :     {
400 :     xframe.intra = eframe->intra;
401 :     xframe.quant = eframe->quant;
402 :     }
403 :     else
404 :     {
405 :     xframe.intra = -1;
406 :     xframe.quant = 0;
407 :     }
408 : Isibaar 3
409 : edgomez 143 /* Encode the frame */
410 :     xerr = encoder_encode((Encoder *) handle, &xframe, (eresult ? &xstats : NULL) );
411 : Isibaar 3
412 : edgomez 143 /* Copy back the xvid structure to the divx4 one */
413 :     if (eresult)
414 :     {
415 :     eresult->is_key_frame = xframe.intra;
416 :     eresult->quantizer = xstats.quant;
417 :     eresult->total_bits = xframe.length * 8;
418 :     eresult->motion_bits = xstats.hlength * 8;
419 :     eresult->texture_bits = eresult->total_bits - eresult->motion_bits;
420 :     }
421 : Isibaar 3
422 : edgomez 143 eframe->length = xframe.length;
423 : Isibaar 3
424 : edgomez 143 break;
425 :     }
426 : Isibaar 3
427 :     default:
428 :     return ENC_FAIL;
429 :     }
430 :    
431 : edgomez 143 /* XviD Error code -> Divx4 error code */
432 : Isibaar 3 switch(xerr)
433 :     {
434 : edgomez 143 case XVID_ERR_OK :
435 :     return ENC_OK;
436 :     case XVID_ERR_MEMORY :
437 :     return ENC_MEMORY;
438 :     case XVID_ERR_FORMAT :
439 :     return ENC_BAD_FORMAT;
440 :     default :
441 : Isibaar 3 return ENC_FAIL;
442 :     }
443 :     }
444 :    
445 : edgomez 143 /**************************************************************************
446 :     * Local Functions
447 :     *************************************************************************/
448 :    
449 :     /***************************************
450 :     * DINST chainlist helper functions *
451 :     ***************************************/
452 :    
453 :     /* Find an element in the chainlist according to its key value */
454 :     static DINST * dinst_find(unsigned long key)
455 :     {
456 :     DINST * dcur = dhead;
457 :    
458 :     while (dcur)
459 :     {
460 :     if (dcur->key == key)
461 :     {
462 :     return dcur;
463 :     }
464 :     dcur = dcur->next;
465 :     }
466 :    
467 :     return NULL;
468 :     }
469 :    
470 :    
471 :     /* Add an element to the chainlist */
472 :     static DINST * dinst_add(unsigned long key)
473 :     {
474 :     DINST * dnext = dhead;
475 :    
476 :     dhead = malloc(sizeof(DINST));
477 :     if (dhead == NULL)
478 :     {
479 :     dhead = dnext;
480 :     return NULL;
481 :     }
482 :    
483 :     dhead->key = key;
484 :     dhead->next = dnext;
485 :    
486 :     return dhead;
487 :     }
488 :    
489 :    
490 :     /* Remove an elmement from the chainlist */
491 :     static void dinst_remove(unsigned long key)
492 :     {
493 :     DINST * dcur = dhead;
494 :    
495 :     if (dhead == NULL)
496 :     {
497 :     return;
498 :     }
499 :    
500 :     if (dcur->key == key)
501 :     {
502 :     dhead = dcur->next;
503 :     free(dcur);
504 :     return;
505 :     }
506 :    
507 :     while (dcur->next)
508 :     {
509 :     if (dcur->next->key == key)
510 :     {
511 :     DINST * tmp = dcur->next;
512 :     dcur->next = tmp->next;
513 :     free(tmp);
514 :     return;
515 :     }
516 :     dcur = dcur->next;
517 :     }
518 :     }
519 :    
520 :     /***************************************
521 :     * Colorspace code converter *
522 :     ***************************************/
523 :    
524 :     static int xvid_to_opendivx_dec_csp(int csp)
525 :     {
526 :    
527 :     switch(csp)
528 :     {
529 :     case DEC_YV12 :
530 :     return XVID_CSP_YV12;
531 :     case DEC_420 :
532 :     return XVID_CSP_I420;
533 :     case DEC_YUY2 :
534 :     return XVID_CSP_YUY2;
535 :     case DEC_UYVY :
536 :     return XVID_CSP_UYVY;
537 :     case DEC_RGB32 :
538 :     return XVID_CSP_VFLIP | XVID_CSP_RGB32;
539 :     case DEC_RGB24 :
540 :     return XVID_CSP_VFLIP | XVID_CSP_RGB24;
541 :     case DEC_RGB565 :
542 :     return XVID_CSP_VFLIP | XVID_CSP_RGB565;
543 :     case DEC_RGB555 :
544 :     return XVID_CSP_VFLIP | XVID_CSP_RGB555;
545 :     case DEC_RGB32_INV :
546 :     return XVID_CSP_RGB32;
547 :     case DEC_RGB24_INV :
548 :     return XVID_CSP_RGB24;
549 :     case DEC_RGB565_INV :
550 :     return XVID_CSP_RGB565;
551 :     case DEC_RGB555_INV :
552 :     return XVID_CSP_RGB555;
553 :     case DEC_USER :
554 :     return XVID_CSP_USER;
555 :     default :
556 :     return -1;
557 :     }
558 :     }
559 :    
560 :     static int xvid_to_opendivx_enc_csp(int csp)
561 :     {
562 :    
563 :     switch (csp)
564 :     {
565 :     case ENC_CSP_RGB24 :
566 :     return XVID_CSP_VFLIP | XVID_CSP_RGB24;
567 :     case ENC_CSP_YV12 :
568 :     return XVID_CSP_YV12;
569 :     case ENC_CSP_YUY2 :
570 :     return XVID_CSP_YUY2;
571 :     case ENC_CSP_UYVY :
572 :     return XVID_CSP_UYVY;
573 :     case ENC_CSP_I420 :
574 :     return XVID_CSP_I420;
575 :     default :
576 :     return -1;
577 :     }
578 :     }

No admin address has been configured
ViewVC Help
Powered by ViewVC 1.0.4