mediastreamfilter.c 10.6 KB
Newer Older
1 2 3
/*
 * Implementation of MediaStream Filter
 *
4
 * Copyright 2008, 2012 Christian Costa
5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
 */

#include "wine/debug.h"

#define COBJMACROS

#include "winbase.h"
#include "wingdi.h"
27 28 29
#include "dshow.h"

#include "wine/strmbase.h"
30 31 32 33 34 35 36 37

#include "amstream_private.h"

#include "ddstream.h"

WINE_DEFAULT_DEBUG_CHANNEL(amstream);

typedef struct {
38
    BaseFilter filter;
39
    ULONG nb_streams;
40
    IAMMediaStream** streams;
41 42
} IMediaStreamFilterImpl;

43 44
static inline IMediaStreamFilterImpl *impl_from_IMediaStreamFilter(IMediaStreamFilter *iface)
{
45
    return CONTAINING_RECORD(iface, IMediaStreamFilterImpl, filter);
46 47
}

48 49
/*** IUnknown methods ***/

50
static HRESULT WINAPI MediaStreamFilterImpl_QueryInterface(IMediaStreamFilter *iface, REFIID riid, void **ret_iface)
51
{
52
    TRACE("(%p)->(%s, %p)\n", iface, debugstr_guid(riid), ret_iface);
53

54
    *ret_iface = NULL;
55

56 57 58 59 60 61
    if (IsEqualIID(riid, &IID_IUnknown) ||
        IsEqualIID(riid, &IID_IPersist) ||
        IsEqualIID(riid, &IID_IMediaFilter) ||
        IsEqualIID(riid, &IID_IBaseFilter) ||
        IsEqualIID(riid, &IID_IMediaStreamFilter))
        *ret_iface = iface;
62

63
    if (*ret_iface)
64
    {
65
        IMediaStreamFilter_AddRef(*ret_iface);
66 67 68 69 70 71
        return S_OK;
    }

    return E_NOINTERFACE;
}

72
static ULONG WINAPI MediaStreamFilterImpl_AddRef(IMediaStreamFilter *iface)
73
{
74 75 76 77 78 79
    IMediaStreamFilterImpl *This = impl_from_IMediaStreamFilter(iface);
    ULONG ref = BaseFilterImpl_AddRef(&This->filter.IBaseFilter_iface);

    TRACE("(%p)->(): new ref = %u\n", iface, ref);

    return ref;
80 81
}

82
static ULONG WINAPI MediaStreamFilterImpl_Release(IMediaStreamFilter *iface)
83
{
84
    IMediaStreamFilterImpl *This = impl_from_IMediaStreamFilter(iface);
85
    ULONG ref = InterlockedDecrement(&This->filter.refCount);
86

87
    TRACE("(%p)->(): new ref = %u\n", iface, ref);
88

89
    if (!ref)
90
    {
91
        ULONG i;
92
        for (i = 0; i < This->nb_streams; i++)
93
        {
94
            IAMMediaStream_JoinFilter(This->streams[i], NULL);
95
            IAMMediaStream_Release(This->streams[i]);
96
        }
97
        CoTaskMemFree(This->streams);
98
        BaseFilter_Destroy(&This->filter);
99
        HeapFree(GetProcessHeap(), 0, This);
100
    }
101

102
    return ref;
103 104 105 106
}

/*** IPersist methods ***/

107
static HRESULT WINAPI MediaStreamFilterImpl_GetClassID(IMediaStreamFilter *iface, CLSID *clsid)
108
{
109 110
    IMediaStreamFilterImpl *This = impl_from_IMediaStreamFilter(iface);
    return BaseFilterImpl_GetClassID(&This->filter.IBaseFilter_iface, clsid);
111 112
}

113
/*** IBaseFilter methods ***/
114

115
static HRESULT WINAPI MediaStreamFilterImpl_Stop(IMediaStreamFilter *iface)
116 117 118 119 120 121
{
    FIXME("(%p)->(): Stub!\n", iface);

    return E_NOTIMPL;
}

122
static HRESULT WINAPI MediaStreamFilterImpl_Pause(IMediaStreamFilter *iface)
123 124 125 126 127 128
{
    FIXME("(%p)->(): Stub!\n", iface);

    return E_NOTIMPL;
}

129
static HRESULT WINAPI MediaStreamFilterImpl_Run(IMediaStreamFilter *iface, REFERENCE_TIME start)
130
{
131
    FIXME("(%p)->(%s): Stub!\n", iface, wine_dbgstr_longlong(start));
132 133 134 135

    return E_NOTIMPL;
}

136
static HRESULT WINAPI MediaStreamFilterImpl_GetState(IMediaStreamFilter *iface, DWORD ms_timeout, FILTER_STATE *state)
137
{
138 139
    IMediaStreamFilterImpl *This = impl_from_IMediaStreamFilter(iface);
    return BaseFilterImpl_GetState(&This->filter.IBaseFilter_iface, ms_timeout, state);
140 141
}

142
static HRESULT WINAPI MediaStreamFilterImpl_SetSyncSource(IMediaStreamFilter *iface, IReferenceClock *clock)
143
{
144 145
    IMediaStreamFilterImpl *This = impl_from_IMediaStreamFilter(iface);
    return BaseFilterImpl_SetSyncSource(&This->filter.IBaseFilter_iface, clock);
146 147
}

148
static HRESULT WINAPI MediaStreamFilterImpl_GetSyncSource(IMediaStreamFilter *iface, IReferenceClock **clock)
149
{
150 151
    IMediaStreamFilterImpl *This = impl_from_IMediaStreamFilter(iface);
    return BaseFilterImpl_GetSyncSource(&This->filter.IBaseFilter_iface, clock);
152 153
}

154
static HRESULT WINAPI MediaStreamFilterImpl_EnumPins(IMediaStreamFilter *iface, IEnumPins **enum_pins)
155
{
156 157
    IMediaStreamFilterImpl *This = impl_from_IMediaStreamFilter(iface);
    return BaseFilterImpl_EnumPins(&This->filter.IBaseFilter_iface, enum_pins);
158 159
}

160
static HRESULT WINAPI MediaStreamFilterImpl_FindPin(IMediaStreamFilter *iface, LPCWSTR id, IPin **pin)
161
{
162
    FIXME("(%p)->(%s,%p): Stub!\n", iface, debugstr_w(id), pin);
163 164 165 166

    return E_NOTIMPL;
}

167
static HRESULT WINAPI MediaStreamFilterImpl_QueryFilterInfo(IMediaStreamFilter *iface, FILTER_INFO *info)
168
{
169 170
    IMediaStreamFilterImpl *This = impl_from_IMediaStreamFilter(iface);
    return BaseFilterImpl_QueryFilterInfo(&This->filter.IBaseFilter_iface, info);
171 172
}

173
static HRESULT WINAPI MediaStreamFilterImpl_JoinFilterGraph(IMediaStreamFilter *iface, IFilterGraph *graph, LPCWSTR name)
174
{
175 176
    IMediaStreamFilterImpl *This = impl_from_IMediaStreamFilter(iface);
    return BaseFilterImpl_JoinFilterGraph(&This->filter.IBaseFilter_iface, graph, name);
177 178
}

179
static HRESULT WINAPI MediaStreamFilterImpl_QueryVendorInfo(IMediaStreamFilter *iface, LPWSTR *vendor_info)
180
{
181 182
    IMediaStreamFilterImpl *This = impl_from_IMediaStreamFilter(iface);
    return BaseFilterImpl_QueryVendorInfo(&This->filter.IBaseFilter_iface, vendor_info);
183 184 185 186 187 188
}

/*** IMediaStreamFilter methods ***/

static HRESULT WINAPI MediaStreamFilterImpl_AddMediaStream(IMediaStreamFilter* iface, IAMMediaStream *pAMMediaStream)
{
189
    IMediaStreamFilterImpl *This = impl_from_IMediaStreamFilter(iface);
190
    IAMMediaStream** streams;
191
    HRESULT hr;
192

193 194
    TRACE("(%p)->(%p)\n", iface, pAMMediaStream);

195
    streams = CoTaskMemRealloc(This->streams, (This->nb_streams + 1) * sizeof(IAMMediaStream*));
196 197 198
    if (!streams)
        return E_OUTOFMEMORY;
    This->streams = streams;
199 200

    hr = IAMMediaStream_JoinFilter(pAMMediaStream, iface);
201 202 203
    if (FAILED(hr))
        return hr;

204
    This->streams[This->nb_streams] = pAMMediaStream;
205 206
    This->nb_streams++;

207
    IAMMediaStream_AddRef(pAMMediaStream);
208 209

    return S_OK;
210 211 212 213
}

static HRESULT WINAPI MediaStreamFilterImpl_GetMediaStream(IMediaStreamFilter* iface, REFMSPID idPurpose, IMediaStream **ppMediaStream)
{
214 215 216
    IMediaStreamFilterImpl *This = impl_from_IMediaStreamFilter(iface);
    MSPID purpose_id;
    unsigned int i;
217

218 219 220 221
    TRACE("(%p)->(%s,%p)\n", iface, debugstr_guid(idPurpose), ppMediaStream);

    for (i = 0; i < This->nb_streams; i++)
    {
222
        IAMMediaStream_GetInformation(This->streams[i], &purpose_id, NULL);
223 224
        if (IsEqualIID(&purpose_id, idPurpose))
        {
225
            *ppMediaStream = (IMediaStream *)This->streams[i];
226 227 228 229 230 231
            IMediaStream_AddRef(*ppMediaStream);
            return S_OK;
        }
    }

    return MS_E_NOSTREAM;
232 233
}

234
static HRESULT WINAPI MediaStreamFilterImpl_EnumMediaStreams(IMediaStreamFilter* iface, LONG Index, IMediaStream **ppMediaStream)
235
{
236
    FIXME("(%p)->(%d,%p): Stub!\n", iface, Index, ppMediaStream);
237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309

    return E_NOTIMPL;
}

