On Fri Sep 8 01:32:38 2023 +0000, Ziqing Hui wrote:
See the 2 commits: https://gitlab.winehq.org/wine/wine/-/merge_requests/3303/diffs?commit_id=d1... https://gitlab.winehq.org/wine/wine/-/merge_requests/3303/diffs?commit_id=54... The output interface looks like this:
gst_private.h: HRESULT 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);
We will use them like this: (https://gitlab.winehq.org/wine/wine/-/merge_requests/3303/diffs?commit_id=54...)
media_sink.c static HRESULT media_sink_write_stream(struct media_sink *media_sink) { BYTE *data = NULL; ULONG written; QWORD offset; UINT32 size; HRESULT hr; while (SUCCEEDED(hr = wg_muxer_get_buffer(media_sink->muxer, &size, &offset))) { if (!(data = calloc(1, size))) return E_OUTOFMEMORY; if (FAILED(hr = wg_muxer_copy_buffer(media_sink->muxer, data, size))) { free(data); WARN("Failed to copy buffer, hr %#lx.", hr); return hr; } if ((offset != UINT64_MAX && FAILED(hr = IMFByteStream_SetCurrentPosition(media_sink->bytestream, offset))) || FAILED(hr = IMFByteStream_Write(media_sink->bytestream, data, size, &written))) { free(data); return hr; } free(data); wg_muxer_free_buffer(media_sink->muxer); } return S_OK; }
And we implement them like this: (https://gitlab.winehq.org/wine/wine/-/merge_requests/3303/diffs?commit_id=d1...)
wg_muxer.c: NTSTATUS wg_muxer_get_buffer(void *args) { struct wg_muxer_get_buffer_params *params = args; struct wg_muxer *muxer = get_muxer(params->muxer); if (!muxer->buffer) { if (!(muxer->buffer = gst_atomic_queue_pop(muxer->output_queue))) return MF_E_SINK_NO_SAMPLES_PROCESSED; if (!gst_buffer_map(muxer->buffer, &muxer->map_info, GST_MAP_READ)) { GST_ERROR("Failed to map buffer %p, dropped.", muxer->buffer); gst_buffer_unref(muxer->buffer); muxer->buffer = NULL; return E_FAIL; } } params->size = muxer->map_info.size; if (GST_BUFFER_OFFSET_IS_VALID(muxer->buffer)) params->offset = GST_BUFFER_OFFSET(muxer->buffer); return S_OK; } NTSTATUS wg_muxer_copy_buffer(void *args) { struct wg_muxer_copy_buffer_params *params = args; struct wg_muxer *muxer = get_muxer(params->muxer); if (!muxer->buffer) return MF_E_SINK_NO_SAMPLES_PROCESSED; if (params->size < muxer->map_info.size) return MF_E_BUFFERTOOSMALL; memcpy(params->buffer, muxer->map_info.data, muxer->map_info.size); return S_OK; } NTSTATUS wg_muxer_free_buffer(void *args) { struct wg_muxer *muxer = get_muxer(*(wg_muxer_t *)args); if (muxer->buffer) muxer_free_buffer(muxer); return S_OK; }
What about simply one wg_muxer_get_data where you would just read some requested number of bytes, or less, from the output buffer, popping additional buffers from the output queue if needed and if available?
I don't think there's any reason to express individual buffers to the PE side, as it's all written to a stream anyway.