amstream: Reconnect if the new format is incompatible with the connection media type in AMDirectDrawStream::SetFormat.
Signed-off-by: Anton Baskanov <baskanov@gmail.com> Signed-off-by: Zebediah Figura <z.figura12@gmail.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
337fcca4d1
commit
47ab124022
|
@ -51,6 +51,7 @@ struct ddraw_stream
|
|||
IDirectDraw *ddraw;
|
||||
CRITICAL_SECTION cs;
|
||||
IMediaStreamFilter *filter;
|
||||
IFilterGraph *graph;
|
||||
|
||||
IPin *peer;
|
||||
IMemAllocator *allocator;
|
||||
|
@ -294,6 +295,8 @@ static HRESULT WINAPI ddraw_IAMMediaStream_JoinFilterGraph(IAMMediaStream *iface
|
|||
|
||||
TRACE("stream %p, filtergraph %p.\n", stream, filtergraph);
|
||||
|
||||
stream->graph = filtergraph;
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
@ -438,6 +441,10 @@ static HRESULT WINAPI ddraw_IDirectDrawMediaStream_SetFormat(IDirectDrawMediaStr
|
|||
const DDSURFACEDESC *format, IDirectDrawPalette *palette)
|
||||
{
|
||||
struct ddraw_stream *stream = impl_from_IDirectDrawMediaStream(iface);
|
||||
AM_MEDIA_TYPE old_media_type;
|
||||
struct format old_format;
|
||||
IPin *old_peer;
|
||||
HRESULT hr;
|
||||
|
||||
TRACE("stream %p, format %p, palette %p.\n", stream, format, palette);
|
||||
|
||||
|
@ -503,6 +510,7 @@ static HRESULT WINAPI ddraw_IDirectDrawMediaStream_SetFormat(IDirectDrawMediaStr
|
|||
|
||||
EnterCriticalSection(&stream->cs);
|
||||
|
||||
old_format = stream->format;
|
||||
stream->format.flags = format->dwFlags & (DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT);
|
||||
if (format->dwFlags & (DDSD_WIDTH | DDSD_HEIGHT))
|
||||
{
|
||||
|
@ -512,6 +520,35 @@ static HRESULT WINAPI ddraw_IDirectDrawMediaStream_SetFormat(IDirectDrawMediaStr
|
|||
if (format->dwFlags & DDSD_PIXELFORMAT)
|
||||
stream->format.pf = format->ddpfPixelFormat;
|
||||
|
||||
if (stream->peer && !is_format_compatible(stream, old_format.width, old_format.height, &old_format.pf))
|
||||
{
|
||||
hr = CopyMediaType(&old_media_type, &stream->mt);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
stream->format = old_format;
|
||||
LeaveCriticalSection(&stream->cs);
|
||||
return hr;
|
||||
}
|
||||
old_peer = stream->peer;
|
||||
IPin_AddRef(old_peer);
|
||||
|
||||
IFilterGraph_Disconnect(stream->graph, stream->peer);
|
||||
IFilterGraph_Disconnect(stream->graph, &stream->IPin_iface);
|
||||
hr = IFilterGraph_ConnectDirect(stream->graph, old_peer, &stream->IPin_iface, NULL);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
stream->format = old_format;
|
||||
IFilterGraph_ConnectDirect(stream->graph, old_peer, &stream->IPin_iface, &old_media_type);
|
||||
IPin_Release(old_peer);
|
||||
FreeMediaType(&old_media_type);
|
||||
LeaveCriticalSection(&stream->cs);
|
||||
return DDERR_INVALIDSURFACETYPE;
|
||||
}
|
||||
|
||||
IPin_Release(old_peer);
|
||||
FreeMediaType(&old_media_type);
|
||||
}
|
||||
|
||||
LeaveCriticalSection(&stream->cs);
|
||||
|
||||
return S_OK;
|
||||
|
|
|
@ -923,6 +923,7 @@ struct testfilter
|
|||
IMediaSeeking IMediaSeeking_iface;
|
||||
LONGLONG current_position;
|
||||
LONGLONG stop_position;
|
||||
const AM_MEDIA_TYPE *preferred_mt;
|
||||
HRESULT get_duration_hr;
|
||||
HRESULT get_stop_position_hr;
|
||||
HRESULT set_positions_hr;
|
||||
|
@ -983,6 +984,16 @@ static inline struct testfilter *impl_from_base_pin(struct strmbase_pin *iface)
|
|||
return CONTAINING_RECORD(iface, struct testfilter, source.pin);
|
||||
}
|
||||
|
||||
static HRESULT testsource_get_media_type(struct strmbase_pin *iface, unsigned int index, AM_MEDIA_TYPE *mt)
|
||||
{
|
||||
struct testfilter *filter = impl_from_base_pin(iface);
|
||||
|
||||
if (index < 1 && filter->preferred_mt)
|
||||
return CopyMediaType(mt, filter->preferred_mt);
|
||||
|
||||
return VFW_S_NO_MORE_ITEMS;
|
||||
}
|
||||
|
||||
static HRESULT testsource_query_interface(struct strmbase_pin *iface, REFIID iid, void **out)
|
||||
{
|
||||
struct testfilter *filter = impl_from_base_pin(iface);
|
||||
|
@ -997,6 +1008,25 @@ static HRESULT testsource_query_interface(struct strmbase_pin *iface, REFIID iid
|
|||
return S_OK;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI testsource_DecideAllocator(struct strmbase_source *iface, IMemInputPin *pin, IMemAllocator **alloc)
|
||||
{
|
||||
ALLOCATOR_PROPERTIES props = {0};
|
||||
HRESULT hr;
|
||||
|
||||
/* AMDirectDrawStream tries to use it's custom allocator and
|
||||
* when it is able to do so it's behavior changes slightly
|
||||
* (e.g. it uses dynamic format change instead of reconnecting in SetFormat).
|
||||
* We don't yet implement the custom allocator so force the standard one for now. */
|
||||
hr = BaseOutputPinImpl_InitAllocator(iface, alloc);
|
||||
ok(hr == S_OK, "Got hr %#x.\n", hr);
|
||||
|
||||
IMemInputPin_GetAllocatorRequirements(pin, &props);
|
||||
hr = iface->pFuncsTable->pfnDecideBufferSize(iface, *alloc, &props);
|
||||
ok(hr == S_OK, "Got hr %#x.\n", hr);
|
||||
|
||||
return IMemInputPin_NotifyAllocator(pin, *alloc, FALSE);
|
||||
}
|
||||
|
||||
static HRESULT WINAPI testsource_DecideBufferSize(struct strmbase_source *iface,
|
||||
IMemAllocator *alloc, ALLOCATOR_PROPERTIES *requested)
|
||||
{
|
||||
|
@ -1016,10 +1046,11 @@ static HRESULT WINAPI testsource_DecideBufferSize(struct strmbase_source *iface,
|
|||
|
||||
static const struct strmbase_source_ops testsource_ops =
|
||||
{
|
||||
.base.pin_get_media_type = testsource_get_media_type,
|
||||
.base.pin_query_interface = testsource_query_interface,
|
||||
.pfnAttemptConnection = BaseOutputPinImpl_AttemptConnection,
|
||||
.pfnDecideBufferSize = testsource_DecideBufferSize,
|
||||
.pfnDecideAllocator = BaseOutputPinImpl_DecideAllocator,
|
||||
.pfnDecideAllocator = testsource_DecideAllocator,
|
||||
};
|
||||
|
||||
static void testfilter_init(struct testfilter *filter)
|
||||
|
@ -4942,10 +4973,17 @@ static void test_ddrawstream_set_format(void)
|
|||
|
||||
IDirectDrawMediaStream *ddraw_stream;
|
||||
IAMMultiMediaStream *mmstream;
|
||||
DDSURFACEDESC current_format;
|
||||
DDSURFACEDESC desired_format;
|
||||
struct testfilter source;
|
||||
IGraphBuilder *graph;
|
||||
DDSURFACEDESC format;
|
||||
IMediaStream *stream;
|
||||
VIDEOINFO video_info;
|
||||
AM_MEDIA_TYPE mt;
|
||||
HRESULT hr;
|
||||
ULONG ref;
|
||||
IPin *pin;
|
||||
|
||||
mmstream = create_ammultimediastream();
|
||||
|
||||
|
@ -5039,6 +5077,96 @@ static void test_ddrawstream_set_format(void)
|
|||
ref = IMediaStream_Release(stream);
|
||||
ok(!ref, "Got outstanding refcount %d.\n", ref);
|
||||
|
||||
mmstream = create_ammultimediastream();
|
||||
|
||||
hr = IAMMultiMediaStream_AddMediaStream(mmstream, NULL, &MSPID_PrimaryVideo, 0, &stream);
|
||||
ok(hr == S_OK, "Got hr %#x.\n", hr);
|
||||
hr = IMediaStream_QueryInterface(stream, &IID_IDirectDrawMediaStream, (void **)&ddraw_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, "Expected non-NULL graph.\n");
|
||||
|
||||
testfilter_init(&source);
|
||||
|
||||
hr = IGraphBuilder_AddFilter(graph, &source.filter.IBaseFilter_iface, L"source");
|
||||
ok(hr == S_OK, "Got hr %#x.\n", hr);
|
||||
|
||||
hr = IGraphBuilder_ConnectDirect(graph, &source.source.pin.IPin_iface, pin, &rgb8_mt);
|
||||
ok(hr == S_OK, "Got hr %#x.\n", hr);
|
||||
|
||||
source.preferred_mt = NULL;
|
||||
|
||||
hr = IDirectDrawMediaStream_SetFormat(ddraw_stream, &rgb555_format, NULL);
|
||||
ok(hr == DDERR_INVALIDSURFACETYPE, "Got hr %#x.\n", hr);
|
||||
ok(IsEqualGUID(&source.source.pin.mt.subtype, &MEDIASUBTYPE_RGB8),
|
||||
"Got subtype %s.\n", wine_dbgstr_guid(&source.source.pin.mt.subtype));
|
||||
hr = IDirectDrawMediaStream_GetFormat(ddraw_stream, ¤t_format, NULL, &desired_format, NULL);
|
||||
ok(hr == S_OK, "Got hr %#x.\n", hr);
|
||||
ok(current_format.ddpfPixelFormat.dwRGBBitCount == 8,
|
||||
"Got rgb bit count %u.\n", current_format.ddpfPixelFormat.dwRGBBitCount);
|
||||
ok(desired_format.ddpfPixelFormat.dwRGBBitCount == 8,
|
||||
"Got rgb bit count %u.\n", desired_format.ddpfPixelFormat.dwRGBBitCount);
|
||||
|
||||
format = rgb555_format;
|
||||
format.dwFlags = 0;
|
||||
hr = IDirectDrawMediaStream_SetFormat(ddraw_stream, &format, NULL);
|
||||
ok(hr == S_OK, "Got hr %#x.\n", hr);
|
||||
ok(IsEqualGUID(&source.source.pin.mt.subtype, &MEDIASUBTYPE_RGB8),
|
||||
"Got subtype %s.\n", wine_dbgstr_guid(&source.source.pin.mt.subtype));
|
||||
|
||||
source.preferred_mt = &rgb555_mt;
|
||||
|
||||
hr = IDirectDrawMediaStream_SetFormat(ddraw_stream, &rgb8_format, NULL);
|
||||
ok(hr == S_OK, "Got hr %#x.\n", hr);
|
||||
|
||||
hr = IDirectDrawMediaStream_SetFormat(ddraw_stream, &rgb555_format, NULL);
|
||||
ok(hr == S_OK, "Got hr %#x.\n", hr);
|
||||
ok(IsEqualGUID(&source.source.pin.mt.subtype, &MEDIASUBTYPE_RGB555),
|
||||
"Got subtype %s.\n", wine_dbgstr_guid(&source.source.pin.mt.subtype));
|
||||
hr = IDirectDrawMediaStream_GetFormat(ddraw_stream, ¤t_format, NULL, &desired_format, NULL);
|
||||
ok(hr == S_OK, "Got hr %#x.\n", hr);
|
||||
ok(current_format.ddpfPixelFormat.dwRGBBitCount == 16,
|
||||
"Got rgb bit count %u.\n", current_format.ddpfPixelFormat.dwRGBBitCount);
|
||||
ok(desired_format.ddpfPixelFormat.dwRGBBitCount == 16,
|
||||
"Got rgb bit count %u.\n", desired_format.ddpfPixelFormat.dwRGBBitCount);
|
||||
|
||||
video_info = rgb555_video_info;
|
||||
video_info.bmiHeader.biWidth = 222;
|
||||
video_info.bmiHeader.biHeight = -555;
|
||||
mt = rgb555_mt;
|
||||
mt.pbFormat = (BYTE *)&video_info;
|
||||
source.preferred_mt = &mt;
|
||||
|
||||
format = rgb555_format;
|
||||
format.dwFlags |= DDSD_WIDTH | DDSD_HEIGHT;
|
||||
format.dwWidth = 222;
|
||||
format.dwHeight = 555;
|
||||
hr = IDirectDrawMediaStream_SetFormat(ddraw_stream, &format, NULL);
|
||||
ok(hr == S_OK, "Got hr %#x.\n", hr);
|
||||
ok(IsEqualGUID(&source.source.pin.mt.subtype, &MEDIASUBTYPE_RGB555),
|
||||
"Got subtype %s.\n", wine_dbgstr_guid(&source.source.pin.mt.subtype));
|
||||
ok(((VIDEOINFO *)source.source.pin.mt.pbFormat)->bmiHeader.biWidth == 222,
|
||||
"Got width %d.\n", ((VIDEOINFO *)source.source.pin.mt.pbFormat)->bmiHeader.biWidth);
|
||||
ok(((VIDEOINFO *)source.source.pin.mt.pbFormat)->bmiHeader.biHeight == -555,
|
||||
"Got height %d.\n", ((VIDEOINFO *)source.source.pin.mt.pbFormat)->bmiHeader.biHeight);
|
||||
|
||||
hr = IGraphBuilder_Disconnect(graph, &source.source.pin.IPin_iface);
|
||||
ok(hr == S_OK, "Got hr %#x.\n", hr);
|
||||
hr = IGraphBuilder_Disconnect(graph, pin);
|
||||
ok(hr == S_OK, "Got hr %#x.\n", hr);
|
||||
|
||||
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);
|
||||
IDirectDrawMediaStream_Release(ddraw_stream);
|
||||
ref = IMediaStream_Release(stream);
|
||||
ok(!ref, "Got outstanding refcount %d.\n", ref);
|
||||
}
|
||||
|
||||
static void check_ammediastream_join_am_multi_media_stream(const CLSID *clsid)
|
||||
|
|
Loading…
Reference in New Issue