2 * Copyright (C) 2013 Piotr Caban for CodeWeavers
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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
31 #include "qcap_main.h"
33 #include "wine/debug.h"
35 WINE_DEFAULT_DEBUG_CHANNEL(qcap
);
37 #define MAX_PIN_NO 128
38 #define AVISUPERINDEX_ENTRIES 2000
39 #define AVISTDINDEX_ENTRIES 4000
40 #define ALIGN(x) ((x+1)/2*2)
44 IQualityControl IQualityControl_iface
;
60 IAMStreamControl IAMStreamControl_iface
;
61 IPropertyBag IPropertyBag_iface
;
62 IQualityControl IQualityControl_iface
;
64 REFERENCE_TIME avg_time_per_frame
;
77 BYTE indx_data
[FIELD_OFFSET(AVISUPERINDEX
, aIndex
[AVISUPERINDEX_ENTRIES
])];
82 BYTE ix_data
[FIELD_OFFSET(AVISTDINDEX
, aIndex
[AVISTDINDEX_ENTRIES
])];
84 IMediaSample
*samples_head
;
85 IMemAllocator
*samples_allocator
;
90 IConfigAviMux IConfigAviMux_iface
;
91 IConfigInterleaving IConfigInterleaving_iface
;
92 IMediaSeeking IMediaSeeking_iface
;
93 IPersistMediaPropertyBag IPersistMediaPropertyBag_iface
;
94 ISpecifyPropertyPages ISpecifyPropertyPages_iface
;
96 InterleavingMode mode
;
97 REFERENCE_TIME interleave
;
98 REFERENCE_TIME preroll
;
102 AviMuxIn
*in
[MAX_PIN_NO
-1];
104 REFERENCE_TIME start
, stop
;
112 static HRESULT
create_input_pin(AviMux
*);
114 static inline AviMux
* impl_from_BaseFilter(BaseFilter
*filter
)
116 return CONTAINING_RECORD(filter
, AviMux
, filter
);
119 static IPin
* WINAPI
AviMux_GetPin(BaseFilter
*iface
, int pos
)
121 AviMux
*This
= impl_from_BaseFilter(iface
);
123 TRACE("(%p)->(%d)\n", This
, pos
);
126 IPin_AddRef(&This
->out
->pin
.pin
.IPin_iface
);
127 return &This
->out
->pin
.pin
.IPin_iface
;
128 }else if(pos
>0 && pos
<=This
->input_pin_no
) {
129 IPin_AddRef(&This
->in
[pos
-1]->pin
.pin
.IPin_iface
);
130 return &This
->in
[pos
-1]->pin
.pin
.IPin_iface
;
136 static const BaseFilterFuncTable filter_func_table
= {
140 static inline AviMux
* impl_from_IBaseFilter(IBaseFilter
*iface
)
142 BaseFilter
*filter
= CONTAINING_RECORD(iface
, BaseFilter
, IBaseFilter_iface
);
143 return impl_from_BaseFilter(filter
);
146 static HRESULT WINAPI
AviMux_QueryInterface(IBaseFilter
*iface
, REFIID riid
, void **ppv
)
148 AviMux
*This
= impl_from_IBaseFilter(iface
);
150 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), ppv
);
152 if(IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IPersist
) ||
153 IsEqualIID(riid
, &IID_IMediaFilter
) || IsEqualIID(riid
, &IID_IBaseFilter
))
154 *ppv
= &This
->filter
.IBaseFilter_iface
;
155 else if(IsEqualIID(riid
, &IID_IConfigAviMux
))
156 *ppv
= &This
->IConfigAviMux_iface
;
157 else if(IsEqualIID(riid
, &IID_IConfigInterleaving
))
158 *ppv
= &This
->IConfigInterleaving_iface
;
159 else if(IsEqualIID(riid
, &IID_IMediaSeeking
))
160 *ppv
= &This
->IMediaSeeking_iface
;
161 else if(IsEqualIID(riid
, &IID_IPersistMediaPropertyBag
))
162 *ppv
= &This
->IPersistMediaPropertyBag_iface
;
163 else if(IsEqualIID(riid
, &IID_ISpecifyPropertyPages
))
164 *ppv
= &This
->ISpecifyPropertyPages_iface
;
166 FIXME("no interface for %s\n", debugstr_guid(riid
));
168 return E_NOINTERFACE
;
171 IUnknown_AddRef((IUnknown
*)*ppv
);
175 static ULONG WINAPI
AviMux_Release(IBaseFilter
*iface
)
177 AviMux
*This
= impl_from_IBaseFilter(iface
);
178 ULONG ref
= BaseFilterImpl_Release(iface
);
180 TRACE("(%p) new refcount: %u\n", This
, ref
);
185 BaseOutputPinImpl_Release(&This
->out
->pin
.pin
.IPin_iface
);
187 for(i
=0; i
<This
->input_pin_no
; i
++) {
188 IPin_Disconnect(&This
->in
[i
]->pin
.pin
.IPin_iface
);
189 IMemAllocator_Release(This
->in
[i
]->samples_allocator
);
190 This
->in
[i
]->samples_allocator
= NULL
;
191 BaseInputPinImpl_Release(&This
->in
[i
]->pin
.pin
.IPin_iface
);
194 HeapFree(GetProcessHeap(), 0, This
->idx1
);
195 HeapFree(GetProcessHeap(), 0, This
);
196 ObjectRefCount(FALSE
);
201 static HRESULT
out_flush(AviMux
*This
)
206 if(!This
->out
->buf_pos
)
209 hr
= IStream_Write(This
->out
->stream
, This
->out
->buf
, This
->out
->buf_pos
, &written
);
212 if(written
!= This
->out
->buf_pos
)
215 This
->out
->buf_pos
= 0;
219 static HRESULT
out_seek(AviMux
*This
, int pos
)
224 hr
= out_flush(This
);
229 hr
= IStream_Seek(This
->out
->stream
, li
, STREAM_SEEK_SET
, NULL
);
233 This
->out
->out_pos
= pos
;
234 if(This
->out
->out_pos
> This
->out
->size
)
235 This
->out
->size
= This
->out
->out_pos
;
239 static HRESULT
out_write(AviMux
*This
, const void *data
, int size
)
245 if(size
> sizeof(This
->out
->buf
)-This
->out
->buf_pos
)
246 chunk_size
= sizeof(This
->out
->buf
)-This
->out
->buf_pos
;
250 memcpy(This
->out
->buf
+ This
->out
->buf_pos
, data
, chunk_size
);
252 data
= (const BYTE
*)data
+ chunk_size
;
253 This
->out
->buf_pos
+= chunk_size
;
254 This
->out
->out_pos
+= chunk_size
;
255 if(This
->out
->out_pos
> This
->out
->size
)
256 This
->out
->size
= This
->out
->out_pos
;
260 hr
= out_flush(This
);
268 static inline HRESULT
idx1_add_entry(AviMux
*avimux
, DWORD ckid
, DWORD flags
, DWORD off
, DWORD len
)
270 if(avimux
->idx1_entries
== avimux
->idx1_size
) {
271 AVIINDEXENTRY
*new_idx
= HeapReAlloc(GetProcessHeap(), 0, avimux
->idx1
,
272 sizeof(*avimux
->idx1
)*2*avimux
->idx1_size
);
274 return E_OUTOFMEMORY
;
276 avimux
->idx1_size
*= 2;
277 avimux
->idx1
= new_idx
;
280 avimux
->idx1
[avimux
->idx1_entries
].ckid
= ckid
;
281 avimux
->idx1
[avimux
->idx1_entries
].dwFlags
= flags
;
282 avimux
->idx1
[avimux
->idx1_entries
].dwChunkOffset
= off
;
283 avimux
->idx1
[avimux
->idx1_entries
].dwChunkLength
= len
;
284 avimux
->idx1_entries
++;
288 static HRESULT
flush_queue(AviMux
*avimux
, AviMuxIn
*avimuxin
, BOOL closing
)
290 IMediaSample
*sample
, **prev
, **head_prev
;
297 if(avimux
->out
->cur_stream
!= avimuxin
->stream_id
)
300 while(avimuxin
->samples_head
) {
301 hr
= IMediaSample_GetPointer(avimuxin
->samples_head
, (BYTE
**)&head_prev
);
306 hr
= IMediaSample_GetPointer(*head_prev
, (BYTE
**)&prev
);
312 size
= IMediaSample_GetActualDataLength(sample
);
313 hr
= IMediaSample_GetPointer(sample
, &data
);
316 flags
= IMediaSample_IsDiscontinuity(sample
)==S_OK
? AM_SAMPLE_TIMEDISCONTINUITY
: 0;
317 if(IMediaSample_IsSyncPoint(sample
) == S_OK
)
318 flags
|= AM_SAMPLE_SPLICEPOINT
;
320 if(avimuxin
->stream_time
+ (closing
? 0 : avimuxin
->strh
.dwScale
) > avimux
->out
->cur_time
&&
321 !(flags
& AM_SAMPLE_TIMEDISCONTINUITY
)) {
325 avimux
->out
->cur_stream
++;
326 if(avimux
->out
->cur_stream
>= avimux
->input_pin_no
-1) {
327 avimux
->out
->cur_time
+= avimux
->interleave
;
328 avimux
->out
->cur_stream
= 0;
330 avimuxin
= avimux
->in
[avimux
->out
->cur_stream
];
334 if(avimuxin
->ix
->nEntriesInUse
== AVISTDINDEX_ENTRIES
) {
335 /* TODO: use output pins Deliver/Receive method */
336 hr
= out_seek(avimux
, avimuxin
->ix_off
);
339 hr
= out_write(avimux
, avimuxin
->ix
, sizeof(avimuxin
->ix_data
));
343 avimuxin
->indx
->aIndex
[avimuxin
->indx
->nEntriesInUse
].qwOffset
= avimuxin
->ix_off
;
344 avimuxin
->indx
->aIndex
[avimuxin
->indx
->nEntriesInUse
].dwSize
= sizeof(avimuxin
->ix_data
);
345 avimuxin
->indx
->aIndex
[avimuxin
->indx
->nEntriesInUse
].dwDuration
= AVISTDINDEX_ENTRIES
;
346 avimuxin
->indx
->nEntriesInUse
++;
348 memset(avimuxin
->ix
->aIndex
, 0, sizeof(avimuxin
->ix
->aIndex
)*avimuxin
->ix
->nEntriesInUse
);
349 avimuxin
->ix
->nEntriesInUse
= 0;
350 avimuxin
->ix
->qwBaseOffset
= 0;
352 avimuxin
->ix_off
= avimux
->out
->size
;
353 avimux
->out
->size
+= sizeof(avimuxin
->ix_data
);
356 if(*head_prev
== avimuxin
->samples_head
)
357 avimuxin
->samples_head
= NULL
;
361 avimuxin
->stream_time
+= avimuxin
->strh
.dwScale
;
362 avimuxin
->strh
.dwLength
++;
363 if(!(flags
& AM_SAMPLE_TIMEDISCONTINUITY
)) {
364 if(!avimuxin
->ix
->qwBaseOffset
)
365 avimuxin
->ix
->qwBaseOffset
= avimux
->out
->size
;
366 avimuxin
->ix
->aIndex
[avimuxin
->ix
->nEntriesInUse
].dwOffset
= avimux
->out
->size
367 + sizeof(RIFFCHUNK
) - avimuxin
->ix
->qwBaseOffset
;
369 hr
= out_seek(avimux
, avimux
->out
->size
);
371 IMediaSample_Release(sample
);
375 avimuxin
->ix
->aIndex
[avimuxin
->ix
->nEntriesInUse
].dwSize
= size
|
376 (flags
& AM_SAMPLE_SPLICEPOINT
? 0 : AVISTDINDEX_DELTAFRAME
);
377 avimuxin
->ix
->nEntriesInUse
++;
379 rf
.fcc
= FCC('0'+avimuxin
->stream_id
/10, '0'+avimuxin
->stream_id
%10,
380 'd', flags
& AM_SAMPLE_SPLICEPOINT
? 'b' : 'c');
382 hr
= idx1_add_entry(avimux
, rf
.fcc
, flags
& AM_SAMPLE_SPLICEPOINT
? AVIIF_KEYFRAME
: 0,
383 flags
& AM_SAMPLE_TIMEDISCONTINUITY
?
384 avimux
->idx1
[avimux
->idx1_entries
-1].dwChunkOffset
: avimux
->out
->size
, size
);
386 IMediaSample_Release(sample
);
390 if(!(flags
& AM_SAMPLE_TIMEDISCONTINUITY
)) {
391 hr
= out_write(avimux
, &rf
, sizeof(rf
));
393 IMediaSample_Release(sample
);
396 hr
= out_write(avimux
, data
, size
);
398 IMediaSample_Release(sample
);
402 hr
= out_write(avimux
, &flags
, ALIGN(rf
.cb
)-rf
.cb
);
404 IMediaSample_Release(sample
);
408 IMediaSample_Release(sample
);
413 static HRESULT
queue_sample(AviMux
*avimux
, AviMuxIn
*avimuxin
, IMediaSample
*sample
)
415 IMediaSample
**prev
, **head_prev
;
418 hr
= IMediaSample_GetPointer(sample
, (BYTE
**)&prev
);
423 if(avimuxin
->samples_head
) {
424 hr
= IMediaSample_GetPointer(avimuxin
->samples_head
, (BYTE
**)&head_prev
);
434 avimuxin
->samples_head
= sample
;
435 IMediaSample_AddRef(sample
);
437 return flush_queue(avimux
, avimuxin
, FALSE
);
440 static HRESULT WINAPI
AviMux_Stop(IBaseFilter
*iface
)
442 AviMux
*This
= impl_from_IBaseFilter(iface
);
446 TRACE("(%p)\n", This
);
448 if(This
->filter
.state
== State_Stopped
)
451 if(This
->out
->stream
) {
455 int idx1_off
, empty_stream
;
457 empty_stream
= This
->out
->cur_stream
;
458 for(i
=empty_stream
+1; ; i
++) {
459 if(i
>= This
->input_pin_no
-1)
461 if(i
== empty_stream
)
464 This
->out
->cur_stream
= i
;
465 hr
= flush_queue(This
, This
->in
[This
->out
->cur_stream
], TRUE
);
470 idx1_off
= This
->out
->size
;
471 rc
.fcc
= ckidAVIOLDINDEX
;
472 rc
.cb
= This
->idx1_entries
* sizeof(*This
->idx1
);
473 hr
= out_write(This
, &rc
, sizeof(rc
));
476 hr
= out_write(This
, This
->idx1
, This
->idx1_entries
* sizeof(*This
->idx1
));
479 /* native writes 8 '\0' characters after the end of RIFF data */
481 hr
= out_write(This
, &i
, sizeof(i
));
484 hr
= out_write(This
, &i
, sizeof(i
));
488 for(i
=0; i
<This
->input_pin_no
; i
++) {
489 if(!This
->in
[i
]->pin
.pin
.pConnectedTo
)
492 hr
= out_seek(This
, This
->in
[i
]->ix_off
);
496 This
->in
[i
]->indx
->aIndex
[This
->in
[i
]->indx
->nEntriesInUse
].qwOffset
= This
->in
[i
]->ix_off
;
497 This
->in
[i
]->indx
->aIndex
[This
->in
[i
]->indx
->nEntriesInUse
].dwSize
= sizeof(This
->in
[i
]->ix_data
);
498 This
->in
[i
]->indx
->aIndex
[This
->in
[i
]->indx
->nEntriesInUse
].dwDuration
= This
->in
[i
]->strh
.dwLength
;
499 if(This
->in
[i
]->indx
->nEntriesInUse
) {
500 This
->in
[i
]->indx
->aIndex
[This
->in
[i
]->indx
->nEntriesInUse
].dwDuration
-=
501 This
->in
[i
]->indx
->aIndex
[This
->in
[i
]->indx
->nEntriesInUse
-1].dwDuration
;
503 This
->in
[i
]->indx
->nEntriesInUse
++;
504 hr
= out_write(This
, This
->in
[i
]->ix
, sizeof(This
->in
[i
]->ix_data
));
509 hr
= out_seek(This
, 0);
513 rl
.fcc
= FCC('R','I','F','F');
514 rl
.cb
= This
->out
->size
-sizeof(RIFFCHUNK
)-2*sizeof(int);
515 rl
.fccListType
= FCC('A','V','I',' ');
516 hr
= out_write(This
, &rl
, sizeof(rl
));
520 rl
.fcc
= FCC('L','I','S','T');
521 rl
.cb
= This
->out
->movi_off
- sizeof(RIFFLIST
) - sizeof(RIFFCHUNK
);
522 rl
.fccListType
= FCC('h','d','r','l');
523 hr
= out_write(This
, &rl
, sizeof(rl
));
527 /* FIXME: set This->avih.dwMaxBytesPerSec value */
528 This
->avih
.dwTotalFrames
= (This
->stop
-This
->start
) / 10 / This
->avih
.dwMicroSecPerFrame
;
529 hr
= out_write(This
, &This
->avih
, sizeof(This
->avih
));
533 for(i
=0; i
<This
->input_pin_no
; i
++) {
534 if(!This
->in
[i
]->pin
.pin
.pConnectedTo
)
537 rl
.cb
= sizeof(FOURCC
) + sizeof(AVISTREAMHEADER
) + sizeof(RIFFCHUNK
) +
538 This
->in
[i
]->strf
->cb
+ sizeof(This
->in
[i
]->indx_data
);
539 rl
.fccListType
= ckidSTREAMLIST
;
540 hr
= out_write(This
, &rl
, sizeof(rl
));
544 hr
= out_write(This
, &This
->in
[i
]->strh
, sizeof(AVISTREAMHEADER
));
548 hr
= out_write(This
, This
->in
[i
]->strf
, sizeof(RIFFCHUNK
) + This
->in
[i
]->strf
->cb
);
552 hr
= out_write(This
, This
->in
[i
]->indx
, sizeof(This
->in
[i
]->indx_data
));
557 rl
.cb
= sizeof(dmlh
) + sizeof(FOURCC
);
558 rl
.fccListType
= ckidODML
;
559 hr
= out_write(This
, &rl
, sizeof(rl
));
563 memset(&dmlh
, 0, sizeof(dmlh
));
564 dmlh
.fcc
= ckidAVIEXTHEADER
;
565 dmlh
.cb
= sizeof(dmlh
) - sizeof(RIFFCHUNK
);
566 dmlh
.dwGrandFrames
= This
->in
[0]->strh
.dwLength
;
567 hr
= out_write(This
, &dmlh
, sizeof(dmlh
));
569 rl
.cb
= idx1_off
- This
->out
->movi_off
- sizeof(RIFFCHUNK
);
570 rl
.fccListType
= FCC('m','o','v','i');
571 out_write(This
, &rl
, sizeof(rl
));
574 IStream_Release(This
->out
->stream
);
575 This
->out
->stream
= NULL
;
578 This
->filter
.state
= State_Stopped
;
582 static HRESULT WINAPI
AviMux_Pause(IBaseFilter
*iface
)
584 AviMux
*This
= impl_from_IBaseFilter(iface
);
585 FIXME("(%p)\n", This
);
589 static HRESULT WINAPI
AviMux_Run(IBaseFilter
*iface
, REFERENCE_TIME tStart
)
591 AviMux
*This
= impl_from_IBaseFilter(iface
);
595 TRACE("(%p)->(%s)\n", This
, wine_dbgstr_longlong(tStart
));
597 if(This
->filter
.state
== State_Running
)
600 if(This
->mode
!= INTERLEAVE_FULL
) {
601 FIXME("mode not supported (%d)\n", This
->mode
);
606 FIXME("tStart parameter ignored\n");
608 for(i
=0; i
<This
->input_pin_no
; i
++) {
612 if(!This
->in
[i
]->pin
.pin
.pConnectedTo
)
615 hr
= IPin_QueryInterface(This
->in
[i
]->pin
.pin
.pConnectedTo
,
616 &IID_IMediaSeeking
, (void**)&ms
);
620 hr
= IMediaSeeking_GetPositions(ms
, &cur
, &stop
);
622 IMediaSeeking_Release(ms
);
626 FIXME("Use IMediaSeeking to fill stream header\n");
627 IMediaSeeking_Release(ms
);
630 if(This
->out
->pin
.pMemInputPin
) {
631 hr
= IMemInputPin_QueryInterface(This
->out
->pin
.pMemInputPin
,
632 &IID_IStream
, (void**)&This
->out
->stream
);
637 This
->idx1_entries
= 0;
638 if(!This
->idx1_size
) {
639 This
->idx1_size
= 1024;
640 This
->idx1
= HeapAlloc(GetProcessHeap(), 0, sizeof(*This
->idx1
)*This
->idx1_size
);
642 return E_OUTOFMEMORY
;
645 This
->out
->size
= 3*sizeof(RIFFLIST
) + sizeof(AVIMAINHEADER
) + sizeof(AVIEXTHEADER
);
648 memset(&This
->avih
, 0, sizeof(This
->avih
));
649 for(i
=0; i
<This
->input_pin_no
; i
++) {
650 if(!This
->in
[i
]->pin
.pin
.pConnectedTo
)
653 This
->avih
.dwStreams
++;
654 This
->out
->size
+= sizeof(RIFFLIST
) + sizeof(AVISTREAMHEADER
) + sizeof(RIFFCHUNK
)
655 + This
->in
[i
]->strf
->cb
+ sizeof(This
->in
[i
]->indx_data
);
657 This
->in
[i
]->strh
.dwScale
= MulDiv(This
->in
[i
]->avg_time_per_frame
, This
->interleave
, 10000000);
658 This
->in
[i
]->strh
.dwRate
= This
->interleave
;
660 hr
= IMemAllocator_Commit(This
->in
[i
]->pin
.pAllocator
);
662 if(This
->out
->stream
) {
663 IStream_Release(This
->out
->stream
);
664 This
->out
->stream
= NULL
;
670 This
->out
->movi_off
= This
->out
->size
;
671 This
->out
->size
+= sizeof(RIFFLIST
);
673 idx1_add_entry(This
, FCC('7','F','x','x'), 0, This
->out
->movi_off
+sizeof(RIFFLIST
), 0);
676 for(i
=0; i
<This
->input_pin_no
; i
++) {
677 if(!This
->in
[i
]->pin
.pin
.pConnectedTo
)
680 This
->in
[i
]->ix_off
= This
->out
->size
;
681 This
->out
->size
+= sizeof(This
->in
[i
]->ix_data
);
682 This
->in
[i
]->ix
->fcc
= FCC('i','x','0'+stream_id
/10,'0'+stream_id
%10);
683 This
->in
[i
]->ix
->cb
= sizeof(This
->in
[i
]->ix_data
) - sizeof(RIFFCHUNK
);
684 This
->in
[i
]->ix
->wLongsPerEntry
= 2;
685 This
->in
[i
]->ix
->bIndexSubType
= 0;
686 This
->in
[i
]->ix
->bIndexType
= AVI_INDEX_OF_CHUNKS
;
687 This
->in
[i
]->ix
->dwChunkId
= FCC('0'+stream_id
/10,'0'+stream_id
%10,'d','b');
688 This
->in
[i
]->ix
->qwBaseOffset
= 0;
690 This
->in
[i
]->indx
->fcc
= ckidAVISUPERINDEX
;
691 This
->in
[i
]->indx
->cb
= sizeof(This
->in
[i
]->indx_data
) - sizeof(RIFFCHUNK
);
692 This
->in
[i
]->indx
->wLongsPerEntry
= 4;
693 This
->in
[i
]->indx
->bIndexSubType
= 0;
694 This
->in
[i
]->indx
->bIndexType
= AVI_INDEX_OF_INDEXES
;
695 This
->in
[i
]->indx
->dwChunkId
= This
->in
[i
]->ix
->dwChunkId
;
696 This
->in
[i
]->stream_id
= stream_id
++;
699 This
->out
->buf_pos
= 0;
700 This
->out
->out_pos
= 0;
702 This
->avih
.fcc
= ckidMAINAVIHEADER
;
703 This
->avih
.cb
= sizeof(AVIMAINHEADER
) - sizeof(RIFFCHUNK
);
704 /* TODO: Use first video stream */
705 This
->avih
.dwMicroSecPerFrame
= This
->in
[0]->avg_time_per_frame
/10;
706 This
->avih
.dwPaddingGranularity
= 1;
707 This
->avih
.dwFlags
= AVIF_TRUSTCKTYPE
| AVIF_HASINDEX
;
708 This
->avih
.dwWidth
= ((BITMAPINFOHEADER
*)This
->in
[0]->strf
->data
)->biWidth
;
709 This
->avih
.dwHeight
= ((BITMAPINFOHEADER
*)This
->in
[0]->strf
->data
)->biHeight
;
711 This
->filter
.state
= State_Running
;
715 static HRESULT WINAPI
AviMux_EnumPins(IBaseFilter
*iface
, IEnumPins
**ppEnum
)
717 AviMux
*This
= impl_from_IBaseFilter(iface
);
718 TRACE("(%p)->(%p)\n", This
, ppEnum
);
719 return BaseFilterImpl_EnumPins(iface
, ppEnum
);
722 static HRESULT WINAPI
AviMux_FindPin(IBaseFilter
*iface
, LPCWSTR Id
, IPin
**ppPin
)
724 AviMux
*This
= impl_from_IBaseFilter(iface
);
727 TRACE("(%p)->(%s %p)\n", This
, debugstr_w(Id
), ppPin
);
732 if(!lstrcmpiW(Id
, This
->out
->pin
.pin
.pinInfo
.achName
)) {
733 IPin_AddRef(&This
->out
->pin
.pin
.IPin_iface
);
734 *ppPin
= &This
->out
->pin
.pin
.IPin_iface
;
738 for(i
=0; i
<This
->input_pin_no
; i
++) {
739 if(lstrcmpiW(Id
, This
->in
[i
]->pin
.pin
.pinInfo
.achName
))
742 IPin_AddRef(&This
->in
[i
]->pin
.pin
.IPin_iface
);
743 *ppPin
= &This
->in
[i
]->pin
.pin
.IPin_iface
;
747 return VFW_E_NOT_FOUND
;
750 static HRESULT WINAPI
AviMux_QueryFilterInfo(IBaseFilter
*iface
, FILTER_INFO
*pInfo
)
752 AviMux
*This
= impl_from_IBaseFilter(iface
);
753 FIXME("(%p)->(%p)\n", This
, pInfo
);
757 static HRESULT WINAPI
AviMux_QueryVendorInfo(IBaseFilter
*iface
, LPWSTR
*pVendorInfo
)
759 AviMux
*This
= impl_from_IBaseFilter(iface
);
760 FIXME("(%p)->(%p)\n", This
, pVendorInfo
);
764 static const IBaseFilterVtbl AviMuxVtbl
= {
765 AviMux_QueryInterface
,
766 BaseFilterImpl_AddRef
,
768 BaseFilterImpl_GetClassID
,
772 BaseFilterImpl_GetState
,
773 BaseFilterImpl_SetSyncSource
,
774 BaseFilterImpl_GetSyncSource
,
777 AviMux_QueryFilterInfo
,
778 BaseFilterImpl_JoinFilterGraph
,
779 AviMux_QueryVendorInfo
782 static inline AviMux
* impl_from_IConfigAviMux(IConfigAviMux
*iface
)
784 return CONTAINING_RECORD(iface
, AviMux
, IConfigAviMux_iface
);
787 static HRESULT WINAPI
ConfigAviMux_QueryInterface(
788 IConfigAviMux
*iface
, REFIID riid
, void **ppv
)
790 AviMux
*This
= impl_from_IConfigAviMux(iface
);
791 return IBaseFilter_QueryInterface(&This
->filter
.IBaseFilter_iface
, riid
, ppv
);
794 static ULONG WINAPI
ConfigAviMux_AddRef(IConfigAviMux
*iface
)
796 AviMux
*This
= impl_from_IConfigAviMux(iface
);
797 return IBaseFilter_AddRef(&This
->filter
.IBaseFilter_iface
);
800 static ULONG WINAPI
ConfigAviMux_Release(IConfigAviMux
*iface
)
802 AviMux
*This
= impl_from_IConfigAviMux(iface
);
803 return IBaseFilter_Release(&This
->filter
.IBaseFilter_iface
);
806 static HRESULT WINAPI
ConfigAviMux_SetMasterStream(IConfigAviMux
*iface
, LONG iStream
)
808 AviMux
*This
= impl_from_IConfigAviMux(iface
);
809 FIXME("(%p)->(%d)\n", This
, iStream
);
813 static HRESULT WINAPI
ConfigAviMux_GetMasterStream(IConfigAviMux
*iface
, LONG
*pStream
)
815 AviMux
*This
= impl_from_IConfigAviMux(iface
);
816 FIXME("(%p)->(%p)\n", This
, pStream
);
820 static HRESULT WINAPI
ConfigAviMux_SetOutputCompatibilityIndex(
821 IConfigAviMux
*iface
, BOOL fOldIndex
)
823 AviMux
*This
= impl_from_IConfigAviMux(iface
);
824 FIXME("(%p)->(%x)\n", This
, fOldIndex
);
828 static HRESULT WINAPI
ConfigAviMux_GetOutputCompatibilityIndex(
829 IConfigAviMux
*iface
, BOOL
*pfOldIndex
)
831 AviMux
*This
= impl_from_IConfigAviMux(iface
);
832 FIXME("(%p)->(%p)\n", This
, pfOldIndex
);
836 static const IConfigAviMuxVtbl ConfigAviMuxVtbl
= {
837 ConfigAviMux_QueryInterface
,
839 ConfigAviMux_Release
,
840 ConfigAviMux_SetMasterStream
,
841 ConfigAviMux_GetMasterStream
,
842 ConfigAviMux_SetOutputCompatibilityIndex
,
843 ConfigAviMux_GetOutputCompatibilityIndex
846 static inline AviMux
* impl_from_IConfigInterleaving(IConfigInterleaving
*iface
)
848 return CONTAINING_RECORD(iface
, AviMux
, IConfigInterleaving_iface
);
851 static HRESULT WINAPI
ConfigInterleaving_QueryInterface(
852 IConfigInterleaving
*iface
, REFIID riid
, void **ppv
)
854 AviMux
*This
= impl_from_IConfigInterleaving(iface
);
855 return IBaseFilter_QueryInterface(&This
->filter
.IBaseFilter_iface
, riid
, ppv
);
858 static ULONG WINAPI
ConfigInterleaving_AddRef(IConfigInterleaving
*iface
)
860 AviMux
*This
= impl_from_IConfigInterleaving(iface
);
861 return IBaseFilter_AddRef(&This
->filter
.IBaseFilter_iface
);
864 static ULONG WINAPI
ConfigInterleaving_Release(IConfigInterleaving
*iface
)
866 AviMux
*This
= impl_from_IConfigInterleaving(iface
);
867 return IBaseFilter_Release(&This
->filter
.IBaseFilter_iface
);
870 static HRESULT WINAPI
ConfigInterleaving_put_Mode(
871 IConfigInterleaving
*iface
, InterleavingMode mode
)
873 AviMux
*This
= impl_from_IConfigInterleaving(iface
);
875 TRACE("(%p)->(%d)\n", This
, mode
);
877 if(mode
>INTERLEAVE_NONE_BUFFERED
)
880 if(This
->mode
!= mode
) {
881 if(This
->out
->pin
.pin
.pConnectedTo
) {
882 HRESULT hr
= IFilterGraph_Reconnect(This
->filter
.filterInfo
.pGraph
,
883 &This
->out
->pin
.pin
.IPin_iface
);
894 static HRESULT WINAPI
ConfigInterleaving_get_Mode(
895 IConfigInterleaving
*iface
, InterleavingMode
*pMode
)
897 AviMux
*This
= impl_from_IConfigInterleaving(iface
);
898 FIXME("(%p)->(%p)\n", This
, pMode
);
902 static HRESULT WINAPI
ConfigInterleaving_put_Interleaving(IConfigInterleaving
*iface
,
903 const REFERENCE_TIME
*prtInterleave
, const REFERENCE_TIME
*prtPreroll
)
905 AviMux
*This
= impl_from_IConfigInterleaving(iface
);
907 TRACE("(%p)->(%p %p)\n", This
, prtInterleave
, prtPreroll
);
910 This
->interleave
= *prtInterleave
;
912 This
->preroll
= *prtPreroll
;
916 static HRESULT WINAPI
ConfigInterleaving_get_Interleaving(IConfigInterleaving
*iface
,
917 REFERENCE_TIME
*prtInterleave
, REFERENCE_TIME
*prtPreroll
)
919 AviMux
*This
= impl_from_IConfigInterleaving(iface
);
920 FIXME("(%p)->(%p %p)\n", This
, prtInterleave
, prtPreroll
);
924 static const IConfigInterleavingVtbl ConfigInterleavingVtbl
= {
925 ConfigInterleaving_QueryInterface
,
926 ConfigInterleaving_AddRef
,
927 ConfigInterleaving_Release
,
928 ConfigInterleaving_put_Mode
,
929 ConfigInterleaving_get_Mode
,
930 ConfigInterleaving_put_Interleaving
,
931 ConfigInterleaving_get_Interleaving
934 static inline AviMux
* impl_from_IMediaSeeking(IMediaSeeking
*iface
)
936 return CONTAINING_RECORD(iface
, AviMux
, IMediaSeeking_iface
);
939 static HRESULT WINAPI
MediaSeeking_QueryInterface(
940 IMediaSeeking
*iface
, REFIID riid
, void **ppv
)
942 AviMux
*This
= impl_from_IMediaSeeking(iface
);
943 return IBaseFilter_QueryInterface(&This
->filter
.IBaseFilter_iface
, riid
, ppv
);
946 static ULONG WINAPI
MediaSeeking_AddRef(IMediaSeeking
*iface
)
948 AviMux
*This
= impl_from_IMediaSeeking(iface
);
949 return IBaseFilter_AddRef(&This
->filter
.IBaseFilter_iface
);
952 static ULONG WINAPI
MediaSeeking_Release(IMediaSeeking
*iface
)
954 AviMux
*This
= impl_from_IMediaSeeking(iface
);
955 return IBaseFilter_Release(&This
->filter
.IBaseFilter_iface
);
958 static HRESULT WINAPI
MediaSeeking_GetCapabilities(
959 IMediaSeeking
*iface
, DWORD
*pCapabilities
)
961 AviMux
*This
= impl_from_IMediaSeeking(iface
);
962 FIXME("(%p)->(%p)\n", This
, pCapabilities
);
966 static HRESULT WINAPI
MediaSeeking_CheckCapabilities(
967 IMediaSeeking
*iface
, DWORD
*pCapabilities
)
969 AviMux
*This
= impl_from_IMediaSeeking(iface
);
970 FIXME("(%p)->(%p)\n", This
, pCapabilities
);
974 static HRESULT WINAPI
MediaSeeking_IsFormatSupported(
975 IMediaSeeking
*iface
, const GUID
*pFormat
)
977 AviMux
*This
= impl_from_IMediaSeeking(iface
);
978 FIXME("(%p)->(%s)\n", This
, debugstr_guid(pFormat
));
982 static HRESULT WINAPI
MediaSeeking_QueryPreferredFormat(
983 IMediaSeeking
*iface
, GUID
*pFormat
)
985 AviMux
*This
= impl_from_IMediaSeeking(iface
);
986 FIXME("(%p)->(%p)\n", This
, pFormat
);
990 static HRESULT WINAPI
MediaSeeking_GetTimeFormat(
991 IMediaSeeking
*iface
, GUID
*pFormat
)
993 AviMux
*This
= impl_from_IMediaSeeking(iface
);
994 FIXME("(%p)->(%p)\n", This
, pFormat
);
998 static HRESULT WINAPI
MediaSeeking_IsUsingTimeFormat(
999 IMediaSeeking
*iface
, const GUID
*pFormat
)
1001 AviMux
*This
= impl_from_IMediaSeeking(iface
);
1002 FIXME("(%p)->(%s)\n", This
, debugstr_guid(pFormat
));
1006 static HRESULT WINAPI
MediaSeeking_SetTimeFormat(
1007 IMediaSeeking
*iface
, const GUID
*pFormat
)
1009 AviMux
*This
= impl_from_IMediaSeeking(iface
);
1010 FIXME("(%p)->(%s)\n", This
, debugstr_guid(pFormat
));
1014 static HRESULT WINAPI
MediaSeeking_GetDuration(
1015 IMediaSeeking
*iface
, LONGLONG
*pDuration
)
1017 AviMux
*This
= impl_from_IMediaSeeking(iface
);
1018 FIXME("(%p)->(%p)\n", This
, pDuration
);
1022 static HRESULT WINAPI
MediaSeeking_GetStopPosition(
1023 IMediaSeeking
*iface
, LONGLONG
*pStop
)
1025 AviMux
*This
= impl_from_IMediaSeeking(iface
);
1026 FIXME("(%p)->(%p)\n", This
, pStop
);
1030 static HRESULT WINAPI
MediaSeeking_GetCurrentPosition(
1031 IMediaSeeking
*iface
, LONGLONG
*pCurrent
)
1033 AviMux
*This
= impl_from_IMediaSeeking(iface
);
1034 FIXME("(%p)->(%p)\n", This
, pCurrent
);
1038 static HRESULT WINAPI
MediaSeeking_ConvertTimeFormat(IMediaSeeking
*iface
, LONGLONG
*pTarget
,
1039 const GUID
*pTargetFormat
, LONGLONG Source
, const GUID
*pSourceFormat
)
1041 AviMux
*This
= impl_from_IMediaSeeking(iface
);
1042 FIXME("(%p)->(%p %s %s %s)\n", This
, pTarget
, debugstr_guid(pTargetFormat
),
1043 wine_dbgstr_longlong(Source
), debugstr_guid(pSourceFormat
));
1047 static HRESULT WINAPI
MediaSeeking_SetPositions(IMediaSeeking
*iface
, LONGLONG
*pCurrent
,
1048 DWORD dwCurrentFlags
, LONGLONG
*pStop
, DWORD dwStopFlags
)
1050 AviMux
*This
= impl_from_IMediaSeeking(iface
);
1051 FIXME("(%p)->(%p %x %p %x)\n", This
, pCurrent
, dwCurrentFlags
, pStop
, dwStopFlags
);
1055 static HRESULT WINAPI
MediaSeeking_GetPositions(IMediaSeeking
*iface
,
1056 LONGLONG
*pCurrent
, LONGLONG
*pStop
)
1058 AviMux
*This
= impl_from_IMediaSeeking(iface
);
1059 FIXME("(%p)->(%p %p)\n", This
, pCurrent
, pStop
);
1063 static HRESULT WINAPI
MediaSeeking_GetAvailable(IMediaSeeking
*iface
,
1064 LONGLONG
*pEarliest
, LONGLONG
*pLatest
)
1066 AviMux
*This
= impl_from_IMediaSeeking(iface
);
1067 FIXME("(%p)->(%p %p)\n", This
, pEarliest
, pLatest
);
1071 static HRESULT WINAPI
MediaSeeking_SetRate(IMediaSeeking
*iface
, double dRate
)
1073 AviMux
*This
= impl_from_IMediaSeeking(iface
);
1074 FIXME("(%p)->(%lf)\n", This
, dRate
);
1078 static HRESULT WINAPI
MediaSeeking_GetRate(IMediaSeeking
*iface
, double *pdRate
)
1080 AviMux
*This
= impl_from_IMediaSeeking(iface
);
1081 FIXME("(%p)->(%p)\n", This
, pdRate
);
1085 static HRESULT WINAPI
MediaSeeking_GetPreroll(IMediaSeeking
*iface
, LONGLONG
*pllPreroll
)
1087 AviMux
*This
= impl_from_IMediaSeeking(iface
);
1088 FIXME("(%p)->(%p)\n", This
, pllPreroll
);
1092 static const IMediaSeekingVtbl MediaSeekingVtbl
= {
1093 MediaSeeking_QueryInterface
,
1094 MediaSeeking_AddRef
,
1095 MediaSeeking_Release
,
1096 MediaSeeking_GetCapabilities
,
1097 MediaSeeking_CheckCapabilities
,
1098 MediaSeeking_IsFormatSupported
,
1099 MediaSeeking_QueryPreferredFormat
,
1100 MediaSeeking_GetTimeFormat
,
1101 MediaSeeking_IsUsingTimeFormat
,
1102 MediaSeeking_SetTimeFormat
,
1103 MediaSeeking_GetDuration
,
1104 MediaSeeking_GetStopPosition
,
1105 MediaSeeking_GetCurrentPosition
,
1106 MediaSeeking_ConvertTimeFormat
,
1107 MediaSeeking_SetPositions
,
1108 MediaSeeking_GetPositions
,
1109 MediaSeeking_GetAvailable
,
1110 MediaSeeking_SetRate
,
1111 MediaSeeking_GetRate
,
1112 MediaSeeking_GetPreroll
1115 static inline AviMux
* impl_from_IPersistMediaPropertyBag(IPersistMediaPropertyBag
*iface
)
1117 return CONTAINING_RECORD(iface
, AviMux
, IPersistMediaPropertyBag_iface
);
1120 static HRESULT WINAPI
PersistMediaPropertyBag_QueryInterface(
1121 IPersistMediaPropertyBag
*iface
, REFIID riid
, void **ppv
)
1123 AviMux
*This
= impl_from_IPersistMediaPropertyBag(iface
);
1124 return IBaseFilter_QueryInterface(&This
->filter
.IBaseFilter_iface
, riid
, ppv
);
1127 static ULONG WINAPI
PersistMediaPropertyBag_AddRef(IPersistMediaPropertyBag
*iface
)
1129 AviMux
*This
= impl_from_IPersistMediaPropertyBag(iface
);
1130 return IBaseFilter_AddRef(&This
->filter
.IBaseFilter_iface
);
1133 static ULONG WINAPI
PersistMediaPropertyBag_Release(IPersistMediaPropertyBag
*iface
)
1135 AviMux
*This
= impl_from_IPersistMediaPropertyBag(iface
);
1136 return IBaseFilter_Release(&This
->filter
.IBaseFilter_iface
);
1139 static HRESULT WINAPI
PersistMediaPropertyBag_GetClassID(
1140 IPersistMediaPropertyBag
*iface
, CLSID
*pClassID
)
1142 AviMux
*This
= impl_from_IPersistMediaPropertyBag(iface
);
1143 return IBaseFilter_GetClassID(&This
->filter
.IBaseFilter_iface
, pClassID
);
1146 static HRESULT WINAPI
PersistMediaPropertyBag_InitNew(IPersistMediaPropertyBag
*iface
)
1148 AviMux
*This
= impl_from_IPersistMediaPropertyBag(iface
);
1149 FIXME("(%p)->()\n", This
);
1153 static HRESULT WINAPI
PersistMediaPropertyBag_Load(IPersistMediaPropertyBag
*iface
,
1154 IMediaPropertyBag
*pPropBag
, IErrorLog
*pErrorLog
)
1156 AviMux
*This
= impl_from_IPersistMediaPropertyBag(iface
);
1157 FIXME("(%p)->()\n", This
);
1161 static HRESULT WINAPI
PersistMediaPropertyBag_Save(IPersistMediaPropertyBag
*iface
,
1162 IMediaPropertyBag
*pPropBag
, BOOL fClearDirty
, BOOL fSaveAllProperties
)
1164 AviMux
*This
= impl_from_IPersistMediaPropertyBag(iface
);
1165 FIXME("(%p)->()\n", This
);
1169 static const IPersistMediaPropertyBagVtbl PersistMediaPropertyBagVtbl
= {
1170 PersistMediaPropertyBag_QueryInterface
,
1171 PersistMediaPropertyBag_AddRef
,
1172 PersistMediaPropertyBag_Release
,
1173 PersistMediaPropertyBag_GetClassID
,
1174 PersistMediaPropertyBag_InitNew
,
1175 PersistMediaPropertyBag_Load
,
1176 PersistMediaPropertyBag_Save
1179 static inline AviMux
* impl_from_ISpecifyPropertyPages(ISpecifyPropertyPages
*iface
)
1181 return CONTAINING_RECORD(iface
, AviMux
, ISpecifyPropertyPages_iface
);
1184 static HRESULT WINAPI
SpecifyPropertyPages_QueryInterface(
1185 ISpecifyPropertyPages
*iface
, REFIID riid
, void **ppv
)
1187 AviMux
*This
= impl_from_ISpecifyPropertyPages(iface
);
1188 return IBaseFilter_QueryInterface(&This
->filter
.IBaseFilter_iface
, riid
, ppv
);
1191 static ULONG WINAPI
SpecifyPropertyPages_AddRef(ISpecifyPropertyPages
*iface
)
1193 AviMux
*This
= impl_from_ISpecifyPropertyPages(iface
);
1194 return IBaseFilter_AddRef(&This
->filter
.IBaseFilter_iface
);
1197 static ULONG WINAPI
SpecifyPropertyPages_Release(ISpecifyPropertyPages
*iface
)
1199 AviMux
*This
= impl_from_ISpecifyPropertyPages(iface
);
1200 return IBaseFilter_Release(&This
->filter
.IBaseFilter_iface
);
1203 static HRESULT WINAPI
SpecifyPropertyPages_GetPages(
1204 ISpecifyPropertyPages
*iface
, CAUUID
*pPages
)
1206 AviMux
*This
= impl_from_ISpecifyPropertyPages(iface
);
1207 FIXME("(%p)->(%p)\n", This
, pPages
);
1211 static const ISpecifyPropertyPagesVtbl SpecifyPropertyPagesVtbl
= {
1212 SpecifyPropertyPages_QueryInterface
,
1213 SpecifyPropertyPages_AddRef
,
1214 SpecifyPropertyPages_Release
,
1215 SpecifyPropertyPages_GetPages
1218 static HRESULT WINAPI
AviMuxOut_CheckMediaType(BasePin
*base
, const AM_MEDIA_TYPE
*amt
)
1220 FIXME("(%p) stub\n", base
);
1224 static HRESULT WINAPI
AviMuxOut_AttemptConnection(BaseOutputPin
*base
,
1225 IPin
*pReceivePin
, const AM_MEDIA_TYPE
*pmt
)
1230 TRACE("(%p)->(%p AM_MEDIA_TYPE(%p))\n", base
, pReceivePin
, pmt
);
1231 dump_AM_MEDIA_TYPE(pmt
);
1233 hr
= IPin_QueryDirection(pReceivePin
, &dir
);
1234 if(hr
==S_OK
&& dir
!=PINDIR_INPUT
)
1235 return VFW_E_INVALID_DIRECTION
;
1237 return BaseOutputPinImpl_AttemptConnection(base
, pReceivePin
, pmt
);
1240 static HRESULT WINAPI
AviMuxOut_GetMediaType(BasePin
*base
, int iPosition
, AM_MEDIA_TYPE
*amt
)
1242 TRACE("(%p)->(%d %p)\n", base
, iPosition
, amt
);
1245 return E_INVALIDARG
;
1247 return VFW_S_NO_MORE_ITEMS
;
1249 amt
->majortype
= MEDIATYPE_Stream
;
1250 amt
->subtype
= MEDIASUBTYPE_Avi
;
1251 amt
->bFixedSizeSamples
= TRUE
;
1252 amt
->bTemporalCompression
= FALSE
;
1253 amt
->lSampleSize
= 1;
1254 amt
->formattype
= GUID_NULL
;
1257 amt
->pbFormat
= NULL
;
1261 static HRESULT WINAPI
AviMuxOut_DecideAllocator(BaseOutputPin
*base
,
1262 IMemInputPin
*pPin
, IMemAllocator
**pAlloc
)
1264 ALLOCATOR_PROPERTIES req
, actual
;
1267 TRACE("(%p)->(%p %p)\n", base
, pPin
, pAlloc
);
1269 hr
= BaseOutputPinImpl_InitAllocator(base
, pAlloc
);
1273 hr
= IMemInputPin_GetAllocatorRequirements(pPin
, &req
);
1280 hr
= IMemAllocator_SetProperties(*pAlloc
, &req
, &actual
);
1284 return IMemInputPin_NotifyAllocator(pPin
, *pAlloc
, TRUE
);
1287 static const BaseOutputPinFuncTable AviMuxOut_BaseOutputFuncTable
= {
1289 AviMuxOut_CheckMediaType
,
1290 AviMuxOut_GetMediaType
1292 AviMuxOut_AttemptConnection
,
1294 AviMuxOut_DecideAllocator
,
1297 static inline AviMux
* impl_from_out_IPin(IPin
*iface
)
1299 BasePin
*bp
= CONTAINING_RECORD(iface
, BasePin
, IPin_iface
);
1300 IBaseFilter
*bf
= bp
->pinInfo
.pFilter
;
1302 return impl_from_IBaseFilter(bf
);
1305 static HRESULT WINAPI
AviMuxOut_QueryInterface(IPin
*iface
, REFIID riid
, void **ppv
)
1307 AviMux
*This
= impl_from_out_IPin(iface
);
1309 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), ppv
);
1311 if(IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IPin
))
1313 else if(IsEqualIID(riid
, &IID_IQualityControl
))
1314 *ppv
= &This
->out
->IQualityControl_iface
;
1316 FIXME("no interface for %s\n", debugstr_guid(riid
));
1318 return E_NOINTERFACE
;
1321 IUnknown_AddRef((IUnknown
*)*ppv
);
1325 static ULONG WINAPI
AviMuxOut_AddRef(IPin
*iface
)
1327 AviMux
*This
= impl_from_out_IPin(iface
);
1328 return IBaseFilter_AddRef(&This
->filter
.IBaseFilter_iface
);
1331 static ULONG WINAPI
AviMuxOut_Release(IPin
*iface
)
1333 AviMux
*This
= impl_from_out_IPin(iface
);
1334 return IBaseFilter_Release(&This
->filter
.IBaseFilter_iface
);
1337 static HRESULT WINAPI
AviMuxOut_Connect(IPin
*iface
,
1338 IPin
*pReceivePin
, const AM_MEDIA_TYPE
*pmt
)
1340 AviMux
*This
= impl_from_out_IPin(iface
);
1344 TRACE("(%p)->(%p AM_MEDIA_TYPE(%p))\n", This
, pReceivePin
, pmt
);
1345 dump_AM_MEDIA_TYPE(pmt
);
1347 hr
= BaseOutputPinImpl_Connect(iface
, pReceivePin
, pmt
);
1351 for(i
=0; i
<This
->input_pin_no
; i
++) {
1352 if(!This
->in
[i
]->pin
.pin
.pConnectedTo
)
1355 hr
= IFilterGraph_Reconnect(This
->filter
.filterInfo
.pGraph
, &This
->in
[i
]->pin
.pin
.IPin_iface
);
1357 BaseOutputPinImpl_Disconnect(iface
);
1363 IBaseFilter_AddRef(&This
->filter
.IBaseFilter_iface
);
1367 static HRESULT WINAPI
AviMuxOut_ReceiveConnection(IPin
*iface
,
1368 IPin
*pConnector
, const AM_MEDIA_TYPE
*pmt
)
1370 AviMux
*This
= impl_from_out_IPin(iface
);
1371 TRACE("(%p)->(%p AM_MEDIA_TYPE(%p)\n", This
, pConnector
, pmt
);
1372 dump_AM_MEDIA_TYPE(pmt
);
1373 return BaseOutputPinImpl_ReceiveConnection(iface
, pConnector
, pmt
);
1376 static HRESULT WINAPI
AviMuxOut_Disconnect(IPin
*iface
)
1378 AviMux
*This
= impl_from_out_IPin(iface
);
1381 TRACE("(%p)\n", This
);
1383 hr
= BaseOutputPinImpl_Disconnect(iface
);
1385 IBaseFilter_Release(&This
->filter
.IBaseFilter_iface
);
1389 static HRESULT WINAPI
AviMuxOut_ConnectedTo(IPin
*iface
, IPin
**pPin
)
1391 AviMux
*This
= impl_from_out_IPin(iface
);
1392 TRACE("(%p)->(%p)\n", This
, pPin
);
1393 return BasePinImpl_ConnectedTo(iface
, pPin
);
1396 static HRESULT WINAPI
AviMuxOut_ConnectionMediaType(IPin
*iface
, AM_MEDIA_TYPE
*pmt
)
1398 AviMux
*This
= impl_from_out_IPin(iface
);
1399 TRACE("(%p)->(%p)\n", This
, pmt
);
1400 return BasePinImpl_ConnectionMediaType(iface
, pmt
);
1403 static HRESULT WINAPI
AviMuxOut_QueryPinInfo(IPin
*iface
, PIN_INFO
*pInfo
)
1405 AviMux
*This
= impl_from_out_IPin(iface
);
1406 TRACE("(%p)->(%p)\n", This
, pInfo
);
1407 return BasePinImpl_QueryPinInfo(iface
, pInfo
);
1410 static HRESULT WINAPI
AviMuxOut_QueryDirection(IPin
*iface
, PIN_DIRECTION
*pPinDir
)
1412 AviMux
*This
= impl_from_out_IPin(iface
);
1413 TRACE("(%p)->(%p)\n", This
, pPinDir
);
1414 return BasePinImpl_QueryDirection(iface
, pPinDir
);
1417 static HRESULT WINAPI
AviMuxOut_QueryId(IPin
*iface
, LPWSTR
*Id
)
1419 AviMux
*This
= impl_from_out_IPin(iface
);
1420 TRACE("(%p)->(%p)\n", This
, Id
);
1421 return BasePinImpl_QueryId(iface
, Id
);
1424 static HRESULT WINAPI
AviMuxOut_QueryAccept(IPin
*iface
, const AM_MEDIA_TYPE
*pmt
)
1426 AviMux
*This
= impl_from_out_IPin(iface
);
1427 TRACE("(%p)->(AM_MEDIA_TYPE(%p))\n", This
, pmt
);
1428 dump_AM_MEDIA_TYPE(pmt
);
1429 return BasePinImpl_QueryAccept(iface
, pmt
);
1432 static HRESULT WINAPI
AviMuxOut_EnumMediaTypes(IPin
*iface
, IEnumMediaTypes
**ppEnum
)
1434 AviMux
*This
= impl_from_out_IPin(iface
);
1435 TRACE("(%p)->(%p)\n", This
, ppEnum
);
1436 return BasePinImpl_EnumMediaTypes(iface
, ppEnum
);
1439 static HRESULT WINAPI
AviMuxOut_QueryInternalConnections(
1440 IPin
*iface
, IPin
**apPin
, ULONG
*nPin
)
1442 AviMux
*This
= impl_from_out_IPin(iface
);
1443 FIXME("(%p)->(%p %p)\n", This
, apPin
, nPin
);
1447 static HRESULT WINAPI
AviMuxOut_EndOfStream(IPin
*iface
)
1449 AviMux
*This
= impl_from_out_IPin(iface
);
1450 TRACE("(%p)\n", This
);
1451 return BaseOutputPinImpl_EndOfStream(iface
);
1454 static HRESULT WINAPI
AviMuxOut_BeginFlush(IPin
*iface
)
1456 AviMux
*This
= impl_from_out_IPin(iface
);
1457 TRACE("(%p)\n", This
);
1458 return BaseOutputPinImpl_BeginFlush(iface
);
1461 static HRESULT WINAPI
AviMuxOut_EndFlush(IPin
*iface
)
1463 AviMux
*This
= impl_from_out_IPin(iface
);
1464 TRACE("(%p)\n", This
);
1465 return BaseOutputPinImpl_EndFlush(iface
);
1468 static HRESULT WINAPI
AviMuxOut_NewSegment(IPin
*iface
, REFERENCE_TIME tStart
,
1469 REFERENCE_TIME tStop
, double dRate
)
1471 AviMux
*This
= impl_from_out_IPin(iface
);
1472 TRACE("(%p)->(%s %s %f)\n", This
, wine_dbgstr_longlong(tStart
), wine_dbgstr_longlong(tStop
), dRate
);
1473 return BasePinImpl_NewSegment(iface
, tStart
, tStop
, dRate
);
1476 static const IPinVtbl AviMuxOut_PinVtbl
= {
1477 AviMuxOut_QueryInterface
,
1481 AviMuxOut_ReceiveConnection
,
1482 AviMuxOut_Disconnect
,
1483 AviMuxOut_ConnectedTo
,
1484 AviMuxOut_ConnectionMediaType
,
1485 AviMuxOut_QueryPinInfo
,
1486 AviMuxOut_QueryDirection
,
1488 AviMuxOut_QueryAccept
,
1489 AviMuxOut_EnumMediaTypes
,
1490 AviMuxOut_QueryInternalConnections
,
1491 AviMuxOut_EndOfStream
,
1492 AviMuxOut_BeginFlush
,
1494 AviMuxOut_NewSegment
1497 static inline AviMux
* impl_from_out_IQualityControl(IQualityControl
*iface
)
1499 AviMuxOut
*amo
= CONTAINING_RECORD(iface
, AviMuxOut
, IQualityControl_iface
);
1500 return impl_from_IBaseFilter(amo
->pin
.pin
.pinInfo
.pFilter
);
1503 static HRESULT WINAPI
AviMuxOut_QualityControl_QueryInterface(
1504 IQualityControl
*iface
, REFIID riid
, void **ppv
)
1506 AviMux
*This
= impl_from_out_IQualityControl(iface
);
1507 return IPin_QueryInterface(&This
->out
->pin
.pin
.IPin_iface
, riid
, ppv
);
1510 static ULONG WINAPI
AviMuxOut_QualityControl_AddRef(IQualityControl
*iface
)
1512 AviMux
*This
= impl_from_out_IQualityControl(iface
);
1513 return IBaseFilter_AddRef(&This
->filter
.IBaseFilter_iface
);
1516 static ULONG WINAPI
AviMuxOut_QualityControl_Release(IQualityControl
*iface
)
1518 AviMux
*This
= impl_from_out_IQualityControl(iface
);
1519 return IBaseFilter_Release(&This
->filter
.IBaseFilter_iface
);
1522 static HRESULT WINAPI
AviMuxOut_QualityControl_Notify(IQualityControl
*iface
,
1523 IBaseFilter
*pSelf
, Quality q
)
1525 AviMux
*This
= impl_from_out_IQualityControl(iface
);
1526 FIXME("(%p)->(%p { 0x%x %u %s %s })\n", This
, pSelf
,
1527 q
.Type
, q
.Proportion
,
1528 wine_dbgstr_longlong(q
.Late
),
1529 wine_dbgstr_longlong(q
.TimeStamp
));
1533 static HRESULT WINAPI
AviMuxOut_QualityControl_SetSink(
1534 IQualityControl
*iface
, IQualityControl
*piqc
)
1536 AviMux
*This
= impl_from_out_IQualityControl(iface
);
1537 FIXME("(%p)->(%p)\n", This
, piqc
);
1541 static const IQualityControlVtbl AviMuxOut_QualityControlVtbl
= {
1542 AviMuxOut_QualityControl_QueryInterface
,
1543 AviMuxOut_QualityControl_AddRef
,
1544 AviMuxOut_QualityControl_Release
,
1545 AviMuxOut_QualityControl_Notify
,
1546 AviMuxOut_QualityControl_SetSink
1549 static HRESULT WINAPI
AviMuxIn_CheckMediaType(BasePin
*base
, const AM_MEDIA_TYPE
*pmt
)
1551 TRACE("(%p:%s)->(AM_MEDIA_TYPE(%p))\n", base
, debugstr_w(base
->pinInfo
.achName
), pmt
);
1552 dump_AM_MEDIA_TYPE(pmt
);
1554 if(IsEqualIID(&pmt
->majortype
, &MEDIATYPE_Audio
) &&
1555 IsEqualIID(&pmt
->formattype
, &FORMAT_WaveFormatEx
))
1557 if(IsEqualIID(&pmt
->majortype
, &MEDIATYPE_Interleaved
) &&
1558 IsEqualIID(&pmt
->formattype
, &FORMAT_DvInfo
))
1560 if(IsEqualIID(&pmt
->majortype
, &MEDIATYPE_Video
) &&
1561 (IsEqualIID(&pmt
->formattype
, &FORMAT_VideoInfo
) ||
1562 IsEqualIID(&pmt
->formattype
, &FORMAT_DvInfo
)))
1567 static HRESULT WINAPI
AviMuxIn_GetMediaType(BasePin
*base
, int iPosition
, AM_MEDIA_TYPE
*amt
)
1572 static HRESULT WINAPI
AviMuxIn_Receive(BaseInputPin
*base
, IMediaSample
*pSample
)
1574 AviMuxIn
*avimuxin
= CONTAINING_RECORD(base
, AviMuxIn
, pin
);
1575 AviMux
*avimux
= impl_from_IBaseFilter(base
->pin
.pinInfo
.pFilter
);
1576 REFERENCE_TIME start
, stop
;
1577 IMediaSample
*sample
;
1581 DWORD max_size
, size
;
1585 TRACE("(%p:%s)->(%p)\n", base
, debugstr_w(base
->pin
.pinInfo
.achName
), pSample
);
1587 hr
= IMediaSample_QueryInterface(pSample
, &IID_IMediaSample2
, (void**)&ms2
);
1589 AM_SAMPLE2_PROPERTIES props
;
1591 memset(&props
, 0, sizeof(props
));
1592 hr
= IMediaSample2_GetProperties(ms2
, sizeof(props
), (BYTE
*)&props
);
1593 IMediaSample2_Release(ms2
);
1597 flags
= props
.dwSampleFlags
;
1598 frame
= props
.pbBuffer
;
1599 size
= props
.lActual
;
1601 flags
= IMediaSample_IsSyncPoint(pSample
) == S_OK
? AM_SAMPLE_SPLICEPOINT
: 0;
1602 hr
= IMediaSample_GetPointer(pSample
, &frame
);
1605 size
= IMediaSample_GetActualDataLength(pSample
);
1608 if(!avimuxin
->pin
.pin
.mtCurrent
.bTemporalCompression
)
1609 flags
|= AM_SAMPLE_SPLICEPOINT
;
1611 hr
= IMediaSample_GetTime(pSample
, &start
, &stop
);
1615 if(avimuxin
->stop
>stop
)
1616 return VFW_E_START_TIME_AFTER_END
;
1618 if(avimux
->start
== -1)
1619 avimux
->start
= start
;
1620 if(avimux
->stop
< stop
)
1621 avimux
->stop
= stop
;
1623 if(avimux
->avih
.dwSuggestedBufferSize
< ALIGN(size
)+sizeof(RIFFCHUNK
))
1624 avimux
->avih
.dwSuggestedBufferSize
= ALIGN(size
) + sizeof(RIFFCHUNK
);
1625 if(avimuxin
->strh
.dwSuggestedBufferSize
< ALIGN(size
)+sizeof(RIFFCHUNK
))
1626 avimuxin
->strh
.dwSuggestedBufferSize
= ALIGN(size
) + sizeof(RIFFCHUNK
);
1629 if(avimuxin
->stop
!=-1 && start
> avimuxin
->stop
) {
1630 frames_no
+= (double)(start
- avimuxin
->stop
) / 10000000
1631 * avimuxin
->strh
.dwRate
/ avimuxin
->strh
.dwScale
+ 0.5;
1633 avimuxin
->stop
= stop
;
1635 while(--frames_no
) {
1636 /* TODO: store all control frames in one buffer */
1637 hr
= IMemAllocator_GetBuffer(avimuxin
->samples_allocator
, &sample
, NULL
, NULL
, 0);
1640 hr
= IMediaSample_SetActualDataLength(sample
, 0);
1642 hr
= IMediaSample_SetDiscontinuity(sample
, TRUE
);
1644 hr
= IMediaSample_SetSyncPoint(sample
, FALSE
);
1646 hr
= queue_sample(avimux
, avimuxin
, sample
);
1647 IMediaSample_Release(sample
);
1652 hr
= IMemAllocator_GetBuffer(avimuxin
->samples_allocator
, &sample
, NULL
, NULL
, 0);
1655 max_size
= IMediaSample_GetSize(sample
);
1658 hr
= IMediaSample_SetActualDataLength(sample
, size
);
1660 hr
= IMediaSample_SetDiscontinuity(sample
, FALSE
);
1662 hr
= IMediaSample_SetSyncPoint(sample
, flags
& AM_SAMPLE_SPLICEPOINT
);
1663 /* TODO: avoid unnecessary copying */
1665 hr
= IMediaSample_GetPointer(sample
, &buf
);
1667 memcpy(buf
, frame
, size
);
1668 hr
= queue_sample(avimux
, avimuxin
, sample
);
1670 IMediaSample_Release(sample
);
1675 static const BaseInputPinFuncTable AviMuxIn_BaseInputFuncTable
= {
1677 AviMuxIn_CheckMediaType
,
1678 AviMuxIn_GetMediaType
1683 static inline AviMux
* impl_from_in_IPin(IPin
*iface
)
1685 BasePin
*bp
= CONTAINING_RECORD(iface
, BasePin
, IPin_iface
);
1686 IBaseFilter
*bf
= bp
->pinInfo
.pFilter
;
1688 return impl_from_IBaseFilter(bf
);
1691 static inline AviMuxIn
* AviMuxIn_from_IPin(IPin
*iface
)
1693 BasePin
*bp
= CONTAINING_RECORD(iface
, BasePin
, IPin_iface
);
1694 BaseInputPin
*bip
= CONTAINING_RECORD(bp
, BaseInputPin
, pin
);
1695 return CONTAINING_RECORD(bip
, AviMuxIn
, pin
);
1698 static HRESULT WINAPI
AviMuxIn_QueryInterface(IPin
*iface
, REFIID riid
, void **ppv
)
1700 AviMux
*This
= impl_from_in_IPin(iface
);
1701 AviMuxIn
*avimuxin
= AviMuxIn_from_IPin(iface
);
1703 TRACE("(%p:%s)->(%s %p)\n", This
, debugstr_w(avimuxin
->pin
.pin
.pinInfo
.achName
),
1704 debugstr_guid(riid
), ppv
);
1706 if(IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IPin
))
1707 *ppv
= &avimuxin
->pin
.pin
.IPin_iface
;
1708 else if(IsEqualIID(riid
, &IID_IAMStreamControl
))
1709 *ppv
= &avimuxin
->IAMStreamControl_iface
;
1710 else if(IsEqualIID(riid
, &IID_IMemInputPin
))
1711 *ppv
= &avimuxin
->pin
.IMemInputPin_iface
;
1712 else if(IsEqualIID(riid
, &IID_IPropertyBag
))
1713 *ppv
= &avimuxin
->IPropertyBag_iface
;
1714 else if(IsEqualIID(riid
, &IID_IQualityControl
))
1715 *ppv
= &avimuxin
->IQualityControl_iface
;
1717 FIXME("no interface for %s\n", debugstr_guid(riid
));
1719 return E_NOINTERFACE
;
1722 IUnknown_AddRef((IUnknown
*)*ppv
);
1726 static ULONG WINAPI
AviMuxIn_AddRef(IPin
*iface
)
1728 AviMux
*This
= impl_from_in_IPin(iface
);
1729 return IBaseFilter_AddRef(&This
->filter
.IBaseFilter_iface
);
1732 static ULONG WINAPI
AviMuxIn_Release(IPin
*iface
)
1734 AviMux
*This
= impl_from_in_IPin(iface
);
1735 return IBaseFilter_Release(&This
->filter
.IBaseFilter_iface
);
1738 static HRESULT WINAPI
AviMuxIn_Connect(IPin
*iface
,
1739 IPin
*pReceivePin
, const AM_MEDIA_TYPE
*pmt
)
1741 AviMux
*This
= impl_from_in_IPin(iface
);
1742 AviMuxIn
*avimuxin
= AviMuxIn_from_IPin(iface
);
1743 TRACE("(%p:%s)->(%p AM_MEDIA_TYPE(%p))\n", This
,
1744 debugstr_w(avimuxin
->pin
.pin
.pinInfo
.achName
), pReceivePin
, pmt
);
1745 dump_AM_MEDIA_TYPE(pmt
);
1746 return BaseInputPinImpl_Connect(iface
, pReceivePin
, pmt
);
1749 static HRESULT WINAPI
AviMuxIn_ReceiveConnection(IPin
*iface
,
1750 IPin
*pConnector
, const AM_MEDIA_TYPE
*pmt
)
1752 AviMux
*This
= impl_from_in_IPin(iface
);
1753 AviMuxIn
*avimuxin
= AviMuxIn_from_IPin(iface
);
1756 TRACE("(%p:%s)->(%p AM_MEDIA_TYPE(%p))\n", This
,
1757 debugstr_w(avimuxin
->pin
.pin
.pinInfo
.achName
), pConnector
, pmt
);
1758 dump_AM_MEDIA_TYPE(pmt
);
1763 hr
= BaseInputPinImpl_ReceiveConnection(iface
, pConnector
, pmt
);
1767 if(IsEqualIID(&pmt
->majortype
, &MEDIATYPE_Video
) &&
1768 IsEqualIID(&pmt
->formattype
, &FORMAT_VideoInfo
)) {
1769 ALLOCATOR_PROPERTIES req
, act
;
1770 VIDEOINFOHEADER
*vih
;
1773 vih
= (VIDEOINFOHEADER
*)pmt
->pbFormat
;
1774 avimuxin
->strh
.fcc
= ckidSTREAMHEADER
;
1775 avimuxin
->strh
.cb
= sizeof(AVISTREAMHEADER
) - FIELD_OFFSET(AVISTREAMHEADER
, fccType
);
1776 avimuxin
->strh
.fccType
= streamtypeVIDEO
;
1777 /* FIXME: fccHandler should be set differently */
1778 avimuxin
->strh
.fccHandler
= vih
->bmiHeader
.biCompression
?
1779 vih
->bmiHeader
.biCompression
: FCC('D','I','B',' ');
1780 avimuxin
->avg_time_per_frame
= vih
->AvgTimePerFrame
;
1781 avimuxin
->stop
= -1;
1784 req
.cbBuffer
= vih
->bmiHeader
.biSizeImage
;
1786 req
.cbPrefix
= sizeof(void*);
1787 hr
= IMemAllocator_SetProperties(avimuxin
->samples_allocator
, &req
, &act
);
1789 hr
= IMemAllocator_Commit(avimuxin
->samples_allocator
);
1791 BasePinImpl_Disconnect(iface
);
1795 size
= pmt
->cbFormat
- FIELD_OFFSET(VIDEOINFOHEADER
, bmiHeader
);
1796 avimuxin
->strf
= CoTaskMemAlloc(sizeof(RIFFCHUNK
) + ALIGN(FIELD_OFFSET(BITMAPINFO
, bmiColors
[vih
->bmiHeader
.biClrUsed
])));
1797 avimuxin
->strf
->fcc
= ckidSTREAMFORMAT
;
1798 avimuxin
->strf
->cb
= FIELD_OFFSET(BITMAPINFO
, bmiColors
[vih
->bmiHeader
.biClrUsed
]);
1799 if(size
> avimuxin
->strf
->cb
)
1800 size
= avimuxin
->strf
->cb
;
1801 memcpy(avimuxin
->strf
->data
, &vih
->bmiHeader
, size
);
1803 FIXME("format not supported: %s %s\n", debugstr_guid(&pmt
->majortype
),
1804 debugstr_guid(&pmt
->formattype
));
1808 return create_input_pin(This
);
1811 static HRESULT WINAPI
AviMuxIn_Disconnect(IPin
*iface
)
1813 AviMux
*This
= impl_from_in_IPin(iface
);
1814 AviMuxIn
*avimuxin
= AviMuxIn_from_IPin(iface
);
1815 IMediaSample
**prev
, *cur
;
1818 TRACE("(%p:%s)\n", This
, debugstr_w(avimuxin
->pin
.pin
.pinInfo
.achName
));
1820 hr
= BasePinImpl_Disconnect(iface
);
1824 IMemAllocator_Decommit(avimuxin
->samples_allocator
);
1825 while(avimuxin
->samples_head
) {
1826 cur
= avimuxin
->samples_head
;
1827 hr
= IMediaSample_GetPointer(cur
, (BYTE
**)&prev
);
1832 cur
= avimuxin
->samples_head
;
1833 avimuxin
->samples_head
= *prev
;
1834 IMediaSample_Release(cur
);
1836 if(cur
== avimuxin
->samples_head
)
1837 avimuxin
->samples_head
= NULL
;
1839 CoTaskMemFree(avimuxin
->strf
);
1840 avimuxin
->strf
= NULL
;
1844 static HRESULT WINAPI
AviMuxIn_ConnectedTo(IPin
*iface
, IPin
**pPin
)
1846 AviMux
*This
= impl_from_in_IPin(iface
);
1847 AviMuxIn
*avimuxin
= AviMuxIn_from_IPin(iface
);
1848 TRACE("(%p:%s)->(%p)\n", This
, debugstr_w(avimuxin
->pin
.pin
.pinInfo
.achName
), pPin
);
1849 return BasePinImpl_ConnectedTo(iface
, pPin
);
1852 static HRESULT WINAPI
AviMuxIn_ConnectionMediaType(IPin
*iface
, AM_MEDIA_TYPE
*pmt
)
1854 AviMux
*This
= impl_from_in_IPin(iface
);
1855 AviMuxIn
*avimuxin
= AviMuxIn_from_IPin(iface
);
1856 TRACE("(%p:%s)->(%p)\n", This
, debugstr_w(avimuxin
->pin
.pin
.pinInfo
.achName
), pmt
);
1857 return BasePinImpl_ConnectionMediaType(iface
, pmt
);
1860 static HRESULT WINAPI
AviMuxIn_QueryPinInfo(IPin
*iface
, PIN_INFO
*pInfo
)
1862 AviMux
*This
= impl_from_in_IPin(iface
);
1863 AviMuxIn
*avimuxin
= AviMuxIn_from_IPin(iface
);
1864 TRACE("(%p:%s)->(%p)\n", This
, debugstr_w(avimuxin
->pin
.pin
.pinInfo
.achName
), pInfo
);
1865 return BasePinImpl_QueryPinInfo(iface
, pInfo
);
1868 static HRESULT WINAPI
AviMuxIn_QueryDirection(IPin
*iface
, PIN_DIRECTION
*pPinDir
)
1870 AviMux
*This
= impl_from_in_IPin(iface
);
1871 AviMuxIn
*avimuxin
= AviMuxIn_from_IPin(iface
);
1872 TRACE("(%p:%s)->(%p)\n", This
, debugstr_w(avimuxin
->pin
.pin
.pinInfo
.achName
), pPinDir
);
1873 return BasePinImpl_QueryDirection(iface
, pPinDir
);
1876 static HRESULT WINAPI
AviMuxIn_QueryId(IPin
*iface
, LPWSTR
*Id
)
1878 AviMux
*This
= impl_from_in_IPin(iface
);
1879 AviMuxIn
*avimuxin
= AviMuxIn_from_IPin(iface
);
1880 TRACE("(%p:%s)->(%p)\n", This
, debugstr_w(avimuxin
->pin
.pin
.pinInfo
.achName
), Id
);
1881 return BasePinImpl_QueryId(iface
, Id
);
1884 static HRESULT WINAPI
AviMuxIn_QueryAccept(IPin
*iface
, const AM_MEDIA_TYPE
*pmt
)
1886 AviMux
*This
= impl_from_in_IPin(iface
);
1887 AviMuxIn
*avimuxin
= AviMuxIn_from_IPin(iface
);
1888 TRACE("(%p:%s)->(AM_MEDIA_TYPE(%p))\n", This
,
1889 debugstr_w(avimuxin
->pin
.pin
.pinInfo
.achName
), pmt
);
1890 dump_AM_MEDIA_TYPE(pmt
);
1891 return BasePinImpl_QueryAccept(iface
, pmt
);
1894 static HRESULT WINAPI
AviMuxIn_EnumMediaTypes(IPin
*iface
, IEnumMediaTypes
**ppEnum
)
1896 AviMux
*This
= impl_from_in_IPin(iface
);
1897 AviMuxIn
*avimuxin
= AviMuxIn_from_IPin(iface
);
1898 TRACE("(%p:%s)->(%p)\n", This
, debugstr_w(avimuxin
->pin
.pin
.pinInfo
.achName
), ppEnum
);
1899 return BasePinImpl_EnumMediaTypes(iface
, ppEnum
);
1902 static HRESULT WINAPI
AviMuxIn_QueryInternalConnections(
1903 IPin
*iface
, IPin
**apPin
, ULONG
*nPin
)
1905 AviMux
*This
= impl_from_in_IPin(iface
);
1906 AviMuxIn
*avimuxin
= AviMuxIn_from_IPin(iface
);
1907 TRACE("(%p:%s)->(%p %p)\n", This
, debugstr_w(avimuxin
->pin
.pin
.pinInfo
.achName
), apPin
, nPin
);
1908 return BasePinImpl_QueryInternalConnections(iface
, apPin
, nPin
);
1911 static HRESULT WINAPI
AviMuxIn_EndOfStream(IPin
*iface
)
1913 AviMux
*This
= impl_from_in_IPin(iface
);
1914 AviMuxIn
*avimuxin
= AviMuxIn_from_IPin(iface
);
1915 TRACE("(%p:%s)\n", This
, debugstr_w(avimuxin
->pin
.pin
.pinInfo
.achName
));
1916 return BaseInputPinImpl_EndOfStream(iface
);
1919 static HRESULT WINAPI
AviMuxIn_BeginFlush(IPin
*iface
)
1921 AviMux
*This
= impl_from_in_IPin(iface
);
1922 AviMuxIn
*avimuxin
= AviMuxIn_from_IPin(iface
);
1923 TRACE("(%p:%s)\n", This
, debugstr_w(avimuxin
->pin
.pin
.pinInfo
.achName
));
1924 return BaseInputPinImpl_BeginFlush(iface
);
1927 static HRESULT WINAPI
AviMuxIn_EndFlush(IPin
*iface
)
1929 AviMux
*This
= impl_from_in_IPin(iface
);
1930 AviMuxIn
*avimuxin
= AviMuxIn_from_IPin(iface
);
1931 TRACE("(%p:%s)\n", This
, debugstr_w(avimuxin
->pin
.pin
.pinInfo
.achName
));
1932 return BaseInputPinImpl_EndFlush(iface
);
1935 static HRESULT WINAPI
AviMuxIn_NewSegment(IPin
*iface
, REFERENCE_TIME tStart
,
1936 REFERENCE_TIME tStop
, double dRate
)
1938 AviMux
*This
= impl_from_in_IPin(iface
);
1939 AviMuxIn
*avimuxin
= AviMuxIn_from_IPin(iface
);
1940 TRACE("(%p:%s)->(%s %s %f)\n", This
, debugstr_w(avimuxin
->pin
.pin
.pinInfo
.achName
),
1941 wine_dbgstr_longlong(tStart
), wine_dbgstr_longlong(tStop
), dRate
);
1942 return BasePinImpl_NewSegment(iface
, tStart
, tStop
, dRate
);
1945 static const IPinVtbl AviMuxIn_PinVtbl
= {
1946 AviMuxIn_QueryInterface
,
1950 AviMuxIn_ReceiveConnection
,
1951 AviMuxIn_Disconnect
,
1952 AviMuxIn_ConnectedTo
,
1953 AviMuxIn_ConnectionMediaType
,
1954 AviMuxIn_QueryPinInfo
,
1955 AviMuxIn_QueryDirection
,
1957 AviMuxIn_QueryAccept
,
1958 AviMuxIn_EnumMediaTypes
,
1959 AviMuxIn_QueryInternalConnections
,
1960 AviMuxIn_EndOfStream
,
1961 AviMuxIn_BeginFlush
,
1966 static inline AviMuxIn
* AviMuxIn_from_IAMStreamControl(IAMStreamControl
*iface
)
1968 return CONTAINING_RECORD(iface
, AviMuxIn
, IAMStreamControl_iface
);
1971 static HRESULT WINAPI
AviMuxIn_AMStreamControl_QueryInterface(
1972 IAMStreamControl
*iface
, REFIID riid
, void **ppv
)
1974 AviMuxIn
*avimuxin
= AviMuxIn_from_IAMStreamControl(iface
);
1975 return IPin_QueryInterface(&avimuxin
->pin
.pin
.IPin_iface
, riid
, ppv
);
1978 static ULONG WINAPI
AviMuxIn_AMStreamControl_AddRef(IAMStreamControl
*iface
)
1980 AviMuxIn
*avimuxin
= AviMuxIn_from_IAMStreamControl(iface
);
1981 AviMux
*This
= impl_from_in_IPin(&avimuxin
->pin
.pin
.IPin_iface
);
1982 return IBaseFilter_AddRef(&This
->filter
.IBaseFilter_iface
);
1985 static ULONG WINAPI
AviMuxIn_AMStreamControl_Release(IAMStreamControl
*iface
)
1987 AviMuxIn
*avimuxin
= AviMuxIn_from_IAMStreamControl(iface
);
1988 AviMux
*This
= impl_from_in_IPin(&avimuxin
->pin
.pin
.IPin_iface
);
1989 return IBaseFilter_Release(&This
->filter
.IBaseFilter_iface
);
1992 static HRESULT WINAPI
AviMuxIn_AMStreamControl_StartAt(IAMStreamControl
*iface
,
1993 const REFERENCE_TIME
*ptStart
, DWORD dwCookie
)
1995 AviMuxIn
*avimuxin
= AviMuxIn_from_IAMStreamControl(iface
);
1996 AviMux
*This
= impl_from_in_IPin(&avimuxin
->pin
.pin
.IPin_iface
);
1997 FIXME("(%p:%s)->(%p %x)\n", This
,
1998 debugstr_w(avimuxin
->pin
.pin
.pinInfo
.achName
), ptStart
, dwCookie
);
2002 static HRESULT WINAPI
AviMuxIn_AMStreamControl_StopAt(IAMStreamControl
*iface
,
2003 const REFERENCE_TIME
*ptStop
, BOOL bSendExtra
, DWORD dwCookie
)
2005 AviMuxIn
*avimuxin
= AviMuxIn_from_IAMStreamControl(iface
);
2006 AviMux
*This
= impl_from_in_IPin(&avimuxin
->pin
.pin
.IPin_iface
);
2007 FIXME("(%p:%s)->(%p %x %x)\n", This
, debugstr_w(avimuxin
->pin
.pin
.pinInfo
.achName
),
2008 ptStop
, bSendExtra
, dwCookie
);
2012 static HRESULT WINAPI
AviMuxIn_AMStreamControl_GetInfo(
2013 IAMStreamControl
*iface
, AM_STREAM_INFO
*pInfo
)
2015 AviMuxIn
*avimuxin
= AviMuxIn_from_IAMStreamControl(iface
);
2016 AviMux
*This
= impl_from_in_IPin(&avimuxin
->pin
.pin
.IPin_iface
);
2017 FIXME("(%p:%s)->(%p)\n", This
, debugstr_w(avimuxin
->pin
.pin
.pinInfo
.achName
), pInfo
);
2021 static const IAMStreamControlVtbl AviMuxIn_AMStreamControlVtbl
= {
2022 AviMuxIn_AMStreamControl_QueryInterface
,
2023 AviMuxIn_AMStreamControl_AddRef
,
2024 AviMuxIn_AMStreamControl_Release
,
2025 AviMuxIn_AMStreamControl_StartAt
,
2026 AviMuxIn_AMStreamControl_StopAt
,
2027 AviMuxIn_AMStreamControl_GetInfo
2030 static inline AviMuxIn
* AviMuxIn_from_IMemInputPin(IMemInputPin
*iface
)
2032 BaseInputPin
*bip
= CONTAINING_RECORD(iface
, BaseInputPin
, IMemInputPin_iface
);
2033 return CONTAINING_RECORD(bip
, AviMuxIn
, pin
);
2036 static HRESULT WINAPI
AviMuxIn_MemInputPin_QueryInterface(
2037 IMemInputPin
*iface
, REFIID riid
, void **ppv
)
2039 AviMuxIn
*avimuxin
= AviMuxIn_from_IMemInputPin(iface
);
2040 return IPin_QueryInterface(&avimuxin
->pin
.pin
.IPin_iface
, riid
, ppv
);
2043 static ULONG WINAPI
AviMuxIn_MemInputPin_AddRef(IMemInputPin
*iface
)
2045 AviMuxIn
*avimuxin
= AviMuxIn_from_IMemInputPin(iface
);
2046 AviMux
*This
= impl_from_in_IPin(&avimuxin
->pin
.pin
.IPin_iface
);
2047 return IBaseFilter_AddRef(&This
->filter
.IBaseFilter_iface
);
2050 static ULONG WINAPI
AviMuxIn_MemInputPin_Release(IMemInputPin
*iface
)
2052 AviMuxIn
*avimuxin
= AviMuxIn_from_IMemInputPin(iface
);
2053 AviMux
*This
= impl_from_in_IPin(&avimuxin
->pin
.pin
.IPin_iface
);
2054 return IBaseFilter_Release(&This
->filter
.IBaseFilter_iface
);
2057 static HRESULT WINAPI
AviMuxIn_MemInputPin_GetAllocator(
2058 IMemInputPin
*iface
, IMemAllocator
**ppAllocator
)
2060 AviMuxIn
*avimuxin
= AviMuxIn_from_IMemInputPin(iface
);
2061 AviMux
*This
= impl_from_in_IPin(&avimuxin
->pin
.pin
.IPin_iface
);
2063 TRACE("(%p:%s)->(%p)\n", This
, debugstr_w(avimuxin
->pin
.pin
.pinInfo
.achName
), ppAllocator
);
2068 IMemAllocator_AddRef(avimuxin
->pin
.pAllocator
);
2069 *ppAllocator
= avimuxin
->pin
.pAllocator
;
2073 static HRESULT WINAPI
AviMuxIn_MemInputPin_NotifyAllocator(
2074 IMemInputPin
*iface
, IMemAllocator
*pAllocator
, BOOL bReadOnly
)
2076 AviMuxIn
*avimuxin
= AviMuxIn_from_IMemInputPin(iface
);
2077 AviMux
*This
= impl_from_in_IPin(&avimuxin
->pin
.pin
.IPin_iface
);
2078 ALLOCATOR_PROPERTIES props
;
2081 TRACE("(%p:%s)->(%p %x)\n", This
, debugstr_w(avimuxin
->pin
.pin
.pinInfo
.achName
),
2082 pAllocator
, bReadOnly
);
2087 memset(&props
, 0, sizeof(props
));
2088 hr
= IMemAllocator_GetProperties(pAllocator
, &props
);
2094 return IMemAllocator_SetProperties(avimuxin
->pin
.pAllocator
, &props
, &props
);
2097 static HRESULT WINAPI
AviMuxIn_MemInputPin_GetAllocatorRequirements(
2098 IMemInputPin
*iface
, ALLOCATOR_PROPERTIES
*pProps
)
2100 AviMuxIn
*avimuxin
= AviMuxIn_from_IMemInputPin(iface
);
2101 AviMux
*This
= impl_from_in_IPin(&avimuxin
->pin
.pin
.IPin_iface
);
2103 TRACE("(%p:%s)->(%p)\n", This
, debugstr_w(avimuxin
->pin
.pin
.pinInfo
.achName
), pProps
);
2108 pProps
->cbAlign
= 1;
2109 pProps
->cbPrefix
= 8;
2113 static HRESULT WINAPI
AviMuxIn_MemInputPin_Receive(
2114 IMemInputPin
*iface
, IMediaSample
*pSample
)
2116 AviMuxIn
*avimuxin
= AviMuxIn_from_IMemInputPin(iface
);
2117 AviMux
*This
= impl_from_in_IPin(&avimuxin
->pin
.pin
.IPin_iface
);
2119 TRACE("(%p:%s)->(%p)\n", This
, debugstr_w(avimuxin
->pin
.pin
.pinInfo
.achName
), pSample
);
2121 return avimuxin
->pin
.pFuncsTable
->pfnReceive(&avimuxin
->pin
, pSample
);
2124 static HRESULT WINAPI
AviMuxIn_MemInputPin_ReceiveMultiple(IMemInputPin
*iface
,
2125 IMediaSample
**pSamples
, LONG nSamples
, LONG
*nSamplesProcessed
)
2127 AviMuxIn
*avimuxin
= AviMuxIn_from_IMemInputPin(iface
);
2128 AviMux
*This
= impl_from_in_IPin(&avimuxin
->pin
.pin
.IPin_iface
);
2131 TRACE("(%p:%s)->(%p %d %p)\n", This
, debugstr_w(avimuxin
->pin
.pin
.pinInfo
.achName
),
2132 pSamples
, nSamples
, nSamplesProcessed
);
2134 for(*nSamplesProcessed
=0; *nSamplesProcessed
<nSamples
; (*nSamplesProcessed
)++)
2136 hr
= avimuxin
->pin
.pFuncsTable
->pfnReceive(&avimuxin
->pin
, pSamples
[*nSamplesProcessed
]);
2144 static HRESULT WINAPI
AviMuxIn_MemInputPin_ReceiveCanBlock(IMemInputPin
*iface
)
2146 AviMuxIn
*avimuxin
= AviMuxIn_from_IMemInputPin(iface
);
2147 AviMux
*This
= impl_from_in_IPin(&avimuxin
->pin
.pin
.IPin_iface
);
2150 TRACE("(%p:%s)\n", This
, debugstr_w(avimuxin
->pin
.pin
.pinInfo
.achName
));
2152 if(!This
->out
->pin
.pMemInputPin
)
2155 hr
= IMemInputPin_ReceiveCanBlock(This
->out
->pin
.pMemInputPin
);
2156 return hr
!= S_FALSE
? S_OK
: S_FALSE
;
2159 static const IMemInputPinVtbl AviMuxIn_MemInputPinVtbl
= {
2160 AviMuxIn_MemInputPin_QueryInterface
,
2161 AviMuxIn_MemInputPin_AddRef
,
2162 AviMuxIn_MemInputPin_Release
,
2163 AviMuxIn_MemInputPin_GetAllocator
,
2164 AviMuxIn_MemInputPin_NotifyAllocator
,
2165 AviMuxIn_MemInputPin_GetAllocatorRequirements
,
2166 AviMuxIn_MemInputPin_Receive
,
2167 AviMuxIn_MemInputPin_ReceiveMultiple
,
2168 AviMuxIn_MemInputPin_ReceiveCanBlock
2171 static inline AviMuxIn
* AviMuxIn_from_IPropertyBag(IPropertyBag
*iface
)
2173 return CONTAINING_RECORD(iface
, AviMuxIn
, IPropertyBag_iface
);
2176 static HRESULT WINAPI
AviMuxIn_PropertyBag_QueryInterface(
2177 IPropertyBag
*iface
, REFIID riid
, void **ppv
)
2179 AviMuxIn
*avimuxin
= AviMuxIn_from_IPropertyBag(iface
);
2180 return IPin_QueryInterface(&avimuxin
->pin
.pin
.IPin_iface
, riid
, ppv
);
2183 static ULONG WINAPI
AviMuxIn_PropertyBag_AddRef(IPropertyBag
*iface
)
2185 AviMuxIn
*avimuxin
= AviMuxIn_from_IPropertyBag(iface
);
2186 AviMux
*This
= impl_from_in_IPin(&avimuxin
->pin
.pin
.IPin_iface
);
2187 return IBaseFilter_AddRef(&This
->filter
.IBaseFilter_iface
);
2190 static ULONG WINAPI
AviMuxIn_PropertyBag_Release(IPropertyBag
*iface
)
2192 AviMuxIn
*avimuxin
= AviMuxIn_from_IPropertyBag(iface
);
2193 AviMux
*This
= impl_from_in_IPin(&avimuxin
->pin
.pin
.IPin_iface
);
2194 return IBaseFilter_Release(&This
->filter
.IBaseFilter_iface
);
2197 static HRESULT WINAPI
AviMuxIn_PropertyBag_Read(IPropertyBag
*iface
,
2198 LPCOLESTR pszPropName
, VARIANT
*pVar
, IErrorLog
*pErrorLog
)
2200 AviMuxIn
*avimuxin
= AviMuxIn_from_IPropertyBag(iface
);
2201 AviMux
*This
= impl_from_in_IPin(&avimuxin
->pin
.pin
.IPin_iface
);
2202 FIXME("(%p:%s)->(%s %p %p)\n", This
, debugstr_w(avimuxin
->pin
.pin
.pinInfo
.achName
),
2203 debugstr_w(pszPropName
), pVar
, pErrorLog
);
2207 static HRESULT WINAPI
AviMuxIn_PropertyBag_Write(IPropertyBag
*iface
,
2208 LPCOLESTR pszPropName
, VARIANT
*pVar
)
2210 AviMuxIn
*avimuxin
= AviMuxIn_from_IPropertyBag(iface
);
2211 AviMux
*This
= impl_from_in_IPin(&avimuxin
->pin
.pin
.IPin_iface
);
2212 FIXME("(%p:%s)->(%s %p)\n", This
, debugstr_w(avimuxin
->pin
.pin
.pinInfo
.achName
),
2213 debugstr_w(pszPropName
), pVar
);
2217 static const IPropertyBagVtbl AviMuxIn_PropertyBagVtbl
= {
2218 AviMuxIn_PropertyBag_QueryInterface
,
2219 AviMuxIn_PropertyBag_AddRef
,
2220 AviMuxIn_PropertyBag_Release
,
2221 AviMuxIn_PropertyBag_Read
,
2222 AviMuxIn_PropertyBag_Write
2225 static inline AviMuxIn
* AviMuxIn_from_IQualityControl(IQualityControl
*iface
)
2227 return CONTAINING_RECORD(iface
, AviMuxIn
, IQualityControl_iface
);
2230 static HRESULT WINAPI
AviMuxIn_QualityControl_QueryInterface(
2231 IQualityControl
*iface
, REFIID riid
, void **ppv
)
2233 AviMuxIn
*avimuxin
= AviMuxIn_from_IQualityControl(iface
);
2234 return IPin_QueryInterface(&avimuxin
->pin
.pin
.IPin_iface
, riid
, ppv
);
2237 static ULONG WINAPI
AviMuxIn_QualityControl_AddRef(IQualityControl
*iface
)
2239 AviMuxIn
*avimuxin
= AviMuxIn_from_IQualityControl(iface
);
2240 AviMux
*This
= impl_from_in_IPin(&avimuxin
->pin
.pin
.IPin_iface
);
2241 return IBaseFilter_AddRef(&This
->filter
.IBaseFilter_iface
);
2244 static ULONG WINAPI
AviMuxIn_QualityControl_Release(IQualityControl
*iface
)
2246 AviMuxIn
*avimuxin
= AviMuxIn_from_IQualityControl(iface
);
2247 AviMux
*This
= impl_from_in_IPin(&avimuxin
->pin
.pin
.IPin_iface
);
2248 return IBaseFilter_Release(&This
->filter
.IBaseFilter_iface
);
2251 static HRESULT WINAPI
AviMuxIn_QualityControl_Notify(IQualityControl
*iface
,
2252 IBaseFilter
*pSelf
, Quality q
)
2254 AviMuxIn
*avimuxin
= AviMuxIn_from_IQualityControl(iface
);
2255 AviMux
*This
= impl_from_in_IPin(&avimuxin
->pin
.pin
.IPin_iface
);
2256 FIXME("(%p:%s)->(%p { 0x%x %u %s %s })\n", This
, debugstr_w(avimuxin
->pin
.pin
.pinInfo
.achName
), pSelf
,
2257 q
.Type
, q
.Proportion
,
2258 wine_dbgstr_longlong(q
.Late
),
2259 wine_dbgstr_longlong(q
.TimeStamp
));
2263 static HRESULT WINAPI
AviMuxIn_QualityControl_SetSink(
2264 IQualityControl
*iface
, IQualityControl
*piqc
)
2266 AviMuxIn
*avimuxin
= AviMuxIn_from_IQualityControl(iface
);
2267 AviMux
*This
= impl_from_in_IPin(&avimuxin
->pin
.pin
.IPin_iface
);
2268 FIXME("(%p:%s)->(%p)\n", This
, debugstr_w(avimuxin
->pin
.pin
.pinInfo
.achName
), piqc
);
2272 static const IQualityControlVtbl AviMuxIn_QualityControlVtbl
= {
2273 AviMuxIn_QualityControl_QueryInterface
,
2274 AviMuxIn_QualityControl_AddRef
,
2275 AviMuxIn_QualityControl_Release
,
2276 AviMuxIn_QualityControl_Notify
,
2277 AviMuxIn_QualityControl_SetSink
2280 static HRESULT
create_input_pin(AviMux
*avimux
)
2282 static const WCHAR name
[] = {'I','n','p','u','t',' ','0','0',0};
2286 if(avimux
->input_pin_no
>= MAX_PIN_NO
-1)
2289 info
.dir
= PINDIR_INPUT
;
2290 info
.pFilter
= &avimux
->filter
.IBaseFilter_iface
;
2291 memcpy(info
.achName
, name
, sizeof(name
));
2292 info
.achName
[7] = '0' + (avimux
->input_pin_no
+1) % 10;
2293 info
.achName
[6] = '0' + (avimux
->input_pin_no
+1) / 10;
2295 hr
= BaseInputPin_Construct(&AviMuxIn_PinVtbl
, sizeof(AviMuxIn
), &info
,
2296 &AviMuxIn_BaseInputFuncTable
, &avimux
->filter
.csFilter
, NULL
, (IPin
**)&avimux
->in
[avimux
->input_pin_no
]);
2299 avimux
->in
[avimux
->input_pin_no
]->pin
.IMemInputPin_iface
.lpVtbl
= &AviMuxIn_MemInputPinVtbl
;
2300 avimux
->in
[avimux
->input_pin_no
]->IAMStreamControl_iface
.lpVtbl
= &AviMuxIn_AMStreamControlVtbl
;
2301 avimux
->in
[avimux
->input_pin_no
]->IPropertyBag_iface
.lpVtbl
= &AviMuxIn_PropertyBagVtbl
;
2302 avimux
->in
[avimux
->input_pin_no
]->IQualityControl_iface
.lpVtbl
= &AviMuxIn_QualityControlVtbl
;
2304 avimux
->in
[avimux
->input_pin_no
]->samples_head
= NULL
;
2305 hr
= CoCreateInstance(&CLSID_MemoryAllocator
, NULL
, CLSCTX_INPROC_SERVER
,
2306 &IID_IMemAllocator
, (void**)&avimux
->in
[avimux
->input_pin_no
]->samples_allocator
);
2308 BaseInputPinImpl_Release(&avimux
->in
[avimux
->input_pin_no
]->pin
.pin
.IPin_iface
);
2312 hr
= CoCreateInstance(&CLSID_MemoryAllocator
, NULL
, CLSCTX_INPROC_SERVER
,
2313 &IID_IMemAllocator
, (void**)&avimux
->in
[avimux
->input_pin_no
]->pin
.pAllocator
);
2315 IMemAllocator_Release(avimux
->in
[avimux
->input_pin_no
]->samples_allocator
);
2316 BaseInputPinImpl_Release(&avimux
->in
[avimux
->input_pin_no
]->pin
.pin
.IPin_iface
);
2320 avimux
->in
[avimux
->input_pin_no
]->stream_time
= 0;
2321 memset(&avimux
->in
[avimux
->input_pin_no
]->strh
, 0, sizeof(avimux
->in
[avimux
->input_pin_no
]->strh
));
2322 avimux
->in
[avimux
->input_pin_no
]->strf
= NULL
;
2323 memset(&avimux
->in
[avimux
->input_pin_no
]->indx_data
, 0, sizeof(avimux
->in
[avimux
->input_pin_no
]->indx_data
));
2324 memset(&avimux
->in
[avimux
->input_pin_no
]->ix_data
, 0, sizeof(avimux
->in
[avimux
->input_pin_no
]->ix_data
));
2325 avimux
->in
[avimux
->input_pin_no
]->indx
= (AVISUPERINDEX
*)&avimux
->in
[avimux
->input_pin_no
]->indx_data
;
2326 avimux
->in
[avimux
->input_pin_no
]->ix
= (AVISTDINDEX
*)avimux
->in
[avimux
->input_pin_no
]->ix_data
;
2328 avimux
->input_pin_no
++;
2332 IUnknown
* WINAPI
QCAP_createAVIMux(IUnknown
*pUnkOuter
, HRESULT
*phr
)
2334 static const WCHAR output_name
[] = {'A','V','I',' ','O','u','t',0};
2340 TRACE("(%p)\n", pUnkOuter
);
2343 *phr
= CLASS_E_NOAGGREGATION
;
2347 avimux
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(AviMux
));
2349 *phr
= E_OUTOFMEMORY
;
2353 BaseFilter_Init(&avimux
->filter
, &AviMuxVtbl
, &CLSID_AviDest
,
2354 (DWORD_PTR
)(__FILE__
": AviMux.csFilter"), &filter_func_table
);
2355 avimux
->IConfigAviMux_iface
.lpVtbl
= &ConfigAviMuxVtbl
;
2356 avimux
->IConfigInterleaving_iface
.lpVtbl
= &ConfigInterleavingVtbl
;
2357 avimux
->IMediaSeeking_iface
.lpVtbl
= &MediaSeekingVtbl
;
2358 avimux
->IPersistMediaPropertyBag_iface
.lpVtbl
= &PersistMediaPropertyBagVtbl
;
2359 avimux
->ISpecifyPropertyPages_iface
.lpVtbl
= &SpecifyPropertyPagesVtbl
;
2361 info
.dir
= PINDIR_OUTPUT
;
2362 info
.pFilter
= &avimux
->filter
.IBaseFilter_iface
;
2363 lstrcpyW(info
.achName
, output_name
);
2364 hr
= BaseOutputPin_Construct(&AviMuxOut_PinVtbl
, sizeof(AviMuxOut
), &info
,
2365 &AviMuxOut_BaseOutputFuncTable
, &avimux
->filter
.csFilter
, (IPin
**)&avimux
->out
);
2367 BaseFilterImpl_Release(&avimux
->filter
.IBaseFilter_iface
);
2368 HeapFree(GetProcessHeap(), 0, avimux
);
2372 avimux
->out
->IQualityControl_iface
.lpVtbl
= &AviMuxOut_QualityControlVtbl
;
2373 avimux
->out
->cur_stream
= 0;
2374 avimux
->out
->cur_time
= 0;
2375 avimux
->out
->stream
= NULL
;
2377 hr
= create_input_pin(avimux
);
2379 BaseOutputPinImpl_Release(&avimux
->out
->pin
.pin
.IPin_iface
);
2380 BaseFilterImpl_Release(&avimux
->filter
.IBaseFilter_iface
);
2381 HeapFree(GetProcessHeap(), 0, avimux
);
2386 avimux
->interleave
= 10000000;
2388 ObjectRefCount(TRUE
);
2390 return (IUnknown
*)&avimux
->filter
.IBaseFilter_iface
;