Jean-Baptiste Kempf pushed to branch master at VideoLAN / VLC


Commits:
f78a65f0 by Steve Lhomme at 2023-01-24T07:54:05+00:00
frame: use a more Win32 friendly version of reading a file in memory

It's only used when the file cannot be mapped in memory.

This was not a real implementation of pread. As the comment suggests, the
original offset was not respected. But we don't care in this case as we 
want to
read the whole file from start to end.

It is now a cancelation point. We can't cancel during the duration of the
ReadFile call, but at least we cancel when it's done even if the whole file 
is
not read.

- - - - -
2db583da by Steve Lhomme at 2023-01-24T07:54:05+00:00
frame: return early if the win32 HANDLE is not usable

- - - - -
b409c9c4 by Steve Lhomme at 2023-01-24T07:54:05+00:00
frame: handle cancelation when memory mapping on Win32

The function is a cancelation point, so we should handle it from all code
pathes.

- - - - -


1 changed file:

- src/misc/frame.c


Changes:

=====================================
src/misc/frame.c
=====================================
@@ -386,23 +386,10 @@ vlc_frame_t *vlc_frame_shm_Alloc (void *addr, size_t 
length)
 
 
 #ifdef _WIN32
-# include <io.h>
-
-static
-ssize_t pread (int fd, void *buf, size_t count, off_t offset)
+static void cleanup_hmap(void *opaque)
 {
-    HANDLE handle = (HANDLE)(intptr_t)_get_osfhandle (fd);
-    if (handle == INVALID_HANDLE_VALUE)
-        return -1;
-
-    OVERLAPPED olap = {.Offset = offset, .OffsetHigh = (offset >> 32)};
-    DWORD written;
-    /* This braindead API will override the file pointer even if we specify
-     * an explicit read offset... So do not expect this to mix well with
-     * regular read() calls. */
-    if (ReadFile (handle, buf, count, &written, &olap))
-        return written;
-    return -1;
+    HANDLE hMap = opaque;
+    CloseHandle(hMap);
 }
 #endif
 
@@ -451,30 +438,39 @@ vlc_frame_t *vlc_frame_File(int fd, bool write)
             return vlc_frame_mmap_Alloc (addr, length);
     }
 #elif defined(_WIN32)
+    HANDLE handle = INVALID_HANDLE_VALUE;
     if (length > 0)
     {
-        HANDLE handle = (HANDLE)(intptr_t)_get_osfhandle (fd);
-        if (handle != INVALID_HANDLE_VALUE)
+        handle = (HANDLE)(intptr_t)_get_osfhandle (fd);
+        if (handle == INVALID_HANDLE_VALUE)
         {
-            void *addr = NULL;
-            HANDLE hMap;
-            DWORD prot = write ? PAGE_READWRITE : PAGE_READONLY;
-            DWORD access = FILE_MAP_READ | (write ? FILE_MAP_WRITE : 0);
+            errno = EBADF;
+            return NULL;
+        }
+
+        void *addr = NULL;
+        HANDLE hMap;
+        DWORD prot = write ? PAGE_READWRITE : PAGE_READONLY;
+        DWORD access = FILE_MAP_READ | (write ? FILE_MAP_WRITE : 0);
 #ifdef VLC_WINSTORE_APP
-            hMap = CreateFileMappingFromApp(handle, NULL, prot, length, NULL);
-            if (hMap != INVALID_HANDLE_VALUE)
-                addr = MapViewOfFileFromApp(hMap, access, 0, length);
+        hMap = CreateFileMappingFromApp(handle, NULL, prot, length, NULL);
+        if (hMap != INVALID_HANDLE_VALUE)
+            addr = MapViewOfFileFromApp(hMap, access, 0, length);
 #else
-            hMap = CreateFileMapping(handle, NULL, prot, 0, length, NULL);
-            if (hMap != INVALID_HANDLE_VALUE)
-                addr = MapViewOfFile(hMap, access, 0, 0, length);
+        DWORD hLength = (DWORD)(length >> 32);
+        DWORD lLength = (DWORD)(length & 0xFFFFFFFF);
+        hMap = CreateFileMapping(handle, NULL, prot, hLength, lLength, NULL);
+        if (hMap != INVALID_HANDLE_VALUE)
+            addr = MapViewOfFile(hMap, access, 0, 0, length);
 #endif
+        vlc_cleanup_push(cleanup_hmap, hMap);
+        vlc_testcancel();
+        vlc_cleanup_pop();
 
-            if (addr != NULL)
-                return vlc_frame_mapview_Alloc(hMap, addr, length);
+        if (addr != NULL)
+            return vlc_frame_mapview_Alloc(hMap, addr, length);
 
-            CloseHandle(hMap);
-        }
+        CloseHandle(hMap);
     }
 #else
     (void) write;
@@ -486,6 +482,48 @@ vlc_frame_t *vlc_frame_File(int fd, bool write)
         return NULL;
     vlc_frame_cleanup_push (frame);
 
+#if defined(_WIN32)
+    LARGE_INTEGER srcPointer = { 0 };
+    if (unlikely(!SetFilePointerEx(handle, srcPointer, &srcPointer, 
FILE_CURRENT)))
+    {
+        vlc_frame_Release (frame);
+        frame = NULL;
+        errno = EIO;
+        goto done;
+    }
+    LARGE_INTEGER startPointer = { 0 };
+    if (unlikely(!SetFilePointerEx(handle, startPointer, NULL, FILE_BEGIN)))
+    {
+        vlc_frame_Release (frame);
+        frame = NULL;
+        errno = EIO;
+        goto done;
+    }
+    for (size_t i = 0; i < length;)
+    {
+        DWORD hOffset = (DWORD)(i >> 32);
+        DWORD lOffset = (DWORD)(i & 0xFFFFFFFF);
+        OVERLAPPED olap = {.Offset = hOffset, .OffsetHigh = lOffset};
+        DWORD lLength = (length - i) > ULONG_MAX ? ULONG_MAX : (DWORD)(length 
- i);
+        DWORD len;
+        if (!ReadFile(handle, frame->p_buffer + i, lLength, &len, &olap))
+        {
+            vlc_frame_Release (frame);
+            frame = NULL;
+            errno = EIO;
+            break;
+        }
+        vlc_testcancel();
+        i += len;
+    }
+    if (unlikely(!SetFilePointerEx(handle, srcPointer, NULL, FILE_BEGIN)))
+    {
+        vlc_frame_Release (frame);
+        frame = NULL;
+        errno = EIO;
+        goto done;
+    }
+#else // !_WIN32
     for (size_t i = 0; i < length;)
     {
         ssize_t len = pread (fd, frame->p_buffer + i, length - i, i);
@@ -497,6 +535,8 @@ vlc_frame_t *vlc_frame_File(int fd, bool write)
         }
         i += len;
     }
+#endif // !_WIN32
+done:
     vlc_cleanup_pop ();
     return frame;
 }



View it on GitLab: 
https://code.videolan.org/videolan/vlc/-/compare/6d65ec658949c63546af2df9758865aeed1a23e5...b409c9c4733ef21d24bef958d1755f6d555711a0

-- 
View it on GitLab: 
https://code.videolan.org/videolan/vlc/-/compare/6d65ec658949c63546af2df9758865aeed1a23e5...b409c9c4733ef21d24bef958d1755f6d555711a0
You're receiving this email because of your account on code.videolan.org.


VideoLAN code repository instance
_______________________________________________
vlc-commits mailing list
vlc-commits@videolan.org
https://mailman.videolan.org/listinfo/vlc-commits

Reply via email to