main.c 9.99 KB
Newer Older
1
/* GStreamer Base Functions
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
 *
 * Copyright 2002 Lionel Ulmer
 * Copyright 2010 Aric Stewart, CodeWeavers
 *
 * 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
 */

21 22
#define WINE_NO_NAMELESS_EXTENSION

23
#include "gst_private.h"
24
#include "winternl.h"
25 26
#include "rpcproxy.h"

27
#include "initguid.h"
28 29
#include "gst_guids.h"

30
LONG object_locks;
31

32
WINE_DEFAULT_DEBUG_CHANNEL(quartz);
33

34 35
const struct unix_funcs *unix_funcs = NULL;

36 37 38
BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, void *reserved)
{
    if (reason == DLL_PROCESS_ATTACH)
39
    {
40
        DisableThreadLibraryCalls(instance);
41
        __wine_init_unix_lib(instance, reason, NULL, &unix_funcs);
42
    }
43 44
    return TRUE;
}
45

46
HRESULT WINAPI DllCanUnloadNow(void)
47
{
48
    TRACE(".\n");
49

50 51
    return object_locks ? S_FALSE : S_OK;
}
52

53
struct class_factory
54
{
55 56
    IClassFactory IClassFactory_iface;
    HRESULT (*create_instance)(IUnknown *outer, IUnknown **out);
57 58
};

59
static inline struct class_factory *impl_from_IClassFactory(IClassFactory *iface)
60
{
61 62
    return CONTAINING_RECORD(iface, struct class_factory, IClassFactory_iface);
}
63

64
static HRESULT WINAPI class_factory_QueryInterface(IClassFactory *iface, REFIID iid, void **out)
65
{
66
    TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out);
67

68
    if (IsEqualGUID(iid, &IID_IUnknown) || IsEqualGUID(iid, &IID_IClassFactory))
69
    {
70 71 72 73
        *out = iface;
        IClassFactory_AddRef(iface);
        return S_OK;
    }
74

75 76 77 78
    *out = NULL;
    WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid));
    return E_NOINTERFACE;
}
79

80
static ULONG WINAPI class_factory_AddRef(IClassFactory *iface)
81
{
82 83
    return 2;
}
84

85
static ULONG WINAPI class_factory_Release(IClassFactory *iface)
86
{
87 88
    return 1;
}
89

90
static HRESULT WINAPI class_factory_CreateInstance(IClassFactory *iface, IUnknown *outer, REFIID iid, void **out)
91
{
92 93 94
    struct class_factory *factory = impl_from_IClassFactory(iface);
    IUnknown *unk;
    HRESULT hr;
95

96
    TRACE("iface %p, outer %p, iid %s, out %p.\n", iface, outer, debugstr_guid(iid), out);
97

98 99
    if (outer && !IsEqualGUID(iid, &IID_IUnknown))
        return E_NOINTERFACE;
100

101 102
    *out = NULL;
    if (SUCCEEDED(hr = factory->create_instance(outer, &unk)))
103
    {
104 105 106 107 108
        hr = IUnknown_QueryInterface(unk, iid, out);
        IUnknown_Release(unk);
    }
    return hr;
}
109

110
static HRESULT WINAPI class_factory_LockServer(IClassFactory *iface, BOOL lock)
111
{
112 113 114 115 116 117 118
    TRACE("iface %p, lock %d.\n", iface, lock);

    if (lock)
        InterlockedIncrement(&object_locks);
    else
        InterlockedDecrement(&object_locks);
    return S_OK;
119 120
}

121
static const IClassFactoryVtbl class_factory_vtbl =
122
{
123 124 125 126 127 128
    class_factory_QueryInterface,
    class_factory_AddRef,
    class_factory_Release,
    class_factory_CreateInstance,
    class_factory_LockServer,
};
129

130
static struct class_factory avi_splitter_cf = {{&class_factory_vtbl}, avi_splitter_create};
131
static struct class_factory decodebin_parser_cf = {{&class_factory_vtbl}, decodebin_parser_create};
132 133
static struct class_factory mpeg_splitter_cf = {{&class_factory_vtbl}, mpeg_splitter_create};
static struct class_factory wave_parser_cf = {{&class_factory_vtbl}, wave_parser_create};
134

