From: Rémi Bernon rbernon@codeweavers.com
--- dlls/mfsrcsnk/media_source.c | 3 ++- dlls/winedmo/main.c | 7 +++--- dlls/winedmo/unix_demuxer.c | 42 +++++++++++++++++++++++++++++++----- dlls/winedmo/unixlib.c | 2 ++ dlls/winedmo/unixlib.h | 1 + dlls/winedmo/winedmo.spec | 2 +- include/wine/winedmo.h | 2 +- 7 files changed, 48 insertions(+), 11 deletions(-)
diff --git a/dlls/mfsrcsnk/media_source.c b/dlls/mfsrcsnk/media_source.c index ba3209637bd..02034d512d8 100644 --- a/dlls/mfsrcsnk/media_source.c +++ b/dlls/mfsrcsnk/media_source.c @@ -90,6 +90,7 @@ struct media_source struct winedmo_demuxer winedmo_demuxer; struct winedmo_stream winedmo_stream; UINT64 file_size; + INT64 duration; UINT stream_count; WCHAR mime_type[256];
@@ -518,7 +519,7 @@ static HRESULT media_source_async_create(struct media_source *source, IMFAsyncRe source->winedmo_stream.p_seek = media_source_seek_cb; source->winedmo_stream.p_read = media_source_read_cb;
- if ((status = winedmo_demuxer_create(source->url, &source->winedmo_stream, &source->file_size, + if ((status = winedmo_demuxer_create(source->url, &source->winedmo_stream, &source->file_size, &source->duration, &source->stream_count, source->mime_type, &source->winedmo_demuxer))) { WARN("Failed to create demuxer, status %#lx\n", status); diff --git a/dlls/winedmo/main.c b/dlls/winedmo/main.c index 22b6220ad05..ad7bc6753cd 100644 --- a/dlls/winedmo/main.c +++ b/dlls/winedmo/main.c @@ -126,7 +126,7 @@ NTSTATUS CDECL winedmo_demuxer_check( const char *mime_type ) return status; }
-NTSTATUS CDECL winedmo_demuxer_create( const WCHAR *url, struct winedmo_stream *stream, UINT64 *stream_size, +NTSTATUS CDECL winedmo_demuxer_create( const WCHAR *url, struct winedmo_stream *stream, UINT64 *stream_size, INT64 *duration, UINT *stream_count, WCHAR *mime_type, struct winedmo_demuxer *demuxer ) { struct demuxer_create_params params = {0}; @@ -154,11 +154,12 @@ NTSTATUS CDECL winedmo_demuxer_create( const WCHAR *url, struct winedmo_stream * return status; }
+ *duration = params.duration; *stream_count = params.stream_count; MultiByteToWideChar( CP_ACP, 0, params.mime_type, -1, mime_type, 256 ); *demuxer = params.demuxer; - TRACE( "created demuxer %#I64x, stream %p, stream_size %#I64x, stream_count %u, mime_type %s\n", demuxer->handle, - stream, *stream_size, params.stream_count, debugstr_a(params.mime_type) ); + TRACE( "created demuxer %#I64x, stream %p, stream_size %#I64x, duration %I64d, stream_count %u, mime_type %s\n", + demuxer->handle, stream, *stream_size, params.duration, params.stream_count, debugstr_a(params.mime_type) ); return STATUS_SUCCESS; }
diff --git a/dlls/winedmo/unix_demuxer.c b/dlls/winedmo/unix_demuxer.c index 8c0dcf09e12..2a3499068dc 100644 --- a/dlls/winedmo/unix_demuxer.c +++ b/dlls/winedmo/unix_demuxer.c @@ -39,6 +39,34 @@ static AVFormatContext *get_demuxer( struct winedmo_demuxer demuxer ) return (AVFormatContext *)(UINT_PTR)demuxer.handle; }
+static INT64 get_user_time( INT64 time, AVRational time_base ) +{ + static const AVRational USER_TIME_BASE_Q = {1, 10000000}; + return av_rescale_q_rnd( time, time_base, USER_TIME_BASE_Q, AV_ROUND_PASS_MINMAX ); +} + +static INT64 get_stream_time( const AVStream *stream, INT64 time ) +{ + if (stream->time_base.num && stream->time_base.den) return get_user_time( time, stream->time_base ); + return get_user_time( time, AV_TIME_BASE_Q ); +} + +static INT64 get_context_duration( const AVFormatContext *ctx ) +{ + INT64 i, max_duration = AV_NOPTS_VALUE; + + for (i = 0; i < ctx->nb_streams; i++) + { + const AVStream *stream = ctx->streams[i]; + INT64 duration = get_stream_time( stream, stream->duration ); + if (duration == AV_NOPTS_VALUE) continue; + if (duration >= max_duration) max_duration = duration; + if (max_duration == AV_NOPTS_VALUE) max_duration = duration; + } + + return max_duration; +} + NTSTATUS demuxer_check( void *arg ) { struct demuxer_check_params *params = arg; @@ -83,12 +111,16 @@ NTSTATUS demuxer_create( void *arg ) return STATUS_UNSUCCESSFUL; }
- if (!(ctx->nb_streams && ctx->duration != AV_NOPTS_VALUE) && (ret = avformat_find_stream_info( ctx, NULL )) < 0) + if ((params->duration = get_context_duration( ctx )) == AV_NOPTS_VALUE) { - ERR( "Failed to find stream info, ret %d (%s).\n", ret, av_err2str(ret) ); - avio_context_free( &ctx->pb ); - avformat_free_context( ctx ); - return STATUS_UNSUCCESSFUL; + if ((ret = avformat_find_stream_info( ctx, NULL )) < 0) + { + ERR( "Failed to find stream info, ret %d (%s).\n", ret, av_err2str(ret) ); + avio_context_free( &ctx->pb ); + avformat_free_context( ctx ); + return STATUS_UNSUCCESSFUL; + } + params->duration = get_context_duration( ctx ); }
params->demuxer.handle = (UINT_PTR)ctx; diff --git a/dlls/winedmo/unixlib.c b/dlls/winedmo/unixlib.c index 3f1a2c1c440..e6f2a8ee889 100644 --- a/dlls/winedmo/unixlib.c +++ b/dlls/winedmo/unixlib.c @@ -149,6 +149,7 @@ static NTSTATUS wow64_demuxer_create( void *arg ) struct winedmo_demuxer demuxer; char mime_type[256]; UINT32 stream_count; + INT64 duration; } *params32 = arg; struct demuxer_create_params params; NTSTATUS status; @@ -159,6 +160,7 @@ static NTSTATUS wow64_demuxer_create( void *arg ) params32->demuxer = params.demuxer; memcpy( params32->mime_type, params.mime_type, 256 ); params32->stream_count = params.stream_count; + params32->duration = params.duration;
return status; } diff --git a/dlls/winedmo/unixlib.h b/dlls/winedmo/unixlib.h index ad0dacf7016..b3f0583ff07 100644 --- a/dlls/winedmo/unixlib.h +++ b/dlls/winedmo/unixlib.h @@ -75,6 +75,7 @@ struct demuxer_create_params struct winedmo_demuxer demuxer; char mime_type[256]; UINT32 stream_count; + INT64 duration; };
struct demuxer_destroy_params diff --git a/dlls/winedmo/winedmo.spec b/dlls/winedmo/winedmo.spec index 60dca7e5405..61da0617a7c 100644 --- a/dlls/winedmo/winedmo.spec +++ b/dlls/winedmo/winedmo.spec @@ -1,3 +1,3 @@ @ cdecl winedmo_demuxer_check(str) -@ cdecl winedmo_demuxer_create(wstr ptr ptr ptr ptr ptr) +@ cdecl winedmo_demuxer_create(wstr ptr ptr ptr ptr ptr ptr) @ cdecl winedmo_demuxer_destroy(ptr) diff --git a/include/wine/winedmo.h b/include/wine/winedmo.h index 37cf43a2301..758066a85b5 100644 --- a/include/wine/winedmo.h +++ b/include/wine/winedmo.h @@ -35,7 +35,7 @@ struct winedmo_stream struct winedmo_demuxer { UINT64 handle; };
NTSTATUS CDECL winedmo_demuxer_check( const char *mime_type ); -NTSTATUS CDECL winedmo_demuxer_create( const WCHAR *url, struct winedmo_stream *stream, UINT64 *stream_size, +NTSTATUS CDECL winedmo_demuxer_create( const WCHAR *url, struct winedmo_stream *stream, UINT64 *stream_size, INT64 *duration, UINT *stream_count, WCHAR *mime_type, struct winedmo_demuxer *demuxer ); NTSTATUS CDECL winedmo_demuxer_destroy( struct winedmo_demuxer *demuxer );