static HRESULT WINAPI MediaStreamFilterImpl_SupportSeeking(IMediaStreamFilter* iface, BOOL bRenderer)
{
    FIXME("(%p)->(%d): Stub!\n", iface, bRenderer);

    return E_NOTIMPL;
}

static HRESULT WINAPI MediaStreamFilterImpl_ReferenceTimeToStreamTime(IMediaStreamFilter* iface, REFERENCE_TIME *pTime)
{
    FIXME("(%p)->(%p): Stub!\n", iface, pTime);

    return E_NOTIMPL;
}

static HRESULT WINAPI MediaStreamFilterImpl_GetCurrentStreamTime(IMediaStreamFilter* iface, REFERENCE_TIME *pCurrentStreamTime)
{
    FIXME("(%p)->(%p): Stub!\n", iface, pCurrentStreamTime);

    return E_NOTIMPL;
}

static HRESULT WINAPI MediaStreamFilterImpl_WaitUntil(IMediaStreamFilter* iface, REFERENCE_TIME WaitStreamTime)
{
    FIXME("(%p)->(%s): Stub!\n", iface, wine_dbgstr_longlong(WaitStreamTime));

    return E_NOTIMPL;
}

static HRESULT WINAPI MediaStreamFilterImpl_Flush(IMediaStreamFilter* iface, BOOL bCancelEOS)
{
    FIXME("(%p)->(%d): Stub!\n", iface, bCancelEOS);

    return E_NOTIMPL;
}

static HRESULT WINAPI MediaStreamFilterImpl_EndOfStream(IMediaStreamFilter* iface)
{
    FIXME("(%p)->(): Stub!\n",  iface);

    return E_NOTIMPL;
}

static const IMediaStreamFilterVtbl MediaStreamFilter_Vtbl =
{
    MediaStreamFilterImpl_QueryInterface,
    MediaStreamFilterImpl_AddRef,
    MediaStreamFilterImpl_Release,
    MediaStreamFilterImpl_GetClassID,
    MediaStreamFilterImpl_Stop,
    MediaStreamFilterImpl_Pause,
    MediaStreamFilterImpl_Run,
    MediaStreamFilterImpl_GetState,
    MediaStreamFilterImpl_SetSyncSource,
    MediaStreamFilterImpl_GetSyncSource,
    MediaStreamFilterImpl_EnumPins,
    MediaStreamFilterImpl_FindPin,
    MediaStreamFilterImpl_QueryFilterInfo,
    MediaStreamFilterImpl_JoinFilterGraph,
    MediaStreamFilterImpl_QueryVendorInfo,
    MediaStreamFilterImpl_AddMediaStream,
    MediaStreamFilterImpl_GetMediaStream,
    MediaStreamFilterImpl_EnumMediaStreams,
    MediaStreamFilterImpl_SupportSeeking,
    MediaStreamFilterImpl_ReferenceTimeToStreamTime,
    MediaStreamFilterImpl_GetCurrentStreamTime,
    MediaStreamFilterImpl_WaitUntil,
    MediaStreamFilterImpl_Flush,
    MediaStreamFilterImpl_EndOfStream
};
310

311 312
static IPin* WINAPI MediaStreamFilterImpl_GetPin(BaseFilter *iface, int pos)
{
313 314 315 316
    IMediaStreamFilterImpl* This = (IMediaStreamFilterImpl*)iface;

    if (pos < This->nb_streams)
    {
317 318 319
        IPin *pin = NULL;
        IAMMediaStream_QueryInterface(This->streams[pos], &IID_IPin, (void **)&pin);
        return pin;
320 321
    }

322 323 324 325 326
    return NULL;
}

static LONG WINAPI MediaStreamFilterImpl_GetPinCount(BaseFilter *iface)
{
327 328 329
    IMediaStreamFilterImpl* This = (IMediaStreamFilterImpl*)iface;

    return This->nb_streams;
330 331 332 333 334 335 336
}

static const BaseFilterFuncTable BaseFuncTable = {
    MediaStreamFilterImpl_GetPin,
    MediaStreamFilterImpl_GetPinCount
};

337 338 339 340 341 342 343 344 345 346 347 348 349
HRESULT MediaStreamFilter_create(IUnknown *pUnkOuter, void **ppObj)
{
    IMediaStreamFilterImpl* object;

    TRACE("(%p,%p)\n", pUnkOuter, ppObj);

    if( pUnkOuter )
        return CLASS_E_NOAGGREGATION;

    object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IMediaStreamFilterImpl));
    if (!object)
        return E_OUTOFMEMORY;

350
    BaseFilter_Init(&object->filter, (IBaseFilterVtbl*)&MediaStreamFilter_Vtbl, &CLSID_MediaStreamFilter, (DWORD_PTR)(__FILE__ ": MediaStreamFilterImpl.csFilter"), &BaseFuncTable);
351

352
    *ppObj = &object->filter.IBaseFilter_iface;
353 354 355

    return S_OK;
}