[FFmpeg-devel] [PATCH] Windows support for av_file_map()

Daniel Verkamp daniel
Wed Jan 5 06:47:49 CET 2011


On Sat, Jan 1, 2011 at 11:39 AM, Michael Niedermayer <michaelni at gmx.at> wrote:
> On Fri, Dec 31, 2010 at 02:35:50AM -0700, Daniel Verkamp wrote:
>> Hi,
>>
>> Here's a simple implementation of av_file_map() using
>> CreateFileMapping() and MapViewOfFile(), which are the rough Win32
>> equivalent of mmap().
>>
>> This currently maps a read-only view of the file; this could be
>> changed to R/W to match the mmap() path if desired, but any code
>> expecting to actually use it for writing will fail with the non-mmap()
>> path anyway since the file is never written back in that case.
>>
>> Thanks,
>> -- Daniel Verkamp
>
> lgtm if tested
>

Applied with a small modification recommended by Ramiro on IRC.

An (ugly hack of an) idea occurred to me: for the malloc() (non-mmap)
case, the buffer could be allocated with some extra space at the
beginning to store a fd or other information to be used to flush the
file at close time; this follows the same API with working write
access.  A first try at implementing this is attached.

On the other hand, this API is not very useful on 32-bit machines,
since it only maps full files, and large files will obviously not fit
into a 32-bit address space no matter how hard they are squeezed.  It
might not be a bad idea to have some kind of windowing/view support
like mmap() et. al. if this is really intended to be used for anything
other than the trivial small file case (and if that's all it's for, it
seems like overkill).

Thanks,
-- Daniel Verkamp
-------------- next part --------------
Index: file.c
===================================================================
--- file.c	(revision 26221)
+++ file.c	(working copy)
@@ -33,6 +33,11 @@
     void *log_ctx;
 } FileLogContext;
 
+/// Stored immediately preceding file data in memory in non-memory-mapped implementation
+typedef struct {
+    int fd;
+} FileMapContext;
+
 static const AVClass file_log_ctx_class = {
     "FILE", av_default_item_name, NULL, LIBAVUTIL_VERSION_INT,
     offsetof(FileLogContext, log_offset), offsetof(FileLogContext, log_ctx)
@@ -42,7 +47,7 @@
                 int log_offset, void *log_ctx)
 {
     FileLogContext file_log_ctx = { &file_log_ctx_class, log_offset, log_ctx };
-    int err, fd = open(filename, O_RDONLY);
+    int err, fd = open(filename, O_RDWR);
     struct stat st;
     av_unused void *ptr;
     off_t off_size;
@@ -84,6 +89,7 @@
         return err;
     }
     *bufptr = ptr;
+    close(fd);
 #elif HAVE_MAPVIEWOFFILE
     {
         HANDLE mh, fh = (HANDLE)_get_osfhandle(fd);
@@ -104,18 +110,31 @@
         }
 
         *bufptr = ptr;
+        close(fd);
     }
 #else
-    *bufptr = av_malloc(*size);
-    if (!*bufptr) {
+    {
+        size_t total_size = *size + sizeof(FileMapContext);
+        if (total_size < *size) {
+            av_log(&file_log_ctx, AV_LOG_ERROR,
+                   "File size for file '%s' is too big\n", filename);
+            close(fd);
+            return AVERROR(EINVAL);
+        }
+        FileMapContext* buf = av_malloc(total_size);
+
+        if (!buf) {
         av_log(&file_log_ctx, AV_LOG_ERROR, "Memory allocation error occurred\n");
         close(fd);
         return AVERROR(ENOMEM);
     }
+
+    buf->fd = fd;
+    *bufptr = (uint8_t*)(buf + 1);
     read(fd, *bufptr, *size);
+    }
 #endif
 
-    close(fd);
     return 0;
 }
 
@@ -126,7 +145,13 @@
 #elif HAVE_MAPVIEWOFFILE
     UnmapViewOfFile(bufptr);
 #else
-    av_free(bufptr);
+    {
+        FileMapContext* buf = (FileMapContext*)bufptr - 1;
+        if (!lseek(buf->fd, 0, SEEK_SET))
+            write(buf->fd, bufptr, size);
+        close(buf->fd);
+        av_free(buf);
+    }
 #endif
 }
 



More information about the ffmpeg-devel mailing list