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
1946c2dc
Commit
1946c2dc
authored
Jul 26, 2023
by
Ziqing Hui
Committed by
Alexandre Julliard
Aug 14, 2023
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
winegstreamer: Add async command handling to media sink.
parent
21729200
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
265 additions
and
11 deletions
+265
-11
media_sink.c
dlls/winegstreamer/media_sink.c
+265
-11
No files found.
dlls/winegstreamer/media_sink.c
View file @
1946c2dc
...
...
@@ -26,6 +26,21 @@
WINE_DEFAULT_DEBUG_CHANNEL
(
mfplat
);
enum
async_op
{
ASYNC_START
,
ASYNC_STOP
,
ASYNC_PAUSE
,
};
struct
async_command
{
IUnknown
IUnknown_iface
;
LONG
refcount
;
enum
async_op
op
;
};
struct
stream_sink
{
IMFStreamSink
IMFStreamSink_iface
;
...
...
@@ -45,9 +60,18 @@ struct media_sink
IMFFinalizableMediaSink
IMFFinalizableMediaSink_iface
;
IMFMediaEventGenerator
IMFMediaEventGenerator_iface
;
IMFClockStateSink
IMFClockStateSink_iface
;
IMFAsyncCallback
async_callback
;
LONG
refcount
;
CRITICAL_SECTION
cs
;
bool
shutdown
;
enum
{
STATE_OPENED
,
STATE_STARTED
,
STATE_STOPPED
,
STATE_PAUSED
,
STATE_SHUTDOWN
,
}
state
;
IMFByteStream
*
bytestream
;
IMFMediaEventQueue
*
event_queue
;
...
...
@@ -80,6 +104,71 @@ static struct media_sink *impl_from_IMFClockStateSink(IMFClockStateSink *iface)
return
CONTAINING_RECORD
(
iface
,
struct
media_sink
,
IMFClockStateSink_iface
);
}
static
struct
media_sink
*
impl_from_async_callback
(
IMFAsyncCallback
*
iface
)
{
return
CONTAINING_RECORD
(
iface
,
struct
media_sink
,
async_callback
);
}
static
struct
async_command
*
impl_from_async_command_IUnknown
(
IUnknown
*
iface
)
{
return
CONTAINING_RECORD
(
iface
,
struct
async_command
,
IUnknown_iface
);
}
static
HRESULT
WINAPI
async_command_QueryInterface
(
IUnknown
*
iface
,
REFIID
riid
,
void
**
obj
)
{
if
(
IsEqualIID
(
riid
,
&
IID_IUnknown
))
{
*
obj
=
iface
;
IUnknown_AddRef
(
iface
);
return
S_OK
;
}
WARN
(
"Unsupported interface %s.
\n
"
,
debugstr_guid
(
riid
));
*
obj
=
NULL
;
return
E_NOINTERFACE
;
}
static
ULONG
WINAPI
async_command_AddRef
(
IUnknown
*
iface
)
{
struct
async_command
*
command
=
impl_from_async_command_IUnknown
(
iface
);
return
InterlockedIncrement
(
&
command
->
refcount
);
}
static
ULONG
WINAPI
async_command_Release
(
IUnknown
*
iface
)
{
struct
async_command
*
command
=
impl_from_async_command_IUnknown
(
iface
);
ULONG
refcount
=
InterlockedDecrement
(
&
command
->
refcount
);
if
(
!
refcount
)
free
(
command
);
return
refcount
;
}
static
const
IUnknownVtbl
async_command_vtbl
=
{
async_command_QueryInterface
,
async_command_AddRef
,
async_command_Release
,
};
static
HRESULT
async_command_create
(
enum
async_op
op
,
struct
async_command
**
out
)
{
struct
async_command
*
command
;
if
(
!
(
command
=
calloc
(
1
,
sizeof
(
*
command
))))
return
E_OUTOFMEMORY
;
command
->
IUnknown_iface
.
lpVtbl
=
&
async_command_vtbl
;
command
->
refcount
=
1
;
command
->
op
=
op
;
TRACE
(
"Created async command %p.
\n
"
,
command
);
*
out
=
command
;
return
S_OK
;
}
static
HRESULT
WINAPI
stream_sink_QueryInterface
(
IMFStreamSink
*
iface
,
REFIID
riid
,
void
**
obj
)
{
struct
stream_sink
*
stream_sink
=
impl_from_IMFStreamSink
(
iface
);
...
...
@@ -377,6 +466,53 @@ static struct stream_sink *media_sink_get_stream_sink_by_id(struct media_sink *m
return
NULL
;
}
static
HRESULT
media_sink_queue_command
(
struct
media_sink
*
media_sink
,
enum
async_op
op
)
{
struct
async_command
*
command
;
HRESULT
hr
;
if
(
media_sink
->
state
==
STATE_SHUTDOWN
)
return
MF_E_SHUTDOWN
;
if
(
FAILED
(
hr
=
async_command_create
(
op
,
&
command
)))
return
hr
;
return
MFPutWorkItem
(
MFASYNC_CALLBACK_QUEUE_STANDARD
,
&
media_sink
->
async_callback
,
&
command
->
IUnknown_iface
);
}
static
HRESULT
media_sink_queue_stream_event
(
struct
media_sink
*
media_sink
,
MediaEventType
type
)
{
struct
stream_sink
*
stream_sink
;
HRESULT
hr
;
LIST_FOR_EACH_ENTRY
(
stream_sink
,
&
media_sink
->
stream_sinks
,
struct
stream_sink
,
entry
)
{
if
(
FAILED
(
hr
=
IMFMediaEventQueue_QueueEventParamVar
(
stream_sink
->
event_queue
,
type
,
&
GUID_NULL
,
S_OK
,
NULL
)))
return
hr
;
}
return
S_OK
;
}
static
HRESULT
media_sink_start
(
struct
media_sink
*
media_sink
)
{
media_sink
->
state
=
STATE_STARTED
;
return
media_sink_queue_stream_event
(
media_sink
,
MEStreamSinkStarted
);
}
static
HRESULT
media_sink_stop
(
struct
media_sink
*
media_sink
)
{
media_sink
->
state
=
STATE_STOPPED
;
return
media_sink_queue_stream_event
(
media_sink
,
MEStreamSinkStopped
);
}
static
HRESULT
media_sink_pause
(
struct
media_sink
*
media_sink
)
{
media_sink
->
state
=
STATE_PAUSED
;
return
media_sink_queue_stream_event
(
media_sink
,
MEStreamSinkPaused
);
}
static
HRESULT
WINAPI
media_sink_QueryInterface
(
IMFFinalizableMediaSink
*
iface
,
REFIID
riid
,
void
**
obj
)
{
struct
media_sink
*
media_sink
=
impl_from_IMFFinalizableMediaSink
(
iface
);
...
...
@@ -532,7 +668,7 @@ static HRESULT WINAPI media_sink_Shutdown(IMFFinalizableMediaSink *iface)
EnterCriticalSection
(
&
media_sink
->
cs
);
if
(
media_sink
->
s
hutdown
)
if
(
media_sink
->
s
tate
==
STATE_SHUTDOWN
)
{
LeaveCriticalSection
(
&
media_sink
->
cs
);
return
MF_E_SHUTDOWN
;
...
...
@@ -548,7 +684,7 @@ static HRESULT WINAPI media_sink_Shutdown(IMFFinalizableMediaSink *iface)
IMFMediaEventQueue_Shutdown
(
media_sink
->
event_queue
);
IMFByteStream_Close
(
media_sink
->
bytestream
);
media_sink
->
s
hutdown
=
TRUE
;
media_sink
->
s
tate
=
STATE_SHUTDOWN
;
LeaveCriticalSection
(
&
media_sink
->
cs
);
...
...
@@ -676,30 +812,62 @@ static ULONG WINAPI media_sink_clock_sink_Release(IMFClockStateSink *iface)
static
HRESULT
WINAPI
media_sink_clock_sink_OnClockStart
(
IMFClockStateSink
*
iface
,
MFTIME
systime
,
LONGLONG
offset
)
{
FIXME
(
"iface %p, systime %s, offset %s stub!
\n
"
,
iface
,
debugstr_time
(
systime
),
debugstr_time
(
offset
));
struct
media_sink
*
media_sink
=
impl_from_IMFClockStateSink
(
iface
);
HRESULT
hr
;
return
E_NOTIMPL
;
TRACE
(
"iface %p, systime %s, offset %s.
\n
"
,
iface
,
debugstr_time
(
systime
),
debugstr_time
(
offset
));
EnterCriticalSection
(
&
media_sink
->
cs
);
hr
=
media_sink_queue_command
(
media_sink
,
ASYNC_START
);
LeaveCriticalSection
(
&
media_sink
->
cs
);
return
hr
;
}
static
HRESULT
WINAPI
media_sink_clock_sink_OnClockStop
(
IMFClockStateSink
*
iface
,
MFTIME
systime
)
{
FIXME
(
"iface %p, systime %s stub!
\n
"
,
iface
,
debugstr_time
(
systime
));
struct
media_sink
*
media_sink
=
impl_from_IMFClockStateSink
(
iface
);
HRESULT
hr
;
return
E_NOTIMPL
;
TRACE
(
"iface %p, systime %s.
\n
"
,
iface
,
debugstr_time
(
systime
));
EnterCriticalSection
(
&
media_sink
->
cs
);
hr
=
media_sink_queue_command
(
media_sink
,
ASYNC_STOP
);
LeaveCriticalSection
(
&
media_sink
->
cs
);
return
hr
;
}
static
HRESULT
WINAPI
media_sink_clock_sink_OnClockPause
(
IMFClockStateSink
*
iface
,
MFTIME
systime
)
{
FIXME
(
"%p, %s stub!
\n
"
,
iface
,
debugstr_time
(
systime
));
struct
media_sink
*
media_sink
=
impl_from_IMFClockStateSink
(
iface
);
HRESULT
hr
;
return
E_NOTIMPL
;
TRACE
(
"iface %p, systime %s.
\n
"
,
iface
,
debugstr_time
(
systime
));
EnterCriticalSection
(
&
media_sink
->
cs
);
hr
=
media_sink_queue_command
(
media_sink
,
ASYNC_PAUSE
);
LeaveCriticalSection
(
&
media_sink
->
cs
);
return
hr
;
}
static
HRESULT
WINAPI
media_sink_clock_sink_OnClockRestart
(
IMFClockStateSink
*
iface
,
MFTIME
systime
)
{
FIXME
(
"iface %p, systime %s stub!
\n
"
,
iface
,
debugstr_time
(
systime
));
struct
media_sink
*
media_sink
=
impl_from_IMFClockStateSink
(
iface
);
HRESULT
hr
;
return
E_NOTIMPL
;
TRACE
(
"iface %p, systime %s.
\n
"
,
iface
,
debugstr_time
(
systime
));
EnterCriticalSection
(
&
media_sink
->
cs
);
hr
=
media_sink_queue_command
(
media_sink
,
ASYNC_START
);
LeaveCriticalSection
(
&
media_sink
->
cs
);
return
hr
;
}
static
HRESULT
WINAPI
media_sink_clock_sink_OnClockSetRate
(
IMFClockStateSink
*
iface
,
MFTIME
systime
,
float
rate
)
...
...
@@ -721,6 +889,90 @@ static const IMFClockStateSinkVtbl media_sink_clock_sink_vtbl =
media_sink_clock_sink_OnClockSetRate
,
};
static
HRESULT
WINAPI
media_sink_callback_QueryInterface
(
IMFAsyncCallback
*
iface
,
REFIID
riid
,
void
**
obj
)
{
TRACE
(
"iface %p, riid %s, obj %p.
\n
"
,
iface
,
debugstr_guid
(
riid
),
obj
);
if
(
IsEqualIID
(
riid
,
&
IID_IMFAsyncCallback
)
||
IsEqualIID
(
riid
,
&
IID_IUnknown
))
{
*
obj
=
iface
;
IMFAsyncCallback_AddRef
(
iface
);
return
S_OK
;
}
WARN
(
"Unsupported interface %s.
\n
"
,
debugstr_guid
(
riid
));
*
obj
=
NULL
;
return
E_NOINTERFACE
;
}
static
ULONG
WINAPI
media_sink_callback_AddRef
(
IMFAsyncCallback
*
iface
)
{
struct
media_sink
*
sink
=
impl_from_async_callback
(
iface
);
return
IMFFinalizableMediaSink_AddRef
(
&
sink
->
IMFFinalizableMediaSink_iface
);
}
static
ULONG
WINAPI
media_sink_callback_Release
(
IMFAsyncCallback
*
iface
)
{
struct
media_sink
*
sink
=
impl_from_async_callback
(
iface
);
return
IMFFinalizableMediaSink_Release
(
&
sink
->
IMFFinalizableMediaSink_iface
);
}
static
HRESULT
WINAPI
media_sink_callback_GetParameters
(
IMFAsyncCallback
*
iface
,
DWORD
*
flags
,
DWORD
*
queue
)
{
TRACE
(
"iface %p, flags %p, queue %p.
\n
"
,
iface
,
flags
,
queue
);
return
E_NOTIMPL
;
}
static
HRESULT
WINAPI
media_sink_callback_Invoke
(
IMFAsyncCallback
*
iface
,
IMFAsyncResult
*
async_result
)
{
struct
media_sink
*
media_sink
=
impl_from_async_callback
(
iface
);
struct
async_command
*
command
;
HRESULT
hr
=
E_FAIL
;
IUnknown
*
state
;
TRACE
(
"iface %p, async_result %p.
\n
"
,
iface
,
async_result
);
EnterCriticalSection
(
&
media_sink
->
cs
);
if
(
!
(
state
=
IMFAsyncResult_GetStateNoAddRef
(
async_result
)))
{
LeaveCriticalSection
(
&
media_sink
->
cs
);
return
hr
;
}
command
=
impl_from_async_command_IUnknown
(
state
);
switch
(
command
->
op
)
{
case
ASYNC_START
:
hr
=
media_sink_start
(
media_sink
);
break
;
case
ASYNC_STOP
:
hr
=
media_sink_stop
(
media_sink
);
break
;
case
ASYNC_PAUSE
:
hr
=
media_sink_pause
(
media_sink
);
break
;
default:
WARN
(
"Unsupported op %u.
\n
"
,
command
->
op
);
break
;
}
LeaveCriticalSection
(
&
media_sink
->
cs
);
return
hr
;
}
static
const
IMFAsyncCallbackVtbl
media_sink_callback_vtbl
=
{
media_sink_callback_QueryInterface
,
media_sink_callback_AddRef
,
media_sink_callback_Release
,
media_sink_callback_GetParameters
,
media_sink_callback_Invoke
,
};
static
HRESULT
media_sink_create
(
IMFByteStream
*
bytestream
,
struct
media_sink
**
out
)
{
struct
media_sink
*
media_sink
;
...
...
@@ -743,7 +995,9 @@ static HRESULT media_sink_create(IMFByteStream *bytestream, struct media_sink **
media_sink
->
IMFFinalizableMediaSink_iface
.
lpVtbl
=
&
media_sink_vtbl
;
media_sink
->
IMFMediaEventGenerator_iface
.
lpVtbl
=
&
media_sink_event_vtbl
;
media_sink
->
IMFClockStateSink_iface
.
lpVtbl
=
&
media_sink_clock_sink_vtbl
;
media_sink
->
async_callback
.
lpVtbl
=
&
media_sink_callback_vtbl
;
media_sink
->
refcount
=
1
;
media_sink
->
state
=
STATE_OPENED
;
InitializeCriticalSection
(
&
media_sink
->
cs
);
media_sink
->
cs
.
DebugInfo
->
Spare
[
0
]
=
(
DWORD_PTR
)(
__FILE__
": cs"
);
IMFByteStream_AddRef
((
media_sink
->
bytestream
=
bytestream
));
...
...
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