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
c40ab0f9
Commit
c40ab0f9
authored
Jun 06, 2022
by
Rémi Bernon
Committed by
Alexandre Julliard
Jun 09, 2022
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
winegstreamer: Support zero-copy in wg_transform_push_data.
Signed-off-by:
Rémi Bernon
<
rbernon@codeweavers.com
>
parent
f17b8010
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
153 additions
and
15 deletions
+153
-15
mf.c
dlls/mf/tests/mf.c
+0
-1
gst_private.h
dlls/winegstreamer/gst_private.h
+8
-1
h264_decoder.c
dlls/winegstreamer/h264_decoder.c
+13
-4
mfplat.c
dlls/winegstreamer/mfplat.c
+84
-3
quartz_transform.c
dlls/winegstreamer/quartz_transform.c
+9
-0
unixlib.h
dlls/winegstreamer/unixlib.h
+2
-0
wg_transform.c
dlls/winegstreamer/wg_transform.c
+25
-3
wma_decoder.c
dlls/winegstreamer/wma_decoder.c
+12
-3
No files found.
dlls/mf/tests/mf.c
View file @
c40ab0f9
...
...
@@ -6423,7 +6423,6 @@ static void test_wma_decoder(void)
hr
=
IMFTransform_ProcessInput
(
transform
,
0
,
sample
,
0
);
ok
(
hr
==
MF_E_NOTACCEPTING
,
"ProcessInput returned %#lx
\n
"
,
hr
);
ret
=
IMFSample_Release
(
sample
);
todo_wine
ok
(
ret
==
1
,
"Release returned %lu
\n
"
,
ret
);
/* As output_info.dwFlags doesn't have MFT_OUTPUT_STREAM_CAN_PROVIDE_SAMPLES
...
...
dlls/winegstreamer/gst_private.h
View file @
c40ab0f9
...
...
@@ -64,6 +64,12 @@ static inline const char *debugstr_time(REFERENCE_TIME time)
#define MEDIATIME_FROM_BYTES(x) ((LONGLONG)(x) * 10000000)
struct
wg_sample_queue
;
HRESULT
wg_sample_queue_create
(
struct
wg_sample_queue
**
out
);
void
wg_sample_queue_destroy
(
struct
wg_sample_queue
*
queue
);
void
wg_sample_queue_flush
(
struct
wg_sample_queue
*
queue
,
bool
all
);
struct
wg_parser
*
wg_parser_create
(
enum
wg_parser_type
type
,
bool
unlimited_buffering
);
void
wg_parser_destroy
(
struct
wg_parser
*
parser
);
...
...
@@ -123,7 +129,8 @@ void mf_media_type_to_wg_format(IMFMediaType *type, struct wg_format *format);
HRESULT
wg_sample_create_mf
(
IMFSample
*
sample
,
struct
wg_sample
**
out
);
void
wg_sample_release
(
struct
wg_sample
*
wg_sample
);
HRESULT
wg_transform_push_mf
(
struct
wg_transform
*
transform
,
struct
wg_sample
*
sample
);
HRESULT
wg_transform_push_mf
(
struct
wg_transform
*
transform
,
struct
wg_sample
*
sample
,
struct
wg_sample_queue
*
queue
);
HRESULT
wg_transform_read_mf
(
struct
wg_transform
*
transform
,
struct
wg_sample
*
sample
,
struct
wg_format
*
format
);
...
...
dlls/winegstreamer/h264_decoder.c
View file @
c40ab0f9
...
...
@@ -52,6 +52,7 @@ struct h264_decoder
struct
wg_format
wg_format
;
struct
wg_transform
*
wg_transform
;
struct
wg_sample_queue
*
wg_sample_queue
;
};
static
struct
h264_decoder
*
impl_from_IMFTransform
(
IMFTransform
*
iface
)
...
...
@@ -237,6 +238,8 @@ static ULONG WINAPI transform_Release(IMFTransform *iface)
IMFMediaType_Release
(
decoder
->
input_type
);
if
(
decoder
->
output_type
)
IMFMediaType_Release
(
decoder
->
output_type
);
wg_sample_queue_destroy
(
decoder
->
wg_sample_queue
);
free
(
decoder
);
}
...
...
@@ -543,9 +546,7 @@ static HRESULT WINAPI transform_ProcessInput(IMFTransform *iface, DWORD id, IMFS
if
(
FAILED
(
hr
=
wg_sample_create_mf
(
sample
,
&
wg_sample
)))
return
hr
;
hr
=
wg_transform_push_mf
(
decoder
->
wg_transform
,
wg_sample
);
wg_sample_release
(
wg_sample
);
return
hr
;
return
wg_transform_push_mf
(
decoder
->
wg_transform
,
wg_sample
,
decoder
->
wg_sample_queue
);
}
static
HRESULT
WINAPI
transform_ProcessOutput
(
IMFTransform
*
iface
,
DWORD
flags
,
DWORD
count
,
...
...
@@ -582,7 +583,8 @@ static HRESULT WINAPI transform_ProcessOutput(IMFTransform *iface, DWORD flags,
return
MF_E_BUFFERTOOSMALL
;
}
hr
=
wg_transform_read_mf
(
decoder
->
wg_transform
,
wg_sample
,
&
wg_format
);
if
(
SUCCEEDED
(
hr
=
wg_transform_read_mf
(
decoder
->
wg_transform
,
wg_sample
,
&
wg_format
)))
wg_sample_queue_flush
(
decoder
->
wg_sample_queue
,
false
);
wg_sample_release
(
wg_sample
);
if
(
hr
==
MF_E_TRANSFORM_STREAM_CHANGE
)
...
...
@@ -648,6 +650,7 @@ HRESULT h264_decoder_create(REFIID riid, void **ret)
static
const
struct
wg_format
input_format
=
{.
major_type
=
WG_MAJOR_TYPE_H264
};
struct
wg_transform
*
transform
;
struct
h264_decoder
*
decoder
;
HRESULT
hr
;
TRACE
(
"riid %s, ret %p.
\n
"
,
debugstr_guid
(
riid
),
ret
);
...
...
@@ -669,6 +672,12 @@ HRESULT h264_decoder_create(REFIID riid, void **ret)
decoder
->
wg_format
.
u
.
video
.
fps_n
=
30000
;
decoder
->
wg_format
.
u
.
video
.
fps_d
=
1001
;
if
(
FAILED
(
hr
=
wg_sample_queue_create
(
&
decoder
->
wg_sample_queue
)))
{
free
(
decoder
);
return
hr
;
}
*
ret
=
&
decoder
->
IMFTransform_iface
;
TRACE
(
"Created decoder %p
\n
"
,
*
ret
);
return
S_OK
;
...
...
dlls/winegstreamer/mfplat.c
View file @
c40ab0f9
...
...
@@ -26,6 +26,7 @@
#include "mfapi.h"
#include "wine/debug.h"
#include "wine/list.h"
WINE_DEFAULT_DEBUG_CHANNEL
(
mfplat
);
...
...
@@ -958,11 +959,18 @@ void mf_media_type_to_wg_format(IMFMediaType *type, struct wg_format *format)
FIXME
(
"Unrecognized major type %s.
\n
"
,
debugstr_guid
(
&
major_type
));
}
struct
wg_sample_queue
{
CRITICAL_SECTION
cs
;
struct
list
samples
;
};
struct
mf_sample
{
IMFSample
*
sample
;
IMFMediaBuffer
*
media_buffer
;
struct
wg_sample
wg_sample
;
struct
list
entry
;
};
HRESULT
wg_sample_create_mf
(
IMFSample
*
sample
,
struct
wg_sample
**
out
)
...
...
@@ -1008,14 +1016,83 @@ void wg_sample_release(struct wg_sample *wg_sample)
IMFMediaBuffer_Unlock
(
mf_sample
->
media_buffer
);
IMFMediaBuffer_Release
(
mf_sample
->
media_buffer
);
IMFSample_Release
(
mf_sample
->
sample
);
free
(
mf_sample
);
}
HRESULT
wg_transform_push_mf
(
struct
wg_transform
*
transform
,
struct
wg_sample
*
sample
)
static
void
wg_sample_queue_begin_append
(
struct
wg_sample_queue
*
queue
,
struct
wg_sample
*
wg_sample
)
{
struct
mf_sample
*
mf_sample
=
CONTAINING_RECORD
(
wg_sample
,
struct
mf_sample
,
wg_sample
);
/* make sure a concurrent wg_sample_queue_flush call won't release the sample until we're done */
InterlockedIncrement
(
&
wg_sample
->
refcount
);
mf_sample
->
wg_sample
.
flags
|=
WG_SAMPLE_FLAG_HAS_REFCOUNT
;
EnterCriticalSection
(
&
queue
->
cs
);
list_add_tail
(
&
queue
->
samples
,
&
mf_sample
->
entry
);
LeaveCriticalSection
(
&
queue
->
cs
);
}
static
void
wg_sample_queue_end_append
(
struct
wg_sample_queue
*
queue
,
struct
wg_sample
*
wg_sample
)
{
/* release temporary ref taken in wg_sample_queue_begin_append */
InterlockedDecrement
(
&
wg_sample
->
refcount
);
wg_sample_queue_flush
(
queue
,
false
);
}
void
wg_sample_queue_flush
(
struct
wg_sample_queue
*
queue
,
bool
all
)
{
struct
mf_sample
*
mf_sample
,
*
next
;
EnterCriticalSection
(
&
queue
->
cs
);
LIST_FOR_EACH_ENTRY_SAFE
(
mf_sample
,
next
,
&
queue
->
samples
,
struct
mf_sample
,
entry
)
{
if
(
!
InterlockedOr
(
&
mf_sample
->
wg_sample
.
refcount
,
0
)
||
all
)
{
list_remove
(
&
mf_sample
->
entry
);
wg_sample_release
(
&
mf_sample
->
wg_sample
);
}
}
LeaveCriticalSection
(
&
queue
->
cs
);
}
HRESULT
wg_sample_queue_create
(
struct
wg_sample_queue
**
out
)
{
struct
mf_sample
*
mf_sample
=
CONTAINING_RECORD
(
sample
,
struct
mf_sample
,
wg_sample
);
struct
wg_sample_queue
*
queue
;
if
(
!
(
queue
=
calloc
(
1
,
sizeof
(
*
queue
))))
return
E_OUTOFMEMORY
;
InitializeCriticalSection
(
&
queue
->
cs
);
queue
->
cs
.
DebugInfo
->
Spare
[
0
]
=
(
DWORD_PTR
)(
__FILE__
": cs"
);
list_init
(
&
queue
->
samples
);
TRACE
(
"Created sample queue %p
\n
"
,
queue
);
*
out
=
queue
;
return
S_OK
;
}
void
wg_sample_queue_destroy
(
struct
wg_sample_queue
*
queue
)
{
wg_sample_queue_flush
(
queue
,
true
);
queue
->
cs
.
DebugInfo
->
Spare
[
0
]
=
0
;
InitializeCriticalSection
(
&
queue
->
cs
);
free
(
queue
);
}
HRESULT
wg_transform_push_mf
(
struct
wg_transform
*
transform
,
struct
wg_sample
*
wg_sample
,
struct
wg_sample_queue
*
queue
)
{
struct
mf_sample
*
mf_sample
=
CONTAINING_RECORD
(
wg_sample
,
struct
mf_sample
,
wg_sample
);
LONGLONG
time
,
duration
;
UINT32
value
;
HRESULT
hr
;
if
(
SUCCEEDED
(
IMFSample_GetSampleTime
(
mf_sample
->
sample
,
&
time
)))
{
...
...
@@ -1030,7 +1107,11 @@ HRESULT wg_transform_push_mf(struct wg_transform *transform, struct wg_sample *s
if
(
SUCCEEDED
(
IMFSample_GetUINT32
(
mf_sample
->
sample
,
&
MFSampleExtension_CleanPoint
,
&
value
))
&&
value
)
mf_sample
->
wg_sample
.
flags
|=
WG_SAMPLE_FLAG_SYNC_POINT
;
return
wg_transform_push_data
(
transform
,
sample
);
wg_sample_queue_begin_append
(
queue
,
wg_sample
);
hr
=
wg_transform_push_data
(
transform
,
wg_sample
);
wg_sample_queue_end_append
(
queue
,
wg_sample
);
return
hr
;
}
HRESULT
wg_transform_read_mf
(
struct
wg_transform
*
transform
,
struct
wg_sample
*
wg_sample
,
...
...
dlls/winegstreamer/quartz_transform.c
View file @
c40ab0f9
...
...
@@ -40,6 +40,7 @@ struct transform
IQualityControl
*
qc_sink
;
struct
wg_transform
*
transform
;
struct
wg_sample_queue
*
sample_queue
;
const
struct
transform_ops
*
ops
;
};
...
...
@@ -76,6 +77,7 @@ static void transform_destroy(struct strmbase_filter *iface)
strmbase_sink_cleanup
(
&
filter
->
sink
);
strmbase_filter_cleanup
(
&
filter
->
filter
);
wg_sample_queue_destroy
(
filter
->
sample_queue
);
free
(
filter
);
}
...
...
@@ -572,11 +574,18 @@ static const IQualityControlVtbl source_quality_control_vtbl =
static
HRESULT
transform_create
(
IUnknown
*
outer
,
const
CLSID
*
clsid
,
const
struct
transform_ops
*
ops
,
struct
transform
**
out
)
{
struct
transform
*
object
;
HRESULT
hr
;
object
=
calloc
(
1
,
sizeof
(
*
object
));
if
(
!
object
)
return
E_OUTOFMEMORY
;
if
(
FAILED
(
hr
=
wg_sample_queue_create
(
&
object
->
sample_queue
)))
{
free
(
object
);
return
hr
;
}
strmbase_filter_init
(
&
object
->
filter
,
outer
,
clsid
,
&
filter_ops
);
strmbase_sink_init
(
&
object
->
sink
,
&
object
->
filter
,
L"In"
,
&
sink_ops
,
NULL
);
strmbase_source_init
(
&
object
->
source
,
&
object
->
filter
,
L"Out"
,
&
source_ops
);
...
...
dlls/winegstreamer/unixlib.h
View file @
c40ab0f9
...
...
@@ -121,6 +121,8 @@ enum wg_sample_flag
WG_SAMPLE_FLAG_HAS_PTS
=
2
,
WG_SAMPLE_FLAG_HAS_DURATION
=
4
,
WG_SAMPLE_FLAG_SYNC_POINT
=
8
,
WG_SAMPLE_FLAG_HAS_REFCOUNT
=
0x10000
,
/* sample is queued on the client side and may be wrapped */
};
struct
wg_sample
...
...
dlls/winegstreamer/wg_transform.c
View file @
c40ab0f9
...
...
@@ -519,6 +519,13 @@ out:
return
status
;
}
static
void
wg_sample_free_notify
(
void
*
arg
)
{
struct
wg_sample
*
sample
=
arg
;
GST_DEBUG
(
"Releasing wg_sample %p"
,
sample
);
InterlockedDecrement
(
&
sample
->
refcount
);
}
NTSTATUS
wg_transform_push_data
(
void
*
args
)
{
struct
wg_transform_push_data_params
*
params
=
args
;
...
...
@@ -535,12 +542,28 @@ NTSTATUS wg_transform_push_data(void *args)
return
STATUS_SUCCESS
;
}
if
(
!
(
buffer
=
gst_buffer_new_and_alloc
(
sample
->
size
)))
if
(
!
(
sample
->
flags
&
WG_SAMPLE_FLAG_HAS_REFCOUNT
))
{
if
(
!
(
buffer
=
gst_buffer_new_and_alloc
(
sample
->
size
)))
{
GST_ERROR
(
"Failed to allocate input buffer"
);
return
STATUS_NO_MEMORY
;
}
gst_buffer_fill
(
buffer
,
0
,
sample
->
data
,
sample
->
size
);
GST_INFO
(
"Copied %u bytes from sample %p to buffer %p"
,
sample
->
size
,
sample
,
buffer
);
}
else
if
(
!
(
buffer
=
gst_buffer_new_wrapped_full
(
GST_MEMORY_FLAG_READONLY
,
sample
->
data
,
sample
->
max_size
,
0
,
sample
->
size
,
sample
,
wg_sample_free_notify
)))
{
GST_ERROR
(
"Failed to allocate input buffer"
);
return
STATUS_NO_MEMORY
;
}
gst_buffer_fill
(
buffer
,
0
,
sample
->
data
,
sample
->
size
);
else
{
InterlockedIncrement
(
&
sample
->
refcount
);
GST_INFO
(
"Wrapped %u/%u bytes from sample %p to buffer %p"
,
sample
->
size
,
sample
->
max_size
,
sample
,
buffer
);
}
if
(
sample
->
flags
&
WG_SAMPLE_FLAG_HAS_PTS
)
GST_BUFFER_PTS
(
buffer
)
=
sample
->
pts
*
100
;
if
(
sample
->
flags
&
WG_SAMPLE_FLAG_HAS_DURATION
)
...
...
@@ -549,7 +572,6 @@ NTSTATUS wg_transform_push_data(void *args)
GST_BUFFER_FLAG_SET
(
buffer
,
GST_BUFFER_FLAG_DELTA_UNIT
);
gst_buffer_list_insert
(
transform
->
input
,
-
1
,
buffer
);
GST_INFO
(
"Copied %u bytes from sample %p to input buffer list"
,
sample
->
size
,
sample
);
params
->
result
=
S_OK
;
return
STATUS_SUCCESS
;
}
...
...
dlls/winegstreamer/wma_decoder.c
View file @
c40ab0f9
...
...
@@ -56,6 +56,7 @@ struct wma_decoder
IMFMediaType
*
output_type
;
struct
wg_transform
*
wg_transform
;
struct
wg_sample_queue
*
wg_sample_queue
;
};
static
inline
struct
wma_decoder
*
impl_from_IUnknown
(
IUnknown
*
iface
)
...
...
@@ -135,6 +136,8 @@ static ULONG WINAPI unknown_Release(IUnknown *iface)
IMFMediaType_Release
(
decoder
->
input_type
);
if
(
decoder
->
output_type
)
IMFMediaType_Release
(
decoder
->
output_type
);
wg_sample_queue_destroy
(
decoder
->
wg_sample_queue
);
free
(
decoder
);
}
...
...
@@ -544,9 +547,7 @@ static HRESULT WINAPI transform_ProcessInput(IMFTransform *iface, DWORD id, IMFS
return
S_OK
;
}
hr
=
wg_transform_push_mf
(
decoder
->
wg_transform
,
wg_sample
);
wg_sample_release
(
wg_sample
);
return
hr
;
return
wg_transform_push_mf
(
decoder
->
wg_transform
,
wg_sample
,
decoder
->
wg_sample_queue
);
}
static
HRESULT
WINAPI
transform_ProcessOutput
(
IMFTransform
*
iface
,
DWORD
flags
,
DWORD
count
,
...
...
@@ -590,6 +591,7 @@ static HRESULT WINAPI transform_ProcessOutput(IMFTransform *iface, DWORD flags,
{
if
(
wg_sample
->
flags
&
WG_SAMPLE_FLAG_INCOMPLETE
)
samples
[
0
].
dwStatus
|=
MFT_OUTPUT_DATA_BUFFER_INCOMPLETE
;
wg_sample_queue_flush
(
decoder
->
wg_sample_queue
,
false
);
}
wg_sample_release
(
wg_sample
);
...
...
@@ -882,6 +884,7 @@ HRESULT wma_decoder_create(IUnknown *outer, IUnknown **out)
static
const
struct
wg_format
input_format
=
{.
major_type
=
WG_MAJOR_TYPE_WMA
};
struct
wg_transform
*
transform
;
struct
wma_decoder
*
decoder
;
HRESULT
hr
;
TRACE
(
"outer %p, out %p.
\n
"
,
outer
,
out
);
...
...
@@ -895,6 +898,12 @@ HRESULT wma_decoder_create(IUnknown *outer, IUnknown **out)
if
(
!
(
decoder
=
calloc
(
1
,
sizeof
(
*
decoder
))))
return
E_OUTOFMEMORY
;
if
(
FAILED
(
hr
=
wg_sample_queue_create
(
&
decoder
->
wg_sample_queue
)))
{
free
(
decoder
);
return
hr
;
}
decoder
->
IUnknown_inner
.
lpVtbl
=
&
unknown_vtbl
;
decoder
->
IMFTransform_iface
.
lpVtbl
=
&
transform_vtbl
;
decoder
->
IMediaObject_iface
.
lpVtbl
=
&
media_object_vtbl
;
...
...
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