1/*
2 * DirectShow capture interface
3 * Copyright (c) 2010 Ramiro Polla
4 *
5 * This file is part of FFmpeg.
6 *
7 * FFmpeg is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * FFmpeg is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with FFmpeg; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 */
21
22#include "dshow_capture.h"
23
24DECLARE_QUERYINTERFACE(libAVFilter,
25    { {&IID_IUnknown,0}, {&IID_IBaseFilter,0} })
26DECLARE_ADDREF(libAVFilter)
27DECLARE_RELEASE(libAVFilter)
28
29long WINAPI
30libAVFilter_GetClassID(libAVFilter *this, CLSID *id)
31{
32    dshowdebug("libAVFilter_GetClassID(%p)\n", this);
33    /* I'm not creating a ClassID just for this. */
34    return E_FAIL;
35}
36long WINAPI
37libAVFilter_Stop(libAVFilter *this)
38{
39    dshowdebug("libAVFilter_Stop(%p)\n", this);
40    this->state = State_Stopped;
41    return S_OK;
42}
43long WINAPI
44libAVFilter_Pause(libAVFilter *this)
45{
46    dshowdebug("libAVFilter_Pause(%p)\n", this);
47    this->state = State_Paused;
48    return S_OK;
49}
50long WINAPI
51libAVFilter_Run(libAVFilter *this, REFERENCE_TIME start)
52{
53    dshowdebug("libAVFilter_Run(%p) %"PRId64"\n", this, start);
54    this->state = State_Running;
55    this->start_time = start;
56    return S_OK;
57}
58long WINAPI
59libAVFilter_GetState(libAVFilter *this, DWORD ms, FILTER_STATE *state)
60{
61    dshowdebug("libAVFilter_GetState(%p)\n", this);
62    if (!state)
63        return E_POINTER;
64    *state = this->state;
65    return S_OK;
66}
67long WINAPI
68libAVFilter_SetSyncSource(libAVFilter *this, IReferenceClock *clock)
69{
70    dshowdebug("libAVFilter_SetSyncSource(%p)\n", this);
71
72    if (this->clock != clock) {
73        if (this->clock)
74            IReferenceClock_Release(this->clock);
75        this->clock = clock;
76        if (clock)
77            IReferenceClock_AddRef(clock);
78    }
79
80    return S_OK;
81}
82long WINAPI
83libAVFilter_GetSyncSource(libAVFilter *this, IReferenceClock **clock)
84{
85    dshowdebug("libAVFilter_GetSyncSource(%p)\n", this);
86
87    if (!clock)
88        return E_POINTER;
89    if (this->clock)
90        IReferenceClock_AddRef(this->clock);
91    *clock = this->clock;
92
93    return S_OK;
94}
95long WINAPI
96libAVFilter_EnumPins(libAVFilter *this, IEnumPins **enumpin)
97{
98    libAVEnumPins *new;
99    dshowdebug("libAVFilter_EnumPins(%p)\n", this);
100
101    if (!enumpin)
102        return E_POINTER;
103    new = libAVEnumPins_Create(this->pin, this);
104    if (!new)
105        return E_OUTOFMEMORY;
106
107    *enumpin = (IEnumPins *) new;
108    return S_OK;
109}
110long WINAPI
111libAVFilter_FindPin(libAVFilter *this, const wchar_t *id, IPin **pin)
112{
113    libAVPin *found = NULL;
114    dshowdebug("libAVFilter_FindPin(%p)\n", this);
115
116    if (!id || !pin)
117        return E_POINTER;
118    if (!wcscmp(id, L"In")) {
119        found = this->pin;
120        libAVPin_AddRef(found);
121    }
122    *pin = (IPin *) found;
123    if (!found)
124        return VFW_E_NOT_FOUND;
125
126    return S_OK;
127}
128long WINAPI
129libAVFilter_QueryFilterInfo(libAVFilter *this, FILTER_INFO *info)
130{
131    dshowdebug("libAVFilter_QueryFilterInfo(%p)\n", this);
132
133    if (!info)
134        return E_POINTER;
135    if (this->info.pGraph)
136        IFilterGraph_AddRef(this->info.pGraph);
137    *info = this->info;
138
139    return S_OK;
140}
141long WINAPI
142libAVFilter_JoinFilterGraph(libAVFilter *this, IFilterGraph *graph,
143                            const wchar_t *name)
144{
145    dshowdebug("libAVFilter_JoinFilterGraph(%p)\n", this);
146
147    this->info.pGraph = graph;
148    if (name)
149        wcscpy(this->info.achName, name);
150
151    return S_OK;
152}
153long WINAPI
154libAVFilter_QueryVendorInfo(libAVFilter *this, wchar_t **info)
155{
156    dshowdebug("libAVFilter_QueryVendorInfo(%p)\n", this);
157
158    if (!info)
159        return E_POINTER;
160    *info = wcsdup(L"libAV");
161
162    return S_OK;
163}
164
165static int
166libAVFilter_Setup(libAVFilter *this, void *priv_data, void *callback,
167                  enum dshowDeviceType type)
168{
169    IBaseFilterVtbl *vtbl = this->vtbl;
170    SETVTBL(vtbl, libAVFilter, QueryInterface);
171    SETVTBL(vtbl, libAVFilter, AddRef);
172    SETVTBL(vtbl, libAVFilter, Release);
173    SETVTBL(vtbl, libAVFilter, GetClassID);
174    SETVTBL(vtbl, libAVFilter, Stop);
175    SETVTBL(vtbl, libAVFilter, Pause);
176    SETVTBL(vtbl, libAVFilter, Run);
177    SETVTBL(vtbl, libAVFilter, GetState);
178    SETVTBL(vtbl, libAVFilter, SetSyncSource);
179    SETVTBL(vtbl, libAVFilter, GetSyncSource);
180    SETVTBL(vtbl, libAVFilter, EnumPins);
181    SETVTBL(vtbl, libAVFilter, FindPin);
182    SETVTBL(vtbl, libAVFilter, QueryFilterInfo);
183    SETVTBL(vtbl, libAVFilter, JoinFilterGraph);
184    SETVTBL(vtbl, libAVFilter, QueryVendorInfo);
185
186    this->pin = libAVPin_Create(this);
187
188    this->priv_data = priv_data;
189    this->callback  = callback;
190    this->type      = type;
191
192    return 1;
193}
194static int
195libAVFilter_Cleanup(libAVFilter *this)
196{
197    libAVPin_Release(this->pin);
198    return 1;
199}
200DECLARE_CREATE(libAVFilter, libAVFilter_Setup(this, priv_data, callback, type),
201               void *priv_data, void *callback, enum dshowDeviceType type)
202DECLARE_DESTROY(libAVFilter, libAVFilter_Cleanup)
203