Commit a67d7c15 authored by Nikolay Sivov's avatar Nikolay Sivov Committed by Alexandre Julliard

mfreadwrite/reader: Add support for reading to SA-allocated samples.

parent f892f2fe
...@@ -85,6 +85,7 @@ struct stream_response ...@@ -85,6 +85,7 @@ struct stream_response
DWORD stream_flags; DWORD stream_flags;
LONGLONG timestamp; LONGLONG timestamp;
IMFSample *sample; IMFSample *sample;
unsigned int sa_pending : 1;
}; };
enum media_stream_state enum media_stream_state
...@@ -365,27 +366,15 @@ static HRESULT WINAPI source_reader_callback_GetParameters(IMFAsyncCallback *ifa ...@@ -365,27 +366,15 @@ static HRESULT WINAPI source_reader_callback_GetParameters(IMFAsyncCallback *ifa
return E_NOTIMPL; return E_NOTIMPL;
} }
static void source_reader_queue_response(struct source_reader *reader, struct media_stream *stream, HRESULT status, static void source_reader_response_ready(struct source_reader *reader, struct stream_response *response)
DWORD stream_flags, LONGLONG timestamp, IMFSample *sample)
{ {
struct source_reader_async_command *command; struct source_reader_async_command *command;
struct stream_response *response; struct media_stream *stream = &reader->streams[response->stream_index];
HRESULT hr; HRESULT hr;
response = heap_alloc_zero(sizeof(*response)); if (!stream->requests || response->sa_pending)
response->status = status; return;
response->stream_index = stream->index;
response->stream_flags = stream_flags;
response->timestamp = timestamp;
response->sample = sample;
if (response->sample)
IMFSample_AddRef(response->sample);
list_add_tail(&reader->responses, &response->entry);
stream->responses++;
if (stream->requests)
{
if (reader->async_callback) if (reader->async_callback)
{ {
if (SUCCEEDED(source_reader_create_async_op(SOURCE_READER_ASYNC_SAMPLE_READY, &command))) if (SUCCEEDED(source_reader_create_async_op(SOURCE_READER_ASYNC_SAMPLE_READY, &command)))
...@@ -401,9 +390,81 @@ static void source_reader_queue_response(struct source_reader *reader, struct me ...@@ -401,9 +390,81 @@ static void source_reader_queue_response(struct source_reader *reader, struct me
WakeAllConditionVariable(&reader->sample_event); WakeAllConditionVariable(&reader->sample_event);
stream->requests--; stream->requests--;
}
static void source_reader_copy_sample_buffer(IMFSample *src, IMFSample *dst)
{
IMFMediaBuffer *buffer;
unsigned int flags;
LONGLONG time;
HRESULT hr;
IMFSample_CopyAllItems(src, (IMFAttributes *)dst);
IMFSample_SetSampleDuration(dst, 0);
IMFSample_SetSampleTime(dst, 0);
IMFSample_SetSampleFlags(dst, 0);
if (SUCCEEDED(IMFSample_GetSampleDuration(src, &time)))
IMFSample_SetSampleDuration(dst, time);
if (SUCCEEDED(IMFSample_GetSampleTime(src, &time)))
IMFSample_SetSampleTime(dst, time);
if (SUCCEEDED(IMFSample_GetSampleFlags(src, &flags)))
IMFSample_SetSampleFlags(dst, flags);
if (SUCCEEDED(IMFSample_ConvertToContiguousBuffer(src, NULL)))
{
if (SUCCEEDED(IMFSample_GetBufferByIndex(dst, 0, &buffer)))
{
if (FAILED(hr = IMFSample_CopyToBuffer(src, buffer)))
WARN("Failed to copy a buffer, hr %#x.\n", hr);
IMFMediaBuffer_Release(buffer);
}
} }
} }
static void source_reader_set_sa_response(struct source_reader *reader, struct stream_response *response)
{
struct media_stream *stream = &reader->streams[response->stream_index];
IMFSample *sample;
if (SUCCEEDED(IMFVideoSampleAllocatorEx_AllocateSample(stream->allocator, &sample)))
{
source_reader_copy_sample_buffer(response->sample, sample);
response->sa_pending = 0;
IMFSample_Release(response->sample);
response->sample = sample;
}
}
static void source_reader_queue_response(struct source_reader *reader, struct media_stream *stream, HRESULT status,
DWORD stream_flags, LONGLONG timestamp, IMFSample *sample)
{
struct stream_response *response;
response = heap_alloc_zero(sizeof(*response));
response->status = status;
response->stream_index = stream->index;
response->stream_flags = stream_flags;
response->timestamp = timestamp;
response->sample = sample;
if (response->sample)
IMFSample_AddRef(response->sample);
if (response->sample && stream->allocator)
{
response->sa_pending = 1;
source_reader_set_sa_response(reader, response);
}
list_add_tail(&reader->responses, &response->entry);
stream->responses++;
source_reader_response_ready(reader, response);
}
static HRESULT source_reader_request_sample(struct source_reader *reader, struct media_stream *stream) static HRESULT source_reader_request_sample(struct source_reader *reader, struct media_stream *stream)
{ {
HRESULT hr = S_OK; HRESULT hr = S_OK;
...@@ -874,20 +935,26 @@ static struct stream_response * media_stream_detach_response(struct source_reade ...@@ -874,20 +935,26 @@ static struct stream_response * media_stream_detach_response(struct source_reade
static struct stream_response *media_stream_pop_response(struct source_reader *reader, struct media_stream *stream) static struct stream_response *media_stream_pop_response(struct source_reader *reader, struct media_stream *stream)
{ {
struct stream_response *response; struct stream_response *response;
struct list *head;
if (stream)
{
LIST_FOR_EACH_ENTRY(response, &reader->responses, struct stream_response, entry) LIST_FOR_EACH_ENTRY(response, &reader->responses, struct stream_response, entry)
{ {
if (response->stream_index == stream->index) if ((stream && response->stream_index != stream->index) || response->sa_pending)
continue;
return media_stream_detach_response(reader, response); return media_stream_detach_response(reader, response);
} }
}
else return NULL;
}
static struct stream_response *media_stream_pick_pending_response(struct source_reader *reader, unsigned int stream)
{
struct stream_response *response;
LIST_FOR_EACH_ENTRY(response, &reader->responses, struct stream_response, entry)
{ {
if ((head = list_head(&reader->responses))) if (response->stream_index == stream && response->sa_pending)
return media_stream_detach_response(reader, LIST_ENTRY(head, struct stream_response, entry)); return response;
} }
return NULL; return NULL;
...@@ -963,7 +1030,7 @@ static BOOL source_reader_got_response_for_stream(struct source_reader *reader, ...@@ -963,7 +1030,7 @@ static BOOL source_reader_got_response_for_stream(struct source_reader *reader,
LIST_FOR_EACH_ENTRY(response, &reader->responses, struct stream_response, entry) LIST_FOR_EACH_ENTRY(response, &reader->responses, struct stream_response, entry)
{ {
if (response->stream_index == stream->index) if (response->stream_index == stream->index && !response->sa_pending)
return TRUE; return TRUE;
} }
...@@ -1201,6 +1268,18 @@ static HRESULT WINAPI source_reader_async_commands_callback_Invoke(IMFAsyncCallb ...@@ -1201,6 +1268,18 @@ static HRESULT WINAPI source_reader_async_commands_callback_Invoke(IMFAsyncCallb
break; break;
case SOURCE_READER_ASYNC_SA_READY:
EnterCriticalSection(&reader->cs);
if ((response = media_stream_pick_pending_response(reader, command->u.sa.stream_index)))
{
source_reader_set_sa_response(reader, response);
source_reader_response_ready(reader, response);
}
LeaveCriticalSection(&reader->cs);
break;
case SOURCE_READER_ASYNC_SAMPLE_READY: case SOURCE_READER_ASYNC_SAMPLE_READY:
EnterCriticalSection(&reader->cs); EnterCriticalSection(&reader->cs);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment