Module: wine Branch: master Commit: 37b2548399c393b2c0d7b8fa74971359c5a9f66c URL: https://gitlab.winehq.org/wine/wine/-/commit/37b2548399c393b2c0d7b8fa7497135...
Author: Ziqing Hui zhui@codeweavers.com Date: Fri Aug 18 10:03:45 2023 +0800
winegstreamer: Implement ProcessSample for media sink.
---
dlls/winegstreamer/gst_private.h | 1 + dlls/winegstreamer/main.c | 21 ++++++++++ dlls/winegstreamer/media_sink.c | 88 ++++++++++++++++++++++++++++++++++++++- dlls/winegstreamer/unix_private.h | 1 + dlls/winegstreamer/unixlib.h | 8 ++++ dlls/winegstreamer/wg_muxer.c | 5 +++ dlls/winegstreamer/wg_parser.c | 19 +++++++++ 7 files changed, 141 insertions(+), 2 deletions(-)
diff --git a/dlls/winegstreamer/gst_private.h b/dlls/winegstreamer/gst_private.h index 22d92cfeef7..8712980092b 100644 --- a/dlls/winegstreamer/gst_private.h +++ b/dlls/winegstreamer/gst_private.h @@ -114,6 +114,7 @@ HRESULT wg_muxer_create(const char *format, wg_muxer_t *muxer); void wg_muxer_destroy(wg_muxer_t muxer); HRESULT wg_muxer_add_stream(wg_muxer_t muxer, UINT32 stream_id, const struct wg_format *format); HRESULT wg_muxer_start(wg_muxer_t muxer); +HRESULT wg_muxer_push_sample(wg_muxer_t muxer, struct wg_sample *sample, UINT32 stream_id);
unsigned int wg_format_get_bytes_for_uncompressed(wg_video_format format, unsigned int width, unsigned int height); unsigned int wg_format_get_max_size(const struct wg_format *format); diff --git a/dlls/winegstreamer/main.c b/dlls/winegstreamer/main.c index 58ad8c6f3d7..3eb82bdccf5 100644 --- a/dlls/winegstreamer/main.c +++ b/dlls/winegstreamer/main.c @@ -523,6 +523,27 @@ HRESULT wg_muxer_start(wg_muxer_t muxer) return S_OK; }
+HRESULT wg_muxer_push_sample(wg_muxer_t muxer, struct wg_sample *sample, UINT32 steam_id) +{ + struct wg_muxer_push_sample_params params = + { + .muxer = muxer, + .sample = sample, + .stream_id = steam_id, + }; + NTSTATUS status; + + TRACE("muxer %#I64x, sample %p.\n", muxer, sample); + + if ((status = WINE_UNIX_CALL(unix_wg_muxer_push_sample, ¶ms))) + { + WARN("Failed to push sample, status %#lx.\n", status); + return HRESULT_FROM_NT(status); + } + + return S_OK; +} + #define ALIGN(n, alignment) (((n) + (alignment) - 1) & ~((alignment) - 1))
unsigned int wg_format_get_stride(const struct wg_format *format) diff --git a/dlls/winegstreamer/media_sink.c b/dlls/winegstreamer/media_sink.c index 489ede1d26a..d9c15291b61 100644 --- a/dlls/winegstreamer/media_sink.c +++ b/dlls/winegstreamer/media_sink.c @@ -31,6 +31,7 @@ enum async_op ASYNC_START, ASYNC_STOP, ASYNC_PAUSE, + ASYNC_PROCESS, };
struct async_command @@ -39,6 +40,15 @@ struct async_command LONG refcount;
enum async_op op; + + union + { + struct + { + IMFSample *sample; + UINT32 stream_id; + } process; + } u; };
struct stream_sink @@ -142,7 +152,11 @@ static ULONG WINAPI async_command_Release(IUnknown *iface) ULONG refcount = InterlockedDecrement(&command->refcount);
if (!refcount) + { + if (command->op == ASYNC_PROCESS && command->u.process.sample) + IMFSample_Release(command->u.process.sample); free(command); + }
return refcount; } @@ -301,9 +315,41 @@ static HRESULT WINAPI stream_sink_GetMediaTypeHandler(IMFStreamSink *iface, IMFM
static HRESULT WINAPI stream_sink_ProcessSample(IMFStreamSink *iface, IMFSample *sample) { - FIXME("iface %p, sample %p stub!\n", iface, sample); + struct stream_sink *stream_sink = impl_from_IMFStreamSink(iface); + struct media_sink *media_sink = impl_from_IMFFinalizableMediaSink(stream_sink->media_sink); + struct async_command *command; + HRESULT hr;
- return E_NOTIMPL; + TRACE("iface %p, sample %p.\n", iface, sample); + + EnterCriticalSection(&media_sink->cs); + + if (media_sink->state == STATE_SHUTDOWN) + { + LeaveCriticalSection(&media_sink->cs); + return MF_E_SHUTDOWN; + } + + if (media_sink->state != STATE_STARTED && media_sink->state != STATE_PAUSED) + { + LeaveCriticalSection(&media_sink->cs); + return MF_E_INVALIDREQUEST; + } + + if (FAILED(hr = (async_command_create(ASYNC_PROCESS, &command)))) + { + LeaveCriticalSection(&media_sink->cs); + return hr; + } + IMFSample_AddRef((command->u.process.sample = sample)); + command->u.process.stream_id = stream_sink->id; + + if (FAILED(hr = MFPutWorkItem(MFASYNC_CALLBACK_QUEUE_STANDARD, &media_sink->async_callback, &command->IUnknown_iface))) + IUnknown_Release(&command->IUnknown_iface); + + LeaveCriticalSection(&media_sink->cs); + + return hr; }
static HRESULT WINAPI stream_sink_PlaceMarker(IMFStreamSink *iface, MFSTREAMSINK_MARKER_TYPE marker_type, @@ -521,6 +567,40 @@ static HRESULT media_sink_pause(struct media_sink *media_sink) return media_sink_queue_stream_event(media_sink, MEStreamSinkPaused); }
+static HRESULT media_sink_process(struct media_sink *media_sink, IMFSample *sample, UINT32 stream_id) +{ + wg_muxer_t muxer = media_sink->muxer; + struct wg_sample *wg_sample; + LONGLONG time, duration; + UINT32 value; + HRESULT hr; + + TRACE("media_sink %p, sample %p, stream_id %u.\n", media_sink, sample, stream_id); + + if (FAILED(hr = wg_sample_create_mf(sample, &wg_sample))) + return hr; + + if (SUCCEEDED(IMFSample_GetSampleTime(sample, &time))) + { + wg_sample->flags |= WG_SAMPLE_FLAG_HAS_PTS; + wg_sample->pts = time; + } + if (SUCCEEDED(IMFSample_GetSampleDuration(sample, &duration))) + { + wg_sample->flags |= WG_SAMPLE_FLAG_HAS_DURATION; + wg_sample->duration = duration; + } + if (SUCCEEDED(IMFSample_GetUINT32(sample, &MFSampleExtension_CleanPoint, &value)) && value) + wg_sample->flags |= WG_SAMPLE_FLAG_SYNC_POINT; + if (SUCCEEDED(IMFSample_GetUINT32(sample, &MFSampleExtension_Discontinuity, &value)) && value) + wg_sample->flags |= WG_SAMPLE_FLAG_DISCONTINUITY; + + hr = wg_muxer_push_sample(muxer, wg_sample, stream_id); + wg_sample_release(wg_sample); + + return hr; +} + static HRESULT WINAPI media_sink_QueryInterface(IMFFinalizableMediaSink *iface, REFIID riid, void **obj) { struct media_sink *media_sink = impl_from_IMFFinalizableMediaSink(iface); @@ -1022,6 +1102,10 @@ static HRESULT WINAPI media_sink_callback_Invoke(IMFAsyncCallback *iface, IMFAsy case ASYNC_PAUSE: hr = media_sink_pause(media_sink); break; + case ASYNC_PROCESS: + if (FAILED(hr = media_sink_process(media_sink, command->u.process.sample, command->u.process.stream_id))) + WARN("Failed to process sample, hr %#lx.\n", hr); + break; default: WARN("Unsupported op %u.\n", command->op); break; diff --git a/dlls/winegstreamer/unix_private.h b/dlls/winegstreamer/unix_private.h index ad1817d8c2d..f639b03bcce 100644 --- a/dlls/winegstreamer/unix_private.h +++ b/dlls/winegstreamer/unix_private.h @@ -69,6 +69,7 @@ extern NTSTATUS wg_muxer_create(void *args) DECLSPEC_HIDDEN; extern NTSTATUS wg_muxer_destroy(void *args) DECLSPEC_HIDDEN; extern NTSTATUS wg_muxer_add_stream(void *args) DECLSPEC_HIDDEN; extern NTSTATUS wg_muxer_start(void *args) DECLSPEC_HIDDEN; +extern NTSTATUS wg_muxer_push_sample(void *args) DECLSPEC_HIDDEN;
/* wg_allocator.c */
diff --git a/dlls/winegstreamer/unixlib.h b/dlls/winegstreamer/unixlib.h index 70bbe89208f..6c0c61f76bb 100644 --- a/dlls/winegstreamer/unixlib.h +++ b/dlls/winegstreamer/unixlib.h @@ -385,6 +385,13 @@ struct wg_muxer_add_stream_params const struct wg_format *format; };
+struct wg_muxer_push_sample_params +{ + wg_muxer_t muxer; + struct wg_sample *sample; + UINT32 stream_id; +}; + enum unix_funcs { unix_wg_init_gstreamer, @@ -429,6 +436,7 @@ enum unix_funcs unix_wg_muxer_destroy, unix_wg_muxer_add_stream, unix_wg_muxer_start, + unix_wg_muxer_push_sample,
unix_wg_funcs_count, }; diff --git a/dlls/winegstreamer/wg_muxer.c b/dlls/winegstreamer/wg_muxer.c index aa453ad9837..5d37489f994 100644 --- a/dlls/winegstreamer/wg_muxer.c +++ b/dlls/winegstreamer/wg_muxer.c @@ -343,3 +343,8 @@ NTSTATUS wg_muxer_start(void *args)
return STATUS_SUCCESS; } + +NTSTATUS wg_muxer_push_sample(void *args) +{ + return STATUS_NOT_IMPLEMENTED; +} diff --git a/dlls/winegstreamer/wg_parser.c b/dlls/winegstreamer/wg_parser.c index 065b4216dd4..5a526b15712 100644 --- a/dlls/winegstreamer/wg_parser.c +++ b/dlls/winegstreamer/wg_parser.c @@ -1923,6 +1923,7 @@ const unixlib_entry_t __wine_unix_call_funcs[] = X(wg_muxer_destroy), X(wg_muxer_add_stream), X(wg_muxer_start), + X(wg_muxer_push_sample), };
C_ASSERT(ARRAYSIZE(__wine_unix_call_funcs) == unix_wg_funcs_count); @@ -2166,6 +2167,23 @@ NTSTATUS wow64_wg_muxer_add_stream(void *args) return wg_muxer_add_stream(¶ms); }
+NTSTATUS wow64_wg_muxer_push_sample(void *args) +{ + struct + { + wg_muxer_t muxer; + PTR32 sample; + UINT32 stream_id; + } *params32 = args; + struct wg_muxer_push_sample_params params = + { + .muxer = params32->muxer, + .sample = ULongToPtr(params32->sample), + .stream_id = params32->stream_id, + }; + return wg_muxer_push_sample(¶ms); +} + const unixlib_entry_t __wine_unix_call_wow64_funcs[] = { #define X64(name) [unix_ ## name] = wow64_ ## name @@ -2211,6 +2229,7 @@ const unixlib_entry_t __wine_unix_call_wow64_funcs[] = X(wg_muxer_destroy), X64(wg_muxer_add_stream), X(wg_muxer_start), + X64(wg_muxer_push_sample), };
C_ASSERT(ARRAYSIZE(__wine_unix_call_wow64_funcs) == unix_wg_funcs_count);