ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/trunk/vfw/src/codec.c
Revision: 355
Committed: Thu Aug 1 12:56:29 2002 UTC (22 years, 2 months ago) by chl
Content type: text/plain
File size: 20371 byte(s)
Log Message:
Support for XVID_GREYSCALE (at least that's what Koepi claims...)

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