From: Brendan McGrath bmcgrath@codeweavers.com
--- dlls/mf/samplegrabber.c | 93 ++++++++++++----------------------------- dlls/mf/tests/mf.c | 64 ++++++---------------------- 2 files changed, 39 insertions(+), 118 deletions(-)
diff --git a/dlls/mf/samplegrabber.c b/dlls/mf/samplegrabber.c index a8c797f25ed..fe884cadff3 100644 --- a/dlls/mf/samplegrabber.c +++ b/dlls/mf/samplegrabber.c @@ -89,8 +89,7 @@ struct sample_grabber float rate; enum sink_state state; CRITICAL_SECTION cs; - UINT32 sample_count; - IMFSample *samples[MAX_SAMPLE_QUEUE_LENGTH]; + byte samples_queued; };
static IMFSampleGrabberSinkCallback *sample_grabber_get_callback(const struct sample_grabber *sink) @@ -187,13 +186,14 @@ static ULONG WINAPI sample_grabber_stream_AddRef(IMFStreamSink *iface) return IMFMediaSink_AddRef(&grabber->IMFMediaSink_iface); }
-static void stream_release_pending_item(struct scheduled_item *item) +static void stream_release_pending_item(struct sample_grabber *grabber, struct scheduled_item *item) { list_remove(&item->entry); switch (item->type) { case ITEM_TYPE_SAMPLE: IMFSample_Release(item->u.sample); + grabber->samples_queued--; break; case ITEM_TYPE_MARKER: PropVariantClear(&item->u.marker.context); @@ -398,13 +398,13 @@ static HRESULT stream_queue_sample(struct sample_grabber *grabber, IMFSample *sa item->u.sample = sample; IMFSample_AddRef(item->u.sample); list_init(&item->entry); - if (list_empty(&grabber->items)) + if (!grabber->samples_queued++) hr = stream_schedule_sample(grabber, item);
if (SUCCEEDED(hr)) list_add_tail(&grabber->items, &item->entry); else - stream_release_pending_item(item); + stream_release_pending_item(grabber, item);
return hr; } @@ -430,7 +430,7 @@ static HRESULT WINAPI sample_grabber_stream_ProcessSample(IMFStreamSink *iface,
if (grabber->is_shut_down) hr = MF_E_STREAMSINK_REMOVED; - else if (grabber->state == SINK_STATE_RUNNING || (grabber->state == SINK_STATE_PAUSED && grabber->ignore_clock)) + else if (grabber->state != SINK_STATE_STOPPED) { hr = IMFSample_GetSampleTime(sample, &sampletime);
@@ -448,14 +448,6 @@ static HRESULT WINAPI sample_grabber_stream_ProcessSample(IMFStreamSink *iface, hr = stream_queue_sample(grabber, sample); } } - else if (grabber->state == SINK_STATE_PAUSED) - { - if (grabber->sample_count < MAX_SAMPLE_QUEUE_LENGTH) - { - IMFSample_AddRef(sample); - grabber->samples[grabber->sample_count++] = sample; - } - }
LeaveCriticalSection(&grabber->cs);
@@ -492,7 +484,7 @@ static HRESULT stream_place_marker(struct sample_grabber *grabber, MFSTREAMSINK_ if (SUCCEEDED(hr)) list_add_tail(&grabber->items, &item->entry); else - stream_release_pending_item(item); + stream_release_pending_item(grabber, item);
return hr; } @@ -520,7 +512,6 @@ static HRESULT WINAPI sample_grabber_stream_PlaceMarker(IMFStreamSink *iface, MF static HRESULT WINAPI sample_grabber_stream_Flush(IMFStreamSink *iface) { struct sample_grabber *grabber = impl_from_IMFStreamSink(iface); - struct scheduled_item *item, *next_item; HRESULT hr = S_OK;
TRACE("%p.\n", iface); @@ -529,17 +520,6 @@ static HRESULT WINAPI sample_grabber_stream_Flush(IMFStreamSink *iface)
if (grabber->is_shut_down) hr = MF_E_STREAMSINK_REMOVED; - else - { - LIST_FOR_EACH_ENTRY_SAFE(item, next_item, &grabber->items, struct scheduled_item, entry) - { - /* Samples are discarded, markers are processed immediately. */ - if (item->type == ITEM_TYPE_MARKER) - sample_grabber_stream_report_marker(grabber, &item->u.marker.context, E_ABORT); - - stream_release_pending_item(item); - } - }
LeaveCriticalSection(&grabber->cs);
@@ -761,7 +741,7 @@ static HRESULT WINAPI sample_grabber_stream_timer_callback_Invoke(IMFAsyncCallba if (item->type == ITEM_TYPE_MARKER) { sample_grabber_stream_report_marker(grabber, &item->u.marker.context, S_OK); - stream_release_pending_item(item); + stream_release_pending_item(grabber, item); } else if (item->type == ITEM_TYPE_SAMPLE) { @@ -769,8 +749,10 @@ static HRESULT WINAPI sample_grabber_stream_timer_callback_Invoke(IMFAsyncCallba { if (FAILED(hr = sample_grabber_report_sample(grabber, item->u.sample, &sample_delivered))) WARN("Failed to report a sample, hr %#lx.\n", hr); - stream_release_pending_item(item); + stream_release_pending_item(grabber, item); sample_reported = TRUE; + if (sample_delivered) + sample_grabber_stream_request_sample(grabber); } else { @@ -780,8 +762,6 @@ static HRESULT WINAPI sample_grabber_stream_timer_callback_Invoke(IMFAsyncCallba } } } - if (sample_delivered) - sample_grabber_stream_request_sample(grabber);
LeaveCriticalSection(&grabber->cs);
@@ -852,21 +832,7 @@ static void sample_grabber_release_pending_items(struct sample_grabber *grabber)
LIST_FOR_EACH_ENTRY_SAFE(item, next_item, &grabber->items, struct scheduled_item, entry) { - stream_release_pending_item(item); - } -} - -static void release_samples(struct sample_grabber *grabber) -{ - unsigned int i; - - for (i = 0; i < MAX_SAMPLE_QUEUE_LENGTH; ++i) - { - if (grabber->samples[i]) - { - IMFSample_Release(grabber->samples[i]); - grabber->samples[i] = NULL; - } + stream_release_pending_item(grabber, item); } }
@@ -902,7 +868,6 @@ static ULONG WINAPI sample_grabber_sink_Release(IMFMediaSink *iface) if (grabber->sample_attributes) IMFAttributes_Release(grabber->sample_attributes); sample_grabber_release_pending_items(grabber); - release_samples(grabber); DeleteCriticalSection(&grabber->cs); free(grabber); } @@ -1175,6 +1140,7 @@ static HRESULT sample_grabber_set_state(struct sample_grabber *grabber, enum sin [SINK_STATE_RUNNING] = MEStreamSinkStarted, }; BOOL do_callback = FALSE; + byte required_requests; HRESULT hr = S_OK; unsigned int i;
@@ -1189,27 +1155,21 @@ static HRESULT sample_grabber_set_state(struct sample_grabber *grabber, enum sin if (state == SINK_STATE_STOPPED) { sample_grabber_cancel_timer(grabber); - release_samples(grabber); - grabber->sample_count = MAX_SAMPLE_QUEUE_LENGTH; + sample_grabber_release_pending_items(grabber); } - - if (state == SINK_STATE_RUNNING && grabber->state != SINK_STATE_RUNNING) + else if (state == SINK_STATE_RUNNING && + (grabber->state != SINK_STATE_RUNNING || offset != PRESENTATION_CURRENT_POSITION)) { - /* Every transition to running state sends a bunch requests to build up initial queue. */ - for (i = 0; i < grabber->sample_count; ++i) - { - if (grabber->state == SINK_STATE_PAUSED && offset == PRESENTATION_CURRENT_POSITION) - { - assert(grabber->samples[i]); - stream_queue_sample(grabber, grabber->samples[i]); - } - else - { - sample_grabber_stream_request_sample(grabber); - } - } - release_samples(grabber); - grabber->sample_count = 0; + required_requests = (grabber->state == SINK_STATE_STOPPED) ? + MAX_SAMPLE_QUEUE_LENGTH : min(grabber->samples_queued, MAX_SAMPLE_QUEUE_LENGTH); + + if (offset != PRESENTATION_CURRENT_POSITION) + sample_grabber_cancel_timer(grabber); + + sample_grabber_release_pending_items(grabber); + + for (i = 0; i < required_requests; i++) + sample_grabber_stream_request_sample(grabber); }
do_callback = state != grabber->state || state != SINK_STATE_PAUSED; @@ -1517,7 +1477,6 @@ static HRESULT sample_grabber_create_object(IMFAttributes *attributes, void *use object->IMFStreamSink_iface.lpVtbl = &sample_grabber_stream_vtbl; object->IMFMediaTypeHandler_iface.lpVtbl = &sample_grabber_stream_type_handler_vtbl; object->timer_callback.lpVtbl = &sample_grabber_stream_timer_callback_vtbl; - object->sample_count = MAX_SAMPLE_QUEUE_LENGTH; object->refcount = 1; object->rate = 1.0f; if (FAILED(IMFSampleGrabberSinkCallback_QueryInterface(context->callback, &IID_IMFSampleGrabberSinkCallback2, diff --git a/dlls/mf/tests/mf.c b/dlls/mf/tests/mf.c index 5cbb7ddf485..79acccd7cd9 100644 --- a/dlls/mf/tests/mf.c +++ b/dlls/mf/tests/mf.c @@ -4312,15 +4312,11 @@ static HRESULT WINAPI timer_SetTimer(IMFTimer *iface, DWORD flags, LONGLONG time struct timer_cancel *tc; HRESULT hr;
- todo_wine_if(time == 83334) CHECK_EXPECT(timer_SetTimer);
ok(flags == 0, "Unexpected flags value %#lx\n", flags); - todo_wine_if(time == 83334) ok(time == expected_pts, "Unexpected time value %I64d\n", time); - todo_wine_if(time == 83334) ok(pc->callback_result == NULL, "Unexpected callback result value %p\n", pc->callback_result); - todo_wine_if(time == 83334) ok(pc->cancel_key == NULL, "Unexpected cancel key %p\n", pc->cancel_key);
hr = MFCreateAsyncResult(NULL, callback, state, &pc->callback_result); @@ -4336,7 +4332,6 @@ static HRESULT WINAPI timer_CancelTimer(IMFTimer *iface, IUnknown *cancel_key) { struct presentation_clock* pc = impl_from_IMFTimer(iface);
- todo_wine CHECK_EXPECT(timer_CancelTimer); ok(cancel_key == pc->cancel_key, "Unexpected cancel key %p\n", cancel_key);
@@ -4559,8 +4554,6 @@ static void supply_samples(IMFStreamSink *stream, int num_samples) } }
-static BOOL ignore_clock = FALSE; - #define count_samples_requested(stream) _count_samples_requested(__LINE__, stream) static int _count_samples_requested(int line, IMFStreamSink *stream) { @@ -4585,7 +4578,6 @@ static int _count_samples_requested(int line, IMFStreamSink *stream) } else if (met == MEStreamSinkMarker) { - todo_wine_if(!ignore_clock) CHECK_EXPECT(MEStreamSinkMarker); break; } @@ -4737,18 +4729,15 @@ static void test_sample_grabber_seek(void) SET_EXPECT(timer_CancelTimer); hr = IMFClockStateSink_OnClockStart(clock_sink, 0, 1234); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); - todo_wine CHECK_CALLED(timer_CancelTimer);
samples_requested = count_samples_requested(stream); - todo_wine ok(samples_requested == 4, "Unexpected number of samples requested %d\n", samples_requested);
/* test number of new sample requests on seek when in running state and 3 samples have been provided */ sample_pts = 0; SET_EXPECT(timer_SetTimer); supply_samples(stream, 2); - todo_wine CHECK_CALLED(timer_SetTimer); /* this marker gets silently discarded on the next seek */ hr = IMFStreamSink_PlaceMarker(stream, MFSTREAMSINK_MARKER_DEFAULT, NULL, NULL); @@ -4772,18 +4761,15 @@ static void test_sample_grabber_seek(void) SET_EXPECT(timer_CancelTimer); hr = IMFClockStateSink_OnClockStart(clock_sink, 0, 1234); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); - todo_wine CHECK_CALLED(timer_CancelTimer);
samples_requested = count_samples_requested(stream); - todo_wine ok(samples_requested == 2, "Unexpected number of samples requested %d\n", samples_requested);
/* test number of new sample requests after a flush then seek */ sample_pts = expected_pts = 0; SET_EXPECT(timer_SetTimer); supply_samples(stream, 2); - todo_wine CHECK_CALLED(timer_SetTimer);
/* there is no cancel timer, or sample requests during a flush */ @@ -4796,11 +4782,9 @@ static void test_sample_grabber_seek(void) SET_EXPECT(timer_CancelTimer); hr = IMFClockStateSink_OnClockStart(clock_sink, 0, 1234); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); - todo_wine CHECK_CALLED(timer_CancelTimer);
samples_requested = count_samples_requested(stream); - todo_wine ok(samples_requested == 3, "Unexpected number of samples requested %d\n", samples_requested);
/* test number of new sample requests on seek whilst stopped */ @@ -4811,7 +4795,6 @@ static void test_sample_grabber_seek(void) ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
samples_requested = count_samples_requested(stream); - todo_wine ok(samples_requested == 4, "Unexpected number of samples requested %d\n", samples_requested);
/* test number of new sample requests on seek whilst paused and 3 samples provided */ @@ -4823,31 +4806,21 @@ static void test_sample_grabber_seek(void) ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); supply_samples(stream, 2);
- todo_wine hr = trigger_timer(mock_clock); - todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
hr = WaitForSingleObject(grabber_callback_impl->ready_event, 1000); - todo_wine ok(hr == WAIT_OBJECT_0, "Unexpected hr %#lx.\n", hr);
- if (hr == WAIT_OBJECT_0) - { - expected_pts = 41667; - SET_EXPECT(timer_SetTimer); - SetEvent(grabber_callback_impl->done_event); + expected_pts = 41667; + SET_EXPECT(timer_SetTimer); + SetEvent(grabber_callback_impl->done_event);
- SET_EXPECT(MEStreamSinkMarker); - samples_requested = count_samples_requested(stream); - ok(samples_requested == 1, "Unexpected number of samples requested %d\n", samples_requested); - CHECK_CALLED(MEStreamSinkMarker); - CHECK_CALLED(timer_SetTimer); - } - else - { - skip("skipping MEStreamSinkMarker test\n"); - } + SET_EXPECT(MEStreamSinkMarker); + samples_requested = count_samples_requested(stream); + ok(samples_requested == 1, "Unexpected number of samples requested %d\n", samples_requested); + CHECK_CALLED(MEStreamSinkMarker); + CHECK_CALLED(timer_SetTimer);
hr = IMFClockStateSink_OnClockPause(clock_sink, 0); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); @@ -4871,7 +4844,6 @@ static void test_sample_grabber_seek(void) ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
samples_requested = count_samples_requested(stream); - todo_wine ok(samples_requested == 0, "Unexpected number of samples requested %d\n", samples_requested);
/* test sample received in the paused state with no samples queued */ @@ -4881,21 +4853,18 @@ static void test_sample_grabber_seek(void) expected_pts = sample_pts; SET_EXPECT(timer_SetTimer); supply_samples(stream, 4); - todo_wine CHECK_CALLED(timer_SetTimer);
hr = IMFClockStateSink_OnClockStart(clock_sink, 0, PRESENTATION_CURRENT_POSITION); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
samples_requested = count_samples_requested(stream); - todo_wine ok(samples_requested == 4, "Unexpected number of samples requested %d\n", samples_requested);
/* test sample received in the stopped state */ SET_EXPECT(timer_CancelTimer); hr = IMFClockStateSink_OnClockStop(clock_sink, 0); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); - todo_wine CHECK_CALLED(timer_CancelTimer);
supply_samples(stream, 4); @@ -4904,30 +4873,24 @@ static void test_sample_grabber_seek(void) ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
samples_requested = count_samples_requested(stream); - todo_wine ok(samples_requested == 4, "Unexpected number of samples requested %d\n", samples_requested);
/* check contents of collection */ hr = IMFCollection_GetElementCount(grabber_callback_impl->samples, &count); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); - todo_wine ok(count == ARRAY_SIZE(use_clock_samples), "Unexpected total of samples delivered %ld\n", count);
for (i = 0; i < ARRAY_SIZE(use_clock_samples); i++) { hr = IMFCollection_GetElement(grabber_callback_impl->samples, i, (IUnknown**)&sample); - todo_wine_if(i) ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
- if (hr == S_OK) - { - hr = IMFSample_GetSampleTime(sample, &pts); - ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); - ok(pts == use_clock_samples[i], "%d: Unexpected pts %I64d, expected %I64d\n", i, pts, use_clock_samples[i]); + hr = IMFSample_GetSampleTime(sample, &pts); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(pts == use_clock_samples[i], "%d: Unexpected pts %I64d, expected %I64d\n", i, pts, use_clock_samples[i]);
- ref = IMFSample_Release(sample); - ok(ref == 1, "Release returned %ld\n", ref); - } + ref = IMFSample_Release(sample); + ok(ref == 1, "Release returned %ld\n", ref); }
/* required for the sink to be fully released */ @@ -4943,7 +4906,6 @@ static void test_sample_grabber_seek(void)
/* test with MF_SAMPLEGRABBERSINK_IGNORE_CLOCK */
- ignore_clock = TRUE; grabber_callback = create_test_grabber_callback(); grabber_callback_impl = impl_from_IMFSampleGrabberSinkCallback(grabber_callback); grabber_callback_impl->do_event = FALSE;