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
ed8d3d32
Commit
ed8d3d32
authored
Feb 20, 2020
by
Zebediah Figura
Committed by
Alexandre Julliard
Feb 21, 2020
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
qasf/dmowrapper: Implement receiving and delivering samples.
Signed-off-by:
Zebediah Figura
<
zfigura@codeweavers.com
>
Signed-off-by:
Alexandre Julliard
<
julliard@winehq.org
>
parent
e7c735b8
Show whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
609 additions
and
20 deletions
+609
-20
dmowrapper.c
dlls/qasf/dmowrapper.c
+246
-1
dmowrapper.c
dlls/qasf/tests/dmowrapper.c
+346
-19
mediaobj.idl
include/mediaobj.idl
+17
-0
No files found.
dlls/qasf/dmowrapper.c
View file @
ed8d3d32
...
...
@@ -22,9 +22,16 @@
WINE_DEFAULT_DEBUG_CHANNEL
(
qasf
);
struct
buffer
{
IMediaBuffer
IMediaBuffer_iface
;
IMediaSample
*
sample
;
};
struct
dmo_wrapper_source
{
struct
strmbase_source
pin
;
struct
buffer
buffer
;
};
struct
dmo_wrapper
...
...
@@ -37,6 +44,80 @@ struct dmo_wrapper
DWORD
sink_count
,
source_count
;
struct
strmbase_sink
*
sinks
;
struct
dmo_wrapper_source
*
sources
;
DMO_OUTPUT_DATA_BUFFER
*
buffers
;
struct
buffer
input_buffer
;
};
static
struct
buffer
*
impl_from_IMediaBuffer
(
IMediaBuffer
*
iface
)
{
return
CONTAINING_RECORD
(
iface
,
struct
buffer
,
IMediaBuffer_iface
);
}
static
HRESULT
WINAPI
buffer_QueryInterface
(
IMediaBuffer
*
iface
,
REFIID
iid
,
void
**
out
)
{
TRACE
(
"iface %p, iid %s, out %p.
\n
"
,
iface
,
debugstr_guid
(
iid
),
out
);
if
(
IsEqualGUID
(
iid
,
&
IID_IUnknown
)
||
IsEqualGUID
(
iid
,
&
IID_IMediaBuffer
))
{
IMediaBuffer_AddRef
(
iface
);
*
out
=
iface
;
return
S_OK
;
}
WARN
(
"%s not implemented, returning E_NOINTERFACE.
\n
"
,
debugstr_guid
(
iid
));
*
out
=
NULL
;
return
E_NOINTERFACE
;
}
static
ULONG
WINAPI
buffer_AddRef
(
IMediaBuffer
*
iface
)
{
TRACE
(
"iface %p.
\n
"
,
iface
);
return
2
;
}
static
ULONG
WINAPI
buffer_Release
(
IMediaBuffer
*
iface
)
{
TRACE
(
"iface %p.
\n
"
,
iface
);
return
1
;
}
static
HRESULT
WINAPI
buffer_SetLength
(
IMediaBuffer
*
iface
,
DWORD
len
)
{
struct
buffer
*
buffer
=
impl_from_IMediaBuffer
(
iface
);
TRACE
(
"iface %p, len %u.
\n
"
,
iface
,
len
);
return
IMediaSample_SetActualDataLength
(
buffer
->
sample
,
len
);
}
static
HRESULT
WINAPI
buffer_GetMaxLength
(
IMediaBuffer
*
iface
,
DWORD
*
len
)
{
struct
buffer
*
buffer
=
impl_from_IMediaBuffer
(
iface
);
TRACE
(
"iface %p, len %p.
\n
"
,
iface
,
len
);
*
len
=
IMediaSample_GetSize
(
buffer
->
sample
);
return
S_OK
;
}
static
HRESULT
WINAPI
buffer_GetBufferAndLength
(
IMediaBuffer
*
iface
,
BYTE
**
data
,
DWORD
*
len
)
{
struct
buffer
*
buffer
=
impl_from_IMediaBuffer
(
iface
);
TRACE
(
"iface %p, data %p, len %p.
\n
"
,
iface
,
data
,
len
);
*
len
=
IMediaSample_GetActualDataLength
(
buffer
->
sample
);
return
IMediaSample_GetPointer
(
buffer
->
sample
,
data
);
}
static
const
IMediaBufferVtbl
buffer_vtbl
=
{
buffer_QueryInterface
,
buffer_AddRef
,
buffer_Release
,
buffer_SetLength
,
buffer_GetMaxLength
,
buffer_GetBufferAndLength
,
};
static
inline
struct
dmo_wrapper
*
impl_from_strmbase_filter
(
struct
strmbase_filter
*
iface
)
...
...
@@ -120,6 +201,140 @@ static void dmo_wrapper_sink_disconnect(struct strmbase_sink *iface)
IMediaObject_Release
(
dmo
);
}
static
HRESULT
process_output
(
struct
dmo_wrapper
*
filter
,
IMediaObject
*
dmo
)
{
DMO_OUTPUT_DATA_BUFFER
*
buffers
=
filter
->
buffers
;
DWORD
status
,
i
;
BOOL
more_data
;
HRESULT
hr
;
for
(
i
=
0
;
i
<
filter
->
source_count
;
++
i
)
{
if
(
filter
->
sources
[
i
].
pin
.
pin
.
peer
)
{
if
(
FAILED
(
hr
=
IMemAllocator_GetBuffer
(
filter
->
sources
[
i
].
pin
.
pAllocator
,
&
filter
->
sources
[
i
].
buffer
.
sample
,
NULL
,
NULL
,
0
)))
{
ERR
(
"Failed to get sample, hr %#x.
\n
"
,
hr
);
goto
out
;
}
buffers
[
i
].
pBuffer
=
&
filter
->
sources
[
i
].
buffer
.
IMediaBuffer_iface
;
IMediaSample_SetActualDataLength
(
filter
->
sources
[
i
].
buffer
.
sample
,
0
);
}
else
buffers
[
i
].
pBuffer
=
NULL
;
}
do
{
more_data
=
FALSE
;
hr
=
IMediaObject_ProcessOutput
(
dmo
,
DMO_PROCESS_OUTPUT_DISCARD_WHEN_NO_BUFFER
,
filter
->
source_count
,
buffers
,
&
status
);
if
(
hr
!=
S_OK
)
break
;
for
(
i
=
0
;
i
<
filter
->
source_count
;
++
i
)
{
IMediaSample
*
sample
=
filter
->
sources
[
i
].
buffer
.
sample
;
if
(
!
buffers
[
i
].
pBuffer
)
continue
;
if
(
buffers
[
i
].
dwStatus
&
DMO_OUTPUT_DATA_BUFFERF_INCOMPLETE
)
more_data
=
TRUE
;
if
(
buffers
[
i
].
dwStatus
&
DMO_OUTPUT_DATA_BUFFERF_TIME
)
{
if
(
buffers
[
i
].
dwStatus
&
DMO_OUTPUT_DATA_BUFFERF_TIMELENGTH
)
{
REFERENCE_TIME
stop
=
buffers
[
i
].
rtTimestamp
+
buffers
[
i
].
rtTimelength
;
IMediaSample_SetTime
(
sample
,
&
buffers
[
i
].
rtTimestamp
,
&
stop
);
}
else
IMediaSample_SetTime
(
sample
,
&
buffers
[
i
].
rtTimestamp
,
NULL
);
}
if
(
buffers
[
i
].
dwStatus
&
DMO_OUTPUT_DATA_BUFFERF_SYNCPOINT
)
IMediaSample_SetSyncPoint
(
sample
,
TRUE
);
if
(
IMediaSample_GetActualDataLength
(
sample
))
{
if
(
FAILED
(
hr
=
IMemInputPin_Receive
(
filter
->
sources
[
i
].
pin
.
pMemInputPin
,
sample
)))
{
WARN
(
"Downstream sink returned %#x.
\n
"
,
hr
);
goto
out
;
}
IMediaSample_SetActualDataLength
(
sample
,
0
);
}
}
}
while
(
more_data
);
out:
for
(
i
=
0
;
i
<
filter
->
source_count
;
++
i
)
{
if
(
filter
->
sources
[
i
].
buffer
.
sample
)
{
IMediaSample_Release
(
filter
->
sources
[
i
].
buffer
.
sample
);
filter
->
sources
[
i
].
buffer
.
sample
=
NULL
;
}
}
return
hr
;
}
static
HRESULT
WINAPI
dmo_wrapper_sink_Receive
(
struct
strmbase_sink
*
iface
,
IMediaSample
*
sample
)
{
struct
dmo_wrapper
*
filter
=
impl_from_strmbase_filter
(
iface
->
pin
.
filter
);
DWORD
index
=
iface
-
filter
->
sinks
;
REFERENCE_TIME
start
=
0
,
stop
=
0
;
IMediaObject
*
dmo
;
DWORD
flags
=
0
;
HRESULT
hr
;
IUnknown_QueryInterface
(
filter
->
dmo
,
&
IID_IMediaObject
,
(
void
**
)
&
dmo
);
if
(
IMediaSample_IsDiscontinuity
(
sample
)
==
S_OK
)
{
if
(
FAILED
(
hr
=
IMediaObject_Discontinuity
(
dmo
,
index
)))
{
ERR
(
"Discontinuity() failed, hr %#x.
\n
"
,
hr
);
goto
out
;
}
/* Calling Discontinuity() might change the DMO's mind about whether it
* has more data to process. The DirectX documentation explicitly
* states that we should call ProcessOutput() again in this case. */
process_output
(
filter
,
dmo
);
}
if
(
IMediaSample_IsSyncPoint
(
sample
)
==
S_OK
)
flags
|=
DMO_INPUT_DATA_BUFFERF_SYNCPOINT
;
if
(
SUCCEEDED
(
hr
=
IMediaSample_GetTime
(
sample
,
&
start
,
&
stop
)))
{
flags
|=
DMO_INPUT_DATA_BUFFERF_TIME
|
DMO_INPUT_DATA_BUFFERF_TIMELENGTH
;
if
(
hr
==
VFW_S_NO_STOP_TIME
)
stop
=
start
+
1
;
}
filter
->
input_buffer
.
sample
=
sample
;
if
(
FAILED
(
hr
=
IMediaObject_ProcessInput
(
dmo
,
index
,
&
filter
->
input_buffer
.
IMediaBuffer_iface
,
flags
,
start
,
stop
-
start
)))
{
ERR
(
"ProcessInput() failed, hr %#x.
\n
"
,
hr
);
goto
out
;
}
process_output
(
filter
,
dmo
);
out:
filter
->
input_buffer
.
sample
=
NULL
;
IMediaObject_Release
(
dmo
);
return
hr
;
}
static
const
struct
strmbase_sink_ops
sink_ops
=
{
.
base
.
pin_query_interface
=
dmo_wrapper_sink_query_interface
,
...
...
@@ -127,6 +342,7 @@ static const struct strmbase_sink_ops sink_ops =
.
base
.
pin_get_media_type
=
dmo_wrapper_sink_get_media_type
,
.
sink_connect
=
dmo_wrapper_sink_connect
,
.
sink_disconnect
=
dmo_wrapper_sink_disconnect
,
.
pfnReceive
=
dmo_wrapper_sink_Receive
,
};
static
inline
struct
dmo_wrapper_source
*
impl_source_from_strmbase_pin
(
struct
strmbase_pin
*
iface
)
...
...
@@ -245,6 +461,7 @@ static HRESULT WINAPI dmo_wrapper_filter_Init(IDMOWrapperFilter *iface, REFCLSID
{
struct
dmo_wrapper
*
filter
=
impl_from_IDMOWrapperFilter
(
iface
);
struct
dmo_wrapper_source
*
sources
;
DMO_OUTPUT_DATA_BUFFER
*
buffers
;
DWORD
input_count
,
output_count
;
struct
strmbase_sink
*
sinks
;
IMediaObject
*
dmo
;
...
...
@@ -270,10 +487,12 @@ static HRESULT WINAPI dmo_wrapper_filter_Init(IDMOWrapperFilter *iface, REFCLSID
sinks
=
calloc
(
sizeof
(
*
sinks
),
input_count
);
sources
=
calloc
(
sizeof
(
*
sources
),
output_count
);
if
(
!
sinks
||
!
sources
)
buffers
=
calloc
(
sizeof
(
*
buffers
),
output_count
);
if
(
!
sinks
||
!
sources
||
!
buffers
)
{
free
(
sinks
);
free
(
sources
);
free
(
buffers
);
IMediaObject_Release
(
dmo
);
IUnknown_Release
(
unk
);
return
hr
;
...
...
@@ -289,6 +508,7 @@ static HRESULT WINAPI dmo_wrapper_filter_Init(IDMOWrapperFilter *iface, REFCLSID
{
swprintf
(
id
,
ARRAY_SIZE
(
id
),
L"out%u"
,
i
);
strmbase_source_init
(
&
sources
[
i
].
pin
,
&
filter
->
filter
,
id
,
&
source_ops
);
sources
[
i
].
buffer
.
IMediaBuffer_iface
.
lpVtbl
=
&
buffer_vtbl
;
}
EnterCriticalSection
(
&
filter
->
filter
.
csFilter
);
...
...
@@ -298,6 +518,7 @@ static HRESULT WINAPI dmo_wrapper_filter_Init(IDMOWrapperFilter *iface, REFCLSID
filter
->
source_count
=
output_count
;
filter
->
sinks
=
sinks
;
filter
->
sources
=
sources
;
filter
->
buffers
=
buffers
;
LeaveCriticalSection
(
&
filter
->
filter
.
csFilter
);
...
...
@@ -358,13 +579,34 @@ static HRESULT dmo_wrapper_query_interface(struct strmbase_filter *iface, REFIID
return
E_NOINTERFACE
;
}
static
HRESULT
dmo_wrapper_init_stream
(
struct
strmbase_filter
*
iface
)
{
struct
dmo_wrapper
*
filter
=
impl_from_strmbase_filter
(
iface
);
DWORD
i
;
for
(
i
=
0
;
i
<
filter
->
source_count
;
++
i
)
{
if
(
filter
->
sources
[
i
].
pin
.
pin
.
peer
)
IMemAllocator_Commit
(
filter
->
sources
[
i
].
pin
.
pAllocator
);
}
return
S_OK
;
}
static
HRESULT
dmo_wrapper_cleanup_stream
(
struct
strmbase_filter
*
iface
)
{
struct
dmo_wrapper
*
filter
=
impl_from_strmbase_filter
(
iface
);
IMediaObject
*
dmo
;
DWORD
i
;
IUnknown_QueryInterface
(
filter
->
dmo
,
&
IID_IMediaObject
,
(
void
**
)
&
dmo
);
for
(
i
=
0
;
i
<
filter
->
source_count
;
++
i
)
{
if
(
filter
->
sources
[
i
].
pin
.
pin
.
peer
)
IMemAllocator_Decommit
(
filter
->
sources
[
i
].
pin
.
pAllocator
);
}
IMediaObject_Flush
(
dmo
);
IMediaObject_Release
(
dmo
);
...
...
@@ -376,6 +618,7 @@ static struct strmbase_filter_ops filter_ops =
.
filter_get_pin
=
dmo_wrapper_get_pin
,
.
filter_destroy
=
dmo_wrapper_destroy
,
.
filter_query_interface
=
dmo_wrapper_query_interface
,
.
filter_init_stream
=
dmo_wrapper_init_stream
,
.
filter_cleanup_stream
=
dmo_wrapper_cleanup_stream
,
};
...
...
@@ -391,6 +634,8 @@ HRESULT dmo_wrapper_create(IUnknown *outer, IUnknown **out)
object
->
IDMOWrapperFilter_iface
.
lpVtbl
=
&
dmo_wrapper_filter_vtbl
;
object
->
input_buffer
.
IMediaBuffer_iface
.
lpVtbl
=
&
buffer_vtbl
;
TRACE
(
"Created DMO wrapper %p.
\n
"
,
object
);
*
out
=
&
object
->
filter
.
IUnknown_inner
;
...
...
dlls/qasf/tests/dmowrapper.c
View file @
ed8d3d32
...
...
@@ -56,6 +56,13 @@ static inline BOOL compare_media_types(const AM_MEDIA_TYPE *a, const AM_MEDIA_TY
&&
!
memcmp
(
a
->
pbFormat
,
b
->
pbFormat
,
a
->
cbFormat
);
}
static
ULONG
get_refcount
(
void
*
iface
)
{
IUnknown
*
unknown
=
iface
;
IUnknown_AddRef
(
unknown
);
return
IUnknown_Release
(
unknown
);
}
static
const
IMediaObjectVtbl
dmo_vtbl
;
static
IMediaObject
testdmo
=
{
&
dmo_vtbl
};
...
...
@@ -69,7 +76,11 @@ static HRESULT testdmo_GetOutputSizeInfo_hr = S_OK;
static
DWORD
testdmo_output_size
=
123
;
static
DWORD
testdmo_output_alignment
=
1
;
static
unsigned
int
got_Flush
;
static
unsigned
int
got_Flush
,
got_Discontinuity
,
got_ProcessInput
,
got_ProcessOutput
,
got_Receive
;
static
IMediaBuffer
*
testdmo_buffer
;
static
int
testmode
;
static
HRESULT
WINAPI
dmo_inner_QueryInterface
(
IUnknown
*
iface
,
REFIID
iid
,
void
**
out
)
{
...
...
@@ -249,8 +260,9 @@ static HRESULT WINAPI dmo_Flush(IMediaObject *iface)
static
HRESULT
WINAPI
dmo_Discontinuity
(
IMediaObject
*
iface
,
DWORD
index
)
{
ok
(
0
,
"Unexpected call.
\n
"
);
return
E_NOTIMPL
;
if
(
winetest_debug
>
1
)
trace
(
"Discontinuity(index %u)
\n
"
,
index
);
++
got_Discontinuity
;
return
S_OK
;
}
static
HRESULT
WINAPI
dmo_AllocateStreamingResources
(
IMediaObject
*
iface
)
...
...
@@ -267,22 +279,132 @@ static HRESULT WINAPI dmo_FreeStreamingResources(IMediaObject *iface)
static
HRESULT
WINAPI
dmo_GetInputStatus
(
IMediaObject
*
iface
,
DWORD
index
,
DWORD
*
flags
)
{
ok
(
0
,
"Unexpected call.
\n
"
);
return
E_NOTIMPL
;
if
(
winetest_debug
>
1
)
trace
(
"GetInputStatus(index %u)
\n
"
,
index
);
*
flags
=
DMO_INPUT_STATUSF_ACCEPT_DATA
;
return
S_OK
;
}
static
HRESULT
WINAPI
dmo_ProcessInput
(
IMediaObject
*
iface
,
DWORD
index
,
IMediaBuffer
*
buffer
,
DWORD
flags
,
REFERENCE_TIME
timestamp
,
REFERENCE_TIME
timelength
)
{
ok
(
0
,
"Unexpected call.
\n
"
);
return
E_NOTIMPL
;
BYTE
*
data
,
expect
[
200
];
DWORD
len
,
i
;
HRESULT
hr
;
if
(
winetest_debug
>
1
)
trace
(
"ProcessInput(index %u, flags %#x, timestamp %I64d, timelength %I64d)
\n
"
,
index
,
flags
,
timestamp
,
timelength
);
++
got_ProcessInput
;
hr
=
IMediaBuffer_GetBufferAndLength
(
buffer
,
&
data
,
&
len
);
ok
(
hr
==
S_OK
,
"Got hr %#x.
\n
"
,
hr
);
ok
(
len
==
200
,
"Got length %u.
\n
"
,
len
);
for
(
i
=
0
;
i
<
200
;
++
i
)
expect
[
i
]
=
i
;
ok
(
!
memcmp
(
data
,
expect
,
200
),
"Data didn't match.
\n
"
);
hr
=
IMediaBuffer_GetMaxLength
(
buffer
,
&
len
);
ok
(
hr
==
S_OK
,
"Got hr %#x.
\n
"
,
hr
);
ok
(
len
==
256
,
"Got length %u.
\n
"
,
len
);
if
(
testmode
==
0
)
{
ok
(
!
flags
,
"Got flags %#x.
\n
"
,
flags
);
ok
(
!
timestamp
,
"Got timestamp %s.
\n
"
,
wine_dbgstr_longlong
(
timestamp
));
ok
(
!
timelength
,
"Got length %s.
\n
"
,
wine_dbgstr_longlong
(
timelength
));
}
else
if
(
testmode
==
1
)
{
ok
(
flags
==
(
DMO_INPUT_DATA_BUFFERF_TIME
|
DMO_INPUT_DATA_BUFFERF_TIMELENGTH
),
"Got flags %#x.
\n
"
,
flags
);
ok
(
timestamp
==
20000
,
"Got timestamp %s.
\n
"
,
wine_dbgstr_longlong
(
timestamp
));
ok
(
timelength
==
1
,
"Got length %s.
\n
"
,
wine_dbgstr_longlong
(
timelength
));
}
else
if
(
testmode
==
6
)
{
ok
(
flags
==
(
DMO_INPUT_DATA_BUFFERF_TIME
|
DMO_INPUT_DATA_BUFFERF_TIMELENGTH
|
DMO_INPUT_DATA_BUFFERF_SYNCPOINT
),
"Got flags %#x.
\n
"
,
flags
);
ok
(
timestamp
==
20000
,
"Got timestamp %s.
\n
"
,
wine_dbgstr_longlong
(
timestamp
));
ok
(
timelength
==
10000
,
"Got length %s.
\n
"
,
wine_dbgstr_longlong
(
timelength
));
}
else
{
ok
(
flags
==
(
DMO_INPUT_DATA_BUFFERF_TIME
|
DMO_INPUT_DATA_BUFFERF_TIMELENGTH
),
"Got flags %#x.
\n
"
,
flags
);
ok
(
timestamp
==
20000
,
"Got timestamp %s.
\n
"
,
wine_dbgstr_longlong
(
timestamp
));
ok
(
timelength
==
10000
,
"Got length %s.
\n
"
,
wine_dbgstr_longlong
(
timelength
));
}
testdmo_buffer
=
buffer
;
IMediaBuffer_AddRef
(
buffer
);
return
S_OK
;
}
static
HRESULT
WINAPI
dmo_ProcessOutput
(
IMediaObject
*
iface
,
DWORD
flags
,
DWORD
count
,
DMO_OUTPUT_DATA_BUFFER
*
buffers
,
DWORD
*
status
)
{
ok
(
0
,
"Unexpected call.
\n
"
);
return
E_NOTIMPL
;
DWORD
len
,
i
;
HRESULT
hr
;
BYTE
*
data
;
if
(
winetest_debug
>
1
)
trace
(
"ProcessOutput(flags %#x, count %u)
\n
"
,
flags
,
count
);
++
got_ProcessOutput
;
*
status
=
0
;
ok
(
flags
==
DMO_PROCESS_OUTPUT_DISCARD_WHEN_NO_BUFFER
,
"Got flags %#x.
\n
"
,
flags
);
ok
(
count
==
2
,
"Got count %u.
\n
"
,
count
);
ok
(
!!
buffers
[
0
].
pBuffer
,
"Expected a buffer.
\n
"
);
ok
(
!
buffers
[
1
].
pBuffer
,
"Got unexpected buffer %p.
\n
"
,
buffers
[
1
].
pBuffer
);
buffers
[
1
].
dwStatus
=
DMO_OUTPUT_DATA_BUFFERF_INCOMPLETE
;
hr
=
IMediaBuffer_GetBufferAndLength
(
buffers
[
0
].
pBuffer
,
&
data
,
&
len
);
ok
(
hr
==
S_OK
,
"Got hr %#x.
\n
"
,
hr
);
ok
(
!
len
,
"Got length %u.
\n
"
,
len
);
hr
=
IMediaBuffer_GetMaxLength
(
buffers
[
0
].
pBuffer
,
&
len
);
ok
(
hr
==
S_OK
,
"Got hr %#x.
\n
"
,
hr
);
ok
(
len
==
16384
,
"Got length %u.
\n
"
,
len
);
buffers
[
0
].
dwStatus
=
DMO_OUTPUT_DATA_BUFFERF_TIME
|
DMO_OUTPUT_DATA_BUFFERF_TIMELENGTH
;
buffers
[
0
].
rtTimelength
=
1000
;
buffers
[
0
].
rtTimestamp
=
5000
;
if
(
testmode
==
3
)
{
hr
=
IMediaBuffer_SetLength
(
buffers
[
0
].
pBuffer
,
16200
);
ok
(
hr
==
S_OK
,
"Got hr %#x.
\n
"
,
hr
);
buffers
[
0
].
dwStatus
|=
DMO_OUTPUT_DATA_BUFFERF_INCOMPLETE
;
return
S_OK
;
}
else
if
(
testmode
==
5
)
{
hr
=
IMediaBuffer_SetLength
(
buffers
[
0
].
pBuffer
,
0
);
ok
(
hr
==
S_OK
,
"Got hr %#x.
\n
"
,
hr
);
IMediaBuffer_Release
(
testdmo_buffer
);
return
S_FALSE
;
}
else
{
if
(
testmode
==
7
)
buffers
[
0
].
dwStatus
|=
DMO_OUTPUT_DATA_BUFFERF_SYNCPOINT
;
else
if
(
testmode
==
8
)
buffers
[
0
].
dwStatus
=
DMO_OUTPUT_DATA_BUFFERF_TIME
;
else
if
(
testmode
==
9
)
buffers
[
0
].
dwStatus
=
0
;
for
(
i
=
0
;
i
<
300
;
++
i
)
data
[
i
]
=
111
-
i
;
hr
=
IMediaBuffer_SetLength
(
buffers
[
0
].
pBuffer
,
300
);
ok
(
hr
==
S_OK
,
"Got hr %#x.
\n
"
,
hr
);
if
(
testmode
!=
10
)
IMediaBuffer_Release
(
testdmo_buffer
);
return
S_OK
;
}
return
S_OK
;
}
static
HRESULT
WINAPI
dmo_Lock
(
IMediaObject
*
iface
,
LONG
lock
)
...
...
@@ -384,13 +506,6 @@ static IBaseFilter *create_dmo_wrapper(void)
return
filter
;
}
static
ULONG
get_refcount
(
void
*
iface
)
{
IUnknown
*
unknown
=
iface
;
IUnknown_AddRef
(
unknown
);
return
IUnknown_Release
(
unknown
);
}
#define check_interface(a, b, c) check_interface_(__LINE__, a, b, c)
static
void
check_interface_
(
unsigned
int
line
,
void
*
iface_ptr
,
REFIID
iid
,
BOOL
supported
)
{
...
...
@@ -1077,6 +1192,61 @@ static HRESULT testsink_get_media_type(struct strmbase_pin *iface, unsigned int
static
HRESULT
WINAPI
testsink_Receive
(
struct
strmbase_sink
*
iface
,
IMediaSample
*
sample
)
{
REFERENCE_TIME
start
,
stop
;
LONG
len
,
i
;
HRESULT
hr
;
++
got_Receive
;
len
=
IMediaSample_GetSize
(
sample
);
ok
(
len
==
16384
,
"Got size %u.
\n
"
,
len
);
len
=
IMediaSample_GetActualDataLength
(
sample
);
if
(
testmode
==
3
)
ok
(
len
==
16200
,
"Got length %u.
\n
"
,
len
);
else
{
BYTE
*
data
,
expect
[
300
];
ok
(
len
==
300
,
"Got length %u.
\n
"
,
len
);
hr
=
IMediaSample_GetPointer
(
sample
,
&
data
);
ok
(
hr
==
S_OK
,
"Got hr %#x.
\n
"
,
hr
);
for
(
i
=
0
;
i
<
300
;
++
i
)
expect
[
i
]
=
111
-
i
;
ok
(
!
memcmp
(
data
,
expect
,
300
),
"Data didn't match.
\n
"
);
}
hr
=
IMediaSample_GetTime
(
sample
,
&
start
,
&
stop
);
if
(
testmode
==
8
)
{
ok
(
hr
==
VFW_S_NO_STOP_TIME
,
"Got hr %#x.
\n
"
,
hr
);
ok
(
start
==
5000
,
"Got start time %s.
\n
"
,
wine_dbgstr_longlong
(
start
));
}
else
if
(
testmode
==
9
)
ok
(
hr
==
VFW_E_SAMPLE_TIME_NOT_SET
,
"Got hr %#x.
\n
"
,
hr
);
else
{
ok
(
hr
==
S_OK
,
"Got hr %#x.
\n
"
,
hr
);
ok
(
start
==
5000
,
"Got start time %s.
\n
"
,
wine_dbgstr_longlong
(
start
));
ok
(
stop
==
6000
,
"Got stop time %s.
\n
"
,
wine_dbgstr_longlong
(
stop
));
}
hr
=
IMediaSample_GetMediaTime
(
sample
,
&
start
,
&
stop
);
ok
(
hr
==
VFW_E_MEDIA_TIME_NOT_SET
,
"Got hr %#x.
\n
"
,
hr
);
hr
=
IMediaSample_IsDiscontinuity
(
sample
);
ok
(
hr
==
S_FALSE
,
"Got hr %#x.
\n
"
,
hr
);
hr
=
IMediaSample_IsPreroll
(
sample
);
ok
(
hr
==
S_FALSE
,
"Got hr %#x.
\n
"
,
hr
);
hr
=
IMediaSample_IsSyncPoint
(
sample
);
ok
(
hr
==
(
testmode
==
7
?
S_OK
:
S_FALSE
),
"Got hr %#x.
\n
"
,
hr
);
if
(
testmode
==
3
)
testmode
=
4
;
if
(
testmode
==
10
)
testmode
=
11
;
return
S_OK
;
}
...
...
@@ -1100,7 +1270,7 @@ static void testfilter_init(struct testfilter *filter)
static
void
test_sink_allocator
(
IMemInputPin
*
input
)
{
IMemAllocator
*
req_allocator
,
*
ret_allocator
;
ALLOCATOR_PROPERTIES
props
;
ALLOCATOR_PROPERTIES
props
,
ret_props
;
HRESULT
hr
;
hr
=
IMemInputPin_GetAllocatorRequirements
(
input
,
&
props
);
...
...
@@ -1141,6 +1311,13 @@ static void test_sink_allocator(IMemInputPin *input)
CoCreateInstance
(
&
CLSID_MemoryAllocator
,
NULL
,
CLSCTX_INPROC_SERVER
,
&
IID_IMemAllocator
,
(
void
**
)
&
req_allocator
);
props
.
cBuffers
=
1
;
props
.
cbBuffer
=
256
;
props
.
cbAlign
=
1
;
props
.
cbPrefix
=
0
;
hr
=
IMemAllocator_SetProperties
(
req_allocator
,
&
props
,
&
ret_props
);
ok
(
hr
==
S_OK
,
"Got hr %#x.
\n
"
,
hr
);
hr
=
IMemInputPin_NotifyAllocator
(
input
,
req_allocator
,
TRUE
);
ok
(
hr
==
S_OK
,
"Got hr %#x.
\n
"
,
hr
);
...
...
@@ -1275,6 +1452,155 @@ static void test_filter_state(IMediaControl *control)
ok
(
state
==
State_Stopped
,
"Got state %u.
\n
"
,
state
);
}
static
void
test_sample_processing
(
IMediaControl
*
control
,
IMemInputPin
*
input
)
{
REFERENCE_TIME
start
,
stop
;
IMemAllocator
*
allocator
;
IMediaSample
*
sample
;
LONG
size
,
i
;
HRESULT
hr
;
BYTE
*
data
;
hr
=
IMemInputPin_ReceiveCanBlock
(
input
);
ok
(
hr
==
S_OK
,
"Got hr %#x.
\n
"
,
hr
);
hr
=
IMemInputPin_GetAllocator
(
input
,
&
allocator
);
ok
(
hr
==
S_OK
,
"Got hr %#x.
\n
"
,
hr
);
hr
=
IMediaControl_Pause
(
control
);
ok
(
hr
==
S_OK
,
"Got hr %#x.
\n
"
,
hr
);
hr
=
IMemAllocator_GetBuffer
(
allocator
,
&
sample
,
NULL
,
NULL
,
0
);
ok
(
hr
==
VFW_E_NOT_COMMITTED
,
"Got hr %#x.
\n
"
,
hr
);
hr
=
IMemAllocator_Commit
(
allocator
);
ok
(
hr
==
S_OK
,
"Got hr %#x.
\n
"
,
hr
);
hr
=
IMemAllocator_GetBuffer
(
allocator
,
&
sample
,
NULL
,
NULL
,
0
);
ok
(
hr
==
S_OK
,
"Got hr %#x.
\n
"
,
hr
);
hr
=
IMediaSample_GetPointer
(
sample
,
&
data
);
ok
(
hr
==
S_OK
,
"Got hr %#x.
\n
"
,
hr
);
size
=
IMediaSample_GetSize
(
sample
);
ok
(
size
==
256
,
"Got size %d.
\n
"
,
size
);
for
(
i
=
0
;
i
<
200
;
++
i
)
data
[
i
]
=
i
;
hr
=
IMediaSample_SetActualDataLength
(
sample
,
200
);
ok
(
hr
==
S_OK
,
"Got hr %#x.
\n
"
,
hr
);
start
=
10000
;
stop
=
20000
;
hr
=
IMediaSample_SetMediaTime
(
sample
,
&
start
,
&
stop
);
ok
(
hr
==
S_OK
,
"Got hr %#x.
\n
"
,
hr
);
hr
=
IMediaSample_SetPreroll
(
sample
,
TRUE
);
ok
(
hr
==
S_OK
,
"Got hr %#x.
\n
"
,
hr
);
testmode
=
0
;
hr
=
IMemInputPin_Receive
(
input
,
sample
);
ok
(
hr
==
S_OK
,
"Got hr %#x.
\n
"
,
hr
);
ok
(
got_ProcessInput
==
1
,
"Got %u calls to ProcessInput().
\n
"
,
got_ProcessInput
);
ok
(
got_ProcessOutput
==
1
,
"Got %u calls to ProcessOutput().
\n
"
,
got_ProcessOutput
);
ok
(
got_Receive
==
1
,
"Got %u calls to Receive().
\n
"
,
got_Receive
);
got_ProcessInput
=
got_ProcessOutput
=
got_Receive
=
0
;
start
=
20000
;
hr
=
IMediaSample_SetTime
(
sample
,
&
start
,
NULL
);
ok
(
hr
==
S_OK
,
"Got hr %#x.
\n
"
,
hr
);
testmode
=
1
;
hr
=
IMemInputPin_Receive
(
input
,
sample
);
ok
(
hr
==
S_OK
,
"Got hr %#x.
\n
"
,
hr
);
ok
(
got_ProcessInput
==
1
,
"Got %u calls to ProcessInput().
\n
"
,
got_ProcessInput
);
ok
(
got_ProcessOutput
==
1
,
"Got %u calls to ProcessOutput().
\n
"
,
got_ProcessOutput
);
ok
(
got_Receive
==
1
,
"Got %u calls to Receive().
\n
"
,
got_Receive
);
got_ProcessInput
=
got_ProcessOutput
=
got_Receive
=
0
;
stop
=
30000
;
hr
=
IMediaSample_SetTime
(
sample
,
&
start
,
&
stop
);
ok
(
hr
==
S_OK
,
"Got hr %#x.
\n
"
,
hr
);
testmode
=
2
;
hr
=
IMemInputPin_Receive
(
input
,
sample
);
ok
(
hr
==
S_OK
,
"Got hr %#x.
\n
"
,
hr
);
ok
(
got_ProcessInput
==
1
,
"Got %u calls to ProcessInput().
\n
"
,
got_ProcessInput
);
ok
(
got_ProcessOutput
==
1
,
"Got %u calls to ProcessOutput().
\n
"
,
got_ProcessOutput
);
ok
(
got_Receive
==
1
,
"Got %u calls to Receive().
\n
"
,
got_Receive
);
got_ProcessInput
=
got_ProcessOutput
=
got_Receive
=
0
;
testmode
=
3
;
hr
=
IMemInputPin_Receive
(
input
,
sample
);
ok
(
hr
==
S_OK
,
"Got hr %#x.
\n
"
,
hr
);
ok
(
got_ProcessInput
==
1
,
"Got %u calls to ProcessInput().
\n
"
,
got_ProcessInput
);
ok
(
got_ProcessOutput
==
2
,
"Got %u calls to ProcessOutput().
\n
"
,
got_ProcessOutput
);
ok
(
got_Receive
==
2
,
"Got %u calls to Receive().
\n
"
,
got_Receive
);
got_ProcessInput
=
got_ProcessOutput
=
got_Receive
=
0
;
testmode
=
5
;
hr
=
IMemInputPin_Receive
(
input
,
sample
);
ok
(
hr
==
S_OK
,
"Got hr %#x.
\n
"
,
hr
);
ok
(
got_ProcessInput
==
1
,
"Got %u calls to ProcessInput().
\n
"
,
got_ProcessInput
);
ok
(
got_ProcessOutput
==
1
,
"Got %u calls to ProcessOutput().
\n
"
,
got_ProcessOutput
);
ok
(
!
got_Receive
,
"Got %u calls to Receive().
\n
"
,
got_Receive
);
got_ProcessInput
=
got_ProcessOutput
=
got_Receive
=
0
;
hr
=
IMediaSample_SetSyncPoint
(
sample
,
TRUE
);
ok
(
hr
==
S_OK
,
"Got hr %#x.
\n
"
,
hr
);
testmode
=
6
;
hr
=
IMemInputPin_Receive
(
input
,
sample
);
ok
(
hr
==
S_OK
,
"Got hr %#x.
\n
"
,
hr
);
ok
(
got_ProcessInput
==
1
,
"Got %u calls to ProcessInput().
\n
"
,
got_ProcessInput
);
ok
(
got_ProcessOutput
==
1
,
"Got %u calls to ProcessOutput().
\n
"
,
got_ProcessOutput
);
ok
(
got_Receive
==
1
,
"Got %u calls to Receive().
\n
"
,
got_Receive
);
got_ProcessInput
=
got_ProcessOutput
=
got_Receive
=
0
;
hr
=
IMediaSample_SetSyncPoint
(
sample
,
FALSE
);
ok
(
hr
==
S_OK
,
"Got hr %#x.
\n
"
,
hr
);
testmode
=
7
;
hr
=
IMemInputPin_Receive
(
input
,
sample
);
ok
(
hr
==
S_OK
,
"Got hr %#x.
\n
"
,
hr
);
ok
(
got_ProcessInput
==
1
,
"Got %u calls to ProcessInput().
\n
"
,
got_ProcessInput
);
ok
(
got_ProcessOutput
==
1
,
"Got %u calls to ProcessOutput().
\n
"
,
got_ProcessOutput
);
ok
(
got_Receive
==
1
,
"Got %u calls to Receive().
\n
"
,
got_Receive
);
got_ProcessInput
=
got_ProcessOutput
=
got_Receive
=
0
;
testmode
=
8
;
hr
=
IMemInputPin_Receive
(
input
,
sample
);
ok
(
hr
==
S_OK
,
"Got hr %#x.
\n
"
,
hr
);
ok
(
got_ProcessInput
==
1
,
"Got %u calls to ProcessInput().
\n
"
,
got_ProcessInput
);
ok
(
got_ProcessOutput
==
1
,
"Got %u calls to ProcessOutput().
\n
"
,
got_ProcessOutput
);
ok
(
got_Receive
==
1
,
"Got %u calls to Receive().
\n
"
,
got_Receive
);
got_ProcessInput
=
got_ProcessOutput
=
got_Receive
=
0
;
testmode
=
9
;
hr
=
IMemInputPin_Receive
(
input
,
sample
);
ok
(
hr
==
S_OK
,
"Got hr %#x.
\n
"
,
hr
);
ok
(
got_ProcessInput
==
1
,
"Got %u calls to ProcessInput().
\n
"
,
got_ProcessInput
);
ok
(
got_ProcessOutput
==
1
,
"Got %u calls to ProcessOutput().
\n
"
,
got_ProcessOutput
);
ok
(
got_Receive
==
1
,
"Got %u calls to Receive().
\n
"
,
got_Receive
);
got_ProcessInput
=
got_ProcessOutput
=
got_Receive
=
0
;
hr
=
IMediaSample_SetDiscontinuity
(
sample
,
TRUE
);
ok
(
hr
==
S_OK
,
"Got hr %#x.
\n
"
,
hr
);
ok
(
!
got_Discontinuity
,
"Got %u calls to Discontinuity().
\n
"
,
got_Discontinuity
);
testmode
=
10
;
hr
=
IMemInputPin_Receive
(
input
,
sample
);
ok
(
hr
==
S_OK
,
"Got hr %#x.
\n
"
,
hr
);
ok
(
got_ProcessInput
==
1
,
"Got %u calls to ProcessInput().
\n
"
,
got_ProcessInput
);
ok
(
got_ProcessOutput
==
2
,
"Got %u calls to ProcessOutput().
\n
"
,
got_ProcessOutput
);
ok
(
got_Receive
==
2
,
"Got %u calls to Receive().
\n
"
,
got_Receive
);
ok
(
got_Discontinuity
==
1
,
"Got %u calls to Discontinuity().
\n
"
,
got_Discontinuity
);
got_ProcessInput
=
got_ProcessOutput
=
got_Receive
=
0
;
hr
=
IMediaControl_Stop
(
control
);
ok
(
hr
==
S_OK
,
"Got hr %#x.
\n
"
,
hr
);
IMediaSample_Release
(
sample
);
IMemAllocator_Release
(
allocator
);
}
static
void
test_connect_pin
(
void
)
{
AM_MEDIA_TYPE
req_mt
=
...
...
@@ -1366,6 +1692,9 @@ static void test_connect_pin(void)
ok
(
testdmo_output_mt_set
,
"Ouput type should be set.
\n
"
);
ok
(
compare_media_types
(
&
testdmo_output_mt
,
&
req_mt
),
"Media types didn't match.
\n
"
);
test_filter_state
(
control
);
test_sample_processing
(
control
,
meminput
);
hr
=
IFilterGraph2_Disconnect
(
graph
,
source
);
ok
(
hr
==
S_OK
,
"Got hr %#x.
\n
"
,
hr
);
hr
=
IFilterGraph2_Disconnect
(
graph
,
source
);
...
...
@@ -1383,8 +1712,6 @@ static void test_connect_pin(void)
ok
(
!
testdmo_output_mt_set
,
"Output type should not be set.
\n
"
);
test_filter_state
(
control
);
req_mt
.
lSampleSize
=
0
;
hr
=
IFilterGraph2_ConnectDirect
(
graph
,
source
,
&
testsink
.
sink
.
pin
.
IPin_iface
,
&
req_mt
);
ok
(
hr
==
VFW_E_TYPE_NOT_ACCEPTED
,
"Got hr %#x.
\n
"
,
hr
);
...
...
include/mediaobj.idl
View file @
ed8d3d32
...
...
@@ -87,6 +87,23 @@ interface IMediaBuffer : IUnknown
)
;
}
enum
_DMO_INPUT_STATUS_FLAGS
{
DMO_INPUT_STATUSF_ACCEPT_DATA
=
0
x00000001
,
}
;
enum
_DMO_INPUT_DATA_BUFFER_FLAGS
{
DMO_INPUT_DATA_BUFFERF_SYNCPOINT
=
0
x00000001
,
DMO_INPUT_DATA_BUFFERF_TIME
=
0
x00000002
,
DMO_INPUT_DATA_BUFFERF_TIMELENGTH
=
0
x00000004
,
}
;
enum
_DMO_PROCESS_OUTPUT_FLAGS
{
DMO_PROCESS_OUTPUT_DISCARD_WHEN_NO_BUFFER
=
0
x00000001
,
}
;
typedef
struct
_DMO_OUTPUT_DATA_BUFFER
{
IMediaBuffer
*
pBuffer
;
DWORD
dwStatus
;
...
...
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