ViewVC Help
View File | Revision Log | Show Annotations | Root Listing
root/cvs/xvidcore/src/divx4.c
Revision: 1.16.2.1
Committed: Sat Oct 5 21:34:35 2002 UTC (22 years ago) by Isibaar
Content type: text/plain
Branch: dev-api-3
Changes since 1.16: +7 -10 lines
Log Message:
qpel support code

File Contents

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