ReactOS 0.4.17-dev-966-gf06eace
avimux.c
Go to the documentation of this file.
1/*
2 * Copyright (C) 2013 Piotr Caban for CodeWeavers
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
17 */
18
19#include "qcap_private.h"
20#include "vfw.h"
21#include "aviriff.h"
22
24
25#define MAX_PIN_NO 128
26#define AVISUPERINDEX_ENTRIES 2000
27#define AVISTDINDEX_ENTRIES 4000
28#define ALIGN(x) ((x+1)/2*2)
29
30typedef struct {
35
40
41 /* strl chunk */
43 struct {
47 } *strf;
49#ifdef __REACTOS__
50 /* MSVC does not accept FIELD_OFFSET with a subscript as an array bound
51 in C (C2057). offsetof() to the member plus the element size is the
52 same value and is a constant expression for both compilers. */
53 BYTE indx_data[offsetof(AVISUPERINDEX, aIndex) + AVISUPERINDEX_ENTRIES * sizeof(((AVISUPERINDEX *)0)->aIndex[0])];
54#else
56#endif
57
58 /* movi chunk */
59 int ix_off;
61#ifdef __REACTOS__
62 /* MSVC does not accept FIELD_OFFSET with a subscript as an array bound
63 in C (C2057). offsetof() to the member plus the element size is the
64 same value and is a constant expression for both compilers. */
65 BYTE ix_data[offsetof(AVISTDINDEX, aIndex) + AVISTDINDEX_ENTRIES * sizeof(((AVISTDINDEX *)0)->aIndex[0])];
66#else
68#endif
69
72} AviMuxIn;
73
74typedef struct {
81
82 InterleavingMode mode;
85
88
91
94
98
101
103 BYTE buf[65536];
104
107 int size;
109} AviMux;
110
112
114{
116}
117
118static struct strmbase_pin *avi_mux_get_pin(struct strmbase_filter *iface, unsigned int index)
119{
121
122 if (!index)
123 return &filter->source.pin;
124 else if (index <= filter->input_pin_no)
125 return &filter->in[index - 1]->pin.pin;
126 return NULL;
127}
128
129static void avi_mux_destroy(struct strmbase_filter *iface)
130{
132 int i;
133
135
136 for (i = 0; i < filter->input_pin_no; ++i)
137 {
138 IPin_Disconnect(&filter->in[i]->pin.pin.IPin_iface);
139 IMemAllocator_Release(filter->in[i]->samples_allocator);
140 filter->in[i]->samples_allocator = NULL;
141 strmbase_sink_cleanup(&filter->in[i]->pin);
142 free(filter->in[i]);
143 }
144
145 free(filter->idx1);
147 free(filter);
148}
149
150static HRESULT avi_mux_query_interface(struct strmbase_filter *iface, REFIID iid, void **out)
151{
153
154 if (IsEqualGUID(iid, &IID_IConfigAviMux))
155 *out = &filter->IConfigAviMux_iface;
156 else if (IsEqualGUID(iid, &IID_IConfigInterleaving))
157 *out = &filter->IConfigInterleaving_iface;
158 else if (IsEqualGUID(iid, &IID_IMediaSeeking))
160 else if (IsEqualGUID(iid, &IID_IPersistMediaPropertyBag))
161 *out = &filter->IPersistMediaPropertyBag_iface;
163 *out = &filter->ISpecifyPropertyPages_iface;
164 else
165 return E_NOINTERFACE;
166
167 IUnknown_AddRef((IUnknown *)*out);
168 return S_OK;
169}
170
172{
173 ULONG written;
174 HRESULT hr;
175
176 if(!This->buf_pos)
177 return S_OK;
178
179 hr = IStream_Write(This->stream, This->buf, This->buf_pos, &written);
180 if(FAILED(hr))
181 return hr;
182 if (written != This->buf_pos)
183 return E_FAIL;
184
185 This->buf_pos = 0;
186 return S_OK;
187}
188
190{
192 HRESULT hr;
193
194 hr = out_flush(This);
195 if(FAILED(hr))
196 return hr;
197
198 li.QuadPart = pos;
199 hr = IStream_Seek(This->stream, li, STREAM_SEEK_SET, NULL);
200 if(FAILED(hr))
201 return hr;
202
203 This->out_pos = pos;
204 if(This->out_pos > This->size)
205 This->size = This->out_pos;
206 return hr;
207}
208
209static HRESULT out_write(AviMux *This, const void *data, int size)
210{
211 int chunk_size;
212 HRESULT hr;
213
214 while(1) {
215 if (size > sizeof(This->buf) - This->buf_pos)
216 chunk_size = sizeof(This->buf) - This->buf_pos;
217 else
218 chunk_size = size;
219
220 memcpy(This->buf + This->buf_pos, data, chunk_size);
221 size -= chunk_size;
222 data = (const BYTE*)data + chunk_size;
223 This->buf_pos += chunk_size;
224 This->out_pos += chunk_size;
225 if (This->out_pos > This->size)
226 This->size = This->out_pos;
227
228 if(!size)
229 break;
230 hr = out_flush(This);
231 if(FAILED(hr))
232 return hr;
233 }
234
235 return S_OK;
236}
237
238static inline HRESULT idx1_add_entry(AviMux *avimux, DWORD ckid, DWORD flags, DWORD off, DWORD len)
239{
240 if(avimux->idx1_entries == avimux->idx1_size) {
241 AVIINDEXENTRY *new_idx = realloc(avimux->idx1, sizeof(*avimux->idx1) * 2 * avimux->idx1_size);
242 if(!new_idx)
243 return E_OUTOFMEMORY;
244
245 avimux->idx1_size *= 2;
246 avimux->idx1 = new_idx;
247 }
248
249 avimux->idx1[avimux->idx1_entries].ckid = ckid;
250 avimux->idx1[avimux->idx1_entries].dwFlags = flags;
251 avimux->idx1[avimux->idx1_entries].dwChunkOffset = off;
252 avimux->idx1[avimux->idx1_entries].dwChunkLength = len;
253 avimux->idx1_entries++;
254 return S_OK;
255}
256
257static HRESULT flush_queue(AviMux *avimux, AviMuxIn *avimuxin, BOOL closing)
258{
259 IMediaSample *sample, **prev, **head_prev;
260 BYTE *data;
261 RIFFCHUNK rf;
262 DWORD size;
263 DWORD flags;
264 HRESULT hr;
265
266 if (avimux->cur_stream != avimuxin->stream_id)
267 return S_OK;
268
269 while(avimuxin->samples_head) {
270 hr = IMediaSample_GetPointer(avimuxin->samples_head, (BYTE**)&head_prev);
271 if(FAILED(hr))
272 return hr;
273 head_prev--;
274
275 hr = IMediaSample_GetPointer(*head_prev, (BYTE**)&prev);
276 if(FAILED(hr))
277 return hr;
278 prev--;
279
280 sample = *head_prev;
281 size = IMediaSample_GetActualDataLength(sample);
282 hr = IMediaSample_GetPointer(sample, &data);
283 if(FAILED(hr))
284 return hr;
285 flags = IMediaSample_IsDiscontinuity(sample)==S_OK ? AM_SAMPLE_TIMEDISCONTINUITY : 0;
286 if(IMediaSample_IsSyncPoint(sample) == S_OK)
288
289 if (avimuxin->stream_time + (closing ? 0 : avimuxin->strh.dwScale) > avimux->cur_time
291 {
292 if(closing)
293 break;
294
295 avimux->cur_stream++;
296 if(avimux->cur_stream >= avimux->input_pin_no-1) {
297 avimux->cur_time += avimux->interleave;
298 avimux->cur_stream = 0;
299 }
300 avimuxin = avimux->in[avimux->cur_stream];
301 continue;
302 }
303
304 if(avimuxin->ix->nEntriesInUse == AVISTDINDEX_ENTRIES) {
305 /* TODO: use output pins Deliver/Receive method */
306 hr = out_seek(avimux, avimuxin->ix_off);
307 if(FAILED(hr))
308 return hr;
309 hr = out_write(avimux, avimuxin->ix, sizeof(avimuxin->ix_data));
310 if(FAILED(hr))
311 return hr;
312
313 avimuxin->indx->aIndex[avimuxin->indx->nEntriesInUse].qwOffset = avimuxin->ix_off;
314 avimuxin->indx->aIndex[avimuxin->indx->nEntriesInUse].dwSize = sizeof(avimuxin->ix_data);
315 avimuxin->indx->aIndex[avimuxin->indx->nEntriesInUse].dwDuration = AVISTDINDEX_ENTRIES;
316 avimuxin->indx->nEntriesInUse++;
317
318 memset(avimuxin->ix->aIndex, 0, sizeof(avimuxin->ix->aIndex)*avimuxin->ix->nEntriesInUse);
319 avimuxin->ix->nEntriesInUse = 0;
320 avimuxin->ix->qwBaseOffset = 0;
321
322 avimuxin->ix_off = avimux->size;
323 avimux->size += sizeof(avimuxin->ix_data);
324 }
325
326 if(*head_prev == avimuxin->samples_head)
327 avimuxin->samples_head = NULL;
328 else
329 *head_prev = *prev;
330
331 avimuxin->stream_time += avimuxin->strh.dwScale;
332 avimuxin->strh.dwLength++;
334 if(!avimuxin->ix->qwBaseOffset)
335 avimuxin->ix->qwBaseOffset = avimux->size;
336 avimuxin->ix->aIndex[avimuxin->ix->nEntriesInUse].dwOffset =
337 avimux->size + sizeof(RIFFCHUNK) - avimuxin->ix->qwBaseOffset;
338
339 hr = out_seek(avimux, avimux->size);
340 if(FAILED(hr)) {
341 IMediaSample_Release(sample);
342 return hr;
343 }
344 }
345 avimuxin->ix->aIndex[avimuxin->ix->nEntriesInUse].dwSize = size |
347 avimuxin->ix->nEntriesInUse++;
348
349 rf.fcc = FCC('0'+avimuxin->stream_id/10, '0'+avimuxin->stream_id%10,
350 'd', flags & AM_SAMPLE_SPLICEPOINT ? 'b' : 'c');
351 rf.cb = size;
354 avimux->idx1[avimux->idx1_entries-1].dwChunkOffset : avimux->size, size);
355 if(FAILED(hr)) {
356 IMediaSample_Release(sample);
357 return hr;
358 }
359
361 hr = out_write(avimux, &rf, sizeof(rf));
362 if(FAILED(hr)) {
363 IMediaSample_Release(sample);
364 return hr;
365 }
366 hr = out_write(avimux, data, size);
367 if(FAILED(hr)) {
368 IMediaSample_Release(sample);
369 return hr;
370 }
371 flags = 0;
372 hr = out_write(avimux, &flags, ALIGN(rf.cb)-rf.cb);
373 if(FAILED(hr)) {
374 IMediaSample_Release(sample);
375 return hr;
376 }
377 }
378 IMediaSample_Release(sample);
379 }
380 return S_OK;
381}
382
384{
385 IMediaSample **prev, **head_prev;
386 HRESULT hr;
387
388 hr = IMediaSample_GetPointer(sample, (BYTE**)&prev);
389 if(FAILED(hr))
390 return hr;
391 prev--;
392
393 if(avimuxin->samples_head) {
394 hr = IMediaSample_GetPointer(avimuxin->samples_head, (BYTE**)&head_prev);
395 if(FAILED(hr))
396 return hr;
397 head_prev--;
398
399 *prev = *head_prev;
400 *head_prev = sample;
401 }else {
402 *prev = sample;
403 }
404 avimuxin->samples_head = sample;
405 IMediaSample_AddRef(sample);
406
407 return flush_queue(avimux, avimuxin, FALSE);
408}
409
411{
413 HRESULT hr;
414 int i;
415
416 if (This->stream)
417 {
418 AVIEXTHEADER dmlh;
419 RIFFCHUNK rc;
420 RIFFLIST rl;
421 int idx1_off, empty_stream;
422
423 empty_stream = This->cur_stream;
424 for(i=empty_stream+1; ; i++) {
425 if(i >= This->input_pin_no-1)
426 i = 0;
427 if(i == empty_stream)
428 break;
429
430 This->cur_stream = i;
431 hr = flush_queue(This, This->in[This->cur_stream], TRUE);
432 if(FAILED(hr))
433 return hr;
434 }
435
436 idx1_off = This->size;
437 rc.fcc = ckidAVIOLDINDEX;
438 rc.cb = This->idx1_entries * sizeof(*This->idx1);
439 hr = out_write(This, &rc, sizeof(rc));
440 if(FAILED(hr))
441 return hr;
442 hr = out_write(This, This->idx1, This->idx1_entries * sizeof(*This->idx1));
443 if(FAILED(hr))
444 return hr;
445 /* native writes 8 '\0' characters after the end of RIFF data */
446 i = 0;
447 hr = out_write(This, &i, sizeof(i));
448 if(FAILED(hr))
449 return hr;
450 hr = out_write(This, &i, sizeof(i));
451 if(FAILED(hr))
452 return hr;
453
454 for(i=0; i<This->input_pin_no; i++) {
455 if(!This->in[i]->pin.pin.peer)
456 continue;
457
458 hr = out_seek(This, This->in[i]->ix_off);
459 if(FAILED(hr))
460 return hr;
461
462 This->in[i]->indx->aIndex[This->in[i]->indx->nEntriesInUse].qwOffset = This->in[i]->ix_off;
463 This->in[i]->indx->aIndex[This->in[i]->indx->nEntriesInUse].dwSize = sizeof(This->in[i]->ix_data);
464 This->in[i]->indx->aIndex[This->in[i]->indx->nEntriesInUse].dwDuration = This->in[i]->strh.dwLength;
465 if(This->in[i]->indx->nEntriesInUse) {
466 This->in[i]->indx->aIndex[This->in[i]->indx->nEntriesInUse].dwDuration -=
467 This->in[i]->indx->aIndex[This->in[i]->indx->nEntriesInUse-1].dwDuration;
468 }
469 This->in[i]->indx->nEntriesInUse++;
470 hr = out_write(This, This->in[i]->ix, sizeof(This->in[i]->ix_data));
471 if(FAILED(hr))
472 return hr;
473 }
474
475 hr = out_seek(This, 0);
476 if(FAILED(hr))
477 return hr;
478
479 rl.fcc = FCC('R','I','F','F');
480 rl.cb = This->size - sizeof(RIFFCHUNK) - 2 * sizeof(int);
481 rl.fccListType = FCC('A','V','I',' ');
482 hr = out_write(This, &rl, sizeof(rl));
483 if(FAILED(hr))
484 return hr;
485
486 rl.fcc = FCC('L','I','S','T');
487 rl.cb = This->movi_off - sizeof(RIFFLIST) - sizeof(RIFFCHUNK);
488 rl.fccListType = FCC('h','d','r','l');
489 hr = out_write(This, &rl, sizeof(rl));
490 if(FAILED(hr))
491 return hr;
492
493 /* FIXME: set This->avih.dwMaxBytesPerSec value */
494 This->avih.dwTotalFrames = (This->stop-This->start) / 10 / This->avih.dwMicroSecPerFrame;
495 hr = out_write(This, &This->avih, sizeof(This->avih));
496 if(FAILED(hr))
497 return hr;
498
499 for(i=0; i<This->input_pin_no; i++) {
500 if(!This->in[i]->pin.pin.peer)
501 continue;
502
503 rl.cb = sizeof(FOURCC) + sizeof(AVISTREAMHEADER) + sizeof(RIFFCHUNK) +
504 This->in[i]->strf->cb + sizeof(This->in[i]->indx_data);
506 hr = out_write(This, &rl, sizeof(rl));
507 if(FAILED(hr))
508 return hr;
509
510 hr = out_write(This, &This->in[i]->strh, sizeof(AVISTREAMHEADER));
511 if(FAILED(hr))
512 return hr;
513
514 hr = out_write(This, This->in[i]->strf, sizeof(RIFFCHUNK) + This->in[i]->strf->cb);
515 if(FAILED(hr))
516 return hr;
517
518 hr = out_write(This, This->in[i]->indx, sizeof(This->in[i]->indx_data));
519 if(FAILED(hr))
520 return hr;
521 }
522
523 rl.cb = sizeof(dmlh) + sizeof(FOURCC);
525 hr = out_write(This, &rl, sizeof(rl));
526 if(FAILED(hr))
527 return hr;
528
529 memset(&dmlh, 0, sizeof(dmlh));
530 dmlh.fcc = ckidAVIEXTHEADER;
531 dmlh.cb = sizeof(dmlh) - sizeof(RIFFCHUNK);
532 dmlh.dwGrandFrames = This->in[0]->strh.dwLength;
533 hr = out_write(This, &dmlh, sizeof(dmlh));
534
535 rl.cb = idx1_off - This->movi_off - sizeof(RIFFCHUNK);
536 rl.fccListType = FCC('m','o','v','i');
537 out_write(This, &rl, sizeof(rl));
539
540 IStream_Release(This->stream);
541 This->stream = NULL;
542 }
543
544 return S_OK;
545}
546
548{
550 HRESULT hr;
551 int i, stream_id;
552
553 if(This->mode != INTERLEAVE_FULL) {
554 FIXME("mode not supported (%d)\n", This->mode);
555 return E_NOTIMPL;
556 }
557
558 for(i=0; i<This->input_pin_no; i++) {
559 IMediaSeeking *ms;
560 LONGLONG cur, stop;
561
562 if(!This->in[i]->pin.pin.peer)
563 continue;
564
565 hr = IPin_QueryInterface(This->in[i]->pin.pin.peer,
566 &IID_IMediaSeeking, (void**)&ms);
567 if(FAILED(hr))
568 continue;
569
570 hr = IMediaSeeking_GetPositions(ms, &cur, &stop);
571 if(FAILED(hr)) {
572 IMediaSeeking_Release(ms);
573 continue;
574 }
575
576 FIXME("Use IMediaSeeking to fill stream header\n");
577 IMediaSeeking_Release(ms);
578 }
579
580 if (This->source.pMemInputPin)
581 {
582 hr = IMemInputPin_QueryInterface(This->source.pMemInputPin,
583 &IID_IStream, (void **)&This->stream);
584 if(FAILED(hr))
585 return hr;
586 }
587
588 This->idx1_entries = 0;
589 if(!This->idx1_size) {
590 This->idx1_size = 1024;
591 if (!(This->idx1 = malloc(sizeof(*This->idx1) * This->idx1_size)))
592 return E_OUTOFMEMORY;
593 }
594
595 This->size = 3*sizeof(RIFFLIST) + sizeof(AVIMAINHEADER) + sizeof(AVIEXTHEADER);
596 This->start = -1;
597 This->stop = -1;
598 memset(&This->avih, 0, sizeof(This->avih));
599 for(i=0; i<This->input_pin_no; i++) {
600 if(!This->in[i]->pin.pin.peer)
601 continue;
602
603 This->avih.dwStreams++;
604 This->size += sizeof(RIFFLIST) + sizeof(AVISTREAMHEADER) + sizeof(RIFFCHUNK)
605 + This->in[i]->strf->cb + sizeof(This->in[i]->indx_data);
606
607 This->in[i]->strh.dwScale = MulDiv(This->in[i]->avg_time_per_frame, This->interleave, 10000000);
608 This->in[i]->strh.dwRate = This->interleave;
609
610 hr = IMemAllocator_Commit(This->in[i]->pin.pAllocator);
611 if(FAILED(hr)) {
612 if (This->stream)
613 {
614 IStream_Release(This->stream);
615 This->stream = NULL;
616 }
617 return hr;
618 }
619 }
620
621 This->movi_off = This->size;
622 This->size += sizeof(RIFFLIST);
623
624 idx1_add_entry(This, FCC('7','F','x','x'), 0, This->movi_off + sizeof(RIFFLIST), 0);
625
626 stream_id = 0;
627 for(i=0; i<This->input_pin_no; i++) {
628 if(!This->in[i]->pin.pin.peer)
629 continue;
630
631 This->in[i]->ix_off = This->size;
632 This->size += sizeof(This->in[i]->ix_data);
633 This->in[i]->ix->fcc = FCC('i','x','0'+stream_id/10,'0'+stream_id%10);
634 This->in[i]->ix->cb = sizeof(This->in[i]->ix_data) - sizeof(RIFFCHUNK);
635 This->in[i]->ix->wLongsPerEntry = 2;
636 This->in[i]->ix->bIndexSubType = 0;
637 This->in[i]->ix->bIndexType = AVI_INDEX_OF_CHUNKS;
638 This->in[i]->ix->dwChunkId = FCC('0'+stream_id/10,'0'+stream_id%10,'d','b');
639 This->in[i]->ix->qwBaseOffset = 0;
640
641 This->in[i]->indx->fcc = ckidAVISUPERINDEX;
642 This->in[i]->indx->cb = sizeof(This->in[i]->indx_data) - sizeof(RIFFCHUNK);
643 This->in[i]->indx->wLongsPerEntry = 4;
644 This->in[i]->indx->bIndexSubType = 0;
645 This->in[i]->indx->bIndexType = AVI_INDEX_OF_INDEXES;
646 This->in[i]->indx->dwChunkId = This->in[i]->ix->dwChunkId;
647 This->in[i]->stream_id = stream_id++;
648 }
649
650 This->buf_pos = 0;
651 This->out_pos = 0;
652
653 This->avih.fcc = ckidMAINAVIHEADER;
654 This->avih.cb = sizeof(AVIMAINHEADER) - sizeof(RIFFCHUNK);
655 /* TODO: Use first video stream */
656 This->avih.dwMicroSecPerFrame = This->in[0]->avg_time_per_frame/10;
657 This->avih.dwPaddingGranularity = 1;
658 This->avih.dwFlags = AVIF_TRUSTCKTYPE | AVIF_HASINDEX;
659 This->avih.dwWidth = ((BITMAPINFOHEADER*)This->in[0]->strf->data)->biWidth;
660 This->avih.dwHeight = ((BITMAPINFOHEADER*)This->in[0]->strf->data)->biHeight;
661
662 return S_OK;
663}
664
665static const struct strmbase_filter_ops filter_ops =
666{
667 .filter_get_pin = avi_mux_get_pin,
668 .filter_destroy = avi_mux_destroy,
669 .filter_query_interface = avi_mux_query_interface,
670 .filter_init_stream = avi_mux_init_stream,
671 .filter_cleanup_stream = avi_mux_cleanup_stream,
672};
673
675{
676 return CONTAINING_RECORD(iface, AviMux, IConfigAviMux_iface);
677}
678
680 IConfigAviMux *iface, REFIID riid, void **ppv)
681{
683 return IBaseFilter_QueryInterface(&This->filter.IBaseFilter_iface, riid, ppv);
684}
685
687{
689 return IBaseFilter_AddRef(&This->filter.IBaseFilter_iface);
690}
691
693{
695 return IBaseFilter_Release(&This->filter.IBaseFilter_iface);
696}
697
699{
701 FIXME("filter %p, index %ld, stub!\n", This, iStream);
702 return E_NOTIMPL;
703}
704
706{
708 FIXME("(%p)->(%p)\n", This, pStream);
709 return E_NOTIMPL;
710}
711
713 IConfigAviMux *iface, BOOL fOldIndex)
714{
716 FIXME("(%p)->(%x)\n", This, fOldIndex);
717 return E_NOTIMPL;
718}
719
721 IConfigAviMux *iface, BOOL *pfOldIndex)
722{
724 FIXME("(%p)->(%p)\n", This, pfOldIndex);
725 return E_NOTIMPL;
726}
727
728static const IConfigAviMuxVtbl ConfigAviMuxVtbl = {
736};
737
739{
740 return CONTAINING_RECORD(iface, AviMux, IConfigInterleaving_iface);
741}
742
744 IConfigInterleaving *iface, REFIID riid, void **ppv)
745{
747 return IBaseFilter_QueryInterface(&This->filter.IBaseFilter_iface, riid, ppv);
748}
749
751{
753 return IBaseFilter_AddRef(&This->filter.IBaseFilter_iface);
754}
755
757{
759 return IBaseFilter_Release(&This->filter.IBaseFilter_iface);
760}
761
763 IConfigInterleaving *iface, InterleavingMode mode)
764{
766
767 TRACE("(%p)->(%d)\n", This, mode);
768
769 if(mode>INTERLEAVE_NONE_BUFFERED)
770 return E_INVALIDARG;
771
772 if(This->mode != mode) {
773 if(This->source.pin.peer) {
774 HRESULT hr = IFilterGraph_Reconnect(This->filter.graph, &This->source.pin.IPin_iface);
775 if(FAILED(hr))
776 return hr;
777 }
778
779 This->mode = mode;
780 }
781
782 return S_OK;
783}
784
786 IConfigInterleaving *iface, InterleavingMode *pMode)
787{
789 FIXME("(%p)->(%p)\n", This, pMode);
790 return E_NOTIMPL;
791}
792
794 const REFERENCE_TIME *prtInterleave, const REFERENCE_TIME *prtPreroll)
795{
797
798 TRACE("(%p)->(%p %p)\n", This, prtInterleave, prtPreroll);
799
800 if(prtInterleave)
801 This->interleave = *prtInterleave;
802 if(prtPreroll)
803 This->preroll = *prtPreroll;
804 return S_OK;
805}
806
808 REFERENCE_TIME *prtInterleave, REFERENCE_TIME *prtPreroll)
809{
811 FIXME("(%p)->(%p %p)\n", This, prtInterleave, prtPreroll);
812 return E_NOTIMPL;
813}
814
815static const IConfigInterleavingVtbl ConfigInterleavingVtbl = {
823};
824
826{
827 return CONTAINING_RECORD(iface, AviMux, IMediaSeeking_iface);
828}
829
831 IMediaSeeking *iface, REFIID riid, void **ppv)
832{
834 return IBaseFilter_QueryInterface(&This->filter.IBaseFilter_iface, riid, ppv);
835}
836
838{
840 return IBaseFilter_AddRef(&This->filter.IBaseFilter_iface);
841}
842
844{
846 return IBaseFilter_Release(&This->filter.IBaseFilter_iface);
847}
848
850 IMediaSeeking *iface, DWORD *pCapabilities)
851{
853 FIXME("(%p)->(%p)\n", This, pCapabilities);
854 return E_NOTIMPL;
855}
856
858 IMediaSeeking *iface, DWORD *pCapabilities)
859{
861 FIXME("(%p)->(%p)\n", This, pCapabilities);
862 return E_NOTIMPL;
863}
864
866 IMediaSeeking *iface, const GUID *pFormat)
867{
869 FIXME("(%p)->(%s)\n", This, debugstr_guid(pFormat));
870 return E_NOTIMPL;
871}
872
874 IMediaSeeking *iface, GUID *pFormat)
875{
877 FIXME("(%p)->(%p)\n", This, pFormat);
878 return E_NOTIMPL;
879}
880
882 IMediaSeeking *iface, GUID *pFormat)
883{
885 FIXME("(%p)->(%p)\n", This, pFormat);
886 return E_NOTIMPL;
887}
888
890 IMediaSeeking *iface, const GUID *pFormat)
891{
893 FIXME("(%p)->(%s)\n", This, debugstr_guid(pFormat));
894 return E_NOTIMPL;
895}
896
898 IMediaSeeking *iface, const GUID *pFormat)
899{
901 FIXME("(%p)->(%s)\n", This, debugstr_guid(pFormat));
902 return E_NOTIMPL;
903}
904
906 IMediaSeeking *iface, LONGLONG *pDuration)
907{
909 FIXME("(%p)->(%p)\n", This, pDuration);
910 return E_NOTIMPL;
911}
912
914 IMediaSeeking *iface, LONGLONG *pStop)
915{
917 FIXME("(%p)->(%p)\n", This, pStop);
918 return E_NOTIMPL;
919}
920
922 IMediaSeeking *iface, LONGLONG *pCurrent)
923{
925 FIXME("(%p)->(%p)\n", This, pCurrent);
926 return E_NOTIMPL;
927}
928
930 const GUID *pTargetFormat, LONGLONG Source, const GUID *pSourceFormat)
931{
933 FIXME("(%p)->(%p %s %s %s)\n", This, pTarget, debugstr_guid(pTargetFormat),
934 wine_dbgstr_longlong(Source), debugstr_guid(pSourceFormat));
935 return E_NOTIMPL;
936}
937
939 DWORD dwCurrentFlags, LONGLONG *pStop, DWORD dwStopFlags)
940{
942 FIXME("(%p)->(%p %#lx %p %#lx)\n", This, pCurrent, dwCurrentFlags, pStop, dwStopFlags);
943 return E_NOTIMPL;
944}
945
947 LONGLONG *pCurrent, LONGLONG *pStop)
948{
950 FIXME("(%p)->(%p %p)\n", This, pCurrent, pStop);
951 return E_NOTIMPL;
952}
953
955 LONGLONG *pEarliest, LONGLONG *pLatest)
956{
958 FIXME("(%p)->(%p %p)\n", This, pEarliest, pLatest);
959 return E_NOTIMPL;
960}
961
963{
965 FIXME("(%p)->(%lf)\n", This, dRate);
966 return E_NOTIMPL;
967}
968
969static HRESULT WINAPI MediaSeeking_GetRate(IMediaSeeking *iface, double *pdRate)
970{
972 FIXME("(%p)->(%p)\n", This, pdRate);
973 return E_NOTIMPL;
974}
975
977{
979 FIXME("(%p)->(%p)\n", This, pllPreroll);
980 return E_NOTIMPL;
981}
982
983static const IMediaSeekingVtbl MediaSeekingVtbl = {
1004};
1005
1007{
1008 return CONTAINING_RECORD(iface, AviMux, IPersistMediaPropertyBag_iface);
1009}
1010
1012 IPersistMediaPropertyBag *iface, REFIID riid, void **ppv)
1013{
1015 return IBaseFilter_QueryInterface(&This->filter.IBaseFilter_iface, riid, ppv);
1016}
1017
1019{
1021 return IBaseFilter_AddRef(&This->filter.IBaseFilter_iface);
1022}
1023
1025{
1027 return IBaseFilter_Release(&This->filter.IBaseFilter_iface);
1028}
1029
1031 IPersistMediaPropertyBag *iface, CLSID *pClassID)
1032{
1034 return IBaseFilter_GetClassID(&This->filter.IBaseFilter_iface, pClassID);
1035}
1036
1038{
1040 FIXME("(%p)->()\n", This);
1041 return E_NOTIMPL;
1042}
1043
1045 IMediaPropertyBag *pPropBag, IErrorLog *pErrorLog)
1046{
1048 FIXME("(%p)->()\n", This);
1049 return E_NOTIMPL;
1050}
1051
1053 IMediaPropertyBag *pPropBag, BOOL fClearDirty, BOOL fSaveAllProperties)
1054{
1056 FIXME("(%p)->()\n", This);
1057 return E_NOTIMPL;
1058}
1059
1060static const IPersistMediaPropertyBagVtbl PersistMediaPropertyBagVtbl = {
1068};
1069
1071{
1072 return CONTAINING_RECORD(iface, AviMux, ISpecifyPropertyPages_iface);
1073}
1074
1076 ISpecifyPropertyPages *iface, REFIID riid, void **ppv)
1077{
1079 return IBaseFilter_QueryInterface(&This->filter.IBaseFilter_iface, riid, ppv);
1080}
1081
1083{
1085 return IBaseFilter_AddRef(&This->filter.IBaseFilter_iface);
1086}
1087
1089{
1091 return IBaseFilter_Release(&This->filter.IBaseFilter_iface);
1092}
1093
1095 ISpecifyPropertyPages *iface, CAUUID *pPages)
1096{
1098 FIXME("(%p)->(%p)\n", This, pPages);
1099 return E_NOTIMPL;
1100}
1101
1102static const ISpecifyPropertyPagesVtbl SpecifyPropertyPagesVtbl = {
1107};
1108
1109static inline AviMux *impl_from_source_pin(struct strmbase_pin *iface)
1110{
1111 return CONTAINING_RECORD(iface, AviMux, source.pin);
1112}
1113
1114static HRESULT source_query_interface(struct strmbase_pin *iface, REFIID iid, void **out)
1115{
1117
1118 if (IsEqualGUID(iid, &IID_IQualityControl))
1119 *out = &filter->IQualityControl_iface;
1120 else
1121 return E_NOINTERFACE;
1122
1123 IUnknown_AddRef((IUnknown *)*out);
1124 return S_OK;
1125}
1126
1128{
1129 if (!IsEqualGUID(&mt->majortype, &GUID_NULL) && !IsEqualGUID(&mt->majortype, &MEDIATYPE_Stream))
1130 return S_FALSE;
1131 if (!IsEqualGUID(&mt->subtype, &GUID_NULL) && !IsEqualGUID(&mt->subtype, &MEDIASUBTYPE_Avi))
1132 return S_FALSE;
1133 return S_OK;
1134}
1135
1137 IPin *pReceivePin, const AM_MEDIA_TYPE *pmt)
1138{
1141 unsigned int i;
1142 HRESULT hr;
1143
1144 hr = IPin_QueryDirection(pReceivePin, &dir);
1145 if(hr==S_OK && dir!=PINDIR_INPUT)
1147
1148 if (FAILED(hr = BaseOutputPinImpl_AttemptConnection(iface, pReceivePin, pmt)))
1149 return hr;
1150
1151 for (i = 0; i < filter->input_pin_no; ++i)
1152 {
1153 if (!filter->in[i]->pin.pin.peer)
1154 continue;
1155
1156 hr = IFilterGraph_Reconnect(filter->filter.graph, &filter->in[i]->pin.pin.IPin_iface);
1157 if (FAILED(hr))
1158 {
1159 IPin_Disconnect(&iface->pin.IPin_iface);
1160 break;
1161 }
1162 }
1163
1164 return hr;
1165}
1166
1167static HRESULT source_get_media_type(struct strmbase_pin *base, unsigned int iPosition, AM_MEDIA_TYPE *amt)
1168{
1169 TRACE("(%p)->(%d %p)\n", base, iPosition, amt);
1170
1171 if(iPosition > 0)
1172 return VFW_S_NO_MORE_ITEMS;
1173
1174 amt->majortype = MEDIATYPE_Stream;
1175 amt->subtype = MEDIASUBTYPE_Avi;
1176 amt->bFixedSizeSamples = TRUE;
1177 amt->bTemporalCompression = FALSE;
1178 amt->lSampleSize = 1;
1179 amt->formattype = GUID_NULL;
1180 amt->pUnk = NULL;
1181 amt->cbFormat = 0;
1182 amt->pbFormat = NULL;
1183 return S_OK;
1184}
1185
1187 IMemInputPin *pPin, IMemAllocator **pAlloc)
1188{
1189 ALLOCATOR_PROPERTIES req, actual;
1190 HRESULT hr;
1191
1192 TRACE("(%p)->(%p %p)\n", base, pPin, pAlloc);
1193
1194 if (FAILED(hr = CoCreateInstance(&CLSID_MemoryAllocator, NULL,
1195 CLSCTX_INPROC_SERVER, &IID_IMemAllocator, (void **)pAlloc)))
1196 {
1197 ERR("Failed to create allocator, hr %#lx.\n", hr);
1198 return hr;
1199 }
1200
1201 hr = IMemInputPin_GetAllocatorRequirements(pPin, &req);
1202 if(FAILED(hr))
1203 req.cbAlign = 1;
1204 req.cBuffers = 32;
1205 req.cbBuffer = 0;
1206 req.cbPrefix = 0;
1207
1208 hr = IMemAllocator_SetProperties(*pAlloc, &req, &actual);
1209 if(FAILED(hr))
1210 return hr;
1211
1212 return IMemInputPin_NotifyAllocator(pPin, *pAlloc, TRUE);
1213}
1214
1215static const struct strmbase_source_ops source_ops =
1216{
1217 .base.pin_query_interface = source_query_interface,
1218 .base.pin_query_accept = source_query_accept,
1219 .base.pin_get_media_type = source_get_media_type,
1220 .pfnAttemptConnection = AviMuxOut_AttemptConnection,
1221 .pfnDecideAllocator = AviMuxOut_DecideAllocator,
1222};
1223
1225{
1226 return CONTAINING_RECORD(iface, AviMux, IQualityControl_iface);
1227}
1228
1230 IQualityControl *iface, REFIID riid, void **ppv)
1231{
1233 return IPin_QueryInterface(&This->source.pin.IPin_iface, riid, ppv);
1234}
1235
1237{
1239 return IBaseFilter_AddRef(&This->filter.IBaseFilter_iface);
1240}
1241
1243{
1245 return IBaseFilter_Release(&This->filter.IBaseFilter_iface);
1246}
1247
1249 IBaseFilter *sender, Quality q)
1250{
1252
1253 FIXME("filter %p, sender %p, type %#x, proportion %ld, late %s, timestamp %s, stub!\n",
1254 filter, sender, q.Type, q.Proportion,
1255 wine_dbgstr_longlong(q.Late), wine_dbgstr_longlong(q.TimeStamp));
1256
1257 return E_NOTIMPL;
1258}
1259
1261 IQualityControl *iface, IQualityControl *piqc)
1262{
1264 FIXME("(%p)->(%p)\n", This, piqc);
1265 return E_NOTIMPL;
1266}
1267
1268static const IQualityControlVtbl AviMuxOut_QualityControlVtbl = {
1274};
1275
1277{
1278 return CONTAINING_RECORD(iface, AviMuxIn, pin.pin);
1279}
1280
1281static HRESULT sink_query_interface(struct strmbase_pin *iface, REFIID iid, void **out)
1282{
1284
1285 if (IsEqualGUID(iid, &IID_IAMStreamControl))
1286 *out = &pin->IAMStreamControl_iface;
1287 else if (IsEqualGUID(iid, &IID_IMemInputPin))
1288 *out = &pin->pin.IMemInputPin_iface;
1289 else if (IsEqualGUID(iid, &IID_IPropertyBag))
1290 *out = &pin->IPropertyBag_iface;
1291 else if (IsEqualGUID(iid, &IID_IQualityControl))
1292 *out = &pin->IQualityControl_iface;
1293 else
1294 return E_NOINTERFACE;
1295
1296 IUnknown_AddRef((IUnknown *)*out);
1297 return S_OK;
1298}
1299
1301{
1302 if(IsEqualIID(&pmt->majortype, &MEDIATYPE_Audio) &&
1303 IsEqualIID(&pmt->formattype, &FORMAT_WaveFormatEx))
1304 return S_OK;
1305 if(IsEqualIID(&pmt->majortype, &MEDIATYPE_Interleaved) &&
1306 IsEqualIID(&pmt->formattype, &FORMAT_DvInfo))
1307 return S_OK;
1308 if(IsEqualIID(&pmt->majortype, &MEDIATYPE_Video) &&
1309 (IsEqualIID(&pmt->formattype, &FORMAT_VideoInfo) ||
1310 IsEqualIID(&pmt->formattype, &FORMAT_DvInfo)))
1311 return S_OK;
1312 return S_FALSE;
1313}
1314
1316{
1317 AviMux *avimux = impl_from_strmbase_filter(base->pin.filter);
1318 AviMuxIn *avimuxin = CONTAINING_RECORD(base, AviMuxIn, pin);
1319 REFERENCE_TIME start, stop;
1321 int frames_no;
1322 IMediaSample2 *ms2;
1323 BYTE *frame, *buf;
1325 DWORD flags;
1326 HRESULT hr;
1327
1328 TRACE("pin %p, pSample %p.\n", avimuxin, pSample);
1329
1330 hr = IMediaSample_QueryInterface(pSample, &IID_IMediaSample2, (void**)&ms2);
1331 if(SUCCEEDED(hr)) {
1333
1334 memset(&props, 0, sizeof(props));
1335 hr = IMediaSample2_GetProperties(ms2, sizeof(props), (BYTE*)&props);
1336 IMediaSample2_Release(ms2);
1337 if(FAILED(hr))
1338 return hr;
1339
1340 flags = props.dwSampleFlags;
1341 frame = props.pbBuffer;
1342 size = props.lActual;
1343 }else {
1344 flags = IMediaSample_IsSyncPoint(pSample) == S_OK ? AM_SAMPLE_SPLICEPOINT : 0;
1345 hr = IMediaSample_GetPointer(pSample, &frame);
1346 if(FAILED(hr))
1347 return hr;
1348 size = IMediaSample_GetActualDataLength(pSample);
1349 }
1350
1351 if(!avimuxin->pin.pin.mt.bTemporalCompression)
1353
1354 hr = IMediaSample_GetTime(pSample, &start, &stop);
1355 if(FAILED(hr))
1356 return hr;
1357
1358 if(avimuxin->stop>stop)
1360
1361 if(avimux->start == -1)
1362 avimux->start = start;
1363 if(avimux->stop < stop)
1364 avimux->stop = stop;
1365
1366 if(avimux->avih.dwSuggestedBufferSize < ALIGN(size)+sizeof(RIFFCHUNK))
1367 avimux->avih.dwSuggestedBufferSize = ALIGN(size) + sizeof(RIFFCHUNK);
1368 if(avimuxin->strh.dwSuggestedBufferSize < ALIGN(size)+sizeof(RIFFCHUNK))
1369 avimuxin->strh.dwSuggestedBufferSize = ALIGN(size) + sizeof(RIFFCHUNK);
1370
1371 frames_no = 1;
1372 if(avimuxin->stop!=-1 && start > avimuxin->stop) {
1373 frames_no += (double)(start - avimuxin->stop) / 10000000
1374 * avimuxin->strh.dwRate / avimuxin->strh.dwScale + 0.5;
1375 }
1376 avimuxin->stop = stop;
1377
1378 while(--frames_no) {
1379 /* TODO: store all control frames in one buffer */
1380 hr = IMemAllocator_GetBuffer(avimuxin->samples_allocator, &sample, NULL, NULL, 0);
1381 if(FAILED(hr))
1382 return hr;
1383 hr = IMediaSample_SetActualDataLength(sample, 0);
1384 if(SUCCEEDED(hr))
1385 hr = IMediaSample_SetDiscontinuity(sample, TRUE);
1386 if(SUCCEEDED(hr))
1387 hr = IMediaSample_SetSyncPoint(sample, FALSE);
1388 if(SUCCEEDED(hr))
1389 hr = queue_sample(avimux, avimuxin, sample);
1390 IMediaSample_Release(sample);
1391 if(FAILED(hr))
1392 return hr;
1393 }
1394
1395 hr = IMemAllocator_GetBuffer(avimuxin->samples_allocator, &sample, NULL, NULL, 0);
1396 if(FAILED(hr))
1397 return hr;
1398 max_size = IMediaSample_GetSize(sample);
1399 if(size > max_size)
1400 size = max_size;
1401 hr = IMediaSample_SetActualDataLength(sample, size);
1402 if(SUCCEEDED(hr))
1403 hr = IMediaSample_SetDiscontinuity(sample, FALSE);
1404 if(SUCCEEDED(hr))
1405 hr = IMediaSample_SetSyncPoint(sample, flags & AM_SAMPLE_SPLICEPOINT);
1406 /* TODO: avoid unnecessary copying */
1407 if(SUCCEEDED(hr))
1408 hr = IMediaSample_GetPointer(sample, &buf);
1409 if(SUCCEEDED(hr)) {
1410 memcpy(buf, frame, size);
1411 hr = queue_sample(avimux, avimuxin, sample);
1412 }
1413 IMediaSample_Release(sample);
1414
1415 return hr;
1416}
1417
1418static HRESULT avi_mux_sink_connect(struct strmbase_sink *iface, IPin *peer, const AM_MEDIA_TYPE *pmt)
1419{
1420 AviMuxIn *avimuxin = impl_sink_from_strmbase_pin(&iface->pin);
1421 AviMux *This = impl_from_strmbase_filter(iface->pin.filter);
1422 HRESULT hr;
1423
1424 if(!pmt)
1425 return E_POINTER;
1426
1427 if(IsEqualIID(&pmt->majortype, &MEDIATYPE_Video) &&
1428 IsEqualIID(&pmt->formattype, &FORMAT_VideoInfo)) {
1429 ALLOCATOR_PROPERTIES req, act;
1430 VIDEOINFOHEADER *vih;
1431 int size;
1432
1433 vih = (VIDEOINFOHEADER*)pmt->pbFormat;
1434 avimuxin->strh.fcc = ckidSTREAMHEADER;
1435 avimuxin->strh.cb = sizeof(AVISTREAMHEADER) - FIELD_OFFSET(AVISTREAMHEADER, fccType);
1436 avimuxin->strh.fccType = streamtypeVIDEO;
1437 /* FIXME: fccHandler should be set differently */
1438 avimuxin->strh.fccHandler = vih->bmiHeader.biCompression ?
1439 vih->bmiHeader.biCompression : FCC('D','I','B',' ');
1440 avimuxin->avg_time_per_frame = vih->AvgTimePerFrame;
1441 avimuxin->stop = -1;
1442
1443 req.cBuffers = 32;
1444 req.cbBuffer = vih->bmiHeader.biSizeImage;
1445 req.cbAlign = 1;
1446 req.cbPrefix = sizeof(void*);
1447 hr = IMemAllocator_SetProperties(avimuxin->samples_allocator, &req, &act);
1448 if(SUCCEEDED(hr))
1449 hr = IMemAllocator_Commit(avimuxin->samples_allocator);
1450 if (FAILED(hr))
1451 return hr;
1452
1453 size = pmt->cbFormat - FIELD_OFFSET(VIDEOINFOHEADER, bmiHeader);
1454 avimuxin->strf = malloc(sizeof(RIFFCHUNK) + ALIGN(FIELD_OFFSET(BITMAPINFO, bmiColors[vih->bmiHeader.biClrUsed])));
1455 avimuxin->strf->fcc = ckidSTREAMFORMAT;
1456 avimuxin->strf->cb = FIELD_OFFSET(BITMAPINFO, bmiColors[vih->bmiHeader.biClrUsed]);
1457 if(size > avimuxin->strf->cb)
1458 size = avimuxin->strf->cb;
1459 memcpy(avimuxin->strf->data, &vih->bmiHeader, size);
1460 }else {
1461 FIXME("format not supported: %s %s\n", debugstr_guid(&pmt->majortype),
1462 debugstr_guid(&pmt->formattype));
1463 return E_NOTIMPL;
1464 }
1465
1466 return create_input_pin(This);
1467}
1468
1469static void avi_mux_sink_disconnect(struct strmbase_sink *iface)
1470{
1471 AviMuxIn *avimuxin = impl_sink_from_strmbase_pin(&iface->pin);
1472 IMediaSample **prev, *cur;
1473
1474 IMemAllocator_Decommit(avimuxin->samples_allocator);
1475 while(avimuxin->samples_head) {
1476 cur = avimuxin->samples_head;
1477 if (FAILED(IMediaSample_GetPointer(cur, (BYTE **)&prev)))
1478 break;
1479 prev--;
1480
1481 cur = avimuxin->samples_head;
1482 avimuxin->samples_head = *prev;
1483 IMediaSample_Release(cur);
1484
1485 if(cur == avimuxin->samples_head)
1486 avimuxin->samples_head = NULL;
1487 }
1488 free(avimuxin->strf);
1489 avimuxin->strf = NULL;
1490}
1491
1492static const struct strmbase_sink_ops sink_ops =
1493{
1494 .base.pin_query_interface = sink_query_interface,
1495 .base.pin_query_accept = sink_query_accept,
1496 .pfnReceive = AviMuxIn_Receive,
1497 .sink_connect = avi_mux_sink_connect,
1498 .sink_disconnect = avi_mux_sink_disconnect,
1499};
1500
1501static inline AviMux* impl_from_in_IPin(IPin *iface)
1502{
1503 struct strmbase_pin *pin = CONTAINING_RECORD(iface, struct strmbase_pin, IPin_iface);
1504 return impl_from_strmbase_filter(pin->filter);
1505}
1506
1508{
1509 return CONTAINING_RECORD(iface, AviMuxIn, IAMStreamControl_iface);
1510}
1511
1513 IAMStreamControl *iface, REFIID riid, void **ppv)
1514{
1515 AviMuxIn *avimuxin = AviMuxIn_from_IAMStreamControl(iface);
1516 return IPin_QueryInterface(&avimuxin->pin.pin.IPin_iface, riid, ppv);
1517}
1518
1520{
1521 AviMuxIn *avimuxin = AviMuxIn_from_IAMStreamControl(iface);
1522 AviMux *This = impl_from_in_IPin(&avimuxin->pin.pin.IPin_iface);
1523 return IBaseFilter_AddRef(&This->filter.IBaseFilter_iface);
1524}
1525
1527{
1528 AviMuxIn *avimuxin = AviMuxIn_from_IAMStreamControl(iface);
1529 AviMux *This = impl_from_in_IPin(&avimuxin->pin.pin.IPin_iface);
1530 return IBaseFilter_Release(&This->filter.IBaseFilter_iface);
1531}
1532
1535{
1536 FIXME("iface %p, start %p, cookie %#lx, stub!\n", iface, start, cookie);
1537 return E_NOTIMPL;
1538}
1539
1541 const REFERENCE_TIME *stop, BOOL send_extra, DWORD cookie)
1542{
1543 FIXME("iface %p, stop %p, send_extra %d, cookie %#lx, stub!\n", iface, stop, send_extra, cookie);
1544 return E_NOTIMPL;
1545}
1546
1549{
1550 FIXME("iface %p, info %p, stub!\n", iface, info);
1551 return E_NOTIMPL;
1552}
1553
1554static const IAMStreamControlVtbl AviMuxIn_AMStreamControlVtbl = {
1561};
1562
1564{
1565 return CONTAINING_RECORD(iface, AviMuxIn, pin.IMemInputPin_iface);
1566}
1567
1569 IMemInputPin *iface, REFIID riid, void **ppv)
1570{
1571 AviMuxIn *avimuxin = AviMuxIn_from_IMemInputPin(iface);
1572 return IPin_QueryInterface(&avimuxin->pin.pin.IPin_iface, riid, ppv);
1573}
1574
1576{
1577 AviMuxIn *avimuxin = AviMuxIn_from_IMemInputPin(iface);
1578 AviMux *This = impl_from_in_IPin(&avimuxin->pin.pin.IPin_iface);
1579 return IBaseFilter_AddRef(&This->filter.IBaseFilter_iface);
1580}
1581
1583{
1584 AviMuxIn *avimuxin = AviMuxIn_from_IMemInputPin(iface);
1585 AviMux *This = impl_from_in_IPin(&avimuxin->pin.pin.IPin_iface);
1586 return IBaseFilter_Release(&This->filter.IBaseFilter_iface);
1587}
1588
1590 IMemInputPin *iface, IMemAllocator **ppAllocator)
1591{
1592 AviMuxIn *avimuxin = AviMuxIn_from_IMemInputPin(iface);
1593
1594 TRACE("pin %p, ppAllocator %p.\n", avimuxin, ppAllocator);
1595
1596 if(!ppAllocator)
1597 return E_POINTER;
1598
1599 IMemAllocator_AddRef(avimuxin->pin.pAllocator);
1600 *ppAllocator = avimuxin->pin.pAllocator;
1601 return S_OK;
1602}
1603
1605 IMemInputPin *iface, IMemAllocator *pAllocator, BOOL bReadOnly)
1606{
1607 AviMuxIn *avimuxin = AviMuxIn_from_IMemInputPin(iface);
1609 HRESULT hr;
1610
1611 TRACE("pin %p, pAllocator %p, bReadOnly %d.\n", avimuxin, pAllocator, bReadOnly);
1612
1613 if(!pAllocator)
1614 return E_POINTER;
1615
1616 memset(&props, 0, sizeof(props));
1617 hr = IMemAllocator_GetProperties(pAllocator, &props);
1618 if(FAILED(hr))
1619 return hr;
1620
1621 props.cbAlign = 1;
1622 props.cbPrefix = 8;
1623 return IMemAllocator_SetProperties(avimuxin->pin.pAllocator, &props, &props);
1624}
1625
1627 IMemInputPin *iface, ALLOCATOR_PROPERTIES *pProps)
1628{
1629 AviMuxIn *avimuxin = AviMuxIn_from_IMemInputPin(iface);
1630
1631 TRACE("pin %p, pProps %p.\n", avimuxin, pProps);
1632
1633 if(!pProps)
1634 return E_POINTER;
1635
1636 pProps->cbAlign = 1;
1637 pProps->cbPrefix = 8;
1638 return S_OK;
1639}
1640
1642 IMemInputPin *iface, IMediaSample *pSample)
1643{
1644 AviMuxIn *avimuxin = AviMuxIn_from_IMemInputPin(iface);
1645
1646 TRACE("pin %p, pSample %p.\n", avimuxin, pSample);
1647
1648 return avimuxin->pin.pFuncsTable->pfnReceive(&avimuxin->pin, pSample);
1649}
1650
1652 IMediaSample **pSamples, LONG nSamples, LONG *nSamplesProcessed)
1653{
1654 AviMuxIn *avimuxin = AviMuxIn_from_IMemInputPin(iface);
1655 HRESULT hr = S_OK;
1656
1657 TRACE("pin %p, pSamples %p, nSamples %ld, nSamplesProcessed %p.\n",
1658 avimuxin, pSamples, nSamples, nSamplesProcessed);
1659
1660 for(*nSamplesProcessed=0; *nSamplesProcessed<nSamples; (*nSamplesProcessed)++)
1661 {
1662 hr = avimuxin->pin.pFuncsTable->pfnReceive(&avimuxin->pin, pSamples[*nSamplesProcessed]);
1663 if(hr != S_OK)
1664 break;
1665 }
1666
1667 return hr;
1668}
1669
1671{
1672 AviMuxIn *avimuxin = AviMuxIn_from_IMemInputPin(iface);
1673 AviMux *This = impl_from_in_IPin(&avimuxin->pin.pin.IPin_iface);
1674 HRESULT hr;
1675
1676 TRACE("avimuxin %p.\n", avimuxin);
1677
1678 if(!This->source.pMemInputPin)
1679 return S_FALSE;
1680
1681 hr = IMemInputPin_ReceiveCanBlock(This->source.pMemInputPin);
1682 return hr != S_FALSE ? S_OK : S_FALSE;
1683}
1684
1685static const IMemInputPinVtbl AviMuxIn_MemInputPinVtbl = {
1695};
1696
1698{
1699 return CONTAINING_RECORD(iface, AviMuxIn, IPropertyBag_iface);
1700}
1701
1703 IPropertyBag *iface, REFIID riid, void **ppv)
1704{
1705 AviMuxIn *avimuxin = AviMuxIn_from_IPropertyBag(iface);
1706 return IPin_QueryInterface(&avimuxin->pin.pin.IPin_iface, riid, ppv);
1707}
1708
1710{
1711 AviMuxIn *avimuxin = AviMuxIn_from_IPropertyBag(iface);
1712 AviMux *This = impl_from_in_IPin(&avimuxin->pin.pin.IPin_iface);
1713 return IBaseFilter_AddRef(&This->filter.IBaseFilter_iface);
1714}
1715
1717{
1718 AviMuxIn *avimuxin = AviMuxIn_from_IPropertyBag(iface);
1719 AviMux *This = impl_from_in_IPin(&avimuxin->pin.pin.IPin_iface);
1720 return IBaseFilter_Release(&This->filter.IBaseFilter_iface);
1721}
1722
1724 const WCHAR *name, VARIANT *value, IErrorLog *error_log)
1725{
1726 FIXME("iface %p, name %s, value %p, error_log %p, stub!\n",
1727 iface, debugstr_w(name), value, error_log);
1728 return E_NOTIMPL;
1729}
1730
1732 const WCHAR *name, VARIANT *value)
1733{
1734 FIXME("iface %p, name %s, value %s, stub!\n",
1736 return E_NOTIMPL;
1737}
1738
1739static const IPropertyBagVtbl AviMuxIn_PropertyBagVtbl = {
1745};
1746
1748{
1749 return CONTAINING_RECORD(iface, AviMuxIn, IQualityControl_iface);
1750}
1751
1753 IQualityControl *iface, REFIID riid, void **ppv)
1754{
1755 AviMuxIn *avimuxin = AviMuxIn_from_IQualityControl(iface);
1756 return IPin_QueryInterface(&avimuxin->pin.pin.IPin_iface, riid, ppv);
1757}
1758
1760{
1761 AviMuxIn *avimuxin = AviMuxIn_from_IQualityControl(iface);
1762 AviMux *This = impl_from_in_IPin(&avimuxin->pin.pin.IPin_iface);
1763 return IBaseFilter_AddRef(&This->filter.IBaseFilter_iface);
1764}
1765
1767{
1768 AviMuxIn *avimuxin = AviMuxIn_from_IQualityControl(iface);
1769 AviMux *This = impl_from_in_IPin(&avimuxin->pin.pin.IPin_iface);
1770 return IBaseFilter_Release(&This->filter.IBaseFilter_iface);
1771}
1772
1775{
1776 FIXME("iface %p, filter %p, type %u, proportion %ld, late %s, timestamp %s, stub!\n",
1777 iface, filter, q.Type, q.Proportion, wine_dbgstr_longlong(q.Late),
1778 wine_dbgstr_longlong(q.TimeStamp));
1779 return E_NOTIMPL;
1780}
1781
1783{
1784 FIXME("iface %p, sink %p, stub!\n", iface, sink);
1785 return E_NOTIMPL;
1786}
1787
1788static const IQualityControlVtbl AviMuxIn_QualityControlVtbl = {
1794};
1795
1797{
1799 WCHAR name[19];
1800 HRESULT hr;
1801
1802 if(avimux->input_pin_no >= MAX_PIN_NO-1)
1803 return E_FAIL;
1804
1805 swprintf(name, ARRAY_SIZE(name), L"Input %02u", avimux->input_pin_no + 1);
1806
1807 if (!(object = calloc(1, sizeof(*object))))
1808 return E_OUTOFMEMORY;
1809
1810 strmbase_sink_init(&object->pin, &avimux->filter, name, &sink_ops, NULL);
1811 object->pin.IMemInputPin_iface.lpVtbl = &AviMuxIn_MemInputPinVtbl;
1812 object->IAMStreamControl_iface.lpVtbl = &AviMuxIn_AMStreamControlVtbl;
1813 object->IPropertyBag_iface.lpVtbl = &AviMuxIn_PropertyBagVtbl;
1814 object->IQualityControl_iface.lpVtbl = &AviMuxIn_QualityControlVtbl;
1815
1816 hr = CoCreateInstance(&CLSID_MemoryAllocator, NULL, CLSCTX_INPROC_SERVER,
1817 &IID_IMemAllocator, (void **)&object->samples_allocator);
1818 if (FAILED(hr))
1819 {
1821 free(object);
1822 return hr;
1823 }
1824
1825 hr = CoCreateInstance(&CLSID_MemoryAllocator, NULL, CLSCTX_INPROC_SERVER,
1826 &IID_IMemAllocator, (void **)&object->pin.pAllocator);
1827 if (FAILED(hr))
1828 {
1829 IMemAllocator_Release(object->samples_allocator);
1831 free(object);
1832 return hr;
1833 }
1834
1835 object->indx = (AVISUPERINDEX *)&object->indx_data;
1836 object->ix = (AVISTDINDEX *)object->ix_data;
1837
1838 avimux->in[avimux->input_pin_no++] = object;
1839 return S_OK;
1840}
1841
1843{
1844 AviMux *avimux;
1845 HRESULT hr;
1846
1847 if (!(avimux = calloc(1, sizeof(AviMux))))
1848 return E_OUTOFMEMORY;
1849
1850 strmbase_filter_init(&avimux->filter, outer, &CLSID_AviDest, &filter_ops);
1851 avimux->IConfigAviMux_iface.lpVtbl = &ConfigAviMuxVtbl;
1853 avimux->IMediaSeeking_iface.lpVtbl = &MediaSeekingVtbl;
1856
1857 strmbase_source_init(&avimux->source, &avimux->filter, L"AVI Out", &source_ops);
1859 avimux->cur_stream = 0;
1860 avimux->cur_time = 0;
1861 avimux->stream = NULL;
1862
1863 hr = create_input_pin(avimux);
1864 if(FAILED(hr)) {
1867 free(avimux);
1868 return hr;
1869 }
1870
1871 avimux->interleave = 10000000;
1872
1873 TRACE("Created AVI mux %p.\n", avimux);
1874 *out = &avimux->filter.IUnknown_inner;
1875 return S_OK;
1876}
unsigned int dir
Definition: maze.c:112
static const IMediaSeekingVtbl MediaSeekingVtbl
Definition: avimux.c:983
static HRESULT WINAPI PersistMediaPropertyBag_Load(IPersistMediaPropertyBag *iface, IMediaPropertyBag *pPropBag, IErrorLog *pErrorLog)
Definition: avimux.c:1044
static HRESULT WINAPI MediaSeeking_GetCapabilities(IMediaSeeking *iface, DWORD *pCapabilities)
Definition: avimux.c:849
static HRESULT WINAPI ConfigAviMux_GetMasterStream(IConfigAviMux *iface, LONG *pStream)
Definition: avimux.c:705
static HRESULT WINAPI MediaSeeking_QueryInterface(IMediaSeeking *iface, REFIID riid, void **ppv)
Definition: avimux.c:830
static HRESULT queue_sample(AviMux *avimux, AviMuxIn *avimuxin, IMediaSample *sample)
Definition: avimux.c:383
static HRESULT WINAPI AviMuxOut_QualityControl_QueryInterface(IQualityControl *iface, REFIID riid, void **ppv)
Definition: avimux.c:1229
static HRESULT idx1_add_entry(AviMux *avimux, DWORD ckid, DWORD flags, DWORD off, DWORD len)
Definition: avimux.c:238
static const IPersistMediaPropertyBagVtbl PersistMediaPropertyBagVtbl
Definition: avimux.c:1060
static HRESULT WINAPI MediaSeeking_GetAvailable(IMediaSeeking *iface, LONGLONG *pEarliest, LONGLONG *pLatest)
Definition: avimux.c:954
static AviMux * impl_from_IConfigInterleaving(IConfigInterleaving *iface)
Definition: avimux.c:738
static const IPropertyBagVtbl AviMuxIn_PropertyBagVtbl
Definition: avimux.c:1739
static HRESULT WINAPI PersistMediaPropertyBag_Save(IPersistMediaPropertyBag *iface, IMediaPropertyBag *pPropBag, BOOL fClearDirty, BOOL fSaveAllProperties)
Definition: avimux.c:1052
static AviMux * impl_from_IPersistMediaPropertyBag(IPersistMediaPropertyBag *iface)
Definition: avimux.c:1006
static const IConfigInterleavingVtbl ConfigInterleavingVtbl
Definition: avimux.c:815
static HRESULT WINAPI ConfigInterleaving_get_Interleaving(IConfigInterleaving *iface, REFERENCE_TIME *prtInterleave, REFERENCE_TIME *prtPreroll)
Definition: avimux.c:807
static AviMuxIn * AviMuxIn_from_IAMStreamControl(IAMStreamControl *iface)
Definition: avimux.c:1507
static HRESULT flush_queue(AviMux *avimux, AviMuxIn *avimuxin, BOOL closing)
Definition: avimux.c:257
static HRESULT avi_mux_cleanup_stream(struct strmbase_filter *iface)
Definition: avimux.c:410
static ULONG WINAPI AviMuxOut_QualityControl_AddRef(IQualityControl *iface)
Definition: avimux.c:1236
static HRESULT WINAPI AviMuxIn_MemInputPin_GetAllocatorRequirements(IMemInputPin *iface, ALLOCATOR_PROPERTIES *pProps)
Definition: avimux.c:1626
static HRESULT avi_mux_init_stream(struct strmbase_filter *iface)
Definition: avimux.c:547
HRESULT avi_mux_create(IUnknown *outer, IUnknown **out)
Definition: avimux.c:1842
static AviMux * impl_from_IConfigAviMux(IConfigAviMux *iface)
Definition: avimux.c:674
static HRESULT WINAPI MediaSeeking_IsFormatSupported(IMediaSeeking *iface, const GUID *pFormat)
Definition: avimux.c:865
static HRESULT WINAPI AviMuxIn_PropertyBag_QueryInterface(IPropertyBag *iface, REFIID riid, void **ppv)
Definition: avimux.c:1702
static HRESULT WINAPI MediaSeeking_GetDuration(IMediaSeeking *iface, LONGLONG *pDuration)
Definition: avimux.c:905
static HRESULT WINAPI AviMuxIn_QualityControl_QueryInterface(IQualityControl *iface, REFIID riid, void **ppv)
Definition: avimux.c:1752
static HRESULT WINAPI AviMuxOut_QualityControl_Notify(IQualityControl *iface, IBaseFilter *sender, Quality q)
Definition: avimux.c:1248
static const IConfigAviMuxVtbl ConfigAviMuxVtbl
Definition: avimux.c:728
static ULONG WINAPI AviMuxIn_PropertyBag_AddRef(IPropertyBag *iface)
Definition: avimux.c:1709
static const IQualityControlVtbl AviMuxOut_QualityControlVtbl
Definition: avimux.c:1268
static AviMux * impl_from_IMediaSeeking(IMediaSeeking *iface)
Definition: avimux.c:825
static HRESULT WINAPI ConfigInterleaving_get_Mode(IConfigInterleaving *iface, InterleavingMode *pMode)
Definition: avimux.c:785
static HRESULT WINAPI MediaSeeking_CheckCapabilities(IMediaSeeking *iface, DWORD *pCapabilities)
Definition: avimux.c:857
static HRESULT out_write(AviMux *This, const void *data, int size)
Definition: avimux.c:209
static HRESULT WINAPI MediaSeeking_IsUsingTimeFormat(IMediaSeeking *iface, const GUID *pFormat)
Definition: avimux.c:889
static struct strmbase_pin * avi_mux_get_pin(struct strmbase_filter *iface, unsigned int index)
Definition: avimux.c:118
static HRESULT WINAPI AviMuxIn_AMStreamControl_StartAt(IAMStreamControl *iface, const REFERENCE_TIME *start, DWORD cookie)
Definition: avimux.c:1533
static ULONG WINAPI AviMuxIn_AMStreamControl_Release(IAMStreamControl *iface)
Definition: avimux.c:1526
static const IQualityControlVtbl AviMuxIn_QualityControlVtbl
Definition: avimux.c:1788
static HRESULT WINAPI MediaSeeking_GetPreroll(IMediaSeeking *iface, LONGLONG *pllPreroll)
Definition: avimux.c:976
static HRESULT out_seek(AviMux *This, int pos)
Definition: avimux.c:189
static ULONG WINAPI AviMuxOut_QualityControl_Release(IQualityControl *iface)
Definition: avimux.c:1242
static HRESULT WINAPI MediaSeeking_SetRate(IMediaSeeking *iface, double dRate)
Definition: avimux.c:962
static HRESULT WINAPI AviMuxIn_MemInputPin_GetAllocator(IMemInputPin *iface, IMemAllocator **ppAllocator)
Definition: avimux.c:1589
static HRESULT WINAPI ConfigAviMux_SetOutputCompatibilityIndex(IConfigAviMux *iface, BOOL fOldIndex)
Definition: avimux.c:712
static HRESULT WINAPI SpecifyPropertyPages_GetPages(ISpecifyPropertyPages *iface, CAUUID *pPages)
Definition: avimux.c:1094
static HRESULT out_flush(AviMux *This)
Definition: avimux.c:171
static HRESULT WINAPI AviMuxIn_AMStreamControl_QueryInterface(IAMStreamControl *iface, REFIID riid, void **ppv)
Definition: avimux.c:1512
static HRESULT WINAPI AviMuxOut_QualityControl_SetSink(IQualityControl *iface, IQualityControl *piqc)
Definition: avimux.c:1260
static ULONG WINAPI AviMuxIn_AMStreamControl_AddRef(IAMStreamControl *iface)
Definition: avimux.c:1519
static ULONG WINAPI ConfigInterleaving_Release(IConfigInterleaving *iface)
Definition: avimux.c:756
static HRESULT WINAPI ConfigAviMux_GetOutputCompatibilityIndex(IConfigAviMux *iface, BOOL *pfOldIndex)
Definition: avimux.c:720
static HRESULT WINAPI AviMuxIn_MemInputPin_Receive(IMemInputPin *iface, IMediaSample *pSample)
Definition: avimux.c:1641
static HRESULT WINAPI PersistMediaPropertyBag_GetClassID(IPersistMediaPropertyBag *iface, CLSID *pClassID)
Definition: avimux.c:1030
static HRESULT WINAPI PersistMediaPropertyBag_InitNew(IPersistMediaPropertyBag *iface)
Definition: avimux.c:1037
static HRESULT WINAPI MediaSeeking_GetRate(IMediaSeeking *iface, double *pdRate)
Definition: avimux.c:969
static HRESULT WINAPI MediaSeeking_SetPositions(IMediaSeeking *iface, LONGLONG *pCurrent, DWORD dwCurrentFlags, LONGLONG *pStop, DWORD dwStopFlags)
Definition: avimux.c:938
static AviMux * impl_from_source_pin(struct strmbase_pin *iface)
Definition: avimux.c:1109
static HRESULT WINAPI AviMuxIn_PropertyBag_Write(IPropertyBag *iface, const WCHAR *name, VARIANT *value)
Definition: avimux.c:1731
#define MAX_PIN_NO
Definition: avimux.c:25
static const struct strmbase_source_ops source_ops
Definition: avimux.c:1215
static HRESULT WINAPI ConfigAviMux_SetMasterStream(IConfigAviMux *iface, LONG iStream)
Definition: avimux.c:698
static AviMux * impl_from_out_IQualityControl(IQualityControl *iface)
Definition: avimux.c:1224
static AviMuxIn * impl_sink_from_strmbase_pin(struct strmbase_pin *iface)
Definition: avimux.c:1276
static HRESULT source_query_accept(struct strmbase_pin *iface, const AM_MEDIA_TYPE *mt)
Definition: avimux.c:1127
static AviMux * impl_from_strmbase_filter(struct strmbase_filter *filter)
Definition: avimux.c:113
static const struct strmbase_sink_ops sink_ops
Definition: avimux.c:1492
static AviMux * impl_from_in_IPin(IPin *iface)
Definition: avimux.c:1501
static HRESULT WINAPI MediaSeeking_GetPositions(IMediaSeeking *iface, LONGLONG *pCurrent, LONGLONG *pStop)
Definition: avimux.c:946
static const IAMStreamControlVtbl AviMuxIn_AMStreamControlVtbl
Definition: avimux.c:1554
static HRESULT sink_query_accept(struct strmbase_pin *base, const AM_MEDIA_TYPE *pmt)
Definition: avimux.c:1300
static void avi_mux_destroy(struct strmbase_filter *iface)
Definition: avimux.c:129
static const struct strmbase_filter_ops filter_ops
Definition: avimux.c:665
static ULONG WINAPI AviMuxIn_QualityControl_AddRef(IQualityControl *iface)
Definition: avimux.c:1759
static HRESULT WINAPI AviMuxIn_MemInputPin_ReceiveMultiple(IMemInputPin *iface, IMediaSample **pSamples, LONG nSamples, LONG *nSamplesProcessed)
Definition: avimux.c:1651
static void avi_mux_sink_disconnect(struct strmbase_sink *iface)
Definition: avimux.c:1469
static ULONG WINAPI PersistMediaPropertyBag_AddRef(IPersistMediaPropertyBag *iface)
Definition: avimux.c:1018
static HRESULT avi_mux_sink_connect(struct strmbase_sink *iface, IPin *peer, const AM_MEDIA_TYPE *pmt)
Definition: avimux.c:1418
static HRESULT WINAPI ConfigAviMux_QueryInterface(IConfigAviMux *iface, REFIID riid, void **ppv)
Definition: avimux.c:679
static ULONG WINAPI MediaSeeking_AddRef(IMediaSeeking *iface)
Definition: avimux.c:837
static HRESULT WINAPI AviMuxIn_PropertyBag_Read(IPropertyBag *iface, const WCHAR *name, VARIANT *value, IErrorLog *error_log)
Definition: avimux.c:1723
static ULONG WINAPI ConfigAviMux_AddRef(IConfigAviMux *iface)
Definition: avimux.c:686
static AviMux * impl_from_ISpecifyPropertyPages(ISpecifyPropertyPages *iface)
Definition: avimux.c:1070
static HRESULT WINAPI AviMuxIn_QualityControl_Notify(IQualityControl *iface, IBaseFilter *filter, Quality q)
Definition: avimux.c:1773
static HRESULT WINAPI AviMuxIn_AMStreamControl_GetInfo(IAMStreamControl *iface, AM_STREAM_INFO *info)
Definition: avimux.c:1547
static HRESULT WINAPI AviMuxIn_Receive(struct strmbase_sink *base, IMediaSample *pSample)
Definition: avimux.c:1315
#define AVISUPERINDEX_ENTRIES
Definition: avimux.c:26
static HRESULT WINAPI MediaSeeking_SetTimeFormat(IMediaSeeking *iface, const GUID *pFormat)
Definition: avimux.c:897
static HRESULT avi_mux_query_interface(struct strmbase_filter *iface, REFIID iid, void **out)
Definition: avimux.c:150
static HRESULT WINAPI AviMuxOut_DecideAllocator(struct strmbase_source *base, IMemInputPin *pPin, IMemAllocator **pAlloc)
Definition: avimux.c:1186
static HRESULT WINAPI MediaSeeking_GetCurrentPosition(IMediaSeeking *iface, LONGLONG *pCurrent)
Definition: avimux.c:921
static HRESULT WINAPI AviMuxIn_QualityControl_SetSink(IQualityControl *iface, IQualityControl *sink)
Definition: avimux.c:1782
static ULONG WINAPI AviMuxIn_MemInputPin_Release(IMemInputPin *iface)
Definition: avimux.c:1582
#define ALIGN(x)
Definition: avimux.c:28
static HRESULT WINAPI AviMuxIn_MemInputPin_ReceiveCanBlock(IMemInputPin *iface)
Definition: avimux.c:1670
static HRESULT WINAPI MediaSeeking_GetTimeFormat(IMediaSeeking *iface, GUID *pFormat)
Definition: avimux.c:881
static HRESULT source_get_media_type(struct strmbase_pin *base, unsigned int iPosition, AM_MEDIA_TYPE *amt)
Definition: avimux.c:1167
static HRESULT create_input_pin(AviMux *)
Definition: avimux.c:1796
static ULONG WINAPI ConfigAviMux_Release(IConfigAviMux *iface)
Definition: avimux.c:692
static HRESULT WINAPI MediaSeeking_QueryPreferredFormat(IMediaSeeking *iface, GUID *pFormat)
Definition: avimux.c:873
static ULONG WINAPI SpecifyPropertyPages_AddRef(ISpecifyPropertyPages *iface)
Definition: avimux.c:1082
static HRESULT WINAPI AviMuxIn_AMStreamControl_StopAt(IAMStreamControl *iface, const REFERENCE_TIME *stop, BOOL send_extra, DWORD cookie)
Definition: avimux.c:1540
static ULONG WINAPI SpecifyPropertyPages_Release(ISpecifyPropertyPages *iface)
Definition: avimux.c:1088
static HRESULT WINAPI MediaSeeking_GetStopPosition(IMediaSeeking *iface, LONGLONG *pStop)
Definition: avimux.c:913
static ULONG WINAPI MediaSeeking_Release(IMediaSeeking *iface)
Definition: avimux.c:843
static ULONG WINAPI AviMuxIn_MemInputPin_AddRef(IMemInputPin *iface)
Definition: avimux.c:1575
static AviMuxIn * AviMuxIn_from_IMemInputPin(IMemInputPin *iface)
Definition: avimux.c:1563
static HRESULT WINAPI ConfigInterleaving_put_Mode(IConfigInterleaving *iface, InterleavingMode mode)
Definition: avimux.c:762
static HRESULT WINAPI AviMuxIn_MemInputPin_NotifyAllocator(IMemInputPin *iface, IMemAllocator *pAllocator, BOOL bReadOnly)
Definition: avimux.c:1604
static HRESULT WINAPI ConfigInterleaving_put_Interleaving(IConfigInterleaving *iface, const REFERENCE_TIME *prtInterleave, const REFERENCE_TIME *prtPreroll)
Definition: avimux.c:793
static HRESULT source_query_interface(struct strmbase_pin *iface, REFIID iid, void **out)
Definition: avimux.c:1114
static AviMuxIn * AviMuxIn_from_IPropertyBag(IPropertyBag *iface)
Definition: avimux.c:1697
static ULONG WINAPI AviMuxIn_PropertyBag_Release(IPropertyBag *iface)
Definition: avimux.c:1716
#define AVISTDINDEX_ENTRIES
Definition: avimux.c:27
static ULONG WINAPI ConfigInterleaving_AddRef(IConfigInterleaving *iface)
Definition: avimux.c:750
static ULONG WINAPI AviMuxIn_QualityControl_Release(IQualityControl *iface)
Definition: avimux.c:1766
static HRESULT WINAPI ConfigInterleaving_QueryInterface(IConfigInterleaving *iface, REFIID riid, void **ppv)
Definition: avimux.c:743
static HRESULT WINAPI PersistMediaPropertyBag_QueryInterface(IPersistMediaPropertyBag *iface, REFIID riid, void **ppv)
Definition: avimux.c:1011
static ULONG WINAPI PersistMediaPropertyBag_Release(IPersistMediaPropertyBag *iface)
Definition: avimux.c:1024
static const ISpecifyPropertyPagesVtbl SpecifyPropertyPagesVtbl
Definition: avimux.c:1102
static HRESULT WINAPI SpecifyPropertyPages_QueryInterface(ISpecifyPropertyPages *iface, REFIID riid, void **ppv)
Definition: avimux.c:1075
static HRESULT WINAPI AviMuxIn_MemInputPin_QueryInterface(IMemInputPin *iface, REFIID riid, void **ppv)
Definition: avimux.c:1568
static AviMuxIn * AviMuxIn_from_IQualityControl(IQualityControl *iface)
Definition: avimux.c:1747
static HRESULT WINAPI MediaSeeking_ConvertTimeFormat(IMediaSeeking *iface, LONGLONG *pTarget, const GUID *pTargetFormat, LONGLONG Source, const GUID *pSourceFormat)
Definition: avimux.c:929
static const IMemInputPinVtbl AviMuxIn_MemInputPinVtbl
Definition: avimux.c:1685
static HRESULT sink_query_interface(struct strmbase_pin *iface, REFIID iid, void **out)
Definition: avimux.c:1281
static HRESULT WINAPI AviMuxOut_AttemptConnection(struct strmbase_source *iface, IPin *pReceivePin, const AM_MEDIA_TYPE *pmt)
Definition: avimux.c:1136
#define AVIIF_KEYFRAME
Definition: aviriff.h:131
#define ckidAVISUPERINDEX
Definition: aviriff.h:194
#define AVIF_HASINDEX
Definition: aviriff.h:46
#define FCC(ch0, ch1, ch2, ch3)
Definition: aviriff.h:38
#define ckidMAINAVIHEADER
Definition: aviriff.h:53
#define AVISTDINDEX_DELTAFRAME
Definition: aviriff.h:211
#define AVIF_TRUSTCKTYPE
Definition: aviriff.h:49
struct _aviextheader AVIEXTHEADER
#define ckidAVIEXTHEADER
Definition: aviriff.h:72
#define streamtypeVIDEO
Definition: aviriff.h:92
#define ckidSTREAMHEADER
Definition: aviriff.h:88
#define ckidSTREAMLIST
Definition: aviriff.h:81
struct _rifflist RIFFLIST
#define AVI_INDEX_OF_INDEXES
Definition: aviriff.h:172
#define ckidAVIOLDINDEX
Definition: aviriff.h:127
#define ckidSTREAMFORMAT
Definition: aviriff.h:125
#define ckidODML
Definition: aviriff.h:71
struct _avimainheader AVIMAINHEADER
#define AVI_INDEX_OF_CHUNKS
Definition: aviriff.h:173
struct _riffchunk RIFFCHUNK
enum _PinDirection PIN_DIRECTION
@ PINDIR_INPUT
Definition: axcore.idl:41
@ AM_SAMPLE_TIMEDISCONTINUITY
Definition: axcore.idl:442
@ AM_SAMPLE_SPLICEPOINT
Definition: axcore.idl:437
#define WINE_DEFAULT_DEBUG_CHANNEL(t)
Definition: precomp.h:23
#define ARRAY_SIZE(A)
Definition: main.h:20
static INT max_size
Definition: history.c:51
#define FIXME(fmt,...)
Definition: precomp.h:53
#define ERR(fmt,...)
Definition: precomp.h:57
#define E_OUTOFMEMORY
Definition: ddrawi.h:100
#define E_INVALIDARG
Definition: ddrawi.h:101
#define E_NOTIMPL
Definition: ddrawi.h:99
#define E_FAIL
Definition: ddrawi.h:102
#define realloc
Definition: debug_ros.c:6
#define free
Definition: debug_ros.c:5
#define malloc
Definition: debug_ros.c:4
HRESULT hr
Definition: delayimp.cpp:582
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
HRESULT WINAPI DECLSPEC_HOTPATCH CoCreateInstance(REFCLSID rclsid, IUnknown *outer, DWORD cls_context, REFIID riid, void **obj)
Definition: combase.c:1685
static __inline const char * wine_dbgstr_longlong(ULONGLONG ll)
Definition: compat.h:49
#define swprintf
Definition: precomp.h:40
DWORD FOURCC
Definition: dmdls.h:25
LONGLONG REFERENCE_TIME
Definition: dmusicks.h:9
static const char * debugstr_variant(const VARIANT *var)
Definition: dom.c:505
#define L(x)
Definition: resources.c:13
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
FxIoTarget * pTarget
Definition: fxdeviceapi.cpp:97
FxCollectionEntry * cur
LARGE_INTEGER li
Definition: fxtimerapi.cpp:235
GLuint start
Definition: gl.h:1545
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
GLdouble GLdouble GLdouble GLdouble q
Definition: gl.h:2063
GLsizeiptr size
Definition: glext.h:5919
GLuint index
Definition: glext.h:6031
GLenum mode
Definition: glext.h:6217
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
GLuint in
Definition: glext.h:9616
GLbitfield flags
Definition: glext.h:7161
GLsizei GLenum GLboolean sink
Definition: glext.h:5672
GLenum GLsizei len
Definition: glext.h:6722
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
REFIID riid
Definition: atlbase.h:39
REFIID LPVOID * ppv
Definition: atlbase.h:39
Definition: axcore.idl:92
#define S_OK
Definition: intsafe.h:52
#define SUCCEEDED(hr)
Definition: intsafe.h:50
#define FAILED(hr)
Definition: intsafe.h:51
#define debugstr_guid
Definition: kernel32.h:35
#define debugstr_w
Definition: kernel32.h:32
#define GUID_NULL
Definition: ks.h:106
#define FOURCC(a, b, c, d)
Definition: memtrack.h:4
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
static const char mbstate_t *static wchar_t const char mbstate_t *static const wchar_t int *static double
Definition: string.c:91
static IUnknown * outer
Definition: compobj.c:82
INT WINAPI MulDiv(INT nNumber, INT nNumerator, INT nDenominator)
Definition: muldiv.c:25
_In_ UINT _In_ UINT _In_ PNDIS_PACKET Source
Definition: ndis.h:3169
const GUID IID_IPropertyBag
short WCHAR
Definition: pedump.c:58
long LONG
Definition: pedump.c:60
const GUID IID_ISpecifyPropertyPages
Definition: proxy.cpp:12
#define IsEqualGUID(rguid1, rguid2)
Definition: guiddef.h:147
#define IsEqualIID(riid1, riid2)
Definition: guiddef.h:95
#define REFIID
Definition: guiddef.h:118
#define calloc
Definition: rosglue.h:14
#define offsetof(TYPE, MEMBER)
#define memset(x, y, z)
Definition: compat.h:39
#define TRACE(s)
Definition: solgame.cpp:4
void strmbase_source_init(struct strmbase_source *pin, struct strmbase_filter *filter, const WCHAR *name, const struct strmbase_source_ops *func_table)
Definition: pin.c:765
void strmbase_sink_cleanup(struct strmbase_sink *pin)
Definition: pin.c:1185
void strmbase_sink_init(struct strmbase_sink *pin, struct strmbase_filter *filter, const WCHAR *name, const struct strmbase_sink_ops *ops, IMemAllocator *allocator)
Definition: pin.c:1168
void strmbase_filter_cleanup(struct strmbase_filter *filter)
Definition: filter.c:540
void strmbase_source_cleanup(struct strmbase_source *pin)
Definition: pin.c:778
void strmbase_filter_init(struct strmbase_filter *filter, IUnknown *outer, const CLSID *clsid, const struct strmbase_filter_ops *func_table)
Definition: filter.c:517
HRESULT WINAPI BaseOutputPinImpl_AttemptConnection(struct strmbase_source *pin, IPin *peer, const AM_MEDIA_TYPE *mt)
Definition: pin.c:710
LONGLONG stream_time
Definition: avimux.c:39
REFERENCE_TIME stop
Definition: avimux.c:37
FOURCC fcc
Definition: avimux.c:44
BYTE ix_data[FIELD_OFFSET(AVISTDINDEX, aIndex[AVISTDINDEX_ENTRIES])]
Definition: avimux.c:67
IMediaSample * samples_head
Definition: avimux.c:70
IAMStreamControl IAMStreamControl_iface
Definition: avimux.c:32
AVISTREAMHEADER strh
Definition: avimux.c:42
struct AviMuxIn::@328 * strf
AVISTDINDEX * ix
Definition: avimux.c:60
int stream_id
Definition: avimux.c:38
IPropertyBag IPropertyBag_iface
Definition: avimux.c:33
int ix_off
Definition: avimux.c:59
IQualityControl IQualityControl_iface
Definition: avimux.c:34
REFERENCE_TIME avg_time_per_frame
Definition: avimux.c:36
AVISUPERINDEX * indx
Definition: avimux.c:48
DWORD cb
Definition: avimux.c:45
struct strmbase_sink pin
Definition: avimux.c:31
IMemAllocator * samples_allocator
Definition: avimux.c:71
Definition: avimux.c:74
REFERENCE_TIME stop
Definition: avimux.c:92
int movi_off
Definition: avimux.c:105
REFERENCE_TIME start
Definition: avimux.c:92
AVIINDEXENTRY * idx1
Definition: avimux.c:97
LONGLONG cur_time
Definition: avimux.c:100
IPersistMediaPropertyBag IPersistMediaPropertyBag_iface
Definition: avimux.c:79
IMediaSeeking IMediaSeeking_iface
Definition: avimux.c:78
REFERENCE_TIME preroll
Definition: avimux.c:84
int size
Definition: avimux.c:107
int idx1_size
Definition: avimux.c:96
int input_pin_no
Definition: avimux.c:89
struct strmbase_source source
Definition: avimux.c:86
IConfigInterleaving IConfigInterleaving_iface
Definition: avimux.c:77
int idx1_entries
Definition: avimux.c:95
IQualityControl IQualityControl_iface
Definition: avimux.c:87
AVIMAINHEADER avih
Definition: avimux.c:93
int cur_stream
Definition: avimux.c:99
struct strmbase_filter filter
Definition: avimux.c:75
ISpecifyPropertyPages ISpecifyPropertyPages_iface
Definition: avimux.c:80
IStream * stream
Definition: avimux.c:108
IConfigAviMux IConfigAviMux_iface
Definition: avimux.c:76
int out_pos
Definition: avimux.c:106
AviMuxIn * in[MAX_PIN_NO-1]
Definition: avimux.c:90
int buf_pos
Definition: avimux.c:102
InterleavingMode mode
Definition: avimux.c:82
REFERENCE_TIME interleave
Definition: avimux.c:83
DWORD biCompression
Definition: amvideo.idl:35
DWORD biSizeImage
Definition: amvideo.idl:36
DWORD dwChunkLength
Definition: vfw.h:989
DWORD dwChunkOffset
Definition: vfw.h:988
DWORD ckid
Definition: vfw.h:986
DWORD dwFlags
Definition: vfw.h:987
FOURCC fcc
Definition: aviriff.h:75
DWORD dwGrandFrames
Definition: aviriff.h:77
DWORD cb
Definition: aviriff.h:76
DWORD dwSuggestedBufferSize
Definition: aviriff.h:65
DWORD dwSize
Definition: aviriff.h:216
DWORD dwOffset
Definition: aviriff.h:215
DWORD nEntriesInUse
Definition: aviriff.h:225
AVISTDINDEX_ENTRY aIndex[ANYSIZE_ARRAY]
Definition: aviriff.h:229
DWORDLONG qwBaseOffset
Definition: aviriff.h:227
FOURCC fccHandler
Definition: aviriff.h:103
FOURCC fccType
Definition: aviriff.h:102
DWORD dwSuggestedBufferSize
Definition: aviriff.h:112
DWORD dwLength
Definition: aviriff.h:111
struct _avisuperindex::_avisuperindex_entry aIndex[ANYSIZE_ARRAY]
DWORD nEntriesInUse
Definition: aviriff.h:201
FOURCC fcc
Definition: aviriff.h:27
DWORD cb
Definition: aviriff.h:28
FOURCC fcc
Definition: aviriff.h:33
DWORD cb
Definition: aviriff.h:34
FOURCC fccListType
Definition: aviriff.h:35
Definition: cookie.c:34
Definition: filter.c:165
IBaseFilter * filter
Definition: filtergraph.c:75
IMediaSeeking IMediaSeeking_iface
Definition: filter.c:167
Definition: name.c:39
Definition: wave.c:25
IPin IPin_iface
Definition: strmbase.h:57
struct strmbase_filter * filter
Definition: strmbase.h:58
struct strmbase_pin pin
Definition: strmbase.h:106
struct strmbase_pin pin
Definition: strmbase.h:79
BITMAPINFOHEADER bmiHeader
Definition: amvideo.idl:189
REFERENCE_TIME AvgTimePerFrame
Definition: amvideo.idl:187
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:255
int64_t LONGLONG
Definition: typedefs.h:68
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260
uint32_t ULONG
Definition: typedefs.h:59
LONGLONG QuadPart
Definition: typedefs.h:114
Definition: pdh_main.c:64
#define VFW_E_INVALID_DIRECTION
Definition: vfwmsgs.h:47
#define VFW_E_START_TIME_AFTER_END
Definition: vfwmsgs.h:79
#define VFW_S_NO_MORE_ITEMS
Definition: vfwmsgs.h:19
static const WCHAR props[]
Definition: wbemdisp.c:288
wchar_t tm const _CrtWcstime_Writes_and_advances_ptr_ count wchar_t ** out
Definition: wcsftime.cpp:383
#define WINAPI
Definition: msvc.h:6
#define S_FALSE
Definition: winerror.h:3451
#define E_NOINTERFACE
Definition: winerror.h:3479
#define E_POINTER
Definition: winerror.h:3480
unsigned char BYTE
Definition: xxhash.c:193