Browse Source
Previously, we always loaded entire videos in memory before playing them. `libsmacker` does not provide a streaming API but it does provide a `FILE *` file pointer API. We now take advantage of the `FILE *` API by streaming the videos on platforms that support `fopencookie`. This means faster startup and less memory usage on these platforms.pull/1786/head
6 changed files with 130 additions and 29 deletions
@ -0,0 +1,74 @@
|
||||
#include "storm_file_wrapper.h" |
||||
|
||||
#ifdef DEVILUTIONX_STORM_FILE_WRAPPER_AVAILABLE |
||||
|
||||
#include "storm/storm.h" |
||||
#include "utils/log.hpp" |
||||
|
||||
namespace devilution { |
||||
extern "C" { |
||||
|
||||
#ifdef DEVILUTIONX_STORM_FILE_WRAPPER_IMPL_FOPENCOOKIE |
||||
|
||||
ssize_t SFileCookieRead(void *cookie, char *buf, size_t nbytes) |
||||
{ |
||||
DWORD numRead = 0; |
||||
if (!SFileReadFile(static_cast<HANDLE>(cookie), buf, nbytes, &numRead, nullptr)) { |
||||
const DWORD errCode = SErrGetLastError(); |
||||
if (errCode != STORM_ERROR_HANDLE_EOF) { |
||||
Log("SFileRwRead error: {} ERROR CODE {}", (unsigned int)nbytes, (unsigned int)errCode); |
||||
} |
||||
} |
||||
return numRead; |
||||
} |
||||
|
||||
int SFileCookieSeek(void *cookie, off64_t *pos, int whence) |
||||
{ |
||||
int swhence; |
||||
switch (whence) { |
||||
case SEEK_SET: |
||||
swhence = DVL_FILE_BEGIN; |
||||
break; |
||||
case SEEK_CUR: |
||||
swhence = DVL_FILE_CURRENT; |
||||
break; |
||||
case SEEK_END: |
||||
swhence = DVL_FILE_END; |
||||
break; |
||||
default: |
||||
return -1; |
||||
} |
||||
const std::uint64_t spos = SFileSetFilePointer(static_cast<HANDLE>(cookie), *pos, swhence); |
||||
if (spos == static_cast<std::uint64_t>(-1)) { |
||||
Log("SFileRwSeek error: {}", (unsigned int)SErrGetLastError()); |
||||
return -1; |
||||
} |
||||
*pos = static_cast<off64_t>(spos); |
||||
return 0; |
||||
} |
||||
|
||||
int SFileCookieClose(void *cookie) |
||||
{ |
||||
return SFileCloseFile(static_cast<HANDLE>(cookie)) ? 0 : -1; |
||||
} |
||||
|
||||
} // extern "C"
|
||||
#endif |
||||
|
||||
FILE *FILE_FromStormHandle(HANDLE handle) |
||||
{ |
||||
#ifdef DEVILUTIONX_STORM_FILE_WRAPPER_IMPL_FOPENCOOKIE |
||||
cookie_io_functions_t ioFns; |
||||
std::memset(&ioFns, 0, sizeof(ioFns)); |
||||
ioFns.read = &SFileCookieRead; |
||||
ioFns.seek = &SFileCookieSeek; |
||||
ioFns.close = &SFileCookieClose; |
||||
return fopencookie(handle, "rb", ioFns); |
||||
#else |
||||
#error "unimplemented" |
||||
#endif |
||||
} |
||||
|
||||
} // namespace devilution
|
||||
|
||||
#endif |
||||
@ -0,0 +1,17 @@
|
||||
/** A pointer to a Storm file as a `FILE *`. Only available on some platforms. */ |
||||
#pragma once |
||||
#if defined(__linux__) || defined(__FreeBSD__) || defined(__DragonFly__) |
||||
#include <cstdio> |
||||
|
||||
#include "miniwin/miniwin.h" |
||||
|
||||
#define DEVILUTIONX_STORM_FILE_WRAPPER_AVAILABLE |
||||
#define DEVILUTIONX_STORM_FILE_WRAPPER_IMPL_FOPENCOOKIE |
||||
|
||||
namespace devilution { |
||||
|
||||
FILE *FILE_FromStormHandle(HANDLE handle); |
||||
|
||||
} // namespace devilution
|
||||
|
||||
#endif |
||||
Loading…
Reference in new issue