]> git.sesse.net Git - vlc/blobdiff - modules/access/mmap.c
Use var_Inherit* when applicable.
[vlc] / modules / access / mmap.c
index 188106825d819100227cdc7f2d218be9d667cb77..2c7dfbfc3544cb931e1eb32af33893f85cfb2c25 100644 (file)
 # include <config.h>
 #endif
 
-#include <vlc/vlc.h>
+#include <vlc_common.h>
+#include <vlc_plugin.h>
 #include <vlc_access.h>
 #include <vlc_input.h>
-#include <vlc_charset.h>
-#include <vlc_interface.h>
+#include <vlc_fs.h>
+#include <vlc_dialog.h>
 
 #include <assert.h>
 
-#include <errno.h>
 #include <sys/types.h>
 #include <unistd.h>
 #include <fcntl.h>
 #define FILE_MMAP_LONGTEXT N_( \
     "Try to use memory mapping to read files and block devices." )
 
+#ifndef NDEBUG
+/*# define MMAP_DEBUG 1*/
+#endif
+
 static int Open (vlc_object_t *);
 static void Close (vlc_object_t *);
 
-vlc_module_begin();
-    set_shortname (_("MMap"));
-    set_description (_("Memory-mapped file input"));
-    set_category (CAT_INPUT);
-    set_subcategory (SUBCAT_INPUT_ACCESS);
-    set_capability ("access2", 52);
-    add_shortcut ("file");
-    set_callbacks (Open, Close);
-
-    add_bool ("file-mmap", VLC_TRUE, NULL,
-              FILE_MMAP_TEXT, FILE_MMAP_LONGTEXT, VLC_TRUE);
-vlc_module_end();
+vlc_module_begin ()
+    set_shortname (N_("MMap"))
+    set_description (N_("Memory-mapped file input"))
+    set_category (CAT_INPUT)
+    set_subcategory (SUBCAT_INPUT_ACCESS)
+    set_capability ("access", 52)
+    add_shortcut ("file")
+    set_callbacks (Open, Close)
+#ifdef __APPLE__
+    add_bool ("file-mmap", true, NULL,
+              FILE_MMAP_TEXT, FILE_MMAP_LONGTEXT, true)
+#else
+    add_bool ("file-mmap", false, NULL,
+              FILE_MMAP_TEXT, FILE_MMAP_LONGTEXT, true)
+#endif
+vlc_module_end ()
 
 static block_t *Block (access_t *);
-static int Seek (access_t *, int64_t);
+static int Seek (access_t *, uint64_t);
 static int Control (access_t *, int, va_list);
 
 struct access_sys_t
@@ -75,21 +83,18 @@ static int Open (vlc_object_t *p_this)
 {
     access_t *p_access = (access_t *)p_this;
     access_sys_t *p_sys;
-    const char *path = p_access->psz_path;
+    const char *path = p_access->psz_filepath;
     int fd;
 
-    if (!var_CreateGetBool (p_this, "file-mmap"))
+    assert ((INT64_C(1) << 63) == ((off_t)(INT64_C(1) << 63)));
+
+    if (!var_InheritBool (p_this, "file-mmap"))
         return VLC_EGENERIC; /* disabled */
 
     STANDARD_BLOCK_ACCESS_INIT;
 
-    if (!strcmp (p_access->psz_path, "-"))
-        fd = dup (0);
-    else
-    {
-        msg_Dbg (p_access, "opening file %s", path);
-        fd = utf8_open (path, O_RDONLY | O_NOCTTY, 0666);
-    }
+    msg_Dbg (p_access, "opening file %s", path);
+    fd = vlc_open (path, O_RDONLY | O_NOCTTY);
 
     if (fd == -1)
     {
@@ -110,10 +115,21 @@ static int Open (vlc_object_t *p_this)
 
     if (!S_ISREG (st.st_mode) && !S_ISBLK (st.st_mode))
     {
-        msg_Dbg (p_access, "skipping non regular file %s", path);
+        msg_Dbg (p_access, "skipping non-regular file %s", path);
         goto error;
     }
 
+#if defined(HAVE_FCNTL_H)
+    /* We'd rather use any available memory for reading ahead
+     * than for caching what we've already mmap'ed */
+# if defined(F_RDAHEAD)
+    fcntl (fd, F_RDAHEAD, 1);
+# endif
+# if defined(F_NOCACHE)
+    fcntl (fd, F_NOCACHE, 1);
+# endif
+#endif
+
     /* Autodetect mmap() support */
     if (st.st_size > 0)
     {
@@ -131,7 +147,9 @@ static int Open (vlc_object_t *p_this)
     p_sys->fd = fd;
 
     p_access->info.i_size = st.st_size;
+#ifdef HAVE_POSIX_FADVISE    
     posix_fadvise (fd, 0, 0, POSIX_FADV_SEQUENTIAL);
+#endif 
 
     return VLC_SUCCESS;
 
@@ -155,37 +173,35 @@ static void Close (vlc_object_t * p_this)
 static block_t *Block (access_t *p_access)
 {
     access_sys_t *p_sys = p_access->p_sys;
-#ifndef NDEBUG
-    int64_t dbgpos = lseek (p_sys->fd, 0, SEEK_CUR);
-    if (dbgpos != p_access->info.i_pos)
-        msg_Err (p_access, "position: 0x%08llx instead of 0x%08llx",
-                 p_access->info.i_pos, dbgpos);
-#endif
 
-    if ((uint64_t)p_access->info.i_pos >= (uint64_t)p_access->info.i_size)
-    {
-        /* End of file - check if file size changed... */
-        struct stat st;
+    /* Check if file size changed... */
+    struct stat st;
 
-        if ((fstat (p_sys->fd, &st) == 0)
-         && (st.st_size != p_access->info.i_size))
-        {
-            p_access->info.i_size = st.st_size;
-            p_access->info.i_update |= INPUT_UPDATE_SIZE;
-        }
+    if ((fstat (p_sys->fd, &st) == 0)
+     && (st.st_size != p_access->info.i_size))
+    {
+        p_access->info.i_size = st.st_size;
+        p_access->info.i_update |= INPUT_UPDATE_SIZE;
+    }
 
-        /* Really at end of file then */
-        if ((uint64_t)p_access->info.i_pos >= (uint64_t)p_access->info.i_size)
-        {
-            p_access->info.b_eof = VLC_TRUE;
-            msg_Dbg (p_access, "at end of memory mapped file");
-            return NULL;
-        }
+    if (p_access->info.i_pos >= p_access->info.i_size)
+    {
+        /* We are at end of file */
+        p_access->info.b_eof = true;
+        msg_Dbg (p_access, "at end of memory mapped file");
+        return NULL;
     }
 
+#ifdef MMAP_DEBUG
+    uint64_t dbgpos = lseek (p_sys->fd, 0, SEEK_CUR);
+    if (dbgpos != p_access->info.i_pos)
+        msg_Err (p_access, "position: 0x%016"PRIx64" instead of 0x%016"PRIx64,
+                 p_access->info.i_pos, dbgpos);
+#endif
+
     const uintptr_t page_mask = p_sys->page_size - 1;
     /* Start the mapping on a page boundary: */
-    off_t  outer_offset = p_access->info.i_pos & ~page_mask;
+    off_t  outer_offset = p_access->info.i_pos & ~(off_t)page_mask;
     /* Skip useless bytes at the beginning of the first page: */
     size_t inner_offset = p_access->info.i_pos & page_mask;
     /* Map no more bytes than remain: */
@@ -201,36 +217,40 @@ static block_t *Block (access_t *p_access)
     /* NOTE: We use PROT_WRITE and MAP_PRIVATE so that the block can be
      * modified down the chain, without messing up with the underlying
      * original file. This does NOT need open write permission. */
-    void *addr = mmap (NULL, length, PROT_READ|PROT_WRITE, MAP_PRIVATE,
-                       p_sys->fd, outer_offset);
+    void *addr = mmap (NULL, length, PROT_READ|PROT_WRITE, MAP_PRIVATE
+#ifdef MAP_NO_CACHE
+                       | MAP_NOCACHE
+#endif
+                       , p_sys->fd, outer_offset);
     if (addr == MAP_FAILED)
     {
         msg_Err (p_access, "memory mapping failed (%m)");
-        intf_UserFatal (p_access, VLC_FALSE, _("File reading failed"),
+        dialog_Fatal (p_access, _("File reading failed"), "%s",
                         _("VLC could not read the file."));
-        msleep (INPUT_ERROR_SLEEP);
-        return NULL;
+        goto fatal;
     }
+#ifdef HAVE_POSIX_MADVISE    
     posix_madvise (addr, length, POSIX_MADV_SEQUENTIAL);
+#endif
 
     block_t *block = block_mmap_Alloc (addr, length);
     if (block == NULL)
-        return NULL;
+        goto fatal;
 
     block->p_buffer += inner_offset;
     block->i_buffer -= inner_offset;
 
-#ifndef NDEBUG
-    msg_Dbg (p_access, "mapped 0x%lx bytes at %p from offset 0x%lx",
-             (unsigned long)length, addr, (unsigned long)outer_offset);
+#ifdef MMAP_DEBUG
+    msg_Dbg (p_access, "mapped 0x%zx bytes at %p from offset 0x%"PRIx64,
+             length, addr, (uint64_t)outer_offset);
 
     /* Compare normal I/O with memory mapping */
     char *buf = malloc (block->i_buffer);
     ssize_t i_read = read (p_sys->fd, buf, block->i_buffer);
 
     if (i_read != (ssize_t)block->i_buffer)
-        msg_Err (p_access, "read %u instead of %u bytes", (unsigned)i_read,
-                 (unsigned)block->i_buffer);
+        msg_Err (p_access, "read %zd instead of %zu bytes", i_read,
+                 block->i_buffer);
     if (memcmp (buf, block->p_buffer, block->i_buffer))
         msg_Err (p_access, "inconsistent data buffer");
     free (buf);
@@ -238,37 +258,42 @@ static block_t *Block (access_t *p_access)
 
     p_access->info.i_pos = outer_offset + length;
     return block;
+
+fatal:
+    p_access->info.b_eof = true;
+    return NULL;
 }
 
 
-static int Seek (access_t *p_access, int64_t i_pos)
+static int Seek (access_t *p_access, uint64_t i_pos)
 {
+#ifdef MMAP_DEBUG
+    lseek (p_access->p_sys->fd, i_pos, SEEK_SET);
+#endif
+
     p_access->info.i_pos = i_pos;
-    p_access->info.b_eof = VLC_FALSE;
+    p_access->info.b_eof = false;
     return VLC_SUCCESS;
 }
 
 
 static int Control (access_t *p_access, int query, va_list args)
 {
-    access_sys_t *p_sys = p_access->p_sys;
-
     switch (query)
     {
         case ACCESS_CAN_SEEK:
         case ACCESS_CAN_FASTSEEK:
         case ACCESS_CAN_PAUSE:
         case ACCESS_CAN_CONTROL_PACE:
-            *((vlc_bool_t *)va_arg (args, vlc_bool_t *)) = VLC_TRUE;
-            return VLC_SUCCESS;
-
-        case ACCESS_GET_MTU:
-            *((int *)va_arg (args, int *)) = p_sys->mtu;
+            *va_arg(args, bool *) = true;
             return VLC_SUCCESS;
 
         case ACCESS_GET_PTS_DELAY:
-            *((int64_t *)va_arg (args, int64_t *)) = DEFAULT_PTS_DELAY;
+        {
+            int64_t delay_ms = var_CreateGetInteger (p_access, "file-caching");
+            *va_arg(args, int64_t *) = delay_ms * INT64_C (1000);
             return VLC_SUCCESS;
+        }
 
         case ACCESS_GET_TITLE_INFO:
         case ACCESS_GET_META: