/* * DirectShow transform filters * * Copyright 2022 Anton Baskanov * * 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 "gst_private.h" WINE_DEFAULT_DEBUG_CHANNEL(quartz); struct transform { struct strmbase_filter filter; struct strmbase_sink sink; struct strmbase_source source; }; static inline struct transform *impl_from_strmbase_filter(struct strmbase_filter *iface) { return CONTAINING_RECORD(iface, struct transform, filter); } static struct strmbase_pin *transform_get_pin(struct strmbase_filter *iface, unsigned int index) { struct transform *filter = impl_from_strmbase_filter(iface); if (index == 0) return &filter->sink.pin; if (index == 1) return &filter->source.pin; return NULL; } static void transform_destroy(struct strmbase_filter *iface) { struct transform *filter = impl_from_strmbase_filter(iface); strmbase_source_cleanup(&filter->source); strmbase_sink_cleanup(&filter->sink); strmbase_filter_cleanup(&filter->filter); free(filter); } static const struct strmbase_filter_ops filter_ops = { .filter_get_pin = transform_get_pin, .filter_destroy = transform_destroy, }; static HRESULT transform_sink_query_interface(struct strmbase_pin *pin, REFIID iid, void **out) { struct transform *filter = impl_from_strmbase_filter(pin->filter); if (IsEqualGUID(iid, &IID_IMemInputPin)) *out = &filter->sink.IMemInputPin_iface; else return E_NOINTERFACE; IUnknown_AddRef((IUnknown *)*out); return S_OK; } static const struct strmbase_sink_ops sink_ops = { .base.pin_query_interface = transform_sink_query_interface, }; static const struct strmbase_source_ops source_ops = { .pfnAttemptConnection = BaseOutputPinImpl_AttemptConnection, .pfnDecideAllocator = BaseOutputPinImpl_DecideAllocator, }; static HRESULT transform_create(IUnknown *outer, const CLSID *clsid, struct transform **out) { struct transform *object; object = calloc(1, sizeof(*object)); if (!object) return E_OUTOFMEMORY; strmbase_filter_init(&object->filter, outer, clsid, &filter_ops); strmbase_sink_init(&object->sink, &object->filter, L"In", &sink_ops, NULL); strmbase_source_init(&object->source, &object->filter, L"Out", &source_ops); *out = object; return S_OK; } HRESULT mpeg_audio_codec_create(IUnknown *outer, IUnknown **out) { struct transform *object; HRESULT hr; hr = transform_create(outer, &CLSID_CMpegAudioCodec, &object); if (FAILED(hr)) return hr; wcscpy(object->sink.pin.name, L"XForm In"); wcscpy(object->source.pin.name, L"XForm Out"); TRACE("Created MPEG audio decoder %p.\n", object); *out = &object->filter.IUnknown_inner; return hr; }