From: Rémi Bernon rbernon@codeweavers.com
--- dlls/winedmo/main.c | 5 ++-- dlls/winedmo/unixlib.c | 63 +++++++++++++++++++++++++++--------------- dlls/winedmo/unixlib.h | 10 ++++--- 3 files changed, 50 insertions(+), 28 deletions(-)
diff --git a/dlls/winedmo/main.c b/dlls/winedmo/main.c index 1e91d8e2e51..849c1e675cb 100644 --- a/dlls/winedmo/main.c +++ b/dlls/winedmo/main.c @@ -30,11 +30,12 @@ static struct stream_context *stream_context_create( struct winedmo_stream *stre { struct stream_context *context;
- if (!(context = malloc( 0x10000 ))) return NULL; + if (!(context = malloc( sizeof(*context) + 0x10000 ))) 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 = 0x10000; + context->size = 0;
return context; } diff --git a/dlls/winedmo/unixlib.c b/dlls/winedmo/unixlib.c index 15500ee10b4..c8d37ce90c5 100644 --- a/dlls/winedmo/unixlib.c +++ b/dlls/winedmo/unixlib.c @@ -46,42 +46,61 @@ int64_t unix_seek_callback( void *opaque, int64_t offset, int whence ) if (whence == SEEK_END) offset += context->length; if (whence == SEEK_CUR) offset += context->position;
- 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) 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[]; };