winegstreamer: Implement IWMReaderAdvanced::SetAllocateForOutput().

Signed-off-by: Zebediah Figura <zfigura@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Zebediah Figura 2021-11-10 19:05:46 -06:00 committed by Alexandre Julliard
parent 97d6cfd705
commit 2f7e7d284b
3 changed files with 91 additions and 18 deletions

View File

@ -120,10 +120,11 @@ struct wm_stream
{
struct wm_reader *reader;
struct wg_parser_stream *wg_stream;
WORD index;
bool eos;
struct wg_format format;
WMT_STREAM_SELECTION selection;
WORD index;
bool eos;
bool allocate_output;
};
struct wm_reader
@ -148,6 +149,8 @@ struct wm_reader
struct wm_stream *streams;
WORD stream_count;
IWMReaderCallbackAdvanced *callback_advanced;
const struct wm_reader_ops *ops;
};
@ -174,6 +177,7 @@ void wm_reader_init(struct wm_reader *reader, const struct wm_reader_ops *ops);
HRESULT wm_reader_open_file(struct wm_reader *reader, const WCHAR *filename);
HRESULT wm_reader_open_stream(struct wm_reader *reader, IStream *stream);
void wm_reader_seek(struct wm_reader *reader, QWORD start, LONGLONG duration);
HRESULT wm_reader_set_allocate_for_output(struct wm_reader *reader, DWORD output, BOOL allocate);
HRESULT wm_reader_set_output_props(struct wm_reader *reader, DWORD output,
IWMOutputMediaProps *props);
HRESULT wm_reader_set_streams_selected(struct wm_reader *reader, WORD count,

View File

@ -57,10 +57,16 @@ static REFERENCE_TIME get_current_time(const struct async_reader *reader)
static void open_stream(struct async_reader *reader, IWMReaderCallback *callback, void *context)
{
static const DWORD zero;
HRESULT hr;
IWMReaderCallback_AddRef(reader->callback = callback);
reader->context = context;
IWMReaderCallback_OnStatus(callback, WMT_OPENED, S_OK, WMT_TYPE_DWORD, (BYTE *)&zero, context);
if (FAILED(hr = IWMReaderCallback_QueryInterface(callback,
&IID_IWMReaderCallbackAdvanced, (void **)&reader->reader.callback_advanced)))
reader->reader.callback_advanced = NULL;
TRACE("Querying for IWMReaderCallbackAdvanced returned %#x.\n", hr);
}
static DWORD WINAPI stream_thread(void *arg)
@ -497,11 +503,14 @@ static HRESULT WINAPI WMReaderAdvanced_GetReceiveStreamSamples(IWMReaderAdvanced
return E_NOTIMPL;
}
static HRESULT WINAPI WMReaderAdvanced_SetAllocateForOutput(IWMReaderAdvanced6 *iface, DWORD output_num, BOOL allocate)
static HRESULT WINAPI WMReaderAdvanced_SetAllocateForOutput(IWMReaderAdvanced6 *iface,
DWORD output, BOOL allocate)
{
struct async_reader *This = impl_from_IWMReaderAdvanced6(iface);
FIXME("(%p)->(%d %x)\n", This, output_num, allocate);
return E_NOTIMPL;
struct async_reader *reader = impl_from_IWMReaderAdvanced6(iface);
TRACE("reader %p, output %u, allocate %d.\n", reader, output, allocate);
return wm_reader_set_allocate_for_output(&reader->reader, output, allocate);
}
static HRESULT WINAPI WMReaderAdvanced_GetAllocateForOutput(IWMReaderAdvanced6 *iface, DWORD output_num, BOOL *allocate)

View File

@ -1532,6 +1532,10 @@ HRESULT wm_reader_close(struct wm_reader *reader)
CloseHandle(reader->read_thread);
reader->read_thread = NULL;
if (reader->callback_advanced)
IWMReaderCallbackAdvanced_Release(reader->callback_advanced);
reader->callback_advanced = NULL;
wg_parser_destroy(reader->wg_parser);
reader->wg_parser = NULL;
@ -1736,9 +1740,9 @@ static const char *get_major_type_string(enum wg_major_type type)
HRESULT wm_reader_get_stream_sample(struct wm_stream *stream,
INSSBuffer **ret_sample, QWORD *pts, QWORD *duration, DWORD *flags)
{
IWMReaderCallbackAdvanced *callback_advanced = stream->reader->callback_advanced;
struct wg_parser_stream *wg_stream = stream->wg_stream;
struct wg_parser_event event;
struct buffer *object;
if (stream->selection == WMT_OFF)
return NS_E_INVALID_REQUEST;
@ -1746,6 +1750,9 @@ HRESULT wm_reader_get_stream_sample(struct wm_stream *stream,
if (stream->eos)
return NS_E_NO_MORE_SAMPLES;
if (!stream->allocate_output)
callback_advanced = NULL;
for (;;)
{
if (!wg_parser_stream_get_event(wg_stream, &event))
@ -1760,24 +1767,59 @@ HRESULT wm_reader_get_stream_sample(struct wm_stream *stream,
switch (event.type)
{
case WG_PARSER_EVENT_BUFFER:
/* FIXME: Should these be pooled? */
if (!(object = calloc(1, offsetof(struct buffer, data[event.u.buffer.size]))))
{
DWORD size, capacity;
INSSBuffer *sample;
HRESULT hr;
BYTE *data;
if (callback_advanced)
{
wg_parser_stream_release_buffer(wg_stream);
return E_OUTOFMEMORY;
if (FAILED(hr = IWMReaderCallbackAdvanced_AllocateForOutput(callback_advanced,
stream->index, event.u.buffer.size, &sample, NULL)))
{
ERR("Failed to allocate sample of %u bytes, hr %#x.\n", event.u.buffer.size, hr);
wg_parser_stream_release_buffer(wg_stream);
return hr;
}
}
else
{
struct buffer *object;
/* FIXME: Should these be pooled? */
if (!(object = calloc(1, offsetof(struct buffer, data[event.u.buffer.size]))))
{
wg_parser_stream_release_buffer(wg_stream);
return E_OUTOFMEMORY;
}
object->INSSBuffer_iface.lpVtbl = &buffer_vtbl;
object->refcount = 1;
object->capacity = event.u.buffer.size;
TRACE("Created buffer %p.\n", object);
sample = &object->INSSBuffer_iface;
}
object->INSSBuffer_iface.lpVtbl = &buffer_vtbl;
object->refcount = 1;
object->capacity = object->size = event.u.buffer.size;
if (FAILED(hr = INSSBuffer_GetBufferAndLength(sample, &data, &size)))
ERR("Failed to get data pointer, hr %#x.\n", hr);
if (FAILED(hr = INSSBuffer_GetMaxLength(sample, &capacity)))
ERR("Failed to get capacity, hr %#x.\n", hr);
if (event.u.buffer.size > capacity)
ERR("Returned capacity %u is less than requested capacity %u.\n",
capacity, event.u.buffer.size);
if (!wg_parser_stream_copy_buffer(wg_stream, object->data, 0, object->size))
if (!wg_parser_stream_copy_buffer(wg_stream, data, 0, event.u.buffer.size))
{
/* The GStreamer pin has been flushed. */
free(object);
INSSBuffer_Release(sample);
break;
}
if (FAILED(hr = INSSBuffer_SetLength(sample, event.u.buffer.size)))
ERR("Failed to set size %u, hr %#x.\n", event.u.buffer.size, hr);
wg_parser_stream_release_buffer(wg_stream);
if (!event.u.buffer.has_pts)
@ -1793,9 +1835,9 @@ HRESULT wm_reader_get_stream_sample(struct wm_stream *stream,
if (!event.u.buffer.delta)
*flags |= WM_SF_CLEANPOINT;
TRACE("Created buffer %p.\n", object);
*ret_sample = &object->INSSBuffer_iface;
*ret_sample = sample;
return S_OK;
}
case WG_PARSER_EVENT_EOS:
stream->eos = true;
@ -1891,6 +1933,24 @@ HRESULT wm_reader_get_stream_selection(struct wm_reader *reader,
return S_OK;
}
HRESULT wm_reader_set_allocate_for_output(struct wm_reader *reader, DWORD output, BOOL allocate)
{
struct wm_stream *stream;
EnterCriticalSection(&reader->cs);
if (!(stream = get_stream_by_output_number(reader, output)))
{
LeaveCriticalSection(&reader->cs);
return E_INVALIDARG;
}
stream->allocate_output = !!allocate;
LeaveCriticalSection(&reader->cs);
return S_OK;
}
void wm_reader_init(struct wm_reader *reader, const struct wm_reader_ops *ops)
{
reader->IWMHeaderInfo3_iface.lpVtbl = &header_info_vtbl;