135
HRESULT WINAPI DllGetClassObject(REFCLSID clsid, REFIID iid, void **out)
136
{
137
    struct class_factory *factory;
138 139
    HRESULT hr;

140
    TRACE("clsid %s, iid %s, out %p.\n", debugstr_guid(clsid), debugstr_guid(iid), out);
141

142 143 144
    if (!init_gstreamer())
        return CLASS_E_CLASSNOTAVAILABLE;

145 146 147 148 149
    if (SUCCEEDED(hr = mfplat_get_class_object(clsid, iid, out)))
        return hr;

    if (IsEqualGUID(clsid, &CLSID_AviSplitter))
        factory = &avi_splitter_cf;
150 151
    else if (IsEqualGUID(clsid, &CLSID_decodebin_parser))
        factory = &decodebin_parser_cf;
152 153 154 155 156 157 158 159 160 161 162
    else if (IsEqualGUID(clsid, &CLSID_MPEG1Splitter))
        factory = &mpeg_splitter_cf;
    else if (IsEqualGUID(clsid, &CLSID_WAVEParser))
        factory = &wave_parser_cf;
    else
    {
        FIXME("%s not implemented, returning CLASS_E_CLASSNOTAVAILABLE.\n", debugstr_guid(clsid));
        return CLASS_E_CLASSNOTAVAILABLE;
    }

    return IClassFactory_QueryInterface(&factory->IClassFactory_iface, iid, out);
163 164
}

165
static BOOL CALLBACK init_gstreamer_proc(INIT_ONCE *once, void *param, void **ctx)
166
{
167
    HINSTANCE handle;
168

169 170 171
    /* Unloading glib is a bad idea.. it installs atexit handlers,
     * so never unload the dll after loading */
    GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_PIN,
172
            (LPCWSTR)init_gstreamer_proc, &handle);
173
    if (!handle)
174
        ERR("Failed to pin module.\n");
175 176 177 178 179 180 181 182

    return TRUE;
}

BOOL init_gstreamer(void)
{
    static INIT_ONCE once = INIT_ONCE_STATIC_INIT;

183
    InitOnceExecuteOnce(&once, init_gstreamer_proc, NULL, NULL);
184

185
    return TRUE;
186 187
}

188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 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
static const REGPINTYPES reg_audio_mt = {&MEDIATYPE_Audio, &GUID_NULL};
static const REGPINTYPES reg_stream_mt = {&MEDIATYPE_Stream, &GUID_NULL};
static const REGPINTYPES reg_video_mt = {&MEDIATYPE_Video, &GUID_NULL};

static const REGPINTYPES reg_avi_splitter_sink_mt = {&MEDIATYPE_Stream, &MEDIASUBTYPE_Avi};

static const REGFILTERPINS2 reg_avi_splitter_pins[2] =
{
    {
        .nMediaTypes = 1,
        .lpMediaType = &reg_avi_splitter_sink_mt,
    },
    {
        .dwFlags = REG_PINFLAG_B_OUTPUT,
        .nMediaTypes = 1,
        .lpMediaType = &reg_video_mt,
    },
};

static const REGFILTER2 reg_avi_splitter =
{
    .dwVersion = 2,
    .dwMerit = MERIT_NORMAL,
    .u.s2.cPins2 = 2,
    .u.s2.rgPins2 = reg_avi_splitter_pins,
};

static const REGPINTYPES reg_mpeg_splitter_sink_mts[4] =
{
    {&MEDIATYPE_Stream, &MEDIASUBTYPE_MPEG1Audio},
    {&MEDIATYPE_Stream, &MEDIASUBTYPE_MPEG1Video},
    {&MEDIATYPE_Stream, &MEDIASUBTYPE_MPEG1System},
    {&MEDIATYPE_Stream, &MEDIASUBTYPE_MPEG1VideoCD},
};

static const REGPINTYPES reg_mpeg_splitter_audio_mts[2] =
{
    {&MEDIATYPE_Audio, &MEDIASUBTYPE_MPEG1Packet},
    {&MEDIATYPE_Audio, &MEDIASUBTYPE_MPEG1AudioPayload},
};

static const REGPINTYPES reg_mpeg_splitter_video_mts[2] =
{
    {&MEDIATYPE_Video, &MEDIASUBTYPE_MPEG1Packet},
    {&MEDIATYPE_Video, &MEDIASUBTYPE_MPEG1Payload},
};

static const REGFILTERPINS2 reg_mpeg_splitter_pins[3] =
{
    {
        .nMediaTypes = 4,
        .lpMediaType = reg_mpeg_splitter_sink_mts,
    },
    {
        .dwFlags = REG_PINFLAG_B_ZERO | REG_PINFLAG_B_OUTPUT,
        .nMediaTypes = 2,
        .lpMediaType = reg_mpeg_splitter_audio_mts,
    },
    {
        .dwFlags = REG_PINFLAG_B_ZERO | REG_PINFLAG_B_OUTPUT,
        .nMediaTypes = 2,
        .lpMediaType = reg_mpeg_splitter_video_mts,
    },
};

