From: Rémi Bernon rbernon@codeweavers.com
--- dlls/winedmo/unixlib.c | 1 + 1 file changed, 1 insertion(+)
diff --git a/dlls/winedmo/unixlib.c b/dlls/winedmo/unixlib.c index 15500ee10b4..431b612d7d6 100644 --- a/dlls/winedmo/unixlib.c +++ b/dlls/winedmo/unixlib.c @@ -45,6 +45,7 @@ int64_t unix_seek_callback( void *opaque, int64_t offset, int whence ) if (whence == AVSEEK_SIZE) return context->length; if (whence == SEEK_END) offset += context->length; if (whence == SEEK_CUR) offset += context->position; + if ((UINT64)offset > context->length) offset = context->length;
params.offset = offset; status = KeUserDispatchCallback( ¶ms.dispatch, sizeof(params), &ret_ptr, &ret_len );
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/winedmo/unixlib.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/dlls/winedmo/unixlib.c b/dlls/winedmo/unixlib.c index 431b612d7d6..fd563eef6bf 100644 --- a/dlls/winedmo/unixlib.c +++ b/dlls/winedmo/unixlib.c @@ -63,7 +63,7 @@ int unix_read_callback( void *opaque, uint8_t *buffer, int size )
TRACE( "opaque %p, buffer %p, size %#x\n", opaque, buffer, size );
- if (!size) return AVERROR_EOF; + if (!(size = min( (UINT64)size, context->length - context->position ))) return AVERROR_EOF;
do {
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/winedmo/main.c | 6 ++-- dlls/winedmo/unixlib.c | 63 +++++++++++++++++++++++++++--------------- dlls/winedmo/unixlib.h | 10 ++++--- 3 files changed, 51 insertions(+), 28 deletions(-)
diff --git a/dlls/winedmo/main.c b/dlls/winedmo/main.c index 1e91d8e2e51..77411352445 100644 --- a/dlls/winedmo/main.c +++ b/dlls/winedmo/main.c @@ -28,13 +28,15 @@ WINE_DEFAULT_DEBUG_CHANNEL(dmo);
static struct stream_context *stream_context_create( struct winedmo_stream *stream, UINT64 stream_size ) { + static const UINT BUFFER_SIZE = 0x40000; struct stream_context *context;
- if (!(context = malloc( 0x10000 ))) return NULL; + if (!(context = malloc( sizeof(*context) + BUFFER_SIZE ))) return NULL; context->stream = (UINT_PTR)stream; context->length = stream_size; context->position = 0; - context->buffer_size = 0x10000 - offsetof(struct stream_context, buffer); + context->capacity = BUFFER_SIZE; + context->size = 0;
return context; } diff --git a/dlls/winedmo/unixlib.c b/dlls/winedmo/unixlib.c index fd563eef6bf..ea0ccde8545 100644 --- a/dlls/winedmo/unixlib.c +++ b/dlls/winedmo/unixlib.c @@ -47,42 +47,61 @@ int64_t unix_seek_callback( void *opaque, int64_t offset, int whence ) if (whence == SEEK_CUR) offset += context->position; if ((UINT64)offset > context->length) offset = context->length;
- params.offset = offset; - status = KeUserDispatchCallback( ¶ms.dispatch, sizeof(params), &ret_ptr, &ret_len ); - if (status || ret_len != sizeof(UINT64)) return AVERROR( EINVAL ); - offset = *(UINT64 *)ret_ptr; + if (offset / context->capacity != context->position / context->capacity) + { + for (;;) + { + /* seek stream to multiples of buffer capacity */ + params.offset = (offset / context->capacity) * context->capacity; + status = KeUserDispatchCallback( ¶ms.dispatch, sizeof(params), &ret_ptr, &ret_len ); + if (status || ret_len != sizeof(UINT64)) return AVERROR( EINVAL ); + if (*(UINT64 *)ret_ptr == params.offset) break; + offset = *(UINT64 *)ret_ptr; + } + context->size = 0; + }
context->position = offset; return offset; }
+static int stream_context_read( struct stream_context *context ) +{ + struct read_callback_params params = {.dispatch = {.callback = read_callback}, .context = (UINT_PTR)context}; + void *ret_ptr; + ULONG ret_len; + int status; + + params.size = context->capacity; + status = KeUserDispatchCallback( ¶ms.dispatch, sizeof(params), &ret_ptr, &ret_len ); + if (status || ret_len != sizeof(ULONG)) return AVERROR( EINVAL ); + context->size = *(ULONG *)ret_ptr; + return 0; +} + int unix_read_callback( void *opaque, uint8_t *buffer, int size ) { struct stream_context *context = opaque; - int ret, status, total = 0; - - TRACE( "opaque %p, buffer %p, size %#x\n", opaque, buffer, size ); + int ret, total = 0;
if (!(size = min( (UINT64)size, context->length - context->position ))) return AVERROR_EOF;
- do + while (size) { - struct read_callback_params params = {.dispatch = {.callback = read_callback}, .context = (UINT_PTR)context}; - void *ret_ptr; - ULONG ret_len; - - params.size = min( size, context->buffer_size ); - status = KeUserDispatchCallback( ¶ms.dispatch, sizeof(params), &ret_ptr, &ret_len ); - if (status || ret_len != sizeof(ULONG)) return AVERROR( EINVAL ); - if (!(ret = *(ULONG *)ret_ptr)) break; - memcpy( buffer, context->buffer, ret ); - buffer += ret; - total += ret; - size -= ret; - } while (size && ret == context->buffer_size); + int step, buffer_offset = context->position % context->capacity; + + if (!context->size && (ret = stream_context_read( context )) < 0) return ret; + if (!(step = min( size, context->size - buffer_offset ))) break; + memcpy( buffer, context->buffer + buffer_offset, step ); + buffer += step; + total += step; + size -= step; + + context->position += step; + if (!(context->position % context->capacity)) context->size = 0; + }
if (!total) return AVERROR_EOF; - context->position += total; return total; }
diff --git a/dlls/winedmo/unixlib.h b/dlls/winedmo/unixlib.h index cf37bd5342a..b23f786fe47 100644 --- a/dlls/winedmo/unixlib.h +++ b/dlls/winedmo/unixlib.h @@ -40,10 +40,12 @@ struct process_attach_params
struct stream_context { - UINT64 stream; - UINT64 length; - UINT64 position; - UINT64 buffer_size; + UINT64 stream; /* client-side stream handle */ + UINT64 length; /* total length of the stream */ + UINT64 position; /* current position in the stream */ + + UINT32 capacity; /* total allocated capacity for the buffer */ + UINT32 size; /* current data size in the buffer */ BYTE buffer[]; };
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/winedmo/unix_demuxer.c | 1 + 1 file changed, 1 insertion(+)
diff --git a/dlls/winedmo/unix_demuxer.c b/dlls/winedmo/unix_demuxer.c index 7a1a262e6c9..a29720e84b4 100644 --- a/dlls/winedmo/unix_demuxer.c +++ b/dlls/winedmo/unix_demuxer.c @@ -79,6 +79,7 @@ static INT64 get_context_duration( const AVFormatContext *ctx ) if (max_duration == AV_NOPTS_VALUE) max_duration = duration; }
+ if (max_duration == AV_NOPTS_VALUE) return get_user_time( ctx->duration, AV_TIME_BASE_Q ); return max_duration; }
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/winedmo/unix_media_type.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-)
diff --git a/dlls/winedmo/unix_media_type.c b/dlls/winedmo/unix_media_type.c index fac3a82e8c9..fe3060eaea7 100644 --- a/dlls/winedmo/unix_media_type.c +++ b/dlls/winedmo/unix_media_type.c @@ -67,7 +67,7 @@ static inline const char *debugstr_area( const MFVideoArea *area ) } \ } while (0)
-static WORD wave_format_tag_from_codec_id( enum AVCodecID id ) +static UINT wave_format_tag_from_codec_id( enum AVCodecID id ) { const struct AVCodecTag *table[] = {avformat_get_riff_audio_tags(), avformat_get_mov_audio_tags(), 0}; return av_codec_get_tag( table, id ); @@ -161,9 +161,8 @@ static NTSTATUS heaac_wave_format_from_codec_params( const AVCodecParameters *pa
static NTSTATUS audio_format_from_codec_params( const AVCodecParameters *params, void *format, UINT32 *format_size ) { - UINT wave_format_size = sizeof(WAVEFORMATEX); + UINT format_tag, wave_format_size = sizeof(WAVEFORMATEX); UINT64 channel_mask; - WORD format_tag; int channels;
if (params->codec_id == AV_CODEC_ID_AAC) return heaac_wave_format_from_codec_params( params, format, format_size );
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/winedmo/unix_demuxer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/dlls/winedmo/unix_demuxer.c b/dlls/winedmo/unix_demuxer.c index a29720e84b4..4c6bc15579b 100644 --- a/dlls/winedmo/unix_demuxer.c +++ b/dlls/winedmo/unix_demuxer.c @@ -312,7 +312,7 @@ NTSTATUS demuxer_seek( void *arg )
TRACE( "demuxer %p, timestamp 0x%s\n", demuxer, wine_dbgstr_longlong( params->timestamp ) );
- if ((ret = av_seek_frame( demuxer->ctx, -1, timestamp, AVSEEK_FLAG_ANY )) < 0) + if ((ret = avformat_seek_file( demuxer->ctx, -1, 0, timestamp, timestamp, 0 )) < 0) { ERR( "Failed to seek demuxer %p, error %s.\n", demuxer, debugstr_averr(ret) ); return STATUS_UNSUCCESSFUL;