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

Annotation of /xvidcore/src/divx4.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.11 - (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 : edgomez 1.11 * 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 : Isibaar 1.1 *
40 : edgomez 1.11 * $Id: divx4.c,v 1.10 2002/04/28 20:03:14 edgomez Exp $
41 : edgomez 1.10 *
42 : Isibaar 1.1 *************************************************************************/
43 :    
44 : knhor 1.7 #include <stdlib.h>
45 : edgomez 1.9 #include <string.h>
46 : edgomez 1.11 #include <stdio.h>
47 : Isibaar 1.1
48 :     #include "xvid.h"
49 :     #include "divx4.h"
50 :     #include "decoder.h"
51 :     #include "encoder.h"
52 :    
53 :     #define EMULATED_DIVX_VERSION 20011001
54 :    
55 : edgomez 1.9 /**************************************************************************
56 :     * Divx Instance Structure
57 :     *
58 :     * This chain list datatype allows XviD do instanciate multiples divx4
59 :     * sessions.
60 :     *
61 :     * ToDo : The way this chain list is used does not guarantee reentrance
62 :     * because they are not protected by any kind of mutex to allow
63 :     * only one modifier. We should add a mutex for each element in
64 :     * the chainlist.
65 :     *************************************************************************/
66 : Isibaar 1.1
67 :    
68 :     typedef struct DINST
69 :     {
70 :     unsigned long key;
71 :     struct DINST * next;
72 :    
73 :     void * handle;
74 :     XVID_DEC_FRAME xframe;
75 :    
76 :     } DINST;
77 :    
78 : edgomez 1.11 typedef struct EINST
79 :     {
80 :     struct EINST * next;
81 :    
82 :     void * handle;
83 :     int quality;
84 :    
85 :     } EINST;
86 :    
87 : edgomez 1.9 /**************************************************************************
88 :     * Global data (needed to emulate correctly exported symbols from divx4)
89 :     *************************************************************************/
90 :    
91 :     /* This is not used in this module but is required by some divx4 encoders*/
92 :     int quiet_encore = 1;
93 :    
94 :     /**************************************************************************
95 :     * Local data
96 :     *************************************************************************/
97 :    
98 :     /* The Divx4 instance chainlist */
99 :     static DINST * dhead = NULL;
100 : edgomez 1.11 static EINST * ehead = NULL;
101 : edgomez 1.9
102 :     /* Divx4 quality to XviD encoder motion flag presets */
103 :     static int const divx4_motion_presets[7] = {
104 :     0,
105 :    
106 :     PMV_QUICKSTOP16,
107 :    
108 :     PMV_EARLYSTOP16,
109 :    
110 :     PMV_EARLYSTOP16 | PMV_HALFPELREFINE16,
111 :    
112 :     PMV_EARLYSTOP16 | PMV_HALFPELREFINE16 |
113 :     PMV_EARLYSTOP8 | PMV_HALFPELDIAMOND8,
114 :    
115 :     PMV_EARLYSTOP16 | PMV_HALFPELREFINE16 |
116 :     PMV_EARLYSTOP8 | PMV_HALFPELDIAMOND8,
117 :    
118 :     PMV_EARLYSTOP16 | PMV_HALFPELREFINE16 |
119 :     PMV_EXTSEARCH16 | PMV_EARLYSTOP8 |
120 :     PMV_HALFPELREFINE8 | PMV_HALFPELDIAMOND8
121 :     };
122 :    
123 :    
124 :     /* Divx4 quality to general encoder flag presets */
125 :     static int const divx4_general_presets[7] = {
126 :     0,
127 :     XVID_H263QUANT,
128 :     XVID_H263QUANT,
129 :     XVID_H263QUANT | XVID_HALFPEL,
130 :     XVID_H263QUANT | XVID_INTER4V | XVID_HALFPEL,
131 :     XVID_H263QUANT | XVID_INTER4V | XVID_HALFPEL,
132 :     XVID_H263QUANT | XVID_INTER4V | XVID_HALFPEL
133 :     };
134 :    
135 :     /**************************************************************************
136 :     * Local Prototypes
137 :     *************************************************************************/
138 :    
139 :     /* Chain list helper functions */
140 :     static DINST * dinst_find(unsigned long key);
141 :     static DINST * dinst_add(unsigned long key);
142 :     static void dinst_remove(unsigned long key);
143 :    
144 : edgomez 1.11 static EINST * einst_find(void *handle);
145 :     static EINST * einst_add(void *handle);
146 :     static void einst_remove(void *handle);
147 :    
148 : edgomez 1.9 /* Converts divx4 colorspaces codes to xvid codes */
149 :     static int xvid_to_opendivx_dec_csp(int csp);
150 :     static int xvid_to_opendivx_enc_csp(int csp);
151 :    
152 :     /**************************************************************************
153 :     * decore part
154 :     *
155 :     * decore is the divx4 entry point used to decompress the mpeg4 bitstream
156 :     * into a user defined image format.
157 :     *************************************************************************/
158 :    
159 :     int
160 :     decore(unsigned long key, unsigned long opt, void * param1, void * param2)
161 :     {
162 :    
163 :     int xerr;
164 :    
165 :     switch (opt) {
166 :    
167 :     case DEC_OPT_MEMORY_REQS :
168 :     {
169 :     memset(param2, 0, sizeof(DEC_MEM_REQS));
170 :     return DEC_OK;
171 :     }
172 :    
173 :     case DEC_OPT_INIT :
174 :     {
175 :     XVID_INIT_PARAM xinit;
176 :     XVID_DEC_PARAM xparam;
177 :     DINST * dcur;
178 :     DEC_PARAM * dparam = (DEC_PARAM *)param1;
179 :    
180 :     /* Find the divx4 instance */
181 :     if ((dcur = dinst_find(key)) == NULL)
182 :     {
183 :     dcur = dinst_add(key);
184 :     }
185 :    
186 :     /*
187 :     * XviD initialization
188 :     * XviD will detect the host cpu type and activate optimized
189 :     * functions according to the host cpu features.
190 :     */
191 :     xinit.cpu_flags = 0;
192 :     xvid_init(NULL, 0, &xinit, NULL);
193 :    
194 :     /* XviD decoder initialization for this instance */
195 :     xparam.width = dparam->x_dim;
196 :     xparam.height = dparam->y_dim;
197 :     dcur->xframe.colorspace =
198 :     xvid_to_opendivx_dec_csp(dparam->output_format);
199 :    
200 :     xerr = decoder_create(&xparam);
201 :    
202 :     /* Store the xvid handle into the divx4 instance chainlist */
203 :     dcur->handle = xparam.handle;
204 :    
205 :     break;
206 :     }
207 :    
208 :     case DEC_OPT_RELEASE :
209 :     {
210 :     DINST * dcur;
211 :    
212 :     /* Find the divx4 instance into the chain list */
213 :     if ((dcur = dinst_find(key)) == NULL)
214 :     {
215 :     return DEC_EXIT;
216 :     }
217 :    
218 :     /* Destroy the XviD decoder attached to this divx4 instance */
219 :     xerr = decoder_destroy(dcur->handle);
220 :    
221 :     /* Remove the divx4 instance from the chainlist */
222 :     dinst_remove(key);
223 :    
224 :     break;
225 :     }
226 :    
227 :     case DEC_OPT_SETPP :
228 :     {
229 :     DINST * dcur;
230 :    
231 :     /* Find the divx4 instance into the chain list */
232 :     if ((dcur = dinst_find(key)) == NULL)
233 :     {
234 :     return DEC_EXIT;
235 :     }
236 :    
237 :     /*
238 :     * We return DEC_OK but XviD has no postprocessing implemented
239 :     * in core.
240 :     */
241 :     return DEC_OK;
242 :     }
243 :    
244 :     case DEC_OPT_SETOUT :
245 :     {
246 :     DINST * dcur;
247 :     DEC_PARAM * dparam = (DEC_PARAM *)param1;
248 :    
249 :     if ((dcur = dinst_find(key)) == NULL)
250 :     {
251 :     return DEC_EXIT;
252 :     }
253 :    
254 :     /* Change the output colorspace */
255 :     dcur->xframe.colorspace =
256 :     xvid_to_opendivx_dec_csp(dparam->output_format);
257 :    
258 :     return DEC_OK;
259 :     }
260 : Isibaar 1.1
261 : edgomez 1.9 case DEC_OPT_FRAME:
262 :     {
263 :     int csp_tmp = 0;
264 :     DINST * dcur;
265 :     DEC_FRAME * dframe = (DEC_FRAME *)param1;
266 :    
267 :     if ((dcur = dinst_find(key)) == NULL)
268 :     {
269 :     return DEC_EXIT;
270 :     }
271 :    
272 :     /* Copy the divx4 fields to the XviD decoder structure */
273 :     dcur->xframe.bitstream = dframe->bitstream;
274 :     dcur->xframe.length = dframe->length;
275 :     dcur->xframe.image = dframe->bmp;
276 :     dcur->xframe.stride = dframe->stride;
277 :    
278 :     /* Does the frame need to be skipped ? */
279 :     if (!dframe->render_flag)
280 :     {
281 :     /*
282 :     * Then we use the null colorspace to force XviD to
283 :     * skip the frame. The original colorspace will be
284 :     * restored after the decoder call
285 :     */
286 :     csp_tmp = dcur->xframe.colorspace;
287 :     dcur->xframe.colorspace = XVID_CSP_NULL;
288 :     }
289 :    
290 :     /* Decode the bitstream */
291 :     xerr = decoder_decode(dcur->handle, &dcur->xframe);
292 :    
293 :     /* Restore the real colorspace for this instance */
294 :     if (!dframe->render_flag)
295 :     {
296 :     dcur->xframe.colorspace = csp_tmp;
297 :     }
298 :    
299 :     break;
300 :     }
301 :    
302 :     case DEC_OPT_FRAME_311 :
303 :     /* XviD does not handle Divx ;-) 3.11 yet */
304 :     return DEC_EXIT;
305 :    
306 :     case DEC_OPT_VERSION:
307 :     return EMULATED_DIVX_VERSION;
308 :    
309 :     default :
310 :     return DEC_EXIT;
311 :     }
312 :    
313 :    
314 :     /* XviD error code -> Divx4 */
315 :     switch(xerr)
316 :     {
317 :     case XVID_ERR_OK :
318 :     return DEC_OK;
319 :     case XVID_ERR_MEMORY :
320 :     return DEC_MEMORY;
321 :     case XVID_ERR_FORMAT :
322 :     return DEC_BAD_FORMAT;
323 :     default :
324 :     return DEC_EXIT;
325 :     }
326 :     }
327 :    
328 :     /**************************************************************************
329 :     * Encore Part
330 :     *
331 :     * encore is the divx4 entry point used to compress a frame to a mpeg4
332 :     * bitstream.
333 :     *************************************************************************/
334 :    
335 :     #define FRAMERATE_INCR 1001
336 :    
337 :     int
338 :     encore(void * handle, int opt, void * param1, void * param2)
339 :     {
340 :    
341 :     int xerr;
342 :    
343 :     switch(opt) {
344 :     case ENC_OPT_INIT :
345 :     {
346 : edgomez 1.11 EINST *ecur;
347 : edgomez 1.9 ENC_PARAM * eparam = (ENC_PARAM *)param1;
348 :     XVID_INIT_PARAM xinit;
349 :     XVID_ENC_PARAM xparam;
350 :    
351 :     /* Init XviD which will detect host cpu features */
352 :     xinit.cpu_flags = 0;
353 :     xvid_init(NULL, 0, &xinit, NULL);
354 :    
355 :     /* Settings are copied to the XviD encoder structure */
356 :     xparam.width = eparam->x_dim;
357 :     xparam.height = eparam->y_dim;
358 :     if ((eparam->framerate - (int)eparam->framerate) == 0)
359 :     {
360 :     xparam.fincr = 1;
361 :     xparam.fbase = (int)eparam->framerate;
362 :     }
363 :     else
364 :     {
365 :     xparam.fincr = FRAMERATE_INCR;
366 :     xparam.fbase = (int)(FRAMERATE_INCR * eparam->framerate);
367 :     }
368 :     xparam.rc_bitrate = eparam->bitrate;
369 :     xparam.rc_reaction_delay_factor = 16;
370 :     xparam.rc_averaging_period = 100;
371 :     xparam.rc_buffer = 100;
372 :     xparam.min_quantizer = eparam->min_quantizer;
373 :     xparam.max_quantizer = eparam->max_quantizer;
374 :     xparam.max_key_interval = eparam->max_key_interval;
375 :    
376 :     /* Create the encoder session */
377 :     xerr = encoder_create(&xparam);
378 :    
379 :     eparam->handle = xparam.handle;
380 :    
381 : edgomez 1.11 /* Create an encoder instance in the chainlist */
382 :     if ((ecur = einst_find(xparam.handle)) == NULL)
383 :     {
384 :     ecur = einst_add(xparam.handle);
385 :    
386 :     if(ecur == NULL) {
387 :     encoder_destroy((Encoder*)xparam.handle);
388 :     return ENC_MEMORY;
389 :     }
390 :    
391 :     }
392 :    
393 :     ecur->quality = eparam->quality;
394 :     if(ecur->quality < 0) ecur->quality = 0;
395 :     if(ecur->quality > 6) ecur->quality = 6;
396 :    
397 : edgomez 1.9 break;
398 :     }
399 :    
400 :     case ENC_OPT_RELEASE :
401 :     {
402 : edgomez 1.11 EINST *ecur;
403 :    
404 :     if ((ecur = einst_find(handle)) == NULL)
405 :     {
406 :     return ENC_FAIL;
407 :     }
408 :    
409 : edgomez 1.9 xerr = encoder_destroy((Encoder *) handle);
410 :     break;
411 :     }
412 :    
413 :     case ENC_OPT_ENCODE :
414 :     case ENC_OPT_ENCODE_VBR :
415 :     {
416 : edgomez 1.11 EINST *ecur;
417 :    
418 : edgomez 1.9 ENC_FRAME * eframe = (ENC_FRAME *)param1;
419 :     ENC_RESULT * eresult = (ENC_RESULT *)param2;
420 :     XVID_ENC_FRAME xframe;
421 :     XVID_ENC_STATS xstats;
422 :    
423 : edgomez 1.11 if ((ecur = einst_find(handle)) == NULL)
424 :     {
425 :     return ENC_FAIL;
426 :     }
427 :    
428 : edgomez 1.9 /* Copy the divx4 info into the xvid structure */
429 :     xframe.bitstream = eframe->bitstream;
430 :     xframe.length = eframe->length;
431 : edgomez 1.11 xframe.motion = divx4_motion_presets[ecur->quality];
432 :     xframe.general = divx4_general_presets[ecur->quality];
433 : edgomez 1.9
434 :     xframe.image = eframe->image;
435 :     xframe.colorspace =
436 :     xvid_to_opendivx_enc_csp(eframe->colorspace);
437 :    
438 :     if (opt == ENC_OPT_ENCODE_VBR)
439 :     {
440 :     xframe.intra = eframe->intra;
441 :     xframe.quant = eframe->quant;
442 :     }
443 :     else
444 :     {
445 :     xframe.intra = -1;
446 :     xframe.quant = 0;
447 :     }
448 :    
449 :     /* Encode the frame */
450 :     xerr = encoder_encode((Encoder *) handle, &xframe, (eresult ? &xstats : NULL) );
451 :    
452 :     /* Copy back the xvid structure to the divx4 one */
453 :     if (eresult)
454 :     {
455 :     eresult->is_key_frame = xframe.intra;
456 :     eresult->quantizer = xstats.quant;
457 :     eresult->total_bits = xframe.length * 8;
458 :     eresult->motion_bits = xstats.hlength * 8;
459 :     eresult->texture_bits = eresult->total_bits - eresult->motion_bits;
460 :     }
461 :    
462 :     eframe->length = xframe.length;
463 :    
464 :     break;
465 :     }
466 :    
467 :     default:
468 :     return ENC_FAIL;
469 :     }
470 :    
471 :     /* XviD Error code -> Divx4 error code */
472 :     switch(xerr)
473 :     {
474 :     case XVID_ERR_OK :
475 :     return ENC_OK;
476 :     case XVID_ERR_MEMORY :
477 :     return ENC_MEMORY;
478 :     case XVID_ERR_FORMAT :
479 :     return ENC_BAD_FORMAT;
480 :     default :
481 :     return ENC_FAIL;
482 :     }
483 :     }
484 :    
485 :     /**************************************************************************
486 :     * Local Functions
487 :     *************************************************************************/
488 : Isibaar 1.1
489 : edgomez 1.9 /***************************************
490 :     * DINST chainlist helper functions *
491 :     ***************************************/
492 : Isibaar 1.1
493 : edgomez 1.9 /* Find an element in the chainlist according to its key value */
494 :     static DINST * dinst_find(unsigned long key)
495 : Isibaar 1.1 {
496 :     DINST * dcur = dhead;
497 :    
498 :     while (dcur)
499 :     {
500 :     if (dcur->key == key)
501 :     {
502 :     return dcur;
503 :     }
504 :     dcur = dcur->next;
505 :     }
506 :    
507 :     return NULL;
508 :     }
509 :    
510 :    
511 : edgomez 1.9 /* Add an element to the chainlist */
512 :     static DINST * dinst_add(unsigned long key)
513 : Isibaar 1.1 {
514 :     DINST * dnext = dhead;
515 :    
516 :     dhead = malloc(sizeof(DINST));
517 :     if (dhead == NULL)
518 :     {
519 :     dhead = dnext;
520 :     return NULL;
521 :     }
522 :    
523 :     dhead->key = key;
524 :     dhead->next = dnext;
525 :    
526 :     return dhead;
527 :     }
528 :    
529 :    
530 : edgomez 1.9 /* Remove an elmement from the chainlist */
531 :     static void dinst_remove(unsigned long key)
532 : Isibaar 1.1 {
533 :     DINST * dcur = dhead;
534 :    
535 :     if (dhead == NULL)
536 :     {
537 :     return;
538 :     }
539 :    
540 :     if (dcur->key == key)
541 :     {
542 :     dhead = dcur->next;
543 :     free(dcur);
544 :     return;
545 :     }
546 :    
547 :     while (dcur->next)
548 :     {
549 :     if (dcur->next->key == key)
550 :     {
551 :     DINST * tmp = dcur->next;
552 :     dcur->next = tmp->next;
553 :     free(tmp);
554 :     return;
555 :     }
556 :     dcur = dcur->next;
557 :     }
558 :     }
559 :    
560 : edgomez 1.11
561 :     /***************************************
562 :     * EINST chainlist helper functions *
563 :     ***************************************/
564 :    
565 :     /* Find an element in the chainlist according to its handle */
566 :     static EINST * einst_find(void *handle)
567 :     {
568 :     EINST * ecur = ehead;
569 :    
570 :     while (ecur)
571 :     {
572 :     if (ecur->handle == handle)
573 :     {
574 :     return ecur;
575 :     }
576 :     ecur = ecur->next;
577 :     }
578 :    
579 :     return NULL;
580 :     }
581 :    
582 :    
583 :     /* Add an element to the chainlist */
584 :     static EINST * einst_add(void *handle)
585 :     {
586 :     EINST * enext = ehead;
587 :    
588 :     ehead = malloc(sizeof(EINST));
589 :     if (ehead == NULL)
590 :     {
591 :     ehead = enext;
592 :     return NULL;
593 :     }
594 :    
595 :     ehead->handle = handle;
596 :     ehead->next = enext;
597 :    
598 :     return ehead;
599 :     }
600 :    
601 :    
602 :     /* Remove an elmement from the chainlist */
603 :     static void einst_remove(void *handle)
604 :     {
605 :     EINST * ecur = ehead;
606 :    
607 :     if (ehead == NULL)
608 :     {
609 :     return;
610 :     }
611 :    
612 :     if (ecur->handle == handle)
613 :     {
614 :     ehead = ecur->next;
615 :     free(ecur);
616 :     return;
617 :     }
618 :    
619 :     while (ecur->next)
620 :     {
621 :     if (ecur->next->handle == handle)
622 :     {
623 :     EINST * tmp = ecur->next;
624 :     ecur->next = tmp->next;
625 :     free(tmp);
626 :     return;
627 :     }
628 :     ecur = ecur->next;
629 :     }
630 :     }
631 : edgomez 1.9 /***************************************
632 :     * Colorspace code converter *
633 :     ***************************************/
634 : Isibaar 1.1
635 : edgomez 1.9 static int xvid_to_opendivx_dec_csp(int csp)
636 : Isibaar 1.1 {
637 : edgomez 1.9
638 : Isibaar 1.1 switch(csp)
639 :     {
640 :     case DEC_YV12 :
641 :     return XVID_CSP_YV12;
642 :     case DEC_420 :
643 :     return XVID_CSP_I420;
644 :     case DEC_YUY2 :
645 :     return XVID_CSP_YUY2;
646 :     case DEC_UYVY :
647 :     return XVID_CSP_UYVY;
648 :     case DEC_RGB32 :
649 :     return XVID_CSP_VFLIP | XVID_CSP_RGB32;
650 :     case DEC_RGB24 :
651 :     return XVID_CSP_VFLIP | XVID_CSP_RGB24;
652 :     case DEC_RGB565 :
653 :     return XVID_CSP_VFLIP | XVID_CSP_RGB565;
654 :     case DEC_RGB555 :
655 :     return XVID_CSP_VFLIP | XVID_CSP_RGB555;
656 :     case DEC_RGB32_INV :
657 :     return XVID_CSP_RGB32;
658 :     case DEC_RGB24_INV :
659 :     return XVID_CSP_RGB24;
660 :     case DEC_RGB565_INV :
661 :     return XVID_CSP_RGB565;
662 :     case DEC_RGB555_INV :
663 :     return XVID_CSP_RGB555;
664 :     case DEC_USER :
665 :     return XVID_CSP_USER;
666 :     default :
667 :     return -1;
668 :     }
669 :     }
670 :    
671 : edgomez 1.9 static int xvid_to_opendivx_enc_csp(int csp)
672 : Isibaar 1.1 {
673 :    
674 : edgomez 1.9 switch (csp)
675 : Isibaar 1.1 {
676 : edgomez 1.9 case ENC_CSP_RGB24 :
677 :     return XVID_CSP_VFLIP | XVID_CSP_RGB24;
678 :     case ENC_CSP_YV12 :
679 :     return XVID_CSP_YV12;
680 :     case ENC_CSP_YUY2 :
681 :     return XVID_CSP_YUY2;
682 :     case ENC_CSP_UYVY :
683 :     return XVID_CSP_UYVY;
684 :     case ENC_CSP_I420 :
685 :     return XVID_CSP_I420;
686 : Isibaar 1.1 default :
687 : edgomez 1.9 return -1;
688 : Isibaar 1.1 }
689 :     }

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