static const REGFILTER2 reg_mpeg_splitter =
{
    .dwVersion = 2,
    .dwMerit = MERIT_NORMAL,
    .u.s2.cPins2 = 3,
    .u.s2.rgPins2 = reg_mpeg_splitter_pins,
};

static const REGPINTYPES reg_wave_parser_sink_mts[3] =
{
    {&MEDIATYPE_Stream, &MEDIASUBTYPE_WAVE},
    {&MEDIATYPE_Stream, &MEDIASUBTYPE_AU},
    {&MEDIATYPE_Stream, &MEDIASUBTYPE_AIFF},
};

static const REGFILTERPINS2 reg_wave_parser_pins[2] =
{
    {
        .nMediaTypes = 3,
        .lpMediaType = reg_wave_parser_sink_mts,
    },
    {
        .dwFlags = REG_PINFLAG_B_OUTPUT,
        .nMediaTypes = 1,
        .lpMediaType = &reg_audio_mt,
    },
};

static const REGFILTER2 reg_wave_parser =
{
    .dwVersion = 2,
    .dwMerit = MERIT_UNLIKELY,
    .u.s2.cPins2 = 2,
    .u.s2.rgPins2 = reg_wave_parser_pins,
};

289
static const REGFILTERPINS2 reg_decodebin_parser_pins[3] =
290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306
{
    {
        .nMediaTypes = 1,
        .lpMediaType = &reg_stream_mt,
    },
    {
        .dwFlags = REG_PINFLAG_B_OUTPUT,
        .nMediaTypes = 1,
        .lpMediaType = &reg_audio_mt,
    },
    {
        .dwFlags = REG_PINFLAG_B_OUTPUT,
        .nMediaTypes = 1,
        .lpMediaType = &reg_video_mt,
    },
};

307
static const REGFILTER2 reg_decodebin_parser =
308 309 310 311
{
    .dwVersion = 2,
    .dwMerit = MERIT_PREFERRED,
    .u.s2.cPins2 = 3,
312
    .u.s2.rgPins2 = reg_decodebin_parser_pins,
313 314
};

315 316
HRESULT WINAPI DllRegisterServer(void)
{
317
    IFilterMapper2 *mapper;
318 319
    HRESULT hr;

320
    TRACE(".\n");
321

322
    if (FAILED(hr = __wine_register_resources()))
323 324 325 326 327 328
        return hr;

    if (FAILED(hr = CoCreateInstance(&CLSID_FilterMapper2, NULL, CLSCTX_INPROC_SERVER,
            &IID_IFilterMapper2, (void **)&mapper)))
        return hr;

329
    IFilterMapper2_RegisterFilter(mapper, &CLSID_AviSplitter, L"AVI Splitter", NULL, NULL, NULL, &reg_avi_splitter);
330
    IFilterMapper2_RegisterFilter(mapper, &CLSID_decodebin_parser,
331 332 333 334
            L"GStreamer splitter filter", NULL, NULL, NULL, &reg_decodebin_parser);
    IFilterMapper2_RegisterFilter(mapper, &CLSID_MPEG1Splitter,
            L"MPEG-I Stream Splitter", NULL, NULL, NULL, &reg_mpeg_splitter);
    IFilterMapper2_RegisterFilter(mapper, &CLSID_WAVEParser, L"Wave Parser", NULL, NULL, NULL, &reg_wave_parser);
335 336

    IFilterMapper2_Release(mapper);
337 338

    return mfplat_DllRegisterServer();
339 340 341 342
}

HRESULT WINAPI DllUnregisterServer(void)
{
343
    IFilterMapper2 *mapper;
344 345
    HRESULT hr;

346
    TRACE(".\n");
347

348
    if (FAILED(hr = __wine_unregister_resources()))
349 350 351 352 353 354 355
        return hr;

    if (FAILED(hr = CoCreateInstance(&CLSID_FilterMapper2, NULL, CLSCTX_INPROC_SERVER,
            &IID_IFilterMapper2, (void **)&mapper)))
        return hr;

    IFilterMapper2_UnregisterFilter(mapper, NULL, NULL, &CLSID_AviSplitter);
356
    IFilterMapper2_UnregisterFilter(mapper, NULL, NULL, &CLSID_decodebin_parser);
357 358 359 360 361
    IFilterMapper2_UnregisterFilter(mapper, NULL, NULL, &CLSID_MPEG1Splitter);
    IFilterMapper2_UnregisterFilter(mapper, NULL, NULL, &CLSID_WAVEParser);

    IFilterMapper2_Release(mapper);
    return S_OK;
362
}