Sync to Wine-0_9_2:
[reactos.git] / reactos / lib / avifil32 / editstream.c
1 /*
2 * Copyright 2003 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 */
18
19 #define COM_NO_WINDOWS_H
20 #include <assert.h>
21 #include <stdarg.h>
22
23 #include "windef.h"
24 #include "winbase.h"
25 #include "winuser.h"
26 #include "wingdi.h"
27 #include "winnls.h"
28 #include "winerror.h"
29 #include "windowsx.h"
30 #include "mmsystem.h"
31 #include "vfw.h"
32
33 #include "avifile_private.h"
34 #include "extrachunk.h"
35
36 #include "wine/debug.h"
37
38 WINE_DEFAULT_DEBUG_CHANNEL(avifile);
39
40 /***********************************************************************/
41
42 /* internal interface to get access to table of stream in an editable stream */
43
44 typedef struct _EditStreamTable {
45 PAVISTREAM pStream; /* stream which contains the data */
46 DWORD dwStart; /* where starts the part which is also our */
47 DWORD dwLength; /* how many is also in this stream */
48 } EditStreamTable;
49
50 #define INTERFACE IEditStreamInternal
51 DECLARE_INTERFACE_(IEditStreamInternal,IUnknown)
52 {
53 /*** IUnknown methods ***/
54 STDMETHOD_(HRESULT,QueryInterface)(THIS_ REFIID riid, void** ppvObject) PURE;
55 STDMETHOD_(ULONG,AddRef)(THIS) PURE;
56 STDMETHOD_(ULONG,Release)(THIS) PURE;
57 /*** IEditStreamInternal methods ***/
58 STDMETHOD(GetEditStreamImpl)(THIS_ LPVOID*) PURE;
59 };
60 #undef INTERFACE
61
62 #define EditStreamEnd(This,streamNr) ((This)->pStreams[streamNr].dwStart + \
63 (This)->pStreams[streamNr].dwLength)
64
65 /***********************************************************************/
66
67 static HRESULT WINAPI IAVIEditStream_fnQueryInterface(IAVIEditStream*iface,REFIID refiid,LPVOID *obj);
68 static ULONG WINAPI IAVIEditStream_fnAddRef(IAVIEditStream*iface);
69 static ULONG WINAPI IAVIEditStream_fnRelease(IAVIEditStream*iface);
70 static HRESULT WINAPI IAVIEditStream_fnCut(IAVIEditStream*iface,LONG*plStart,
71 LONG*plLength,PAVISTREAM*ppResult);
72 static HRESULT WINAPI IAVIEditStream_fnCopy(IAVIEditStream*iface,LONG*plStart,
73 LONG*plLength,PAVISTREAM*ppResult);
74 static HRESULT WINAPI IAVIEditStream_fnPaste(IAVIEditStream*iface,LONG*plStart,
75 LONG*plLength,PAVISTREAM pSource,
76 LONG lStart,LONG lEnd);
77 static HRESULT WINAPI IAVIEditStream_fnClone(IAVIEditStream*iface,
78 PAVISTREAM*ppResult);
79 static HRESULT WINAPI IAVIEditStream_fnSetInfo(IAVIEditStream*iface,
80 LPAVISTREAMINFOW asi,LONG size);
81
82 static const struct IAVIEditStreamVtbl ieditstream = {
83 IAVIEditStream_fnQueryInterface,
84 IAVIEditStream_fnAddRef,
85 IAVIEditStream_fnRelease,
86 IAVIEditStream_fnCut,
87 IAVIEditStream_fnCopy,
88 IAVIEditStream_fnPaste,
89 IAVIEditStream_fnClone,
90 IAVIEditStream_fnSetInfo
91 };
92
93 static HRESULT WINAPI IEditAVIStream_fnQueryInterface(IAVIStream*iface,REFIID refiid,LPVOID*obj);
94 static ULONG WINAPI IEditAVIStream_fnAddRef(IAVIStream*iface);
95 static ULONG WINAPI IEditAVIStream_fnRelease(IAVIStream*iface);
96 static HRESULT WINAPI IEditAVIStream_fnCreate(IAVIStream*iface,LPARAM lParam1,LPARAM lParam2);
97 static HRESULT WINAPI IEditAVIStream_fnInfo(IAVIStream*iface,AVISTREAMINFOW *psi,LONG size);
98 static LONG WINAPI IEditAVIStream_fnFindSample(IAVIStream*iface,LONG pos,
99 LONG flags);
100 static HRESULT WINAPI IEditAVIStream_fnReadFormat(IAVIStream*iface,LONG pos,LPVOID format,LONG*formatsize);
101 static HRESULT WINAPI IEditAVIStream_fnSetFormat(IAVIStream*iface,LONG pos,LPVOID format,LONG formatsize);
102 static HRESULT WINAPI IEditAVIStream_fnRead(IAVIStream*iface,LONG start,
103 LONG samples,LPVOID buffer,
104 LONG buffersize,LONG*bytesread,
105 LONG*samplesread);
106 static HRESULT WINAPI IEditAVIStream_fnWrite(IAVIStream*iface,LONG start,
107 LONG samples,LPVOID buffer,
108 LONG buffersize,DWORD flags,
109 LONG*sampwritten,LONG*byteswritten);
110 static HRESULT WINAPI IEditAVIStream_fnDelete(IAVIStream*iface,LONG start,LONG samples);
111 static HRESULT WINAPI IEditAVIStream_fnReadData(IAVIStream*iface,DWORD fcc,
112 LPVOID lp,LONG *lpread);
113 static HRESULT WINAPI IEditAVIStream_fnWriteData(IAVIStream*iface,DWORD fcc,
114 LPVOID lp,LONG size);
115 static HRESULT WINAPI IEditAVIStream_fnSetInfo(IAVIStream*iface,AVISTREAMINFOW*info,LONG infolen);
116
117 static const struct IAVIStreamVtbl ieditstast = {
118 IEditAVIStream_fnQueryInterface,
119 IEditAVIStream_fnAddRef,
120 IEditAVIStream_fnRelease,
121 IEditAVIStream_fnCreate,
122 IEditAVIStream_fnInfo,
123 IEditAVIStream_fnFindSample,
124 IEditAVIStream_fnReadFormat,
125 IEditAVIStream_fnSetFormat,
126 IEditAVIStream_fnRead,
127 IEditAVIStream_fnWrite,
128 IEditAVIStream_fnDelete,
129 IEditAVIStream_fnReadData,
130 IEditAVIStream_fnWriteData,
131 IEditAVIStream_fnSetInfo
132 };
133
134 static HRESULT WINAPI IEditStreamInternal_fnQueryInterface(IEditStreamInternal*iface,REFIID refiid,LPVOID*obj);
135 static ULONG WINAPI IEditStreamInternal_fnAddRef(IEditStreamInternal*iface);
136 static ULONG WINAPI IEditStreamInternal_fnRelease(IEditStreamInternal*iface);
137 static HRESULT WINAPI IEditStreamInternal_fnGetEditStreamImpl(IEditStreamInternal*iface,LPVOID*ppimpl);
138
139 static const struct IEditStreamInternalVtbl ieditstreaminternal = {
140 IEditStreamInternal_fnQueryInterface,
141 IEditStreamInternal_fnAddRef,
142 IEditStreamInternal_fnRelease,
143 IEditStreamInternal_fnGetEditStreamImpl
144 };
145
146 typedef struct _IAVIEditStreamImpl IAVIEditStreamImpl;
147
148 typedef struct _IEditAVIStreamImpl {
149 /* IUnknown stuff */
150 const IAVIStreamVtbl *lpVtbl;
151
152 /* IAVIStream stuff */
153 IAVIEditStreamImpl *pae;
154 } IEditAVIStreamImpl;
155
156 typedef struct _IEditStreamInternalImpl {
157 /* IUnknown stuff */
158 const IEditStreamInternalVtbl *lpVtbl;
159
160 /* IEditStreamInternal stuff */
161 IAVIEditStreamImpl *pae;
162 } IEditStreamInternalImpl;
163
164 struct _IAVIEditStreamImpl {
165 /* IUnknown stuff */
166 const IAVIEditStreamVtbl *lpVtbl;
167 LONG ref;
168
169 /* IAVIEditStream stuff */
170 IEditAVIStreamImpl iAVIStream;
171 IEditStreamInternalImpl iEditStreamInternal;
172
173 AVISTREAMINFOW sInfo;
174
175 EditStreamTable *pStreams;
176 DWORD nStreams; /* current fill level of pStreams table */
177 DWORD nTableSize; /* size of pStreams table */
178
179 BOOL bDecompress;
180 PAVISTREAM pCurStream;
181 PGETFRAME pg; /* IGetFrame for pCurStream */
182 LPBITMAPINFOHEADER lpFrame; /* frame of pCurStream */
183 };
184
185 /***********************************************************************/
186
187 PAVIEDITSTREAM AVIFILE_CreateEditStream(PAVISTREAM pstream)
188 {
189 IAVIEditStreamImpl *pedit = NULL;
190
191 pedit = (IAVIEditStreamImpl*)LocalAlloc(LPTR,sizeof(IAVIEditStreamImpl));
192 if (pedit == NULL)
193 return NULL;
194
195 pedit->lpVtbl = &ieditstream;
196 pedit->iAVIStream.lpVtbl = &ieditstast;
197 pedit->iAVIStream.pae = pedit;
198 pedit->iEditStreamInternal.lpVtbl = &ieditstreaminternal;
199 pedit->iEditStreamInternal.pae = pedit;
200 pedit->ref = 1;
201
202 IAVIStream_Create((PAVISTREAM)&pedit->iAVIStream,(LPARAM)pstream,0);
203
204 return (PAVIEDITSTREAM)pedit;
205 }
206
207 static HRESULT AVIFILE_FindStreamInTable(IAVIEditStreamImpl* const This,
208 DWORD pos,PAVISTREAM *ppStream,
209 DWORD* streamPos,
210 DWORD* streamNr,BOOL bFindSample)
211 {
212 DWORD n;
213
214 TRACE("(%p,%lu,%p,%p,%p,%d)\n",This,pos,ppStream,streamPos,
215 streamNr,bFindSample);
216
217 if (pos < This->sInfo.dwStart)
218 return AVIERR_BADPARAM;
219
220 pos -= This->sInfo.dwStart;
221 for (n = 0; n < This->nStreams; n++) {
222 if (pos < This->pStreams[n].dwLength) {
223 *ppStream = This->pStreams[n].pStream;
224 *streamPos = This->pStreams[n].dwStart + pos;
225 if (streamNr != NULL)
226 *streamNr = n;
227
228 return AVIERR_OK;
229 }
230 pos -= This->pStreams[n].dwLength;
231 }
232 if (pos == 0 && bFindSample) {
233 *ppStream = This->pStreams[--n].pStream;
234 *streamPos = EditStreamEnd(This, n);
235 if (streamNr != NULL)
236 *streamNr = n;
237
238 TRACE(" -- pos=0 && b=1 -> (%p,%lu,%lu)\n",*ppStream, *streamPos, n);
239 return AVIERR_OK;
240 } else {
241 *ppStream = NULL;
242 *streamPos = 0;
243 if (streamNr != NULL)
244 *streamNr = 0;
245
246 TRACE(" -> ERROR (NULL,0,0)\n");
247 return AVIERR_BADPARAM;
248 }
249 }
250
251 static LPVOID AVIFILE_ReadFrame(IAVIEditStreamImpl* const This,
252 PAVISTREAM pstream, LONG pos)
253 {
254 PGETFRAME pg;
255
256 TRACE("(%p,%p,%ld)\n",This,pstream,pos);
257
258 if (pstream == NULL)
259 return NULL;
260
261 /* if stream changes make sure that only palette changes */
262 if (This->pCurStream != pstream) {
263 pg = AVIStreamGetFrameOpen(pstream, NULL);
264 if (pg == NULL)
265 return NULL;
266 if (This->pg != NULL) {
267 if (IGetFrame_SetFormat(pg, This->lpFrame, NULL, 0, 0, -1, -1)) {
268 AVIStreamGetFrameClose(pg);
269 ERR(": IGetFrame_SetFormat failed\n");
270 return NULL;
271 }
272 AVIStreamGetFrameClose(This->pg);
273 }
274 This->pg = pg;
275 This->pCurStream = pstream;
276 }
277
278 /* now get the decompressed frame */
279 This->lpFrame = AVIStreamGetFrame(This->pg, pos);
280 if (This->lpFrame != NULL)
281 This->sInfo.dwSuggestedBufferSize = This->lpFrame->biSizeImage;
282
283 return This->lpFrame;
284 }
285
286 static HRESULT AVIFILE_RemoveStream(IAVIEditStreamImpl* const This, DWORD nr)
287 {
288 assert(This != NULL);
289 assert(nr < This->nStreams);
290
291 /* remove part nr */
292 IAVIStream_Release(This->pStreams[nr].pStream);
293 This->nStreams--;
294 if (This->nStreams - nr > 0) {
295 memmove(This->pStreams + nr, This->pStreams + nr + 1,
296 (This->nStreams - nr) * sizeof(EditStreamTable));
297 }
298 This->pStreams[This->nStreams].pStream = NULL;
299 This->pStreams[This->nStreams].dwStart = 0;
300 This->pStreams[This->nStreams].dwLength = 0;
301
302 /* try to merge the part before the deleted one and the one after it */
303 if (0 < nr && 0 < This->nStreams &&
304 This->pStreams[nr - 1].pStream == This->pStreams[nr].pStream) {
305 if (EditStreamEnd(This, nr - 1) == This->pStreams[nr].dwStart) {
306 This->pStreams[nr - 1].dwLength += This->pStreams[nr].dwLength;
307 return AVIFILE_RemoveStream(This, nr);
308 }
309 }
310
311 return AVIERR_OK;
312 }
313
314 static BOOL AVIFILE_FormatsEqual(PAVISTREAM avi1, PAVISTREAM avi2)
315 {
316 LPVOID fmt1 = NULL, fmt2 = NULL;
317 LONG size1, size2, start1, start2;
318 BOOL status = FALSE;
319
320 assert(avi1 != NULL && avi2 != NULL);
321
322 /* get stream starts and check format sizes */
323 start1 = AVIStreamStart(avi1);
324 start2 = AVIStreamStart(avi2);
325 if (FAILED(AVIStreamFormatSize(avi1, start1, &size1)))
326 return FALSE;
327 if (FAILED(AVIStreamFormatSize(avi2, start2, &size2)))
328 return FALSE;
329 if (size1 != size2)
330 return FALSE;
331
332 /* sizes match, now get formats and compare them */
333 fmt1 = GlobalAllocPtr(GHND, size1);
334 if (fmt1 == NULL)
335 return FALSE;
336 if (SUCCEEDED(AVIStreamReadFormat(avi1, start1, fmt1, &size1))) {
337 fmt2 = GlobalAllocPtr(GHND, size1);
338 if (fmt2 != NULL) {
339 if (SUCCEEDED(AVIStreamReadFormat(avi2, start2, fmt2, &size1)))
340 status = (memcmp(fmt1, fmt2, size1) == 0);
341 }
342 }
343
344 if (fmt2 != NULL)
345 GlobalFreePtr(fmt2);
346 GlobalFreePtr(fmt1);
347
348 return status;
349 }
350
351 /***********************************************************************/
352
353 static HRESULT WINAPI IAVIEditStream_fnQueryInterface(IAVIEditStream*iface,REFIID refiid,LPVOID *obj)
354 {
355 IAVIEditStreamImpl *This = (IAVIEditStreamImpl *)iface;
356
357 TRACE("(%p,%s,%p)\n", This, debugstr_guid(refiid), obj);
358
359 if (IsEqualGUID(&IID_IUnknown, refiid) ||
360 IsEqualGUID(&IID_IAVIEditStream, refiid)) {
361 *obj = iface;
362 IAVIEditStream_AddRef(iface);
363
364 return S_OK;
365 } else if (IsEqualGUID(&IID_IAVIStream, refiid)) {
366 *obj = &This->iAVIStream;
367 IAVIEditStream_AddRef(iface);
368
369 return S_OK;
370 } else if (IsEqualGUID(&IID_IEditStreamInternal, refiid)) {
371 *obj = &This->iEditStreamInternal;
372 IAVIEditStream_AddRef(iface);
373
374 return S_OK;
375 }
376
377 return OLE_E_ENUM_NOMORE;
378 }
379
380 static ULONG WINAPI IAVIEditStream_fnAddRef(IAVIEditStream*iface)
381 {
382 IAVIEditStreamImpl *This = (IAVIEditStreamImpl *)iface;
383 ULONG ref = InterlockedIncrement(&This->ref);
384
385 TRACE("(%p) -> %ld\n", iface, ref);
386
387 return ref;
388 }
389
390 static ULONG WINAPI IAVIEditStream_fnRelease(IAVIEditStream*iface)
391 {
392 IAVIEditStreamImpl *This = (IAVIEditStreamImpl *)iface;
393 DWORD i;
394 ULONG ref = InterlockedDecrement(&This->ref);
395
396 TRACE("(%p) -> %ld\n", iface, ref);
397
398 if (!ref) {
399 /* release memory */
400 if (This->pg != NULL)
401 AVIStreamGetFrameClose(This->pg);
402 if (This->pStreams != NULL) {
403 for (i = 0; i < This->nStreams; i++) {
404 if (This->pStreams[i].pStream != NULL)
405 IAVIStream_Release(This->pStreams[i].pStream);
406 }
407 GlobalFreePtr(This->pStreams);
408 }
409
410 LocalFree((HLOCAL)This);
411 return 0;
412 }
413 return ref;
414 }
415
416 static HRESULT WINAPI IAVIEditStream_fnCut(IAVIEditStream*iface,LONG*plStart,
417 LONG*plLength,PAVISTREAM*ppResult)
418 {
419 IAVIEditStreamImpl *This = (IAVIEditStreamImpl *)iface;
420 PAVISTREAM stream;
421 DWORD start, len, streamPos, streamNr;
422 HRESULT hr;
423
424 TRACE("(%p,%p,%p,%p)\n",iface,plStart,plLength,ppResult);
425
426 if (ppResult != NULL)
427 *ppResult = NULL;
428 if (plStart == NULL || plLength == NULL || *plStart < 0)
429 return AVIERR_BADPARAM;
430
431 /* if asked for cutted part copy it before deleting */
432 if (ppResult != NULL) {
433 hr = IAVIEditStream_Copy(iface, plStart, plLength, ppResult);
434 if (FAILED(hr))
435 return hr;
436 }
437
438 start = *plStart;
439 len = *plLength;
440
441 /* now delete the requested part */
442 while (len > 0) {
443 hr = AVIFILE_FindStreamInTable(This, start, &stream,
444 &streamPos, &streamNr, FALSE);
445 if (FAILED(hr))
446 return hr;
447 if (This->pStreams[streamNr].dwStart == streamPos) {
448 /* deleting from start of part */
449 if (len < This->pStreams[streamNr].dwLength) {
450 start += len;
451 This->pStreams[streamNr].dwStart += len;
452 This->pStreams[streamNr].dwLength -= len;
453 This->sInfo.dwLength -= len;
454 len = 0;
455
456 /* we must return decompressed data now */
457 This->bDecompress = TRUE;
458 } else {
459 /* deleting hole part */
460 len -= This->pStreams[streamNr].dwLength;
461 AVIFILE_RemoveStream(This,streamNr);
462 }
463 } else if (EditStreamEnd(This, streamNr) <= streamPos + len) {
464 /* deleting at end of a part */
465 DWORD count = EditStreamEnd(This, streamNr) - streamPos;
466 This->sInfo.dwLength -= count;
467 len -= count;
468 This->pStreams[streamNr].dwLength =
469 streamPos - This->pStreams[streamNr].dwStart;
470 } else {
471 /* splitting */
472 if (This->nStreams + 1 >= This->nTableSize) {
473 This->pStreams =
474 GlobalReAllocPtr(This->pStreams, (This->nTableSize + 32) * sizeof(EditStreamTable), GMEM_SHARE|GHND);
475 if (This->pStreams == NULL)
476 return AVIERR_MEMORY;
477 This->nTableSize += 32;
478 }
479 memmove(This->pStreams + streamNr + 1, This->pStreams + streamNr,
480 (This->nStreams - streamNr) * sizeof(EditStreamTable));
481 This->nStreams++;
482
483 IAVIStream_AddRef(This->pStreams[streamNr + 1].pStream);
484 This->pStreams[streamNr + 1].dwStart = streamPos + len;
485 This->pStreams[streamNr + 1].dwLength =
486 EditStreamEnd(This, streamNr) - This->pStreams[streamNr + 1].dwStart;
487
488 This->pStreams[streamNr].dwLength =
489 streamPos - This->pStreams[streamNr].dwStart;
490 This->sInfo.dwLength -= len;
491 len = 0;
492 }
493 }
494
495 This->sInfo.dwEditCount++;
496
497 return AVIERR_OK;
498 }
499
500 static HRESULT WINAPI IAVIEditStream_fnCopy(IAVIEditStream*iface,LONG*plStart,
501 LONG*plLength,PAVISTREAM*ppResult)
502 {
503 IAVIEditStreamImpl *This = (IAVIEditStreamImpl *)iface;
504 IAVIEditStreamImpl* pEdit;
505 HRESULT hr;
506 LONG start = 0;
507
508 TRACE("(%p,%p,%p,%p)\n",iface,plStart,plLength,ppResult);
509
510 if (ppResult == NULL)
511 return AVIERR_BADPARAM;
512 *ppResult = NULL;
513 if (plStart == NULL || plLength == NULL || *plStart < 0 || *plLength < 0)
514 return AVIERR_BADPARAM;
515
516 /* check bounds */
517 if (*(LPDWORD)plLength > This->sInfo.dwLength)
518 *(LPDWORD)plLength = This->sInfo.dwLength;
519 if (*(LPDWORD)plStart < This->sInfo.dwStart) {
520 *(LPDWORD)plLength -= This->sInfo.dwStart - *(LPDWORD)plStart;
521 *(LPDWORD)plStart = This->sInfo.dwStart;
522 if (*plLength < 0)
523 return AVIERR_BADPARAM;
524 }
525 if (*(LPDWORD)plStart + *(LPDWORD)plLength > This->sInfo.dwStart + This->sInfo.dwLength)
526 *(LPDWORD)plLength = This->sInfo.dwStart + This->sInfo.dwLength -
527 *(LPDWORD)plStart;
528
529 pEdit = (IAVIEditStreamImpl*)AVIFILE_CreateEditStream(NULL);
530 if (pEdit == NULL)
531 return AVIERR_MEMORY;
532
533 hr = IAVIEditStream_Paste((PAVIEDITSTREAM)pEdit,&start,plLength,
534 (PAVISTREAM)&This->iAVIStream,*plStart,
535 *plStart + *plLength);
536 *plStart = start;
537 if (FAILED(hr))
538 IAVIEditStream_Release((PAVIEDITSTREAM)pEdit);
539 else
540 *ppResult = (PAVISTREAM)&pEdit->iAVIStream;
541
542 return hr;
543 }
544
545 static HRESULT WINAPI IAVIEditStream_fnPaste(IAVIEditStream*iface,LONG*plStart,
546 LONG*plLength,PAVISTREAM pSource,
547 LONG lStart,LONG lLength)
548 {
549 IAVIEditStreamImpl *This = (IAVIEditStreamImpl *)iface;
550 AVISTREAMINFOW srcInfo;
551 IEditStreamInternal*pInternal = NULL;
552 IAVIEditStreamImpl *pEdit = NULL;
553 PAVISTREAM pStream;
554 DWORD startPos, endPos, streamNr, nStreams;
555 ULONG n;
556
557 TRACE("(%p,%p,%p,%p,%ld,%ld)\n",iface,plStart,plLength,
558 pSource,lStart,lLength);
559
560 if (pSource == NULL)
561 return AVIERR_BADHANDLE;
562 if (plStart == NULL || *plStart < 0)
563 return AVIERR_BADPARAM;
564 if (This->sInfo.dwStart + This->sInfo.dwLength < *plStart)
565 return AVIERR_BADPARAM; /* Can't paste with holes */
566 if (FAILED(IAVIStream_Info(pSource, &srcInfo, sizeof(srcInfo))))
567 return AVIERR_ERROR;
568 if (lStart < srcInfo.dwStart || lStart >= srcInfo.dwStart + srcInfo.dwLength)
569 return AVIERR_BADPARAM;
570 if (This->sInfo.fccType == 0) {
571 /* This stream is empty */
572 IAVIStream_Info(pSource, &This->sInfo, sizeof(This->sInfo));
573 This->sInfo.dwStart = *plStart;
574 This->sInfo.dwLength = 0;
575 }
576 if (This->sInfo.fccType != srcInfo.fccType)
577 return AVIERR_UNSUPPORTED; /* different stream types */
578 if (lLength == -1) /* Copy the hole stream */
579 lLength = srcInfo.dwLength;
580 if (lStart + lLength > srcInfo.dwStart + srcInfo.dwLength)
581 lLength = srcInfo.dwStart + srcInfo.dwLength - lStart;
582 if (lLength + *plStart >= 0x80000000)
583 return AVIERR_MEMORY;
584
585 /* streamtype specific tests */
586 if (srcInfo.fccType == streamtypeVIDEO) {
587 LONG size;
588
589 size = srcInfo.rcFrame.right - srcInfo.rcFrame.left;
590 if (size != This->sInfo.rcFrame.right - This->sInfo.rcFrame.left)
591 return AVIERR_UNSUPPORTED; /* FIXME: Can't GetFrame convert it? */
592 size = srcInfo.rcFrame.bottom - srcInfo.rcFrame.top;
593 if (size != This->sInfo.rcFrame.bottom - This->sInfo.rcFrame.top)
594 return AVIERR_UNSUPPORTED; /* FIXME: Can't GetFrame convert it? */
595 } else if (srcInfo.fccType == streamtypeAUDIO) {
596 if (! AVIFILE_FormatsEqual((PAVISTREAM)&This->iAVIStream, pSource))
597 return AVIERR_UNSUPPORTED;
598 } else {
599 /* FIXME: streamtypeMIDI and streamtypeTEXT */
600 return AVIERR_UNSUPPORTED;
601 }
602
603 /* try to get an IEditStreamInternal interface */
604 if (SUCCEEDED(IAVIStream_QueryInterface(pSource, &IID_IEditStreamInternal,
605 (LPVOID*)&pInternal))) {
606 pInternal->lpVtbl->GetEditStreamImpl(pInternal, (LPVOID*)&pEdit);
607 pInternal->lpVtbl->Release(pInternal);
608 }
609
610 /* for video must check for change of format */
611 if (This->sInfo.fccType == streamtypeVIDEO) {
612 if (! This->bDecompress) {
613 /* Need to decompress if any of the following conditions matches:
614 * - pSource is an editable stream which decompresses
615 * - the nearest keyframe of pSource isn't lStart
616 * - the nearest keyframe of this stream isn't *plStart
617 * - the format of pSource doesn't match this one
618 */
619 if ((pEdit != NULL && pEdit->bDecompress) ||
620 AVIStreamNearestKeyFrame(pSource, lStart) != lStart ||
621 AVIStreamNearestKeyFrame((PAVISTREAM)&This->iAVIStream, *plStart) != *plStart ||
622 (This->nStreams > 0 && !AVIFILE_FormatsEqual((PAVISTREAM)&This->iAVIStream, pSource))) {
623 /* Use first stream part to get format to convert everything to */
624 AVIFILE_ReadFrame(This, This->pStreams[0].pStream,
625 This->pStreams[0].dwStart);
626
627 /* Check if we could convert the source streams to the disired format... */
628 if (pEdit != NULL) {
629 if (FAILED(AVIFILE_FindStreamInTable(pEdit, lStart, &pStream,
630 &startPos, &streamNr, TRUE)))
631 return AVIERR_INTERNAL;
632 for (n = lStart; n < lStart + lLength; streamNr++) {
633 if (AVIFILE_ReadFrame(This, pEdit->pStreams[streamNr].pStream, startPos) == NULL)
634 return AVIERR_BADFORMAT;
635 startPos = pEdit->pStreams[streamNr].dwStart;
636 n += pEdit->pStreams[streamNr].dwLength;
637 }
638 } else if (AVIFILE_ReadFrame(This, pSource, lStart) == NULL)
639 return AVIERR_BADFORMAT;
640
641 This->bDecompress = TRUE;
642 This->sInfo.fccHandler = 0;
643 }
644 } else if (AVIFILE_ReadFrame(This, pSource, lStart) == NULL)
645 return AVIERR_BADFORMAT; /* Can't convert source to own format */
646 } /* FIXME: something special for the other formats? */
647
648 /* Make sure we have enough memory for parts */
649 if (pEdit != NULL) {
650 DWORD nLastStream;
651
652 AVIFILE_FindStreamInTable(pEdit, lStart + lLength, &pStream,
653 &endPos, &nLastStream, TRUE);
654 AVIFILE_FindStreamInTable(pEdit, lStart, &pStream,
655 &startPos, &streamNr, FALSE);
656 if (nLastStream == streamNr)
657 nLastStream++;
658
659 nStreams = nLastStream - streamNr;
660 } else
661 nStreams = 1;
662 if (This->nStreams + nStreams + 1 > This->nTableSize) {
663 n = This->nStreams + nStreams + 33;
664
665 This->pStreams =
666 GlobalReAllocPtr(This->pStreams, n * sizeof(EditStreamTable), GMEM_SHARE|GHND);
667 if (This->pStreams == NULL)
668 return AVIERR_MEMORY;
669 This->nTableSize = n;
670 }
671
672 if (plLength != NULL)
673 *plLength = lLength;
674
675 /* now do the real work */
676 if (This->sInfo.dwStart + This->sInfo.dwLength > *plStart) {
677 AVIFILE_FindStreamInTable(This, *plStart, &pStream,
678 &startPos, &streamNr, FALSE);
679 if (startPos != This->pStreams[streamNr].dwStart) {
680 /* split stream streamNr at startPos */
681 memmove(This->pStreams + streamNr + nStreams + 1,
682 This->pStreams + streamNr,
683 (This->nStreams + nStreams - streamNr + 1) * sizeof(EditStreamTable));
684
685 This->pStreams[streamNr + 2].dwLength =
686 EditStreamEnd(This, streamNr + 2) - startPos;
687 This->pStreams[streamNr + 2].dwStart = startPos;
688 This->pStreams[streamNr].dwLength =
689 startPos - This->pStreams[streamNr].dwStart;
690 IAVIStream_AddRef(This->pStreams[streamNr].pStream);
691 streamNr++;
692 } else {
693 /* insert before stream at streamNr */
694 memmove(This->pStreams + streamNr + nStreams, This->pStreams + streamNr,
695 (This->nStreams + nStreams - streamNr) * sizeof(EditStreamTable));
696 }
697 } else /* append the streams */
698 streamNr = This->nStreams;
699
700 if (pEdit != NULL) {
701 /* insert the parts of the editable stream instead of itself */
702 AVIFILE_FindStreamInTable(pEdit, lStart + lLength, &pStream,
703 &endPos, NULL, FALSE);
704 AVIFILE_FindStreamInTable(pEdit, lStart, &pStream, &startPos, &n, FALSE);
705
706 memcpy(This->pStreams + streamNr, pEdit->pStreams + n,
707 nStreams * sizeof(EditStreamTable));
708 if (This->pStreams[streamNr].dwStart < startPos) {
709 This->pStreams[streamNr].dwLength =
710 EditStreamEnd(This, streamNr) - startPos;
711 This->pStreams[streamNr].dwStart = startPos;
712 }
713 if (endPos < EditStreamEnd(This, streamNr + nStreams))
714 This->pStreams[streamNr + nStreams].dwLength =
715 endPos - This->pStreams[streamNr + nStreams].dwStart;
716 } else {
717 /* a simple stream */
718 This->pStreams[streamNr].pStream = pSource;
719 This->pStreams[streamNr].dwStart = lStart;
720 This->pStreams[streamNr].dwLength = lLength;
721 }
722
723 for (n = 0; n < nStreams; n++) {
724 IAVIStream_AddRef(This->pStreams[streamNr + n].pStream);
725 if (0 < streamNr + n &&
726 This->pStreams[streamNr + n - 1].pStream != This->pStreams[streamNr + n].pStream) {
727 This->sInfo.dwFlags |= AVISTREAMINFO_FORMATCHANGES;
728 This->sInfo.dwFormatChangeCount++;
729 }
730 }
731 This->sInfo.dwEditCount++;
732 This->sInfo.dwLength += lLength;
733 This->nStreams += nStreams;
734
735 return AVIERR_OK;
736 }
737
738 static HRESULT WINAPI IAVIEditStream_fnClone(IAVIEditStream*iface,
739 PAVISTREAM*ppResult)
740 {
741 IAVIEditStreamImpl *This = (IAVIEditStreamImpl *)iface;
742 IAVIEditStreamImpl* pEdit;
743 DWORD i;
744
745 TRACE("(%p,%p)\n",iface,ppResult);
746
747 if (ppResult == NULL)
748 return AVIERR_BADPARAM;
749 *ppResult = NULL;
750
751 pEdit = (IAVIEditStreamImpl*)AVIFILE_CreateEditStream(NULL);
752 if (pEdit == NULL)
753 return AVIERR_MEMORY;
754 if (This->nStreams > pEdit->nTableSize) {
755 pEdit->pStreams = GlobalReAllocPtr(pEdit->pStreams, This->nStreams * sizeof(EditStreamTable),GMEM_SHARE|GHND);
756 if (pEdit->pStreams == NULL)
757 return AVIERR_MEMORY;
758 pEdit->nTableSize = This->nStreams;
759 }
760 pEdit->nStreams = This->nStreams;
761 memcpy(pEdit->pStreams, This->pStreams,
762 This->nStreams * sizeof(EditStreamTable));
763 memcpy(&pEdit->sInfo,&This->sInfo,sizeof(This->sInfo));
764 for (i = 0; i < This->nStreams; i++) {
765 if (pEdit->pStreams[i].pStream != NULL)
766 IAVIStream_AddRef(pEdit->pStreams[i].pStream);
767 }
768
769 *ppResult = (PAVISTREAM)&pEdit->iAVIStream;
770
771 return AVIERR_OK;
772 }
773
774 static HRESULT WINAPI IAVIEditStream_fnSetInfo(IAVIEditStream*iface,
775 LPAVISTREAMINFOW asi,LONG size)
776 {
777 IAVIEditStreamImpl *This = (IAVIEditStreamImpl *)iface;
778
779 TRACE("(%p,%p,%ld)\n",iface,asi,size);
780
781 /* check parameters */
782 if (asi == NULL)
783 return AVIERR_BADPARAM;
784 if (size != sizeof(AVISTREAMINFOW))
785 return AVIERR_BADSIZE;
786 if (asi->dwScale == 0 || asi->dwRate == 0 || (LONG)asi->dwQuality < -1 ||
787 asi->dwQuality > ICQUALITY_HIGH)
788 return AVIERR_ERROR;
789
790 This->sInfo.wLanguage = asi->wLanguage;
791 This->sInfo.wPriority = asi->wPriority;
792 This->sInfo.dwStart = asi->dwStart;
793 if (asi->dwRate != 0)
794 This->sInfo.dwRate = asi->dwRate;
795 if (asi->dwScale != 0)
796 This->sInfo.dwScale = asi->dwScale;
797 if (asi->dwQuality <= ICQUALITY_HIGH)
798 This->sInfo.dwQuality = ICQUALITY_HIGH;
799 CopyRect(&This->sInfo.rcFrame, &asi->rcFrame);
800 memcpy(&This->sInfo.szName, &asi->szName, sizeof(asi->szName));
801 This->sInfo.dwEditCount++;
802
803 return AVIERR_OK;
804 }
805
806 static HRESULT WINAPI IEditAVIStream_fnQueryInterface(IAVIStream*iface,
807 REFIID refiid,LPVOID*obj)
808 {
809 IEditAVIStreamImpl *This = (IEditAVIStreamImpl *)iface;
810
811 assert(This->pae != NULL);
812
813 return IAVIEditStream_QueryInterface((IAVIEditStream*)This->pae,refiid,obj);
814 }
815
816 static ULONG WINAPI IEditAVIStream_fnAddRef(IAVIStream*iface)
817 {
818 IEditAVIStreamImpl *This = (IEditAVIStreamImpl *)iface;
819
820 assert(This->pae != NULL);
821
822 return IAVIEditStream_AddRef((IAVIEditStream*)This->pae);
823 }
824
825 static ULONG WINAPI IEditAVIStream_fnRelease(IAVIStream*iface)
826 {
827 IEditAVIStreamImpl *This = (IEditAVIStreamImpl *)iface;
828
829 assert(This->pae != NULL);
830
831 return IAVIEditStream_Release((IAVIEditStream*)This->pae);
832 }
833
834 static HRESULT WINAPI IEditAVIStream_fnCreate(IAVIStream*iface,
835 LPARAM lParam1,LPARAM lParam2)
836 {
837 IAVIEditStreamImpl *This = ((IEditAVIStreamImpl*)iface)->pae;
838
839 if (lParam2 != 0)
840 return AVIERR_ERROR;
841
842 if (This->pStreams == NULL) {
843 This->pStreams =
844 GlobalAllocPtr(GMEM_SHARE|GHND, 256 * sizeof(EditStreamTable));
845 if (This->pStreams == NULL)
846 return AVIERR_MEMORY;
847 This->nTableSize = 256;
848 }
849
850 if (lParam1 != 0) {
851 IAVIStream_Info((PAVISTREAM)lParam1, &This->sInfo, sizeof(This->sInfo));
852 IAVIStream_AddRef((PAVISTREAM)lParam1);
853 This->pStreams[0].pStream = (PAVISTREAM)lParam1;
854 This->pStreams[0].dwStart = This->sInfo.dwStart;
855 This->pStreams[0].dwLength = This->sInfo.dwLength;
856 This->nStreams = 1;
857 }
858 return AVIERR_OK;
859 }
860
861 static HRESULT WINAPI IEditAVIStream_fnInfo(IAVIStream*iface,
862 AVISTREAMINFOW *psi,LONG size)
863 {
864 IEditAVIStreamImpl *This = (IEditAVIStreamImpl *)iface;
865
866 TRACE("(%p,%p,%ld)\n",iface,psi,size);
867
868 assert(This->pae != NULL);
869
870 if (psi == NULL)
871 return AVIERR_BADPARAM;
872 if (size < 0)
873 return AVIERR_BADSIZE;
874
875 if (This->pae->bDecompress)
876 This->pae->sInfo.fccHandler = 0;
877
878 memcpy(psi, &This->pae->sInfo, min((DWORD)size, sizeof(This->pae->sInfo)));
879
880 if ((DWORD)size < sizeof(This->pae->sInfo))
881 return AVIERR_BUFFERTOOSMALL;
882 return AVIERR_OK;
883 }
884
885 static LONG WINAPI IEditAVIStream_fnFindSample(IAVIStream*iface,LONG pos,
886 LONG flags)
887 {
888 IAVIEditStreamImpl* const This = ((IEditAVIStreamImpl* const)iface)->pae;
889 PAVISTREAM stream;
890 DWORD streamPos, streamNr;
891
892 TRACE("(%p,%ld,0x%08lX)\n",iface,pos,flags);
893
894 if (flags & FIND_FROM_START)
895 pos = (LONG)This->sInfo.dwStart;
896
897 /* outside of stream? */
898 if (pos < (LONG)This->sInfo.dwStart ||
899 (LONG)This->sInfo.dwStart + (LONG)This->sInfo.dwLength <= pos)
900 return -1;
901
902 /* map our position to a stream and position in it */
903 if (AVIFILE_FindStreamInTable(This, pos, &stream, &streamPos,
904 &streamNr, TRUE))
905 return -1; /* doesn't exist */
906
907 if (This->bDecompress) {
908 /* only one stream -- format changes only at start */
909 if (flags & FIND_FORMAT)
910 return (flags & FIND_NEXT ? -1 : 0);
911
912 /* FIXME: map positions back to us */
913 return IAVIStream_FindSample(stream, streamPos, flags);
914 } else {
915 /* assume change of format every frame */
916 return pos;
917 }
918 }
919
920 static HRESULT WINAPI IEditAVIStream_fnReadFormat(IAVIStream*iface,LONG pos,
921 LPVOID format,LONG*fmtsize)
922 {
923 IAVIEditStreamImpl* const This = ((IEditAVIStreamImpl* const)iface)->pae;
924 LPBITMAPINFOHEADER lp;
925 PAVISTREAM stream;
926 DWORD n;
927 HRESULT hr;
928
929 TRACE("(%p,%ld,%p,%p)\n",iface,pos,format,fmtsize);
930
931 if (fmtsize == NULL || pos < This->sInfo.dwStart ||
932 This->sInfo.dwStart + This->sInfo.dwLength <= pos)
933 return AVIERR_BADPARAM;
934
935 /* find stream corresponding to position */
936 hr = AVIFILE_FindStreamInTable(This, pos, &stream, &n, NULL, FALSE);
937 if (FAILED(hr))
938 return hr;
939
940 if (! This->bDecompress)
941 return IAVIStream_ReadFormat(stream, n, format, fmtsize);
942
943 lp = (LPBITMAPINFOHEADER)AVIFILE_ReadFrame(This, stream, n);
944 if (lp == NULL)
945 return AVIERR_ERROR;
946 if (lp->biBitCount <= 8) {
947 n = (lp->biClrUsed > 0 ? lp->biClrUsed : 1 << lp->biBitCount);
948 n *= sizeof(RGBQUAD);
949 } else
950 n = 0;
951 n += lp->biSize;
952
953 memcpy(format, lp, min((LONG)n, *fmtsize));
954 hr = ((LONG)n > *fmtsize ? AVIERR_BUFFERTOOSMALL : AVIERR_OK);
955 *fmtsize = n;
956
957 return hr;
958 }
959
960 static HRESULT WINAPI IEditAVIStream_fnSetFormat(IAVIStream*iface,LONG pos,
961 LPVOID format,LONG formatsize)
962 {
963 TRACE("(%p,%ld,%p,%ld)\n",iface,pos,format,formatsize);
964
965 return AVIERR_UNSUPPORTED;
966 }
967
968 static HRESULT WINAPI IEditAVIStream_fnRead(IAVIStream*iface,LONG start,
969 LONG samples,LPVOID buffer,
970 LONG buffersize,LONG*bytesread,
971 LONG*samplesread)
972 {
973 IAVIEditStreamImpl* const This = ((IEditAVIStreamImpl* const)iface)->pae;
974 PAVISTREAM stream;
975 DWORD streamPos, streamNr;
976 LONG readBytes, readSamples, count;
977 HRESULT hr;
978
979 TRACE("(%p,%ld,%ld,%p,%ld,%p,%p) -- 0x%08lX\n",iface,start,samples,
980 buffer,buffersize,bytesread,samplesread,This->sInfo.fccType);
981
982 /* check parameters */
983 if (bytesread != NULL)
984 *bytesread = 0;
985 if (samplesread != NULL)
986 *samplesread = 0;
987 if (buffersize < 0)
988 return AVIERR_BADSIZE;
989 if ((DWORD)start < This->sInfo.dwStart ||
990 This->sInfo.dwStart + This->sInfo.dwLength < (DWORD)start)
991 return AVIERR_BADPARAM;
992
993 if (! This->bDecompress) {
994 /* audio like data -- sample-based */
995 do {
996 if (samples == 0)
997 return AVIERR_OK; /* nothing at all or already done */
998
999 if (FAILED(AVIFILE_FindStreamInTable(This, start, &stream,
1000 &streamPos, &streamNr, FALSE)))
1001 return AVIERR_ERROR;
1002
1003 /* limit to end of the stream */
1004 count = samples;
1005 if (streamPos + count > EditStreamEnd(This, streamNr))
1006 count = EditStreamEnd(This, streamNr) - streamPos;
1007
1008 hr = IAVIStream_Read(stream, streamPos, count, buffer, buffersize,
1009 &readBytes, &readSamples);
1010 if (FAILED(hr))
1011 return hr;
1012 if (readBytes == 0 && readSamples == 0 && count != 0)
1013 return AVIERR_FILEREAD; /* for bad stream implementations */
1014
1015 if (samplesread != NULL)
1016 *samplesread += readSamples;
1017 if (bytesread != NULL)
1018 *bytesread += readBytes;
1019 if (buffer != NULL) {
1020 buffer = ((LPBYTE)buffer)+readBytes;
1021 buffersize -= readBytes;
1022 }
1023 start += count;
1024 samples -= count;
1025 } while (This->sInfo.dwStart + This->sInfo.dwLength > start);
1026 } else {
1027 /* video like data -- frame-based */
1028 LPBITMAPINFOHEADER lp;
1029
1030 if (samples == 0)
1031 return AVIERR_OK;
1032
1033 if (FAILED(AVIFILE_FindStreamInTable(This, start, &stream,
1034 &streamPos, &streamNr, FALSE)))
1035 return AVIERR_ERROR;
1036
1037 lp = AVIFILE_ReadFrame(This, stream, streamPos);
1038 if (lp == NULL)
1039 return AVIERR_ERROR;
1040
1041 if (buffer != NULL) {
1042 /* need size of format to skip */
1043 if (lp->biBitCount <= 8) {
1044 count = lp->biClrUsed > 0 ? lp->biClrUsed : 1 << lp->biBitCount;
1045 count *= sizeof(RGBQUAD);
1046 } else
1047 count = 0;
1048 count += lp->biSize;
1049
1050 if (buffersize < lp->biSizeImage)
1051 return AVIERR_BUFFERTOOSMALL;
1052 memcpy(buffer, (LPBYTE)lp + count, lp->biSizeImage);
1053 }
1054
1055 if (bytesread != NULL)
1056 *bytesread = lp->biSizeImage;
1057 if (samplesread != NULL)
1058 *samplesread = 1;
1059 }
1060
1061 return AVIERR_OK;
1062 }
1063
1064 static HRESULT WINAPI IEditAVIStream_fnWrite(IAVIStream*iface,LONG start,
1065 LONG samples,LPVOID buffer,
1066 LONG buffersize,DWORD flags,
1067 LONG*sampwritten,LONG*byteswritten)
1068 {
1069 TRACE("(%p,%ld,%ld,%p,%ld,0x%08lX,%p,%p)\n",iface,start,samples,buffer,
1070 buffersize,flags,sampwritten,byteswritten);
1071
1072 /* be sure return parameters have correct values */
1073 if (sampwritten != NULL)
1074 *sampwritten = 0;
1075 if (byteswritten != NULL)
1076 *byteswritten = 0;
1077
1078 return AVIERR_UNSUPPORTED;
1079 }
1080
1081 static HRESULT WINAPI IEditAVIStream_fnDelete(IAVIStream*iface,LONG start,
1082 LONG samples)
1083 {
1084 IEditAVIStreamImpl *This = (IEditAVIStreamImpl *)iface;
1085
1086 TRACE("(%p,%ld,%ld)\n",iface,start,samples);
1087
1088 return IAVIEditStream_Cut((IAVIEditStream*)This->pae,&start,&samples,NULL);
1089 }
1090
1091 static HRESULT WINAPI IEditAVIStream_fnReadData(IAVIStream*iface,DWORD fcc,
1092 LPVOID lp,LONG *lpread)
1093 {
1094 IAVIEditStreamImpl* const This = ((IEditAVIStreamImpl* const)iface)->pae;
1095 DWORD n;
1096
1097 TRACE("(%p,0x%08lX,%p,%p)\n",iface,fcc,lp,lpread);
1098
1099 /* check parameters */
1100 if (lp == NULL || lpread == NULL)
1101 return AVIERR_BADPARAM;
1102
1103 /* simply ask every stream and return the first block found */
1104 for (n = 0; n < This->nStreams; n++) {
1105 HRESULT hr = IAVIStream_ReadData(This->pStreams[n].pStream,fcc,lp,lpread);
1106
1107 if (SUCCEEDED(hr))
1108 return hr;
1109 }
1110
1111 *lpread = 0;
1112 return AVIERR_NODATA;
1113 }
1114
1115 static HRESULT WINAPI IEditAVIStream_fnWriteData(IAVIStream*iface,DWORD fcc,
1116 LPVOID lp,LONG size)
1117 {
1118 TRACE("(%p,0x%08lX,%p,%ld)\n",iface,fcc,lp,size);
1119
1120 return AVIERR_UNSUPPORTED;
1121 }
1122
1123 static HRESULT WINAPI IEditAVIStream_fnSetInfo(IAVIStream*iface,
1124 AVISTREAMINFOW*info,LONG len)
1125 {
1126 IEditAVIStreamImpl *This = (IEditAVIStreamImpl *)iface;
1127
1128 TRACE("(%p,%p,%ld)\n",iface,info,len);
1129
1130 return IAVIEditStream_SetInfo((IAVIEditStream*)This->pae,info,len);
1131 }
1132
1133 static HRESULT WINAPI IEditStreamInternal_fnQueryInterface(IEditStreamInternal*iface,REFIID refiid,LPVOID*obj)
1134 {
1135 IEditStreamInternalImpl *This = (IEditStreamInternalImpl *)iface;
1136
1137 assert(This->pae != NULL);
1138
1139 return IAVIEditStream_QueryInterface((IAVIEditStream*)This->pae, refiid, obj);
1140 }
1141
1142 static ULONG WINAPI IEditStreamInternal_fnAddRef(IEditStreamInternal*iface)
1143 {
1144 IEditStreamInternalImpl *This = (IEditStreamInternalImpl *)iface;
1145
1146 assert(This->pae != NULL);
1147
1148 return IAVIEditStream_AddRef((IAVIEditStream*)This->pae);
1149 }
1150
1151 static ULONG WINAPI IEditStreamInternal_fnRelease(IEditStreamInternal*iface)
1152 {
1153 IEditStreamInternalImpl *This = (IEditStreamInternalImpl *)iface;
1154
1155 assert(This->pae != NULL);
1156
1157 return IAVIEditStream_Release((IAVIEditStream*)This->pae);
1158 }
1159
1160 static HRESULT WINAPI IEditStreamInternal_fnGetEditStreamImpl(IEditStreamInternal*iface,LPVOID*ppimpl)
1161 {
1162 IEditStreamInternalImpl *This = (IEditStreamInternalImpl *)iface;
1163
1164 TRACE("(%p,%p) -> %p\n", iface, ppimpl, This->pae);
1165
1166 assert(This->pae != NULL);
1167 assert(ppimpl != NULL);
1168
1169 *ppimpl = This->pae;
1170 return AVIERR_OK;
1171 }