ReactOS 0.4.15-dev-6052-g2626c72
icmstream.c
Go to the documentation of this file.
1/*
2 * Copyright 2002 Michael G├╝nnewig
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
17 */
18
19#include <assert.h>
20#include <stdarg.h>
21
22#include "windef.h"
23#include "winbase.h"
24#include "wingdi.h"
25#include "winuser.h"
26#include "winerror.h"
27#include "mmsystem.h"
28#include "vfw.h"
29
30#include "avifile_private.h"
31
32#include "wine/debug.h"
33
35
36#define MAX_FRAMESIZE (16 * 1024 * 1024)
37#define MAX_FRAMESIZE_DIFF 512
38
39/***********************************************************************/
40
41typedef struct _IAVIStreamImpl {
42 /* IUnknown stuff */
44 LONG ref;
45
46 /* IAVIStream stuff */
49
51 HIC hic;
53
60
61 LPBITMAPINFOHEADER lpbiCur; /* current frame */
63 LPBITMAPINFOHEADER lpbiPrev; /* previous frame */
65
66 LPBITMAPINFOHEADER lpbiOutput; /* output format of codec */
68 LPBITMAPINFOHEADER lpbiInput; /* input format for codec */
71
72/***********************************************************************/
73
75 LPBITMAPINFOHEADER lpbi, LPVOID lpBits);
77
79{
80 return CONTAINING_RECORD(iface, IAVIStreamImpl, IAVIStream_iface);
81}
82
83static inline void AVIFILE_Reset(IAVIStreamImpl *This)
84{
85 This->lCurrent = -1;
86 This->lLastKey = 0;
87 This->dwLastQuality = ICQUALITY_HIGH;
88 This->dwUnusedBytes = 0;
89}
90
92 REFIID refiid, LPVOID *obj)
93{
95
96 TRACE("(%p,%s,%p)\n", iface, debugstr_guid(refiid), obj);
97
98 if (IsEqualGUID(&IID_IUnknown, refiid) ||
99 IsEqualGUID(&IID_IAVIStream, refiid)) {
100 *obj = &This->IAVIStream_iface;
101 IAVIStream_AddRef(iface);
102
103 return S_OK;
104 }
105
106 return OLE_E_ENUM_NOMORE;
107}
108
110{
113
114 TRACE("(%p) -> %d\n", iface, ref);
115
116 /* also add reference to the nested stream */
117 if (This->pStream != NULL)
118 IAVIStream_AddRef(This->pStream);
119
120 return ref;
121}
122
124{
127
128 TRACE("(%p) -> %d\n", iface, ref);
129
130 if (ref == 0) {
131 /* destruct */
132 if (This->pg != NULL) {
134 This->pg = NULL;
135 }
136 if (This->pStream != NULL) {
137 IAVIStream_Release(This->pStream);
138 This->pStream = NULL;
139 }
140 if (This->hic != NULL) {
141 if (This->lpbiPrev != NULL) {
142 ICDecompressEnd(This->hic);
143 HeapFree(GetProcessHeap(), 0, This->lpbiPrev);
144 This->lpbiPrev = NULL;
145 This->lpPrev = NULL;
146 }
147 ICCompressEnd(This->hic);
148 This->hic = NULL;
149 }
150 if (This->lpbiCur != NULL) {
151 HeapFree(GetProcessHeap(), 0, This->lpbiCur);
152 This->lpbiCur = NULL;
153 This->lpCur = NULL;
154 }
155 if (This->lpbiOutput != NULL) {
156 HeapFree(GetProcessHeap(), 0, This->lpbiOutput);
157 This->lpbiOutput = NULL;
158 This->cbOutput = 0;
159 }
160 if (This->lpbiInput != NULL) {
161 HeapFree(GetProcessHeap(), 0, This->lpbiInput);
162 This->lpbiInput = NULL;
163 This->cbInput = 0;
164 }
165
167
168 return 0;
169 }
170
171 /* also release reference to the nested stream */
172 if (This->pStream != NULL)
173 IAVIStream_Release(This->pStream);
174
175 return ref;
176}
177
178/* lParam1: PAVISTREAM
179 * lParam2: LPAVICOMPRESSOPTIONS
180 */
182 LPARAM lParam2)
183{
185
186 ICINFO icinfo;
187 ICCOMPRESSFRAMES icFrames;
189
190 TRACE("(%p,0x%08lX,0x%08lX)\n", iface, lParam1, lParam2);
191
192 /* check parameter */
193 if ((LPVOID)lParam1 == NULL)
194 return AVIERR_BADPARAM;
195
196 /* get infos from stream */
197 IAVIStream_Info((PAVISTREAM)lParam1, &This->sInfo, sizeof(This->sInfo));
198 if (This->sInfo.fccType != streamtypeVIDEO)
199 return AVIERR_ERROR; /* error in registry or AVIMakeCompressedStream */
200
201 /* add reference to the stream */
202 This->pStream = (PAVISTREAM)lParam1;
203 IAVIStream_AddRef(This->pStream);
204
206
207 if (pco != NULL && pco->fccHandler != comptypeDIB) {
208 /* we should compress */
209 This->sInfo.fccHandler = pco->fccHandler;
210
211 This->hic = ICOpen(ICTYPE_VIDEO, pco->fccHandler, ICMODE_COMPRESS);
212 if (This->hic == NULL)
213 return AVIERR_NOCOMPRESSOR;
214
215 /* restore saved state of codec */
216 if (pco->cbParms > 0 && pco->lpParms != NULL) {
217 ICSetState(This->hic, pco->lpParms, pco->cbParms);
218 }
219
220 /* set quality -- resolve default quality */
221 This->sInfo.dwQuality = pco->dwQuality;
222 if (pco->dwQuality == ICQUALITY_DEFAULT)
223 This->sInfo.dwQuality = ICGetDefaultQuality(This->hic);
224
225 /* get capabilities of codec */
226 ICGetInfo(This->hic, &icinfo, sizeof(icinfo));
227 This->dwICMFlags = icinfo.dwFlags;
228
229 /* use keyframes? */
230 if ((pco->dwFlags & AVICOMPRESSF_KEYFRAMES) &&
232 This->lKeyFrameEvery = pco->dwKeyFrameEvery;
233 } else
234 This->lKeyFrameEvery = 1;
235
236 /* use datarate? */
237 if ((pco->dwFlags & AVICOMPRESSF_DATARATE)) {
238 /* Do we have a chance to reduce size to desired one? */
239 if ((icinfo.dwFlags & (VIDCF_CRUNCH|VIDCF_QUALITY)) == 0)
240 return AVIERR_NOCOMPRESSOR;
241
242 assert(This->sInfo.dwRate != 0);
243
244 This->dwBytesPerFrame = MulDiv(pco->dwBytesPerSecond,
245 This->sInfo.dwScale, This->sInfo.dwRate);
246 } else {
247 pco->dwBytesPerSecond = 0;
248 This->dwBytesPerFrame = 0;
249 }
250
251 if (icinfo.dwFlags & VIDCF_COMPRESSFRAMES) {
252 memset(&icFrames, 0, sizeof(icFrames));
253 icFrames.lpbiOutput = This->lpbiOutput;
254 icFrames.lpbiInput = This->lpbiInput;
255 icFrames.lFrameCount = This->sInfo.dwLength;
256 icFrames.lQuality = This->sInfo.dwQuality;
257 icFrames.lDataRate = pco->dwBytesPerSecond;
258 icFrames.lKeyRate = This->lKeyFrameEvery;
259 icFrames.dwRate = This->sInfo.dwRate;
260 icFrames.dwScale = This->sInfo.dwScale;
262 (LPARAM)&icFrames, (LPARAM)sizeof(icFrames));
263 }
264 } else
265 This->sInfo.fccHandler = comptypeDIB;
266
267 return AVIERR_OK;
268}
269
271 LONG size)
272{
274
275 TRACE("(%p,%p,%d)\n", iface, psi, size);
276
277 if (psi == NULL)
278 return AVIERR_BADPARAM;
279 if (size < 0)
280 return AVIERR_BADSIZE;
281
282 memcpy(psi, &This->sInfo, min((DWORD)size, sizeof(This->sInfo)));
283
284 if ((DWORD)size < sizeof(This->sInfo))
286 return AVIERR_OK;
287}
288
290 LONG flags)
291{
293
294 TRACE("(%p,%d,0x%08X)\n",iface,pos,flags);
295
296 if (flags & FIND_FROM_START) {
297 pos = This->sInfo.dwStart;
299 flags |= FIND_NEXT;
300 }
301
302 if (flags & FIND_RET)
303 WARN(": FIND_RET flags will be ignored!\n");
304
305 if (flags & FIND_KEY) {
306 if (This->hic == NULL)
307 return pos; /* we decompress so every frame is a keyframe */
308
309 if (flags & FIND_PREV) {
310 /* need to read old or new frames? */
311 if (This->lLastKey <= pos || pos < This->lCurrent)
312 IAVIStream_Read(iface, pos, 1, NULL, 0, NULL, NULL);
313
314 return This->lLastKey;
315 }
316 } else if (flags & FIND_ANY) {
317 return pos; /* We really don't know, reread is too expensive, so guess. */
318 } else if (flags & FIND_FORMAT) {
319 if (flags & FIND_PREV)
320 return 0;
321 }
322
323 return -1;
324}
325
327 LPVOID format, LONG *formatsize)
328{
330
332 HRESULT hr;
333
334 TRACE("(%p,%d,%p,%p)\n", iface, pos, format, formatsize);
335
336 if (formatsize == NULL)
337 return AVIERR_BADPARAM;
338
339 if (This->pg == NULL) {
341
342 if (FAILED(hr))
343 return hr;
344 }
345
346 lpbi = AVIStreamGetFrame(This->pg, pos);
347 if (lpbi == NULL)
348 return AVIERR_MEMORY;
349
350 if (This->hic == NULL) {
351 LONG size = lpbi->biSize + lpbi->biClrUsed * sizeof(RGBQUAD);
352
353 if (size > 0) {
354 if (This->sInfo.dwSuggestedBufferSize < lpbi->biSizeImage)
355 This->sInfo.dwSuggestedBufferSize = lpbi->biSizeImage;
356
357 This->cbOutput = size;
358 if (format != NULL) {
359 if (This->lpbiOutput != NULL)
360 memcpy(format, This->lpbiOutput, min(*formatsize, This->cbOutput));
361 else
362 memcpy(format, lpbi, min(*formatsize, size));
363 }
364 }
365 } else if (format != NULL)
366 memcpy(format, This->lpbiOutput, min(*formatsize, This->cbOutput));
367
368 if (*formatsize < This->cbOutput)
370 else
371 hr = AVIERR_OK;
372
373 *formatsize = This->cbOutput;
374 return hr;
375}
376
378 LPVOID format, LONG formatsize)
379{
381
382 TRACE("(%p,%d,%p,%d)\n", iface, pos, format, formatsize);
383
384 /* check parameters */
385 if (format == NULL || formatsize <= 0)
386 return AVIERR_BADPARAM;
387
388 /* We can only accept RGB data for writing */
389 if (((LPBITMAPINFOHEADER)format)->biCompression != BI_RGB) {
390 WARN(": need RGB data as input\n");
391 return AVIERR_UNSUPPORTED;
392 }
393
394 /* Input format already known?
395 * Changing of palette is supported, but be quiet if it's the same */
396 if (This->lpbiInput != NULL) {
397 if (This->cbInput != formatsize)
398 return AVIERR_UNSUPPORTED;
399
400 if (memcmp(format, This->lpbiInput, formatsize) == 0)
401 return AVIERR_OK;
402 }
403
404 /* Does the nested stream support writing? */
405 if ((This->sInfo.dwCaps & AVIFILECAPS_CANWRITE) == 0)
406 return AVIERR_READONLY;
407
408 /* check if frame is already written */
409 if (This->sInfo.dwLength + This->sInfo.dwStart > pos)
410 return AVIERR_UNSUPPORTED;
411
412 /* check if we should compress */
413 if (This->sInfo.fccHandler == 0 ||
414 This->sInfo.fccHandler == mmioFOURCC('N','O','N','E'))
415 This->sInfo.fccHandler = comptypeDIB;
416
417 /* only pass through? */
418 if (This->sInfo.fccHandler == comptypeDIB)
419 return IAVIStream_SetFormat(This->pStream, pos, format, formatsize);
420
421 /* initial format setting? */
422 if (This->lpbiInput == NULL) {
423 ULONG size;
424
425 assert(This->hic != NULL);
426
427 /* get memory for input format */
428 This->lpbiInput = HeapAlloc(GetProcessHeap(), 0, formatsize);
429 if (This->lpbiInput == NULL)
430 return AVIERR_MEMORY;
431 This->cbInput = formatsize;
432 memcpy(This->lpbiInput, format, formatsize);
433
434 /* get output format */
435 size = ICCompressGetFormatSize(This->hic, This->lpbiInput);
436 if (size < sizeof(BITMAPINFOHEADER))
437 return AVIERR_COMPRESSOR;
438 This->lpbiOutput = HeapAlloc(GetProcessHeap(), 0, size);
439 if (This->lpbiOutput == NULL)
440 return AVIERR_MEMORY;
441 This->cbOutput = size;
442 if (ICCompressGetFormat(This->hic,This->lpbiInput,This->lpbiOutput) < S_OK)
443 return AVIERR_COMPRESSOR;
444
445 /* update AVISTREAMINFO structure */
446 This->sInfo.rcFrame.right =
447 This->sInfo.rcFrame.left + This->lpbiOutput->biWidth;
448 This->sInfo.rcFrame.bottom =
449 This->sInfo.rcFrame.top + This->lpbiOutput->biHeight;
450
451 /* prepare codec for compression */
452 if (ICCompressBegin(This->hic, This->lpbiInput, This->lpbiOutput) != S_OK)
453 return AVIERR_COMPRESSOR;
454
455 /* allocate memory for compressed frame */
456 size = ICCompressGetSize(This->hic, This->lpbiInput, This->lpbiOutput);
457 This->lpbiCur = HeapAlloc(GetProcessHeap(), 0, This->cbOutput + size);
458 if (This->lpbiCur == NULL)
459 return AVIERR_MEMORY;
460 memcpy(This->lpbiCur, This->lpbiOutput, This->cbOutput);
461 This->lpCur = DIBPTR(This->lpbiCur);
462
463 /* allocate memory for last frame if needed */
464 if (This->lKeyFrameEvery != 1 &&
465 (This->dwICMFlags & VIDCF_FASTTEMPORALC) == 0) {
466 size = ICDecompressGetFormatSize(This->hic, This->lpbiOutput);
467 This->lpbiPrev = HeapAlloc(GetProcessHeap(), 0, size);
468 if (This->lpbiPrev == NULL)
469 return AVIERR_MEMORY;
470 if (ICDecompressGetFormat(This->hic, This->lpbiOutput, This->lpbiPrev) < S_OK)
471 return AVIERR_COMPRESSOR;
472
473 if (This->lpbiPrev->biSizeImage == 0) {
474 This->lpbiPrev->biSizeImage =
475 DIBWIDTHBYTES(*This->lpbiPrev) * This->lpbiPrev->biHeight;
476 }
477
478 /* get memory for format and picture */
479 size += This->lpbiPrev->biSizeImage;
480 This->lpbiPrev = HeapReAlloc(GetProcessHeap(), 0, This->lpbiPrev, size);
481 if (This->lpbiPrev == NULL)
482 return AVIERR_MEMORY;
483 This->lpPrev = DIBPTR(This->lpbiPrev);
484
485 /* prepare codec also for decompression */
486 if (ICDecompressBegin(This->hic,This->lpbiOutput,This->lpbiPrev) != S_OK)
487 return AVIERR_COMPRESSOR;
488 }
489 } else {
490 /* format change -- check that's only the palette */
492
493 if (lpbi->biSize != This->lpbiInput->biSize ||
494 lpbi->biWidth != This->lpbiInput->biWidth ||
495 lpbi->biHeight != This->lpbiInput->biHeight ||
496 lpbi->biBitCount != This->lpbiInput->biBitCount ||
497 lpbi->biPlanes != This->lpbiInput->biPlanes ||
498 lpbi->biCompression != This->lpbiInput->biCompression ||
499 lpbi->biClrUsed != This->lpbiInput->biClrUsed)
500 return AVIERR_UNSUPPORTED;
501
502 /* get new output format */
503 if (ICCompressGetFormat(This->hic, lpbi, This->lpbiOutput) < S_OK)
504 return AVIERR_BADFORMAT;
505
506 /* restart compression */
507 ICCompressEnd(This->hic);
508 if (ICCompressBegin(This->hic, lpbi, This->lpbiOutput) != S_OK)
509 return AVIERR_COMPRESSOR;
510
511 /* check if we need to restart decompression also */
512 if (This->lKeyFrameEvery != 1 &&
513 (This->dwICMFlags & VIDCF_FASTTEMPORALC) == 0) {
514 ICDecompressEnd(This->hic);
515 if (ICDecompressGetFormat(This->hic,This->lpbiOutput,This->lpbiPrev) < S_OK)
516 return AVIERR_COMPRESSOR;
517 if (ICDecompressBegin(This->hic,This->lpbiOutput,This->lpbiPrev) != S_OK)
518 return AVIERR_COMPRESSOR;
519 }
520 }
521
522 /* tell nested stream the new format */
523 return IAVIStream_SetFormat(This->pStream, pos,
524 This->lpbiOutput, This->cbOutput);
525}
526
529 LONG buffersize, LPLONG bytesread,
530 LPLONG samplesread)
531{
533
535
536 TRACE("(%p,%d,%d,%p,%d,%p,%p)\n", iface, start, samples, buffer,
537 buffersize, bytesread, samplesread);
538
539 /* clear return parameters if given */
540 if (bytesread != NULL)
541 *bytesread = 0;
542 if (samplesread != NULL)
543 *samplesread = 0;
544
545 if (samples == 0)
546 return AVIERR_OK;
547
548 /* check parameters */
549 if (samples != 1 && (bytesread == NULL && samplesread == NULL))
550 return AVIERR_BADPARAM;
551 if (samples == -1) /* read as much as we could */
552 samples = 1;
553
554 if (This->pg == NULL) {
556
557 if (FAILED(hr))
558 return hr;
559 }
560
561 /* compress or decompress? */
562 if (This->hic == NULL) {
563 /* decompress */
564 lpbi = AVIStreamGetFrame(This->pg, start);
565 if (lpbi == NULL)
566 return AVIERR_MEMORY;
567
568 if (buffer != NULL && buffersize > 0) {
569 /* check buffersize */
570 if (buffersize < lpbi->biSizeImage)
572
573 memcpy(buffer, DIBPTR(lpbi), lpbi->biSizeImage);
574 }
575
576 /* fill out return parameters if given */
577 if (bytesread != NULL)
578 *bytesread = lpbi->biSizeImage;
579 } else {
580 /* compress */
581 if (This->lCurrent > start)
583
584 while (start > This->lCurrent) {
585 HRESULT hr;
586
587 lpbi = AVIStreamGetFrame(This->pg, ++This->lCurrent);
588 if (lpbi == NULL) {
590 return AVIERR_MEMORY;
591 }
592
593 hr = AVIFILE_EncodeFrame(This, lpbi, DIBPTR(lpbi));
594 if (FAILED(hr)) {
596 return hr;
597 }
598 }
599
600 if (buffer != NULL && buffersize > 0) {
601 /* check buffersize */
602 if (This->lpbiCur->biSizeImage > buffersize)
604
605 memcpy(buffer, This->lpCur, This->lpbiCur->biSizeImage);
606 }
607
608 /* fill out return parameters if given */
609 if (bytesread != NULL)
610 *bytesread = This->lpbiCur->biSizeImage;
611 }
612
613 /* fill out return parameters if given */
614 if (samplesread != NULL)
615 *samplesread = 1;
616
617 return AVIERR_OK;
618}
619
622 LONG buffersize, DWORD flags,
623 LPLONG sampwritten,
624 LPLONG byteswritten)
625{
627
628 HRESULT hr;
629
630 TRACE("(%p,%d,%d,%p,%d,0x%08X,%p,%p)\n", iface, start, samples,
631 buffer, buffersize, flags, sampwritten, byteswritten);
632
633 /* clear return parameters if given */
634 if (sampwritten != NULL)
635 *sampwritten = 0;
636 if (byteswritten != NULL)
637 *byteswritten = 0;
638
639 /* check parameters */
640 if (buffer == NULL && (buffersize > 0 || samples > 0))
641 return AVIERR_BADPARAM;
642
643 if (This->sInfo.fccHandler == comptypeDIB) {
644 /* only pass through */
646
647 return IAVIStream_Write(This->pStream, start, samples, buffer, buffersize,
648 flags, sampwritten, byteswritten);
649 } else {
650 /* compress data before writing to pStream */
651 if (samples != 1 && (sampwritten == NULL && byteswritten == NULL))
652 return AVIERR_UNSUPPORTED;
653
654 This->lCurrent = start;
655 hr = AVIFILE_EncodeFrame(This, This->lpbiInput, buffer);
656 if (FAILED(hr))
657 return hr;
658
659 if (This->lLastKey == start)
661
662 return IAVIStream_Write(This->pStream, start, samples, This->lpCur,
663 This->lpbiCur->biSizeImage, flags, byteswritten,
664 sampwritten);
665 }
666}
667
670{
672
673 TRACE("(%p,%d,%d)\n", iface, start, samples);
674
675 return IAVIStream_Delete(This->pStream, start, samples);
676}
677
679 LPVOID lp, LPLONG lpread)
680{
682
683 TRACE("(%p,0x%08X,%p,%p)\n", iface, fcc, lp, lpread);
684
685 assert(This->pStream != NULL);
686
687 return IAVIStream_ReadData(This->pStream, fcc, lp, lpread);
688}
689
691 LPVOID lp, LONG size)
692{
694
695 TRACE("(%p,0x%08x,%p,%d)\n", iface, fcc, lp, size);
696
697 assert(This->pStream != NULL);
698
699 return IAVIStream_WriteData(This->pStream, fcc, lp, size);
700}
701
703 LPAVISTREAMINFOW info, LONG infolen)
704{
705 FIXME("(%p,%p,%d): stub\n", iface, info, infolen);
706
707 return E_FAIL;
708}
709
710static const struct IAVIStreamVtbl iicmst = {
725};
726
728{
729 IAVIStreamImpl *pstream;
730 HRESULT hr;
731
732 assert(riid != NULL && ppv != NULL);
733
734 *ppv = NULL;
735
737 if (pstream == NULL)
738 return AVIERR_MEMORY;
739
740 pstream->IAVIStream_iface.lpVtbl = &iicmst;
741 AVIFILE_Reset(pstream);
742
744 if (FAILED(hr))
745 HeapFree(GetProcessHeap(), 0, pstream);
746
747 return hr;
748}
749
750/***********************************************************************/
751
753 LPBITMAPINFOHEADER lpbi, LPVOID lpBits)
754{
755 DWORD dwMinQual, dwMaxQual, dwCurQual;
756 DWORD dwRequest;
757 DWORD icmFlags = 0;
758 DWORD idxFlags = 0;
759 BOOL bDecreasedQual = FALSE;
760 BOOL doSizeCheck;
761 BOOL noPrev;
762
763 /* make lKeyFrameEvery and at start a keyframe */
764 if ((This->lKeyFrameEvery != 0 &&
765 (This->lCurrent - This->lLastKey) >= This->lKeyFrameEvery) ||
766 This->lCurrent == This->sInfo.dwStart) {
767 idxFlags = AVIIF_KEYFRAME;
768 icmFlags = ICCOMPRESS_KEYFRAME;
769 }
770
771 if (This->lKeyFrameEvery != 0) {
772 if (This->lCurrent == This->sInfo.dwStart) {
773 if (idxFlags & AVIIF_KEYFRAME) {
774 /* allow keyframes to consume all unused bytes */
775 dwRequest = This->dwBytesPerFrame + This->dwUnusedBytes;
776 This->dwUnusedBytes = 0;
777 } else {
778 /* for non-keyframes only allow some of the unused bytes to be consumed */
779 DWORD tmp1 = 0;
780 DWORD tmp2;
781
782 if (This->dwBytesPerFrame >= This->dwUnusedBytes)
783 tmp1 = This->dwBytesPerFrame / This->lKeyFrameEvery;
784 tmp2 = (This->dwUnusedBytes + tmp1) / This->lKeyFrameEvery;
785
786 dwRequest = This->dwBytesPerFrame - tmp1 + tmp2;
787 This->dwUnusedBytes -= tmp2;
788 }
789 } else
790 dwRequest = MAX_FRAMESIZE;
791 } else {
792 /* only one keyframe at start desired */
793 if (This->lCurrent == This->sInfo.dwStart) {
794 dwRequest = This->dwBytesPerFrame + This->dwUnusedBytes;
795 This->dwUnusedBytes = 0;
796 } else
797 dwRequest = MAX_FRAMESIZE;
798 }
799
800 /* must we check for frame size to gain the requested
801 * data rate or can we trust the codec? */
802 doSizeCheck = (dwRequest != 0 && ((This->dwICMFlags & (VIDCF_CRUNCH|VIDCF_QUALITY)) == 0));
803
804 dwMaxQual = dwCurQual = This->sInfo.dwQuality;
805 dwMinQual = ICQUALITY_LOW;
806
807 noPrev = TRUE;
808 if ((icmFlags & ICCOMPRESS_KEYFRAME) == 0 &&
809 (This->dwICMFlags & VIDCF_FASTTEMPORALC) == 0)
810 noPrev = FALSE;
811
812 do {
813 DWORD idxCkid = 0;
814 DWORD res;
815
816 res = ICCompress(This->hic,icmFlags,This->lpbiCur,This->lpCur,lpbi,lpBits,
817 &idxCkid, &idxFlags, This->lCurrent, dwRequest, dwCurQual,
818 noPrev ? NULL:This->lpbiPrev, noPrev ? NULL:This->lpPrev);
819 if (res == ICERR_NEWPALETTE) {
820 FIXME(": codec has changed palette -- unhandled!\n");
821 } else if (res != ICERR_OK)
822 return AVIERR_COMPRESSOR;
823
824 /* need to check for framesize */
825 if (! doSizeCheck)
826 break;
827
828 if (dwRequest >= This->lpbiCur->biSizeImage) {
829 /* frame is smaller -- try to maximize quality */
830 if (dwMaxQual - dwCurQual > 10) {
831 DWORD tmp = dwRequest / 8;
832
833 if (tmp < MAX_FRAMESIZE_DIFF)
834 tmp = MAX_FRAMESIZE_DIFF;
835
836 if (tmp < dwRequest - This->lpbiCur->biSizeImage && bDecreasedQual) {
837 tmp = dwCurQual;
838 dwCurQual = (dwMinQual + dwMaxQual) / 2;
839 dwMinQual = tmp;
840 continue;
841 }
842 } else
843 break;
844 } else if (dwMaxQual - dwMinQual <= 1) {
845 break;
846 } else {
847 dwMaxQual = dwCurQual;
848
849 if (bDecreasedQual || dwCurQual == This->dwLastQuality)
850 dwCurQual = (dwMinQual + dwMaxQual) / 2;
851 else
852 FIXME(": no new quality computed min=%u cur=%u max=%u last=%u\n",
853 dwMinQual, dwCurQual, dwMaxQual, This->dwLastQuality);
854
855 bDecreasedQual = TRUE;
856 }
857 } while (TRUE);
858
859 /* remember some values */
860 This->dwLastQuality = dwCurQual;
861 This->dwUnusedBytes = dwRequest - This->lpbiCur->biSizeImage;
862 if (icmFlags & ICCOMPRESS_KEYFRAME)
863 This->lLastKey = This->lCurrent;
864
865 /* Does we manage previous frame? */
866 if (This->lpPrev != NULL && This->lKeyFrameEvery != 1)
867 ICDecompress(This->hic, 0, This->lpbiCur, This->lpCur,
868 This->lpbiPrev, This->lpPrev);
869
870 return AVIERR_OK;
871}
872
874{
876 DWORD size;
877
878 /* pre-conditions */
879 assert(This != NULL);
880 assert(This->pStream != NULL);
881 assert(This->pg == NULL);
882
883 This->pg = AVIStreamGetFrameOpen(This->pStream, NULL);
884 if (This->pg == NULL)
885 return AVIERR_ERROR;
886
887 /* When we only decompress this is enough */
888 if (This->sInfo.fccHandler == comptypeDIB)
889 return AVIERR_OK;
890
891 assert(This->hic != NULL);
892 assert(This->lpbiOutput == NULL);
893
894 /* get input format */
895 lpbi = AVIStreamGetFrame(This->pg, This->sInfo.dwStart);
896 if (lpbi == NULL)
897 return AVIERR_MEMORY;
898
899 /* get memory for output format */
900 size = ICCompressGetFormatSize(This->hic, lpbi);
901 if ((LONG)size < (LONG)sizeof(BITMAPINFOHEADER))
902 return AVIERR_COMPRESSOR;
903 This->lpbiOutput = HeapAlloc(GetProcessHeap(), 0, size);
904 if (This->lpbiOutput == NULL)
905 return AVIERR_MEMORY;
906 This->cbOutput = size;
907
908 if (ICCompressGetFormat(This->hic, lpbi, This->lpbiOutput) < S_OK)
909 return AVIERR_BADFORMAT;
910
911 /* update AVISTREAMINFO structure */
912 This->sInfo.rcFrame.right =
913 This->sInfo.rcFrame.left + This->lpbiOutput->biWidth;
914 This->sInfo.rcFrame.bottom =
915 This->sInfo.rcFrame.top + This->lpbiOutput->biHeight;
916 This->sInfo.dwSuggestedBufferSize =
917 ICCompressGetSize(This->hic, lpbi, This->lpbiOutput);
918
919 /* prepare codec for compression */
920 if (ICCompressBegin(This->hic, lpbi, This->lpbiOutput) != S_OK)
921 return AVIERR_COMPRESSOR;
922
923 /* allocate memory for current frame */
924 size += This->sInfo.dwSuggestedBufferSize;
925 This->lpbiCur = HeapAlloc(GetProcessHeap(), 0, size);
926 if (This->lpbiCur == NULL)
927 return AVIERR_MEMORY;
928 memcpy(This->lpbiCur, This->lpbiOutput, This->cbOutput);
929 This->lpCur = DIBPTR(This->lpbiCur);
930
931 /* allocate memory for last frame if needed */
932 if (This->lKeyFrameEvery != 1 &&
933 (This->dwICMFlags & VIDCF_FASTTEMPORALC) == 0) {
934 size = ICDecompressGetFormatSize(This->hic, This->lpbiOutput);
935 This->lpbiPrev = HeapAlloc(GetProcessHeap(), 0, size);
936 if (This->lpbiPrev == NULL)
937 return AVIERR_MEMORY;
938 if (ICDecompressGetFormat(This->hic, This->lpbiOutput, This->lpbiPrev) < S_OK)
939 return AVIERR_COMPRESSOR;
940
941 if (This->lpbiPrev->biSizeImage == 0) {
942 This->lpbiPrev->biSizeImage =
943 DIBWIDTHBYTES(*This->lpbiPrev) * This->lpbiPrev->biHeight;
944 }
945
946 /* get memory for format and picture */
947 size += This->lpbiPrev->biSizeImage;
948 This->lpbiPrev = HeapReAlloc(GetProcessHeap(), 0, This->lpbiPrev, size );
949 if (This->lpbiPrev == NULL)
950 return AVIERR_MEMORY;
951 This->lpPrev = DIBPTR(This->lpbiPrev);
952
953 /* prepare codec also for decompression */
954 if (ICDecompressBegin(This->hic,This->lpbiOutput,This->lpbiPrev) != S_OK)
955 return AVIERR_COMPRESSOR;
956 }
957
958 return AVIERR_OK;
959}
int memcmp(void *Buffer1, void *Buffer2, ACPI_SIZE Count)
Definition: utclib.c:112
#define InterlockedIncrement
Definition: armddk.h:53
#define InterlockedDecrement
Definition: armddk.h:52
#define DIBPTR(lp)
#define DIBWIDTHBYTES(bi)
#define AVIIF_KEYFRAME
Definition: aviriff.h:131
#define streamtypeVIDEO
Definition: aviriff.h:92
static const WCHAR avifile[]
Definition: avisplitter.c:273
#define WINE_DEFAULT_DEBUG_CHANNEL(t)
Definition: precomp.h:23
const GUID IID_IUnknown
#define FIXME(fmt,...)
Definition: debug.h:111
#define WARN(fmt,...)
Definition: debug.h:112
#define E_FAIL
Definition: ddrawi.h:102
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
PGETFRAME WINAPI AVIStreamGetFrameOpen(PAVISTREAM pstream, LPBITMAPINFOHEADER lpbiWanted)
Definition: api.c:639
HRESULT WINAPI AVIStreamGetFrameClose(PGETFRAME pg)
Definition: api.c:677
LPVOID WINAPI AVIStreamGetFrame(PGETFRAME pg, LONG pos)
Definition: api.c:664
#define GetProcessHeap()
Definition: compat.h:736
#define HeapAlloc
Definition: compat.h:733
#define HeapReAlloc
Definition: compat.h:734
#define HeapFree(x, y, z)
Definition: compat.h:735
#define HEAP_ZERO_MEMORY
Definition: compat.h:134
#define assert(x)
Definition: debug.h:53
#define BI_RGB
Definition: precomp.h:47
ULONG RGBQUAD
Definition: precomp.h:50
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
GLuint start
Definition: gl.h:1545
GLint GLint GLsizei GLsizei GLsizei GLint GLenum format
Definition: gl.h:1546
GLsizeiptr size
Definition: glext.h:5919
GLsizei samples
Definition: glext.h:7006
GLuint res
Definition: glext.h:9613
GLuint buffer
Definition: glext.h:5915
GLbitfield flags
Definition: glext.h:7161
static HRESULT WINAPI ICMStream_fnReadFormat(IAVIStream *iface, LONG pos, LPVOID format, LONG *formatsize)
Definition: icmstream.c:326
static HRESULT WINAPI ICMStream_fnReadData(IAVIStream *iface, DWORD fcc, LPVOID lp, LPLONG lpread)
Definition: icmstream.c:678
static HRESULT WINAPI ICMStream_fnWrite(IAVIStream *iface, LONG start, LONG samples, LPVOID buffer, LONG buffersize, DWORD flags, LPLONG sampwritten, LPLONG byteswritten)
Definition: icmstream.c:620
static void AVIFILE_Reset(IAVIStreamImpl *This)
Definition: icmstream.c:83
static LONG WINAPI ICMStream_fnFindSample(IAVIStream *iface, LONG pos, LONG flags)
Definition: icmstream.c:289
static HRESULT WINAPI ICMStream_fnQueryInterface(IAVIStream *iface, REFIID refiid, LPVOID *obj)
Definition: icmstream.c:91
#define MAX_FRAMESIZE_DIFF
Definition: icmstream.c:37
static HRESULT WINAPI ICMStream_fnRead(IAVIStream *iface, LONG start, LONG samples, LPVOID buffer, LONG buffersize, LPLONG bytesread, LPLONG samplesread)
Definition: icmstream.c:527
struct _IAVIStreamImpl IAVIStreamImpl
static const struct IAVIStreamVtbl iicmst
Definition: icmstream.c:710
HRESULT AVIFILE_CreateICMStream(REFIID riid, LPVOID *ppv)
Definition: icmstream.c:727
static HRESULT WINAPI ICMStream_fnSetInfo(IAVIStream *iface, LPAVISTREAMINFOW info, LONG infolen)
Definition: icmstream.c:702
static ULONG WINAPI ICMStream_fnRelease(IAVIStream *iface)
Definition: icmstream.c:123
static IAVIStreamImpl * impl_from_IAVIStream(IAVIStream *iface)
Definition: icmstream.c:78
static HRESULT WINAPI ICMStream_fnDelete(IAVIStream *iface, LONG start, LONG samples)
Definition: icmstream.c:668
static HRESULT WINAPI ICMStream_fnInfo(IAVIStream *iface, LPAVISTREAMINFOW psi, LONG size)
Definition: icmstream.c:270
static HRESULT AVIFILE_OpenGetFrame(IAVIStreamImpl *This)
Definition: icmstream.c:873
static HRESULT WINAPI ICMStream_fnSetFormat(IAVIStream *iface, LONG pos, LPVOID format, LONG formatsize)
Definition: icmstream.c:377
static ULONG WINAPI ICMStream_fnAddRef(IAVIStream *iface)
Definition: icmstream.c:109
static HRESULT WINAPI ICMStream_fnWriteData(IAVIStream *iface, DWORD fcc, LPVOID lp, LONG size)
Definition: icmstream.c:690
static HRESULT WINAPI ICMStream_fnCreate(IAVIStream *iface, LPARAM lParam1, LPARAM lParam2)
Definition: icmstream.c:181
#define MAX_FRAMESIZE
Definition: icmstream.c:36
static HRESULT AVIFILE_EncodeFrame(IAVIStreamImpl *This, LPBITMAPINFOHEADER lpbi, LPVOID lpBits)
Definition: icmstream.c:752
REFIID riid
Definition: atlbase.h:39
REFIID LPVOID * ppv
Definition: atlbase.h:39
#define S_OK
Definition: intsafe.h:52
#define FAILED(hr)
Definition: intsafe.h:51
#define debugstr_guid
Definition: kernel32.h:35
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
#define ICTYPE_VIDEO
Definition: mmreg.h:531
#define mmioFOURCC(c0, c1, c2, c3)
Definition: mmsystem.h:38
#define min(a, b)
Definition: monoChain.cc:55
HIC VFWAPI ICOpen(DWORD fccType, DWORD fccHandler, UINT wMode)
Definition: msvideo_main.c:441
DWORD VFWAPIV ICDecompress(HIC hic, DWORD dwFlags, LPBITMAPINFOHEADER lpbiFormat, LPVOID lpData, LPBITMAPINFOHEADER lpbi, LPVOID lpBits)
Definition: msvideo_main.c:827
LRESULT VFWAPI ICSendMessage(HIC hic, UINT msg, DWORD_PTR lParam1, DWORD_PTR lParam2)
LRESULT VFWAPI ICGetInfo(HIC hic, ICINFO *picinfo, DWORD cb)
Definition: msvideo_main.c:594
DWORD VFWAPIV ICCompress(HIC hic, DWORD dwFlags, LPBITMAPINFOHEADER lpbiOutput, LPVOID lpData, LPBITMAPINFOHEADER lpbiInput, LPVOID lpBits, LPDWORD lpckid, LPDWORD lpdwFlags, LONG lFrameNum, DWORD dwFrameSize, DWORD dwQuality, LPBITMAPINFOHEADER lpbiPrev, LPVOID lpPrev)
Definition: msvideo_main.c:797
INT WINAPI MulDiv(INT nNumber, INT nNumerator, INT nDenominator)
Definition: muldiv.c:25
long LONG
Definition: pedump.c:60
#define IsEqualGUID(rguid1, rguid2)
Definition: guiddef.h:147
#define REFIID
Definition: guiddef.h:118
#define memset(x, y, z)
Definition: compat.h:39
HRESULT hr
Definition: shlfolder.c:183
#define TRACE(s)
Definition: solgame.cpp:4
DWORD biCompression
Definition: amvideo.idl:35
DWORD biSizeImage
Definition: amvideo.idl:36
LONG lKeyRate
Definition: vfw.h:244
DWORD dwScale
Definition: vfw.h:246
LPBITMAPINFOHEADER lpbiInput
Definition: vfw.h:238
DWORD dwRate
Definition: vfw.h:245
LONG lDataRate
Definition: vfw.h:243
LONG lQuality
Definition: vfw.h:242
LONG lFrameCount
Definition: vfw.h:241
LPBITMAPINFOHEADER lpbiOutput
Definition: vfw.h:236
Definition: vfw.h:280
DWORD dwFlags
Definition: vfw.h:284
DWORD dwUnusedBytes
Definition: icmstream.c:59
LPBITMAPINFOHEADER lpbiOutput
Definition: icmstream.c:66
DWORD dwLastQuality
Definition: icmstream.c:57
LPBITMAPINFOHEADER lpbiCur
Definition: icmstream.c:61
LPVOID lpCur
Definition: icmstream.c:62
PGETFRAME pg
Definition: icmstream.c:50
IAVIStream IAVIStream_iface
Definition: acmstream.c:41
PAVISTREAM pStream
Definition: acmstream.c:45
DWORD dwICMFlags
Definition: icmstream.c:52
LONG lKeyFrameEvery
Definition: icmstream.c:56
LPBITMAPINFOHEADER lpbiPrev
Definition: icmstream.c:63
LPBITMAPINFOHEADER lpbiInput
Definition: icmstream.c:68
AVISTREAMINFOW sInfo
Definition: acmstream.c:46
LPVOID lpPrev
Definition: icmstream.c:64
DWORD dwBytesPerFrame
Definition: icmstream.c:58
Definition: send.c:48
int32_t * LPLONG
Definition: typedefs.h:58
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260
uint32_t ULONG
Definition: typedefs.h:59
#define IAVIStream_SetFormat(p, a, b, c)
Definition: vfw.h:1183
#define FIND_NEXT
Definition: vfw.h:1118
#define comptypeDIB
Definition: vfw.h:147
#define ICQUALITY_LOW
Definition: vfw.h:276
#define VIDCF_CRUNCH
Definition: vfw.h:298
#define ICERR_NEWPALETTE
Definition: vfw.h:52
#define IAVIStream_AddRef(p)
Definition: vfw.h:1176
#define AVIERR_NOCOMPRESSOR
Definition: vfw.h:1755
#define IAVIStream_WriteData(p, a, b, c)
Definition: vfw.h:1188
#define ICCompressGetSize(hic, lpbiInput, lpbiOutput)
Definition: vfw.h:218
#define IAVIStream_QueryInterface(p, a, b)
Definition: vfw.h:1175
#define AVIERR_UNSUPPORTED
Definition: vfw.h:1743
#define IAVIStream_Delete(p, a, b)
Definition: vfw.h:1186
#define VIDCF_COMPRESSFRAMES
Definition: vfw.h:300
#define AVIERR_ERROR
Definition: vfw.h:1761
#define ICERR_OK
Definition: vfw.h:50
#define ICQUALITY_DEFAULT
Definition: vfw.h:278
#define VIDCF_QUALITY
Definition: vfw.h:297
#define ICQUALITY_HIGH
Definition: vfw.h:277
#define FIND_PREV
Definition: vfw.h:1119
#define AVICOMPRESSF_KEYFRAMES
Definition: vfw.h:1100
#define AVICOMPRESSF_DATARATE
Definition: vfw.h:1099
#define AVIERR_BADSIZE
Definition: vfw.h:1749
#define ICCompressGetFormat(hic, lpbiInput, lpbiOutput)
Definition: vfw.h:204
#define IAVIStream_Read(p, a, b, c, d, e, f)
Definition: vfw.h:1184
#define ICSetState(hic, pv, cb)
Definition: vfw.h:632
#define AVIERR_BADFORMAT
Definition: vfw.h:1744
#define AVIFILECAPS_CANWRITE
Definition: vfw.h:1061
#define FIND_ANY
Definition: vfw.h:1124
#define VIDCF_FASTTEMPORALC
Definition: vfw.h:302
#define FIND_FROM_START
Definition: vfw.h:1120
#define ICMODE_COMPRESS
Definition: vfw.h:268
#define AVIERR_READONLY
Definition: vfw.h:1756
#define AVIERR_OK
Definition: vfw.h:1740
#define ICCOMPRESS_KEYFRAME
Definition: vfw.h:170
#define VIDCF_TEMPORAL
Definition: vfw.h:299
#define ICDecompressBegin(hic, lpbiInput, lpbiOutput)
Definition: vfw.h:371
#define FIND_RET
Definition: vfw.h:1127
struct AVICOMPRESSOPTIONS * LPAVICOMPRESSOPTIONS
#define IAVIStream_ReadData(p, a, b, c)
Definition: vfw.h:1187
#define ICDecompressGetFormatSize(hic, lpbi)
Definition: vfw.h:389
#define ICDecompressGetFormat(hic, lpbiInput, lpbiOutput)
Definition: vfw.h:383
#define ICDecompressEnd(hic)
Definition: vfw.h:404
#define ICCompressEnd(hic)
Definition: vfw.h:230
#define ICCompressBegin(hic, lpbiInput, lpbiOutput)
Definition: vfw.h:212
#define AVIERR_COMPRESSOR
Definition: vfw.h:1754
struct IAVIStream * PAVISTREAM
Definition: vfw.h:38
#define ICM_COMPRESS_FRAMES_INFO
Definition: vfw.h:143
#define AVIERR_MEMORY
Definition: vfw.h:1745
#define FIND_KEY
Definition: vfw.h:1123
#define AVIERR_BUFFERTOOSMALL
Definition: vfw.h:1758
static DWORD ICGetDefaultQuality(HIC hic)
Definition: vfw.h:637
#define IAVIStream_Write(p, a, b, c, d, e, f, g)
Definition: vfw.h:1185
#define IAVIStream_Release(p)
Definition: vfw.h:1177
#define IAVIStream_Info(p, a, b)
Definition: vfw.h:1180
#define FIND_FORMAT
Definition: vfw.h:1125
#define AVIERR_BADPARAM
Definition: vfw.h:1748
#define ICCompressGetFormatSize(hic, lpbi)
Definition: vfw.h:210
struct IGetFrame * PGETFRAME
Definition: vfw.h:40
_In_ SURFOBJ _In_ CLIPOBJ * pco
Definition: winddi.h:3415
LONG_PTR LPARAM
Definition: windef.h:208
#define WINAPI
Definition: msvc.h:6
#define OLE_E_ENUM_NOMORE
Definition: winerror.h:2616