ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/trunk/vfw/src/codec.c
Revision: 235
Committed: Sun Jun 23 03:59:49 2002 UTC (22 years, 3 months ago) by suxen_drol
Content type: text/plain
File size: 20028 byte(s)
Log Message:
XVID_GLOBAL_*, XVID_CPU_CHKONLY

File Contents

# Content
1 /**************************************************************************
2 *
3 * XVID VFW FRONTEND
4 * codec
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 *
20 *************************************************************************/
21
22 /**************************************************************************
23 *
24 * History:
25 *
26 * 23.06.2002 XVID_CPU_CHKONLY; loading speed up
27 * 25.04.2002 ICDECOMPRESS_PREROLL
28 * 17.04.2002 re-enabled lumi masking for 1st pass
29 * 15.04.2002 updated cbr support
30 * 04.04.2002 separated 2-pass code to 2pass.c
31 * interlacing support
32 * hinted ME support
33 * 23.03.2002 daniel smith <danielsmith@astroboymail.com>
34 * changed inter4v to only be in modes 5 or 6
35 * fixed null mode crash ?
36 * merged foxer's alternative 2-pass code
37 * added DEBUGERR output on errors instead of returning
38 * 16.03.2002 daniel smith <danielsmith@astroboymail.com>
39 * changed BITMAPV4HEADER to BITMAPINFOHEADER
40 * - prevents memcpy crash in compress_get_format()
41 * credits are processed in external 2pass mode
42 * motion search precision = 0 now effective in 2-pass
43 * modulated quantization
44 * added DX50 fourcc
45 * 01.12.2001 inital version; (c)2001 peter ross <suxen_drol@hotmail.com>
46 *
47 *************************************************************************/
48
49 #include <windows.h>
50 #include <vfw.h>
51
52 #include "codec.h"
53 #include "2pass.h"
54
55 int pmvfast_presets[7] = {
56 0, PMV_QUICKSTOP16, PMV_EARLYSTOP16, PMV_EARLYSTOP16 | PMV_EARLYSTOP8,
57 PMV_EARLYSTOP16 | PMV_HALFPELREFINE16 | PMV_EARLYSTOP8 | PMV_HALFPELDIAMOND8,
58 PMV_EARLYSTOP16 | PMV_HALFPELREFINE16 | PMV_EARLYSTOP8 | PMV_HALFPELDIAMOND8,
59 PMV_EARLYSTOP16 | PMV_HALFPELREFINE16 | PMV_EXTSEARCH16 |
60 PMV_EARLYSTOP8 | PMV_HALFPELREFINE8 | PMV_HALFPELDIAMOND8
61 };
62
63 /* return xvid compatbile colorspace,
64 or XVID_CSP_NULL if failure
65 */
66
67 int get_colorspace(BITMAPINFOHEADER * hdr)
68 {
69 if (hdr->biHeight < 0)
70 {
71 DEBUGERR("colorspace: inverted input format not supported");
72 return XVID_CSP_NULL;
73 }
74
75 switch(hdr->biCompression)
76 {
77 case BI_RGB :
78 if (hdr->biBitCount == 16)
79 {
80 DEBUG("RGB16 (RGB555)");
81 return XVID_CSP_VFLIP | XVID_CSP_RGB555;
82 }
83 if (hdr->biBitCount == 24)
84 {
85 DEBUG("RGB24");
86 return XVID_CSP_VFLIP | XVID_CSP_RGB24;
87 }
88 if (hdr->biBitCount == 32)
89 {
90 DEBUG("RGB32");
91 return XVID_CSP_VFLIP | XVID_CSP_RGB32;
92 }
93
94 DEBUG1("BI_RGB unsupported", hdr->biBitCount);
95 return XVID_CSP_NULL;
96
97 // how do these work in BITMAPINFOHEADER ???
98 /* case BI_BITFIELDS :
99 if (hdr->biBitCount == 16
100 if(hdr->biBitCount == 16 &&
101 hdr->bV4RedMask == 0x7c00 &&
102 hdr->bV4GreenMask == 0x3e0 &&
103 hdr->bV4BlueMask == 0x1f)
104 {
105 DEBUG("RGB555");
106 return XVID_CSP_VFLIP | XVID_CSP_RGB555;
107 }
108 if(hdr->bV4BitCount == 16 &&
109 hdr->bV4RedMask == 0xf800 &&
110 hdr->bV4GreenMask == 0x7e0 &&
111 hdr->bV4BlueMask == 0x1f)
112 {
113 DEBUG("RGB565");
114 return XVID_CSP_VFLIP | XVID_CSP_RGB565;
115 }
116
117 DEBUG1("BI_FIELDS unsupported", hdr->bV4BitCount);
118 return XVID_CSP_NULL;
119 */
120 case FOURCC_I420:
121 case FOURCC_IYUV:
122 DEBUG("IYUY");
123 return XVID_CSP_I420;
124
125 case FOURCC_YV12 :
126 DEBUG("YV12");
127 return XVID_CSP_YV12;
128
129 case FOURCC_YUYV :
130 case FOURCC_YUY2 :
131 case FOURCC_V422 :
132 DEBUG("YUY2");
133 return XVID_CSP_YUY2;
134
135 case FOURCC_YVYU:
136 DEBUG("YVYU");
137 return XVID_CSP_YVYU;
138
139 case FOURCC_UYVY:
140 DEBUG("UYVY");
141 return XVID_CSP_UYVY;
142
143 }
144 DEBUGFOURCC("colorspace: unknown", hdr->biCompression);
145 return XVID_CSP_NULL;
146 }
147
148
149 /* compressor */
150
151
152 /* test the output format */
153
154 LRESULT compress_query(CODEC * codec, BITMAPINFO * lpbiInput, BITMAPINFO * lpbiOutput)
155 {
156 BITMAPINFOHEADER * inhdr = &lpbiInput->bmiHeader;
157 BITMAPINFOHEADER * outhdr = &lpbiOutput->bmiHeader;
158
159 if (get_colorspace(inhdr) == XVID_CSP_NULL)
160 {
161 return ICERR_BADFORMAT;
162 }
163
164 if (lpbiOutput == NULL)
165 {
166 return ICERR_OK;
167 }
168
169 if (inhdr->biWidth != outhdr->biWidth || inhdr->biHeight != outhdr->biHeight ||
170 (outhdr->biCompression != FOURCC_XVID && outhdr->biCompression != FOURCC_DIVX))
171 {
172 return ICERR_BADFORMAT;
173 }
174
175 return ICERR_OK;
176 }
177
178
179 LRESULT compress_get_format(CODEC * codec, BITMAPINFO * lpbiInput, BITMAPINFO * lpbiOutput)
180 {
181 BITMAPINFOHEADER * inhdr = &lpbiInput->bmiHeader;
182 BITMAPINFOHEADER * outhdr = &lpbiOutput->bmiHeader;
183
184 if (get_colorspace(inhdr) == XVID_CSP_NULL)
185 {
186 return ICERR_BADFORMAT;
187 }
188
189 if (lpbiOutput == NULL)
190 {
191 return sizeof(BITMAPV4HEADER);
192 }
193
194 memcpy(outhdr, inhdr, sizeof(BITMAPINFOHEADER));
195 outhdr->biSize = sizeof(BITMAPINFOHEADER);
196 outhdr->biBitCount = 24; // or 16
197 outhdr->biSizeImage = compress_get_size(codec, lpbiInput, lpbiOutput);
198 outhdr->biXPelsPerMeter = 0;
199 outhdr->biYPelsPerMeter = 0;
200 outhdr->biClrUsed = 0;
201 outhdr->biClrImportant = 0;
202
203 if (codec->config.fourcc_used == 0)
204 {
205 outhdr->biCompression = FOURCC_XVID;
206 }
207 else if (codec->config.fourcc_used == 1)
208 {
209 outhdr->biCompression = FOURCC_DIVX;
210 }
211 else
212 {
213 outhdr->biCompression = FOURCC_DX50;
214 }
215
216 return ICERR_OK;
217 }
218
219
220 LRESULT compress_get_size(CODEC * codec, BITMAPINFO * lpbiInput, BITMAPINFO * lpbiOutput)
221 {
222 return
223 #ifdef BFRAMES
224 2 *
225 #endif
226 lpbiOutput->bmiHeader.biWidth * lpbiOutput->bmiHeader.biHeight * 3;
227 }
228
229
230 LRESULT compress_frames_info(CODEC * codec, ICCOMPRESSFRAMES * icf)
231 {
232 // DEBUG2("frate fscale", codec->frate, codec->fscale);
233 codec->fincr = icf->dwScale;
234 codec->fbase = icf->dwRate;
235 return ICERR_OK;
236 }
237
238
239 LRESULT compress_begin(CODEC * codec, BITMAPINFO * lpbiInput, BITMAPINFO * lpbiOutput)
240 {
241 XVID_ENC_PARAM param;
242 XVID_INIT_PARAM init_param;
243
244 switch (codec->config.mode)
245 {
246 case DLG_MODE_CBR :
247 param.rc_bitrate = codec->config.rc_bitrate;
248 param.rc_reaction_delay_factor = codec->config.rc_reaction_delay_factor;
249 param.rc_averaging_period = codec->config.rc_averaging_period;
250 param.rc_buffer = codec->config.rc_buffer;
251 break;
252
253 case DLG_MODE_VBR_QUAL :
254 codec->config.fquant = 0;
255 param.rc_bitrate = 0;
256 break;
257
258 case DLG_MODE_VBR_QUANT :
259 codec->config.fquant = (float) codec->config.quant;
260 param.rc_bitrate = 0;
261 break;
262
263 case DLG_MODE_2PASS_1 :
264 case DLG_MODE_2PASS_2_INT :
265 case DLG_MODE_2PASS_2_EXT :
266 param.rc_bitrate = 0;
267 codec->twopass.max_framesize = (int)((double)codec->config.twopass_max_bitrate / 8.0 / ((double)codec->fbase / (double)codec->fincr));
268 break;
269
270 case DLG_MODE_NULL :
271 return ICERR_OK;
272
273 default :
274 break;
275 }
276
277 if(codec->ehandle)
278 {
279 xvid_encore(codec->ehandle, XVID_ENC_DESTROY, NULL, NULL);
280 codec->ehandle = NULL;
281 }
282
283 init_param.cpu_flags = codec->config.cpu;
284 xvid_init(0, 0, &init_param, NULL);
285 if((codec->config.cpu & XVID_CPU_FORCE) <= 0)
286 codec->config.cpu = init_param.cpu_flags;
287
288 param.width = lpbiInput->bmiHeader.biWidth;
289 param.height = lpbiInput->bmiHeader.biHeight;
290 param.fincr = codec->fincr;
291 param.fbase = codec->fbase;
292
293 param.min_quantizer = codec->config.min_pquant;
294 param.max_quantizer = codec->config.max_pquant;
295 param.max_key_interval = codec->config.max_key_interval;
296
297 #ifdef BFRAMES
298 param.global = 0;
299 if (codec->config.packed) param.global |= XVID_GLOBAL_PACKED;
300 if (codec->config.dx50bvop) param.global |= XVID_GLOBAL_DX50BVOP;
301 if (codec->config.debug) param.global |= XVID_GLOBAL_DEBUG;
302 param.max_bframes = codec->config.max_bframes;
303 param.bquant_ratio = codec->config.bquant_ratio;
304 #endif
305
306 switch(xvid_encore(0, XVID_ENC_CREATE, &param, NULL))
307 {
308 case XVID_ERR_FAIL :
309 return ICERR_ERROR;
310
311 case XVID_ERR_MEMORY :
312 return ICERR_MEMORY;
313
314 case XVID_ERR_FORMAT :
315 return ICERR_BADFORMAT;
316 }
317
318 codec->ehandle = param.handle;
319 codec->framenum = 0;
320 codec->keyspacing = 0;
321
322 codec->twopass.hints = codec->twopass.stats1 = codec->twopass.stats2 = INVALID_HANDLE_VALUE;
323 codec->twopass.hintstream = NULL;
324
325 return ICERR_OK;
326 }
327
328
329 LRESULT compress_end(CODEC * codec)
330 {
331 if (codec->ehandle != NULL)
332 {
333 xvid_encore(codec->ehandle, XVID_ENC_DESTROY, NULL, NULL);
334
335 if (codec->twopass.hints != INVALID_HANDLE_VALUE)
336 {
337 CloseHandle(codec->twopass.hints);
338 }
339 if (codec->twopass.stats1 != INVALID_HANDLE_VALUE)
340 {
341 CloseHandle(codec->twopass.stats1);
342 }
343 if (codec->twopass.stats2 != INVALID_HANDLE_VALUE)
344 {
345 CloseHandle(codec->twopass.stats2);
346 }
347 if (codec->twopass.hintstream != NULL)
348 {
349 free(codec->twopass.hintstream);
350 }
351
352 codec->ehandle = NULL;
353
354 codec_2pass_finish(codec);
355 }
356
357 return ICERR_OK;
358 }
359
360
361 LRESULT compress(CODEC * codec, ICCOMPRESS * icc)
362 {
363 BITMAPINFOHEADER * inhdr = icc->lpbiInput;
364 BITMAPINFOHEADER * outhdr = icc->lpbiOutput;
365 XVID_ENC_FRAME frame;
366 XVID_ENC_STATS stats;
367
368 // mpeg2avi yuv bug workaround (2 instances of CODEC)
369 if (codec->twopass.stats1 == INVALID_HANDLE_VALUE)
370 {
371 if (codec_2pass_init(codec) == ICERR_ERROR)
372 {
373 return ICERR_ERROR;
374 }
375 }
376
377 frame.general = 0;
378 frame.motion = 0;
379 frame.intra = -1;
380
381 frame.general |= XVID_HALFPEL;
382
383 if (codec->config.motion_search > 4)
384 frame.general |= XVID_INTER4V;
385
386 if (codec->config.lum_masking)
387 frame.general |= XVID_LUMIMASKING;
388
389 if (codec->config.interlacing)
390 frame.general |= XVID_INTERLACING;
391 // fix 1pass modes/hinted MV by koepi
392 if (codec->config.hinted_me && (codec->config.mode == DLG_MODE_CBR || codec->config.mode == DLG_MODE_VBR_QUAL || codec->config.mode == DLG_MODE_VBR_QUANT))
393 {
394 codec->config.hinted_me = 0;
395 }
396 // end of ugly hack
397
398 if (codec->config.hinted_me && codec->config.mode == DLG_MODE_2PASS_1)
399 {
400 frame.hint.hintstream = codec->twopass.hintstream;
401 frame.hint.rawhints = 0;
402 frame.general |= XVID_HINTEDME_GET;
403 }
404 else if (codec->config.hinted_me && (codec->config.mode == DLG_MODE_2PASS_2_EXT || codec->config.mode == DLG_MODE_2PASS_2_INT))
405 {
406 DWORD read;
407 DWORD blocksize;
408
409 frame.hint.hintstream = codec->twopass.hintstream;
410 frame.hint.rawhints = 0;
411 frame.general |= XVID_HINTEDME_SET;
412
413 if (codec->twopass.hints == INVALID_HANDLE_VALUE)
414 {
415 codec->twopass.hints = CreateFile(codec->config.hintfile, GENERIC_READ, 0, 0, OPEN_EXISTING, 0, 0);
416 if (codec->twopass.hints == INVALID_HANDLE_VALUE)
417 {
418 DEBUGERR("couldn't open hints file");
419 return ICERR_ERROR;
420 }
421 }
422 if (!ReadFile(codec->twopass.hints, &blocksize, sizeof(DWORD), &read, 0) || read != sizeof(DWORD) ||
423 !ReadFile(codec->twopass.hints, frame.hint.hintstream, blocksize, &read, 0) || read != blocksize)
424 {
425 DEBUGERR("couldn't read from hints file");
426 return ICERR_ERROR;
427 }
428 }
429
430 frame.motion = pmvfast_presets[codec->config.motion_search];
431
432 frame.image = icc->lpInput;
433
434 if ((frame.colorspace = get_colorspace(inhdr)) == XVID_CSP_NULL)
435 return ICERR_BADFORMAT;
436
437 frame.bitstream = icc->lpOutput;
438 frame.length = icc->lpbiOutput->biSizeImage;
439
440 switch (codec->config.mode)
441 {
442 case DLG_MODE_CBR :
443 frame.quant = 0;
444 break;
445
446 case DLG_MODE_VBR_QUAL :
447 case DLG_MODE_VBR_QUANT :
448 case DLG_MODE_2PASS_1 :
449 if (codec_get_quant(codec, &frame) == ICERR_ERROR)
450 {
451 return ICERR_ERROR;
452 }
453 break;
454
455 case DLG_MODE_2PASS_2_EXT :
456 case DLG_MODE_2PASS_2_INT :
457 if (codec_2pass_get_quant(codec, &frame) == ICERR_ERROR)
458 {
459 return ICERR_ERROR;
460 }
461 if (codec->config.dummy2pass)
462 {
463 outhdr->biSizeImage = codec->twopass.bytes2;
464 *icc->lpdwFlags = (codec->twopass.nns1.quant & NNSTATS_KEYFRAME) ? AVIIF_KEYFRAME : 0;
465 return ICERR_OK;
466 }
467 break;
468
469 case DLG_MODE_NULL :
470 outhdr->biSizeImage = 0;
471 *icc->lpdwFlags = AVIIF_KEYFRAME;
472 return ICERR_OK;
473
474 default :
475 DEBUGERR("Invalid encoding mode");
476 return ICERR_ERROR;
477 }
478
479 if (codec->config.quant_type == QUANT_MODE_H263)
480 {
481 frame.general |= XVID_H263QUANT;
482 }
483 else
484 {
485 frame.general |= XVID_MPEGQUANT;
486
487 // we actually need "default/custom" selectbox for both inter/intra
488 // this will do for now
489 if (codec->config.quant_type == QUANT_MODE_CUSTOM)
490 {
491 frame.general |= XVID_CUSTOM_QMATRIX;
492 frame.quant_intra_matrix = codec->config.qmatrix_intra;
493 frame.quant_inter_matrix = codec->config.qmatrix_inter;
494 }
495 else
496 {
497 frame.quant_intra_matrix = NULL;
498 frame.quant_inter_matrix = NULL;
499 }
500 }
501
502 // force keyframe spacing in 2-pass 1st pass
503 if (codec->config.motion_search == 0)
504 {
505 frame.intra = 1;
506 }
507 else if (codec->keyspacing < codec->config.min_key_interval && codec->framenum)
508 {
509 DEBUG("current frame forced to p-frame");
510 frame.intra = 0;
511 }
512
513 OutputDebugString(" ");
514 switch (xvid_encore(codec->ehandle, XVID_ENC_ENCODE, &frame, &stats))
515 {
516 case XVID_ERR_FAIL :
517 return ICERR_ERROR;
518
519 case XVID_ERR_MEMORY :
520 return ICERR_MEMORY;
521
522 case XVID_ERR_FORMAT :
523 return ICERR_BADFORMAT;
524 }
525
526 if (frame.intra)
527 {
528 codec->keyspacing = 0;
529 *icc->lpdwFlags = AVIIF_KEYFRAME;
530 }
531 else
532 {
533 *icc->lpdwFlags = 0;
534 }
535
536 outhdr->biSizeImage = frame.length;
537
538 if (codec->config.mode == DLG_MODE_2PASS_1 && codec->config.discard1pass)
539 {
540 outhdr->biSizeImage = 0;
541 }
542
543 if (frame.general & XVID_HINTEDME_GET)
544 {
545 DWORD wrote;
546 DWORD blocksize = frame.hint.hintlength;
547
548 if (codec->twopass.hints == INVALID_HANDLE_VALUE)
549 {
550 codec->twopass.hints = CreateFile(codec->config.hintfile, GENERIC_WRITE, 0, 0, CREATE_ALWAYS, 0, 0);
551 if (codec->twopass.hints == INVALID_HANDLE_VALUE)
552 {
553 DEBUGERR("couldn't create hints file");
554 return ICERR_ERROR;
555 }
556 }
557 if (!WriteFile(codec->twopass.hints, &frame.hint.hintlength, sizeof(int), &wrote, 0) || wrote != sizeof(int) ||
558 !WriteFile(codec->twopass.hints, frame.hint.hintstream, blocksize, &wrote, 0) || wrote != blocksize)
559 {
560 DEBUGERR("couldn't write to hints file");
561 return ICERR_ERROR;
562 }
563 }
564
565 codec_2pass_update(codec, &frame, &stats);
566
567 ++codec->framenum;
568 ++codec->keyspacing;
569
570 return ICERR_OK;
571 }
572
573
574 /* decompressor */
575
576
577 LRESULT decompress_query(CODEC * codec, BITMAPINFO *lpbiInput, BITMAPINFO *lpbiOutput)
578 {
579 BITMAPINFOHEADER * inhdr = &lpbiInput->bmiHeader;
580 BITMAPINFOHEADER * outhdr = &lpbiOutput->bmiHeader;
581
582 if (lpbiInput == NULL)
583 {
584 return ICERR_ERROR;
585 }
586
587 if (inhdr->biCompression != FOURCC_XVID && inhdr->biCompression != FOURCC_DIVX)
588 {
589 return ICERR_BADFORMAT;
590 }
591
592 if (lpbiOutput == NULL)
593 {
594 return ICERR_OK;
595 }
596
597 if (inhdr->biWidth != outhdr->biWidth ||
598 inhdr->biHeight != outhdr->biHeight ||
599 get_colorspace(outhdr) == XVID_CSP_NULL)
600 {
601 return ICERR_BADFORMAT;
602 }
603
604 return ICERR_OK;
605 }
606
607
608 LRESULT decompress_get_format(CODEC * codec, BITMAPINFO * lpbiInput, BITMAPINFO * lpbiOutput)
609 {
610 BITMAPINFOHEADER * inhdr = &lpbiInput->bmiHeader;
611 BITMAPINFOHEADER * outhdr = &lpbiOutput->bmiHeader;
612 LRESULT result;
613
614 if (lpbiOutput == NULL)
615 {
616 return sizeof(BITMAPINFOHEADER);
617 }
618
619 result = decompress_query(codec, lpbiInput, lpbiOutput);
620 if (result != ICERR_OK)
621 {
622 return result;
623 }
624
625 memcpy(outhdr, inhdr, sizeof(BITMAPINFOHEADER));
626 outhdr->biSize = sizeof(BITMAPINFOHEADER);
627 outhdr->biCompression = FOURCC_YUY2;
628 outhdr->biSizeImage = outhdr->biWidth * outhdr->biHeight * outhdr->biBitCount;
629 outhdr->biXPelsPerMeter = 0;
630 outhdr->biYPelsPerMeter = 0;
631 outhdr->biClrUsed = 0;
632 outhdr->biClrImportant = 0;
633
634 return ICERR_OK;
635 }
636
637
638 LRESULT decompress_begin(CODEC * codec, BITMAPINFO * lpbiInput, BITMAPINFO * lpbiOutput)
639 {
640 XVID_DEC_PARAM param;
641 XVID_INIT_PARAM init_param;
642
643 init_param.cpu_flags = codec->config.cpu;
644 xvid_init(0, 0, &init_param, NULL);
645 if((codec->config.cpu & XVID_CPU_FORCE) <= 0)
646 {
647 codec->config.cpu = init_param.cpu_flags;
648 }
649
650 param.width = lpbiInput->bmiHeader.biWidth;
651 param.height = lpbiInput->bmiHeader.biHeight;
652
653 switch(xvid_decore(0, XVID_DEC_CREATE, &param, NULL))
654 {
655 case XVID_ERR_FAIL :
656 return ICERR_ERROR;
657
658 case XVID_ERR_MEMORY :
659 return ICERR_MEMORY;
660
661 case XVID_ERR_FORMAT :
662 return ICERR_BADFORMAT;
663 }
664
665 codec->dhandle = param.handle;
666
667 return ICERR_OK;
668 }
669
670
671 LRESULT decompress_end(CODEC * codec)
672 {
673 if (codec->dhandle != NULL)
674 {
675 xvid_decore(codec->dhandle, XVID_DEC_DESTROY, NULL, NULL);
676 codec->dhandle = NULL;
677 }
678 return ICERR_OK;
679 }
680
681
682 LRESULT decompress(CODEC * codec, ICDECOMPRESS * icd)
683 {
684 XVID_DEC_FRAME frame;
685
686 frame.bitstream = icd->lpInput;
687 frame.length = icd->lpbiInput->biSizeImage;
688
689 frame.image = icd->lpOutput;
690 frame.stride = icd->lpbiOutput->biWidth;
691
692 if (~((icd->dwFlags & ICDECOMPRESS_HURRYUP) | (icd->dwFlags & ICDECOMPRESS_UPDATE) | (icd->dwFlags & ICDECOMPRESS_PREROLL)))
693 {
694 if ((frame.colorspace = get_colorspace(icd->lpbiOutput)) == XVID_CSP_NULL)
695 {
696 return ICERR_BADFORMAT;
697 }
698 }
699 else
700 {
701 frame.colorspace = XVID_CSP_NULL;
702 }
703
704 switch (xvid_decore(codec->dhandle, XVID_DEC_DECODE, &frame, NULL))
705 {
706 case XVID_ERR_FAIL :
707 return ICERR_ERROR;
708
709 case XVID_ERR_MEMORY :
710 return ICERR_MEMORY;
711
712 case XVID_ERR_FORMAT :
713 return ICERR_BADFORMAT;
714 }
715
716 return ICERR_OK;
717 }
718
719 int codec_get_quant(CODEC* codec, XVID_ENC_FRAME* frame)
720 {
721 switch (codec->config.mode)
722 {
723 case DLG_MODE_VBR_QUAL :
724 if (codec_is_in_credits(&codec->config, codec->framenum))
725 {
726 switch (codec->config.credits_mode)
727 {
728 case CREDITS_MODE_RATE :
729 frame->quant = codec_get_vbr_quant(&codec->config, codec->config.quality * codec->config.credits_rate / 100);
730 break;
731
732 case CREDITS_MODE_QUANT :
733 frame->quant = codec->config.credits_quant_p;
734 break;
735
736 default :
737 DEBUGERR("Can't use credits size mode in quality mode");
738 return ICERR_ERROR;
739 }
740 }
741 else
742 {
743 frame->quant = codec_get_vbr_quant(&codec->config, codec->config.quality);
744 }
745 return ICERR_OK;
746
747 case DLG_MODE_VBR_QUANT :
748 if (codec_is_in_credits(&codec->config, codec->framenum))
749 {
750 switch (codec->config.credits_mode)
751 {
752 case CREDITS_MODE_RATE :
753 frame->quant =
754 codec->config.max_pquant -
755 ((codec->config.max_pquant - codec->config.quant) * codec->config.credits_rate / 100);
756 break;
757
758 case CREDITS_MODE_QUANT :
759 frame->quant = codec->config.credits_quant_p;
760 break;
761
762 default :
763 DEBUGERR("Can't use credits size mode in quantizer mode");
764 return ICERR_ERROR;
765 }
766 }
767 else
768 {
769 frame->quant = codec->config.quant;
770 }
771 return ICERR_OK;
772
773 case DLG_MODE_2PASS_1 :
774 if (codec->config.credits_mode == CREDITS_MODE_QUANT)
775 {
776 if (codec_is_in_credits(&codec->config, codec->framenum))
777 {
778 frame->quant = codec->config.credits_quant_p;
779 }
780 else
781 {
782 frame->quant = 2;
783 }
784 }
785 else
786 {
787 frame->quant = 2;
788 }
789 return ICERR_OK;
790
791 default:
792 DEBUGERR("get quant: invalid mode");
793 return ICERR_ERROR;
794 }
795 }
796
797
798 int codec_is_in_credits(CONFIG* config, int framenum)
799 {
800 if (config->credits_start)
801 {
802 if (framenum >= config->credits_start_begin &&
803 framenum <= config->credits_start_end)
804 {
805 return CREDITS_START;
806 }
807 }
808
809 if (config->credits_end)
810 {
811 if (framenum >= config->credits_end_begin &&
812 framenum <= config->credits_end_end)
813 {
814 return CREDITS_END;
815 }
816 }
817
818 return 0;
819 }
820
821
822 int codec_get_vbr_quant(CONFIG* config, int quality)
823 {
824 static float fquant_running = 0;
825 static int my_quality = -1;
826 int quant;
827
828 // if quality changes, recalculate fquant (credits)
829 if (quality != my_quality)
830 {
831 config->fquant = 0;
832 }
833
834 my_quality = quality;
835
836 // desired quantiser = (maxQ-minQ)/100 * (100-qual) + minQ
837 if (!config->fquant)
838 {
839 config->fquant =
840 ((float) (config->max_pquant - config->min_pquant) / 100) *
841 (100 - quality) +
842 (float) config->min_pquant;
843
844 fquant_running = config->fquant;
845 }
846
847 if (fquant_running < config->min_pquant)
848 {
849 fquant_running = (float) config->min_pquant;
850 }
851 else if(fquant_running > config->max_pquant)
852 {
853 fquant_running = (float) config->max_pquant;
854 }
855
856 quant = (int) fquant_running;
857
858 // add error between fquant and quant to fquant_running
859 fquant_running += config->fquant - quant;
860
861 return quant;
862 }
863