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)->(%s)\n", This
, wine_dbgstr_longlong(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_CheckMediaType(BasePin
*base
, const AM_MEDIA_TYPE
*amt
)
1228 FIXME("(%p) stub\n", base
);
1232 static HRESULT WINAPI
AviMuxOut_AttemptConnection(BasePin
*base
,
1233 IPin
*pReceivePin
, const AM_MEDIA_TYPE
*pmt
)
1238 TRACE("(%p)->(%p AM_MEDIA_TYPE(%p))\n", base
, pReceivePin
, pmt
);
1239 dump_AM_MEDIA_TYPE(pmt
);
1241 hr
= IPin_QueryDirection(pReceivePin
, &dir
);
1242 if(hr
==S_OK
&& dir
!=PINDIR_INPUT
)
1243 return VFW_E_INVALID_DIRECTION
;
1245 return BaseOutputPinImpl_AttemptConnection(base
, pReceivePin
, pmt
);
1248 static LONG WINAPI
AviMuxOut_GetMediaTypeVersion(BasePin
*base
)
1253 static HRESULT WINAPI
AviMuxOut_GetMediaType(BasePin
*base
, int iPosition
, AM_MEDIA_TYPE
*amt
)
1255 TRACE("(%p)->(%d %p)\n", base
, iPosition
, amt
);
1258 return E_INVALIDARG
;
1260 return VFW_S_NO_MORE_ITEMS
;
1262 amt
->majortype
= MEDIATYPE_Stream
;
1263 amt
->subtype
= MEDIASUBTYPE_Avi
;
1264 amt
->bFixedSizeSamples
= TRUE
;
1265 amt
->bTemporalCompression
= FALSE
;
1266 amt
->lSampleSize
= 1;
1267 amt
->formattype
= GUID_NULL
;
1270 amt
->pbFormat
= NULL
;
1274 static HRESULT WINAPI
AviMuxOut_DecideAllocator(BaseOutputPin
*base
,
1275 IMemInputPin
*pPin
, IMemAllocator
**pAlloc
)
1277 ALLOCATOR_PROPERTIES req
, actual
;
1280 TRACE("(%p)->(%p %p)\n", base
, pPin
, pAlloc
);
1282 hr
= BaseOutputPinImpl_InitAllocator(base
, pAlloc
);
1286 hr
= IMemInputPin_GetAllocatorRequirements(pPin
, &req
);
1293 hr
= IMemAllocator_SetProperties(*pAlloc
, &req
, &actual
);
1297 return IMemInputPin_NotifyAllocator(pPin
, *pAlloc
, TRUE
);
1300 static HRESULT WINAPI
AviMuxOut_BreakConnect(BaseOutputPin
*base
)
1302 FIXME("(%p)\n", base
);
1306 static const BaseOutputPinFuncTable AviMuxOut_BaseOutputFuncTable
= {
1308 AviMuxOut_CheckMediaType
,
1309 AviMuxOut_AttemptConnection
,
1310 AviMuxOut_GetMediaTypeVersion
,
1311 AviMuxOut_GetMediaType
1314 AviMuxOut_DecideAllocator
,
1315 AviMuxOut_BreakConnect
1318 static inline AviMux
* impl_from_out_IPin(IPin
*iface
)
1320 BasePin
*bp
= CONTAINING_RECORD(iface
, BasePin
, IPin_iface
);
1321 IBaseFilter
*bf
= bp
->pinInfo
.pFilter
;
1323 return impl_from_IBaseFilter(bf
);
1326 static HRESULT WINAPI
AviMuxOut_QueryInterface(IPin
*iface
, REFIID riid
, void **ppv
)
1328 AviMux
*This
= impl_from_out_IPin(iface
);
1330 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), ppv
);
1332 if(IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IPin
))
1334 else if(IsEqualIID(riid
, &IID_IQualityControl
))
1335 *ppv
= &This
->out
->IQualityControl_iface
;
1337 FIXME("no interface for %s\n", debugstr_guid(riid
));
1339 return E_NOINTERFACE
;
1342 IUnknown_AddRef((IUnknown
*)*ppv
);
1346 static ULONG WINAPI
AviMuxOut_AddRef(IPin
*iface
)
1348 AviMux
*This
= impl_from_out_IPin(iface
);
1349 return IBaseFilter_AddRef(&This
->filter
.IBaseFilter_iface
);
1352 static ULONG WINAPI
AviMuxOut_Release(IPin
*iface
)
1354 AviMux
*This
= impl_from_out_IPin(iface
);
1355 return IBaseFilter_Release(&This
->filter
.IBaseFilter_iface
);
1358 static HRESULT WINAPI
AviMuxOut_Connect(IPin
*iface
,
1359 IPin
*pReceivePin
, const AM_MEDIA_TYPE
*pmt
)
1361 AviMux
*This
= impl_from_out_IPin(iface
);
1365 TRACE("(%p)->(%p AM_MEDIA_TYPE(%p))\n", This
, pReceivePin
, pmt
);
1366 dump_AM_MEDIA_TYPE(pmt
);
1368 hr
= BaseOutputPinImpl_Connect(iface
, pReceivePin
, pmt
);
1372 for(i
=0; i
<This
->input_pin_no
; i
++) {
1373 if(!This
->in
[i
]->pin
.pin
.pConnectedTo
)
1376 hr
= IFilterGraph_Reconnect(This
->filter
.filterInfo
.pGraph
, &This
->in
[i
]->pin
.pin
.IPin_iface
);
1378 BaseOutputPinImpl_Disconnect(iface
);
1384 IBaseFilter_AddRef(&This
->filter
.IBaseFilter_iface
);
1388 static HRESULT WINAPI
AviMuxOut_ReceiveConnection(IPin
*iface
,
1389 IPin
*pConnector
, const AM_MEDIA_TYPE
*pmt
)
1391 AviMux
*This
= impl_from_out_IPin(iface
);
1392 TRACE("(%p)->(%p AM_MEDIA_TYPE(%p)\n", This
, pConnector
, pmt
);
1393 dump_AM_MEDIA_TYPE(pmt
);
1394 return BaseOutputPinImpl_ReceiveConnection(iface
, pConnector
, pmt
);
1397 static HRESULT WINAPI
AviMuxOut_Disconnect(IPin
*iface
)
1399 AviMux
*This
= impl_from_out_IPin(iface
);
1402 TRACE("(%p)\n", This
);
1404 hr
= BaseOutputPinImpl_Disconnect(iface
);
1406 IBaseFilter_Release(&This
->filter
.IBaseFilter_iface
);
1410 static HRESULT WINAPI
AviMuxOut_ConnectedTo(IPin
*iface
, IPin
**pPin
)
1412 AviMux
*This
= impl_from_out_IPin(iface
);
1413 TRACE("(%p)->(%p)\n", This
, pPin
);
1414 return BasePinImpl_ConnectedTo(iface
, pPin
);
1417 static HRESULT WINAPI
AviMuxOut_ConnectionMediaType(IPin
*iface
, AM_MEDIA_TYPE
*pmt
)
1419 AviMux
*This
= impl_from_out_IPin(iface
);
1420 TRACE("(%p)->(%p)\n", This
, pmt
);
1421 return BasePinImpl_ConnectionMediaType(iface
, pmt
);
1424 static HRESULT WINAPI
AviMuxOut_QueryPinInfo(IPin
*iface
, PIN_INFO
*pInfo
)
1426 AviMux
*This
= impl_from_out_IPin(iface
);
1427 TRACE("(%p)->(%p)\n", This
, pInfo
);
1428 return BasePinImpl_QueryPinInfo(iface
, pInfo
);
1431 static HRESULT WINAPI
AviMuxOut_QueryDirection(IPin
*iface
, PIN_DIRECTION
*pPinDir
)
1433 AviMux
*This
= impl_from_out_IPin(iface
);
1434 TRACE("(%p)->(%p)\n", This
, pPinDir
);
1435 return BasePinImpl_QueryDirection(iface
, pPinDir
);
1438 static HRESULT WINAPI
AviMuxOut_QueryId(IPin
*iface
, LPWSTR
*Id
)
1440 AviMux
*This
= impl_from_out_IPin(iface
);
1441 TRACE("(%p)->(%p)\n", This
, Id
);
1442 return BasePinImpl_QueryId(iface
, Id
);
1445 static HRESULT WINAPI
AviMuxOut_QueryAccept(IPin
*iface
, const AM_MEDIA_TYPE
*pmt
)
1447 AviMux
*This
= impl_from_out_IPin(iface
);
1448 TRACE("(%p)->(AM_MEDIA_TYPE(%p))\n", This
, pmt
);
1449 dump_AM_MEDIA_TYPE(pmt
);
1450 return BasePinImpl_QueryAccept(iface
, pmt
);
1453 static HRESULT WINAPI
AviMuxOut_EnumMediaTypes(IPin
*iface
, IEnumMediaTypes
**ppEnum
)
1455 AviMux
*This
= impl_from_out_IPin(iface
);
1456 TRACE("(%p)->(%p)\n", This
, ppEnum
);
1457 return BasePinImpl_EnumMediaTypes(iface
, ppEnum
);
1460 static HRESULT WINAPI
AviMuxOut_QueryInternalConnections(
1461 IPin
*iface
, IPin
**apPin
, ULONG
*nPin
)
1463 AviMux
*This
= impl_from_out_IPin(iface
);
1464 FIXME("(%p)->(%p %p)\n", This
, apPin
, nPin
);
1468 static HRESULT WINAPI
AviMuxOut_EndOfStream(IPin
*iface
)
1470 AviMux
*This
= impl_from_out_IPin(iface
);
1471 TRACE("(%p)\n", This
);
1472 return BaseOutputPinImpl_EndOfStream(iface
);
1475 static HRESULT WINAPI
AviMuxOut_BeginFlush(IPin
*iface
)
1477 AviMux
*This
= impl_from_out_IPin(iface
);
1478 TRACE("(%p)\n", This
);
1479 return BaseOutputPinImpl_BeginFlush(iface
);
1482 static HRESULT WINAPI
AviMuxOut_EndFlush(IPin
*iface
)
1484 AviMux
*This
= impl_from_out_IPin(iface
);
1485 TRACE("(%p)\n", This
);
1486 return BaseOutputPinImpl_EndFlush(iface
);
1489 static HRESULT WINAPI
AviMuxOut_NewSegment(IPin
*iface
, REFERENCE_TIME tStart
,
1490 REFERENCE_TIME tStop
, double dRate
)
1492 AviMux
*This
= impl_from_out_IPin(iface
);
1493 TRACE("(%p)->(%s %s %f)\n", This
, wine_dbgstr_longlong(tStart
), wine_dbgstr_longlong(tStop
), dRate
);
1494 return BasePinImpl_NewSegment(iface
, tStart
, tStop
, dRate
);
1497 static const IPinVtbl AviMuxOut_PinVtbl
= {
1498 AviMuxOut_QueryInterface
,
1502 AviMuxOut_ReceiveConnection
,
1503 AviMuxOut_Disconnect
,
1504 AviMuxOut_ConnectedTo
,
1505 AviMuxOut_ConnectionMediaType
,
1506 AviMuxOut_QueryPinInfo
,
1507 AviMuxOut_QueryDirection
,
1509 AviMuxOut_QueryAccept
,
1510 AviMuxOut_EnumMediaTypes
,
1511 AviMuxOut_QueryInternalConnections
,
1512 AviMuxOut_EndOfStream
,
1513 AviMuxOut_BeginFlush
,
1515 AviMuxOut_NewSegment
1518 static inline AviMux
* impl_from_out_IQualityControl(IQualityControl
*iface
)
1520 AviMuxOut
*amo
= CONTAINING_RECORD(iface
, AviMuxOut
, IQualityControl_iface
);
1521 return impl_from_IBaseFilter(amo
->pin
.pin
.pinInfo
.pFilter
);
1524 static HRESULT WINAPI
AviMuxOut_QualityControl_QueryInterface(
1525 IQualityControl
*iface
, REFIID riid
, void **ppv
)
1527 AviMux
*This
= impl_from_out_IQualityControl(iface
);
1528 return IPin_QueryInterface(&This
->out
->pin
.pin
.IPin_iface
, riid
, ppv
);
1531 static ULONG WINAPI
AviMuxOut_QualityControl_AddRef(IQualityControl
*iface
)
1533 AviMux
*This
= impl_from_out_IQualityControl(iface
);
1534 return IBaseFilter_AddRef(&This
->filter
.IBaseFilter_iface
);
1537 static ULONG WINAPI
AviMuxOut_QualityControl_Release(IQualityControl
*iface
)
1539 AviMux
*This
= impl_from_out_IQualityControl(iface
);
1540 return IBaseFilter_Release(&This
->filter
.IBaseFilter_iface
);
1543 static HRESULT WINAPI
AviMuxOut_QualityControl_Notify(IQualityControl
*iface
,
1544 IBaseFilter
*pSelf
, Quality q
)
1546 AviMux
*This
= impl_from_out_IQualityControl(iface
);
1547 FIXME("(%p)->(%p { 0x%x %u %s %s })\n", This
, pSelf
,
1548 q
.Type
, q
.Proportion
,
1549 wine_dbgstr_longlong(q
.Late
),
1550 wine_dbgstr_longlong(q
.TimeStamp
));
1554 static HRESULT WINAPI
AviMuxOut_QualityControl_SetSink(
1555 IQualityControl
*iface
, IQualityControl
*piqc
)
1557 AviMux
*This
= impl_from_out_IQualityControl(iface
);
1558 FIXME("(%p)->(%p)\n", This
, piqc
);
1562 static const IQualityControlVtbl AviMuxOut_QualityControlVtbl
= {
1563 AviMuxOut_QualityControl_QueryInterface
,
1564 AviMuxOut_QualityControl_AddRef
,
1565 AviMuxOut_QualityControl_Release
,
1566 AviMuxOut_QualityControl_Notify
,
1567 AviMuxOut_QualityControl_SetSink
1570 static HRESULT WINAPI
AviMuxIn_CheckMediaType(BasePin
*base
, const AM_MEDIA_TYPE
*pmt
)
1572 TRACE("(%p:%s)->(AM_MEDIA_TYPE(%p))\n", base
, debugstr_w(base
->pinInfo
.achName
), pmt
);
1573 dump_AM_MEDIA_TYPE(pmt
);
1575 if(IsEqualIID(&pmt
->majortype
, &MEDIATYPE_Audio
) &&
1576 IsEqualIID(&pmt
->formattype
, &FORMAT_WaveFormatEx
))
1578 if(IsEqualIID(&pmt
->majortype
, &MEDIATYPE_Interleaved
) &&
1579 IsEqualIID(&pmt
->formattype
, &FORMAT_DvInfo
))
1581 if(IsEqualIID(&pmt
->majortype
, &MEDIATYPE_Video
) &&
1582 (IsEqualIID(&pmt
->formattype
, &FORMAT_VideoInfo
) ||
1583 IsEqualIID(&pmt
->formattype
, &FORMAT_DvInfo
)))
1588 static LONG WINAPI
AviMuxIn_GetMediaTypeVersion(BasePin
*base
)
1593 static HRESULT WINAPI
AviMuxIn_GetMediaType(BasePin
*base
, int iPosition
, AM_MEDIA_TYPE
*amt
)
1598 static HRESULT WINAPI
AviMuxIn_Receive(BaseInputPin
*base
, IMediaSample
*pSample
)
1600 AviMuxIn
*avimuxin
= CONTAINING_RECORD(base
, AviMuxIn
, pin
);
1601 AviMux
*avimux
= impl_from_IBaseFilter(base
->pin
.pinInfo
.pFilter
);
1602 REFERENCE_TIME start
, stop
;
1603 IMediaSample
*sample
;
1607 DWORD max_size
, size
;
1611 TRACE("(%p:%s)->(%p)\n", base
, debugstr_w(base
->pin
.pinInfo
.achName
), pSample
);
1613 hr
= IMediaSample_QueryInterface(pSample
, &IID_IMediaSample2
, (void**)&ms2
);
1615 AM_SAMPLE2_PROPERTIES props
;
1617 memset(&props
, 0, sizeof(props
));
1618 hr
= IMediaSample2_GetProperties(ms2
, sizeof(props
), (BYTE
*)&props
);
1619 IMediaSample2_Release(ms2
);
1623 flags
= props
.dwSampleFlags
;
1624 frame
= props
.pbBuffer
;
1625 size
= props
.lActual
;
1627 flags
= IMediaSample_IsSyncPoint(pSample
) == S_OK
? AM_SAMPLE_SPLICEPOINT
: 0;
1628 hr
= IMediaSample_GetPointer(pSample
, &frame
);
1631 size
= IMediaSample_GetActualDataLength(pSample
);
1634 if(!avimuxin
->pin
.pin
.mtCurrent
.bTemporalCompression
)
1635 flags
|= AM_SAMPLE_SPLICEPOINT
;
1637 hr
= IMediaSample_GetTime(pSample
, &start
, &stop
);
1641 if(avimuxin
->stop
>stop
)
1642 return VFW_E_START_TIME_AFTER_END
;
1644 if(avimux
->start
== -1)
1645 avimux
->start
= start
;
1646 if(avimux
->stop
< stop
)
1647 avimux
->stop
= stop
;
1649 if(avimux
->avih
.dwSuggestedBufferSize
< ALIGN(size
)+sizeof(RIFFCHUNK
))
1650 avimux
->avih
.dwSuggestedBufferSize
= ALIGN(size
) + sizeof(RIFFCHUNK
);
1651 if(avimuxin
->strh
.dwSuggestedBufferSize
< ALIGN(size
)+sizeof(RIFFCHUNK
))
1652 avimuxin
->strh
.dwSuggestedBufferSize
= ALIGN(size
) + sizeof(RIFFCHUNK
);
1655 if(avimuxin
->stop
!=-1 && start
> avimuxin
->stop
) {
1656 frames_no
+= (double)(start
- avimuxin
->stop
) / 10000000
1657 * avimuxin
->strh
.dwRate
/ avimuxin
->strh
.dwScale
+ 0.5;
1659 avimuxin
->stop
= stop
;
1661 while(--frames_no
) {
1662 /* TODO: store all control frames in one buffer */
1663 hr
= IMemAllocator_GetBuffer(avimuxin
->samples_allocator
, &sample
, NULL
, NULL
, 0);
1666 hr
= IMediaSample_SetActualDataLength(sample
, 0);
1668 hr
= IMediaSample_SetDiscontinuity(sample
, TRUE
);
1670 hr
= IMediaSample_SetSyncPoint(sample
, FALSE
);
1672 hr
= queue_sample(avimux
, avimuxin
, sample
);
1673 IMediaSample_Release(sample
);
1678 hr
= IMemAllocator_GetBuffer(avimuxin
->samples_allocator
, &sample
, NULL
, NULL
, 0);
1681 max_size
= IMediaSample_GetSize(sample
);
1684 hr
= IMediaSample_SetActualDataLength(sample
, size
);
1686 hr
= IMediaSample_SetDiscontinuity(sample
, FALSE
);
1688 hr
= IMediaSample_SetSyncPoint(sample
, flags
& AM_SAMPLE_SPLICEPOINT
);
1689 /* TODO: avoid unnecessary copying */
1691 hr
= IMediaSample_GetPointer(sample
, &buf
);
1693 memcpy(buf
, frame
, size
);
1694 hr
= queue_sample(avimux
, avimuxin
, sample
);
1696 IMediaSample_Release(sample
);
1701 static const BaseInputPinFuncTable AviMuxIn_BaseInputFuncTable
= {
1703 AviMuxIn_CheckMediaType
,
1705 AviMuxIn_GetMediaTypeVersion
,
1706 AviMuxIn_GetMediaType
1711 static inline AviMux
* impl_from_in_IPin(IPin
*iface
)
1713 BasePin
*bp
= CONTAINING_RECORD(iface
, BasePin
, IPin_iface
);
1714 IBaseFilter
*bf
= bp
->pinInfo
.pFilter
;
1716 return impl_from_IBaseFilter(bf
);
1719 static inline AviMuxIn
* AviMuxIn_from_IPin(IPin
*iface
)
1721 BasePin
*bp
= CONTAINING_RECORD(iface
, BasePin
, IPin_iface
);
1722 BaseInputPin
*bip
= CONTAINING_RECORD(bp
, BaseInputPin
, pin
);
1723 return CONTAINING_RECORD(bip
, AviMuxIn
, pin
);
1726 static HRESULT WINAPI
AviMuxIn_QueryInterface(IPin
*iface
, REFIID riid
, void **ppv
)
1728 AviMux
*This
= impl_from_in_IPin(iface
);
1729 AviMuxIn
*avimuxin
= AviMuxIn_from_IPin(iface
);
1731 TRACE("(%p:%s)->(%s %p)\n", This
, debugstr_w(avimuxin
->pin
.pin
.pinInfo
.achName
),
1732 debugstr_guid(riid
), ppv
);
1734 if(IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IPin
))
1735 *ppv
= &avimuxin
->pin
.pin
.IPin_iface
;
1736 else if(IsEqualIID(riid
, &IID_IAMStreamControl
))
1737 *ppv
= &avimuxin
->IAMStreamControl_iface
;
1738 else if(IsEqualIID(riid
, &IID_IMemInputPin
))
1739 *ppv
= &avimuxin
->pin
.IMemInputPin_iface
;
1740 else if(IsEqualIID(riid
, &IID_IPropertyBag
))
1741 *ppv
= &avimuxin
->IPropertyBag_iface
;
1742 else if(IsEqualIID(riid
, &IID_IQualityControl
))
1743 *ppv
= &avimuxin
->IQualityControl_iface
;
1745 FIXME("no interface for %s\n", debugstr_guid(riid
));
1747 return E_NOINTERFACE
;
1750 IUnknown_AddRef((IUnknown
*)*ppv
);
1754 static ULONG WINAPI
AviMuxIn_AddRef(IPin
*iface
)
1756 AviMux
*This
= impl_from_in_IPin(iface
);
1757 return IBaseFilter_AddRef(&This
->filter
.IBaseFilter_iface
);
1760 static ULONG WINAPI
AviMuxIn_Release(IPin
*iface
)
1762 AviMux
*This
= impl_from_in_IPin(iface
);
1763 return IBaseFilter_Release(&This
->filter
.IBaseFilter_iface
);
1766 static HRESULT WINAPI
AviMuxIn_Connect(IPin
*iface
,
1767 IPin
*pReceivePin
, const AM_MEDIA_TYPE
*pmt
)
1769 AviMux
*This
= impl_from_in_IPin(iface
);
1770 AviMuxIn
*avimuxin
= AviMuxIn_from_IPin(iface
);
1771 TRACE("(%p:%s)->(%p AM_MEDIA_TYPE(%p))\n", This
,
1772 debugstr_w(avimuxin
->pin
.pin
.pinInfo
.achName
), pReceivePin
, pmt
);
1773 dump_AM_MEDIA_TYPE(pmt
);
1774 return BaseInputPinImpl_Connect(iface
, pReceivePin
, pmt
);
1777 static HRESULT WINAPI
AviMuxIn_ReceiveConnection(IPin
*iface
,
1778 IPin
*pConnector
, const AM_MEDIA_TYPE
*pmt
)
1780 AviMux
*This
= impl_from_in_IPin(iface
);
1781 AviMuxIn
*avimuxin
= AviMuxIn_from_IPin(iface
);
1784 TRACE("(%p:%s)->(%p AM_MEDIA_TYPE(%p))\n", This
,
1785 debugstr_w(avimuxin
->pin
.pin
.pinInfo
.achName
), pConnector
, pmt
);
1786 dump_AM_MEDIA_TYPE(pmt
);
1791 hr
= BaseInputPinImpl_ReceiveConnection(iface
, pConnector
, pmt
);
1795 if(IsEqualIID(&pmt
->majortype
, &MEDIATYPE_Video
) &&
1796 IsEqualIID(&pmt
->formattype
, &FORMAT_VideoInfo
)) {
1797 ALLOCATOR_PROPERTIES req
, act
;
1798 VIDEOINFOHEADER
*vih
;
1801 vih
= (VIDEOINFOHEADER
*)pmt
->pbFormat
;
1802 avimuxin
->strh
.fcc
= ckidSTREAMHEADER
;
1803 avimuxin
->strh
.cb
= sizeof(AVISTREAMHEADER
) - FIELD_OFFSET(AVISTREAMHEADER
, fccType
);
1804 avimuxin
->strh
.fccType
= streamtypeVIDEO
;
1805 /* FIXME: fccHandler should be set differently */
1806 avimuxin
->strh
.fccHandler
= vih
->bmiHeader
.biCompression
?
1807 vih
->bmiHeader
.biCompression
: FCC('D','I','B',' ');
1808 avimuxin
->avg_time_per_frame
= vih
->AvgTimePerFrame
;
1809 avimuxin
->stop
= -1;
1812 req
.cbBuffer
= vih
->bmiHeader
.biSizeImage
;
1814 req
.cbPrefix
= sizeof(void*);
1815 hr
= IMemAllocator_SetProperties(avimuxin
->samples_allocator
, &req
, &act
);
1817 hr
= IMemAllocator_Commit(avimuxin
->samples_allocator
);
1819 BasePinImpl_Disconnect(iface
);
1823 size
= pmt
->cbFormat
- FIELD_OFFSET(VIDEOINFOHEADER
, bmiHeader
);
1824 avimuxin
->strf
= CoTaskMemAlloc(sizeof(RIFFCHUNK
) + ALIGN(FIELD_OFFSET(BITMAPINFO
, bmiColors
[vih
->bmiHeader
.biClrUsed
])));
1825 avimuxin
->strf
->fcc
= ckidSTREAMFORMAT
;
1826 avimuxin
->strf
->cb
= FIELD_OFFSET(BITMAPINFO
, bmiColors
[vih
->bmiHeader
.biClrUsed
]);
1827 if(size
> avimuxin
->strf
->cb
)
1828 size
= avimuxin
->strf
->cb
;
1829 memcpy(avimuxin
->strf
->data
, &vih
->bmiHeader
, size
);
1831 FIXME("format not supported: %s %s\n", debugstr_guid(&pmt
->majortype
),
1832 debugstr_guid(&pmt
->formattype
));
1836 return create_input_pin(This
);
1839 static HRESULT WINAPI
AviMuxIn_Disconnect(IPin
*iface
)
1841 AviMux
*This
= impl_from_in_IPin(iface
);
1842 AviMuxIn
*avimuxin
= AviMuxIn_from_IPin(iface
);
1843 IMediaSample
**prev
, *cur
;
1846 TRACE("(%p:%s)\n", This
, debugstr_w(avimuxin
->pin
.pin
.pinInfo
.achName
));
1848 hr
= BasePinImpl_Disconnect(iface
);
1852 IMemAllocator_Decommit(avimuxin
->samples_allocator
);
1853 while(avimuxin
->samples_head
) {
1854 cur
= avimuxin
->samples_head
;
1855 hr
= IMediaSample_GetPointer(cur
, (BYTE
**)&prev
);
1860 cur
= avimuxin
->samples_head
;
1861 avimuxin
->samples_head
= *prev
;
1862 IMediaSample_Release(cur
);
1864 if(cur
== avimuxin
->samples_head
)
1865 avimuxin
->samples_head
= NULL
;
1867 CoTaskMemFree(avimuxin
->strf
);
1868 avimuxin
->strf
= NULL
;
1872 static HRESULT WINAPI
AviMuxIn_ConnectedTo(IPin
*iface
, IPin
**pPin
)
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
), pPin
);
1877 return BasePinImpl_ConnectedTo(iface
, pPin
);
1880 static HRESULT WINAPI
AviMuxIn_ConnectionMediaType(IPin
*iface
, AM_MEDIA_TYPE
*pmt
)
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
), pmt
);
1885 return BasePinImpl_ConnectionMediaType(iface
, pmt
);
1888 static HRESULT WINAPI
AviMuxIn_QueryPinInfo(IPin
*iface
, PIN_INFO
*pInfo
)
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
), pInfo
);
1893 return BasePinImpl_QueryPinInfo(iface
, pInfo
);
1896 static HRESULT WINAPI
AviMuxIn_QueryDirection(IPin
*iface
, PIN_DIRECTION
*pPinDir
)
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
), pPinDir
);
1901 return BasePinImpl_QueryDirection(iface
, pPinDir
);
1904 static HRESULT WINAPI
AviMuxIn_QueryId(IPin
*iface
, LPWSTR
*Id
)
1906 AviMux
*This
= impl_from_in_IPin(iface
);
1907 AviMuxIn
*avimuxin
= AviMuxIn_from_IPin(iface
);
1908 TRACE("(%p:%s)->(%p)\n", This
, debugstr_w(avimuxin
->pin
.pin
.pinInfo
.achName
), Id
);
1909 return BasePinImpl_QueryId(iface
, Id
);
1912 static HRESULT WINAPI
AviMuxIn_QueryAccept(IPin
*iface
, const AM_MEDIA_TYPE
*pmt
)
1914 AviMux
*This
= impl_from_in_IPin(iface
);
1915 AviMuxIn
*avimuxin
= AviMuxIn_from_IPin(iface
);
1916 TRACE("(%p:%s)->(AM_MEDIA_TYPE(%p))\n", This
,
1917 debugstr_w(avimuxin
->pin
.pin
.pinInfo
.achName
), pmt
);
1918 dump_AM_MEDIA_TYPE(pmt
);
1919 return BasePinImpl_QueryAccept(iface
, pmt
);
1922 static HRESULT WINAPI
AviMuxIn_EnumMediaTypes(IPin
*iface
, IEnumMediaTypes
**ppEnum
)
1924 AviMux
*This
= impl_from_in_IPin(iface
);
1925 AviMuxIn
*avimuxin
= AviMuxIn_from_IPin(iface
);
1926 TRACE("(%p:%s)->(%p)\n", This
, debugstr_w(avimuxin
->pin
.pin
.pinInfo
.achName
), ppEnum
);
1927 return BasePinImpl_EnumMediaTypes(iface
, ppEnum
);
1930 static HRESULT WINAPI
AviMuxIn_QueryInternalConnections(
1931 IPin
*iface
, IPin
**apPin
, ULONG
*nPin
)
1933 AviMux
*This
= impl_from_in_IPin(iface
);
1934 AviMuxIn
*avimuxin
= AviMuxIn_from_IPin(iface
);
1935 TRACE("(%p:%s)->(%p %p)\n", This
, debugstr_w(avimuxin
->pin
.pin
.pinInfo
.achName
), apPin
, nPin
);
1936 return BasePinImpl_QueryInternalConnections(iface
, apPin
, nPin
);
1939 static HRESULT WINAPI
AviMuxIn_EndOfStream(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_EndOfStream(iface
);
1947 static HRESULT WINAPI
AviMuxIn_BeginFlush(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_BeginFlush(iface
);
1955 static HRESULT WINAPI
AviMuxIn_EndFlush(IPin
*iface
)
1957 AviMux
*This
= impl_from_in_IPin(iface
);
1958 AviMuxIn
*avimuxin
= AviMuxIn_from_IPin(iface
);
1959 TRACE("(%p:%s)\n", This
, debugstr_w(avimuxin
->pin
.pin
.pinInfo
.achName
));
1960 return BaseInputPinImpl_EndFlush(iface
);
1963 static HRESULT WINAPI
AviMuxIn_NewSegment(IPin
*iface
, REFERENCE_TIME tStart
,
1964 REFERENCE_TIME tStop
, double dRate
)
1966 AviMux
*This
= impl_from_in_IPin(iface
);
1967 AviMuxIn
*avimuxin
= AviMuxIn_from_IPin(iface
);
1968 TRACE("(%p:%s)->(%s %s %f)\n", This
, debugstr_w(avimuxin
->pin
.pin
.pinInfo
.achName
),
1969 wine_dbgstr_longlong(tStart
), wine_dbgstr_longlong(tStop
), dRate
);
1970 return BasePinImpl_NewSegment(iface
, tStart
, tStop
, dRate
);
1973 static const IPinVtbl AviMuxIn_PinVtbl
= {
1974 AviMuxIn_QueryInterface
,
1978 AviMuxIn_ReceiveConnection
,
1979 AviMuxIn_Disconnect
,
1980 AviMuxIn_ConnectedTo
,
1981 AviMuxIn_ConnectionMediaType
,
1982 AviMuxIn_QueryPinInfo
,
1983 AviMuxIn_QueryDirection
,
1985 AviMuxIn_QueryAccept
,
1986 AviMuxIn_EnumMediaTypes
,
1987 AviMuxIn_QueryInternalConnections
,
1988 AviMuxIn_EndOfStream
,
1989 AviMuxIn_BeginFlush
,
1994 static inline AviMuxIn
* AviMuxIn_from_IAMStreamControl(IAMStreamControl
*iface
)
1996 return CONTAINING_RECORD(iface
, AviMuxIn
, IAMStreamControl_iface
);
1999 static HRESULT WINAPI
AviMuxIn_AMStreamControl_QueryInterface(
2000 IAMStreamControl
*iface
, REFIID riid
, void **ppv
)
2002 AviMuxIn
*avimuxin
= AviMuxIn_from_IAMStreamControl(iface
);
2003 return IPin_QueryInterface(&avimuxin
->pin
.pin
.IPin_iface
, riid
, ppv
);
2006 static ULONG WINAPI
AviMuxIn_AMStreamControl_AddRef(IAMStreamControl
*iface
)
2008 AviMuxIn
*avimuxin
= AviMuxIn_from_IAMStreamControl(iface
);
2009 AviMux
*This
= impl_from_in_IPin(&avimuxin
->pin
.pin
.IPin_iface
);
2010 return IBaseFilter_AddRef(&This
->filter
.IBaseFilter_iface
);
2013 static ULONG WINAPI
AviMuxIn_AMStreamControl_Release(IAMStreamControl
*iface
)
2015 AviMuxIn
*avimuxin
= AviMuxIn_from_IAMStreamControl(iface
);
2016 AviMux
*This
= impl_from_in_IPin(&avimuxin
->pin
.pin
.IPin_iface
);
2017 return IBaseFilter_Release(&This
->filter
.IBaseFilter_iface
);
2020 static HRESULT WINAPI
AviMuxIn_AMStreamControl_StartAt(IAMStreamControl
*iface
,
2021 const REFERENCE_TIME
*ptStart
, DWORD dwCookie
)
2023 AviMuxIn
*avimuxin
= AviMuxIn_from_IAMStreamControl(iface
);
2024 AviMux
*This
= impl_from_in_IPin(&avimuxin
->pin
.pin
.IPin_iface
);
2025 FIXME("(%p:%s)->(%p %x)\n", This
,
2026 debugstr_w(avimuxin
->pin
.pin
.pinInfo
.achName
), ptStart
, dwCookie
);
2030 static HRESULT WINAPI
AviMuxIn_AMStreamControl_StopAt(IAMStreamControl
*iface
,
2031 const REFERENCE_TIME
*ptStop
, BOOL bSendExtra
, DWORD dwCookie
)
2033 AviMuxIn
*avimuxin
= AviMuxIn_from_IAMStreamControl(iface
);
2034 AviMux
*This
= impl_from_in_IPin(&avimuxin
->pin
.pin
.IPin_iface
);
2035 FIXME("(%p:%s)->(%p %x %x)\n", This
, debugstr_w(avimuxin
->pin
.pin
.pinInfo
.achName
),
2036 ptStop
, bSendExtra
, dwCookie
);
2040 static HRESULT WINAPI
AviMuxIn_AMStreamControl_GetInfo(
2041 IAMStreamControl
*iface
, AM_STREAM_INFO
*pInfo
)
2043 AviMuxIn
*avimuxin
= AviMuxIn_from_IAMStreamControl(iface
);
2044 AviMux
*This
= impl_from_in_IPin(&avimuxin
->pin
.pin
.IPin_iface
);
2045 FIXME("(%p:%s)->(%p)\n", This
, debugstr_w(avimuxin
->pin
.pin
.pinInfo
.achName
), pInfo
);
2049 static const IAMStreamControlVtbl AviMuxIn_AMStreamControlVtbl
= {
2050 AviMuxIn_AMStreamControl_QueryInterface
,
2051 AviMuxIn_AMStreamControl_AddRef
,
2052 AviMuxIn_AMStreamControl_Release
,
2053 AviMuxIn_AMStreamControl_StartAt
,
2054 AviMuxIn_AMStreamControl_StopAt
,
2055 AviMuxIn_AMStreamControl_GetInfo
2058 static inline AviMuxIn
* AviMuxIn_from_IMemInputPin(IMemInputPin
*iface
)
2060 BaseInputPin
*bip
= CONTAINING_RECORD(iface
, BaseInputPin
, IMemInputPin_iface
);
2061 return CONTAINING_RECORD(bip
, AviMuxIn
, pin
);
2064 static HRESULT WINAPI
AviMuxIn_MemInputPin_QueryInterface(
2065 IMemInputPin
*iface
, REFIID riid
, void **ppv
)
2067 AviMuxIn
*avimuxin
= AviMuxIn_from_IMemInputPin(iface
);
2068 return IPin_QueryInterface(&avimuxin
->pin
.pin
.IPin_iface
, riid
, ppv
);
2071 static ULONG WINAPI
AviMuxIn_MemInputPin_AddRef(IMemInputPin
*iface
)
2073 AviMuxIn
*avimuxin
= AviMuxIn_from_IMemInputPin(iface
);
2074 AviMux
*This
= impl_from_in_IPin(&avimuxin
->pin
.pin
.IPin_iface
);
2075 return IBaseFilter_AddRef(&This
->filter
.IBaseFilter_iface
);
2078 static ULONG WINAPI
AviMuxIn_MemInputPin_Release(IMemInputPin
*iface
)
2080 AviMuxIn
*avimuxin
= AviMuxIn_from_IMemInputPin(iface
);
2081 AviMux
*This
= impl_from_in_IPin(&avimuxin
->pin
.pin
.IPin_iface
);
2082 return IBaseFilter_Release(&This
->filter
.IBaseFilter_iface
);
2085 static HRESULT WINAPI
AviMuxIn_MemInputPin_GetAllocator(
2086 IMemInputPin
*iface
, IMemAllocator
**ppAllocator
)
2088 AviMuxIn
*avimuxin
= AviMuxIn_from_IMemInputPin(iface
);
2089 AviMux
*This
= impl_from_in_IPin(&avimuxin
->pin
.pin
.IPin_iface
);
2091 TRACE("(%p:%s)->(%p)\n", This
, debugstr_w(avimuxin
->pin
.pin
.pinInfo
.achName
), ppAllocator
);
2096 IMemAllocator_AddRef(avimuxin
->pin
.pAllocator
);
2097 *ppAllocator
= avimuxin
->pin
.pAllocator
;
2101 static HRESULT WINAPI
AviMuxIn_MemInputPin_NotifyAllocator(
2102 IMemInputPin
*iface
, IMemAllocator
*pAllocator
, BOOL bReadOnly
)
2104 AviMuxIn
*avimuxin
= AviMuxIn_from_IMemInputPin(iface
);
2105 AviMux
*This
= impl_from_in_IPin(&avimuxin
->pin
.pin
.IPin_iface
);
2106 ALLOCATOR_PROPERTIES props
;
2109 TRACE("(%p:%s)->(%p %x)\n", This
, debugstr_w(avimuxin
->pin
.pin
.pinInfo
.achName
),
2110 pAllocator
, bReadOnly
);
2115 memset(&props
, 0, sizeof(props
));
2116 hr
= IMemAllocator_GetProperties(pAllocator
, &props
);
2122 return IMemAllocator_SetProperties(avimuxin
->pin
.pAllocator
, &props
, &props
);
2125 static HRESULT WINAPI
AviMuxIn_MemInputPin_GetAllocatorRequirements(
2126 IMemInputPin
*iface
, ALLOCATOR_PROPERTIES
*pProps
)
2128 AviMuxIn
*avimuxin
= AviMuxIn_from_IMemInputPin(iface
);
2129 AviMux
*This
= impl_from_in_IPin(&avimuxin
->pin
.pin
.IPin_iface
);
2131 TRACE("(%p:%s)->(%p)\n", This
, debugstr_w(avimuxin
->pin
.pin
.pinInfo
.achName
), pProps
);
2136 pProps
->cbAlign
= 1;
2137 pProps
->cbPrefix
= 8;
2141 static HRESULT WINAPI
AviMuxIn_MemInputPin_Receive(
2142 IMemInputPin
*iface
, IMediaSample
*pSample
)
2144 AviMuxIn
*avimuxin
= AviMuxIn_from_IMemInputPin(iface
);
2145 AviMux
*This
= impl_from_in_IPin(&avimuxin
->pin
.pin
.IPin_iface
);
2147 TRACE("(%p:%s)->(%p)\n", This
, debugstr_w(avimuxin
->pin
.pin
.pinInfo
.achName
), pSample
);
2149 return avimuxin
->pin
.pFuncsTable
->pfnReceive(&avimuxin
->pin
, pSample
);
2152 static HRESULT WINAPI
AviMuxIn_MemInputPin_ReceiveMultiple(IMemInputPin
*iface
,
2153 IMediaSample
**pSamples
, LONG nSamples
, LONG
*nSamplesProcessed
)
2155 AviMuxIn
*avimuxin
= AviMuxIn_from_IMemInputPin(iface
);
2156 AviMux
*This
= impl_from_in_IPin(&avimuxin
->pin
.pin
.IPin_iface
);
2159 TRACE("(%p:%s)->(%p %d %p)\n", This
, debugstr_w(avimuxin
->pin
.pin
.pinInfo
.achName
),
2160 pSamples
, nSamples
, nSamplesProcessed
);
2162 for(*nSamplesProcessed
=0; *nSamplesProcessed
<nSamples
; (*nSamplesProcessed
)++)
2164 hr
= avimuxin
->pin
.pFuncsTable
->pfnReceive(&avimuxin
->pin
, pSamples
[*nSamplesProcessed
]);
2172 static HRESULT WINAPI
AviMuxIn_MemInputPin_ReceiveCanBlock(IMemInputPin
*iface
)
2174 AviMuxIn
*avimuxin
= AviMuxIn_from_IMemInputPin(iface
);
2175 AviMux
*This
= impl_from_in_IPin(&avimuxin
->pin
.pin
.IPin_iface
);
2178 TRACE("(%p:%s)\n", This
, debugstr_w(avimuxin
->pin
.pin
.pinInfo
.achName
));
2180 if(!This
->out
->pin
.pMemInputPin
)
2183 hr
= IMemInputPin_ReceiveCanBlock(This
->out
->pin
.pMemInputPin
);
2184 return hr
!= S_FALSE
? S_OK
: S_FALSE
;
2187 static const IMemInputPinVtbl AviMuxIn_MemInputPinVtbl
= {
2188 AviMuxIn_MemInputPin_QueryInterface
,
2189 AviMuxIn_MemInputPin_AddRef
,
2190 AviMuxIn_MemInputPin_Release
,
2191 AviMuxIn_MemInputPin_GetAllocator
,
2192 AviMuxIn_MemInputPin_NotifyAllocator
,
2193 AviMuxIn_MemInputPin_GetAllocatorRequirements
,
2194 AviMuxIn_MemInputPin_Receive
,
2195 AviMuxIn_MemInputPin_ReceiveMultiple
,
2196 AviMuxIn_MemInputPin_ReceiveCanBlock
2199 static inline AviMuxIn
* AviMuxIn_from_IPropertyBag(IPropertyBag
*iface
)
2201 return CONTAINING_RECORD(iface
, AviMuxIn
, IPropertyBag_iface
);
2204 static HRESULT WINAPI
AviMuxIn_PropertyBag_QueryInterface(
2205 IPropertyBag
*iface
, REFIID riid
, void **ppv
)
2207 AviMuxIn
*avimuxin
= AviMuxIn_from_IPropertyBag(iface
);
2208 return IPin_QueryInterface(&avimuxin
->pin
.pin
.IPin_iface
, riid
, ppv
);
2211 static ULONG WINAPI
AviMuxIn_PropertyBag_AddRef(IPropertyBag
*iface
)
2213 AviMuxIn
*avimuxin
= AviMuxIn_from_IPropertyBag(iface
);
2214 AviMux
*This
= impl_from_in_IPin(&avimuxin
->pin
.pin
.IPin_iface
);
2215 return IBaseFilter_AddRef(&This
->filter
.IBaseFilter_iface
);
2218 static ULONG WINAPI
AviMuxIn_PropertyBag_Release(IPropertyBag
*iface
)
2220 AviMuxIn
*avimuxin
= AviMuxIn_from_IPropertyBag(iface
);
2221 AviMux
*This
= impl_from_in_IPin(&avimuxin
->pin
.pin
.IPin_iface
);
2222 return IBaseFilter_Release(&This
->filter
.IBaseFilter_iface
);
2225 static HRESULT WINAPI
AviMuxIn_PropertyBag_Read(IPropertyBag
*iface
,
2226 LPCOLESTR pszPropName
, VARIANT
*pVar
, IErrorLog
*pErrorLog
)
2228 AviMuxIn
*avimuxin
= AviMuxIn_from_IPropertyBag(iface
);
2229 AviMux
*This
= impl_from_in_IPin(&avimuxin
->pin
.pin
.IPin_iface
);
2230 FIXME("(%p:%s)->(%s %p %p)\n", This
, debugstr_w(avimuxin
->pin
.pin
.pinInfo
.achName
),
2231 debugstr_w(pszPropName
), pVar
, pErrorLog
);
2235 static HRESULT WINAPI
AviMuxIn_PropertyBag_Write(IPropertyBag
*iface
,
2236 LPCOLESTR pszPropName
, VARIANT
*pVar
)
2238 AviMuxIn
*avimuxin
= AviMuxIn_from_IPropertyBag(iface
);
2239 AviMux
*This
= impl_from_in_IPin(&avimuxin
->pin
.pin
.IPin_iface
);
2240 FIXME("(%p:%s)->(%s %p)\n", This
, debugstr_w(avimuxin
->pin
.pin
.pinInfo
.achName
),
2241 debugstr_w(pszPropName
), pVar
);
2245 static const IPropertyBagVtbl AviMuxIn_PropertyBagVtbl
= {
2246 AviMuxIn_PropertyBag_QueryInterface
,
2247 AviMuxIn_PropertyBag_AddRef
,
2248 AviMuxIn_PropertyBag_Release
,
2249 AviMuxIn_PropertyBag_Read
,
2250 AviMuxIn_PropertyBag_Write
2253 static inline AviMuxIn
* AviMuxIn_from_IQualityControl(IQualityControl
*iface
)
2255 return CONTAINING_RECORD(iface
, AviMuxIn
, IQualityControl_iface
);
2258 static HRESULT WINAPI
AviMuxIn_QualityControl_QueryInterface(
2259 IQualityControl
*iface
, REFIID riid
, void **ppv
)
2261 AviMuxIn
*avimuxin
= AviMuxIn_from_IQualityControl(iface
);
2262 return IPin_QueryInterface(&avimuxin
->pin
.pin
.IPin_iface
, riid
, ppv
);
2265 static ULONG WINAPI
AviMuxIn_QualityControl_AddRef(IQualityControl
*iface
)
2267 AviMuxIn
*avimuxin
= AviMuxIn_from_IQualityControl(iface
);
2268 AviMux
*This
= impl_from_in_IPin(&avimuxin
->pin
.pin
.IPin_iface
);
2269 return IBaseFilter_AddRef(&This
->filter
.IBaseFilter_iface
);
2272 static ULONG WINAPI
AviMuxIn_QualityControl_Release(IQualityControl
*iface
)
2274 AviMuxIn
*avimuxin
= AviMuxIn_from_IQualityControl(iface
);
2275 AviMux
*This
= impl_from_in_IPin(&avimuxin
->pin
.pin
.IPin_iface
);
2276 return IBaseFilter_Release(&This
->filter
.IBaseFilter_iface
);
2279 static HRESULT WINAPI
AviMuxIn_QualityControl_Notify(IQualityControl
*iface
,
2280 IBaseFilter
*pSelf
, Quality q
)
2282 AviMuxIn
*avimuxin
= AviMuxIn_from_IQualityControl(iface
);
2283 AviMux
*This
= impl_from_in_IPin(&avimuxin
->pin
.pin
.IPin_iface
);
2284 FIXME("(%p:%s)->(%p { 0x%x %u %s %s })\n", This
, debugstr_w(avimuxin
->pin
.pin
.pinInfo
.achName
), pSelf
,
2285 q
.Type
, q
.Proportion
,
2286 wine_dbgstr_longlong(q
.Late
),
2287 wine_dbgstr_longlong(q
.TimeStamp
));
2291 static HRESULT WINAPI
AviMuxIn_QualityControl_SetSink(
2292 IQualityControl
*iface
, IQualityControl
*piqc
)
2294 AviMuxIn
*avimuxin
= AviMuxIn_from_IQualityControl(iface
);
2295 AviMux
*This
= impl_from_in_IPin(&avimuxin
->pin
.pin
.IPin_iface
);
2296 FIXME("(%p:%s)->(%p)\n", This
, debugstr_w(avimuxin
->pin
.pin
.pinInfo
.achName
), piqc
);
2300 static const IQualityControlVtbl AviMuxIn_QualityControlVtbl
= {
2301 AviMuxIn_QualityControl_QueryInterface
,
2302 AviMuxIn_QualityControl_AddRef
,
2303 AviMuxIn_QualityControl_Release
,
2304 AviMuxIn_QualityControl_Notify
,
2305 AviMuxIn_QualityControl_SetSink
2308 static HRESULT
create_input_pin(AviMux
*avimux
)
2310 static const WCHAR name
[] = {'I','n','p','u','t',' ','0','0',0};
2314 if(avimux
->input_pin_no
>= MAX_PIN_NO
-1)
2317 info
.dir
= PINDIR_INPUT
;
2318 info
.pFilter
= &avimux
->filter
.IBaseFilter_iface
;
2319 memcpy(info
.achName
, name
, sizeof(name
));
2320 info
.achName
[7] = '0' + (avimux
->input_pin_no
+1) % 10;
2321 info
.achName
[6] = '0' + (avimux
->input_pin_no
+1) / 10;
2323 hr
= BaseInputPin_Construct(&AviMuxIn_PinVtbl
, sizeof(AviMuxIn
), &info
,
2324 &AviMuxIn_BaseInputFuncTable
, &avimux
->filter
.csFilter
, NULL
, (IPin
**)&avimux
->in
[avimux
->input_pin_no
]);
2327 avimux
->in
[avimux
->input_pin_no
]->pin
.IMemInputPin_iface
.lpVtbl
= &AviMuxIn_MemInputPinVtbl
;
2328 avimux
->in
[avimux
->input_pin_no
]->IAMStreamControl_iface
.lpVtbl
= &AviMuxIn_AMStreamControlVtbl
;
2329 avimux
->in
[avimux
->input_pin_no
]->IPropertyBag_iface
.lpVtbl
= &AviMuxIn_PropertyBagVtbl
;
2330 avimux
->in
[avimux
->input_pin_no
]->IQualityControl_iface
.lpVtbl
= &AviMuxIn_QualityControlVtbl
;
2332 avimux
->in
[avimux
->input_pin_no
]->samples_head
= NULL
;
2333 hr
= CoCreateInstance(&CLSID_MemoryAllocator
, NULL
, CLSCTX_INPROC_SERVER
,
2334 &IID_IMemAllocator
, (void**)&avimux
->in
[avimux
->input_pin_no
]->samples_allocator
);
2336 BaseInputPinImpl_Release(&avimux
->in
[avimux
->input_pin_no
]->pin
.pin
.IPin_iface
);
2340 hr
= CoCreateInstance(&CLSID_MemoryAllocator
, NULL
, CLSCTX_INPROC_SERVER
,
2341 &IID_IMemAllocator
, (void**)&avimux
->in
[avimux
->input_pin_no
]->pin
.pAllocator
);
2343 IMemAllocator_Release(avimux
->in
[avimux
->input_pin_no
]->samples_allocator
);
2344 BaseInputPinImpl_Release(&avimux
->in
[avimux
->input_pin_no
]->pin
.pin
.IPin_iface
);
2348 avimux
->in
[avimux
->input_pin_no
]->stream_time
= 0;
2349 memset(&avimux
->in
[avimux
->input_pin_no
]->strh
, 0, sizeof(avimux
->in
[avimux
->input_pin_no
]->strh
));
2350 avimux
->in
[avimux
->input_pin_no
]->strf
= NULL
;
2351 memset(&avimux
->in
[avimux
->input_pin_no
]->indx_data
, 0, sizeof(avimux
->in
[avimux
->input_pin_no
]->indx_data
));
2352 memset(&avimux
->in
[avimux
->input_pin_no
]->ix_data
, 0, sizeof(avimux
->in
[avimux
->input_pin_no
]->ix_data
));
2353 avimux
->in
[avimux
->input_pin_no
]->indx
= (AVISUPERINDEX
*)&avimux
->in
[avimux
->input_pin_no
]->indx_data
;
2354 avimux
->in
[avimux
->input_pin_no
]->ix
= (AVISTDINDEX
*)avimux
->in
[avimux
->input_pin_no
]->ix_data
;
2356 avimux
->input_pin_no
++;
2360 IUnknown
* WINAPI
QCAP_createAVIMux(IUnknown
*pUnkOuter
, HRESULT
*phr
)
2362 static const WCHAR output_name
[] = {'A','V','I',' ','O','u','t',0};
2368 TRACE("(%p)\n", pUnkOuter
);
2371 *phr
= CLASS_E_NOAGGREGATION
;
2375 avimux
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(AviMux
));
2377 *phr
= E_OUTOFMEMORY
;
2381 BaseFilter_Init(&avimux
->filter
, &AviMuxVtbl
, &CLSID_AviDest
,
2382 (DWORD_PTR
)(__FILE__
": AviMux.csFilter"), &filter_func_table
);
2383 avimux
->IConfigAviMux_iface
.lpVtbl
= &ConfigAviMuxVtbl
;
2384 avimux
->IConfigInterleaving_iface
.lpVtbl
= &ConfigInterleavingVtbl
;
2385 avimux
->IMediaSeeking_iface
.lpVtbl
= &MediaSeekingVtbl
;
2386 avimux
->IPersistMediaPropertyBag_iface
.lpVtbl
= &PersistMediaPropertyBagVtbl
;
2387 avimux
->ISpecifyPropertyPages_iface
.lpVtbl
= &SpecifyPropertyPagesVtbl
;
2389 info
.dir
= PINDIR_OUTPUT
;
2390 info
.pFilter
= &avimux
->filter
.IBaseFilter_iface
;
2391 lstrcpyW(info
.achName
, output_name
);
2392 hr
= BaseOutputPin_Construct(&AviMuxOut_PinVtbl
, sizeof(AviMuxOut
), &info
,
2393 &AviMuxOut_BaseOutputFuncTable
, &avimux
->filter
.csFilter
, (IPin
**)&avimux
->out
);
2395 BaseFilterImpl_Release(&avimux
->filter
.IBaseFilter_iface
);
2396 HeapFree(GetProcessHeap(), 0, avimux
);
2400 avimux
->out
->IQualityControl_iface
.lpVtbl
= &AviMuxOut_QualityControlVtbl
;
2401 avimux
->out
->cur_stream
= 0;
2402 avimux
->out
->cur_time
= 0;
2403 avimux
->out
->stream
= NULL
;
2405 hr
= create_input_pin(avimux
);
2407 BaseOutputPinImpl_Release(&avimux
->out
->pin
.pin
.IPin_iface
);
2408 BaseFilterImpl_Release(&avimux
->filter
.IBaseFilter_iface
);
2409 HeapFree(GetProcessHeap(), 0, avimux
);
2414 avimux
->interleave
= 10000000;
2416 ObjectRefCount(TRUE
);
2418 return (IUnknown
*)&avimux
->filter
.IBaseFilter_iface
;