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 LONG WINAPI
AviMux_GetPinCount(BaseFilter
*iface
)
138 AviMux
*This
= impl_from_BaseFilter(iface
);
139 TRACE("(%p)\n", This
);
140 return This
->input_pin_no
+1;
143 static const BaseFilterFuncTable filter_func_table
= {
148 static inline AviMux
* impl_from_IBaseFilter(IBaseFilter
*iface
)
150 BaseFilter
*filter
= CONTAINING_RECORD(iface
, BaseFilter
, IBaseFilter_iface
);
151 return impl_from_BaseFilter(filter
);
154 static HRESULT WINAPI
AviMux_QueryInterface(IBaseFilter
*iface
, REFIID riid
, void **ppv
)
156 AviMux
*This
= impl_from_IBaseFilter(iface
);
158 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), ppv
);
160 if(IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IPersist
) ||
161 IsEqualIID(riid
, &IID_IMediaFilter
) || IsEqualIID(riid
, &IID_IBaseFilter
))
162 *ppv
= &This
->filter
.IBaseFilter_iface
;
163 else if(IsEqualIID(riid
, &IID_IConfigAviMux
))
164 *ppv
= &This
->IConfigAviMux_iface
;
165 else if(IsEqualIID(riid
, &IID_IConfigInterleaving
))
166 *ppv
= &This
->IConfigInterleaving_iface
;
167 else if(IsEqualIID(riid
, &IID_IMediaSeeking
))
168 *ppv
= &This
->IMediaSeeking_iface
;
169 else if(IsEqualIID(riid
, &IID_IPersistMediaPropertyBag
))
170 *ppv
= &This
->IPersistMediaPropertyBag_iface
;
171 else if(IsEqualIID(riid
, &IID_ISpecifyPropertyPages
))
172 *ppv
= &This
->ISpecifyPropertyPages_iface
;
174 FIXME("no interface for %s\n", debugstr_guid(riid
));
176 return E_NOINTERFACE
;
179 IUnknown_AddRef((IUnknown
*)*ppv
);
183 static ULONG WINAPI
AviMux_Release(IBaseFilter
*iface
)
185 AviMux
*This
= impl_from_IBaseFilter(iface
);
186 ULONG ref
= BaseFilterImpl_Release(iface
);
188 TRACE("(%p) new refcount: %u\n", This
, ref
);
193 BaseOutputPinImpl_Release(&This
->out
->pin
.pin
.IPin_iface
);
195 for(i
=0; i
<This
->input_pin_no
; i
++) {
196 IPin_Disconnect(&This
->in
[i
]->pin
.pin
.IPin_iface
);
197 IMemAllocator_Release(This
->in
[i
]->samples_allocator
);
198 This
->in
[i
]->samples_allocator
= NULL
;
199 BaseInputPinImpl_Release(&This
->in
[i
]->pin
.pin
.IPin_iface
);
202 HeapFree(GetProcessHeap(), 0, This
->idx1
);
203 HeapFree(GetProcessHeap(), 0, This
);
204 ObjectRefCount(FALSE
);
209 static HRESULT
out_flush(AviMux
*This
)
214 if(!This
->out
->buf_pos
)
217 hr
= IStream_Write(This
->out
->stream
, This
->out
->buf
, This
->out
->buf_pos
, &written
);
220 if(written
!= This
->out
->buf_pos
)
223 This
->out
->buf_pos
= 0;
227 static HRESULT
out_seek(AviMux
*This
, int pos
)
232 hr
= out_flush(This
);
237 hr
= IStream_Seek(This
->out
->stream
, li
, STREAM_SEEK_SET
, NULL
);
241 This
->out
->out_pos
= pos
;
242 if(This
->out
->out_pos
> This
->out
->size
)
243 This
->out
->size
= This
->out
->out_pos
;
247 static HRESULT
out_write(AviMux
*This
, const void *data
, int size
)
253 if(size
> sizeof(This
->out
->buf
)-This
->out
->buf_pos
)
254 chunk_size
= sizeof(This
->out
->buf
)-This
->out
->buf_pos
;
258 memcpy(This
->out
->buf
+ This
->out
->buf_pos
, data
, chunk_size
);
260 data
= (const BYTE
*)data
+ chunk_size
;
261 This
->out
->buf_pos
+= chunk_size
;
262 This
->out
->out_pos
+= chunk_size
;
263 if(This
->out
->out_pos
> This
->out
->size
)
264 This
->out
->size
= This
->out
->out_pos
;
268 hr
= out_flush(This
);
276 static inline HRESULT
idx1_add_entry(AviMux
*avimux
, DWORD ckid
, DWORD flags
, DWORD off
, DWORD len
)
278 if(avimux
->idx1_entries
== avimux
->idx1_size
) {
279 AVIINDEXENTRY
*new_idx
= HeapReAlloc(GetProcessHeap(), 0, avimux
->idx1
,
280 sizeof(*avimux
->idx1
)*2*avimux
->idx1_size
);
282 return E_OUTOFMEMORY
;
284 avimux
->idx1_size
*= 2;
285 avimux
->idx1
= new_idx
;
288 avimux
->idx1
[avimux
->idx1_entries
].ckid
= ckid
;
289 avimux
->idx1
[avimux
->idx1_entries
].dwFlags
= flags
;
290 avimux
->idx1
[avimux
->idx1_entries
].dwChunkOffset
= off
;
291 avimux
->idx1
[avimux
->idx1_entries
].dwChunkLength
= len
;
292 avimux
->idx1_entries
++;
296 static HRESULT
flush_queue(AviMux
*avimux
, AviMuxIn
*avimuxin
, BOOL closing
)
298 IMediaSample
*sample
, **prev
, **head_prev
;
305 if(avimux
->out
->cur_stream
!= avimuxin
->stream_id
)
308 while(avimuxin
->samples_head
) {
309 hr
= IMediaSample_GetPointer(avimuxin
->samples_head
, (BYTE
**)&head_prev
);
314 hr
= IMediaSample_GetPointer(*head_prev
, (BYTE
**)&prev
);
320 size
= IMediaSample_GetActualDataLength(sample
);
321 hr
= IMediaSample_GetPointer(sample
, &data
);
324 flags
= IMediaSample_IsDiscontinuity(sample
)==S_OK
? AM_SAMPLE_TIMEDISCONTINUITY
: 0;
325 if(IMediaSample_IsSyncPoint(sample
) == S_OK
)
326 flags
|= AM_SAMPLE_SPLICEPOINT
;
328 if(avimuxin
->stream_time
+ (closing
? 0 : avimuxin
->strh
.dwScale
) > avimux
->out
->cur_time
&&
329 !(flags
& AM_SAMPLE_TIMEDISCONTINUITY
)) {
333 avimux
->out
->cur_stream
++;
334 if(avimux
->out
->cur_stream
>= avimux
->input_pin_no
-1) {
335 avimux
->out
->cur_time
+= avimux
->interleave
;
336 avimux
->out
->cur_stream
= 0;
338 avimuxin
= avimux
->in
[avimux
->out
->cur_stream
];
342 if(avimuxin
->ix
->nEntriesInUse
== AVISTDINDEX_ENTRIES
) {
343 /* TODO: use output pins Deliver/Receive method */
344 hr
= out_seek(avimux
, avimuxin
->ix_off
);
347 hr
= out_write(avimux
, avimuxin
->ix
, sizeof(avimuxin
->ix_data
));
351 avimuxin
->indx
->aIndex
[avimuxin
->indx
->nEntriesInUse
].qwOffset
= avimuxin
->ix_off
;
352 avimuxin
->indx
->aIndex
[avimuxin
->indx
->nEntriesInUse
].dwSize
= sizeof(avimuxin
->ix_data
);
353 avimuxin
->indx
->aIndex
[avimuxin
->indx
->nEntriesInUse
].dwDuration
= AVISTDINDEX_ENTRIES
;
354 avimuxin
->indx
->nEntriesInUse
++;
356 memset(avimuxin
->ix
->aIndex
, 0, sizeof(avimuxin
->ix
->aIndex
)*avimuxin
->ix
->nEntriesInUse
);
357 avimuxin
->ix
->nEntriesInUse
= 0;
358 avimuxin
->ix
->qwBaseOffset
= 0;
360 avimuxin
->ix_off
= avimux
->out
->size
;
361 avimux
->out
->size
+= sizeof(avimuxin
->ix_data
);
364 if(*head_prev
== avimuxin
->samples_head
)
365 avimuxin
->samples_head
= NULL
;
369 avimuxin
->stream_time
+= avimuxin
->strh
.dwScale
;
370 avimuxin
->strh
.dwLength
++;
371 if(!(flags
& AM_SAMPLE_TIMEDISCONTINUITY
)) {
372 if(!avimuxin
->ix
->qwBaseOffset
)
373 avimuxin
->ix
->qwBaseOffset
= avimux
->out
->size
;
374 avimuxin
->ix
->aIndex
[avimuxin
->ix
->nEntriesInUse
].dwOffset
= avimux
->out
->size
375 + sizeof(RIFFCHUNK
) - avimuxin
->ix
->qwBaseOffset
;
377 hr
= out_seek(avimux
, avimux
->out
->size
);
379 IMediaSample_Release(sample
);
383 avimuxin
->ix
->aIndex
[avimuxin
->ix
->nEntriesInUse
].dwSize
= size
|
384 (flags
& AM_SAMPLE_SPLICEPOINT
? 0 : AVISTDINDEX_DELTAFRAME
);
385 avimuxin
->ix
->nEntriesInUse
++;
387 rf
.fcc
= FCC('0'+avimuxin
->stream_id
/10, '0'+avimuxin
->stream_id
%10,
388 'd', flags
& AM_SAMPLE_SPLICEPOINT
? 'b' : 'c');
390 hr
= idx1_add_entry(avimux
, rf
.fcc
, flags
& AM_SAMPLE_SPLICEPOINT
? AVIIF_KEYFRAME
: 0,
391 flags
& AM_SAMPLE_TIMEDISCONTINUITY
?
392 avimux
->idx1
[avimux
->idx1_entries
-1].dwChunkOffset
: avimux
->out
->size
, size
);
394 IMediaSample_Release(sample
);
398 if(!(flags
& AM_SAMPLE_TIMEDISCONTINUITY
)) {
399 hr
= out_write(avimux
, &rf
, sizeof(rf
));
401 IMediaSample_Release(sample
);
404 hr
= out_write(avimux
, data
, size
);
406 IMediaSample_Release(sample
);
410 hr
= out_write(avimux
, &flags
, ALIGN(rf
.cb
)-rf
.cb
);
412 IMediaSample_Release(sample
);
416 IMediaSample_Release(sample
);
421 static HRESULT
queue_sample(AviMux
*avimux
, AviMuxIn
*avimuxin
, IMediaSample
*sample
)
423 IMediaSample
**prev
, **head_prev
;
426 hr
= IMediaSample_GetPointer(sample
, (BYTE
**)&prev
);
431 if(avimuxin
->samples_head
) {
432 hr
= IMediaSample_GetPointer(avimuxin
->samples_head
, (BYTE
**)&head_prev
);
442 avimuxin
->samples_head
= sample
;
443 IMediaSample_AddRef(sample
);
445 return flush_queue(avimux
, avimuxin
, FALSE
);
448 static HRESULT WINAPI
AviMux_Stop(IBaseFilter
*iface
)
450 AviMux
*This
= impl_from_IBaseFilter(iface
);
454 TRACE("(%p)\n", This
);
456 if(This
->filter
.state
== State_Stopped
)
459 if(This
->out
->stream
) {
463 int idx1_off
, empty_stream
;
465 empty_stream
= This
->out
->cur_stream
;
466 for(i
=empty_stream
+1; ; i
++) {
467 if(i
>= This
->input_pin_no
-1)
469 if(i
== empty_stream
)
472 This
->out
->cur_stream
= i
;
473 hr
= flush_queue(This
, This
->in
[This
->out
->cur_stream
], TRUE
);
478 idx1_off
= This
->out
->size
;
479 rc
.fcc
= ckidAVIOLDINDEX
;
480 rc
.cb
= This
->idx1_entries
* sizeof(*This
->idx1
);
481 hr
= out_write(This
, &rc
, sizeof(rc
));
484 hr
= out_write(This
, This
->idx1
, This
->idx1_entries
* sizeof(*This
->idx1
));
487 /* native writes 8 '\0' characters after the end of RIFF data */
489 hr
= out_write(This
, &i
, sizeof(i
));
492 hr
= out_write(This
, &i
, sizeof(i
));
496 for(i
=0; i
<This
->input_pin_no
; i
++) {
497 if(!This
->in
[i
]->pin
.pin
.pConnectedTo
)
500 hr
= out_seek(This
, This
->in
[i
]->ix_off
);
504 This
->in
[i
]->indx
->aIndex
[This
->in
[i
]->indx
->nEntriesInUse
].qwOffset
= This
->in
[i
]->ix_off
;
505 This
->in
[i
]->indx
->aIndex
[This
->in
[i
]->indx
->nEntriesInUse
].dwSize
= sizeof(This
->in
[i
]->ix_data
);
506 This
->in
[i
]->indx
->aIndex
[This
->in
[i
]->indx
->nEntriesInUse
].dwDuration
= This
->in
[i
]->strh
.dwLength
;
507 if(This
->in
[i
]->indx
->nEntriesInUse
) {
508 This
->in
[i
]->indx
->aIndex
[This
->in
[i
]->indx
->nEntriesInUse
].dwDuration
-=
509 This
->in
[i
]->indx
->aIndex
[This
->in
[i
]->indx
->nEntriesInUse
-1].dwDuration
;
511 This
->in
[i
]->indx
->nEntriesInUse
++;
512 hr
= out_write(This
, This
->in
[i
]->ix
, sizeof(This
->in
[i
]->ix_data
));
517 hr
= out_seek(This
, 0);
521 rl
.fcc
= FCC('R','I','F','F');
522 rl
.cb
= This
->out
->size
-sizeof(RIFFCHUNK
)-2*sizeof(int);
523 rl
.fccListType
= FCC('A','V','I',' ');
524 hr
= out_write(This
, &rl
, sizeof(rl
));
528 rl
.fcc
= FCC('L','I','S','T');
529 rl
.cb
= This
->out
->movi_off
- sizeof(RIFFLIST
) - sizeof(RIFFCHUNK
);
530 rl
.fccListType
= FCC('h','d','r','l');
531 hr
= out_write(This
, &rl
, sizeof(rl
));
535 /* FIXME: set This->avih.dwMaxBytesPerSec value */
536 This
->avih
.dwTotalFrames
= (This
->stop
-This
->start
) / 10 / This
->avih
.dwMicroSecPerFrame
;
537 hr
= out_write(This
, &This
->avih
, sizeof(This
->avih
));
541 for(i
=0; i
<This
->input_pin_no
; i
++) {
542 if(!This
->in
[i
]->pin
.pin
.pConnectedTo
)
545 rl
.cb
= sizeof(FOURCC
) + sizeof(AVISTREAMHEADER
) + sizeof(RIFFCHUNK
) +
546 This
->in
[i
]->strf
->cb
+ sizeof(This
->in
[i
]->indx_data
);
547 rl
.fccListType
= ckidSTREAMLIST
;
548 hr
= out_write(This
, &rl
, sizeof(rl
));
552 hr
= out_write(This
, &This
->in
[i
]->strh
, sizeof(AVISTREAMHEADER
));
556 hr
= out_write(This
, This
->in
[i
]->strf
, sizeof(RIFFCHUNK
) + This
->in
[i
]->strf
->cb
);
560 hr
= out_write(This
, This
->in
[i
]->indx
, sizeof(This
->in
[i
]->indx_data
));
565 rl
.cb
= sizeof(dmlh
) + sizeof(FOURCC
);
566 rl
.fccListType
= ckidODML
;
567 hr
= out_write(This
, &rl
, sizeof(rl
));
571 memset(&dmlh
, 0, sizeof(dmlh
));
572 dmlh
.fcc
= ckidAVIEXTHEADER
;
573 dmlh
.cb
= sizeof(dmlh
) - sizeof(RIFFCHUNK
);
574 dmlh
.dwGrandFrames
= This
->in
[0]->strh
.dwLength
;
575 hr
= out_write(This
, &dmlh
, sizeof(dmlh
));
577 rl
.cb
= idx1_off
- This
->out
->movi_off
- sizeof(RIFFCHUNK
);
578 rl
.fccListType
= FCC('m','o','v','i');
579 out_write(This
, &rl
, sizeof(rl
));
582 IStream_Release(This
->out
->stream
);
583 This
->out
->stream
= NULL
;
586 This
->filter
.state
= State_Stopped
;
590 static HRESULT WINAPI
AviMux_Pause(IBaseFilter
*iface
)
592 AviMux
*This
= impl_from_IBaseFilter(iface
);
593 FIXME("(%p)\n", This
);
597 static HRESULT WINAPI
AviMux_Run(IBaseFilter
*iface
, REFERENCE_TIME tStart
)
599 AviMux
*This
= impl_from_IBaseFilter(iface
);
603 TRACE("(%p)->(0x%x%08x)\n", This
, (ULONG
)(tStart
>> 32), (ULONG
)tStart
);
605 if(This
->filter
.state
== State_Running
)
608 if(This
->mode
!= INTERLEAVE_FULL
) {
609 FIXME("mode not supported (%d)\n", This
->mode
);
614 FIXME("tStart parameter ignored\n");
616 for(i
=0; i
<This
->input_pin_no
; i
++) {
620 if(!This
->in
[i
]->pin
.pin
.pConnectedTo
)
623 hr
= IPin_QueryInterface(This
->in
[i
]->pin
.pin
.pConnectedTo
,
624 &IID_IMediaSeeking
, (void**)&ms
);
628 hr
= IMediaSeeking_GetPositions(ms
, &cur
, &stop
);
630 IMediaSeeking_Release(ms
);
634 FIXME("Use IMediaSeeking to fill stream header\n");
635 IMediaSeeking_Release(ms
);
638 if(This
->out
->pin
.pMemInputPin
) {
639 hr
= IMemInputPin_QueryInterface(This
->out
->pin
.pMemInputPin
,
640 &IID_IStream
, (void**)&This
->out
->stream
);
645 This
->idx1_entries
= 0;
646 if(!This
->idx1_size
) {
647 This
->idx1_size
= 1024;
648 This
->idx1
= HeapAlloc(GetProcessHeap(), 0, sizeof(*This
->idx1
)*This
->idx1_size
);
650 return E_OUTOFMEMORY
;
653 This
->out
->size
= 3*sizeof(RIFFLIST
) + sizeof(AVIMAINHEADER
) + sizeof(AVIEXTHEADER
);
656 memset(&This
->avih
, 0, sizeof(This
->avih
));
657 for(i
=0; i
<This
->input_pin_no
; i
++) {
658 if(!This
->in
[i
]->pin
.pin
.pConnectedTo
)
661 This
->avih
.dwStreams
++;
662 This
->out
->size
+= sizeof(RIFFLIST
) + sizeof(AVISTREAMHEADER
) + sizeof(RIFFCHUNK
)
663 + This
->in
[i
]->strf
->cb
+ sizeof(This
->in
[i
]->indx_data
);
665 This
->in
[i
]->strh
.dwScale
= MulDiv(This
->in
[i
]->avg_time_per_frame
, This
->interleave
, 10000000);
666 This
->in
[i
]->strh
.dwRate
= This
->interleave
;
668 hr
= IMemAllocator_Commit(This
->in
[i
]->pin
.pAllocator
);
670 if(This
->out
->stream
) {
671 IStream_Release(This
->out
->stream
);
672 This
->out
->stream
= NULL
;
678 This
->out
->movi_off
= This
->out
->size
;
679 This
->out
->size
+= sizeof(RIFFLIST
);
681 idx1_add_entry(This
, FCC('7','F','x','x'), 0, This
->out
->movi_off
+sizeof(RIFFLIST
), 0);
684 for(i
=0; i
<This
->input_pin_no
; i
++) {
685 if(!This
->in
[i
]->pin
.pin
.pConnectedTo
)
688 This
->in
[i
]->ix_off
= This
->out
->size
;
689 This
->out
->size
+= sizeof(This
->in
[i
]->ix_data
);
690 This
->in
[i
]->ix
->fcc
= FCC('i','x','0'+stream_id
/10,'0'+stream_id
%10);
691 This
->in
[i
]->ix
->cb
= sizeof(This
->in
[i
]->ix_data
) - sizeof(RIFFCHUNK
);
692 This
->in
[i
]->ix
->wLongsPerEntry
= 2;
693 This
->in
[i
]->ix
->bIndexSubType
= 0;
694 This
->in
[i
]->ix
->bIndexType
= AVI_INDEX_OF_CHUNKS
;
695 This
->in
[i
]->ix
->dwChunkId
= FCC('0'+stream_id
/10,'0'+stream_id
%10,'d','b');
696 This
->in
[i
]->ix
->qwBaseOffset
= 0;
698 This
->in
[i
]->indx
->fcc
= ckidAVISUPERINDEX
;
699 This
->in
[i
]->indx
->cb
= sizeof(This
->in
[i
]->indx_data
) - sizeof(RIFFCHUNK
);
700 This
->in
[i
]->indx
->wLongsPerEntry
= 4;
701 This
->in
[i
]->indx
->bIndexSubType
= 0;
702 This
->in
[i
]->indx
->bIndexType
= AVI_INDEX_OF_INDEXES
;
703 This
->in
[i
]->indx
->dwChunkId
= This
->in
[i
]->ix
->dwChunkId
;
704 This
->in
[i
]->stream_id
= stream_id
++;
707 This
->out
->buf_pos
= 0;
708 This
->out
->out_pos
= 0;
710 This
->avih
.fcc
= ckidMAINAVIHEADER
;
711 This
->avih
.cb
= sizeof(AVIMAINHEADER
) - sizeof(RIFFCHUNK
);
712 /* TODO: Use first video stream */
713 This
->avih
.dwMicroSecPerFrame
= This
->in
[0]->avg_time_per_frame
/10;
714 This
->avih
.dwPaddingGranularity
= 1;
715 This
->avih
.dwFlags
= AVIF_TRUSTCKTYPE
| AVIF_HASINDEX
;
716 This
->avih
.dwWidth
= ((BITMAPINFOHEADER
*)This
->in
[0]->strf
->data
)->biWidth
;
717 This
->avih
.dwHeight
= ((BITMAPINFOHEADER
*)This
->in
[0]->strf
->data
)->biHeight
;
719 This
->filter
.state
= State_Running
;
723 static HRESULT WINAPI
AviMux_EnumPins(IBaseFilter
*iface
, IEnumPins
**ppEnum
)
725 AviMux
*This
= impl_from_IBaseFilter(iface
);
726 TRACE("(%p)->(%p)\n", This
, ppEnum
);
727 return BaseFilterImpl_EnumPins(iface
, ppEnum
);
730 static HRESULT WINAPI
AviMux_FindPin(IBaseFilter
*iface
, LPCWSTR Id
, IPin
**ppPin
)
732 AviMux
*This
= impl_from_IBaseFilter(iface
);
735 TRACE("(%p)->(%s %p)\n", This
, debugstr_w(Id
), ppPin
);
740 if(!lstrcmpiW(Id
, This
->out
->pin
.pin
.pinInfo
.achName
)) {
741 IPin_AddRef(&This
->out
->pin
.pin
.IPin_iface
);
742 *ppPin
= &This
->out
->pin
.pin
.IPin_iface
;
746 for(i
=0; i
<This
->input_pin_no
; i
++) {
747 if(lstrcmpiW(Id
, This
->in
[i
]->pin
.pin
.pinInfo
.achName
))
750 IPin_AddRef(&This
->in
[i
]->pin
.pin
.IPin_iface
);
751 *ppPin
= &This
->in
[i
]->pin
.pin
.IPin_iface
;
755 return VFW_E_NOT_FOUND
;
758 static HRESULT WINAPI
AviMux_QueryFilterInfo(IBaseFilter
*iface
, FILTER_INFO
*pInfo
)
760 AviMux
*This
= impl_from_IBaseFilter(iface
);
761 FIXME("(%p)->(%p)\n", This
, pInfo
);
765 static HRESULT WINAPI
AviMux_QueryVendorInfo(IBaseFilter
*iface
, LPWSTR
*pVendorInfo
)
767 AviMux
*This
= impl_from_IBaseFilter(iface
);
768 FIXME("(%p)->(%p)\n", This
, pVendorInfo
);
772 static const IBaseFilterVtbl AviMuxVtbl
= {
773 AviMux_QueryInterface
,
774 BaseFilterImpl_AddRef
,
776 BaseFilterImpl_GetClassID
,
780 BaseFilterImpl_GetState
,
781 BaseFilterImpl_SetSyncSource
,
782 BaseFilterImpl_GetSyncSource
,
785 AviMux_QueryFilterInfo
,
786 BaseFilterImpl_JoinFilterGraph
,
787 AviMux_QueryVendorInfo
790 static inline AviMux
* impl_from_IConfigAviMux(IConfigAviMux
*iface
)
792 return CONTAINING_RECORD(iface
, AviMux
, IConfigAviMux_iface
);
795 static HRESULT WINAPI
ConfigAviMux_QueryInterface(
796 IConfigAviMux
*iface
, REFIID riid
, void **ppv
)
798 AviMux
*This
= impl_from_IConfigAviMux(iface
);
799 return IBaseFilter_QueryInterface(&This
->filter
.IBaseFilter_iface
, riid
, ppv
);
802 static ULONG WINAPI
ConfigAviMux_AddRef(IConfigAviMux
*iface
)
804 AviMux
*This
= impl_from_IConfigAviMux(iface
);
805 return IBaseFilter_AddRef(&This
->filter
.IBaseFilter_iface
);
808 static ULONG WINAPI
ConfigAviMux_Release(IConfigAviMux
*iface
)
810 AviMux
*This
= impl_from_IConfigAviMux(iface
);
811 return IBaseFilter_Release(&This
->filter
.IBaseFilter_iface
);
814 static HRESULT WINAPI
ConfigAviMux_SetMasterStream(IConfigAviMux
*iface
, LONG iStream
)
816 AviMux
*This
= impl_from_IConfigAviMux(iface
);
817 FIXME("(%p)->(%d)\n", This
, iStream
);
821 static HRESULT WINAPI
ConfigAviMux_GetMasterStream(IConfigAviMux
*iface
, LONG
*pStream
)
823 AviMux
*This
= impl_from_IConfigAviMux(iface
);
824 FIXME("(%p)->(%p)\n", This
, pStream
);
828 static HRESULT WINAPI
ConfigAviMux_SetOutputCompatibilityIndex(
829 IConfigAviMux
*iface
, BOOL fOldIndex
)
831 AviMux
*This
= impl_from_IConfigAviMux(iface
);
832 FIXME("(%p)->(%x)\n", This
, fOldIndex
);
836 static HRESULT WINAPI
ConfigAviMux_GetOutputCompatibilityIndex(
837 IConfigAviMux
*iface
, BOOL
*pfOldIndex
)
839 AviMux
*This
= impl_from_IConfigAviMux(iface
);
840 FIXME("(%p)->(%p)\n", This
, pfOldIndex
);
844 static const IConfigAviMuxVtbl ConfigAviMuxVtbl
= {
845 ConfigAviMux_QueryInterface
,
847 ConfigAviMux_Release
,
848 ConfigAviMux_SetMasterStream
,
849 ConfigAviMux_GetMasterStream
,
850 ConfigAviMux_SetOutputCompatibilityIndex
,
851 ConfigAviMux_GetOutputCompatibilityIndex
854 static inline AviMux
* impl_from_IConfigInterleaving(IConfigInterleaving
*iface
)
856 return CONTAINING_RECORD(iface
, AviMux
, IConfigInterleaving_iface
);
859 static HRESULT WINAPI
ConfigInterleaving_QueryInterface(
860 IConfigInterleaving
*iface
, REFIID riid
, void **ppv
)
862 AviMux
*This
= impl_from_IConfigInterleaving(iface
);
863 return IBaseFilter_QueryInterface(&This
->filter
.IBaseFilter_iface
, riid
, ppv
);
866 static ULONG WINAPI
ConfigInterleaving_AddRef(IConfigInterleaving
*iface
)
868 AviMux
*This
= impl_from_IConfigInterleaving(iface
);
869 return IBaseFilter_AddRef(&This
->filter
.IBaseFilter_iface
);
872 static ULONG WINAPI
ConfigInterleaving_Release(IConfigInterleaving
*iface
)
874 AviMux
*This
= impl_from_IConfigInterleaving(iface
);
875 return IBaseFilter_Release(&This
->filter
.IBaseFilter_iface
);
878 static HRESULT WINAPI
ConfigInterleaving_put_Mode(
879 IConfigInterleaving
*iface
, InterleavingMode mode
)
881 AviMux
*This
= impl_from_IConfigInterleaving(iface
);
883 TRACE("(%p)->(%d)\n", This
, mode
);
885 if(mode
>INTERLEAVE_NONE_BUFFERED
)
888 if(This
->mode
!= mode
) {
889 if(This
->out
->pin
.pin
.pConnectedTo
) {
890 HRESULT hr
= IFilterGraph_Reconnect(This
->filter
.filterInfo
.pGraph
,
891 &This
->out
->pin
.pin
.IPin_iface
);
902 static HRESULT WINAPI
ConfigInterleaving_get_Mode(
903 IConfigInterleaving
*iface
, InterleavingMode
*pMode
)
905 AviMux
*This
= impl_from_IConfigInterleaving(iface
);
906 FIXME("(%p)->(%p)\n", This
, pMode
);
910 static HRESULT WINAPI
ConfigInterleaving_put_Interleaving(IConfigInterleaving
*iface
,
911 const REFERENCE_TIME
*prtInterleave
, const REFERENCE_TIME
*prtPreroll
)
913 AviMux
*This
= impl_from_IConfigInterleaving(iface
);
915 TRACE("(%p)->(%p %p)\n", This
, prtInterleave
, prtPreroll
);
918 This
->interleave
= *prtInterleave
;
920 This
->preroll
= *prtPreroll
;
924 static HRESULT WINAPI
ConfigInterleaving_get_Interleaving(IConfigInterleaving
*iface
,
925 REFERENCE_TIME
*prtInterleave
, REFERENCE_TIME
*prtPreroll
)
927 AviMux
*This
= impl_from_IConfigInterleaving(iface
);
928 FIXME("(%p)->(%p %p)\n", This
, prtInterleave
, prtPreroll
);
932 static const IConfigInterleavingVtbl ConfigInterleavingVtbl
= {
933 ConfigInterleaving_QueryInterface
,
934 ConfigInterleaving_AddRef
,
935 ConfigInterleaving_Release
,
936 ConfigInterleaving_put_Mode
,
937 ConfigInterleaving_get_Mode
,
938 ConfigInterleaving_put_Interleaving
,
939 ConfigInterleaving_get_Interleaving
942 static inline AviMux
* impl_from_IMediaSeeking(IMediaSeeking
*iface
)
944 return CONTAINING_RECORD(iface
, AviMux
, IMediaSeeking_iface
);
947 static HRESULT WINAPI
MediaSeeking_QueryInterface(
948 IMediaSeeking
*iface
, REFIID riid
, void **ppv
)
950 AviMux
*This
= impl_from_IMediaSeeking(iface
);
951 return IBaseFilter_QueryInterface(&This
->filter
.IBaseFilter_iface
, riid
, ppv
);
954 static ULONG WINAPI
MediaSeeking_AddRef(IMediaSeeking
*iface
)
956 AviMux
*This
= impl_from_IMediaSeeking(iface
);
957 return IBaseFilter_AddRef(&This
->filter
.IBaseFilter_iface
);
960 static ULONG WINAPI
MediaSeeking_Release(IMediaSeeking
*iface
)
962 AviMux
*This
= impl_from_IMediaSeeking(iface
);
963 return IBaseFilter_Release(&This
->filter
.IBaseFilter_iface
);
966 static HRESULT WINAPI
MediaSeeking_GetCapabilities(
967 IMediaSeeking
*iface
, DWORD
*pCapabilities
)
969 AviMux
*This
= impl_from_IMediaSeeking(iface
);
970 FIXME("(%p)->(%p)\n", This
, pCapabilities
);
974 static HRESULT WINAPI
MediaSeeking_CheckCapabilities(
975 IMediaSeeking
*iface
, DWORD
*pCapabilities
)
977 AviMux
*This
= impl_from_IMediaSeeking(iface
);
978 FIXME("(%p)->(%p)\n", This
, pCapabilities
);
982 static HRESULT WINAPI
MediaSeeking_IsFormatSupported(
983 IMediaSeeking
*iface
, const GUID
*pFormat
)
985 AviMux
*This
= impl_from_IMediaSeeking(iface
);
986 FIXME("(%p)->(%s)\n", This
, debugstr_guid(pFormat
));
990 static HRESULT WINAPI
MediaSeeking_QueryPreferredFormat(
991 IMediaSeeking
*iface
, GUID
*pFormat
)
993 AviMux
*This
= impl_from_IMediaSeeking(iface
);
994 FIXME("(%p)->(%p)\n", This
, pFormat
);
998 static HRESULT WINAPI
MediaSeeking_GetTimeFormat(
999 IMediaSeeking
*iface
, GUID
*pFormat
)
1001 AviMux
*This
= impl_from_IMediaSeeking(iface
);
1002 FIXME("(%p)->(%p)\n", This
, pFormat
);
1006 static HRESULT WINAPI
MediaSeeking_IsUsingTimeFormat(
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_SetTimeFormat(
1015 IMediaSeeking
*iface
, const GUID
*pFormat
)
1017 AviMux
*This
= impl_from_IMediaSeeking(iface
);
1018 FIXME("(%p)->(%s)\n", This
, debugstr_guid(pFormat
));
1022 static HRESULT WINAPI
MediaSeeking_GetDuration(
1023 IMediaSeeking
*iface
, LONGLONG
*pDuration
)
1025 AviMux
*This
= impl_from_IMediaSeeking(iface
);
1026 FIXME("(%p)->(%p)\n", This
, pDuration
);
1030 static HRESULT WINAPI
MediaSeeking_GetStopPosition(
1031 IMediaSeeking
*iface
, LONGLONG
*pStop
)
1033 AviMux
*This
= impl_from_IMediaSeeking(iface
);
1034 FIXME("(%p)->(%p)\n", This
, pStop
);
1038 static HRESULT WINAPI
MediaSeeking_GetCurrentPosition(
1039 IMediaSeeking
*iface
, LONGLONG
*pCurrent
)
1041 AviMux
*This
= impl_from_IMediaSeeking(iface
);
1042 FIXME("(%p)->(%p)\n", This
, pCurrent
);
1046 static HRESULT WINAPI
MediaSeeking_ConvertTimeFormat(IMediaSeeking
*iface
, LONGLONG
*pTarget
,
1047 const GUID
*pTargetFormat
, LONGLONG Source
, const GUID
*pSourceFormat
)
1049 AviMux
*This
= impl_from_IMediaSeeking(iface
);
1050 FIXME("(%p)->(%p %s %s %s)\n", This
, pTarget
, debugstr_guid(pTargetFormat
),
1051 wine_dbgstr_longlong(Source
), debugstr_guid(pSourceFormat
));
1055 static HRESULT WINAPI
MediaSeeking_SetPositions(IMediaSeeking
*iface
, LONGLONG
*pCurrent
,
1056 DWORD dwCurrentFlags
, LONGLONG
*pStop
, DWORD dwStopFlags
)
1058 AviMux
*This
= impl_from_IMediaSeeking(iface
);
1059 FIXME("(%p)->(%p %x %p %x)\n", This
, pCurrent
, dwCurrentFlags
, pStop
, dwStopFlags
);
1063 static HRESULT WINAPI
MediaSeeking_GetPositions(IMediaSeeking
*iface
,
1064 LONGLONG
*pCurrent
, LONGLONG
*pStop
)
1066 AviMux
*This
= impl_from_IMediaSeeking(iface
);
1067 FIXME("(%p)->(%p %p)\n", This
, pCurrent
, pStop
);
1071 static HRESULT WINAPI
MediaSeeking_GetAvailable(IMediaSeeking
*iface
,
1072 LONGLONG
*pEarliest
, LONGLONG
*pLatest
)
1074 AviMux
*This
= impl_from_IMediaSeeking(iface
);
1075 FIXME("(%p)->(%p %p)\n", This
, pEarliest
, pLatest
);
1079 static HRESULT WINAPI
MediaSeeking_SetRate(IMediaSeeking
*iface
, double dRate
)
1081 AviMux
*This
= impl_from_IMediaSeeking(iface
);
1082 FIXME("(%p)->(%lf)\n", This
, dRate
);
1086 static HRESULT WINAPI
MediaSeeking_GetRate(IMediaSeeking
*iface
, double *pdRate
)
1088 AviMux
*This
= impl_from_IMediaSeeking(iface
);
1089 FIXME("(%p)->(%p)\n", This
, pdRate
);
1093 static HRESULT WINAPI
MediaSeeking_GetPreroll(IMediaSeeking
*iface
, LONGLONG
*pllPreroll
)
1095 AviMux
*This
= impl_from_IMediaSeeking(iface
);
1096 FIXME("(%p)->(%p)\n", This
, pllPreroll
);
1100 static const IMediaSeekingVtbl MediaSeekingVtbl
= {
1101 MediaSeeking_QueryInterface
,
1102 MediaSeeking_AddRef
,
1103 MediaSeeking_Release
,
1104 MediaSeeking_GetCapabilities
,
1105 MediaSeeking_CheckCapabilities
,
1106 MediaSeeking_IsFormatSupported
,
1107 MediaSeeking_QueryPreferredFormat
,
1108 MediaSeeking_GetTimeFormat
,
1109 MediaSeeking_IsUsingTimeFormat
,
1110 MediaSeeking_SetTimeFormat
,
1111 MediaSeeking_GetDuration
,
1112 MediaSeeking_GetStopPosition
,
1113 MediaSeeking_GetCurrentPosition
,
1114 MediaSeeking_ConvertTimeFormat
,
1115 MediaSeeking_SetPositions
,
1116 MediaSeeking_GetPositions
,
1117 MediaSeeking_GetAvailable
,
1118 MediaSeeking_SetRate
,
1119 MediaSeeking_GetRate
,
1120 MediaSeeking_GetPreroll
1123 static inline AviMux
* impl_from_IPersistMediaPropertyBag(IPersistMediaPropertyBag
*iface
)
1125 return CONTAINING_RECORD(iface
, AviMux
, IPersistMediaPropertyBag_iface
);
1128 static HRESULT WINAPI
PersistMediaPropertyBag_QueryInterface(
1129 IPersistMediaPropertyBag
*iface
, REFIID riid
, void **ppv
)
1131 AviMux
*This
= impl_from_IPersistMediaPropertyBag(iface
);
1132 return IBaseFilter_QueryInterface(&This
->filter
.IBaseFilter_iface
, riid
, ppv
);
1135 static ULONG WINAPI
PersistMediaPropertyBag_AddRef(IPersistMediaPropertyBag
*iface
)
1137 AviMux
*This
= impl_from_IPersistMediaPropertyBag(iface
);
1138 return IBaseFilter_AddRef(&This
->filter
.IBaseFilter_iface
);
1141 static ULONG WINAPI
PersistMediaPropertyBag_Release(IPersistMediaPropertyBag
*iface
)
1143 AviMux
*This
= impl_from_IPersistMediaPropertyBag(iface
);
1144 return IBaseFilter_Release(&This
->filter
.IBaseFilter_iface
);
1147 static HRESULT WINAPI
PersistMediaPropertyBag_GetClassID(
1148 IPersistMediaPropertyBag
*iface
, CLSID
*pClassID
)
1150 AviMux
*This
= impl_from_IPersistMediaPropertyBag(iface
);
1151 return IBaseFilter_GetClassID(&This
->filter
.IBaseFilter_iface
, pClassID
);
1154 static HRESULT WINAPI
PersistMediaPropertyBag_InitNew(IPersistMediaPropertyBag
*iface
)
1156 AviMux
*This
= impl_from_IPersistMediaPropertyBag(iface
);
1157 FIXME("(%p)->()\n", This
);
1161 static HRESULT WINAPI
PersistMediaPropertyBag_Load(IPersistMediaPropertyBag
*iface
,
1162 IMediaPropertyBag
*pPropBag
, IErrorLog
*pErrorLog
)
1164 AviMux
*This
= impl_from_IPersistMediaPropertyBag(iface
);
1165 FIXME("(%p)->()\n", This
);
1169 static HRESULT WINAPI
PersistMediaPropertyBag_Save(IPersistMediaPropertyBag
*iface
,
1170 IMediaPropertyBag
*pPropBag
, BOOL fClearDirty
, BOOL fSaveAllProperties
)
1172 AviMux
*This
= impl_from_IPersistMediaPropertyBag(iface
);
1173 FIXME("(%p)->()\n", This
);
1177 static const IPersistMediaPropertyBagVtbl PersistMediaPropertyBagVtbl
= {
1178 PersistMediaPropertyBag_QueryInterface
,
1179 PersistMediaPropertyBag_AddRef
,
1180 PersistMediaPropertyBag_Release
,
1181 PersistMediaPropertyBag_GetClassID
,
1182 PersistMediaPropertyBag_InitNew
,
1183 PersistMediaPropertyBag_Load
,
1184 PersistMediaPropertyBag_Save
1187 static inline AviMux
* impl_from_ISpecifyPropertyPages(ISpecifyPropertyPages
*iface
)
1189 return CONTAINING_RECORD(iface
, AviMux
, ISpecifyPropertyPages_iface
);
1192 static HRESULT WINAPI
SpecifyPropertyPages_QueryInterface(
1193 ISpecifyPropertyPages
*iface
, REFIID riid
, void **ppv
)
1195 AviMux
*This
= impl_from_ISpecifyPropertyPages(iface
);
1196 return IBaseFilter_QueryInterface(&This
->filter
.IBaseFilter_iface
, riid
, ppv
);
1199 static ULONG WINAPI
SpecifyPropertyPages_AddRef(ISpecifyPropertyPages
*iface
)
1201 AviMux
*This
= impl_from_ISpecifyPropertyPages(iface
);
1202 return IBaseFilter_AddRef(&This
->filter
.IBaseFilter_iface
);
1205 static ULONG WINAPI
SpecifyPropertyPages_Release(ISpecifyPropertyPages
*iface
)
1207 AviMux
*This
= impl_from_ISpecifyPropertyPages(iface
);
1208 return IBaseFilter_Release(&This
->filter
.IBaseFilter_iface
);
1211 static HRESULT WINAPI
SpecifyPropertyPages_GetPages(
1212 ISpecifyPropertyPages
*iface
, CAUUID
*pPages
)
1214 AviMux
*This
= impl_from_ISpecifyPropertyPages(iface
);
1215 FIXME("(%p)->(%p)\n", This
, pPages
);
1219 static const ISpecifyPropertyPagesVtbl SpecifyPropertyPagesVtbl
= {
1220 SpecifyPropertyPages_QueryInterface
,
1221 SpecifyPropertyPages_AddRef
,
1222 SpecifyPropertyPages_Release
,
1223 SpecifyPropertyPages_GetPages
1226 static HRESULT WINAPI
AviMuxOut_AttemptConnection(BasePin
*base
,
1227 IPin
*pReceivePin
, const AM_MEDIA_TYPE
*pmt
)
1232 TRACE("(%p)->(%p AM_MEDIA_TYPE(%p))\n", base
, pReceivePin
, pmt
);
1233 dump_AM_MEDIA_TYPE(pmt
);
1235 hr
= IPin_QueryDirection(pReceivePin
, &dir
);
1236 if(hr
==S_OK
&& dir
!=PINDIR_INPUT
)
1237 return VFW_E_INVALID_DIRECTION
;
1239 return BaseOutputPinImpl_AttemptConnection(base
, pReceivePin
, pmt
);
1242 static LONG WINAPI
AviMuxOut_GetMediaTypeVersion(BasePin
*base
)
1247 static HRESULT WINAPI
AviMuxOut_GetMediaType(BasePin
*base
, int iPosition
, AM_MEDIA_TYPE
*amt
)
1249 TRACE("(%p)->(%d %p)\n", base
, iPosition
, amt
);
1252 return E_INVALIDARG
;
1254 return VFW_S_NO_MORE_ITEMS
;
1256 amt
->majortype
= MEDIATYPE_Stream
;
1257 amt
->subtype
= MEDIASUBTYPE_Avi
;
1258 amt
->bFixedSizeSamples
= TRUE
;
1259 amt
->bTemporalCompression
= FALSE
;
1260 amt
->lSampleSize
= 1;
1261 amt
->formattype
= GUID_NULL
;
1264 amt
->pbFormat
= NULL
;
1268 static HRESULT WINAPI
AviMuxOut_DecideAllocator(BaseOutputPin
*base
,
1269 IMemInputPin
*pPin
, IMemAllocator
**pAlloc
)
1271 ALLOCATOR_PROPERTIES req
, actual
;
1274 TRACE("(%p)->(%p %p)\n", base
, pPin
, pAlloc
);
1276 hr
= BaseOutputPinImpl_InitAllocator(base
, pAlloc
);
1280 hr
= IMemInputPin_GetAllocatorRequirements(pPin
, &req
);
1287 hr
= IMemAllocator_SetProperties(*pAlloc
, &req
, &actual
);
1291 return IMemInputPin_NotifyAllocator(pPin
, *pAlloc
, TRUE
);
1294 static HRESULT WINAPI
AviMuxOut_BreakConnect(BaseOutputPin
*base
)
1296 FIXME("(%p)\n", base
);
1300 static const BaseOutputPinFuncTable AviMuxOut_BaseOutputFuncTable
= {
1303 AviMuxOut_AttemptConnection
,
1304 AviMuxOut_GetMediaTypeVersion
,
1305 AviMuxOut_GetMediaType
1308 AviMuxOut_DecideAllocator
,
1309 AviMuxOut_BreakConnect
1312 static inline AviMux
* impl_from_out_IPin(IPin
*iface
)
1314 BasePin
*bp
= CONTAINING_RECORD(iface
, BasePin
, IPin_iface
);
1315 IBaseFilter
*bf
= bp
->pinInfo
.pFilter
;
1317 return impl_from_IBaseFilter(bf
);
1320 static HRESULT WINAPI
AviMuxOut_QueryInterface(IPin
*iface
, REFIID riid
, void **ppv
)
1322 AviMux
*This
= impl_from_out_IPin(iface
);
1324 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), ppv
);
1326 if(IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IPin
))
1328 else if(IsEqualIID(riid
, &IID_IQualityControl
))
1329 *ppv
= &This
->out
->IQualityControl_iface
;
1331 FIXME("no interface for %s\n", debugstr_guid(riid
));
1333 return E_NOINTERFACE
;
1336 IUnknown_AddRef((IUnknown
*)*ppv
);
1340 static ULONG WINAPI
AviMuxOut_AddRef(IPin
*iface
)
1342 AviMux
*This
= impl_from_out_IPin(iface
);
1343 return IBaseFilter_AddRef(&This
->filter
.IBaseFilter_iface
);
1346 static ULONG WINAPI
AviMuxOut_Release(IPin
*iface
)
1348 AviMux
*This
= impl_from_out_IPin(iface
);
1349 return IBaseFilter_Release(&This
->filter
.IBaseFilter_iface
);
1352 static HRESULT WINAPI
AviMuxOut_Connect(IPin
*iface
,
1353 IPin
*pReceivePin
, const AM_MEDIA_TYPE
*pmt
)
1355 AviMux
*This
= impl_from_out_IPin(iface
);
1359 TRACE("(%p)->(%p AM_MEDIA_TYPE(%p))\n", This
, pReceivePin
, pmt
);
1360 dump_AM_MEDIA_TYPE(pmt
);
1362 hr
= BaseOutputPinImpl_Connect(iface
, pReceivePin
, pmt
);
1366 for(i
=0; i
<This
->input_pin_no
; i
++) {
1367 if(!This
->in
[i
]->pin
.pin
.pConnectedTo
)
1370 hr
= IFilterGraph_Reconnect(This
->filter
.filterInfo
.pGraph
, &This
->in
[i
]->pin
.pin
.IPin_iface
);
1372 BaseOutputPinImpl_Disconnect(iface
);
1378 IBaseFilter_AddRef(&This
->filter
.IBaseFilter_iface
);
1382 static HRESULT WINAPI
AviMuxOut_ReceiveConnection(IPin
*iface
,
1383 IPin
*pConnector
, const AM_MEDIA_TYPE
*pmt
)
1385 AviMux
*This
= impl_from_out_IPin(iface
);
1386 TRACE("(%p)->(%p AM_MEDIA_TYPE(%p)\n", This
, pConnector
, pmt
);
1387 dump_AM_MEDIA_TYPE(pmt
);
1388 return BaseOutputPinImpl_ReceiveConnection(iface
, pConnector
, pmt
);
1391 static HRESULT WINAPI
AviMuxOut_Disconnect(IPin
*iface
)
1393 AviMux
*This
= impl_from_out_IPin(iface
);
1396 TRACE("(%p)\n", This
);
1398 hr
= BaseOutputPinImpl_Disconnect(iface
);
1400 IBaseFilter_Release(&This
->filter
.IBaseFilter_iface
);
1404 static HRESULT WINAPI
AviMuxOut_ConnectedTo(IPin
*iface
, IPin
**pPin
)
1406 AviMux
*This
= impl_from_out_IPin(iface
);
1407 TRACE("(%p)->(%p)\n", This
, pPin
);
1408 return BasePinImpl_ConnectedTo(iface
, pPin
);
1411 static HRESULT WINAPI
AviMuxOut_ConnectionMediaType(IPin
*iface
, AM_MEDIA_TYPE
*pmt
)
1413 AviMux
*This
= impl_from_out_IPin(iface
);
1414 TRACE("(%p)->(%p)\n", This
, pmt
);
1415 return BasePinImpl_ConnectionMediaType(iface
, pmt
);
1418 static HRESULT WINAPI
AviMuxOut_QueryPinInfo(IPin
*iface
, PIN_INFO
*pInfo
)
1420 AviMux
*This
= impl_from_out_IPin(iface
);
1421 TRACE("(%p)->(%p)\n", This
, pInfo
);
1422 return BasePinImpl_QueryPinInfo(iface
, pInfo
);
1425 static HRESULT WINAPI
AviMuxOut_QueryDirection(IPin
*iface
, PIN_DIRECTION
*pPinDir
)
1427 AviMux
*This
= impl_from_out_IPin(iface
);
1428 TRACE("(%p)->(%p)\n", This
, pPinDir
);
1429 return BasePinImpl_QueryDirection(iface
, pPinDir
);
1432 static HRESULT WINAPI
AviMuxOut_QueryId(IPin
*iface
, LPWSTR
*Id
)
1434 AviMux
*This
= impl_from_out_IPin(iface
);
1435 TRACE("(%p)->(%p)\n", This
, Id
);
1436 return BasePinImpl_QueryId(iface
, Id
);
1439 static HRESULT WINAPI
AviMuxOut_QueryAccept(IPin
*iface
, const AM_MEDIA_TYPE
*pmt
)
1441 AviMux
*This
= impl_from_out_IPin(iface
);
1442 TRACE("(%p)->(AM_MEDIA_TYPE(%p))\n", This
, pmt
);
1443 dump_AM_MEDIA_TYPE(pmt
);
1444 return BasePinImpl_QueryAccept(iface
, pmt
);
1447 static HRESULT WINAPI
AviMuxOut_EnumMediaTypes(IPin
*iface
, IEnumMediaTypes
**ppEnum
)
1449 AviMux
*This
= impl_from_out_IPin(iface
);
1450 TRACE("(%p)->(%p)\n", This
, ppEnum
);
1451 return BasePinImpl_EnumMediaTypes(iface
, ppEnum
);
1454 static HRESULT WINAPI
AviMuxOut_QueryInternalConnections(
1455 IPin
*iface
, IPin
**apPin
, ULONG
*nPin
)
1457 AviMux
*This
= impl_from_out_IPin(iface
);
1458 FIXME("(%p)->(%p %p)\n", This
, apPin
, nPin
);
1462 static HRESULT WINAPI
AviMuxOut_EndOfStream(IPin
*iface
)
1464 AviMux
*This
= impl_from_out_IPin(iface
);
1465 TRACE("(%p)\n", This
);
1466 return BaseOutputPinImpl_EndOfStream(iface
);
1469 static HRESULT WINAPI
AviMuxOut_BeginFlush(IPin
*iface
)
1471 AviMux
*This
= impl_from_out_IPin(iface
);
1472 TRACE("(%p)\n", This
);
1473 return BaseOutputPinImpl_BeginFlush(iface
);
1476 static HRESULT WINAPI
AviMuxOut_EndFlush(IPin
*iface
)
1478 AviMux
*This
= impl_from_out_IPin(iface
);
1479 TRACE("(%p)\n", This
);
1480 return BaseOutputPinImpl_EndFlush(iface
);
1483 static HRESULT WINAPI
AviMuxOut_NewSegment(IPin
*iface
, REFERENCE_TIME tStart
,
1484 REFERENCE_TIME tStop
, double dRate
)
1486 AviMux
*This
= impl_from_out_IPin(iface
);
1487 TRACE("(%p)->(0x%x%08x 0x%x%08x %lf)\n", This
, (ULONG
)(tStart
>> 32),
1488 (ULONG
)tStart
, (ULONG
)(tStop
>> 32), (ULONG
)tStop
, dRate
);
1489 return BasePinImpl_NewSegment(iface
, tStart
, tStop
, dRate
);
1492 static const IPinVtbl AviMuxOut_PinVtbl
= {
1493 AviMuxOut_QueryInterface
,
1497 AviMuxOut_ReceiveConnection
,
1498 AviMuxOut_Disconnect
,
1499 AviMuxOut_ConnectedTo
,
1500 AviMuxOut_ConnectionMediaType
,
1501 AviMuxOut_QueryPinInfo
,
1502 AviMuxOut_QueryDirection
,
1504 AviMuxOut_QueryAccept
,
1505 AviMuxOut_EnumMediaTypes
,
1506 AviMuxOut_QueryInternalConnections
,
1507 AviMuxOut_EndOfStream
,
1508 AviMuxOut_BeginFlush
,
1510 AviMuxOut_NewSegment
1513 static inline AviMux
* impl_from_out_IQualityControl(IQualityControl
*iface
)
1515 AviMuxOut
*amo
= CONTAINING_RECORD(iface
, AviMuxOut
, IQualityControl_iface
);
1516 return impl_from_IBaseFilter(amo
->pin
.pin
.pinInfo
.pFilter
);
1519 static HRESULT WINAPI
AviMuxOut_QualityControl_QueryInterface(
1520 IQualityControl
*iface
, REFIID riid
, void **ppv
)
1522 AviMux
*This
= impl_from_out_IQualityControl(iface
);
1523 return IPin_QueryInterface(&This
->out
->pin
.pin
.IPin_iface
, riid
, ppv
);
1526 static ULONG WINAPI
AviMuxOut_QualityControl_AddRef(IQualityControl
*iface
)
1528 AviMux
*This
= impl_from_out_IQualityControl(iface
);
1529 return IBaseFilter_AddRef(&This
->filter
.IBaseFilter_iface
);
1532 static ULONG WINAPI
AviMuxOut_QualityControl_Release(IQualityControl
*iface
)
1534 AviMux
*This
= impl_from_out_IQualityControl(iface
);
1535 return IBaseFilter_Release(&This
->filter
.IBaseFilter_iface
);
1538 static HRESULT WINAPI
AviMuxOut_QualityControl_Notify(IQualityControl
*iface
,
1539 IBaseFilter
*pSelf
, Quality q
)
1541 AviMux
*This
= impl_from_out_IQualityControl(iface
);
1542 FIXME("(%p)->(%p { 0x%x %u %s %s })\n", This
, pSelf
,
1543 q
.Type
, q
.Proportion
,
1544 wine_dbgstr_longlong(q
.Late
),
1545 wine_dbgstr_longlong(q
.TimeStamp
));
1549 static HRESULT WINAPI
AviMuxOut_QualityControl_SetSink(
1550 IQualityControl
*iface
, IQualityControl
*piqc
)
1552 AviMux
*This
= impl_from_out_IQualityControl(iface
);
1553 FIXME("(%p)->(%p)\n", This
, piqc
);
1557 static const IQualityControlVtbl AviMuxOut_QualityControlVtbl
= {
1558 AviMuxOut_QualityControl_QueryInterface
,
1559 AviMuxOut_QualityControl_AddRef
,
1560 AviMuxOut_QualityControl_Release
,
1561 AviMuxOut_QualityControl_Notify
,
1562 AviMuxOut_QualityControl_SetSink
1565 static HRESULT WINAPI
AviMuxIn_CheckMediaType(BasePin
*base
, const AM_MEDIA_TYPE
*pmt
)
1567 TRACE("(%p:%s)->(AM_MEDIA_TYPE(%p))\n", base
, debugstr_w(base
->pinInfo
.achName
), pmt
);
1568 dump_AM_MEDIA_TYPE(pmt
);
1570 if(IsEqualIID(&pmt
->majortype
, &MEDIATYPE_Audio
) &&
1571 IsEqualIID(&pmt
->formattype
, &FORMAT_WaveFormatEx
))
1573 if(IsEqualIID(&pmt
->majortype
, &MEDIATYPE_Interleaved
) &&
1574 IsEqualIID(&pmt
->formattype
, &FORMAT_DvInfo
))
1576 if(IsEqualIID(&pmt
->majortype
, &MEDIATYPE_Video
) &&
1577 (IsEqualIID(&pmt
->formattype
, &FORMAT_VideoInfo
) ||
1578 IsEqualIID(&pmt
->formattype
, &FORMAT_DvInfo
)))
1583 static LONG WINAPI
AviMuxIn_GetMediaTypeVersion(BasePin
*base
)
1588 static HRESULT WINAPI
AviMuxIn_GetMediaType(BasePin
*base
, int iPosition
, AM_MEDIA_TYPE
*amt
)
1593 static HRESULT WINAPI
AviMuxIn_Receive(BaseInputPin
*base
, IMediaSample
*pSample
)
1595 AviMuxIn
*avimuxin
= CONTAINING_RECORD(base
, AviMuxIn
, pin
);
1596 AviMux
*avimux
= impl_from_IBaseFilter(base
->pin
.pinInfo
.pFilter
);
1597 REFERENCE_TIME start
, stop
;
1598 IMediaSample
*sample
;
1602 DWORD max_size
, size
;
1606 TRACE("(%p:%s)->(%p)\n", base
, debugstr_w(base
->pin
.pinInfo
.achName
), pSample
);
1608 hr
= IMediaSample_QueryInterface(pSample
, &IID_IMediaSample2
, (void**)&ms2
);
1610 AM_SAMPLE2_PROPERTIES props
;
1612 memset(&props
, 0, sizeof(props
));
1613 hr
= IMediaSample2_GetProperties(ms2
, sizeof(props
), (BYTE
*)&props
);
1614 IMediaSample2_Release(ms2
);
1618 flags
= props
.dwSampleFlags
;
1619 frame
= props
.pbBuffer
;
1620 size
= props
.lActual
;
1622 flags
= IMediaSample_IsSyncPoint(pSample
) == S_OK
? AM_SAMPLE_SPLICEPOINT
: 0;
1623 hr
= IMediaSample_GetPointer(pSample
, &frame
);
1626 size
= IMediaSample_GetActualDataLength(pSample
);
1629 if(!avimuxin
->pin
.pin
.mtCurrent
.bTemporalCompression
)
1630 flags
|= AM_SAMPLE_SPLICEPOINT
;
1632 hr
= IMediaSample_GetTime(pSample
, &start
, &stop
);
1636 if(avimuxin
->stop
>stop
)
1637 return VFW_E_START_TIME_AFTER_END
;
1639 if(avimux
->start
== -1)
1640 avimux
->start
= start
;
1641 if(avimux
->stop
< stop
)
1642 avimux
->stop
= stop
;
1644 if(avimux
->avih
.dwSuggestedBufferSize
< ALIGN(size
)+sizeof(RIFFCHUNK
))
1645 avimux
->avih
.dwSuggestedBufferSize
= ALIGN(size
) + sizeof(RIFFCHUNK
);
1646 if(avimuxin
->strh
.dwSuggestedBufferSize
< ALIGN(size
)+sizeof(RIFFCHUNK
))
1647 avimuxin
->strh
.dwSuggestedBufferSize
= ALIGN(size
) + sizeof(RIFFCHUNK
);
1650 if(avimuxin
->stop
!=-1 && start
> avimuxin
->stop
) {
1651 frames_no
+= (double)(start
- avimuxin
->stop
) / 10000000
1652 * avimuxin
->strh
.dwRate
/ avimuxin
->strh
.dwScale
+ 0.5;
1654 avimuxin
->stop
= stop
;
1656 while(--frames_no
) {
1657 /* TODO: store all control frames in one buffer */
1658 hr
= IMemAllocator_GetBuffer(avimuxin
->samples_allocator
, &sample
, NULL
, NULL
, 0);
1661 hr
= IMediaSample_SetActualDataLength(sample
, 0);
1663 hr
= IMediaSample_SetDiscontinuity(sample
, TRUE
);
1665 hr
= IMediaSample_SetSyncPoint(sample
, FALSE
);
1667 hr
= queue_sample(avimux
, avimuxin
, sample
);
1668 IMediaSample_Release(sample
);
1673 hr
= IMemAllocator_GetBuffer(avimuxin
->samples_allocator
, &sample
, NULL
, NULL
, 0);
1676 max_size
= IMediaSample_GetSize(sample
);
1679 hr
= IMediaSample_SetActualDataLength(sample
, size
);
1681 hr
= IMediaSample_SetDiscontinuity(sample
, FALSE
);
1683 hr
= IMediaSample_SetSyncPoint(sample
, flags
& AM_SAMPLE_SPLICEPOINT
);
1684 /* TODO: avoid unnecessary copying */
1686 hr
= IMediaSample_GetPointer(sample
, &buf
);
1688 memcpy(buf
, frame
, size
);
1689 hr
= queue_sample(avimux
, avimuxin
, sample
);
1691 IMediaSample_Release(sample
);
1696 static const BaseInputPinFuncTable AviMuxIn_BaseInputFuncTable
= {
1698 AviMuxIn_CheckMediaType
,
1700 AviMuxIn_GetMediaTypeVersion
,
1701 AviMuxIn_GetMediaType
1706 static inline AviMux
* impl_from_in_IPin(IPin
*iface
)
1708 BasePin
*bp
= CONTAINING_RECORD(iface
, BasePin
, IPin_iface
);
1709 IBaseFilter
*bf
= bp
->pinInfo
.pFilter
;
1711 return impl_from_IBaseFilter(bf
);
1714 static inline AviMuxIn
* AviMuxIn_from_IPin(IPin
*iface
)
1716 BasePin
*bp
= CONTAINING_RECORD(iface
, BasePin
, IPin_iface
);
1717 BaseInputPin
*bip
= CONTAINING_RECORD(bp
, BaseInputPin
, pin
);
1718 return CONTAINING_RECORD(bip
, AviMuxIn
, pin
);
1721 static HRESULT WINAPI
AviMuxIn_QueryInterface(IPin
*iface
, REFIID riid
, void **ppv
)
1723 AviMux
*This
= impl_from_in_IPin(iface
);
1724 AviMuxIn
*avimuxin
= AviMuxIn_from_IPin(iface
);
1726 TRACE("(%p:%s)->(%s %p)\n", This
, debugstr_w(avimuxin
->pin
.pin
.pinInfo
.achName
),
1727 debugstr_guid(riid
), ppv
);
1729 if(IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IPin
))
1730 *ppv
= &avimuxin
->pin
.pin
.IPin_iface
;
1731 else if(IsEqualIID(riid
, &IID_IAMStreamControl
))
1732 *ppv
= &avimuxin
->IAMStreamControl_iface
;
1733 else if(IsEqualIID(riid
, &IID_IMemInputPin
))
1734 *ppv
= &avimuxin
->pin
.IMemInputPin_iface
;
1735 else if(IsEqualIID(riid
, &IID_IPropertyBag
))
1736 *ppv
= &avimuxin
->IPropertyBag_iface
;
1737 else if(IsEqualIID(riid
, &IID_IQualityControl
))
1738 *ppv
= &avimuxin
->IQualityControl_iface
;
1740 FIXME("no interface for %s\n", debugstr_guid(riid
));
1742 return E_NOINTERFACE
;
1745 IUnknown_AddRef((IUnknown
*)*ppv
);
1749 static ULONG WINAPI
AviMuxIn_AddRef(IPin
*iface
)
1751 AviMux
*This
= impl_from_in_IPin(iface
);
1752 return IBaseFilter_AddRef(&This
->filter
.IBaseFilter_iface
);
1755 static ULONG WINAPI
AviMuxIn_Release(IPin
*iface
)
1757 AviMux
*This
= impl_from_in_IPin(iface
);
1758 return IBaseFilter_Release(&This
->filter
.IBaseFilter_iface
);
1761 static HRESULT WINAPI
AviMuxIn_Connect(IPin
*iface
,
1762 IPin
*pReceivePin
, const AM_MEDIA_TYPE
*pmt
)
1764 AviMux
*This
= impl_from_in_IPin(iface
);
1765 AviMuxIn
*avimuxin
= AviMuxIn_from_IPin(iface
);
1766 TRACE("(%p:%s)->(%p AM_MEDIA_TYPE(%p))\n", This
,
1767 debugstr_w(avimuxin
->pin
.pin
.pinInfo
.achName
), pReceivePin
, pmt
);
1768 dump_AM_MEDIA_TYPE(pmt
);
1769 return BaseInputPinImpl_Connect(iface
, pReceivePin
, pmt
);
1772 static HRESULT WINAPI
AviMuxIn_ReceiveConnection(IPin
*iface
,
1773 IPin
*pConnector
, const AM_MEDIA_TYPE
*pmt
)
1775 AviMux
*This
= impl_from_in_IPin(iface
);
1776 AviMuxIn
*avimuxin
= AviMuxIn_from_IPin(iface
);
1779 TRACE("(%p:%s)->(%p AM_MEDIA_TYPE(%p))\n", This
,
1780 debugstr_w(avimuxin
->pin
.pin
.pinInfo
.achName
), pConnector
, pmt
);
1781 dump_AM_MEDIA_TYPE(pmt
);
1786 hr
= BaseInputPinImpl_ReceiveConnection(iface
, pConnector
, pmt
);
1790 if(IsEqualIID(&pmt
->majortype
, &MEDIATYPE_Video
) &&
1791 IsEqualIID(&pmt
->formattype
, &FORMAT_VideoInfo
)) {
1792 ALLOCATOR_PROPERTIES req
, act
;
1793 VIDEOINFOHEADER
*vih
;
1796 vih
= (VIDEOINFOHEADER
*)pmt
->pbFormat
;
1797 avimuxin
->strh
.fcc
= ckidSTREAMHEADER
;
1798 avimuxin
->strh
.cb
= sizeof(AVISTREAMHEADER
) - FIELD_OFFSET(AVISTREAMHEADER
, fccType
);
1799 avimuxin
->strh
.fccType
= streamtypeVIDEO
;
1800 /* FIXME: fccHandler should be set differently */
1801 avimuxin
->strh
.fccHandler
= vih
->bmiHeader
.biCompression
?
1802 vih
->bmiHeader
.biCompression
: FCC('D','I','B',' ');
1803 avimuxin
->avg_time_per_frame
= vih
->AvgTimePerFrame
;
1804 avimuxin
->stop
= -1;
1807 req
.cbBuffer
= vih
->bmiHeader
.biSizeImage
;
1809 req
.cbPrefix
= sizeof(void*);
1810 hr
= IMemAllocator_SetProperties(avimuxin
->samples_allocator
, &req
, &act
);
1812 hr
= IMemAllocator_Commit(avimuxin
->samples_allocator
);
1814 BasePinImpl_Disconnect(iface
);
1818 size
= pmt
->cbFormat
- FIELD_OFFSET(VIDEOINFOHEADER
, bmiHeader
);
1819 avimuxin
->strf
= CoTaskMemAlloc(sizeof(RIFFCHUNK
) + ALIGN(FIELD_OFFSET(BITMAPINFO
, bmiColors
[vih
->bmiHeader
.biClrUsed
])));
1820 avimuxin
->strf
->fcc
= ckidSTREAMFORMAT
;
1821 avimuxin
->strf
->cb
= FIELD_OFFSET(BITMAPINFO
, bmiColors
[vih
->bmiHeader
.biClrUsed
]);
1822 if(size
> avimuxin
->strf
->cb
)
1823 size
= avimuxin
->strf
->cb
;
1824 memcpy(avimuxin
->strf
->data
, &vih
->bmiHeader
, size
);
1826 FIXME("format not supported: %s %s\n", debugstr_guid(&pmt
->majortype
),
1827 debugstr_guid(&pmt
->formattype
));
1831 return create_input_pin(This
);
1834 static HRESULT WINAPI
AviMuxIn_Disconnect(IPin
*iface
)
1836 AviMux
*This
= impl_from_in_IPin(iface
);
1837 AviMuxIn
*avimuxin
= AviMuxIn_from_IPin(iface
);
1838 IMediaSample
**prev
, *cur
;
1841 TRACE("(%p:%s)\n", This
, debugstr_w(avimuxin
->pin
.pin
.pinInfo
.achName
));
1843 hr
= BasePinImpl_Disconnect(iface
);
1847 IMemAllocator_Decommit(avimuxin
->samples_allocator
);
1848 while(avimuxin
->samples_head
) {
1849 cur
= avimuxin
->samples_head
;
1850 hr
= IMediaSample_GetPointer(cur
, (BYTE
**)&prev
);
1855 cur
= avimuxin
->samples_head
;
1856 avimuxin
->samples_head
= *prev
;
1857 IMediaSample_Release(cur
);
1859 if(cur
== avimuxin
->samples_head
)
1860 avimuxin
->samples_head
= NULL
;
1862 CoTaskMemFree(avimuxin
->strf
);
1863 avimuxin
->strf
= NULL
;
1867 static HRESULT WINAPI
AviMuxIn_ConnectedTo(IPin
*iface
, IPin
**pPin
)
1869 AviMux
*This
= impl_from_in_IPin(iface
);
1870 AviMuxIn
*avimuxin
= AviMuxIn_from_IPin(iface
);
1871 TRACE("(%p:%s)->(%p)\n", This
, debugstr_w(avimuxin
->pin
.pin
.pinInfo
.achName
), pPin
);
1872 return BasePinImpl_ConnectedTo(iface
, pPin
);
1875 static HRESULT WINAPI
AviMuxIn_ConnectionMediaType(IPin
*iface
, AM_MEDIA_TYPE
*pmt
)
1877 AviMux
*This
= impl_from_in_IPin(iface
);
1878 AviMuxIn
*avimuxin
= AviMuxIn_from_IPin(iface
);
1879 TRACE("(%p:%s)->(%p)\n", This
, debugstr_w(avimuxin
->pin
.pin
.pinInfo
.achName
), pmt
);
1880 return BasePinImpl_ConnectionMediaType(iface
, pmt
);
1883 static HRESULT WINAPI
AviMuxIn_QueryPinInfo(IPin
*iface
, PIN_INFO
*pInfo
)
1885 AviMux
*This
= impl_from_in_IPin(iface
);
1886 AviMuxIn
*avimuxin
= AviMuxIn_from_IPin(iface
);
1887 TRACE("(%p:%s)->(%p)\n", This
, debugstr_w(avimuxin
->pin
.pin
.pinInfo
.achName
), pInfo
);
1888 return BasePinImpl_QueryPinInfo(iface
, pInfo
);
1891 static HRESULT WINAPI
AviMuxIn_QueryDirection(IPin
*iface
, PIN_DIRECTION
*pPinDir
)
1893 AviMux
*This
= impl_from_in_IPin(iface
);
1894 AviMuxIn
*avimuxin
= AviMuxIn_from_IPin(iface
);
1895 TRACE("(%p:%s)->(%p)\n", This
, debugstr_w(avimuxin
->pin
.pin
.pinInfo
.achName
), pPinDir
);
1896 return BasePinImpl_QueryDirection(iface
, pPinDir
);
1899 static HRESULT WINAPI
AviMuxIn_QueryId(IPin
*iface
, LPWSTR
*Id
)
1901 AviMux
*This
= impl_from_in_IPin(iface
);
1902 AviMuxIn
*avimuxin
= AviMuxIn_from_IPin(iface
);
1903 TRACE("(%p:%s)->(%p)\n", This
, debugstr_w(avimuxin
->pin
.pin
.pinInfo
.achName
), Id
);
1904 return BasePinImpl_QueryId(iface
, Id
);
1907 static HRESULT WINAPI
AviMuxIn_QueryAccept(IPin
*iface
, const AM_MEDIA_TYPE
*pmt
)
1909 AviMux
*This
= impl_from_in_IPin(iface
);
1910 AviMuxIn
*avimuxin
= AviMuxIn_from_IPin(iface
);
1911 TRACE("(%p:%s)->(AM_MEDIA_TYPE(%p))\n", This
,
1912 debugstr_w(avimuxin
->pin
.pin
.pinInfo
.achName
), pmt
);
1913 dump_AM_MEDIA_TYPE(pmt
);
1914 return BasePinImpl_QueryAccept(iface
, pmt
);
1917 static HRESULT WINAPI
AviMuxIn_EnumMediaTypes(IPin
*iface
, IEnumMediaTypes
**ppEnum
)
1919 AviMux
*This
= impl_from_in_IPin(iface
);
1920 AviMuxIn
*avimuxin
= AviMuxIn_from_IPin(iface
);
1921 TRACE("(%p:%s)->(%p)\n", This
, debugstr_w(avimuxin
->pin
.pin
.pinInfo
.achName
), ppEnum
);
1922 return BasePinImpl_EnumMediaTypes(iface
, ppEnum
);
1925 static HRESULT WINAPI
AviMuxIn_QueryInternalConnections(
1926 IPin
*iface
, IPin
**apPin
, ULONG
*nPin
)
1928 AviMux
*This
= impl_from_in_IPin(iface
);
1929 AviMuxIn
*avimuxin
= AviMuxIn_from_IPin(iface
);
1930 TRACE("(%p:%s)->(%p %p)\n", This
, debugstr_w(avimuxin
->pin
.pin
.pinInfo
.achName
), apPin
, nPin
);
1931 return BasePinImpl_QueryInternalConnections(iface
, apPin
, nPin
);
1934 static HRESULT WINAPI
AviMuxIn_EndOfStream(IPin
*iface
)
1936 AviMux
*This
= impl_from_in_IPin(iface
);
1937 AviMuxIn
*avimuxin
= AviMuxIn_from_IPin(iface
);
1938 TRACE("(%p:%s)\n", This
, debugstr_w(avimuxin
->pin
.pin
.pinInfo
.achName
));
1939 return BaseInputPinImpl_EndOfStream(iface
);
1942 static HRESULT WINAPI
AviMuxIn_BeginFlush(IPin
*iface
)
1944 AviMux
*This
= impl_from_in_IPin(iface
);
1945 AviMuxIn
*avimuxin
= AviMuxIn_from_IPin(iface
);
1946 TRACE("(%p:%s)\n", This
, debugstr_w(avimuxin
->pin
.pin
.pinInfo
.achName
));
1947 return BaseInputPinImpl_BeginFlush(iface
);
1950 static HRESULT WINAPI
AviMuxIn_EndFlush(IPin
*iface
)
1952 AviMux
*This
= impl_from_in_IPin(iface
);
1953 AviMuxIn
*avimuxin
= AviMuxIn_from_IPin(iface
);
1954 TRACE("(%p:%s)\n", This
, debugstr_w(avimuxin
->pin
.pin
.pinInfo
.achName
));
1955 return BaseInputPinImpl_EndFlush(iface
);
1958 static HRESULT WINAPI
AviMuxIn_NewSegment(IPin
*iface
, REFERENCE_TIME tStart
,
1959 REFERENCE_TIME tStop
, double dRate
)
1961 AviMux
*This
= impl_from_in_IPin(iface
);
1962 AviMuxIn
*avimuxin
= AviMuxIn_from_IPin(iface
);
1963 TRACE("(%p:%s)->(0x%x%08x 0x%x%08x %lf)\n", This
, debugstr_w(avimuxin
->pin
.pin
.pinInfo
.achName
),
1964 (ULONG
)(tStart
>> 32), (ULONG
)tStart
, (ULONG
)(tStop
>> 32), (ULONG
)tStop
, dRate
);
1965 return BasePinImpl_NewSegment(iface
, tStart
, tStop
, dRate
);
1968 static const IPinVtbl AviMuxIn_PinVtbl
= {
1969 AviMuxIn_QueryInterface
,
1973 AviMuxIn_ReceiveConnection
,
1974 AviMuxIn_Disconnect
,
1975 AviMuxIn_ConnectedTo
,
1976 AviMuxIn_ConnectionMediaType
,
1977 AviMuxIn_QueryPinInfo
,
1978 AviMuxIn_QueryDirection
,
1980 AviMuxIn_QueryAccept
,
1981 AviMuxIn_EnumMediaTypes
,
1982 AviMuxIn_QueryInternalConnections
,
1983 AviMuxIn_EndOfStream
,
1984 AviMuxIn_BeginFlush
,
1989 static inline AviMuxIn
* AviMuxIn_from_IAMStreamControl(IAMStreamControl
*iface
)
1991 return CONTAINING_RECORD(iface
, AviMuxIn
, IAMStreamControl_iface
);
1994 static HRESULT WINAPI
AviMuxIn_AMStreamControl_QueryInterface(
1995 IAMStreamControl
*iface
, REFIID riid
, void **ppv
)
1997 AviMuxIn
*avimuxin
= AviMuxIn_from_IAMStreamControl(iface
);
1998 return IPin_QueryInterface(&avimuxin
->pin
.pin
.IPin_iface
, riid
, ppv
);
2001 static ULONG WINAPI
AviMuxIn_AMStreamControl_AddRef(IAMStreamControl
*iface
)
2003 AviMuxIn
*avimuxin
= AviMuxIn_from_IAMStreamControl(iface
);
2004 AviMux
*This
= impl_from_in_IPin(&avimuxin
->pin
.pin
.IPin_iface
);
2005 return IBaseFilter_AddRef(&This
->filter
.IBaseFilter_iface
);
2008 static ULONG WINAPI
AviMuxIn_AMStreamControl_Release(IAMStreamControl
*iface
)
2010 AviMuxIn
*avimuxin
= AviMuxIn_from_IAMStreamControl(iface
);
2011 AviMux
*This
= impl_from_in_IPin(&avimuxin
->pin
.pin
.IPin_iface
);
2012 return IBaseFilter_Release(&This
->filter
.IBaseFilter_iface
);
2015 static HRESULT WINAPI
AviMuxIn_AMStreamControl_StartAt(IAMStreamControl
*iface
,
2016 const REFERENCE_TIME
*ptStart
, DWORD dwCookie
)
2018 AviMuxIn
*avimuxin
= AviMuxIn_from_IAMStreamControl(iface
);
2019 AviMux
*This
= impl_from_in_IPin(&avimuxin
->pin
.pin
.IPin_iface
);
2020 FIXME("(%p:%s)->(%p %x)\n", This
,
2021 debugstr_w(avimuxin
->pin
.pin
.pinInfo
.achName
), ptStart
, dwCookie
);
2025 static HRESULT WINAPI
AviMuxIn_AMStreamControl_StopAt(IAMStreamControl
*iface
,
2026 const REFERENCE_TIME
*ptStop
, BOOL bSendExtra
, DWORD dwCookie
)
2028 AviMuxIn
*avimuxin
= AviMuxIn_from_IAMStreamControl(iface
);
2029 AviMux
*This
= impl_from_in_IPin(&avimuxin
->pin
.pin
.IPin_iface
);
2030 FIXME("(%p:%s)->(%p %x %x)\n", This
, debugstr_w(avimuxin
->pin
.pin
.pinInfo
.achName
),
2031 ptStop
, bSendExtra
, dwCookie
);
2035 static HRESULT WINAPI
AviMuxIn_AMStreamControl_GetInfo(
2036 IAMStreamControl
*iface
, AM_STREAM_INFO
*pInfo
)
2038 AviMuxIn
*avimuxin
= AviMuxIn_from_IAMStreamControl(iface
);
2039 AviMux
*This
= impl_from_in_IPin(&avimuxin
->pin
.pin
.IPin_iface
);
2040 FIXME("(%p:%s)->(%p)\n", This
, debugstr_w(avimuxin
->pin
.pin
.pinInfo
.achName
), pInfo
);
2044 static const IAMStreamControlVtbl AviMuxIn_AMStreamControlVtbl
= {
2045 AviMuxIn_AMStreamControl_QueryInterface
,
2046 AviMuxIn_AMStreamControl_AddRef
,
2047 AviMuxIn_AMStreamControl_Release
,
2048 AviMuxIn_AMStreamControl_StartAt
,
2049 AviMuxIn_AMStreamControl_StopAt
,
2050 AviMuxIn_AMStreamControl_GetInfo
2053 static inline AviMuxIn
* AviMuxIn_from_IMemInputPin(IMemInputPin
*iface
)
2055 BaseInputPin
*bip
= CONTAINING_RECORD(iface
, BaseInputPin
, IMemInputPin_iface
);
2056 return CONTAINING_RECORD(bip
, AviMuxIn
, pin
);
2059 static HRESULT WINAPI
AviMuxIn_MemInputPin_QueryInterface(
2060 IMemInputPin
*iface
, REFIID riid
, void **ppv
)
2062 AviMuxIn
*avimuxin
= AviMuxIn_from_IMemInputPin(iface
);
2063 return IPin_QueryInterface(&avimuxin
->pin
.pin
.IPin_iface
, riid
, ppv
);
2066 static ULONG WINAPI
AviMuxIn_MemInputPin_AddRef(IMemInputPin
*iface
)
2068 AviMuxIn
*avimuxin
= AviMuxIn_from_IMemInputPin(iface
);
2069 AviMux
*This
= impl_from_in_IPin(&avimuxin
->pin
.pin
.IPin_iface
);
2070 return IBaseFilter_AddRef(&This
->filter
.IBaseFilter_iface
);
2073 static ULONG WINAPI
AviMuxIn_MemInputPin_Release(IMemInputPin
*iface
)
2075 AviMuxIn
*avimuxin
= AviMuxIn_from_IMemInputPin(iface
);
2076 AviMux
*This
= impl_from_in_IPin(&avimuxin
->pin
.pin
.IPin_iface
);
2077 return IBaseFilter_Release(&This
->filter
.IBaseFilter_iface
);
2080 static HRESULT WINAPI
AviMuxIn_MemInputPin_GetAllocator(
2081 IMemInputPin
*iface
, IMemAllocator
**ppAllocator
)
2083 AviMuxIn
*avimuxin
= AviMuxIn_from_IMemInputPin(iface
);
2084 AviMux
*This
= impl_from_in_IPin(&avimuxin
->pin
.pin
.IPin_iface
);
2086 TRACE("(%p:%s)->(%p)\n", This
, debugstr_w(avimuxin
->pin
.pin
.pinInfo
.achName
), ppAllocator
);
2091 IMemAllocator_AddRef(avimuxin
->pin
.pAllocator
);
2092 *ppAllocator
= avimuxin
->pin
.pAllocator
;
2096 static HRESULT WINAPI
AviMuxIn_MemInputPin_NotifyAllocator(
2097 IMemInputPin
*iface
, IMemAllocator
*pAllocator
, BOOL bReadOnly
)
2099 AviMuxIn
*avimuxin
= AviMuxIn_from_IMemInputPin(iface
);
2100 AviMux
*This
= impl_from_in_IPin(&avimuxin
->pin
.pin
.IPin_iface
);
2101 ALLOCATOR_PROPERTIES props
;
2104 TRACE("(%p:%s)->(%p %x)\n", This
, debugstr_w(avimuxin
->pin
.pin
.pinInfo
.achName
),
2105 pAllocator
, bReadOnly
);
2110 memset(&props
, 0, sizeof(props
));
2111 hr
= IMemAllocator_GetProperties(pAllocator
, &props
);
2117 return IMemAllocator_SetProperties(avimuxin
->pin
.pAllocator
, &props
, &props
);
2120 static HRESULT WINAPI
AviMuxIn_MemInputPin_GetAllocatorRequirements(
2121 IMemInputPin
*iface
, ALLOCATOR_PROPERTIES
*pProps
)
2123 AviMuxIn
*avimuxin
= AviMuxIn_from_IMemInputPin(iface
);
2124 AviMux
*This
= impl_from_in_IPin(&avimuxin
->pin
.pin
.IPin_iface
);
2126 TRACE("(%p:%s)->(%p)\n", This
, debugstr_w(avimuxin
->pin
.pin
.pinInfo
.achName
), pProps
);
2131 pProps
->cbAlign
= 1;
2132 pProps
->cbPrefix
= 8;
2136 static HRESULT WINAPI
AviMuxIn_MemInputPin_Receive(
2137 IMemInputPin
*iface
, IMediaSample
*pSample
)
2139 AviMuxIn
*avimuxin
= AviMuxIn_from_IMemInputPin(iface
);
2140 AviMux
*This
= impl_from_in_IPin(&avimuxin
->pin
.pin
.IPin_iface
);
2142 TRACE("(%p:%s)->(%p)\n", This
, debugstr_w(avimuxin
->pin
.pin
.pinInfo
.achName
), pSample
);
2144 return avimuxin
->pin
.pFuncsTable
->pfnReceive(&avimuxin
->pin
, pSample
);
2147 static HRESULT WINAPI
AviMuxIn_MemInputPin_ReceiveMultiple(IMemInputPin
*iface
,
2148 IMediaSample
**pSamples
, LONG nSamples
, LONG
*nSamplesProcessed
)
2150 AviMuxIn
*avimuxin
= AviMuxIn_from_IMemInputPin(iface
);
2151 AviMux
*This
= impl_from_in_IPin(&avimuxin
->pin
.pin
.IPin_iface
);
2154 TRACE("(%p:%s)->(%p %d %p)\n", This
, debugstr_w(avimuxin
->pin
.pin
.pinInfo
.achName
),
2155 pSamples
, nSamples
, nSamplesProcessed
);
2157 for(*nSamplesProcessed
=0; *nSamplesProcessed
<nSamples
; (*nSamplesProcessed
)++)
2159 hr
= avimuxin
->pin
.pFuncsTable
->pfnReceive(&avimuxin
->pin
, pSamples
[*nSamplesProcessed
]);
2167 static HRESULT WINAPI
AviMuxIn_MemInputPin_ReceiveCanBlock(IMemInputPin
*iface
)
2169 AviMuxIn
*avimuxin
= AviMuxIn_from_IMemInputPin(iface
);
2170 AviMux
*This
= impl_from_in_IPin(&avimuxin
->pin
.pin
.IPin_iface
);
2173 TRACE("(%p:%s)\n", This
, debugstr_w(avimuxin
->pin
.pin
.pinInfo
.achName
));
2175 if(!This
->out
->pin
.pMemInputPin
)
2178 hr
= IMemInputPin_ReceiveCanBlock(This
->out
->pin
.pMemInputPin
);
2179 return hr
!= S_FALSE
? S_OK
: S_FALSE
;
2182 static const IMemInputPinVtbl AviMuxIn_MemInputPinVtbl
= {
2183 AviMuxIn_MemInputPin_QueryInterface
,
2184 AviMuxIn_MemInputPin_AddRef
,
2185 AviMuxIn_MemInputPin_Release
,
2186 AviMuxIn_MemInputPin_GetAllocator
,
2187 AviMuxIn_MemInputPin_NotifyAllocator
,
2188 AviMuxIn_MemInputPin_GetAllocatorRequirements
,
2189 AviMuxIn_MemInputPin_Receive
,
2190 AviMuxIn_MemInputPin_ReceiveMultiple
,
2191 AviMuxIn_MemInputPin_ReceiveCanBlock
2194 static inline AviMuxIn
* AviMuxIn_from_IPropertyBag(IPropertyBag
*iface
)
2196 return CONTAINING_RECORD(iface
, AviMuxIn
, IPropertyBag_iface
);
2199 static HRESULT WINAPI
AviMuxIn_PropertyBag_QueryInterface(
2200 IPropertyBag
*iface
, REFIID riid
, void **ppv
)
2202 AviMuxIn
*avimuxin
= AviMuxIn_from_IPropertyBag(iface
);
2203 return IPin_QueryInterface(&avimuxin
->pin
.pin
.IPin_iface
, riid
, ppv
);
2206 static ULONG WINAPI
AviMuxIn_PropertyBag_AddRef(IPropertyBag
*iface
)
2208 AviMuxIn
*avimuxin
= AviMuxIn_from_IPropertyBag(iface
);
2209 AviMux
*This
= impl_from_in_IPin(&avimuxin
->pin
.pin
.IPin_iface
);
2210 return IBaseFilter_AddRef(&This
->filter
.IBaseFilter_iface
);
2213 static ULONG WINAPI
AviMuxIn_PropertyBag_Release(IPropertyBag
*iface
)
2215 AviMuxIn
*avimuxin
= AviMuxIn_from_IPropertyBag(iface
);
2216 AviMux
*This
= impl_from_in_IPin(&avimuxin
->pin
.pin
.IPin_iface
);
2217 return IBaseFilter_Release(&This
->filter
.IBaseFilter_iface
);
2220 static HRESULT WINAPI
AviMuxIn_PropertyBag_Read(IPropertyBag
*iface
,
2221 LPCOLESTR pszPropName
, VARIANT
*pVar
, IErrorLog
*pErrorLog
)
2223 AviMuxIn
*avimuxin
= AviMuxIn_from_IPropertyBag(iface
);
2224 AviMux
*This
= impl_from_in_IPin(&avimuxin
->pin
.pin
.IPin_iface
);
2225 FIXME("(%p:%s)->(%s %p %p)\n", This
, debugstr_w(avimuxin
->pin
.pin
.pinInfo
.achName
),
2226 debugstr_w(pszPropName
), pVar
, pErrorLog
);
2230 static HRESULT WINAPI
AviMuxIn_PropertyBag_Write(IPropertyBag
*iface
,
2231 LPCOLESTR pszPropName
, VARIANT
*pVar
)
2233 AviMuxIn
*avimuxin
= AviMuxIn_from_IPropertyBag(iface
);
2234 AviMux
*This
= impl_from_in_IPin(&avimuxin
->pin
.pin
.IPin_iface
);
2235 FIXME("(%p:%s)->(%s %p)\n", This
, debugstr_w(avimuxin
->pin
.pin
.pinInfo
.achName
),
2236 debugstr_w(pszPropName
), pVar
);
2240 static const IPropertyBagVtbl AviMuxIn_PropertyBagVtbl
= {
2241 AviMuxIn_PropertyBag_QueryInterface
,
2242 AviMuxIn_PropertyBag_AddRef
,
2243 AviMuxIn_PropertyBag_Release
,
2244 AviMuxIn_PropertyBag_Read
,
2245 AviMuxIn_PropertyBag_Write
2248 static inline AviMuxIn
* AviMuxIn_from_IQualityControl(IQualityControl
*iface
)
2250 return CONTAINING_RECORD(iface
, AviMuxIn
, IQualityControl_iface
);
2253 static HRESULT WINAPI
AviMuxIn_QualityControl_QueryInterface(
2254 IQualityControl
*iface
, REFIID riid
, void **ppv
)
2256 AviMuxIn
*avimuxin
= AviMuxIn_from_IQualityControl(iface
);
2257 return IPin_QueryInterface(&avimuxin
->pin
.pin
.IPin_iface
, riid
, ppv
);
2260 static ULONG WINAPI
AviMuxIn_QualityControl_AddRef(IQualityControl
*iface
)
2262 AviMuxIn
*avimuxin
= AviMuxIn_from_IQualityControl(iface
);
2263 AviMux
*This
= impl_from_in_IPin(&avimuxin
->pin
.pin
.IPin_iface
);
2264 return IBaseFilter_AddRef(&This
->filter
.IBaseFilter_iface
);
2267 static ULONG WINAPI
AviMuxIn_QualityControl_Release(IQualityControl
*iface
)
2269 AviMuxIn
*avimuxin
= AviMuxIn_from_IQualityControl(iface
);
2270 AviMux
*This
= impl_from_in_IPin(&avimuxin
->pin
.pin
.IPin_iface
);
2271 return IBaseFilter_Release(&This
->filter
.IBaseFilter_iface
);
2274 static HRESULT WINAPI
AviMuxIn_QualityControl_Notify(IQualityControl
*iface
,
2275 IBaseFilter
*pSelf
, Quality q
)
2277 AviMuxIn
*avimuxin
= AviMuxIn_from_IQualityControl(iface
);
2278 AviMux
*This
= impl_from_in_IPin(&avimuxin
->pin
.pin
.IPin_iface
);
2279 FIXME("(%p:%s)->(%p { 0x%x %u %s %s })\n", This
, debugstr_w(avimuxin
->pin
.pin
.pinInfo
.achName
), pSelf
,
2280 q
.Type
, q
.Proportion
,
2281 wine_dbgstr_longlong(q
.Late
),
2282 wine_dbgstr_longlong(q
.TimeStamp
));
2286 static HRESULT WINAPI
AviMuxIn_QualityControl_SetSink(
2287 IQualityControl
*iface
, IQualityControl
*piqc
)
2289 AviMuxIn
*avimuxin
= AviMuxIn_from_IQualityControl(iface
);
2290 AviMux
*This
= impl_from_in_IPin(&avimuxin
->pin
.pin
.IPin_iface
);
2291 FIXME("(%p:%s)->(%p)\n", This
, debugstr_w(avimuxin
->pin
.pin
.pinInfo
.achName
), piqc
);
2295 static const IQualityControlVtbl AviMuxIn_QualityControlVtbl
= {
2296 AviMuxIn_QualityControl_QueryInterface
,
2297 AviMuxIn_QualityControl_AddRef
,
2298 AviMuxIn_QualityControl_Release
,
2299 AviMuxIn_QualityControl_Notify
,
2300 AviMuxIn_QualityControl_SetSink
2303 static HRESULT
create_input_pin(AviMux
*avimux
)
2305 static const WCHAR name
[] = {'I','n','p','u','t',' ','0','0',0};
2309 if(avimux
->input_pin_no
>= MAX_PIN_NO
-1)
2312 info
.dir
= PINDIR_INPUT
;
2313 info
.pFilter
= &avimux
->filter
.IBaseFilter_iface
;
2314 memcpy(info
.achName
, name
, sizeof(name
));
2315 info
.achName
[7] = '0' + (avimux
->input_pin_no
+1) % 10;
2316 info
.achName
[6] = '0' + (avimux
->input_pin_no
+1) / 10;
2318 hr
= BaseInputPin_Construct(&AviMuxIn_PinVtbl
, sizeof(AviMuxIn
), &info
,
2319 &AviMuxIn_BaseInputFuncTable
, &avimux
->filter
.csFilter
, NULL
, (IPin
**)&avimux
->in
[avimux
->input_pin_no
]);
2322 avimux
->in
[avimux
->input_pin_no
]->pin
.IMemInputPin_iface
.lpVtbl
= &AviMuxIn_MemInputPinVtbl
;
2323 avimux
->in
[avimux
->input_pin_no
]->IAMStreamControl_iface
.lpVtbl
= &AviMuxIn_AMStreamControlVtbl
;
2324 avimux
->in
[avimux
->input_pin_no
]->IPropertyBag_iface
.lpVtbl
= &AviMuxIn_PropertyBagVtbl
;
2325 avimux
->in
[avimux
->input_pin_no
]->IQualityControl_iface
.lpVtbl
= &AviMuxIn_QualityControlVtbl
;
2327 avimux
->in
[avimux
->input_pin_no
]->samples_head
= NULL
;
2328 hr
= CoCreateInstance(&CLSID_MemoryAllocator
, NULL
, CLSCTX_INPROC_SERVER
,
2329 &IID_IMemAllocator
, (void**)&avimux
->in
[avimux
->input_pin_no
]->samples_allocator
);
2331 BaseInputPinImpl_Release(&avimux
->in
[avimux
->input_pin_no
]->pin
.pin
.IPin_iface
);
2335 hr
= CoCreateInstance(&CLSID_MemoryAllocator
, NULL
, CLSCTX_INPROC_SERVER
,
2336 &IID_IMemAllocator
, (void**)&avimux
->in
[avimux
->input_pin_no
]->pin
.pAllocator
);
2338 IMemAllocator_Release(avimux
->in
[avimux
->input_pin_no
]->samples_allocator
);
2339 BaseInputPinImpl_Release(&avimux
->in
[avimux
->input_pin_no
]->pin
.pin
.IPin_iface
);
2343 avimux
->in
[avimux
->input_pin_no
]->stream_time
= 0;
2344 memset(&avimux
->in
[avimux
->input_pin_no
]->strh
, 0, sizeof(avimux
->in
[avimux
->input_pin_no
]->strh
));
2345 avimux
->in
[avimux
->input_pin_no
]->strf
= NULL
;
2346 memset(&avimux
->in
[avimux
->input_pin_no
]->indx_data
, 0, sizeof(avimux
->in
[avimux
->input_pin_no
]->indx_data
));
2347 memset(&avimux
->in
[avimux
->input_pin_no
]->ix_data
, 0, sizeof(avimux
->in
[avimux
->input_pin_no
]->ix_data
));
2348 avimux
->in
[avimux
->input_pin_no
]->indx
= (AVISUPERINDEX
*)&avimux
->in
[avimux
->input_pin_no
]->indx_data
;
2349 avimux
->in
[avimux
->input_pin_no
]->ix
= (AVISTDINDEX
*)avimux
->in
[avimux
->input_pin_no
]->ix_data
;
2351 avimux
->input_pin_no
++;
2355 IUnknown
* WINAPI
QCAP_createAVIMux(IUnknown
*pUnkOuter
, HRESULT
*phr
)
2357 static const WCHAR output_name
[] = {'A','V','I',' ','O','u','t',0};
2363 TRACE("(%p)\n", pUnkOuter
);
2366 *phr
= CLASS_E_NOAGGREGATION
;
2370 avimux
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(AviMux
));
2372 *phr
= E_OUTOFMEMORY
;
2376 BaseFilter_Init(&avimux
->filter
, &AviMuxVtbl
, &CLSID_AviDest
,
2377 (DWORD_PTR
)(__FILE__
": AviMux.csFilter"), &filter_func_table
);
2378 avimux
->IConfigAviMux_iface
.lpVtbl
= &ConfigAviMuxVtbl
;
2379 avimux
->IConfigInterleaving_iface
.lpVtbl
= &ConfigInterleavingVtbl
;
2380 avimux
->IMediaSeeking_iface
.lpVtbl
= &MediaSeekingVtbl
;
2381 avimux
->IPersistMediaPropertyBag_iface
.lpVtbl
= &PersistMediaPropertyBagVtbl
;
2382 avimux
->ISpecifyPropertyPages_iface
.lpVtbl
= &SpecifyPropertyPagesVtbl
;
2384 info
.dir
= PINDIR_OUTPUT
;
2385 info
.pFilter
= &avimux
->filter
.IBaseFilter_iface
;
2386 lstrcpyW(info
.achName
, output_name
);
2387 hr
= BaseOutputPin_Construct(&AviMuxOut_PinVtbl
, sizeof(AviMuxOut
), &info
,
2388 &AviMuxOut_BaseOutputFuncTable
, &avimux
->filter
.csFilter
, (IPin
**)&avimux
->out
);
2390 BaseFilterImpl_Release(&avimux
->filter
.IBaseFilter_iface
);
2391 HeapFree(GetProcessHeap(), 0, avimux
);
2395 avimux
->out
->IQualityControl_iface
.lpVtbl
= &AviMuxOut_QualityControlVtbl
;
2396 avimux
->out
->cur_stream
= 0;
2397 avimux
->out
->cur_time
= 0;
2398 avimux
->out
->stream
= NULL
;
2400 hr
= create_input_pin(avimux
);
2402 BaseOutputPinImpl_Release(&avimux
->out
->pin
.pin
.IPin_iface
);
2403 BaseFilterImpl_Release(&avimux
->filter
.IBaseFilter_iface
);
2404 HeapFree(GetProcessHeap(), 0, avimux
);
2409 avimux
->interleave
= 10000000;
2411 ObjectRefCount(TRUE
);
2413 return (IUnknown
*)&avimux
->filter
.IBaseFilter_iface
;