2 * Copyright 2003 Michael Günnewig
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.
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.
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 #define COM_NO_WINDOWS_H
33 #include "avifile_private.h"
34 #include "extrachunk.h"
36 #include "wine/debug.h"
38 WINE_DEFAULT_DEBUG_CHANNEL(avifile);
40 /***********************************************************************/
42 /* internal interface to get access to table of stream in an editable stream */
43 typedef struct IEditStreamInternal IEditStreamInternal;
45 typedef struct _EditStreamTable {
46 PAVISTREAM pStream; /* stream which contains the data */
47 DWORD dwStart; /* where starts the part which is also our */
48 DWORD dwLength; /* how many is also in this stream */
51 #define INTERFACE IEditStreamInternal
52 #define IEditStreamInternal_METHODS \
54 STDMETHOD(GetEditStreamImpl)(THIS_ LPVOID*) PURE;
55 ICOM_DEFINE(IEditStreamInternal, IUnknown)
58 #define EditStreamEnd(This,streamNr) ((This)->pStreams[streamNr].dwStart + \
59 (This)->pStreams[streamNr].dwLength)
61 /***********************************************************************/
63 static HRESULT WINAPI IAVIEditStream_fnQueryInterface(IAVIEditStream*iface,REFIID refiid,LPVOID *obj);
64 static ULONG WINAPI IAVIEditStream_fnAddRef(IAVIEditStream*iface);
65 static ULONG WINAPI IAVIEditStream_fnRelease(IAVIEditStream*iface);
66 static HRESULT WINAPI IAVIEditStream_fnCut(IAVIEditStream*iface,LONG*plStart,
67 LONG*plLength,PAVISTREAM*ppResult);
68 static HRESULT WINAPI IAVIEditStream_fnCopy(IAVIEditStream*iface,LONG*plStart,
69 LONG*plLength,PAVISTREAM*ppResult);
70 static HRESULT WINAPI IAVIEditStream_fnPaste(IAVIEditStream*iface,LONG*plStart,
71 LONG*plLength,PAVISTREAM pSource,
72 LONG lStart,LONG lEnd);
73 static HRESULT WINAPI IAVIEditStream_fnClone(IAVIEditStream*iface,
75 static HRESULT WINAPI IAVIEditStream_fnSetInfo(IAVIEditStream*iface,
76 LPAVISTREAMINFOW asi,LONG size);
78 struct ICOM_VTABLE(IAVIEditStream) ieditstream = {
79 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
80 IAVIEditStream_fnQueryInterface,
81 IAVIEditStream_fnAddRef,
82 IAVIEditStream_fnRelease,
84 IAVIEditStream_fnCopy,
85 IAVIEditStream_fnPaste,
86 IAVIEditStream_fnClone,
87 IAVIEditStream_fnSetInfo
90 static HRESULT WINAPI IEditAVIStream_fnQueryInterface(IAVIStream*iface,REFIID refiid,LPVOID*obj);
91 static ULONG WINAPI IEditAVIStream_fnAddRef(IAVIStream*iface);
92 static ULONG WINAPI IEditAVIStream_fnRelease(IAVIStream*iface);
93 static HRESULT WINAPI IEditAVIStream_fnCreate(IAVIStream*iface,LPARAM lParam1,LPARAM lParam2);
94 static HRESULT WINAPI IEditAVIStream_fnInfo(IAVIStream*iface,AVISTREAMINFOW *psi,LONG size);
95 static LONG WINAPI IEditAVIStream_fnFindSample(IAVIStream*iface,LONG pos,
97 static HRESULT WINAPI IEditAVIStream_fnReadFormat(IAVIStream*iface,LONG pos,LPVOID format,LONG*formatsize);
98 static HRESULT WINAPI IEditAVIStream_fnSetFormat(IAVIStream*iface,LONG pos,LPVOID format,LONG formatsize);
99 static HRESULT WINAPI IEditAVIStream_fnRead(IAVIStream*iface,LONG start,
100 LONG samples,LPVOID buffer,
101 LONG buffersize,LONG*bytesread,
103 static HRESULT WINAPI IEditAVIStream_fnWrite(IAVIStream*iface,LONG start,
104 LONG samples,LPVOID buffer,
105 LONG buffersize,DWORD flags,
106 LONG*sampwritten,LONG*byteswritten);
107 static HRESULT WINAPI IEditAVIStream_fnDelete(IAVIStream*iface,LONG start,LONG samples);
108 static HRESULT WINAPI IEditAVIStream_fnReadData(IAVIStream*iface,DWORD fcc,
109 LPVOID lp,LONG *lpread);
110 static HRESULT WINAPI IEditAVIStream_fnWriteData(IAVIStream*iface,DWORD fcc,
111 LPVOID lp,LONG size);
112 static HRESULT WINAPI IEditAVIStream_fnSetInfo(IAVIStream*iface,AVISTREAMINFOW*info,LONG infolen);
114 struct ICOM_VTABLE(IAVIStream) ieditstast = {
115 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
116 IEditAVIStream_fnQueryInterface,
117 IEditAVIStream_fnAddRef,
118 IEditAVIStream_fnRelease,
119 IEditAVIStream_fnCreate,
120 IEditAVIStream_fnInfo,
121 IEditAVIStream_fnFindSample,
122 IEditAVIStream_fnReadFormat,
123 IEditAVIStream_fnSetFormat,
124 IEditAVIStream_fnRead,
125 IEditAVIStream_fnWrite,
126 IEditAVIStream_fnDelete,
127 IEditAVIStream_fnReadData,
128 IEditAVIStream_fnWriteData,
129 IEditAVIStream_fnSetInfo
132 static HRESULT WINAPI IEditStreamInternal_fnQueryInterface(IEditStreamInternal*iface,REFIID refiid,LPVOID*obj);
133 static ULONG WINAPI IEditStreamInternal_fnAddRef(IEditStreamInternal*iface);
134 static ULONG WINAPI IEditStreamInternal_fnRelease(IEditStreamInternal*iface);
135 static HRESULT WINAPI IEditStreamInternal_fnGetEditStreamImpl(IEditStreamInternal*iface,LPVOID*ppimpl);
137 struct ICOM_VTABLE(IEditStreamInternal) ieditstreaminternal = {
138 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
139 IEditStreamInternal_fnQueryInterface,
140 IEditStreamInternal_fnAddRef,
141 IEditStreamInternal_fnRelease,
142 IEditStreamInternal_fnGetEditStreamImpl
145 typedef struct _IAVIEditStreamImpl IAVIEditStreamImpl;
147 typedef struct _IEditAVIStreamImpl {
149 ICOM_VFIELD(IAVIStream);
151 /* IAVIStream stuff */
152 IAVIEditStreamImpl *pae;
153 } IEditAVIStreamImpl;
155 typedef struct _IEditStreamInternalImpl {
157 ICOM_VFIELD(IEditStreamInternal);
159 /* IEditStreamInternal stuff */
160 IAVIEditStreamImpl *pae;
161 } IEditStreamInternalImpl;
163 struct _IAVIEditStreamImpl {
165 ICOM_VFIELD(IAVIEditStream);
168 /* IAVIEditStream stuff */
169 IEditAVIStreamImpl iAVIStream;
170 IEditStreamInternalImpl iEditStreamInternal;
172 AVISTREAMINFOW sInfo;
174 EditStreamTable *pStreams;
175 DWORD nStreams; /* current fill level of pStreams table */
176 DWORD nTableSize; /* size of pStreams table */
179 PAVISTREAM pCurStream;
180 PGETFRAME pg; /* IGetFrame for pCurStream */
181 LPBITMAPINFOHEADER lpFrame; /* frame of pCurStream */
184 /***********************************************************************/
186 PAVIEDITSTREAM AVIFILE_CreateEditStream(PAVISTREAM pstream)
188 IAVIEditStreamImpl *pedit = NULL;
190 pedit = (IAVIEditStreamImpl*)LocalAlloc(LPTR,sizeof(IAVIEditStreamImpl));
194 pedit->lpVtbl = &ieditstream;
195 pedit->iAVIStream.lpVtbl = &ieditstast;
196 pedit->iAVIStream.pae = pedit;
197 pedit->iEditStreamInternal.lpVtbl = &ieditstreaminternal;
198 pedit->iEditStreamInternal.pae = pedit;
201 IAVIStream_Create((PAVISTREAM)&pedit->iAVIStream,(LPARAM)pstream,0);
203 return (PAVIEDITSTREAM)pedit;
206 static HRESULT AVIFILE_FindStreamInTable(IAVIEditStreamImpl* const This,
207 DWORD pos,PAVISTREAM *ppStream,
209 DWORD* streamNr,BOOL bFindSample)
213 TRACE("(%p,%lu,%p,%p,%p,%d)",This,pos,ppStream,streamPos,
214 streamNr,bFindSample);
216 if (pos < This->sInfo.dwStart)
217 return AVIERR_BADPARAM;
219 pos -= This->sInfo.dwStart;
220 for (n = 0; n < This->nStreams; n++) {
221 if (pos < This->pStreams[n].dwLength) {
222 *ppStream = This->pStreams[n].pStream;
223 *streamPos = This->pStreams[n].dwStart + pos;
224 if (streamNr != NULL)
229 pos -= This->pStreams[n].dwLength;
231 if (pos == 0 && bFindSample) {
232 *ppStream = This->pStreams[--n].pStream;
233 *streamPos = EditStreamEnd(This, n);
234 if (streamNr != NULL)
237 TRACE(" -- pos=0 && b=1 -> (%p,%lu,%lu)\n",*ppStream, *streamPos, n);
242 if (streamNr != NULL)
245 TRACE(" -> ERROR (NULL,0,0)\n");
246 return AVIERR_BADPARAM;
250 static LPVOID AVIFILE_ReadFrame(IAVIEditStreamImpl* const This,
251 PAVISTREAM pstream, LONG pos)
255 TRACE("(%p,%p,%ld)\n",This,pstream,pos);
260 /* if stream changes make sure that only palette changes */
261 if (This->pCurStream != pstream) {
262 pg = AVIStreamGetFrameOpen(pstream, NULL);
265 if (This->pg != NULL) {
266 if (IGetFrame_SetFormat(pg, This->lpFrame, NULL, 0, 0, -1, -1)) {
267 AVIStreamGetFrameClose(pg);
268 ERR(": IGetFrame_SetFormat failed\n");
271 AVIStreamGetFrameClose(This->pg);
274 This->pCurStream = pstream;
277 /* now get the decompressed frame */
278 This->lpFrame = AVIStreamGetFrame(This->pg, pos);
279 if (This->lpFrame != NULL)
280 This->sInfo.dwSuggestedBufferSize = This->lpFrame->biSizeImage;
282 return This->lpFrame;
285 static HRESULT AVIFILE_RemoveStream(IAVIEditStreamImpl* const This, DWORD nr)
287 assert(This != NULL);
288 assert(nr < This->nStreams);
291 IAVIStream_Release(This->pStreams[nr].pStream);
293 if (This->nStreams - nr > 0) {
294 memmove(This->pStreams + nr, This->pStreams + nr + 1,
295 (This->nStreams - nr) * sizeof(EditStreamTable));
297 This->pStreams[This->nStreams].pStream = NULL;
298 This->pStreams[This->nStreams].dwStart = 0;
299 This->pStreams[This->nStreams].dwLength = 0;
301 /* try to merge the part before the deleted one and the one after it */
302 if (0 < nr && 0 < This->nStreams &&
303 This->pStreams[nr - 1].pStream == This->pStreams[nr].pStream) {
304 if (EditStreamEnd(This, nr - 1) == This->pStreams[nr].dwStart) {
305 This->pStreams[nr - 1].dwLength += This->pStreams[nr].dwLength;
306 return AVIFILE_RemoveStream(This, nr);
313 static BOOL AVIFILE_FormatsEqual(PAVISTREAM avi1, PAVISTREAM avi2)
315 LPVOID fmt1 = NULL, fmt2 = NULL;
316 LONG size1, size2, start1, start2;
319 assert(avi1 != NULL && avi2 != NULL);
321 /* get stream starts and check format sizes */
322 start1 = AVIStreamStart(avi1);
323 start2 = AVIStreamStart(avi2);
324 if (FAILED(AVIStreamFormatSize(avi1, start1, &size1)))
326 if (FAILED(AVIStreamFormatSize(avi2, start2, &size2)))
331 /* sizes match, now get formats and compare them */
332 fmt1 = GlobalAllocPtr(GHND, size1);
335 if (SUCCEEDED(AVIStreamReadFormat(avi1, start1, fmt1, &size1))) {
336 fmt2 = GlobalAllocPtr(GHND, size1);
338 if (SUCCEEDED(AVIStreamReadFormat(avi2, start2, fmt2, &size1)))
339 status = memcmp(fmt1, fmt2, size1);
350 /***********************************************************************/
352 static HRESULT WINAPI IAVIEditStream_fnQueryInterface(IAVIEditStream*iface,REFIID refiid,LPVOID *obj)
354 ICOM_THIS(IAVIEditStreamImpl,iface);
356 TRACE("(%p,%s,%p)\n", This, debugstr_guid(refiid), obj);
358 if (IsEqualGUID(&IID_IUnknown, refiid) ||
359 IsEqualGUID(&IID_IAVIEditStream, refiid)) {
361 IAVIEditStream_AddRef(iface);
364 } else if (IsEqualGUID(&IID_IAVIStream, refiid)) {
365 *obj = &This->iAVIStream;
366 IAVIEditStream_AddRef(iface);
369 } else if (IsEqualGUID(&IID_IEditStreamInternal, refiid)) {
370 *obj = &This->iEditStreamInternal;
371 IAVIEditStream_AddRef(iface);
376 return OLE_E_ENUM_NOMORE;
379 static ULONG WINAPI IAVIEditStream_fnAddRef(IAVIEditStream*iface)
381 ICOM_THIS(IAVIEditStreamImpl,iface);
383 TRACE("(%p) -> %ld\n", iface, This->ref + 1);
384 return ++(This->ref);
387 static ULONG WINAPI IAVIEditStream_fnRelease(IAVIEditStream*iface)
389 ICOM_THIS(IAVIEditStreamImpl,iface);
392 TRACE("(%p) -> %ld\n", iface, This->ref - 1);
394 if (!--(This->ref)) {
395 /* releaase memory */
396 if (This->pg != NULL)
397 AVIStreamGetFrameClose(This->pg);
398 if (This->pStreams != NULL) {
399 for (i = 0; i < This->nStreams; i++) {
400 if (This->pStreams[i].pStream != NULL)
401 IAVIStream_Release(This->pStreams[i].pStream);
403 GlobalFreePtr(This->pStreams);
406 LocalFree((HLOCAL)This);
412 static HRESULT WINAPI IAVIEditStream_fnCut(IAVIEditStream*iface,LONG*plStart,
413 LONG*plLength,PAVISTREAM*ppResult)
415 ICOM_THIS(IAVIEditStreamImpl,iface);
417 DWORD start, len, streamPos, streamNr;
420 TRACE("(%p,%p,%p,%p)\n",iface,plStart,plLength,ppResult);
422 if (ppResult != NULL)
424 if (plStart == NULL || plLength == NULL || *plStart < 0)
425 return AVIERR_BADPARAM;
427 /* if asked for cutted part copy it before deleting */
428 if (ppResult != NULL) {
429 hr = IAVIEditStream_Copy(iface, plStart, plLength, ppResult);
437 /* now delete the requested part */
439 hr = AVIFILE_FindStreamInTable(This, start, &stream,
440 &streamPos, &streamNr, FALSE);
443 if (This->pStreams[streamNr].dwStart == streamPos) {
444 /* deleting from start of part */
445 if (len < This->pStreams[streamNr].dwLength) {
447 This->pStreams[streamNr].dwStart += len;
448 This->pStreams[streamNr].dwLength -= len;
449 This->sInfo.dwLength -= len;
452 /* we must return decompressed data now */
453 This->bDecompress = TRUE;
455 /* deleting hole part */
456 len -= This->pStreams[streamNr].dwLength;
457 AVIFILE_RemoveStream(This,streamNr);
459 } else if (EditStreamEnd(This, streamNr) <= streamPos + len) {
460 /* deleting at end of a part */
461 DWORD count = EditStreamEnd(This, streamNr) - streamPos;
462 This->sInfo.dwLength -= count;
464 This->pStreams[streamNr].dwLength =
465 streamPos - This->pStreams[streamNr].dwStart;
468 if (This->nStreams + 1 >= This->nTableSize) {
470 GlobalReAllocPtr(This->pStreams, (This->nTableSize + 32) * sizeof(EditStreamTable), GMEM_SHARE|GHND);
471 if (This->pStreams == NULL)
472 return AVIERR_MEMORY;
473 This->nTableSize += 32;
475 memmove(This->pStreams + streamNr + 1, This->pStreams + streamNr,
476 (This->nStreams - streamNr) * sizeof(EditStreamTable));
479 IAVIStream_AddRef(This->pStreams[streamNr + 1].pStream);
480 This->pStreams[streamNr + 1].dwStart = streamPos + len;
481 This->pStreams[streamNr + 1].dwLength =
482 EditStreamEnd(This, streamNr) - This->pStreams[streamNr + 1].dwStart;
484 This->pStreams[streamNr].dwLength =
485 streamPos - This->pStreams[streamNr].dwStart;
486 This->sInfo.dwLength -= len;
491 This->sInfo.dwEditCount++;
496 static HRESULT WINAPI IAVIEditStream_fnCopy(IAVIEditStream*iface,LONG*plStart,
497 LONG*plLength,PAVISTREAM*ppResult)
499 ICOM_THIS(IAVIEditStreamImpl,iface);
500 IAVIEditStreamImpl* pEdit;
504 TRACE("(%p,%p,%p,%p)\n",iface,plStart,plLength,ppResult);
506 if (ppResult == NULL)
507 return AVIERR_BADPARAM;
509 if (plStart == NULL || plLength == NULL || *plStart < 0 || *plLength < 0)
510 return AVIERR_BADPARAM;
513 if (*(LPDWORD)plLength > This->sInfo.dwLength)
514 *(LPDWORD)plLength = This->sInfo.dwLength;
515 if (*(LPDWORD)plStart < This->sInfo.dwStart) {
516 *(LPDWORD)plLength -= This->sInfo.dwStart - *(LPDWORD)plStart;
517 *(LPDWORD)plStart = This->sInfo.dwStart;
519 return AVIERR_BADPARAM;
521 if (*(LPDWORD)plStart + *(LPDWORD)plLength > This->sInfo.dwStart + This->sInfo.dwLength)
522 *(LPDWORD)plLength = This->sInfo.dwStart + This->sInfo.dwLength -
525 pEdit = (IAVIEditStreamImpl*)AVIFILE_CreateEditStream(NULL);
527 return AVIERR_MEMORY;
529 hr = IAVIEditStream_Paste((PAVIEDITSTREAM)pEdit,&start,plLength,
530 (PAVISTREAM)&This->iAVIStream,*plStart,
531 *plStart + *plLength);
534 IAVIEditStream_Release((PAVIEDITSTREAM)pEdit);
536 *ppResult = (PAVISTREAM)&pEdit->iAVIStream;
541 static HRESULT WINAPI IAVIEditStream_fnPaste(IAVIEditStream*iface,LONG*plStart,
542 LONG*plLength,PAVISTREAM pSource,
543 LONG lStart,LONG lLength)
545 ICOM_THIS(IAVIEditStreamImpl,iface);
546 AVISTREAMINFOW srcInfo;
547 IEditStreamInternal*pTable = NULL;
548 IAVIEditStreamImpl *pEdit = NULL;
550 FIXME("(%p,%p,%p,%p,%ld,%ld),stub!\n",iface,plStart,plLength,
551 pSource,lStart,lLength);
553 if (plStart == NULL || pSource == NULL || lLength < 0)
554 return AVIERR_BADPARAM;
555 if (This->sInfo.dwStart + This->sInfo.dwLength < *plStart)
556 return AVIERR_BADPARAM; /* FIXME: or change plStart to end of stream? */
557 if (FAILED(IAVIStream_Info(pSource, &srcInfo, sizeof(srcInfo))))
559 if (lStart < srcInfo.dwStart || lStart >= srcInfo.dwStart + srcInfo.dwLength)
560 return AVIERR_BADPARAM;
561 if (This->sInfo.fccType != srcInfo.fccType)
562 return AVIERR_UNSUPPORTED; /* different stream types */
563 if (This->sInfo.fccType == 0) {
564 IAVIStream_Info(pSource, &This->sInfo, sizeof(This->sInfo));
565 This->sInfo.dwStart = *plStart;
566 This->sInfo.dwLength = 0;
568 if (lStart + lLength > srcInfo.dwStart + srcInfo.dwLength)
569 lLength = srcInfo.dwStart + srcInfo.dwLength - lStart;
570 if (lLength + *plStart >= 0x80000000)
571 return AVIERR_MEMORY;
573 /* streamtype specific tests */
574 if (srcInfo.fccType == streamtypeVIDEO) {
577 size = srcInfo.rcFrame.right - srcInfo.rcFrame.left;
578 if (size != This->sInfo.rcFrame.right - This->sInfo.rcFrame.left)
579 return AVIERR_UNSUPPORTED; /* FIXME: Can't GetFrame convert it? */
580 size = srcInfo.rcFrame.bottom - srcInfo.rcFrame.top;
581 if (size != This->sInfo.rcFrame.bottom - This->sInfo.rcFrame.top)
582 return AVIERR_UNSUPPORTED; /* FIXME: Can't GetFrame convert it? */
583 } else if (srcInfo.fccType == streamtypeAUDIO) {
584 if (! AVIFILE_FormatsEqual((PAVISTREAM)&This->iAVIStream, pSource))
585 return AVIERR_UNSUPPORTED;
587 /* FIXME: streamtypeMIDI and streamtypeTEXT */
588 return AVIERR_UNSUPPORTED;
591 /* try to get an IEditStreamInternal interface */
592 if (SUCCEEDED(IAVIStream_QueryInterface(pSource, &IID_IEditStreamInternal,
593 (LPVOID*)&pTable))) {
594 pTable->lpVtbl->GetEditStreamImpl(pTable, (LPVOID*)&pEdit);
595 pTable->lpVtbl->Release(pTable);
598 /* FIXME: for video must check for change of format */
599 /* FIXME: if stream to insert is an editable stream insert the
600 * 'sub-streams' else the given stream.
603 return AVIERR_UNSUPPORTED;
606 static HRESULT WINAPI IAVIEditStream_fnClone(IAVIEditStream*iface,
609 ICOM_THIS(IAVIEditStreamImpl,iface);
610 IAVIEditStreamImpl* pEdit;
613 TRACE("(%p,%p)\n",iface,ppResult);
615 if (ppResult == NULL)
616 return AVIERR_BADPARAM;
619 pEdit = (IAVIEditStreamImpl*)AVIFILE_CreateEditStream(NULL);
621 return AVIERR_MEMORY;
622 if (This->nStreams > pEdit->nTableSize) {
623 pEdit->pStreams = GlobalReAllocPtr(pEdit->pStreams, This->nStreams * sizeof(EditStreamTable),GMEM_SHARE|GHND);
624 if (pEdit->pStreams == NULL)
625 return AVIERR_MEMORY;
626 pEdit->nTableSize = This->nStreams;
628 pEdit->nStreams = This->nStreams;
629 memcpy(pEdit->pStreams, This->pStreams,
630 This->nStreams * sizeof(EditStreamTable));
631 memcpy(&pEdit->sInfo,&This->sInfo,sizeof(This->sInfo));
632 for (i = 0; i < This->nStreams; i++) {
633 if (pEdit->pStreams[i].pStream != NULL)
634 IAVIStream_AddRef(pEdit->pStreams[i].pStream);
637 *ppResult = (PAVISTREAM)&pEdit->iAVIStream;
642 static HRESULT WINAPI IAVIEditStream_fnSetInfo(IAVIEditStream*iface,
643 LPAVISTREAMINFOW asi,LONG size)
645 ICOM_THIS(IAVIEditStreamImpl,iface);
647 TRACE("(%p,%p,%ld)",iface,asi,size);
649 /* check parameters */
651 return AVIERR_BADPARAM;
652 if (size != sizeof(AVISTREAMINFOW))
653 return AVIERR_BADSIZE;
654 if (asi->dwScale == 0 || asi->dwRate == 0 || (LONG)asi->dwQuality < -1 ||
655 asi->dwQuality > ICQUALITY_HIGH)
658 This->sInfo.wLanguage = asi->wLanguage;
659 This->sInfo.wPriority = asi->wPriority;
660 This->sInfo.dwStart = asi->dwStart;
661 if (asi->dwRate != 0)
662 This->sInfo.dwRate = asi->dwRate;
663 if (asi->dwScale != 0)
664 This->sInfo.dwScale = asi->dwScale;
665 if (asi->dwQuality <= ICQUALITY_HIGH)
666 This->sInfo.dwQuality = ICQUALITY_HIGH;
667 CopyRect(&This->sInfo.rcFrame, &asi->rcFrame);
668 memcpy(&This->sInfo.szName, &asi->szName, sizeof(asi->szName));
669 This->sInfo.dwEditCount++;
674 static HRESULT WINAPI IEditAVIStream_fnQueryInterface(IAVIStream*iface,
675 REFIID refiid,LPVOID*obj)
677 ICOM_THIS(IEditAVIStreamImpl,iface);
679 assert(This->pae != NULL);
681 return IAVIEditStream_QueryInterface((IAVIEditStream*)This->pae,refiid,obj);
684 static ULONG WINAPI IEditAVIStream_fnAddRef(IAVIStream*iface)
686 ICOM_THIS(IEditAVIStreamImpl,iface);
688 assert(This->pae != NULL);
690 return IAVIEditStream_AddRef((IAVIEditStream*)This->pae);
693 static ULONG WINAPI IEditAVIStream_fnRelease(IAVIStream*iface)
695 ICOM_THIS(IEditAVIStreamImpl,iface);
697 assert(This->pae != NULL);
699 return IAVIEditStream_Release((IAVIEditStream*)This->pae);
702 static HRESULT WINAPI IEditAVIStream_fnCreate(IAVIStream*iface,
703 LPARAM lParam1,LPARAM lParam2)
705 IAVIEditStreamImpl *This = ((IEditAVIStreamImpl*)iface)->pae;
710 if (This->pStreams == NULL) {
712 GlobalAllocPtr(GMEM_SHARE|GHND, 256 * sizeof(EditStreamTable));
713 if (This->pStreams == NULL)
714 return AVIERR_MEMORY;
715 This->nTableSize = 256;
719 IAVIStream_Info((PAVISTREAM)lParam1, &This->sInfo, sizeof(This->sInfo));
720 IAVIStream_AddRef((PAVISTREAM)lParam1);
721 This->pStreams[0].pStream = (PAVISTREAM)lParam1;
722 This->pStreams[0].dwStart = This->sInfo.dwStart;
723 This->pStreams[0].dwLength = This->sInfo.dwLength;
729 static HRESULT WINAPI IEditAVIStream_fnInfo(IAVIStream*iface,
730 AVISTREAMINFOW *psi,LONG size)
732 ICOM_THIS(IEditAVIStreamImpl,iface);
734 TRACE("(%p,%p,%ld)\n",iface,psi,size);
736 assert(This->pae != NULL);
739 return AVIERR_BADPARAM;
741 return AVIERR_BADSIZE;
743 if (This->pae->bDecompress)
744 This->pae->sInfo.fccHandler = 0;
746 memcpy(psi, &This->pae->sInfo, min((DWORD)size, sizeof(This->pae->sInfo)));
748 if ((DWORD)size < sizeof(This->pae->sInfo))
749 return AVIERR_BUFFERTOOSMALL;
753 static LONG WINAPI IEditAVIStream_fnFindSample(IAVIStream*iface,LONG pos,
756 IAVIEditStreamImpl* const This = ((IEditAVIStreamImpl* const)iface)->pae;
758 DWORD streamPos, streamNr;
760 TRACE("(%p,%ld,0x%08lX)\n",iface,pos,flags);
762 if (flags & FIND_FROM_START)
763 pos = (LONG)This->sInfo.dwStart;
765 /* outside of stream? */
766 if (pos < (LONG)This->sInfo.dwStart ||
767 (LONG)This->sInfo.dwStart + (LONG)This->sInfo.dwLength <= pos)
770 /* map our position to a stream and position in it */
771 if (AVIFILE_FindStreamInTable(This, pos, &stream, &streamPos,
773 return -1; /* doesn't exist */
775 if (This->bDecompress) {
776 /* only one stream -- format changes only at start */
777 if (flags & FIND_FORMAT)
778 return (flags & FIND_NEXT ? -1 : 0);
780 /* FIXME: map positions back to us */
781 return IAVIStream_FindSample(stream, streamPos, flags);
783 /* assume change of format every frame */
788 static HRESULT WINAPI IEditAVIStream_fnReadFormat(IAVIStream*iface,LONG pos,
789 LPVOID format,LONG*fmtsize)
791 IAVIEditStreamImpl* const This = ((IEditAVIStreamImpl* const)iface)->pae;
792 LPBITMAPINFOHEADER lp;
797 TRACE("(%p,%ld,%p,%p)\n",iface,pos,format,fmtsize);
799 if (fmtsize == NULL || pos < This->sInfo.dwStart ||
800 This->sInfo.dwStart + This->sInfo.dwLength <= pos)
801 return AVIERR_BADPARAM;
803 /* find stream corresponding to position */
804 hr = AVIFILE_FindStreamInTable(This, pos, &stream, &n, NULL, FALSE);
808 if (! This->bDecompress)
809 return IAVIStream_ReadFormat(stream, n, format, fmtsize);
811 lp = (LPBITMAPINFOHEADER)AVIFILE_ReadFrame(This, stream, n);
814 if (lp->biBitCount <= 8) {
815 n = (lp->biClrUsed > 0 ? lp->biClrUsed : 1 << lp->biBitCount);
816 n *= sizeof(RGBQUAD);
821 memcpy(format, lp, min((LONG)n, *fmtsize));
822 hr = ((LONG)n > *fmtsize ? AVIERR_BUFFERTOOSMALL : AVIERR_OK);
828 static HRESULT WINAPI IEditAVIStream_fnSetFormat(IAVIStream*iface,LONG pos,
829 LPVOID format,LONG formatsize)
831 TRACE("(%p,%ld,%p,%ld)\n",iface,pos,format,formatsize);
833 return AVIERR_UNSUPPORTED;
836 static HRESULT WINAPI IEditAVIStream_fnRead(IAVIStream*iface,LONG start,
837 LONG samples,LPVOID buffer,
838 LONG buffersize,LONG*bytesread,
841 IAVIEditStreamImpl* const This = ((IEditAVIStreamImpl* const)iface)->pae;
843 DWORD streamPos, streamNr;
844 LONG readBytes, readSamples, count;
847 TRACE("(%p,%ld,%ld,%p,%ld,%p,%p) -- 0x%08lX\n",iface,start,samples,
848 buffer,buffersize,bytesread,samplesread,This->sInfo.fccType);
850 /* check parameters */
851 if (bytesread != NULL)
853 if (samplesread != NULL)
856 return AVIERR_BADSIZE;
857 if ((DWORD)start < This->sInfo.dwStart ||
858 This->sInfo.dwStart + This->sInfo.dwLength < (DWORD)start)
859 return AVIERR_BADPARAM;
861 if (! This->bDecompress) {
862 /* audio like data -- sample-based */
865 return AVIERR_OK; /* nothing at all or already done */
867 if (FAILED(AVIFILE_FindStreamInTable(This, start, &stream,
868 &streamPos, &streamNr, FALSE)))
871 /* limit to end of the stream */
873 if (streamPos + count > EditStreamEnd(This, streamNr))
874 count = EditStreamEnd(This, streamNr) - streamPos;
876 hr = IAVIStream_Read(stream, streamPos, count, buffer, buffersize,
877 &readBytes, &readSamples);
880 if (readBytes == 0 && readSamples == 0 && count != 0)
881 return AVIERR_FILEREAD; /* for bad stream implementations */
883 if (samplesread != NULL)
884 *samplesread += readSamples;
885 if (bytesread != NULL)
886 *bytesread += readBytes;
887 if (buffer != NULL) {
888 (LPBYTE)buffer += readBytes;
889 buffersize -= readBytes;
893 } while (This->sInfo.dwStart + This->sInfo.dwLength > start);
895 /* video like data -- frame-based */
896 LPBITMAPINFOHEADER lp;
901 if (FAILED(AVIFILE_FindStreamInTable(This, start, &stream,
902 &streamPos, &streamNr, FALSE)))
905 lp = AVIFILE_ReadFrame(This, stream, streamPos);
909 if (buffer != NULL) {
910 /* need size of format to skip */
911 if (lp->biBitCount <= 8) {
912 count = lp->biClrUsed > 0 ? lp->biClrUsed : 1 << lp->biBitCount;
913 count *= sizeof(RGBQUAD);
918 if (buffersize < lp->biSizeImage)
919 return AVIERR_BUFFERTOOSMALL;
920 memcpy(buffer, (LPBYTE)lp + count, lp->biSizeImage);
923 if (bytesread != NULL)
924 *bytesread = lp->biSizeImage;
925 if (samplesread != NULL)
932 static HRESULT WINAPI IEditAVIStream_fnWrite(IAVIStream*iface,LONG start,
933 LONG samples,LPVOID buffer,
934 LONG buffersize,DWORD flags,
935 LONG*sampwritten,LONG*byteswritten)
937 TRACE("(%p,%ld,%ld,%p,%ld,0x%08lX,%p,%p)",iface,start,samples,buffer,
938 buffersize,flags,sampwritten,byteswritten);
940 /* be sure return parameters have correct values */
941 if (sampwritten != NULL)
943 if (byteswritten != NULL)
946 return AVIERR_UNSUPPORTED;
949 static HRESULT WINAPI IEditAVIStream_fnDelete(IAVIStream*iface,LONG start,
952 ICOM_THIS(IEditAVIStreamImpl,iface);
954 TRACE("(%p,%ld,%ld)\n",iface,start,samples);
956 return IAVIEditStream_Cut((IAVIEditStream*)This->pae,&start,&samples,NULL);
959 static HRESULT WINAPI IEditAVIStream_fnReadData(IAVIStream*iface,DWORD fcc,
960 LPVOID lp,LONG *lpread)
962 IAVIEditStreamImpl* const This = ((IEditAVIStreamImpl* const)iface)->pae;
965 TRACE("(%p,0x%08lX,%p,%p)",iface,fcc,lp,lpread);
967 /* check parameters */
968 if (lp == NULL || lpread == NULL)
969 return AVIERR_BADPARAM;
971 /* simply ask every stream and return the first block found */
972 for (n = 0; n < This->nStreams; n++) {
973 HRESULT hr = IAVIStream_ReadData(This->pStreams[n].pStream,fcc,lp,lpread);
980 return AVIERR_NODATA;
983 static HRESULT WINAPI IEditAVIStream_fnWriteData(IAVIStream*iface,DWORD fcc,
986 TRACE("(%p,0x%08lX,%p,%ld)",iface,fcc,lp,size);
988 return AVIERR_UNSUPPORTED;
991 static HRESULT WINAPI IEditAVIStream_fnSetInfo(IAVIStream*iface,
992 AVISTREAMINFOW*info,LONG len)
994 ICOM_THIS(IEditAVIStreamImpl,iface);
996 TRACE("(%p,%p,%ld)\n",iface,info,len);
998 return IAVIEditStream_SetInfo((IAVIEditStream*)This->pae,info,len);
1001 static HRESULT WINAPI IEditStreamInternal_fnQueryInterface(IEditStreamInternal*iface,REFIID refiid,LPVOID*obj)
1003 ICOM_THIS(IEditStreamInternalImpl,iface);
1005 assert(This->pae != NULL);
1007 return IAVIEditStream_QueryInterface((IAVIEditStream*)This->pae, refiid, obj);
1010 static ULONG WINAPI IEditStreamInternal_fnAddRef(IEditStreamInternal*iface)
1012 ICOM_THIS(IEditStreamInternalImpl,iface);
1014 assert(This->pae != NULL);
1016 return IAVIEditStream_AddRef((IAVIEditStream*)This->pae);
1019 static ULONG WINAPI IEditStreamInternal_fnRelease(IEditStreamInternal*iface)
1021 ICOM_THIS(IEditStreamInternalImpl,iface);
1023 assert(This->pae != NULL);
1025 return IAVIEditStream_Release((IAVIEditStream*)This->pae);
1028 static HRESULT WINAPI IEditStreamInternal_fnGetEditStreamImpl(IEditStreamInternal*iface,LPVOID*ppimpl)
1030 ICOM_THIS(IEditStreamInternalImpl,iface);
1032 assert(This->pae != NULL);
1033 assert(ppimpl != NULL);
1035 *ppimpl = This->pae;