From: Rémi Bernon rbernon@codeweavers.com
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/winegstreamer/Makefile.in | 1 + dlls/winegstreamer/mfplat.c | 176 ---------------------------- dlls/winegstreamer/wg_sample.c | 203 +++++++++++++++++++++++++++++++++ 3 files changed, 204 insertions(+), 176 deletions(-) create mode 100644 dlls/winegstreamer/wg_sample.c
diff --git a/dlls/winegstreamer/Makefile.in b/dlls/winegstreamer/Makefile.in index 50f4dc861d4..6e3517dcb36 100644 --- a/dlls/winegstreamer/Makefile.in +++ b/dlls/winegstreamer/Makefile.in @@ -17,6 +17,7 @@ C_SRCS = \ wg_allocator.c \ wg_format.c \ wg_parser.c \ + wg_sample.c \ wg_transform.c \ wm_asyncreader.c \ wm_reader.c \ diff --git a/dlls/winegstreamer/mfplat.c b/dlls/winegstreamer/mfplat.c index 157ed3ad2f2..c5ca4b15c0f 100644 --- a/dlls/winegstreamer/mfplat.c +++ b/dlls/winegstreamer/mfplat.c @@ -958,179 +958,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 wg_sample_queue -{ - CRITICAL_SECTION cs; - struct list samples; -}; - -struct mf_sample -{ - IMFSample *sample; - IMFMediaBuffer *media_buffer; - struct wg_sample wg_sample; - struct list entry; -}; - -HRESULT wg_sample_create_mf(IMFSample *sample, struct wg_sample **out) -{ - DWORD current_length, max_length; - struct mf_sample *mf_sample; - 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; - - 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 wg_sample_release(struct wg_sample *wg_sample) -{ - struct mf_sample *mf_sample = CONTAINING_RECORD(wg_sample, struct mf_sample, wg_sample); - - if (InterlockedOr(&wg_sample->refcount, 0)) - { - ERR("Sample %p is still in use, trouble ahead!\n", wg_sample); - return; - } - - IMFMediaBuffer_Unlock(mf_sample->media_buffer); - IMFMediaBuffer_Release(mf_sample->media_buffer); - IMFSample_Release(mf_sample->sample); - - free(mf_sample); -} - -static void wg_sample_queue_begin_append(struct wg_sample_queue *queue, struct wg_sample *wg_sample) -{ - struct mf_sample *mf_sample = CONTAINING_RECORD(wg_sample, struct mf_sample, wg_sample); - - /* make sure a concurrent wg_sample_queue_flush call won't release the sample until we're done */ - InterlockedIncrement(&wg_sample->refcount); - mf_sample->wg_sample.flags |= WG_SAMPLE_FLAG_HAS_REFCOUNT; - - EnterCriticalSection(&queue->cs); - list_add_tail(&queue->samples, &mf_sample->entry); - LeaveCriticalSection(&queue->cs); -} - -static void wg_sample_queue_end_append(struct wg_sample_queue *queue, struct wg_sample *wg_sample) -{ - /* release temporary ref taken in wg_sample_queue_begin_append */ - InterlockedDecrement(&wg_sample->refcount); - - wg_sample_queue_flush(queue, false); -} - -void wg_sample_queue_flush(struct wg_sample_queue *queue, bool all) -{ - struct mf_sample *mf_sample, *next; - - EnterCriticalSection(&queue->cs); - - LIST_FOR_EACH_ENTRY_SAFE(mf_sample, next, &queue->samples, struct mf_sample, entry) - { - if (!InterlockedOr(&mf_sample->wg_sample.refcount, 0) || all) - { - list_remove(&mf_sample->entry); - wg_sample_release(&mf_sample->wg_sample); - } - } - - LeaveCriticalSection(&queue->cs); -} - -HRESULT wg_sample_queue_create(struct wg_sample_queue **out) -{ - struct wg_sample_queue *queue; - - if (!(queue = calloc(1, sizeof(*queue)))) - return E_OUTOFMEMORY; - - InitializeCriticalSection(&queue->cs); - queue->cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": cs"); - list_init(&queue->samples); - - TRACE("Created sample queue %p\n", queue); - *out = queue; - - return S_OK; -} - -void wg_sample_queue_destroy(struct wg_sample_queue *queue) -{ - wg_sample_queue_flush(queue, true); - - queue->cs.DebugInfo->Spare[0] = 0; - InitializeCriticalSection(&queue->cs); - - free(queue); -} - -HRESULT wg_transform_push_mf(struct wg_transform *transform, struct wg_sample *wg_sample, - struct wg_sample_queue *queue) -{ - struct mf_sample *mf_sample = CONTAINING_RECORD(wg_sample, struct mf_sample, wg_sample); - LONGLONG time, duration; - UINT32 value; - HRESULT hr; - - if (SUCCEEDED(IMFSample_GetSampleTime(mf_sample->sample, &time))) - { - mf_sample->wg_sample.flags |= WG_SAMPLE_FLAG_HAS_PTS; - mf_sample->wg_sample.pts = time; - } - if (SUCCEEDED(IMFSample_GetSampleDuration(mf_sample->sample, &duration))) - { - mf_sample->wg_sample.flags |= WG_SAMPLE_FLAG_HAS_DURATION; - mf_sample->wg_sample.duration = duration; - } - if (SUCCEEDED(IMFSample_GetUINT32(mf_sample->sample, &MFSampleExtension_CleanPoint, &value)) && value) - mf_sample->wg_sample.flags |= WG_SAMPLE_FLAG_SYNC_POINT; - - wg_sample_queue_begin_append(queue, wg_sample); - hr = wg_transform_push_data(transform, wg_sample); - wg_sample_queue_end_append(queue, wg_sample); - - return hr; -} - -HRESULT wg_transform_read_mf(struct wg_transform *transform, struct wg_sample *wg_sample, - struct wg_format *format) -{ - struct mf_sample *mf_sample = CONTAINING_RECORD(wg_sample, struct mf_sample, wg_sample); - HRESULT hr; - - if (FAILED(hr = wg_transform_read_data(transform, wg_sample, format))) - return hr; - - IMFMediaBuffer_SetCurrentLength(mf_sample->media_buffer, wg_sample->size); - - 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); - - return S_OK; -} diff --git a/dlls/winegstreamer/wg_sample.c b/dlls/winegstreamer/wg_sample.c new file mode 100644 index 00000000000..051e6199ec9 --- /dev/null +++ b/dlls/winegstreamer/wg_sample.c @@ -0,0 +1,203 @@ +/* + * 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" +#include "wine/list.h" + +WINE_DEFAULT_DEBUG_CHANNEL(mfplat); + +struct wg_sample_queue +{ + CRITICAL_SECTION cs; + struct list samples; +}; + +struct sample +{ + IMFSample *sample; + IMFMediaBuffer *media_buffer; + struct wg_sample wg_sample; + struct list entry; +}; + +HRESULT wg_sample_create_mf(IMFSample *mf_sample, struct wg_sample **out) +{ + DWORD current_length, max_length; + struct sample *sample; + BYTE *buffer; + HRESULT hr; + + if (!(sample = calloc(1, sizeof(*sample)))) + return E_OUTOFMEMORY; + if (FAILED(hr = IMFSample_ConvertToContiguousBuffer(mf_sample, &sample->media_buffer))) + goto fail; + if (FAILED(hr = IMFMediaBuffer_Lock(sample->media_buffer, &buffer, &max_length, ¤t_length))) + goto fail; + + IMFSample_AddRef((sample->sample = mf_sample)); + sample->wg_sample.data = buffer; + sample->wg_sample.size = current_length; + sample->wg_sample.max_size = max_length; + + *out = &sample->wg_sample; + TRACE_(mfplat)("Created wg_sample %p for IMFSample %p.\n", *out, mf_sample); + return S_OK; + +fail: + if (sample->media_buffer) + IMFMediaBuffer_Release(sample->media_buffer); + free(sample); + return hr; +} + +void wg_sample_release(struct wg_sample *wg_sample) +{ + struct sample *sample = CONTAINING_RECORD(wg_sample, struct sample, wg_sample); + + if (InterlockedOr(&wg_sample->refcount, 0)) + { + ERR("wg_sample %p is still in use, trouble ahead!\n", wg_sample); + return; + } + + IMFMediaBuffer_Unlock(sample->media_buffer); + IMFMediaBuffer_Release(sample->media_buffer); + IMFSample_Release(sample->sample); + + free(sample); +} + +static void wg_sample_queue_begin_append(struct wg_sample_queue *queue, struct wg_sample *wg_sample) +{ + struct sample *sample = CONTAINING_RECORD(wg_sample, struct sample, wg_sample); + + /* make sure a concurrent wg_sample_queue_flush call won't release the sample until we're done */ + InterlockedIncrement(&wg_sample->refcount); + sample->wg_sample.flags |= WG_SAMPLE_FLAG_HAS_REFCOUNT; + + EnterCriticalSection(&queue->cs); + list_add_tail(&queue->samples, &sample->entry); + LeaveCriticalSection(&queue->cs); +} + +static void wg_sample_queue_end_append(struct wg_sample_queue *queue, struct wg_sample *wg_sample) +{ + /* release temporary ref taken in wg_sample_queue_begin_append */ + InterlockedDecrement(&wg_sample->refcount); + + wg_sample_queue_flush(queue, false); +} + +void wg_sample_queue_flush(struct wg_sample_queue *queue, bool all) +{ + struct sample *sample, *next; + + EnterCriticalSection(&queue->cs); + + LIST_FOR_EACH_ENTRY_SAFE(sample, next, &queue->samples, struct sample, entry) + { + if (!InterlockedOr(&sample->wg_sample.refcount, 0) || all) + { + list_remove(&sample->entry); + wg_sample_release(&sample->wg_sample); + } + } + + LeaveCriticalSection(&queue->cs); +} + +HRESULT wg_sample_queue_create(struct wg_sample_queue **out) +{ + struct wg_sample_queue *queue; + + if (!(queue = calloc(1, sizeof(*queue)))) + return E_OUTOFMEMORY; + + InitializeCriticalSection(&queue->cs); + queue->cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": cs"); + list_init(&queue->samples); + + TRACE("Created wg_sample_queue %p.\n", queue); + *out = queue; + + return S_OK; +} + +void wg_sample_queue_destroy(struct wg_sample_queue *queue) +{ + wg_sample_queue_flush(queue, true); + + queue->cs.DebugInfo->Spare[0] = 0; + InitializeCriticalSection(&queue->cs); + + free(queue); +} + +HRESULT wg_transform_push_mf(struct wg_transform *transform, struct wg_sample *wg_sample, + struct wg_sample_queue *queue) +{ + struct sample *sample = CONTAINING_RECORD(wg_sample, struct sample, wg_sample); + LONGLONG time, duration; + UINT32 value; + HRESULT hr; + + if (SUCCEEDED(IMFSample_GetSampleTime(sample->sample, &time))) + { + sample->wg_sample.flags |= WG_SAMPLE_FLAG_HAS_PTS; + sample->wg_sample.pts = time; + } + if (SUCCEEDED(IMFSample_GetSampleDuration(sample->sample, &duration))) + { + sample->wg_sample.flags |= WG_SAMPLE_FLAG_HAS_DURATION; + sample->wg_sample.duration = duration; + } + if (SUCCEEDED(IMFSample_GetUINT32(sample->sample, &MFSampleExtension_CleanPoint, &value)) && value) + sample->wg_sample.flags |= WG_SAMPLE_FLAG_SYNC_POINT; + + wg_sample_queue_begin_append(queue, wg_sample); + hr = wg_transform_push_data(transform, wg_sample); + wg_sample_queue_end_append(queue, wg_sample); + + return hr; +} + +HRESULT wg_transform_read_mf(struct wg_transform *transform, struct wg_sample *wg_sample, + struct wg_format *format) +{ + struct sample *sample = CONTAINING_RECORD(wg_sample, struct sample, wg_sample); + HRESULT hr; + + if (FAILED(hr = wg_transform_read_data(transform, wg_sample, format))) + return hr; + + IMFMediaBuffer_SetCurrentLength(sample->media_buffer, wg_sample->size); + + if (wg_sample->flags & WG_SAMPLE_FLAG_HAS_PTS) + IMFSample_SetSampleTime(sample->sample, wg_sample->pts); + if (wg_sample->flags & WG_SAMPLE_FLAG_HAS_DURATION) + IMFSample_SetSampleDuration(sample->sample, wg_sample->duration); + if (wg_sample->flags & WG_SAMPLE_FLAG_SYNC_POINT) + IMFSample_SetUINT32(sample->sample, &MFSampleExtension_CleanPoint, 1); + + return S_OK; +}