From: Rémi Bernon rbernon@codeweavers.com
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/winegstreamer/Makefile.in | 1 + dlls/winegstreamer/gst_private.h | 4 +- dlls/winegstreamer/h264_decoder.c | 11 ++- dlls/winegstreamer/mfplat.c | 71 ------------------ dlls/winegstreamer/wg_sample.c | 121 ++++++++++++++++++++++++++++++ dlls/winegstreamer/wma_decoder.c | 12 +-- 6 files changed, 135 insertions(+), 85 deletions(-) create mode 100644 dlls/winegstreamer/wg_sample.c
diff --git a/dlls/winegstreamer/Makefile.in b/dlls/winegstreamer/Makefile.in index e4c2636d02d..bac01776e4c 100644 --- a/dlls/winegstreamer/Makefile.in +++ b/dlls/winegstreamer/Makefile.in @@ -16,6 +16,7 @@ C_SRCS = \ quartz_transform.c \ wg_format.c \ wg_parser.c \ + wg_sample.c \ wg_transform.c \ wm_asyncreader.c \ wm_reader.c \ diff --git a/dlls/winegstreamer/gst_private.h b/dlls/winegstreamer/gst_private.h index 159143d7e54..7ae2eb99076 100644 --- a/dlls/winegstreamer/gst_private.h +++ b/dlls/winegstreamer/gst_private.h @@ -120,8 +120,8 @@ extern HRESULT mfplat_DllRegisterServer(void); IMFMediaType *mf_media_type_from_wg_format(const struct wg_format *format); void mf_media_type_to_wg_format(IMFMediaType *type, struct wg_format *format);
-HRESULT mf_create_wg_sample(IMFSample *sample, struct wg_sample **out); -void mf_destroy_wg_sample(struct wg_sample *wg_sample); +HRESULT wg_sample_wrap_mf(IMFSample *mf_sample, struct wg_sample **out); +void wg_sample_unwrap(struct wg_sample *wg_sample);
HRESULT winegstreamer_stream_handler_create(REFIID riid, void **obj);
diff --git a/dlls/winegstreamer/h264_decoder.c b/dlls/winegstreamer/h264_decoder.c index 19a36a9a77a..43d714f63be 100644 --- a/dlls/winegstreamer/h264_decoder.c +++ b/dlls/winegstreamer/h264_decoder.c @@ -540,12 +540,11 @@ static HRESULT WINAPI transform_ProcessInput(IMFTransform *iface, DWORD id, IMFS if (!decoder->wg_transform) return MF_E_TRANSFORM_TYPE_NOT_SET;
- if (FAILED(hr = mf_create_wg_sample(sample, &wg_sample))) + if (FAILED(hr = wg_sample_wrap_mf(sample, &wg_sample))) return hr;
hr = wg_transform_push_data(decoder->wg_transform, wg_sample); - - mf_destroy_wg_sample(wg_sample); + wg_sample_unwrap(wg_sample); return hr; }
@@ -574,18 +573,18 @@ static HRESULT WINAPI transform_ProcessOutput(IMFTransform *iface, DWORD flags, samples[0].dwStatus = 0; if (!samples[0].pSample) return E_INVALIDARG;
- if (FAILED(hr = mf_create_wg_sample(samples[0].pSample, &wg_sample))) + if (FAILED(hr = wg_sample_wrap_mf(samples[0].pSample, &wg_sample))) return hr;
if (wg_sample->max_size < info.cbSize) { - mf_destroy_wg_sample(wg_sample); + wg_sample_unwrap(wg_sample); return MF_E_BUFFERTOOSMALL; }
hr = wg_transform_read_data(decoder->wg_transform, wg_sample, &wg_format); - mf_destroy_wg_sample(wg_sample); + wg_sample_unwrap(wg_sample);
if (hr == MF_E_TRANSFORM_STREAM_CHANGE) { diff --git a/dlls/winegstreamer/mfplat.c b/dlls/winegstreamer/mfplat.c index 0226e7a2e45..687ea6db5c7 100644 --- a/dlls/winegstreamer/mfplat.c +++ b/dlls/winegstreamer/mfplat.c @@ -957,74 +957,3 @@ void mf_media_type_to_wg_format(IMFMediaType *type, struct wg_format *format) else FIXME("Unrecognized major type %s.\n", debugstr_guid(&major_type)); } - -struct mf_sample -{ - IMFSample *sample; - IMFMediaBuffer *media_buffer; - struct wg_sample wg_sample; -}; - -HRESULT mf_create_wg_sample(IMFSample *sample, struct wg_sample **out) -{ - DWORD current_length, max_length; - struct mf_sample *mf_sample; - LONGLONG time, duration; - UINT32 value; - BYTE *buffer; - HRESULT hr; - - if (!(mf_sample = calloc(1, sizeof(*mf_sample)))) - return E_OUTOFMEMORY; - if (FAILED(hr = IMFSample_ConvertToContiguousBuffer(sample, &mf_sample->media_buffer))) - goto out; - if (FAILED(hr = IMFMediaBuffer_Lock(mf_sample->media_buffer, &buffer, &max_length, ¤t_length))) - goto out; - - if (SUCCEEDED(IMFSample_GetSampleTime(sample, &time))) - { - mf_sample->wg_sample.flags |= WG_SAMPLE_FLAG_HAS_PTS; - mf_sample->wg_sample.pts = time; - } - if (SUCCEEDED(IMFSample_GetSampleDuration(sample, &duration))) - { - mf_sample->wg_sample.flags |= WG_SAMPLE_FLAG_HAS_DURATION; - mf_sample->wg_sample.duration = duration; - } - if (SUCCEEDED(IMFSample_GetUINT32(sample, &MFSampleExtension_CleanPoint, &value)) && value) - mf_sample->wg_sample.flags |= WG_SAMPLE_FLAG_SYNC_POINT; - - IMFSample_AddRef((mf_sample->sample = sample)); - mf_sample->wg_sample.data = buffer; - mf_sample->wg_sample.size = current_length; - mf_sample->wg_sample.max_size = max_length; - - TRACE("Created mf_sample %p for sample %p.\n", mf_sample, sample); - *out = &mf_sample->wg_sample; - return S_OK; - -out: - if (mf_sample->media_buffer) - IMFMediaBuffer_Release(mf_sample->media_buffer); - free(mf_sample); - return hr; -} - -void mf_destroy_wg_sample(struct wg_sample *wg_sample) -{ - struct mf_sample *mf_sample = CONTAINING_RECORD(wg_sample, struct mf_sample, wg_sample); - - IMFMediaBuffer_Unlock(mf_sample->media_buffer); - IMFMediaBuffer_SetCurrentLength(mf_sample->media_buffer, wg_sample->size); - IMFMediaBuffer_Release(mf_sample->media_buffer); - - if (wg_sample->flags & WG_SAMPLE_FLAG_HAS_PTS) - IMFSample_SetSampleTime(mf_sample->sample, wg_sample->pts); - if (wg_sample->flags & WG_SAMPLE_FLAG_HAS_DURATION) - IMFSample_SetSampleDuration(mf_sample->sample, wg_sample->duration); - if (wg_sample->flags & WG_SAMPLE_FLAG_SYNC_POINT) - IMFSample_SetUINT32(mf_sample->sample, &MFSampleExtension_CleanPoint, 1); - - IMFSample_Release(mf_sample->sample); - free(mf_sample); -} diff --git a/dlls/winegstreamer/wg_sample.c b/dlls/winegstreamer/wg_sample.c new file mode 100644 index 00000000000..e20e393e396 --- /dev/null +++ b/dlls/winegstreamer/wg_sample.c @@ -0,0 +1,121 @@ +/* + * Copyright 2022 Rémi Bernon for 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 + */ + +#include "gst_private.h" + +#include "wmcodecdsp.h" +#include "mfapi.h" + +#include "wine/debug.h" + +WINE_DEFAULT_DEBUG_CHANNEL(mfplat); + +struct sample +{ + struct wg_sample wg_sample; + enum wg_sample_type + { + WG_SAMPLE_TYPE_MF = 1, + } type; + + union + { + struct + { + IMFSample *sample; + IMFMediaBuffer *buffer; + } mf; + } u; +}; + +HRESULT wg_sample_wrap_mf(IMFSample *mf_sample, struct wg_sample **out) +{ + DWORD current_length, max_length; + LONGLONG time, duration; + struct sample *sample; + UINT32 value; + BYTE *buffer; + HRESULT hr; + + if (!(sample = calloc(1, sizeof(*sample)))) + return E_OUTOFMEMORY; + if (FAILED(hr = IMFSample_ConvertToContiguousBuffer(mf_sample, &sample->u.mf.buffer))) + goto failed; + if (FAILED(hr = IMFMediaBuffer_Lock(sample->u.mf.buffer, &buffer, &max_length, ¤t_length))) + goto failed; + + if (SUCCEEDED(IMFSample_GetSampleTime(mf_sample, &time))) + { + sample->wg_sample.flags |= WG_SAMPLE_FLAG_HAS_PTS; + sample->wg_sample.pts = time; + } + if (SUCCEEDED(IMFSample_GetSampleDuration(mf_sample, &duration))) + { + sample->wg_sample.flags |= WG_SAMPLE_FLAG_HAS_DURATION; + sample->wg_sample.duration = duration; + } + if (SUCCEEDED(IMFSample_GetUINT32(mf_sample, &MFSampleExtension_CleanPoint, &value)) && value) + sample->wg_sample.flags |= WG_SAMPLE_FLAG_SYNC_POINT; + + IMFSample_AddRef((sample->u.mf.sample = mf_sample)); + sample->wg_sample.data = buffer; + sample->wg_sample.size = current_length; + sample->wg_sample.max_size = max_length; + sample->type = WG_SAMPLE_TYPE_MF; + + TRACE("Created wg_sample %p for sample %p.\n", &sample->wg_sample, mf_sample); + *out = &sample->wg_sample; + return S_OK; + +failed: + if (sample->u.mf.buffer) + IMFMediaBuffer_Release(sample->u.mf.buffer); + free(sample); + return hr; +} + +void wg_sample_unwrap(struct wg_sample *wg_sample) +{ + struct sample *sample = CONTAINING_RECORD(wg_sample, struct sample, wg_sample); + + switch (sample->type) + { + case WG_SAMPLE_TYPE_MF: + TRACE("wg_sample %p\n", wg_sample); + + IMFMediaBuffer_Unlock(sample->u.mf.buffer); + IMFMediaBuffer_SetCurrentLength(sample->u.mf.buffer, wg_sample->size); + IMFMediaBuffer_Release(sample->u.mf.buffer); + + if (wg_sample->flags & WG_SAMPLE_FLAG_HAS_PTS) + IMFSample_SetSampleTime(sample->u.mf.sample, wg_sample->pts); + if (wg_sample->flags & WG_SAMPLE_FLAG_HAS_DURATION) + IMFSample_SetSampleDuration(sample->u.mf.sample, wg_sample->duration); + if (wg_sample->flags & WG_SAMPLE_FLAG_SYNC_POINT) + IMFSample_SetUINT32(sample->u.mf.sample, &MFSampleExtension_CleanPoint, 1); + + IMFSample_Release(sample->u.mf.sample); + break; + + default: + FIXME("Unknown wg_sample %p, type %u\n", wg_sample, sample->type); + break; + } + + free(sample); +} diff --git a/dlls/winegstreamer/wma_decoder.c b/dlls/winegstreamer/wma_decoder.c index 106d32adce9..dc3d1aaef1a 100644 --- a/dlls/winegstreamer/wma_decoder.c +++ b/dlls/winegstreamer/wma_decoder.c @@ -534,18 +534,18 @@ static HRESULT WINAPI transform_ProcessInput(IMFTransform *iface, DWORD id, IMFS if (FAILED(hr = IMFTransform_GetInputStreamInfo(iface, 0, &info))) return hr;
- if (FAILED(hr = mf_create_wg_sample(sample, &wg_sample))) + if (FAILED(hr = wg_sample_wrap_mf(sample, &wg_sample))) return hr;
/* WMA transform uses fixed size input samples and ignores samples with invalid sizes */ if (wg_sample->size % info.cbSize) { - mf_destroy_wg_sample(wg_sample); + wg_sample_unwrap(wg_sample); return S_OK; }
hr = wg_transform_push_data(decoder->wg_transform, wg_sample); - mf_destroy_wg_sample(wg_sample); + wg_sample_unwrap(wg_sample); return hr; }
@@ -576,13 +576,13 @@ static HRESULT WINAPI transform_ProcessOutput(IMFTransform *iface, DWORD flags, return MF_E_TRANSFORM_NEED_MORE_INPUT; }
- if (FAILED(hr = mf_create_wg_sample(samples[0].pSample, &wg_sample))) + if (FAILED(hr = wg_sample_wrap_mf(samples[0].pSample, &wg_sample))) return hr;
wg_sample->size = 0; if (wg_sample->max_size < info.cbSize) { - mf_destroy_wg_sample(wg_sample); + wg_sample_unwrap(wg_sample); return MF_E_BUFFERTOOSMALL; }
@@ -592,7 +592,7 @@ static HRESULT WINAPI transform_ProcessOutput(IMFTransform *iface, DWORD flags, samples[0].dwStatus |= MFT_OUTPUT_DATA_BUFFER_INCOMPLETE; }
- mf_destroy_wg_sample(wg_sample); + wg_sample_unwrap(wg_sample);
if (hr == MF_E_TRANSFORM_STREAM_CHANGE) {