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
d6c9ac94
Commit
d6c9ac94
authored
Jan 24, 2024
by
Rémi Bernon
Committed by
Alexandre Julliard
Mar 01, 2024
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
mfreadwrite/reader: Keep the stream transforms in a list.
parent
48cb5297
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
103 additions
and
30 deletions
+103
-30
reader.c
dlls/mfreadwrite/reader.c
+103
-30
No files found.
dlls/mfreadwrite/reader.c
View file @
d6c9ac94
...
...
@@ -73,6 +73,7 @@ enum media_stream_flags
struct
transform_entry
{
struct
list
entry
;
IMFTransform
*
transform
;
unsigned
int
min_buffer_size
;
};
...
...
@@ -81,7 +82,7 @@ struct media_stream
{
IMFMediaStream
*
stream
;
IMFMediaType
*
current
;
struct
transform_entry
decoder
;
struct
list
transforms
;
IMFVideoSampleAllocatorEx
*
allocator
;
DWORD
id
;
unsigned
int
index
;
...
...
@@ -202,6 +203,30 @@ static ULONG source_reader_addref(struct source_reader *reader)
return
InterlockedIncrement
(
&
reader
->
refcount
);
}
static
void
transform_entry_destroy
(
struct
transform_entry
*
entry
)
{
IMFTransform_Release
(
entry
->
transform
);
free
(
entry
);
}
static
void
media_stream_destroy
(
struct
media_stream
*
stream
)
{
struct
transform_entry
*
entry
,
*
next
;
LIST_FOR_EACH_ENTRY_SAFE
(
entry
,
next
,
&
stream
->
transforms
,
struct
transform_entry
,
entry
)
{
list_remove
(
&
entry
->
entry
);
transform_entry_destroy
(
entry
);
}
if
(
stream
->
stream
)
IMFMediaStream_Release
(
stream
->
stream
);
if
(
stream
->
current
)
IMFMediaType_Release
(
stream
->
current
);
if
(
stream
->
allocator
)
IMFVideoSampleAllocatorEx_Release
(
stream
->
allocator
);
}
static
ULONG
source_reader_release
(
struct
source_reader
*
reader
)
{
ULONG
refcount
=
InterlockedDecrement
(
&
reader
->
refcount
);
...
...
@@ -222,15 +247,7 @@ static ULONG source_reader_release(struct source_reader *reader)
for
(
i
=
0
;
i
<
reader
->
stream_count
;
++
i
)
{
struct
media_stream
*
stream
=
&
reader
->
streams
[
i
];
if
(
stream
->
stream
)
IMFMediaStream_Release
(
stream
->
stream
);
if
(
stream
->
current
)
IMFMediaType_Release
(
stream
->
current
);
if
(
stream
->
decoder
.
transform
)
IMFTransform_Release
(
stream
->
decoder
.
transform
);
if
(
stream
->
allocator
)
IMFVideoSampleAllocatorEx_Release
(
stream
->
allocator
);
media_stream_destroy
(
stream
);
}
source_reader_release_responses
(
reader
,
NULL
);
free
(
reader
->
streams
);
...
...
@@ -749,10 +766,15 @@ static HRESULT source_reader_push_transform_samples(struct source_reader *reader
static
HRESULT
source_reader_pull_transform_samples
(
struct
source_reader
*
reader
,
struct
media_stream
*
stream
,
struct
transform_entry
*
entry
)
{
MFT_OUTPUT_STREAM_INFO
stream_info
=
{
0
};
MFT_OUTPUT_STREAM_INFO
stream_info
=
{
0
};
struct
transform_entry
*
next
=
NULL
;
struct
list
*
ptr
;
DWORD
status
;
HRESULT
hr
;
if
((
ptr
=
list_next
(
&
stream
->
transforms
,
&
entry
->
entry
)))
next
=
LIST_ENTRY
(
ptr
,
struct
transform_entry
,
entry
);
if
(
FAILED
(
hr
=
IMFTransform_GetOutputStreamInfo
(
entry
->
transform
,
0
,
&
stream_info
)))
return
hr
;
stream_info
.
cbSize
=
max
(
stream_info
.
cbSize
,
entry
->
min_buffer_size
);
...
...
@@ -765,8 +787,13 @@ static HRESULT source_reader_pull_transform_samples(struct source_reader *reader
&&
FAILED
(
hr
=
source_reader_allocate_stream_sample
(
&
stream_info
,
&
out_buffer
.
pSample
)))
break
;
if
(
SUCCEEDED
(
hr
=
IMFTransform_ProcessOutput
(
stream
->
decoder
.
transform
,
0
,
1
,
&
out_buffer
,
&
status
)))
hr
=
source_reader_queue_sample
(
reader
,
stream
,
out_buffer
.
pSample
);
if
(
SUCCEEDED
(
hr
=
IMFTransform_ProcessOutput
(
entry
->
transform
,
0
,
1
,
&
out_buffer
,
&
status
)))
{
if
(
next
)
hr
=
source_reader_push_transform_samples
(
reader
,
stream
,
next
,
out_buffer
.
pSample
);
else
hr
=
source_reader_queue_sample
(
reader
,
stream
,
out_buffer
.
pSample
);
}
if
(
out_buffer
.
pSample
)
IMFSample_Release
(
out_buffer
.
pSample
);
...
...
@@ -780,38 +807,51 @@ static HRESULT source_reader_pull_transform_samples(struct source_reader *reader
static
HRESULT
source_reader_drain_transform_samples
(
struct
source_reader
*
reader
,
struct
media_stream
*
stream
,
struct
transform_entry
*
entry
)
{
struct
transform_entry
*
next
=
NULL
;
struct
list
*
ptr
;
HRESULT
hr
;
if
((
ptr
=
list_next
(
&
stream
->
transforms
,
&
entry
->
entry
)))
next
=
LIST_ENTRY
(
ptr
,
struct
transform_entry
,
entry
);
if
(
FAILED
(
hr
=
IMFTransform_ProcessMessage
(
entry
->
transform
,
MFT_MESSAGE_COMMAND_DRAIN
,
0
)))
WARN
(
"Failed to drain transform %p, hr %#lx
\n
"
,
entry
->
transform
,
hr
);
if
(
FAILED
(
hr
=
source_reader_pull_transform_samples
(
reader
,
stream
,
entry
))
&&
hr
!=
MF_E_TRANSFORM_NEED_MORE_INPUT
)
WARN
(
"Failed to pull pending samples, hr %#lx.
\n
"
,
hr
);
return
S_OK
;
return
next
?
source_reader_drain_transform_samples
(
reader
,
stream
,
next
)
:
S_OK
;
}
static
HRESULT
source_reader_flush_transform_samples
(
struct
source_reader
*
reader
,
struct
media_stream
*
stream
,
struct
transform_entry
*
entry
)
{
struct
transform_entry
*
next
=
NULL
;
struct
list
*
ptr
;
HRESULT
hr
;
if
((
ptr
=
list_next
(
&
stream
->
transforms
,
&
entry
->
entry
)))
next
=
LIST_ENTRY
(
ptr
,
struct
transform_entry
,
entry
);
if
(
FAILED
(
hr
=
IMFTransform_ProcessMessage
(
entry
->
transform
,
MFT_MESSAGE_COMMAND_FLUSH
,
0
)))
WARN
(
"Failed to flush transform %p, hr %#lx
\n
"
,
entry
->
transform
,
hr
);
return
S_OK
;
return
next
?
source_reader_flush_transform_samples
(
reader
,
stream
,
next
)
:
S_OK
;
}
static
HRESULT
source_reader_process_sample
(
struct
source_reader
*
reader
,
struct
media_stream
*
stream
,
IMFSample
*
sample
)
{
struct
transform_entry
*
entry
;
struct
list
*
ptr
;
HRESULT
hr
;
if
(
!
stream
->
decoder
.
transform
)
if
(
!
(
ptr
=
list_head
(
&
stream
->
transforms
))
)
return
source_reader_queue_sample
(
reader
,
stream
,
sample
);
entry
=
LIST_ENTRY
(
ptr
,
struct
transform_entry
,
entry
);
/* It's assumed that decoder has 1 input and 1 output, both id's are 0. */
if
(
SUCCEEDED
(
hr
=
source_reader_push_transform_samples
(
reader
,
stream
,
&
stream
->
decoder
,
sample
))
if
(
SUCCEEDED
(
hr
=
source_reader_push_transform_samples
(
reader
,
stream
,
entry
,
sample
))
||
hr
==
MF_E_TRANSFORM_NEED_MORE_INPUT
)
hr
=
stream
->
requests
?
source_reader_request_sample
(
reader
,
stream
)
:
S_OK
;
else
...
...
@@ -895,12 +935,16 @@ static HRESULT source_reader_media_stream_state_handler(struct source_reader *re
switch
(
event_type
)
{
case
MEEndOfStream
:
{
struct
list
*
ptr
;
stream
->
state
=
STREAM_STATE_EOS
;
stream
->
flags
&=
~
STREAM_FLAG_SAMPLE_REQUESTED
;
if
(
stream
->
decoder
.
transform
)
if
(
(
ptr
=
list_head
(
&
stream
->
transforms
))
)
{
if
(
FAILED
(
hr
=
source_reader_drain_transform_samples
(
reader
,
stream
,
&
stream
->
decoder
)))
struct
transform_entry
*
entry
=
LIST_ENTRY
(
ptr
,
struct
transform_entry
,
entry
);
if
(
FAILED
(
hr
=
source_reader_drain_transform_samples
(
reader
,
stream
,
entry
)))
WARN
(
"Failed to drain pending samples, hr %#lx.
\n
"
,
hr
);
}
...
...
@@ -908,6 +952,7 @@ static HRESULT source_reader_media_stream_state_handler(struct source_reader *re
source_reader_queue_response
(
reader
,
stream
,
S_OK
,
MF_SOURCE_READERF_ENDOFSTREAM
,
0
,
NULL
);
break
;
}
case
MEStreamSeeked
:
case
MEStreamStarted
:
stream
->
state
=
STREAM_STATE_READY
;
...
...
@@ -1260,13 +1305,15 @@ static void source_reader_release_responses(struct source_reader *reader, struct
static
void
source_reader_flush_stream
(
struct
source_reader
*
reader
,
DWORD
stream_index
)
{
struct
media_stream
*
stream
=
&
reader
->
streams
[
stream_index
];
struct
list
*
ptr
;
HRESULT
hr
;
source_reader_release_responses
(
reader
,
stream
);
if
(
stream
->
decoder
.
transform
)
if
(
(
ptr
=
list_head
(
&
stream
->
transforms
))
)
{
if
(
FAILED
(
hr
=
source_reader_flush_transform_samples
(
reader
,
stream
,
&
stream
->
decoder
)))
struct
transform_entry
*
entry
=
LIST_ENTRY
(
ptr
,
struct
transform_entry
,
entry
);
if
(
FAILED
(
hr
=
source_reader_flush_transform_samples
(
reader
,
stream
,
entry
)))
WARN
(
"Failed to drain pending samples, hr %#lx.
\n
"
,
hr
);
}
...
...
@@ -1701,6 +1748,8 @@ static HRESULT source_reader_get_source_type_handler(struct source_reader *reade
static
HRESULT
source_reader_set_compatible_media_type
(
struct
source_reader
*
reader
,
DWORD
index
,
IMFMediaType
*
type
)
{
struct
media_stream
*
stream
=
&
reader
->
streams
[
index
];
struct
transform_entry
*
entry
,
*
next
;
IMFMediaTypeHandler
*
type_handler
;
IMFMediaType
*
native_type
;
BOOL
type_set
=
FALSE
;
...
...
@@ -1708,7 +1757,7 @@ static HRESULT source_reader_set_compatible_media_type(struct source_reader *rea
DWORD
flags
;
HRESULT
hr
;
if
(
FAILED
(
hr
=
IMFMediaType_IsEqual
(
type
,
reader
->
streams
[
index
].
current
,
&
flags
)))
if
(
FAILED
(
hr
=
IMFMediaType_IsEqual
(
type
,
stream
->
current
,
&
flags
)))
return
hr
;
if
(
!
(
flags
&
MF_MEDIATYPE_EQUAL_MAJOR_TYPES
))
...
...
@@ -1718,6 +1767,12 @@ static HRESULT source_reader_set_compatible_media_type(struct source_reader *rea
if
(
flags
&
MF_MEDIATYPE_EQUAL_FORMAT_DATA
)
return
S_OK
;
LIST_FOR_EACH_ENTRY_SAFE
(
entry
,
next
,
&
stream
->
transforms
,
struct
transform_entry
,
entry
)
{
list_remove
(
&
entry
->
entry
);
transform_entry_destroy
(
entry
);
}
if
(
FAILED
(
hr
=
source_reader_get_source_type_handler
(
reader
,
index
,
&
type_handler
)))
return
hr
;
...
...
@@ -1728,7 +1783,7 @@ static HRESULT source_reader_set_compatible_media_type(struct source_reader *rea
if
(
SUCCEEDED
(
IMFMediaType_IsEqual
(
native_type
,
type
,
&
flags
))
&&
(
flags
&
compare_flags
)
==
compare_flags
)
{
if
((
type_set
=
SUCCEEDED
(
IMFMediaTypeHandler_SetCurrentMediaType
(
type_handler
,
native_type
))))
IMFMediaType_CopyAllItems
(
native_type
,
(
IMFAttributes
*
)
reader
->
streams
[
index
].
current
);
IMFMediaType_CopyAllItems
(
native_type
,
(
IMFAttributes
*
)
stream
->
current
);
}
IMFMediaType_Release
(
native_type
);
...
...
@@ -1804,12 +1859,11 @@ static HRESULT source_reader_setup_sample_allocator(struct source_reader *reader
return
hr
;
}
static
HRESULT
source_reader_create_transform
(
struct
source_reader
*
reader
,
DWORD
index
,
IMFMediaType
*
input_type
,
IMFMediaType
*
output_type
)
static
HRESULT
source_reader_create_transform
(
struct
source_reader
*
reader
,
IMFMediaType
*
input_type
,
IMFMediaType
*
output_type
,
struct
transform_entry
**
out
)
{
struct
media_stream
*
stream
=
&
reader
->
streams
[
index
];
struct
transform_entry
*
entry
=
&
stream
->
decoder
;
MFT_REGISTER_TYPE_INFO
in_type
,
out_type
;
struct
transform_entry
*
entry
;
GUID
*
classes
,
category
;
IMFTransform
*
transform
;
UINT
i
,
count
;
...
...
@@ -1829,6 +1883,9 @@ static HRESULT source_reader_create_transform(struct source_reader *reader, DWOR
else
return
MF_E_TOPO_CODEC_NOT_FOUND
;
if
(
!
(
entry
=
calloc
(
1
,
sizeof
(
*
entry
))))
return
E_OUTOFMEMORY
;
if
(
IsEqualGUID
(
&
out_type
.
guidMajorType
,
&
MFMediaType_Audio
))
IMFMediaType_GetUINT32
(
output_type
,
&
MF_MT_AUDIO_BLOCK_ALIGNMENT
,
&
entry
->
min_buffer_size
);
...
...
@@ -1855,6 +1912,7 @@ static HRESULT source_reader_create_transform(struct source_reader *reader, DWOR
if
(
SUCCEEDED
(
hr
))
{
entry
->
transform
=
transform
;
*
out
=
entry
;
return
S_OK
;
}
}
...
...
@@ -1865,6 +1923,7 @@ static HRESULT source_reader_create_transform(struct source_reader *reader, DWOR
CoTaskMemFree
(
classes
);
}
free
(
entry
);
return
hr
;
}
...
...
@@ -1877,10 +1936,14 @@ static HRESULT source_reader_create_decoder_for_stream(struct source_reader *rea
while
(
SUCCEEDED
(
hr
=
source_reader_get_native_media_type
(
reader
,
index
,
i
++
,
&
input_type
)))
{
if
(
SUCCEEDED
(
hr
=
source_reader_create_transform
(
reader
,
index
,
input_type
,
output_type
)))
struct
transform_entry
*
entry
;
if
(
SUCCEEDED
(
hr
=
source_reader_create_transform
(
reader
,
input_type
,
output_type
,
&
entry
)))
{
IMFMediaTypeHandler
*
type_handler
;
list_add_tail
(
&
stream
->
transforms
,
&
entry
->
entry
);
if
(
SUCCEEDED
(
source_reader_get_source_type_handler
(
reader
,
index
,
&
type_handler
)))
{
if
(
FAILED
(
hr
=
IMFMediaTypeHandler_SetCurrentMediaType
(
type_handler
,
input_type
)))
...
...
@@ -1888,7 +1951,7 @@ static HRESULT source_reader_create_decoder_for_stream(struct source_reader *rea
IMFMediaTypeHandler_Release
(
type_handler
);
}
if
(
FAILED
(
hr
=
IMFTransform_GetOutputCurrentType
(
stream
->
decoder
.
transform
,
0
,
&
output_type
)))
if
(
FAILED
(
hr
=
IMFTransform_GetOutputCurrentType
(
entry
->
transform
,
0
,
&
output_type
)))
WARN
(
"Failed to get decoder output media type, hr %#lx
\n
"
,
hr
);
else
{
...
...
@@ -2181,6 +2244,7 @@ static HRESULT WINAPI src_reader_GetServiceForStream(IMFSourceReaderEx *iface, D
REFIID
riid
,
void
**
object
)
{
struct
source_reader
*
reader
=
impl_from_IMFSourceReaderEx
(
iface
);
struct
media_stream
*
stream
=
&
reader
->
streams
[
index
];
IUnknown
*
obj
=
NULL
;
HRESULT
hr
=
S_OK
;
...
...
@@ -2203,7 +2267,14 @@ static HRESULT WINAPI src_reader_GetServiceForStream(IMFSourceReaderEx *iface, D
hr
=
MF_E_INVALIDSTREAMNUMBER
;
else
{
obj
=
(
IUnknown
*
)
reader
->
streams
[
index
].
decoder
.
transform
;
struct
list
*
ptr
;
if
((
ptr
=
list_tail
(
&
stream
->
transforms
)))
{
struct
transform_entry
*
entry
=
LIST_ENTRY
(
ptr
,
struct
transform_entry
,
entry
);
obj
=
(
IUnknown
*
)
entry
->
transform
;
}
if
(
!
obj
)
hr
=
E_NOINTERFACE
;
}
break
;
...
...
@@ -2426,6 +2497,8 @@ static HRESULT create_source_reader_from_source(IMFMediaSource *source, IMFAttri
IMFMediaType
*
src_type
;
BOOL
selected
;
list_init
(
&
object
->
streams
[
i
].
transforms
);
if
(
FAILED
(
hr
=
MFCreateMediaType
(
&
object
->
streams
[
i
].
current
)))
break
;
...
...
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