stream-deploy/ZLM/3rdpart/media-server/libmkv/test/mkv-file-buffer.c

157 lines
3.3 KiB
C++

#include "mkv-buffer.h"
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#if defined(_WIN32) || defined(_WIN64)
#define fseek64 _fseeki64
#define ftell64 _ftelli64
#elif defined(OS_LINUX)
#define fseek64 fseeko64
#define ftell64 ftello64
#else
#define fseek64 fseek
#define ftell64 ftell
#endif
static int mkv_file_read(void* fp, void* data, uint64_t bytes)
{
if (bytes == fread(data, 1, bytes, (FILE*)fp))
return 0;
return 0 != ferror((FILE*)fp) ? ferror((FILE*)fp) : -1 /*EOF*/;
}
static int mkv_file_write(void* fp, const void* data, uint64_t bytes)
{
return bytes == fwrite(data, 1, bytes, (FILE*)fp) ? 0 : ferror((FILE*)fp);
}
static int mkv_file_seek(void* fp, int64_t offset)
{
return fseek64((FILE*)fp, offset, offset >= 0 ? SEEK_SET : SEEK_END);
}
static int64_t mkv_file_tell(void* fp)
{
return ftell64((FILE*)fp);
}
static int mkv_file_cache_read(void* fp, void* data, uint64_t bytes)
{
uint8_t* p = (uint8_t*)data;
struct mkv_file_cache_t* file = (struct mkv_file_cache_t*)fp;
while (bytes > 0)
{
assert(file->off <= file->len);
if (file->off >= file->len)
{
if (bytes >= sizeof(file->ptr))
{
if (bytes == fread(p, 1, bytes, file->fp))
{
file->tell += bytes;
return 0;
}
return 0 != ferror(file->fp) ? ferror(file->fp) : -1 /*EOF*/;
}
else
{
file->off = 0;
file->len = fread(file->ptr, 1, sizeof(file->ptr), file->fp);
if (file->len < 1)
return 0 != ferror(file->fp) ? ferror(file->fp) : -1 /*EOF*/;
}
}
if (file->off < file->len)
{
unsigned int n = file->len - file->off;
n = n > bytes ? bytes : n;
memcpy(p, file->ptr + file->off, n);
file->tell += n;
file->off += n;
bytes -= n;
p += n;
}
}
return 0;
}
static int mkv_file_cache_write(void* fp, const void* data, uint64_t bytes)
{
struct mkv_file_cache_t* file = (struct mkv_file_cache_t*)fp;
file->tell += bytes;
if (file->off + bytes < sizeof(file->ptr))
{
memcpy(file->ptr + file->off, data, bytes);
file->off += bytes;
return 0;
}
// write buffer
if (file->off > 0)
{
if (file->off != fwrite(file->ptr, 1, file->off, file->fp))
return ferror(file->fp);
file->off = 0; // clear buffer
}
// write data;
return bytes == fwrite(data, 1, bytes, file->fp) ? 0 : ferror(file->fp);
}
static int mkv_file_cache_seek(void* fp, int64_t offset)
{
int r;
struct mkv_file_cache_t* file = (struct mkv_file_cache_t*)fp;
if (offset != file->tell)
{
if (file->off > file->len)
{
// write bufferred data
if (file->off != fwrite(file->ptr, 1, file->off, file->fp))
return ferror(file->fp);
}
file->off = file->len = 0;
r = fseek64(file->fp, offset, offset >= 0 ? SEEK_SET : SEEK_END);
file->tell = ftell64(file->fp);
return r;
}
return 0;
}
static int64_t mkv_file_cache_tell(void* fp)
{
struct mkv_file_cache_t* file = (struct mkv_file_cache_t*)fp;
if (ftell64(file->fp) != file->tell + (int)(file->len - file->off))
return -1;
return (int64_t)file->tell;
//return ftell64(file->fp);
}
const struct mkv_buffer_t* mkv_file_buffer(void)
{
static struct mkv_buffer_t s_io = {
mkv_file_read,
mkv_file_write,
mkv_file_seek,
mkv_file_tell,
};
return &s_io;
}
const struct mkv_buffer_t* mkv_file_cache_buffer(void)
{
static struct mkv_buffer_t s_io = {
mkv_file_cache_read,
mkv_file_cache_write,
mkv_file_cache_seek,
mkv_file_cache_tell,
};
return &s_io;
}