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)->(%p)\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 Quality)\n", This
, pSelf
);
1546 static HRESULT WINAPI
AviMuxOut_QualityControl_SetSink(
1547 IQualityControl
*iface
, IQualityControl
*piqc
)
1549 AviMux
*This
= impl_from_out_IQualityControl(iface
);
1550 FIXME("(%p)->(%p)\n", This
, piqc
);
1554 static const IQualityControlVtbl AviMuxOut_QualityControlVtbl
= {
1555 AviMuxOut_QualityControl_QueryInterface
,
1556 AviMuxOut_QualityControl_AddRef
,
1557 AviMuxOut_QualityControl_Release
,
1558 AviMuxOut_QualityControl_Notify
,
1559 AviMuxOut_QualityControl_SetSink
1562 static HRESULT WINAPI
AviMuxIn_CheckMediaType(BasePin
*base
, const AM_MEDIA_TYPE
*pmt
)
1564 TRACE("(%p:%s)->(AM_MEDIA_TYPE(%p))\n", base
, debugstr_w(base
->pinInfo
.achName
), pmt
);
1565 dump_AM_MEDIA_TYPE(pmt
);
1567 if(IsEqualIID(&pmt
->majortype
, &MEDIATYPE_Audio
) &&
1568 IsEqualIID(&pmt
->formattype
, &FORMAT_WaveFormatEx
))
1570 if(IsEqualIID(&pmt
->majortype
, &MEDIATYPE_Interleaved
) &&
1571 IsEqualIID(&pmt
->formattype
, &FORMAT_DvInfo
))
1573 if(IsEqualIID(&pmt
->majortype
, &MEDIATYPE_Video
) &&
1574 (IsEqualIID(&pmt
->formattype
, &FORMAT_VideoInfo
) ||
1575 IsEqualIID(&pmt
->formattype
, &FORMAT_DvInfo
)))
1580 static LONG WINAPI
AviMuxIn_GetMediaTypeVersion(BasePin
*base
)
1585 static HRESULT WINAPI
AviMuxIn_GetMediaType(BasePin
*base
, int iPosition
, AM_MEDIA_TYPE
*amt
)
1590 static HRESULT WINAPI
AviMuxIn_Receive(BaseInputPin
*base
, IMediaSample
*pSample
)
1592 AviMuxIn
*avimuxin
= CONTAINING_RECORD(base
, AviMuxIn
, pin
);
1593 AviMux
*avimux
= impl_from_IBaseFilter(base
->pin
.pinInfo
.pFilter
);
1594 REFERENCE_TIME start
, stop
;
1595 IMediaSample
*sample
;
1599 DWORD max_size
, size
;
1603 TRACE("(%p:%s)->(%p)\n", base
, debugstr_w(base
->pin
.pinInfo
.achName
), pSample
);
1605 hr
= IMediaSample_QueryInterface(pSample
, &IID_IMediaSample2
, (void**)&ms2
);
1607 AM_SAMPLE2_PROPERTIES props
;
1609 memset(&props
, 0, sizeof(props
));
1610 hr
= IMediaSample2_GetProperties(ms2
, sizeof(props
), (BYTE
*)&props
);
1611 IMediaSample2_Release(ms2
);
1615 flags
= props
.dwSampleFlags
;
1616 frame
= props
.pbBuffer
;
1617 size
= props
.lActual
;
1619 flags
= IMediaSample_IsSyncPoint(pSample
) == S_OK
? AM_SAMPLE_SPLICEPOINT
: 0;
1620 hr
= IMediaSample_GetPointer(pSample
, &frame
);
1623 size
= IMediaSample_GetActualDataLength(pSample
);
1626 if(!avimuxin
->pin
.pin
.mtCurrent
.bTemporalCompression
)
1627 flags
|= AM_SAMPLE_SPLICEPOINT
;
1629 hr
= IMediaSample_GetTime(pSample
, &start
, &stop
);
1633 if(avimuxin
->stop
>stop
)
1634 return VFW_E_START_TIME_AFTER_END
;
1636 if(avimux
->start
== -1)
1637 avimux
->start
= start
;
1638 if(avimux
->stop
< stop
)
1639 avimux
->stop
= stop
;
1641 if(avimux
->avih
.dwSuggestedBufferSize
< ALIGN(size
)+sizeof(RIFFCHUNK
))
1642 avimux
->avih
.dwSuggestedBufferSize
= ALIGN(size
) + sizeof(RIFFCHUNK
);
1643 if(avimuxin
->strh
.dwSuggestedBufferSize
< ALIGN(size
)+sizeof(RIFFCHUNK
))
1644 avimuxin
->strh
.dwSuggestedBufferSize
= ALIGN(size
) + sizeof(RIFFCHUNK
);
1647 if(avimuxin
->stop
!=-1 && start
> avimuxin
->stop
) {
1648 frames_no
+= (double)(start
- avimuxin
->stop
) / 10000000
1649 * avimuxin
->strh
.dwRate
/ avimuxin
->strh
.dwScale
+ 0.5;
1651 avimuxin
->stop
= stop
;
1653 while(--frames_no
) {
1654 /* TODO: store all control frames in one buffer */
1655 hr
= IMemAllocator_GetBuffer(avimuxin
->samples_allocator
, &sample
, NULL
, NULL
, 0);
1658 hr
= IMediaSample_SetActualDataLength(sample
, 0);
1660 hr
= IMediaSample_SetDiscontinuity(sample
, TRUE
);
1662 hr
= IMediaSample_SetSyncPoint(sample
, FALSE
);
1664 hr
= queue_sample(avimux
, avimuxin
, sample
);
1665 IMediaSample_Release(sample
);
1670 hr
= IMemAllocator_GetBuffer(avimuxin
->samples_allocator
, &sample
, NULL
, NULL
, 0);
1673 max_size
= IMediaSample_GetSize(sample
);
1676 hr
= IMediaSample_SetActualDataLength(sample
, size
);
1678 hr
= IMediaSample_SetDiscontinuity(sample
, FALSE
);
1680 hr
= IMediaSample_SetSyncPoint(sample
, flags
& AM_SAMPLE_SPLICEPOINT
);
1681 /* TODO: avoid unnecesarry copying */
1683 hr
= IMediaSample_GetPointer(sample
, &buf
);
1685 memcpy(buf
, frame
, size
);
1686 hr
= queue_sample(avimux
, avimuxin
, sample
);
1688 IMediaSample_Release(sample
);
1693 static const BaseInputPinFuncTable AviMuxIn_BaseInputFuncTable
= {
1695 AviMuxIn_CheckMediaType
,
1697 AviMuxIn_GetMediaTypeVersion
,
1698 AviMuxIn_GetMediaType
1703 static inline AviMux
* impl_from_in_IPin(IPin
*iface
)
1705 BasePin
*bp
= CONTAINING_RECORD(iface
, BasePin
, IPin_iface
);
1706 IBaseFilter
*bf
= bp
->pinInfo
.pFilter
;
1708 return impl_from_IBaseFilter(bf
);
1711 static inline AviMuxIn
* AviMuxIn_from_IPin(IPin
*iface
)
1713 BasePin
*bp
= CONTAINING_RECORD(iface
, BasePin
, IPin_iface
);
1714 BaseInputPin
*bip
= CONTAINING_RECORD(bp
, BaseInputPin
, pin
);
1715 return CONTAINING_RECORD(bip
, AviMuxIn
, pin
);
1718 static HRESULT WINAPI
AviMuxIn_QueryInterface(IPin
*iface
, REFIID riid
, void **ppv
)
1720 AviMux
*This
= impl_from_in_IPin(iface
);
1721 AviMuxIn
*avimuxin
= AviMuxIn_from_IPin(iface
);
1723 TRACE("(%p:%s)->(%s %p)\n", This
, debugstr_w(avimuxin
->pin
.pin
.pinInfo
.achName
),
1724 debugstr_guid(riid
), ppv
);
1726 if(IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IPin
))
1727 *ppv
= &avimuxin
->pin
.pin
.IPin_iface
;
1728 else if(IsEqualIID(riid
, &IID_IAMStreamControl
))
1729 *ppv
= &avimuxin
->IAMStreamControl_iface
;
1730 else if(IsEqualIID(riid
, &IID_IMemInputPin
))
1731 *ppv
= &avimuxin
->pin
.IMemInputPin_iface
;
1732 else if(IsEqualIID(riid
, &IID_IPropertyBag
))
1733 *ppv
= &avimuxin
->IPropertyBag_iface
;
1734 else if(IsEqualIID(riid
, &IID_IQualityControl
))
1735 *ppv
= &avimuxin
->IQualityControl_iface
;
1737 FIXME("no interface for %s\n", debugstr_guid(riid
));
1739 return E_NOINTERFACE
;
1742 IUnknown_AddRef((IUnknown
*)*ppv
);
1746 static ULONG WINAPI
AviMuxIn_AddRef(IPin
*iface
)
1748 AviMux
*This
= impl_from_in_IPin(iface
);
1749 return IBaseFilter_AddRef(&This
->filter
.IBaseFilter_iface
);
1752 static ULONG WINAPI
AviMuxIn_Release(IPin
*iface
)
1754 AviMux
*This
= impl_from_in_IPin(iface
);
1755 return IBaseFilter_Release(&This
->filter
.IBaseFilter_iface
);
1758 static HRESULT WINAPI
AviMuxIn_Connect(IPin
*iface
,
1759 IPin
*pReceivePin
, const AM_MEDIA_TYPE
*pmt
)
1761 AviMux
*This
= impl_from_in_IPin(iface
);
1762 AviMuxIn
*avimuxin
= AviMuxIn_from_IPin(iface
);
1763 TRACE("(%p:%s)->(%p AM_MEDIA_TYPE(%p))\n", This
,
1764 debugstr_w(avimuxin
->pin
.pin
.pinInfo
.achName
), pReceivePin
, pmt
);
1765 dump_AM_MEDIA_TYPE(pmt
);
1766 return BaseInputPinImpl_Connect(iface
, pReceivePin
, pmt
);
1769 static HRESULT WINAPI
AviMuxIn_ReceiveConnection(IPin
*iface
,
1770 IPin
*pConnector
, const AM_MEDIA_TYPE
*pmt
)
1772 AviMux
*This
= impl_from_in_IPin(iface
);
1773 AviMuxIn
*avimuxin
= AviMuxIn_from_IPin(iface
);
1776 TRACE("(%p:%s)->(%p AM_MEDIA_TYPE(%p))\n", This
,
1777 debugstr_w(avimuxin
->pin
.pin
.pinInfo
.achName
), pConnector
, pmt
);
1778 dump_AM_MEDIA_TYPE(pmt
);
1783 hr
= BaseInputPinImpl_ReceiveConnection(iface
, pConnector
, pmt
);
1787 if(IsEqualIID(&pmt
->majortype
, &MEDIATYPE_Video
) &&
1788 IsEqualIID(&pmt
->formattype
, &FORMAT_VideoInfo
)) {
1789 ALLOCATOR_PROPERTIES req
, act
;
1790 VIDEOINFOHEADER
*vih
;
1793 vih
= (VIDEOINFOHEADER
*)pmt
->pbFormat
;
1794 avimuxin
->strh
.fcc
= ckidSTREAMHEADER
;
1795 avimuxin
->strh
.cb
= sizeof(AVISTREAMHEADER
) - FIELD_OFFSET(AVISTREAMHEADER
, fccType
);
1796 avimuxin
->strh
.fccType
= streamtypeVIDEO
;
1797 /* FIXME: fccHandler should be set differently */
1798 avimuxin
->strh
.fccHandler
= vih
->bmiHeader
.biCompression
?
1799 vih
->bmiHeader
.biCompression
: FCC('D','I','B',' ');
1800 avimuxin
->avg_time_per_frame
= vih
->AvgTimePerFrame
;
1801 avimuxin
->stop
= -1;
1804 req
.cbBuffer
= vih
->bmiHeader
.biSizeImage
;
1806 req
.cbPrefix
= sizeof(void*);
1807 hr
= IMemAllocator_SetProperties(avimuxin
->samples_allocator
, &req
, &act
);
1809 hr
= IMemAllocator_Commit(avimuxin
->samples_allocator
);
1811 BasePinImpl_Disconnect(iface
);
1815 size
= pmt
->cbFormat
- FIELD_OFFSET(VIDEOINFOHEADER
, bmiHeader
);
1816 avimuxin
->strf
= CoTaskMemAlloc(sizeof(RIFFCHUNK
) + ALIGN(FIELD_OFFSET(BITMAPINFO
, bmiColors
[vih
->bmiHeader
.biClrUsed
])));
1817 avimuxin
->strf
->fcc
= ckidSTREAMFORMAT
;
1818 avimuxin
->strf
->cb
= FIELD_OFFSET(BITMAPINFO
, bmiColors
[vih
->bmiHeader
.biClrUsed
]);
1819 if(size
> avimuxin
->strf
->cb
)
1820 size
= avimuxin
->strf
->cb
;
1821 memcpy(avimuxin
->strf
->data
, &vih
->bmiHeader
, size
);
1823 FIXME("format not supported: %s %s\n", debugstr_guid(&pmt
->majortype
),
1824 debugstr_guid(&pmt
->formattype
));
1828 return create_input_pin(This
);
1831 static HRESULT WINAPI
AviMuxIn_Disconnect(IPin
*iface
)
1833 AviMux
*This
= impl_from_in_IPin(iface
);
1834 AviMuxIn
*avimuxin
= AviMuxIn_from_IPin(iface
);
1835 IMediaSample
**prev
, *cur
;
1838 TRACE("(%p:%s)\n", This
, debugstr_w(avimuxin
->pin
.pin
.pinInfo
.achName
));
1840 hr
= BasePinImpl_Disconnect(iface
);
1844 IMemAllocator_Decommit(avimuxin
->samples_allocator
);
1845 while(avimuxin
->samples_head
) {
1846 cur
= avimuxin
->samples_head
;
1847 hr
= IMediaSample_GetPointer(cur
, (BYTE
**)&prev
);
1852 cur
= avimuxin
->samples_head
;
1853 avimuxin
->samples_head
= *prev
;
1854 IMediaSample_Release(cur
);
1856 if(cur
== avimuxin
->samples_head
)
1857 avimuxin
->samples_head
= NULL
;
1859 CoTaskMemFree(avimuxin
->strf
);
1860 avimuxin
->strf
= NULL
;
1864 static HRESULT WINAPI
AviMuxIn_ConnectedTo(IPin
*iface
, IPin
**pPin
)
1866 AviMux
*This
= impl_from_in_IPin(iface
);
1867 AviMuxIn
*avimuxin
= AviMuxIn_from_IPin(iface
);
1868 TRACE("(%p:%s)->(%p)\n", This
, debugstr_w(avimuxin
->pin
.pin
.pinInfo
.achName
), pPin
);
1869 return BasePinImpl_ConnectedTo(iface
, pPin
);
1872 static HRESULT WINAPI
AviMuxIn_ConnectionMediaType(IPin
*iface
, AM_MEDIA_TYPE
*pmt
)
1874 AviMux
*This
= impl_from_in_IPin(iface
);
1875 AviMuxIn
*avimuxin
= AviMuxIn_from_IPin(iface
);
1876 TRACE("(%p:%s)->(%p)\n", This
, debugstr_w(avimuxin
->pin
.pin
.pinInfo
.achName
), pmt
);
1877 return BasePinImpl_ConnectionMediaType(iface
, pmt
);
1880 static HRESULT WINAPI
AviMuxIn_QueryPinInfo(IPin
*iface
, PIN_INFO
*pInfo
)
1882 AviMux
*This
= impl_from_in_IPin(iface
);
1883 AviMuxIn
*avimuxin
= AviMuxIn_from_IPin(iface
);
1884 TRACE("(%p:%s)->(%p)\n", This
, debugstr_w(avimuxin
->pin
.pin
.pinInfo
.achName
), pInfo
);
1885 return BasePinImpl_QueryPinInfo(iface
, pInfo
);
1888 static HRESULT WINAPI
AviMuxIn_QueryDirection(IPin
*iface
, PIN_DIRECTION
*pPinDir
)
1890 AviMux
*This
= impl_from_in_IPin(iface
);
1891 AviMuxIn
*avimuxin
= AviMuxIn_from_IPin(iface
);
1892 TRACE("(%p:%s)->(%p)\n", This
, debugstr_w(avimuxin
->pin
.pin
.pinInfo
.achName
), pPinDir
);
1893 return BasePinImpl_QueryDirection(iface
, pPinDir
);
1896 static HRESULT WINAPI
AviMuxIn_QueryId(IPin
*iface
, LPWSTR
*Id
)
1898 AviMux
*This
= impl_from_in_IPin(iface
);
1899 AviMuxIn
*avimuxin
= AviMuxIn_from_IPin(iface
);
1900 TRACE("(%p:%s)->(%p)\n", This
, debugstr_w(avimuxin
->pin
.pin
.pinInfo
.achName
), Id
);
1901 return BasePinImpl_QueryId(iface
, Id
);
1904 static HRESULT WINAPI
AviMuxIn_QueryAccept(IPin
*iface
, const AM_MEDIA_TYPE
*pmt
)
1906 AviMux
*This
= impl_from_in_IPin(iface
);
1907 AviMuxIn
*avimuxin
= AviMuxIn_from_IPin(iface
);
1908 TRACE("(%p:%s)->(AM_MEDIA_TYPE(%p))\n", This
,
1909 debugstr_w(avimuxin
->pin
.pin
.pinInfo
.achName
), pmt
);
1910 dump_AM_MEDIA_TYPE(pmt
);
1911 return BasePinImpl_QueryAccept(iface
, pmt
);
1914 static HRESULT WINAPI
AviMuxIn_EnumMediaTypes(IPin
*iface
, IEnumMediaTypes
**ppEnum
)
1916 AviMux
*This
= impl_from_in_IPin(iface
);
1917 AviMuxIn
*avimuxin
= AviMuxIn_from_IPin(iface
);
1918 TRACE("(%p:%s)->(%p)\n", This
, debugstr_w(avimuxin
->pin
.pin
.pinInfo
.achName
), ppEnum
);
1919 return BasePinImpl_EnumMediaTypes(iface
, ppEnum
);
1922 static HRESULT WINAPI
AviMuxIn_QueryInternalConnections(
1923 IPin
*iface
, IPin
**apPin
, ULONG
*nPin
)
1925 AviMux
*This
= impl_from_in_IPin(iface
);
1926 AviMuxIn
*avimuxin
= AviMuxIn_from_IPin(iface
);
1927 TRACE("(%p:%s)->(%p %p)\n", This
, debugstr_w(avimuxin
->pin
.pin
.pinInfo
.achName
), apPin
, nPin
);
1928 return BasePinImpl_QueryInternalConnections(iface
, apPin
, nPin
);
1931 static HRESULT WINAPI
AviMuxIn_EndOfStream(IPin
*iface
)
1933 AviMux
*This
= impl_from_in_IPin(iface
);
1934 AviMuxIn
*avimuxin
= AviMuxIn_from_IPin(iface
);
1935 TRACE("(%p:%s)\n", This
, debugstr_w(avimuxin
->pin
.pin
.pinInfo
.achName
));
1936 return BaseInputPinImpl_EndOfStream(iface
);
1939 static HRESULT WINAPI
AviMuxIn_BeginFlush(IPin
*iface
)
1941 AviMux
*This
= impl_from_in_IPin(iface
);
1942 AviMuxIn
*avimuxin
= AviMuxIn_from_IPin(iface
);
1943 TRACE("(%p:%s)\n", This
, debugstr_w(avimuxin
->pin
.pin
.pinInfo
.achName
));
1944 return BaseInputPinImpl_BeginFlush(iface
);
1947 static HRESULT WINAPI
AviMuxIn_EndFlush(IPin
*iface
)
1949 AviMux
*This
= impl_from_in_IPin(iface
);
1950 AviMuxIn
*avimuxin
= AviMuxIn_from_IPin(iface
);
1951 TRACE("(%p:%s)\n", This
, debugstr_w(avimuxin
->pin
.pin
.pinInfo
.achName
));
1952 return BaseInputPinImpl_EndFlush(iface
);
1955 static HRESULT WINAPI
AviMuxIn_NewSegment(IPin
*iface
, REFERENCE_TIME tStart
,
1956 REFERENCE_TIME tStop
, double dRate
)
1958 AviMux
*This
= impl_from_in_IPin(iface
);
1959 AviMuxIn
*avimuxin
= AviMuxIn_from_IPin(iface
);
1960 TRACE("(%p:%s)->(0x%x%08x 0x%x%08x %lf)\n", This
, debugstr_w(avimuxin
->pin
.pin
.pinInfo
.achName
),
1961 (ULONG
)(tStart
>> 32), (ULONG
)tStart
, (ULONG
)(tStop
>> 32), (ULONG
)tStop
, dRate
);
1962 return BasePinImpl_NewSegment(iface
, tStart
, tStop
, dRate
);
1965 static const IPinVtbl AviMuxIn_PinVtbl
= {
1966 AviMuxIn_QueryInterface
,
1970 AviMuxIn_ReceiveConnection
,
1971 AviMuxIn_Disconnect
,
1972 AviMuxIn_ConnectedTo
,
1973 AviMuxIn_ConnectionMediaType
,
1974 AviMuxIn_QueryPinInfo
,
1975 AviMuxIn_QueryDirection
,
1977 AviMuxIn_QueryAccept
,
1978 AviMuxIn_EnumMediaTypes
,
1979 AviMuxIn_QueryInternalConnections
,
1980 AviMuxIn_EndOfStream
,
1981 AviMuxIn_BeginFlush
,
1986 static inline AviMuxIn
* AviMuxIn_from_IAMStreamControl(IAMStreamControl
*iface
)
1988 return CONTAINING_RECORD(iface
, AviMuxIn
, IAMStreamControl_iface
);
1991 static HRESULT WINAPI
AviMuxIn_AMStreamControl_QueryInterface(
1992 IAMStreamControl
*iface
, REFIID riid
, void **ppv
)
1994 AviMuxIn
*avimuxin
= AviMuxIn_from_IAMStreamControl(iface
);
1995 return IPin_QueryInterface(&avimuxin
->pin
.pin
.IPin_iface
, riid
, ppv
);
1998 static ULONG WINAPI
AviMuxIn_AMStreamControl_AddRef(IAMStreamControl
*iface
)
2000 AviMuxIn
*avimuxin
= AviMuxIn_from_IAMStreamControl(iface
);
2001 AviMux
*This
= impl_from_in_IPin(&avimuxin
->pin
.pin
.IPin_iface
);
2002 return IBaseFilter_AddRef(&This
->filter
.IBaseFilter_iface
);
2005 static ULONG WINAPI
AviMuxIn_AMStreamControl_Release(IAMStreamControl
*iface
)
2007 AviMuxIn
*avimuxin
= AviMuxIn_from_IAMStreamControl(iface
);
2008 AviMux
*This
= impl_from_in_IPin(&avimuxin
->pin
.pin
.IPin_iface
);
2009 return IBaseFilter_Release(&This
->filter
.IBaseFilter_iface
);
2012 static HRESULT WINAPI
AviMuxIn_AMStreamControl_StartAt(IAMStreamControl
*iface
,
2013 const REFERENCE_TIME
*ptStart
, DWORD dwCookie
)
2015 AviMuxIn
*avimuxin
= AviMuxIn_from_IAMStreamControl(iface
);
2016 AviMux
*This
= impl_from_in_IPin(&avimuxin
->pin
.pin
.IPin_iface
);
2017 FIXME("(%p:%s)->(%p %x)\n", This
,
2018 debugstr_w(avimuxin
->pin
.pin
.pinInfo
.achName
), ptStart
, dwCookie
);
2022 static HRESULT WINAPI
AviMuxIn_AMStreamControl_StopAt(IAMStreamControl
*iface
,
2023 const REFERENCE_TIME
*ptStop
, BOOL bSendExtra
, DWORD dwCookie
)
2025 AviMuxIn
*avimuxin
= AviMuxIn_from_IAMStreamControl(iface
);
2026 AviMux
*This
= impl_from_in_IPin(&avimuxin
->pin
.pin
.IPin_iface
);
2027 FIXME("(%p:%s)->(%p %x %x)\n", This
, debugstr_w(avimuxin
->pin
.pin
.pinInfo
.achName
),
2028 ptStop
, bSendExtra
, dwCookie
);
2032 static HRESULT WINAPI
AviMuxIn_AMStreamControl_GetInfo(
2033 IAMStreamControl
*iface
, AM_STREAM_INFO
*pInfo
)
2035 AviMuxIn
*avimuxin
= AviMuxIn_from_IAMStreamControl(iface
);
2036 AviMux
*This
= impl_from_in_IPin(&avimuxin
->pin
.pin
.IPin_iface
);
2037 FIXME("(%p:%s)->(%p)\n", This
, debugstr_w(avimuxin
->pin
.pin
.pinInfo
.achName
), pInfo
);
2041 static const IAMStreamControlVtbl AviMuxIn_AMStreamControlVtbl
= {
2042 AviMuxIn_AMStreamControl_QueryInterface
,
2043 AviMuxIn_AMStreamControl_AddRef
,
2044 AviMuxIn_AMStreamControl_Release
,
2045 AviMuxIn_AMStreamControl_StartAt
,
2046 AviMuxIn_AMStreamControl_StopAt
,
2047 AviMuxIn_AMStreamControl_GetInfo
2050 static inline AviMuxIn
* AviMuxIn_from_IMemInputPin(IMemInputPin
*iface
)
2052 BaseInputPin
*bip
= CONTAINING_RECORD(iface
, BaseInputPin
, IMemInputPin_iface
);
2053 return CONTAINING_RECORD(bip
, AviMuxIn
, pin
);
2056 static HRESULT WINAPI
AviMuxIn_MemInputPin_QueryInterface(
2057 IMemInputPin
*iface
, REFIID riid
, void **ppv
)
2059 AviMuxIn
*avimuxin
= AviMuxIn_from_IMemInputPin(iface
);
2060 return IPin_QueryInterface(&avimuxin
->pin
.pin
.IPin_iface
, riid
, ppv
);
2063 static ULONG WINAPI
AviMuxIn_MemInputPin_AddRef(IMemInputPin
*iface
)
2065 AviMuxIn
*avimuxin
= AviMuxIn_from_IMemInputPin(iface
);
2066 AviMux
*This
= impl_from_in_IPin(&avimuxin
->pin
.pin
.IPin_iface
);
2067 return IBaseFilter_AddRef(&This
->filter
.IBaseFilter_iface
);
2070 static ULONG WINAPI
AviMuxIn_MemInputPin_Release(IMemInputPin
*iface
)
2072 AviMuxIn
*avimuxin
= AviMuxIn_from_IMemInputPin(iface
);
2073 AviMux
*This
= impl_from_in_IPin(&avimuxin
->pin
.pin
.IPin_iface
);
2074 return IBaseFilter_Release(&This
->filter
.IBaseFilter_iface
);
2077 static HRESULT WINAPI
AviMuxIn_MemInputPin_GetAllocator(
2078 IMemInputPin
*iface
, IMemAllocator
**ppAllocator
)
2080 AviMuxIn
*avimuxin
= AviMuxIn_from_IMemInputPin(iface
);
2081 AviMux
*This
= impl_from_in_IPin(&avimuxin
->pin
.pin
.IPin_iface
);
2083 TRACE("(%p:%s)->(%p)\n", This
, debugstr_w(avimuxin
->pin
.pin
.pinInfo
.achName
), ppAllocator
);
2088 IMemAllocator_AddRef(avimuxin
->pin
.pAllocator
);
2089 *ppAllocator
= avimuxin
->pin
.pAllocator
;
2093 static HRESULT WINAPI
AviMuxIn_MemInputPin_NotifyAllocator(
2094 IMemInputPin
*iface
, IMemAllocator
*pAllocator
, BOOL bReadOnly
)
2096 AviMuxIn
*avimuxin
= AviMuxIn_from_IMemInputPin(iface
);
2097 AviMux
*This
= impl_from_in_IPin(&avimuxin
->pin
.pin
.IPin_iface
);
2098 ALLOCATOR_PROPERTIES props
;
2101 TRACE("(%p:%s)->(%p %x)\n", This
, debugstr_w(avimuxin
->pin
.pin
.pinInfo
.achName
),
2102 pAllocator
, bReadOnly
);
2107 memset(&props
, 0, sizeof(props
));
2108 hr
= IMemAllocator_GetProperties(pAllocator
, &props
);
2114 return IMemAllocator_SetProperties(avimuxin
->pin
.pAllocator
, &props
, &props
);
2117 static HRESULT WINAPI
AviMuxIn_MemInputPin_GetAllocatorRequirements(
2118 IMemInputPin
*iface
, ALLOCATOR_PROPERTIES
*pProps
)
2120 AviMuxIn
*avimuxin
= AviMuxIn_from_IMemInputPin(iface
);
2121 AviMux
*This
= impl_from_in_IPin(&avimuxin
->pin
.pin
.IPin_iface
);
2123 TRACE("(%p:%s)->(%p)\n", This
, debugstr_w(avimuxin
->pin
.pin
.pinInfo
.achName
), pProps
);
2128 pProps
->cbAlign
= 1;
2129 pProps
->cbPrefix
= 8;
2133 static HRESULT WINAPI
AviMuxIn_MemInputPin_Receive(
2134 IMemInputPin
*iface
, IMediaSample
*pSample
)
2136 AviMuxIn
*avimuxin
= AviMuxIn_from_IMemInputPin(iface
);
2137 AviMux
*This
= impl_from_in_IPin(&avimuxin
->pin
.pin
.IPin_iface
);
2139 TRACE("(%p:%s)->(%p)\n", This
, debugstr_w(avimuxin
->pin
.pin
.pinInfo
.achName
), pSample
);
2141 return avimuxin
->pin
.pFuncsTable
->pfnReceive(&avimuxin
->pin
, pSample
);
2144 static HRESULT WINAPI
AviMuxIn_MemInputPin_ReceiveMultiple(IMemInputPin
*iface
,
2145 IMediaSample
**pSamples
, LONG nSamples
, LONG
*nSamplesProcessed
)
2147 AviMuxIn
*avimuxin
= AviMuxIn_from_IMemInputPin(iface
);
2148 AviMux
*This
= impl_from_in_IPin(&avimuxin
->pin
.pin
.IPin_iface
);
2151 TRACE("(%p:%s)->(%p %d %p)\n", This
, debugstr_w(avimuxin
->pin
.pin
.pinInfo
.achName
),
2152 pSamples
, nSamples
, nSamplesProcessed
);
2154 for(*nSamplesProcessed
=0; *nSamplesProcessed
<nSamples
; (*nSamplesProcessed
)++)
2156 hr
= avimuxin
->pin
.pFuncsTable
->pfnReceive(&avimuxin
->pin
, pSamples
[*nSamplesProcessed
]);
2164 static HRESULT WINAPI
AviMuxIn_MemInputPin_ReceiveCanBlock(IMemInputPin
*iface
)
2166 AviMuxIn
*avimuxin
= AviMuxIn_from_IMemInputPin(iface
);
2167 AviMux
*This
= impl_from_in_IPin(&avimuxin
->pin
.pin
.IPin_iface
);
2170 TRACE("(%p:%s)\n", This
, debugstr_w(avimuxin
->pin
.pin
.pinInfo
.achName
));
2172 if(!This
->out
->pin
.pMemInputPin
)
2175 hr
= IMemInputPin_ReceiveCanBlock(This
->out
->pin
.pMemInputPin
);
2176 return hr
!= S_FALSE
? S_OK
: S_FALSE
;
2179 static const IMemInputPinVtbl AviMuxIn_MemInputPinVtbl
= {
2180 AviMuxIn_MemInputPin_QueryInterface
,
2181 AviMuxIn_MemInputPin_AddRef
,
2182 AviMuxIn_MemInputPin_Release
,
2183 AviMuxIn_MemInputPin_GetAllocator
,
2184 AviMuxIn_MemInputPin_NotifyAllocator
,
2185 AviMuxIn_MemInputPin_GetAllocatorRequirements
,
2186 AviMuxIn_MemInputPin_Receive
,
2187 AviMuxIn_MemInputPin_ReceiveMultiple
,
2188 AviMuxIn_MemInputPin_ReceiveCanBlock
2191 static inline AviMuxIn
* AviMuxIn_from_IPropertyBag(IPropertyBag
*iface
)
2193 return CONTAINING_RECORD(iface
, AviMuxIn
, IPropertyBag_iface
);
2196 static HRESULT WINAPI
AviMuxIn_PropertyBag_QueryInterface(
2197 IPropertyBag
*iface
, REFIID riid
, void **ppv
)
2199 AviMuxIn
*avimuxin
= AviMuxIn_from_IPropertyBag(iface
);
2200 return IPin_QueryInterface(&avimuxin
->pin
.pin
.IPin_iface
, riid
, ppv
);
2203 static ULONG WINAPI
AviMuxIn_PropertyBag_AddRef(IPropertyBag
*iface
)
2205 AviMuxIn
*avimuxin
= AviMuxIn_from_IPropertyBag(iface
);
2206 AviMux
*This
= impl_from_in_IPin(&avimuxin
->pin
.pin
.IPin_iface
);
2207 return IBaseFilter_AddRef(&This
->filter
.IBaseFilter_iface
);
2210 static ULONG WINAPI
AviMuxIn_PropertyBag_Release(IPropertyBag
*iface
)
2212 AviMuxIn
*avimuxin
= AviMuxIn_from_IPropertyBag(iface
);
2213 AviMux
*This
= impl_from_in_IPin(&avimuxin
->pin
.pin
.IPin_iface
);
2214 return IBaseFilter_Release(&This
->filter
.IBaseFilter_iface
);
2217 static HRESULT WINAPI
AviMuxIn_PropertyBag_Read(IPropertyBag
*iface
,
2218 LPCOLESTR pszPropName
, VARIANT
*pVar
, IErrorLog
*pErrorLog
)
2220 AviMuxIn
*avimuxin
= AviMuxIn_from_IPropertyBag(iface
);
2221 AviMux
*This
= impl_from_in_IPin(&avimuxin
->pin
.pin
.IPin_iface
);
2222 FIXME("(%p:%s)->(%s %p %p)\n", This
, debugstr_w(avimuxin
->pin
.pin
.pinInfo
.achName
),
2223 debugstr_w(pszPropName
), pVar
, pErrorLog
);
2227 static HRESULT WINAPI
AviMuxIn_PropertyBag_Write(IPropertyBag
*iface
,
2228 LPCOLESTR pszPropName
, VARIANT
*pVar
)
2230 AviMuxIn
*avimuxin
= AviMuxIn_from_IPropertyBag(iface
);
2231 AviMux
*This
= impl_from_in_IPin(&avimuxin
->pin
.pin
.IPin_iface
);
2232 FIXME("(%p:%s)->(%s %p)\n", This
, debugstr_w(avimuxin
->pin
.pin
.pinInfo
.achName
),
2233 debugstr_w(pszPropName
), pVar
);
2237 static const IPropertyBagVtbl AviMuxIn_PropertyBagVtbl
= {
2238 AviMuxIn_PropertyBag_QueryInterface
,
2239 AviMuxIn_PropertyBag_AddRef
,
2240 AviMuxIn_PropertyBag_Release
,
2241 AviMuxIn_PropertyBag_Read
,
2242 AviMuxIn_PropertyBag_Write
2245 static inline AviMuxIn
* AviMuxIn_from_IQualityControl(IQualityControl
*iface
)
2247 return CONTAINING_RECORD(iface
, AviMuxIn
, IQualityControl_iface
);
2250 static HRESULT WINAPI
AviMuxIn_QualityControl_QueryInterface(
2251 IQualityControl
*iface
, REFIID riid
, void **ppv
)
2253 AviMuxIn
*avimuxin
= AviMuxIn_from_IQualityControl(iface
);
2254 return IPin_QueryInterface(&avimuxin
->pin
.pin
.IPin_iface
, riid
, ppv
);
2257 static ULONG WINAPI
AviMuxIn_QualityControl_AddRef(IQualityControl
*iface
)
2259 AviMuxIn
*avimuxin
= AviMuxIn_from_IQualityControl(iface
);
2260 AviMux
*This
= impl_from_in_IPin(&avimuxin
->pin
.pin
.IPin_iface
);
2261 return IBaseFilter_AddRef(&This
->filter
.IBaseFilter_iface
);
2264 static ULONG WINAPI
AviMuxIn_QualityControl_Release(IQualityControl
*iface
)
2266 AviMuxIn
*avimuxin
= AviMuxIn_from_IQualityControl(iface
);
2267 AviMux
*This
= impl_from_in_IPin(&avimuxin
->pin
.pin
.IPin_iface
);
2268 return IBaseFilter_Release(&This
->filter
.IBaseFilter_iface
);
2271 static HRESULT WINAPI
AviMuxIn_QualityControl_Notify(IQualityControl
*iface
,
2272 IBaseFilter
*pSelf
, Quality q
)
2274 AviMuxIn
*avimuxin
= AviMuxIn_from_IQualityControl(iface
);
2275 AviMux
*This
= impl_from_in_IPin(&avimuxin
->pin
.pin
.IPin_iface
);
2276 FIXME("(%p:%s)->(%p Quality)\n", This
, debugstr_w(avimuxin
->pin
.pin
.pinInfo
.achName
), pSelf
);
2280 static HRESULT WINAPI
AviMuxIn_QualityControl_SetSink(
2281 IQualityControl
*iface
, IQualityControl
*piqc
)
2283 AviMuxIn
*avimuxin
= AviMuxIn_from_IQualityControl(iface
);
2284 AviMux
*This
= impl_from_in_IPin(&avimuxin
->pin
.pin
.IPin_iface
);
2285 FIXME("(%p:%s)->(%p)\n", This
, debugstr_w(avimuxin
->pin
.pin
.pinInfo
.achName
), piqc
);
2289 static const IQualityControlVtbl AviMuxIn_QualityControlVtbl
= {
2290 AviMuxIn_QualityControl_QueryInterface
,
2291 AviMuxIn_QualityControl_AddRef
,
2292 AviMuxIn_QualityControl_Release
,
2293 AviMuxIn_QualityControl_Notify
,
2294 AviMuxIn_QualityControl_SetSink
2297 static HRESULT
create_input_pin(AviMux
*avimux
)
2299 static const WCHAR name
[] = {'I','n','p','u','t',' ','0','0',0};
2303 if(avimux
->input_pin_no
>= MAX_PIN_NO
-1)
2306 info
.dir
= PINDIR_INPUT
;
2307 info
.pFilter
= &avimux
->filter
.IBaseFilter_iface
;
2308 memcpy(info
.achName
, name
, sizeof(name
));
2309 info
.achName
[7] = '0' + (avimux
->input_pin_no
+1) % 10;
2310 info
.achName
[6] = '0' + (avimux
->input_pin_no
+1) / 10;
2312 hr
= BaseInputPin_Construct(&AviMuxIn_PinVtbl
, sizeof(AviMuxIn
), &info
,
2313 &AviMuxIn_BaseInputFuncTable
, &avimux
->filter
.csFilter
, NULL
, (IPin
**)&avimux
->in
[avimux
->input_pin_no
]);
2316 avimux
->in
[avimux
->input_pin_no
]->pin
.IMemInputPin_iface
.lpVtbl
= &AviMuxIn_MemInputPinVtbl
;
2317 avimux
->in
[avimux
->input_pin_no
]->IAMStreamControl_iface
.lpVtbl
= &AviMuxIn_AMStreamControlVtbl
;
2318 avimux
->in
[avimux
->input_pin_no
]->IPropertyBag_iface
.lpVtbl
= &AviMuxIn_PropertyBagVtbl
;
2319 avimux
->in
[avimux
->input_pin_no
]->IQualityControl_iface
.lpVtbl
= &AviMuxIn_QualityControlVtbl
;
2321 avimux
->in
[avimux
->input_pin_no
]->samples_head
= NULL
;
2322 hr
= CoCreateInstance(&CLSID_MemoryAllocator
, NULL
, CLSCTX_INPROC_SERVER
,
2323 &IID_IMemAllocator
, (void**)&avimux
->in
[avimux
->input_pin_no
]->samples_allocator
);
2325 BaseInputPinImpl_Release(&avimux
->in
[avimux
->input_pin_no
]->pin
.pin
.IPin_iface
);
2329 hr
= CoCreateInstance(&CLSID_MemoryAllocator
, NULL
, CLSCTX_INPROC_SERVER
,
2330 &IID_IMemAllocator
, (void**)&avimux
->in
[avimux
->input_pin_no
]->pin
.pAllocator
);
2332 IMemAllocator_Release(avimux
->in
[avimux
->input_pin_no
]->samples_allocator
);
2333 BaseInputPinImpl_Release(&avimux
->in
[avimux
->input_pin_no
]->pin
.pin
.IPin_iface
);
2337 avimux
->in
[avimux
->input_pin_no
]->stream_time
= 0;
2338 memset(&avimux
->in
[avimux
->input_pin_no
]->strh
, 0, sizeof(avimux
->in
[avimux
->input_pin_no
]->strh
));
2339 avimux
->in
[avimux
->input_pin_no
]->strf
= NULL
;
2340 memset(&avimux
->in
[avimux
->input_pin_no
]->indx_data
, 0, sizeof(avimux
->in
[avimux
->input_pin_no
]->indx_data
));
2341 memset(&avimux
->in
[avimux
->input_pin_no
]->ix_data
, 0, sizeof(avimux
->in
[avimux
->input_pin_no
]->ix_data
));
2342 avimux
->in
[avimux
->input_pin_no
]->indx
= (AVISUPERINDEX
*)&avimux
->in
[avimux
->input_pin_no
]->indx_data
;
2343 avimux
->in
[avimux
->input_pin_no
]->ix
= (AVISTDINDEX
*)avimux
->in
[avimux
->input_pin_no
]->ix_data
;
2345 avimux
->input_pin_no
++;
2349 IUnknown
* WINAPI
QCAP_createAVIMux(IUnknown
*pUnkOuter
, HRESULT
*phr
)
2351 static const WCHAR output_name
[] = {'A','V','I',' ','O','u','t',0};
2357 TRACE("(%p)\n", pUnkOuter
);
2360 *phr
= CLASS_E_NOAGGREGATION
;
2364 avimux
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(AviMux
));
2366 *phr
= E_OUTOFMEMORY
;
2370 BaseFilter_Init(&avimux
->filter
, &AviMuxVtbl
, &CLSID_AviDest
,
2371 (DWORD_PTR
)(__FILE__
": AviMux.csFilter"), &filter_func_table
);
2372 avimux
->IConfigAviMux_iface
.lpVtbl
= &ConfigAviMuxVtbl
;
2373 avimux
->IConfigInterleaving_iface
.lpVtbl
= &ConfigInterleavingVtbl
;
2374 avimux
->IMediaSeeking_iface
.lpVtbl
= &MediaSeekingVtbl
;
2375 avimux
->IPersistMediaPropertyBag_iface
.lpVtbl
= &PersistMediaPropertyBagVtbl
;
2376 avimux
->ISpecifyPropertyPages_iface
.lpVtbl
= &SpecifyPropertyPagesVtbl
;
2378 info
.dir
= PINDIR_OUTPUT
;
2379 info
.pFilter
= &avimux
->filter
.IBaseFilter_iface
;
2380 lstrcpyW(info
.achName
, output_name
);
2381 hr
= BaseOutputPin_Construct(&AviMuxOut_PinVtbl
, sizeof(AviMuxOut
), &info
,
2382 &AviMuxOut_BaseOutputFuncTable
, &avimux
->filter
.csFilter
, (IPin
**)&avimux
->out
);
2384 BaseFilterImpl_Release(&avimux
->filter
.IBaseFilter_iface
);
2385 HeapFree(GetProcessHeap(), 0, avimux
);
2389 avimux
->out
->IQualityControl_iface
.lpVtbl
= &AviMuxOut_QualityControlVtbl
;
2390 avimux
->out
->cur_stream
= 0;
2391 avimux
->out
->cur_time
= 0;
2392 avimux
->out
->stream
= NULL
;
2394 hr
= create_input_pin(avimux
);
2396 BaseOutputPinImpl_Release(&avimux
->out
->pin
.pin
.IPin_iface
);
2397 BaseFilterImpl_Release(&avimux
->filter
.IBaseFilter_iface
);
2398 HeapFree(GetProcessHeap(), 0, avimux
);
2403 avimux
->interleave
= 10000000;
2405 ObjectRefCount(TRUE
);
2407 return (IUnknown
*)&avimux
->filter
.IBaseFilter_iface
;