[cvs] / xvidcore / src / divx4.c Repository:
ViewVC logotype

Annotation of /xvidcore/src/divx4.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.9 - (view) (download)

1 : Isibaar 1.1 /**************************************************************************
2 :     *
3 :     * XVID MPEG-4 VIDEO CODEC
4 : edgomez 1.9 * OpenDivx API wrapper
5 : Isibaar 1.1 *
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 1.7 #include <stdlib.h>
43 : edgomez 1.9 #include <string.h>
44 : Isibaar 1.1
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 1.9 /**************************************************************************
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 1.1
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 1.9 /**************************************************************************
76 :     * Global data (needed to emulate correctly exported symbols from divx4)
77 :     *************************************************************************/
78 :    
79 :     /* This is not used in this module but is required by some divx4 encoders*/
80 :     int quiet_encore = 1;
81 :    
82 :     /**************************************************************************
83 :     * Local data
84 :     *************************************************************************/
85 :    
86 :     /* The Divx4 instance chainlist */
87 :     static DINST * dhead = NULL;
88 :    
89 :     /* Divx4 quality to XviD encoder motion flag presets */
90 :     static int const divx4_motion_presets[7] = {
91 :     0,
92 :    
93 :     PMV_QUICKSTOP16,
94 :    
95 :     PMV_EARLYSTOP16,
96 :    
97 :     PMV_EARLYSTOP16 | PMV_HALFPELREFINE16,
98 :    
99 :     PMV_EARLYSTOP16 | PMV_HALFPELREFINE16 |
100 :     PMV_EARLYSTOP8 | PMV_HALFPELDIAMOND8,
101 :    
102 :     PMV_EARLYSTOP16 | PMV_HALFPELREFINE16 |
103 :     PMV_EARLYSTOP8 | PMV_HALFPELDIAMOND8,
104 :    
105 :     PMV_EARLYSTOP16 | PMV_HALFPELREFINE16 |
106 :     PMV_EXTSEARCH16 | PMV_EARLYSTOP8 |
107 :     PMV_HALFPELREFINE8 | PMV_HALFPELDIAMOND8
108 :     };
109 :    
110 :    
111 :     /* 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 :    
122 :     /*
123 :     * Current divx4 encoder quality
124 :     * ToDo : this data should not be shared between encoder instances
125 :     */
126 :     static int quality;
127 :    
128 :     /**************************************************************************
129 :     * Local Prototypes
130 :     *************************************************************************/
131 :    
132 :     /* 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 :    
137 :     /* 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 :    
141 :     /**************************************************************************
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 :    
148 :     int
149 :     decore(unsigned long key, unsigned long opt, void * param1, void * param2)
150 :     {
151 :    
152 :     int xerr;
153 :    
154 :     switch (opt) {
155 :    
156 :     case DEC_OPT_MEMORY_REQS :
157 :     {
158 :     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 :     {
172 :     dcur = dinst_add(key);
173 :     }
174 :    
175 :     /*
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 :    
183 :     /* 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 :    
189 :     xerr = decoder_create(&xparam);
190 :    
191 :     /* Store the xvid handle into the divx4 instance chainlist */
192 :     dcur->handle = xparam.handle;
193 :    
194 :     break;
195 :     }
196 :    
197 :     case DEC_OPT_RELEASE :
198 :     {
199 :     DINST * dcur;
200 :    
201 :     /* Find the divx4 instance into the chain list */
202 :     if ((dcur = dinst_find(key)) == NULL)
203 :     {
204 :     return DEC_EXIT;
205 :     }
206 :    
207 :     /* Destroy the XviD decoder attached to this divx4 instance */
208 :     xerr = decoder_destroy(dcur->handle);
209 :    
210 :     /* Remove the divx4 instance from the chainlist */
211 :     dinst_remove(key);
212 :    
213 :     break;
214 :     }
215 :    
216 :     case DEC_OPT_SETPP :
217 :     {
218 :     DINST * dcur;
219 :    
220 :     /* Find the divx4 instance into the chain list */
221 :     if ((dcur = dinst_find(key)) == NULL)
222 :     {
223 :     return DEC_EXIT;
224 :     }
225 :    
226 :     /*
227 :     * We return DEC_OK but XviD has no postprocessing implemented
228 :     * in core.
229 :     */
230 :     return DEC_OK;
231 :     }
232 :    
233 :     case DEC_OPT_SETOUT :
234 :     {
235 :     DINST * dcur;
236 :     DEC_PARAM * dparam = (DEC_PARAM *)param1;
237 :    
238 :     if ((dcur = dinst_find(key)) == NULL)
239 :     {
240 :     return DEC_EXIT;
241 :     }
242 :    
243 :     /* Change the output colorspace */
244 :     dcur->xframe.colorspace =
245 :     xvid_to_opendivx_dec_csp(dparam->output_format);
246 :    
247 :     return DEC_OK;
248 :     }
249 : Isibaar 1.1
250 : edgomez 1.9 case DEC_OPT_FRAME:
251 :     {
252 :     int csp_tmp = 0;
253 :     DINST * dcur;
254 :     DEC_FRAME * dframe = (DEC_FRAME *)param1;
255 :    
256 :     if ((dcur = dinst_find(key)) == NULL)
257 :     {
258 :     return DEC_EXIT;
259 :     }
260 :    
261 :     /* 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 :    
267 :     /* 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 :    
279 :     /* Decode the bitstream */
280 :     xerr = decoder_decode(dcur->handle, &dcur->xframe);
281 :    
282 :     /* Restore the real colorspace for this instance */
283 :     if (!dframe->render_flag)
284 :     {
285 :     dcur->xframe.colorspace = csp_tmp;
286 :     }
287 :    
288 :     break;
289 :     }
290 :    
291 :     case DEC_OPT_FRAME_311 :
292 :     /* XviD does not handle Divx ;-) 3.11 yet */
293 :     return DEC_EXIT;
294 :    
295 :     case DEC_OPT_VERSION:
296 :     return EMULATED_DIVX_VERSION;
297 :    
298 :     default :
299 :     return DEC_EXIT;
300 :     }
301 :    
302 :    
303 :     /* XviD error code -> Divx4 */
304 :     switch(xerr)
305 :     {
306 :     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 :     return DEC_EXIT;
314 :     }
315 :     }
316 :    
317 :     /**************************************************************************
318 :     * Encore Part
319 :     *
320 :     * encore is the divx4 entry point used to compress a frame to a mpeg4
321 :     * bitstream.
322 :     *************************************************************************/
323 :    
324 :     #define FRAMERATE_INCR 1001
325 :    
326 :     int
327 :     encore(void * handle, int opt, void * param1, void * param2)
328 :     {
329 :    
330 :     int xerr;
331 :    
332 :     switch(opt) {
333 :     case ENC_OPT_INIT :
334 :     {
335 :     ENC_PARAM * eparam = (ENC_PARAM *)param1;
336 :     XVID_INIT_PARAM xinit;
337 :     XVID_ENC_PARAM xparam;
338 :    
339 :     /* Init XviD which will detect host cpu features */
340 :     xinit.cpu_flags = 0;
341 :     xvid_init(NULL, 0, &xinit, NULL);
342 :    
343 :     /* 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 :    
365 :     /* Create the encoder session */
366 :     xerr = encoder_create(&xparam);
367 :    
368 :     eparam->handle = xparam.handle;
369 :    
370 :     break;
371 :     }
372 :    
373 :     case ENC_OPT_RELEASE :
374 :     {
375 :     xerr = encoder_destroy((Encoder *) handle);
376 :     break;
377 :     }
378 :    
379 :     case ENC_OPT_ENCODE :
380 :     case ENC_OPT_ENCODE_VBR :
381 :     {
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 :    
387 :     /* Copy the divx4 info into the xvid structure */
388 :     xframe.bitstream = eframe->bitstream;
389 :     xframe.length = eframe->length;
390 :    
391 :     xframe.motion = divx4_motion_presets[quality];
392 :     xframe.general = divx4_general_presets[quality];
393 :    
394 :     xframe.image = eframe->image;
395 :     xframe.colorspace =
396 :     xvid_to_opendivx_enc_csp(eframe->colorspace);
397 :    
398 :     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 :    
409 :     /* Encode the frame */
410 :     xerr = encoder_encode((Encoder *) handle, &xframe, (eresult ? &xstats : NULL) );
411 :    
412 :     /* 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 :    
422 :     eframe->length = xframe.length;
423 :    
424 :     break;
425 :     }
426 :    
427 :     default:
428 :     return ENC_FAIL;
429 :     }
430 :    
431 :     /* XviD Error code -> Divx4 error code */
432 :     switch(xerr)
433 :     {
434 :     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 :     return ENC_FAIL;
442 :     }
443 :     }
444 :    
445 :     /**************************************************************************
446 :     * Local Functions
447 :     *************************************************************************/
448 : Isibaar 1.1
449 : edgomez 1.9 /***************************************
450 :     * DINST chainlist helper functions *
451 :     ***************************************/
452 : Isibaar 1.1
453 : edgomez 1.9 /* Find an element in the chainlist according to its key value */
454 :     static DINST * dinst_find(unsigned long key)
455 : Isibaar 1.1 {
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 : edgomez 1.9 /* Add an element to the chainlist */
472 :     static DINST * dinst_add(unsigned long key)
473 : Isibaar 1.1 {
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 : edgomez 1.9 /* Remove an elmement from the chainlist */
491 :     static void dinst_remove(unsigned long key)
492 : Isibaar 1.1 {
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 : edgomez 1.9 /***************************************
521 :     * Colorspace code converter *
522 :     ***************************************/
523 : Isibaar 1.1
524 : edgomez 1.9 static int xvid_to_opendivx_dec_csp(int csp)
525 : Isibaar 1.1 {
526 : edgomez 1.9
527 : Isibaar 1.1 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 : edgomez 1.9 static int xvid_to_opendivx_enc_csp(int csp)
561 : Isibaar 1.1 {
562 :    
563 : edgomez 1.9 switch (csp)
564 : Isibaar 1.1 {
565 : edgomez 1.9 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 : Isibaar 1.1 default :
576 : edgomez 1.9 return -1;
577 : Isibaar 1.1 }
578 :     }

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