From: Ziqing Hui zhui@codeweavers.com
--- dlls/winegstreamer/gst_private.h | 2 +- dlls/winegstreamer/main.c | 5 +- dlls/winegstreamer/media_sink.c | 125 +++++++++++++++++++++++++++---- dlls/winegstreamer/unixlib.h | 1 + dlls/winegstreamer/wg_muxer.c | 1 + 5 files changed, 116 insertions(+), 18 deletions(-)
diff --git a/dlls/winegstreamer/gst_private.h b/dlls/winegstreamer/gst_private.h index 0307b7ba375..f6b992c2b78 100644 --- a/dlls/winegstreamer/gst_private.h +++ b/dlls/winegstreamer/gst_private.h @@ -114,7 +114,7 @@ wg_muxer_t wg_muxer_create(enum wg_container_type container_type); void wg_muxer_destroy(wg_muxer_t muxer); HRESULT wg_muxer_add_stream(wg_muxer_t muxer, DWORD stream_id, const struct wg_format *format); HRESULT wg_muxer_push_sample(wg_muxer_t muxer, struct wg_sample *sample); -bool wg_muxer_get_buffer(wg_muxer_t muxer, uint32_t *size); +bool wg_muxer_get_buffer(wg_muxer_t muxer, uint32_t *size, uint64_t *offset); HRESULT wg_muxer_copy_buffer(wg_muxer_t muxer, void *buffer, UINT32 size); void wg_muxer_free_buffer(wg_muxer_t muxer);
diff --git a/dlls/winegstreamer/main.c b/dlls/winegstreamer/main.c index c6a1993740b..6f3fa5a550f 100644 --- a/dlls/winegstreamer/main.c +++ b/dlls/winegstreamer/main.c @@ -520,9 +520,9 @@ HRESULT wg_muxer_push_sample(wg_muxer_t muxer, struct wg_sample *sample) return S_OK; }
-bool wg_muxer_get_buffer(wg_muxer_t muxer, uint32_t *size) +bool wg_muxer_get_buffer(wg_muxer_t muxer, uint32_t *size, uint64_t *offset) { - struct wg_muxer_copy_buffer_params params = + struct wg_muxer_get_buffer_params params = { .muxer = muxer, }; @@ -532,6 +532,7 @@ bool wg_muxer_get_buffer(wg_muxer_t muxer, uint32_t *size) if (!WINE_UNIX_CALL(unix_wg_muxer_get_buffer, ¶ms)) { *size = params.size; + *offset = params.offset; return true; }
diff --git a/dlls/winegstreamer/media_sink.c b/dlls/winegstreamer/media_sink.c index 86a69d0d9ba..63790552ff2 100644 --- a/dlls/winegstreamer/media_sink.c +++ b/dlls/winegstreamer/media_sink.c @@ -30,6 +30,7 @@ enum async_op ASYNC_START, ASYNC_STOP, ASYNC_PAUSE, + ASYNC_PROCESS, };
struct async_command @@ -38,6 +39,9 @@ struct async_command LONG refcount;
enum async_op op; + + IMFSample *sample; + UINT32 stream_id; };
struct stream_sink @@ -77,6 +81,8 @@ struct media_sink struct stream_sink **stream_sinks; size_t stream_sink_count; size_t stream_sink_size; + + wg_muxer_t muxer; };
static struct stream_sink *impl_from_IMFStreamSink(IMFStreamSink *iface) @@ -135,7 +141,11 @@ static ULONG WINAPI async_command_Release(IUnknown *iface) ULONG refcount = InterlockedDecrement(&command->refcount);
if (!refcount) + { + if (command->sample) + IMFSample_Release(command->sample); free(command); + }
return refcount; } @@ -285,9 +295,39 @@ 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 = 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->sample = sample); + command->stream_id = stream_sink->id; + hr = MFPutWorkItem(media_sink->async_queue, &media_sink->async_callback, &command->IUnknown_iface); + + LeaveCriticalSection(&media_sink->cs); + return hr; }
static HRESULT WINAPI stream_sink_PlaceMarker(IMFStreamSink *iface, MFSTREAMSINK_MARKER_TYPE marker_type, @@ -435,6 +475,38 @@ static HRESULT media_sink_pause(struct media_sink *media_sink) return hr; }
+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; + ULONG size, written; + QWORD offset; + BYTE *data; + HRESULT hr; + + if (FAILED(hr = wg_sample_create_mf(sample, &wg_sample))) + return hr; + wg_sample->stream_id = stream_id; + + if (FAILED(hr = wg_muxer_push_sample(muxer, wg_sample))) + return hr; + + while (wg_muxer_get_buffer(muxer, &size, &offset)) + { + if (!(data = malloc(size))) + return E_OUTOFMEMORY; + if (!(wg_muxer_copy_buffer(muxer, data, size))) + return E_FAIL; + + if (FAILED(hr = IMFByteStream_SetCurrentPosition(media_sink->bytestream, offset))) /* FIXME. */ + return hr; + if (FAILED(hr = IMFByteStream_Write(media_sink->bytestream, data, size, &written))) + return hr; + + wg_muxer_free_buffer(muxer); + } +} + static HRESULT WINAPI media_sink_QueryInterface(IMFFinalizableMediaSink *iface, REFIID riid, void **obj) { struct media_sink *media_sink = impl_from_IMFFinalizableMediaSink(iface); @@ -487,6 +559,7 @@ static ULONG WINAPI media_sink_Release(IMFFinalizableMediaSink *iface) IMFFinalizableMediaSink_Shutdown(iface); IMFMediaEventQueue_Release(media_sink->event_queue); IMFByteStream_Release(media_sink->bytestream); + wg_muxer_destroy(media_sink->muxer); free(media_sink); }
@@ -505,6 +578,7 @@ static HRESULT WINAPI media_sink_AddStreamSink(IMFFinalizableMediaSink *iface, D { struct media_sink *media_sink = impl_from_IMFFinalizableMediaSink(iface); struct stream_sink *object; + struct wg_format format; HRESULT hr;
TRACE("iface %p, stream_sink_id %#lx, media_type %p, stream_sink %p.\n", @@ -521,6 +595,13 @@ static HRESULT WINAPI media_sink_AddStreamSink(IMFFinalizableMediaSink *iface, D return hr; }
+ mf_media_type_to_wg_format(media_type, &format); + if (FAILED(hr = wg_muxer_add_stream(media_sink->muxer, stream_sink_id, &format))) + { + IMFStreamSink_Release(&object->IMFStreamSink_iface); + return hr; + } + EnterCriticalSection(&media_sink->cs);
if (!array_reserve((void **)&media_sink->stream_sinks, @@ -565,9 +646,18 @@ static HRESULT WINAPI media_sink_GetStreamSinkByIndex(IMFFinalizableMediaSink *i static HRESULT WINAPI media_sink_GetStreamSinkById(IMFFinalizableMediaSink *iface, DWORD stream_sink_id, IMFStreamSink **stream) { - FIXME("iface %p, stream_sink_id %#lx, stream %p stub!\n", iface, stream_sink_id, stream); + struct media_sink *media_sink = impl_from_IMFFinalizableMediaSink(iface); + struct stream_sink *stream_sink;
- return E_NOTIMPL; + TRACE("iface %p, stream_sink_id %#lx, stream %p stub!\n", iface, stream_sink_id, stream); + + if ((stream_sink = media_sink_get_stream_sink_by_id(media_sink, stream_sink_id))) + { + *stream = &stream_sink->IMFStreamSink_iface; + return S_OK; + } + + return MF_E_INVALIDSTREAMNUMBER; }
static HRESULT WINAPI media_sink_SetPresentationClock(IMFFinalizableMediaSink *iface, IMFPresentationClock *clock) @@ -881,6 +971,9 @@ static HRESULT WINAPI media_sink_callback_Invoke(IMFAsyncCallback *iface, IMFAsy case ASYNC_PAUSE: hr = media_sink_pause(media_sink); break; + case ASYNC_PROCESS: + hr = media_sink_process(media_sink, command->sample, command->stream_id); + break; default: WARN("Unsupported op %u.\n", command->op); break; @@ -905,7 +998,7 @@ static const IMFAsyncCallbackVtbl media_sink_callback_vtbl = static HRESULT media_sink_create(IMFByteStream *bytestream, wg_container_type type, struct media_sink **out) { struct media_sink *media_sink; - HRESULT hr; + HRESULT hr = E_FAIL;
TRACE("bytestream %p, out %p.\n", bytestream, out);
@@ -915,18 +1008,12 @@ static HRESULT media_sink_create(IMFByteStream *bytestream, wg_container_type ty if (!(media_sink = calloc(1, sizeof(*media_sink)))) return E_OUTOFMEMORY;
+ if (!(media_sink->muxer = wg_muxer_create(type))) + goto fail; if (FAILED(hr = MFCreateEventQueue(&media_sink->event_queue))) - { - free(media_sink); - return hr; - } - + goto fail; if (FAILED(hr = MFAllocateWorkQueue(&media_sink->async_queue))) - { - IMFMediaEventQueue_Release(media_sink->event_queue); - free(media_sink); - return hr; - } + goto fail;
media_sink->IMFFinalizableMediaSink_iface.lpVtbl = &media_sink_vtbl; media_sink->IMFMediaEventGenerator_iface.lpVtbl = &media_sink_event_vtbl; @@ -943,6 +1030,14 @@ static HRESULT media_sink_create(IMFByteStream *bytestream, wg_container_type ty TRACE("Created media sink %p.\n", media_sink);
return S_OK; + +fail: + if (media_sink->event_queue) + IMFMediaEventQueue_Release(media_sink->event_queue); + if (media_sink->muxer) + wg_muxer_destroy(media_sink->muxer); + free(media_sink); + return hr; }
static HRESULT WINAPI sink_class_factory_QueryInterface(IMFSinkClassFactory *iface, REFIID riid, void **out) diff --git a/dlls/winegstreamer/unixlib.h b/dlls/winegstreamer/unixlib.h index 05ef465d58f..2c009e2b84b 100644 --- a/dlls/winegstreamer/unixlib.h +++ b/dlls/winegstreamer/unixlib.h @@ -396,6 +396,7 @@ struct wg_muxer_get_buffer_params { wg_muxer_t muxer; UINT32 size; + UINT64 offset; };
struct wg_muxer_copy_buffer_params diff --git a/dlls/winegstreamer/wg_muxer.c b/dlls/winegstreamer/wg_muxer.c index b3968707bdc..0e9e9541773 100644 --- a/dlls/winegstreamer/wg_muxer.c +++ b/dlls/winegstreamer/wg_muxer.c @@ -337,6 +337,7 @@ NTSTATUS wg_muxer_get_buffer(void *args) }
params->size = muxer->map_info.size; + params->offset = GST_BUFFER_OFFSET(muxer->buffer);
return STATUS_SUCCESS; }