mfreadwrite: Start media source when stream selection changes.
Signed-off-by: Nikolay Sivov <nsivov@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
742249e91e
commit
8f0570b3d7
|
@ -99,6 +99,8 @@ struct media_stream
|
||||||
CONDITION_VARIABLE sample_event;
|
CONDITION_VARIABLE sample_event;
|
||||||
struct list samples;
|
struct list samples;
|
||||||
enum media_stream_state state;
|
enum media_stream_state state;
|
||||||
|
BOOL selected;
|
||||||
|
BOOL presented;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct source_reader
|
struct source_reader
|
||||||
|
@ -820,6 +822,41 @@ static IMFSample *media_stream_pop_sample(struct media_stream *stream, DWORD *st
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static HRESULT source_reader_start_source(struct source_reader *reader)
|
||||||
|
{
|
||||||
|
BOOL selection_changed = FALSE;
|
||||||
|
PROPVARIANT position;
|
||||||
|
HRESULT hr = S_OK;
|
||||||
|
DWORD i;
|
||||||
|
|
||||||
|
if (reader->source_state == SOURCE_STATE_STARTED)
|
||||||
|
{
|
||||||
|
for (i = 0; i < reader->stream_count; ++i)
|
||||||
|
{
|
||||||
|
if (FAILED(hr = source_reader_get_stream_selection(reader, i, &reader->streams[i].selected)))
|
||||||
|
return hr;
|
||||||
|
selection_changed = reader->streams[i].selected ^ reader->streams[i].presented;
|
||||||
|
if (selection_changed)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
position.u.hVal.QuadPart = 0;
|
||||||
|
if (reader->source_state != SOURCE_STATE_STARTED || selection_changed)
|
||||||
|
{
|
||||||
|
position.vt = reader->source_state == SOURCE_STATE_STARTED ? VT_EMPTY : VT_I8;
|
||||||
|
|
||||||
|
/* Update cached stream selection if descriptor was accepted. */
|
||||||
|
if (SUCCEEDED(hr = IMFMediaSource_Start(reader->source, reader->descriptor, &GUID_NULL, &position)))
|
||||||
|
{
|
||||||
|
for (i = 0; i < reader->stream_count; ++i)
|
||||||
|
reader->streams[i].presented = reader->streams[i].selected;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
|
||||||
static HRESULT source_reader_read_sample(struct source_reader *reader, DWORD index, DWORD flags, DWORD *actual_index,
|
static HRESULT source_reader_read_sample(struct source_reader *reader, DWORD index, DWORD flags, DWORD *actual_index,
|
||||||
DWORD *stream_flags, LONGLONG *timestamp, IMFSample **sample)
|
DWORD *stream_flags, LONGLONG *timestamp, IMFSample **sample)
|
||||||
{
|
{
|
||||||
|
@ -867,20 +904,23 @@ static HRESULT source_reader_read_sample(struct source_reader *reader, DWORD ind
|
||||||
|
|
||||||
EnterCriticalSection(&stream->cs);
|
EnterCriticalSection(&stream->cs);
|
||||||
|
|
||||||
if (!(flags & MF_SOURCE_READER_CONTROLF_DRAIN))
|
if (SUCCEEDED(hr = source_reader_start_source(reader)))
|
||||||
{
|
{
|
||||||
while (list_empty(&stream->samples) && stream->state != STREAM_STATE_EOS)
|
if (!(flags & MF_SOURCE_READER_CONTROLF_DRAIN))
|
||||||
{
|
{
|
||||||
if (stream->stream)
|
while (list_empty(&stream->samples) && stream->state != STREAM_STATE_EOS)
|
||||||
{
|
{
|
||||||
if (FAILED(hr = IMFMediaStream_RequestSample(stream->stream, NULL)))
|
if (stream->stream)
|
||||||
WARN("Sample request failed, hr %#x.\n", hr);
|
{
|
||||||
|
if (FAILED(hr = IMFMediaStream_RequestSample(stream->stream, NULL)))
|
||||||
|
WARN("Sample request failed, hr %#x.\n", hr);
|
||||||
|
}
|
||||||
|
SleepConditionVariableCS(&stream->sample_event, &stream->cs, INFINITE);
|
||||||
}
|
}
|
||||||
SleepConditionVariableCS(&stream->sample_event, &stream->cs, INFINITE);
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
*sample = media_stream_pop_sample(stream, stream_flags);
|
*sample = media_stream_pop_sample(stream, stream_flags);
|
||||||
|
}
|
||||||
|
|
||||||
LeaveCriticalSection(&stream->cs);
|
LeaveCriticalSection(&stream->cs);
|
||||||
|
|
||||||
|
@ -913,9 +953,6 @@ static HRESULT WINAPI src_reader_ReadSample(IMFSourceReader *iface, DWORD index,
|
||||||
|
|
||||||
TRACE("%p, %#x, %#x, %p, %p, %p, %p\n", iface, index, flags, actual_index, stream_flags, timestamp, sample);
|
TRACE("%p, %#x, %#x, %p, %p, %p, %p\n", iface, index, flags, actual_index, stream_flags, timestamp, sample);
|
||||||
|
|
||||||
/* FIXME: probably should happen once */
|
|
||||||
IMFMediaSource_Start(reader->source, reader->descriptor, NULL, NULL);
|
|
||||||
|
|
||||||
if (reader->async_callback)
|
if (reader->async_callback)
|
||||||
{
|
{
|
||||||
if (actual_index || stream_flags || timestamp || sample)
|
if (actual_index || stream_flags || timestamp || sample)
|
||||||
|
|
|
@ -351,10 +351,11 @@ static HRESULT WINAPI test_source_Start(IMFMediaSource *iface, IMFPresentationDe
|
||||||
PROPVARIANT var;
|
PROPVARIANT var;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
todo_wine {
|
ok(time_format && IsEqualGUID(time_format, &GUID_NULL), "Unexpected time format %s.\n",
|
||||||
ok(time_format && IsEqualGUID(time_format, &GUID_NULL), "Unexpected time format %s.\n", wine_dbgstr_guid(time_format));
|
wine_dbgstr_guid(time_format));
|
||||||
ok(start_position && (start_position->vt == VT_I8 || start_position->vt == VT_EMPTY), "Unexpected position type.\n");
|
ok(start_position && (start_position->vt == VT_I8 || start_position->vt == VT_EMPTY),
|
||||||
}
|
"Unexpected position type.\n");
|
||||||
|
|
||||||
EnterCriticalSection(&source->cs);
|
EnterCriticalSection(&source->cs);
|
||||||
|
|
||||||
event_type = source->state == SOURCE_RUNNING ? MESourceSeeked : MESourceStarted;
|
event_type = source->state == SOURCE_RUNNING ? MESourceSeeked : MESourceStarted;
|
||||||
|
@ -823,16 +824,6 @@ static void test_source_reader_from_media_source(void)
|
||||||
source = create_test_source();
|
source = create_test_source();
|
||||||
ok(!!source, "Failed to create test source.\n");
|
ok(!!source, "Failed to create test source.\n");
|
||||||
|
|
||||||
callback = create_async_callback();
|
|
||||||
|
|
||||||
hr = MFCreateAttributes(&attributes, 1);
|
|
||||||
ok(hr == S_OK, "Failed to create attributes object, hr %#x.\n", hr);
|
|
||||||
|
|
||||||
hr = IMFAttributes_SetUnknown(attributes, &MF_SOURCE_READER_ASYNC_CALLBACK,
|
|
||||||
(IUnknown *)&callback->IMFSourceReaderCallback_iface);
|
|
||||||
ok(hr == S_OK, "Failed to set attribute value, hr %#x.\n", hr);
|
|
||||||
IMFSourceReaderCallback_Release(&callback->IMFSourceReaderCallback_iface);
|
|
||||||
|
|
||||||
hr = MFCreateSourceReaderFromMediaSource(source, NULL, &reader);
|
hr = MFCreateSourceReaderFromMediaSource(source, NULL, &reader);
|
||||||
ok(hr == S_OK, "Failed to create source reader, hr %#x.\n", hr);
|
ok(hr == S_OK, "Failed to create source reader, hr %#x.\n", hr);
|
||||||
|
|
||||||
|
@ -882,10 +873,41 @@ todo_wine
|
||||||
IMFSourceReader_Release(reader);
|
IMFSourceReader_Release(reader);
|
||||||
IMFMediaSource_Release(source);
|
IMFMediaSource_Release(source);
|
||||||
|
|
||||||
|
/* Request from stream 0. */
|
||||||
|
source = create_test_source();
|
||||||
|
ok(!!source, "Failed to create test source.\n");
|
||||||
|
|
||||||
|
hr = MFCreateSourceReaderFromMediaSource(source, NULL, &reader);
|
||||||
|
ok(hr == S_OK, "Failed to create source reader, hr %#x.\n", hr);
|
||||||
|
|
||||||
|
hr = IMFSourceReader_SetStreamSelection(reader, 0, TRUE);
|
||||||
|
ok(hr == S_OK, "Failed to select a stream, hr %#x.\n", hr);
|
||||||
|
|
||||||
|
hr = IMFSourceReader_ReadSample(reader, 0, 0, &actual_index, &stream_flags, ×tamp, &sample);
|
||||||
|
ok(hr == S_OK, "Failed to get a sample, hr %#x.\n", hr);
|
||||||
|
ok(actual_index == 0, "Unexpected stream index %u\n", actual_index);
|
||||||
|
ok(!stream_flags, "Unexpected stream flags %#x.\n", stream_flags);
|
||||||
|
ok(timestamp == 123, "Unexpected timestamp.\n");
|
||||||
|
ok(!!sample, "Expected sample object.\n");
|
||||||
|
IMFSample_Release(sample);
|
||||||
|
|
||||||
|
IMFSourceReader_Release(reader);
|
||||||
|
IMFMediaSource_Release(source);
|
||||||
|
|
||||||
/* Async mode. */
|
/* Async mode. */
|
||||||
source = create_test_source();
|
source = create_test_source();
|
||||||
ok(!!source, "Failed to create test source.\n");
|
ok(!!source, "Failed to create test source.\n");
|
||||||
|
|
||||||
|
callback = create_async_callback();
|
||||||
|
|
||||||
|
hr = MFCreateAttributes(&attributes, 1);
|
||||||
|
ok(hr == S_OK, "Failed to create attributes object, hr %#x.\n", hr);
|
||||||
|
|
||||||
|
hr = IMFAttributes_SetUnknown(attributes, &MF_SOURCE_READER_ASYNC_CALLBACK,
|
||||||
|
(IUnknown *)&callback->IMFSourceReaderCallback_iface);
|
||||||
|
ok(hr == S_OK, "Failed to set attribute value, hr %#x.\n", hr);
|
||||||
|
IMFSourceReaderCallback_Release(&callback->IMFSourceReaderCallback_iface);
|
||||||
|
|
||||||
hr = MFCreateSourceReaderFromMediaSource(source, attributes, &reader);
|
hr = MFCreateSourceReaderFromMediaSource(source, attributes, &reader);
|
||||||
ok(hr == S_OK, "Failed to create source reader, hr %#x.\n", hr);
|
ok(hr == S_OK, "Failed to create source reader, hr %#x.\n", hr);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue