Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wine-winehq
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
wine
wine-winehq
Commits
d6e5b6ca
Commit
d6e5b6ca
authored
Jun 18, 2020
by
Nikolay Sivov
Committed by
Alexandre Julliard
Jun 18, 2020
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
evr: Implement stream managment methods for default mixer.
Signed-off-by:
Nikolay Sivov
<
nsivov@codeweavers.com
>
Signed-off-by:
Alexandre Julliard
<
julliard@winehq.org
>
parent
9c11c636
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
276 additions
and
16 deletions
+276
-16
mixer.c
dlls/evr/mixer.c
+162
-16
evr.c
dlls/evr/tests/evr.c
+114
-0
No files found.
dlls/evr/mixer.c
View file @
d6e5b6ca
...
...
@@ -21,17 +21,30 @@
#include "wine/debug.h"
#include "evr.h"
#include "d3d9.h"
#include "mferror.h"
#include "evr_classes.h"
WINE_DEFAULT_DEBUG_CHANNEL
(
evr
);
#define MAX_MIXER_INPUT_STREAMS 16
struct
input_stream
{
unsigned
int
id
;
};
struct
video_mixer
{
IMFTransform
IMFTransform_iface
;
IMFVideoDeviceID
IMFVideoDeviceID_iface
;
IMFTopologyServiceLookupClient
IMFTopologyServiceLookupClient_iface
;
LONG
refcount
;
struct
input_stream
inputs
[
MAX_MIXER_INPUT_STREAMS
];
unsigned
int
input_ids
[
MAX_MIXER_INPUT_STREAMS
];
unsigned
int
input_count
;
CRITICAL_SECTION
cs
;
};
static
struct
video_mixer
*
impl_from_IMFTransform
(
IMFTransform
*
iface
)
...
...
@@ -49,6 +62,21 @@ static struct video_mixer *impl_from_IMFTopologyServiceLookupClient(IMFTopologyS
return
CONTAINING_RECORD
(
iface
,
struct
video_mixer
,
IMFTopologyServiceLookupClient_iface
);
}
static
int
video_mixer_compare_input_id
(
const
void
*
a
,
const
void
*
b
)
{
const
unsigned
int
*
key
=
a
;
const
struct
input_stream
*
input
=
b
;
if
(
*
key
>
input
->
id
)
return
1
;
if
(
*
key
<
input
->
id
)
return
-
1
;
return
0
;
}
static
struct
input_stream
*
video_mixer_get_input
(
const
struct
video_mixer
*
mixer
,
unsigned
int
id
)
{
return
bsearch
(
&
id
,
mixer
->
inputs
,
mixer
->
input_count
,
sizeof
(
*
mixer
->
inputs
),
video_mixer_compare_input_id
);
}
static
HRESULT
WINAPI
video_mixer_transform_QueryInterface
(
IMFTransform
*
iface
,
REFIID
riid
,
void
**
obj
)
{
struct
video_mixer
*
mixer
=
impl_from_IMFTransform
(
iface
);
...
...
@@ -97,7 +125,10 @@ static ULONG WINAPI video_mixer_transform_Release(IMFTransform *iface)
TRACE
(
"%p, refcount %u.
\n
"
,
iface
,
refcount
);
if
(
!
refcount
)
{
DeleteCriticalSection
(
&
mixer
->
cs
);
free
(
mixer
);
}
return
refcount
;
}
...
...
@@ -105,38 +136,81 @@ static ULONG WINAPI video_mixer_transform_Release(IMFTransform *iface)
static
HRESULT
WINAPI
video_mixer_transform_GetStreamLimits
(
IMFTransform
*
iface
,
DWORD
*
input_minimum
,
DWORD
*
input_maximum
,
DWORD
*
output_minimum
,
DWORD
*
output_maximum
)
{
FIXM
E
(
"%p, %p, %p, %p, %p.
\n
"
,
iface
,
input_minimum
,
input_maximum
,
output_minimum
,
output_maximum
);
TRAC
E
(
"%p, %p, %p, %p, %p.
\n
"
,
iface
,
input_minimum
,
input_maximum
,
output_minimum
,
output_maximum
);
return
E_NOTIMPL
;
*
input_minimum
=
1
;
*
input_maximum
=
16
;
*
output_minimum
=
1
;
*
output_maximum
=
1
;
return
S_OK
;
}
static
HRESULT
WINAPI
video_mixer_transform_GetStreamCount
(
IMFTransform
*
iface
,
DWORD
*
inputs
,
DWORD
*
outputs
)
{
FIXME
(
"%p, %p, %p.
\n
"
,
iface
,
inputs
,
outputs
);
struct
video_mixer
*
mixer
=
impl_from_IMFTransform
(
iface
);
return
E_NOTIMPL
;
TRACE
(
"%p, %p, %p.
\n
"
,
iface
,
inputs
,
outputs
);
EnterCriticalSection
(
&
mixer
->
cs
);
if
(
inputs
)
*
inputs
=
mixer
->
input_count
;
if
(
outputs
)
*
outputs
=
1
;
LeaveCriticalSection
(
&
mixer
->
cs
);
return
S_OK
;
}
static
HRESULT
WINAPI
video_mixer_transform_GetStreamIDs
(
IMFTransform
*
iface
,
DWORD
input_size
,
DWORD
*
inputs
,
DWORD
output_size
,
DWORD
*
outputs
)
{
FIXME
(
"%p, %u, %p, %u, %p.
\n
"
,
iface
,
input_size
,
inputs
,
output_size
,
outputs
);
struct
video_mixer
*
mixer
=
impl_from_IMFTransform
(
iface
);
HRESULT
hr
=
S_OK
;
return
E_NOTIMPL
;
TRACE
(
"%p, %u, %p, %u, %p.
\n
"
,
iface
,
input_size
,
inputs
,
output_size
,
outputs
);
EnterCriticalSection
(
&
mixer
->
cs
);
if
(
mixer
->
input_count
>
input_size
||
!
output_size
)
hr
=
MF_E_BUFFERTOOSMALL
;
else
if
(
inputs
)
memcpy
(
inputs
,
mixer
->
input_ids
,
mixer
->
input_count
*
sizeof
(
*
inputs
));
if
(
outputs
)
*
outputs
=
0
;
LeaveCriticalSection
(
&
mixer
->
cs
);
return
hr
;
}
static
HRESULT
WINAPI
video_mixer_transform_GetInputStreamInfo
(
IMFTransform
*
iface
,
DWORD
id
,
MFT_INPUT_STREAM_INFO
*
info
)
{
FIXME
(
"%p, %u, %p.
\n
"
,
iface
,
id
,
info
);
struct
video_mixer
*
mixer
=
impl_from_IMFTransform
(
iface
);
struct
input_stream
*
input
;
HRESULT
hr
=
S_OK
;
return
E_NOTIMPL
;
TRACE
(
"%p, %u, %p.
\n
"
,
iface
,
id
,
info
);
EnterCriticalSection
(
&
mixer
->
cs
);
if
(
!
(
input
=
video_mixer_get_input
(
mixer
,
id
)))
hr
=
MF_E_INVALIDSTREAMNUMBER
;
else
{
memset
(
info
,
0
,
sizeof
(
*
info
));
if
(
id
)
info
->
dwFlags
|=
MFT_INPUT_STREAM_REMOVABLE
|
MFT_INPUT_STREAM_OPTIONAL
;
}
LeaveCriticalSection
(
&
mixer
->
cs
);
return
hr
;
}
static
HRESULT
WINAPI
video_mixer_transform_GetOutputStreamInfo
(
IMFTransform
*
iface
,
DWORD
id
,
MFT_OUTPUT_STREAM_INFO
*
info
)
{
FIXM
E
(
"%p, %u, %p.
\n
"
,
iface
,
id
,
info
);
TRAC
E
(
"%p, %u, %p.
\n
"
,
iface
,
id
,
info
);
return
E_NOTIMPL
;
if
(
id
)
return
MF_E_INVALIDSTREAMNUMBER
;
memset
(
info
,
0
,
sizeof
(
*
info
));
return
S_OK
;
}
static
HRESULT
WINAPI
video_mixer_transform_GetAttributes
(
IMFTransform
*
iface
,
IMFAttributes
**
attributes
)
...
...
@@ -157,23 +231,93 @@ static HRESULT WINAPI video_mixer_transform_GetInputStreamAttributes(IMFTransfor
static
HRESULT
WINAPI
video_mixer_transform_GetOutputStreamAttributes
(
IMFTransform
*
iface
,
DWORD
id
,
IMFAttributes
**
attributes
)
{
FIXM
E
(
"%p, %u, %p.
\n
"
,
iface
,
id
,
attributes
);
TRAC
E
(
"%p, %u, %p.
\n
"
,
iface
,
id
,
attributes
);
return
E_NOTIMPL
;
}
static
HRESULT
WINAPI
video_mixer_transform_DeleteInputStream
(
IMFTransform
*
iface
,
DWORD
id
)
{
FIXME
(
"%p, %u.
\n
"
,
iface
,
id
);
struct
video_mixer
*
mixer
=
impl_from_IMFTransform
(
iface
);
struct
input_stream
*
input
;
HRESULT
hr
=
S_OK
;
unsigned
int
idx
;
return
E_NOTIMPL
;
TRACE
(
"%p, %u.
\n
"
,
iface
,
id
);
EnterCriticalSection
(
&
mixer
->
cs
);
/* Can't delete reference stream. */
if
(
!
id
||
!
(
input
=
video_mixer_get_input
(
mixer
,
id
)))
hr
=
MF_E_INVALIDSTREAMNUMBER
;
else
{
mixer
->
input_count
--
;
idx
=
input
-
mixer
->
inputs
;
if
(
idx
<
mixer
->
input_count
)
{
memmove
(
&
mixer
->
inputs
[
idx
],
&
mixer
->
inputs
[
idx
+
1
],
(
mixer
->
input_count
-
idx
)
*
sizeof
(
*
mixer
->
inputs
));
memmove
(
&
mixer
->
input_ids
[
idx
],
&
mixer
->
input_ids
[
idx
+
1
],
(
mixer
->
input_count
-
idx
)
*
sizeof
(
*
mixer
->
input_ids
));
}
}
LeaveCriticalSection
(
&
mixer
->
cs
);
return
hr
;
}
static
HRESULT
WINAPI
video_mixer_transform_AddInputStreams
(
IMFTransform
*
iface
,
DWORD
streams
,
DWORD
*
ids
)
static
int
video_mixer_add_input_sort_compare
(
const
void
*
a
,
const
void
*
b
)
{
FIXME
(
"%p, %u, %p.
\n
"
,
iface
,
streams
,
ids
);
const
struct
input_stream
*
left
=
a
,
*
right
=
b
;
return
left
->
id
!=
right
->
id
?
(
left
->
id
<
right
->
id
?
-
1
:
1
)
:
0
;
};
return
E_NOTIMPL
;
static
HRESULT
WINAPI
video_mixer_transform_AddInputStreams
(
IMFTransform
*
iface
,
DWORD
count
,
DWORD
*
ids
)
{
struct
video_mixer
*
mixer
=
impl_from_IMFTransform
(
iface
);
struct
input_stream
inputs
[
MAX_MIXER_INPUT_STREAMS
]
=
{
{
0
}
};
unsigned
int
i
,
len
;
HRESULT
hr
=
S_OK
;
TRACE
(
"%p, %u, %p.
\n
"
,
iface
,
count
,
ids
);
if
(
!
ids
)
return
E_POINTER
;
EnterCriticalSection
(
&
mixer
->
cs
);
if
(
count
>
ARRAY_SIZE
(
mixer
->
inputs
)
-
mixer
->
input_count
)
hr
=
E_INVALIDARG
;
else
{
/* Test for collisions. */
memcpy
(
inputs
,
mixer
->
inputs
,
mixer
->
input_count
*
sizeof
(
*
inputs
));
for
(
i
=
0
;
i
<
count
;
++
i
)
inputs
[
i
+
mixer
->
input_count
].
id
=
ids
[
i
];
len
=
mixer
->
input_count
+
count
;
qsort
(
inputs
,
len
,
sizeof
(
*
inputs
),
video_mixer_add_input_sort_compare
);
for
(
i
=
1
;
i
<
len
;
++
i
)
{
if
(
inputs
[
i
-
1
].
id
==
inputs
[
i
].
id
)
{
hr
=
E_INVALIDARG
;
break
;
}
}
if
(
SUCCEEDED
(
hr
))
{
memcpy
(
&
mixer
->
input_ids
[
mixer
->
input_count
],
ids
,
count
*
sizeof
(
*
ids
));
memcpy
(
mixer
->
inputs
,
inputs
,
len
*
sizeof
(
*
inputs
));
mixer
->
input_count
+=
count
;
}
}
LeaveCriticalSection
(
&
mixer
->
cs
);
return
hr
;
}
static
HRESULT
WINAPI
video_mixer_transform_GetInputAvailableType
(
IMFTransform
*
iface
,
DWORD
id
,
DWORD
index
,
...
...
@@ -407,6 +551,8 @@ HRESULT evr_mixer_create(IUnknown *outer, void **out)
object
->
IMFVideoDeviceID_iface
.
lpVtbl
=
&
video_mixer_device_id_vtbl
;
object
->
IMFTopologyServiceLookupClient_iface
.
lpVtbl
=
&
video_mixer_service_client_vtbl
;
object
->
refcount
=
1
;
object
->
input_count
=
1
;
InitializeCriticalSection
(
&
object
->
cs
);
*
out
=
&
object
->
IMFTransform_iface
;
...
...
dlls/evr/tests/evr.c
View file @
d6e5b6ca
...
...
@@ -25,6 +25,7 @@
#include "evr.h"
#include "initguid.h"
#include "dxva2api.h"
#include "mferror.h"
static
const
WCHAR
sink_id
[]
=
{
'E'
,
'V'
,
'R'
,
' '
,
'I'
,
'n'
,
'p'
,
'u'
,
't'
,
'0'
,
0
};
...
...
@@ -340,8 +341,16 @@ static void test_pin_info(void)
static
void
test_default_mixer
(
void
)
{
DWORD
input_min
,
input_max
,
output_min
,
output_max
;
MFT_OUTPUT_STREAM_INFO
output_info
;
MFT_INPUT_STREAM_INFO
input_info
;
DWORD
input_count
,
output_count
;
IMFVideoDeviceID
*
deviceid
;
DWORD
input_id
,
output_id
;
IMFAttributes
*
attributes
,
*
attributes2
;
IMFTransform
*
transform
;
unsigned
int
i
;
DWORD
ids
[
16
];
IUnknown
*
unk
;
HRESULT
hr
;
IID
iid
;
...
...
@@ -365,6 +374,111 @@ static void test_default_mixer(void)
IMFVideoDeviceID_Release
(
deviceid
);
/* Stream configuration. */
input_count
=
output_count
=
0
;
hr
=
IMFTransform_GetStreamCount
(
transform
,
&
input_count
,
&
output_count
);
ok
(
hr
==
S_OK
,
"Failed to get stream count, hr %#x.
\n
"
,
hr
);
ok
(
input_count
==
1
&&
output_count
==
1
,
"Unexpected stream count %u/%u.
\n
"
,
input_count
,
output_count
);
hr
=
IMFTransform_GetStreamLimits
(
transform
,
&
input_min
,
&
input_max
,
&
output_min
,
&
output_max
);
ok
(
hr
==
S_OK
,
"Failed to get stream limits, hr %#x.
\n
"
,
hr
);
ok
(
input_min
==
1
&&
input_max
==
16
&&
output_min
==
1
&&
output_max
==
1
,
"Unexpected stream limits %u/%u, %u/%u.
\n
"
,
input_min
,
input_max
,
output_min
,
output_max
);
hr
=
IMFTransform_GetInputStreamInfo
(
transform
,
1
,
&
input_info
);
ok
(
hr
==
MF_E_INVALIDSTREAMNUMBER
,
"Unexpected hr %#x.
\n
"
,
hr
);
hr
=
IMFTransform_GetOutputStreamInfo
(
transform
,
1
,
&
output_info
);
ok
(
hr
==
MF_E_INVALIDSTREAMNUMBER
,
"Unexpected hr %#x.
\n
"
,
hr
);
memset
(
&
input_info
,
0xcc
,
sizeof
(
input_info
));
hr
=
IMFTransform_GetInputStreamInfo
(
transform
,
0
,
&
input_info
);
ok
(
hr
==
S_OK
,
"Failed to get input info, hr %#x.
\n
"
,
hr
);
memset
(
&
output_info
,
0xcc
,
sizeof
(
output_info
));
hr
=
IMFTransform_GetOutputStreamInfo
(
transform
,
0
,
&
output_info
);
ok
(
hr
==
S_OK
,
"Failed to get input info, hr %#x.
\n
"
,
hr
);
ok
(
!
(
output_info
.
dwFlags
&
(
MFT_OUTPUT_STREAM_PROVIDES_SAMPLES
|
MFT_OUTPUT_STREAM_CAN_PROVIDE_SAMPLES
)),
"Unexpected output flags %#x.
\n
"
,
output_info
.
dwFlags
);
hr
=
IMFTransform_GetStreamIDs
(
transform
,
1
,
&
input_id
,
1
,
&
output_id
);
ok
(
hr
==
S_OK
,
"Failed to get input info, hr %#x.
\n
"
,
hr
);
ok
(
input_id
==
0
&&
output_id
==
0
,
"Unexpected stream ids.
\n
"
);
hr
=
IMFTransform_GetInputStreamAttributes
(
transform
,
1
,
&
attributes
);
todo_wine
ok
(
hr
==
MF_E_INVALIDSTREAMNUMBER
,
"Unexpected hr %#x.
\n
"
,
hr
);
hr
=
IMFTransform_GetOutputStreamAttributes
(
transform
,
1
,
&
attributes
);
ok
(
hr
==
E_NOTIMPL
,
"Unexpected hr %#x.
\n
"
,
hr
);
hr
=
IMFTransform_GetOutputStreamAttributes
(
transform
,
0
,
&
attributes
);
ok
(
hr
==
E_NOTIMPL
,
"Unexpected hr %#x.
\n
"
,
hr
);
hr
=
IMFTransform_AddInputStreams
(
transform
,
16
,
NULL
);
ok
(
hr
==
E_POINTER
,
"Unexpected hr %#x.
\n
"
,
hr
);
hr
=
IMFTransform_AddInputStreams
(
transform
,
16
,
ids
);
ok
(
hr
==
E_INVALIDARG
,
"Unexpected hr %#x.
\n
"
,
hr
);
memset
(
ids
,
0
,
sizeof
(
ids
));
hr
=
IMFTransform_AddInputStreams
(
transform
,
15
,
ids
);
ok
(
hr
==
E_INVALIDARG
,
"Unexpected hr %#x.
\n
"
,
hr
);
for
(
i
=
0
;
i
<
ARRAY_SIZE
(
ids
);
++
i
)
ids
[
i
]
=
i
+
1
;
hr
=
IMFTransform_AddInputStreams
(
transform
,
15
,
ids
);
ok
(
hr
==
S_OK
,
"Unexpected hr %#x.
\n
"
,
hr
);
input_count
=
output_count
=
0
;
hr
=
IMFTransform_GetStreamCount
(
transform
,
&
input_count
,
&
output_count
);
ok
(
hr
==
S_OK
,
"Failed to get stream count, hr %#x.
\n
"
,
hr
);
ok
(
input_count
==
16
&&
output_count
==
1
,
"Unexpected stream count %u/%u.
\n
"
,
input_count
,
output_count
);
memset
(
&
input_info
,
0
,
sizeof
(
input_info
));
hr
=
IMFTransform_GetInputStreamInfo
(
transform
,
1
,
&
input_info
);
ok
(
hr
==
S_OK
,
"Failed to get input info, hr %#x.
\n
"
,
hr
);
ok
((
input_info
.
dwFlags
&
(
MFT_INPUT_STREAM_REMOVABLE
|
MFT_INPUT_STREAM_OPTIONAL
))
==
(
MFT_INPUT_STREAM_REMOVABLE
|
MFT_INPUT_STREAM_OPTIONAL
),
"Unexpected flags %#x.
\n
"
,
input_info
.
dwFlags
);
attributes
=
NULL
;
hr
=
IMFTransform_GetInputStreamAttributes
(
transform
,
0
,
&
attributes
);
todo_wine
{
ok
(
hr
==
S_OK
,
"Unexpected hr %#x.
\n
"
,
hr
);
ok
(
!!
attributes
,
"Unexpected attributes.
\n
"
);
}
attributes2
=
NULL
;
hr
=
IMFTransform_GetInputStreamAttributes
(
transform
,
0
,
&
attributes2
);
todo_wine
ok
(
hr
==
S_OK
,
"Unexpected hr %#x.
\n
"
,
hr
);
ok
(
attributes
==
attributes2
,
"Unexpected instance.
\n
"
);
if
(
attributes2
)
IMFAttributes_Release
(
attributes2
);
if
(
attributes
)
IMFAttributes_Release
(
attributes
);
attributes
=
NULL
;
hr
=
IMFTransform_GetInputStreamAttributes
(
transform
,
1
,
&
attributes
);
todo_wine
{
ok
(
hr
==
S_OK
,
"Unexpected hr %#x.
\n
"
,
hr
);
ok
(
!!
attributes
,
"Unexpected attributes.
\n
"
);
}
if
(
attributes
)
IMFAttributes_Release
(
attributes
);
hr
=
IMFTransform_DeleteInputStream
(
transform
,
0
);
ok
(
hr
==
MF_E_INVALIDSTREAMNUMBER
,
"Unexpected hr %#x.
\n
"
,
hr
);
hr
=
IMFTransform_DeleteInputStream
(
transform
,
1
);
ok
(
hr
==
S_OK
,
"Unexpected hr %#x.
\n
"
,
hr
);
input_count
=
output_count
=
0
;
hr
=
IMFTransform_GetStreamCount
(
transform
,
&
input_count
,
&
output_count
);
ok
(
hr
==
S_OK
,
"Failed to get stream count, hr %#x.
\n
"
,
hr
);
ok
(
input_count
==
15
&&
output_count
==
1
,
"Unexpected stream count %u/%u.
\n
"
,
input_count
,
output_count
);
IMFTransform_Release
(
transform
);
hr
=
MFCreateVideoMixer
(
NULL
,
&
IID_IMFTransform
,
&
IID_IMFTransform
,
(
void
**
)
&
transform
);
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment