On 4/18/20 9:34 AM, Anton Baskanov wrote:
Signed-off-by: Anton Baskanov baskanov@gmail.com
dlls/amstream/audiostream.c | 66 ++++++++++++++++++++++- dlls/amstream/tests/amstream.c | 99 ++++++++++++++++++++++++++++++++-- 2 files changed, 159 insertions(+), 6 deletions(-)
diff --git a/dlls/amstream/audiostream.c b/dlls/amstream/audiostream.c index 26d615ebf4..81cd2975c8 100644 --- a/dlls/amstream/audiostream.c +++ b/dlls/amstream/audiostream.c @@ -166,6 +166,17 @@ static HRESULT audiostreamsample_create(IAudioMediaStream *parent, IAudioData *a return S_OK; }
+enum queued_event_type +{
- QET_END_OF_STREAM
+};
+struct queued_event +{
- struct list entry;
- enum queued_event_type type;
+};
struct audio_stream { IAMMediaStream IAMMediaStream_iface; @@ -185,8 +196,27 @@ struct audio_stream AM_MEDIA_TYPE mt; WAVEFORMATEX format; FILTER_STATE state;
- BOOL eos;
- struct list event_queue;
};
+static void remove_queued_event(struct queued_event *event) +{
- list_remove(&event->entry);
- HeapFree(GetProcessHeap(), 0, event);
+}
+static void flush_event_queue(struct audio_stream *stream) +{
- while (!list_empty(&stream->event_queue))
- {
struct queued_event *event =
LIST_ENTRY(list_head(&stream->event_queue), struct queued_event, entry);
remove_queued_event(event);
- }
+}
static inline struct audio_stream *impl_from_IAMMediaStream(IAMMediaStream *iface) { return CONTAINING_RECORD(iface, struct audio_stream, IAMMediaStream_iface); @@ -347,6 +377,11 @@ static HRESULT WINAPI audio_IAMMediaStream_SetState(IAMMediaStream *iface, FILTE
EnterCriticalSection(&This->cs);
- if (State_Stopped == state)
flush_event_queue(This);
- if (State_Stopped == This->state)
This->eos = FALSE;
This works, but it feels a little clearer to me to have
if (state == State_Stopped) { flush_event_queue(This); This->eos = FALSE; }
This->state = state; LeaveCriticalSection(&This->cs);
@@ -919,8 +954,34 @@ static HRESULT WINAPI audio_sink_QueryInternalConnections(IPin *iface, IPin **pi
static HRESULT WINAPI audio_sink_EndOfStream(IPin *iface) {
- FIXME("iface %p, stub!\n", iface);
- return E_NOTIMPL;
- struct audio_stream *stream = impl_from_IPin(iface);
- struct queued_event *event;
- TRACE("(%p/%p)->()\n", iface, stream);
- EnterCriticalSection(&stream->cs);
- if (stream->eos)
- {
LeaveCriticalSection(&stream->cs);
return E_FAIL;
- }
- event = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*event));
amstream is compiled with msvcrt, so this can be calloc().
- if (!event)
- {
LeaveCriticalSection(&stream->cs);
return E_OUTOFMEMORY;
- }
- event->type = QET_END_OF_STREAM;
- list_add_tail(&stream->event_queue, &event->entry);
- stream->eos = TRUE;
- LeaveCriticalSection(&stream->cs);
- return S_OK;
}
static HRESULT WINAPI audio_sink_BeginFlush(IPin *iface) @@ -1083,6 +1144,7 @@ HRESULT audio_stream_create(IMultiMediaStream *parent, const MSPID *purpose_id, object->parent = parent; object->purpose_id = *purpose_id; object->stream_type = stream_type;
list_init(&object->event_queue);
*media_stream = &object->IAMMediaStream_iface;
diff --git a/dlls/amstream/tests/amstream.c b/dlls/amstream/tests/amstream.c index 472c6558fc..2ac492bc3c 100644 --- a/dlls/amstream/tests/amstream.c +++ b/dlls/amstream/tests/amstream.c @@ -2381,10 +2381,21 @@ static HRESULT testsource_query_accept(struct strmbase_pin *iface, const AM_MEDI return S_OK; }
-static HRESULT WINAPI testsource_DecideAllocator(struct strmbase_source *iface,
IMemInputPin *peer, IMemAllocator **allocator)
+static HRESULT WINAPI testsource_decide_buffer_size(struct strmbase_source *iface,
IMemAllocator *alloc, ALLOCATOR_PROPERTIES *requested)
{
- return S_OK;
- ALLOCATOR_PROPERTIES actual;
- if (!requested->cbAlign)
requested->cbAlign = 1;
- if (requested->cbBuffer < 4096)
requested->cbBuffer = 4096;
- if (!requested->cBuffers)
requested->cBuffers = 2;
- return IMemAllocator_SetProperties(alloc, requested, &actual);
}
static const struct strmbase_source_ops testsource_ops = @@ -2392,7 +2403,8 @@ static const struct strmbase_source_ops testsource_ops = .base.pin_query_accept = testsource_query_accept, .base.pin_get_media_type = strmbase_pin_get_media_type, .pfnAttemptConnection = BaseOutputPinImpl_AttemptConnection,
- .pfnDecideAllocator = testsource_DecideAllocator,
- .pfnDecideBufferSize = testsource_decide_buffer_size,
- .pfnDecideAllocator = BaseOutputPinImpl_DecideAllocator,
};
static void testfilter_init(struct testfilter *filter) @@ -2814,6 +2826,84 @@ static void test_audiostream_set_state(void) ok(!ref, "Got outstanding refcount %d.\n", ref); }
+void test_audiostream_end_of_stream(void) +{
- static const WAVEFORMATEX format =
- {
.wFormatTag = WAVE_FORMAT_PCM,
.nChannels = 1,
.nSamplesPerSec = 11025,
.wBitsPerSample = 16,
.nBlockAlign = 2,
.nAvgBytesPerSec = 2 * 11025,
- };
- const AM_MEDIA_TYPE mt =
- {
.majortype = MEDIATYPE_Audio,
.subtype = MEDIASUBTYPE_PCM,
.formattype = FORMAT_WaveFormatEx,
.cbFormat = sizeof(WAVEFORMATEX),
.pbFormat = (BYTE *)&format,
- };
- IAMMultiMediaStream *mmstream = create_ammultimediastream();
- struct testfilter source;
- IGraphBuilder *graph;
- IMediaStream *stream;
- HRESULT hr;
- ULONG ref;
- IPin *pin;
- hr = IAMMultiMediaStream_Initialize(mmstream, STREAMTYPE_READ, 0, NULL);
- ok(hr == S_OK, "Got hr %#x.\n", hr);
- hr = IAMMultiMediaStream_AddMediaStream(mmstream, NULL, &MSPID_PrimaryAudio, 0, &stream);
- ok(hr == S_OK, "Got hr %#x.\n", hr);
- hr = IMediaStream_QueryInterface(stream, &IID_IPin, (void **)&pin);
- ok(hr == S_OK, "Got hr %#x.\n", hr);
- hr = IAMMultiMediaStream_GetFilterGraph(mmstream, &graph);
- ok(hr == S_OK, "Got hr %#x.\n", hr);
- ok(graph != NULL, "Expected non-null graph\n");
- testfilter_init(&source);
- hr = IGraphBuilder_AddFilter(graph, &source.filter.IBaseFilter_iface, NULL);
- ok(hr == S_OK, "Got hr %#x.\n", hr);
- hr = IGraphBuilder_ConnectDirect(graph, &source.source.pin.IPin_iface, pin, &mt);
- ok(hr == S_OK, "Got hr %#x.\n", hr);
- hr = IPin_EndOfStream(pin);
- ok(hr == S_OK, "Got hr %#x.\n", hr);
- hr = IPin_EndOfStream(pin);
- ok(hr == E_FAIL, "Got hr %#x.\n", hr);
- hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_RUN);
- ok(hr == S_OK, "Got hr %#x.\n", hr);
- hr = IPin_EndOfStream(pin);
- ok(hr == S_OK, "Got hr %#x.\n", hr);
- hr = IPin_EndOfStream(pin);
- ok(hr == E_FAIL, "Got hr %#x.\n", hr);
- hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_STOP);
- ok(hr == S_OK, "Got hr %#x.\n", hr);
- hr = IPin_EndOfStream(pin);
- ok(hr == E_FAIL, "Got hr %#x.\n", hr);
- IGraphBuilder_Disconnect(graph, pin);
- IGraphBuilder_Disconnect(graph, &source.source.pin.IPin_iface);
- ref = IAMMultiMediaStream_Release(mmstream);
- ok(!ref, "Got outstanding refcount %d.\n", ref);
- ref = IGraphBuilder_Release(graph);
- ok(!ref, "Got outstanding refcount %d.\n", ref);
- IPin_Release(pin);
- ref = IMediaStream_Release(stream);
- ok(!ref, "Got outstanding refcount %d.\n", ref);
+}
void test_mediastreamfilter_get_state(void) { IAMMultiMediaStream *mmstream = create_ammultimediastream(); @@ -2986,6 +3076,7 @@ START_TEST(amstream) test_audiostream_set_format(); test_audiostream_receive_connection(); test_audiostream_set_state();
test_audiostream_end_of_stream();
test_mediastreamfilter_get_state(); test_mediastreamfilter_stop_pause_run();