79 std::lock_guard<std::recursive_mutex> lock_mutex(
m_mutex);
81 uint32_t index = segment_no;
114 bool isdefaultsize =
false;
115 uint8_t *p =
nullptr;
128 ci.
m_buffer =
static_cast<uint8_t*
>(p);
139 std::lock_guard<std::recursive_mutex> lock_mutex(
m_mutex);
141 uint32_t index = segment_no;
181 std::lock_guard<std::recursive_mutex> lock_mutex(
m_mutex);
228 std::shared_ptr<char[]> cachefiletmp =
new_strdup(
m_ci[0].m_cachefile);
230 if (cachefiletmp ==
nullptr)
237 if (
mktree(dirname(cachefiletmp.get()), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) && errno != EEXIST)
239 Logging::error(
m_ci[0].m_cachefile,
"Error creating cache directory: (%1) %2", errno, strerror(errno));
244#if __cplusplus >= 202002L
264 if (!
m_ci[0].m_cachefile_idx.empty())
269 Logging::error(
m_ci[0].m_cachefile,
"INTERNAL ERROR: Buffer::init()! Frame count is zero (%1) %2", errno, strerror(errno));
272 static_assert(
sizeof(
IMAGE_FRAME) == 32,
"sizeof(IMAGE_FRAME) must be 32 bytes");
275 bool isdefaultsize =
false;
276 uint8_t *p =
nullptr;
283 m_ci[0].m_buffer_size_idx = filesize;
284 m_ci[0].m_buffer_idx =
static_cast<uint8_t*
>(p);
287 catch (
bool _success)
305 std::lock_guard<std::recursive_mutex> lock_mutex(
m_mutex);
331 std::lock_guard<std::recursive_mutex> lock_mutex(
m_mutex);
333 return static_cast<uint32_t
>(
m_ci.size());
338 std::lock_guard<std::recursive_mutex> lock_mutex(
m_mutex);
349 std::lock_guard<std::recursive_mutex> lock_mutex(
m_mutex);
356 uint32_t index = segment_no;
362 if (index >=
m_ci.size())
373 std::lock_guard<std::recursive_mutex> lock_mutex(
m_mutex);
384 if (stat(ci->m_cachefile.c_str(), &sb) == -1)
389 if (!S_ISREG(sb.st_mode))
407 std::lock_guard<std::recursive_mutex> lock_mutex(
m_mutex);
456bool Buffer::map_file(
const std::string & filename,
volatile int *fd, uint8_t **p,
size_t *filesize,
bool *isdefaultsize,
size_t defaultsize,
bool truncate)
const
473 *fd = ::open(
filename.c_str(), O_CREAT | O_RDWR | (truncate ? O_TRUNC : 0),
static_cast<mode_t
>(0644));
476 Logging::error(
filename,
"The cache file could not be opened due to an error: (%1) %2", errno, strerror(errno));
480 if (fstat(*fd, &sb) == -1)
486 if (!S_ISREG(sb.st_mode))
492 if (!sb.st_size || defaultsize)
498 defaultsize =
static_cast<size_t>(sysconf(_SC_PAGESIZE));
501 if (ftruncate(*fd,
static_cast<off_t
>(defaultsize)) == -1)
503 Logging::error(
filename,
"Error calling ftruncate() to 'stretch' the file: (%1) %2 (fd = %3)", errno, strerror(errno), *fd);
507 *filesize = defaultsize;
508 *isdefaultsize =
true;
513 *filesize =
static_cast<size_t>(sb.st_size);
514 *isdefaultsize =
false;
517 *p =
static_cast<uint8_t *
>(mmap(
nullptr, *filesize, PROT_READ | PROT_WRITE, MAP_SHARED, *fd, 0));
518 if (*p == MAP_FAILED)
525 catch (
bool _success)
529 if (!success && *fd != -1)
539bool Buffer::unmap_file(
const std::string &filename,
volatile int *fd, uint8_t **p,
size_t len,
size_t * filesize)
const
546 size_t _filesize = *filesize;
556 if (munmap(_p, len ? len :
static_cast<size_t>(sysconf(_SC_PAGESIZE))) == -1)
567 if (ftruncate(_fd,
static_cast<off_t
>(_filesize)) == -1)
569 Logging::error(
filename,
"Error calling ftruncate() to resize and close the cache file: (%1) %2 (fd = %3) Size: %5", errno, strerror(errno), _fd, _filesize);
578 if (unlink(
filename.c_str()) && errno != ENOENT)
580 Logging::error(
filename,
"Error removing the cache file: (%1) %2 (fd = %3)", errno, strerror(errno), _fd);
591 std::lock_guard<std::recursive_mutex> lock_mutex(
m_mutex);
628 if (!
m_ci[0].m_cachefile_idx.empty())
656 std::lock_guard<std::recursive_mutex> lock_mutex(
m_mutex);
684 std::lock_guard<std::recursive_mutex> lock_mutex(
m_mutex);
691 ci.m_buffer_watermark = 0;
692 ci.m_buffer_size = 0;
693 ci.m_seg_finished =
false;
694 ci.m_buffer_write_size = 0;
695 ci.m_buffer_writes = 0;
700 long filesize = sysconf(_SC_PAGESIZE);
702 if (ftruncate(ci.m_fd, filesize) == -1)
704 Logging::error(ci.m_cachefile,
"Error calling ftruncate() to clear the file: (%1) %2 (fd = %3)", errno, strerror(errno), ci.m_fd);
713 if (ci.m_fd_idx != -1)
715 std::memset(ci.m_buffer_idx, 0, ci.m_buffer_size_idx);
724 std::lock_guard<std::recursive_mutex> lock_mutex(
m_mutex);
729 Logging::error(
nullptr,
"INTERNAL ERROR: Buffer::reserve() - m_cur_ci == nullptr!");
736 Logging::error(
nullptr,
"INTERNAL ERROR: Buffer::reserve() - m_cur_ci->m_buffer == nullptr!");
768 std::lock_guard<std::recursive_mutex> lock_mutex(
m_mutex);
777 if (write_ptr ==
nullptr)
786 std::memcpy(write_ptr, data, length);
795 std::lock_guard<std::recursive_mutex> lock_mutex(
m_mutex);
806 size_t bytes_written;
807 size_t start =
static_cast<size_t>(frame_no - 1) *
sizeof(
IMAGE_FRAME);
811 if (old_image_frame->
m_frame_no && (old_image_frame->
m_size <=
static_cast<uint32_t
>(length)))
814 old_image_frame->
m_size =
static_cast<uint32_t
>(length);
817 seek(
static_cast<long>(old_image_frame->
m_offset), SEEK_SET);
819 if (bytes_written != old_image_frame->
m_size)
827 std::memset(&new_image_frame, 0xFF,
sizeof(new_image_frame));
831 new_image_frame.
m_size =
static_cast<uint32_t
>(length);
834 seek(
static_cast<long>(new_image_frame.
m_offset), SEEK_SET);
836 if (bytes_written != new_image_frame.
m_size)
844 return bytes_written;
871 return seek(offset, whence, 0);
878 if (ci ==
nullptr || ci->
m_buffer ==
nullptr)
895 seek_pos =
static_cast<off_t
>(
tell(segment_no)) + offset;
900 seek_pos =
static_cast<off_t
>(
size(segment_no)) + offset;
910 if (seek_pos >
static_cast<off_t
>(
size(segment_no)))
941 return ci->m_buffer_pos;
946 return AV_NOPTS_VALUE;
964 return ci->m_buffer_size;
977 return ci->m_buffer_watermark;
980bool Buffer::copy(std::vector<uint8_t> * out_data,
size_t offset, uint32_t segment_no)
982 return copy(out_data->data(), offset, out_data->size(), segment_no);
985bool Buffer::copy(uint8_t* out_data,
size_t offset,
size_t bufsize, uint32_t segment_no)
987 std::lock_guard<std::recursive_mutex> lock_mutex(
m_mutex);
997 if (ci->m_buffer ==
nullptr)
1003 size_t segment_size = ci->m_buffer_size;
1005 if (!segment_size && errno)
1007 Logging::error(ci->m_cachefile,
"INTERNAL ERROR: Buffer::copy()! size(segment_no) returned error. Segment: %1 (%2) %3", segment_no, errno, strerror(errno));
1011 if (segment_size > offset)
1013 if (segment_size < offset +
bufsize)
1015 bufsize = segment_size - offset - 1;
1018 std::memcpy(out_data, ci->m_buffer + offset,
bufsize);
1024 Logging::error(ci->m_cachefile,
"INTERNAL ERROR: Buffer::copy()! segment_size <= offset - Segment: %1 Segment Size: %2 Offset: %3", segment_no, segment_size, offset);
1033 if (newsize >
size())
1037 size_t alloc_size = newsize -
size();
1040 if (write_size > alloc_size)
1042 alloc_size = write_size;
1044 newsize =
size() + alloc_size;
1065 static std::string empty;
1070 return ci->m_cachefile;
1095 if (unlink(
filename.c_str()) && errno != ENOENT)
1116 std::lock_guard<std::recursive_mutex> lock_mutex(
m_mutex);
1126 size_t start =
static_cast<size_t>(frame_no - 1) *
sizeof(
IMAGE_FRAME);
1130 if (!image_frame->m_frame_no)
1136 data->resize(image_frame->m_size);
1138 return copy(data,
static_cast<size_t>(image_frame->m_offset));
1153 return (
tell(segment_no) ==
size(segment_no));
1163 std::lock_guard<std::recursive_mutex> lock_mutex(
m_mutex);
1173 size_t start =
static_cast<size_t>(frame_no - 1) *
sizeof(
IMAGE_FRAME);
1177 return (image_frame->m_frame_no ?
true :
false);
1182 std::lock_guard<std::recursive_mutex> lock_mutex(
m_mutex);
1186 if ((ci.m_fd != -1 && (fcntl(ci.m_fd, F_GETFL) != -1 || errno != EBADF)))
1217 return ci->m_seg_finished;
1230 return (&
m_ci[segment_no]);
1242 if (segment_no >=
m_ci.size())
1246 return (&
m_ci[segment_no]);
#define CACHE_FLAG_RO
Mark cache file read-only.
#define CACHE_FLAG_RW
Mark cache file writeable, implies read permissions.
#define CACHE_CHECK_BIT(mask, var)
Check bit in bitmask.
#define CACHE_CLOSE_DELETE
Delete cache entry, will unlink cached file! Implies CACHE_CLOSE_FREE.
bool invalidate_segment(uint32_t segment_no=0)
Invalidate the requested cache segment/file.
std::vector< CACHEINFO > m_ci
Cache info.
virtual int64_t duration() const override
Get the duration of the file, in AV_TIME_BASE fractional seconds.
static constexpr int PREALLOC_FACTOR
PREALLOC_FACTOR - Number of elements allocated on reallocate calls Number of elements allocated on re...
virtual bool eof() const override
Check if at end of file.
void increment_pos(size_t increment)
Increment buffer position.
LPCACHEINFO cacheinfo(uint32_t segment_no)
Get cache information.
uint8_t * write_prepare(size_t length)
Prepare for the writing operation.
bool release(int flags=CACHE_CLOSE_NOOPT)
Release cache buffer.
uint32_t m_cur_open
Number of open files.
virtual int openio(LPVIRTUALFILE virtualfile) override
Open a virtual file.
bool segment_exists(uint32_t segment_no)
Check if segment exists.
void finished_segment()
Complete the segment decoding.
bool cachefile_valid(uint32_t segment_no)
Check whether the physical cache file for the requested segment exists and contains data.
virtual int seek(int64_t offset, int whence) override
Seek to position in file.
size_t writeio(const uint8_t *data, size_t length)
Write data to the current position in the buffer. The position pointer will be updated.
bool clear()
Clear (delete) buffer.
bool map_file(const std::string &filename, volatile int *fd, uint8_t **p, size_t *filesize, bool *isdefaultsize, size_t defaultsize, bool truncate) const
Map memory to a file.
virtual ~Buffer()
Free Buffer object.
bool unmap_file(const std::string &filename, volatile int *fd, uint8_t **p, size_t len, size_t *filesize) const
Unmap memory from the file.
virtual void closeio() override
Close buffer.
virtual VIRTUALTYPE type() const override
Get type of this virtual file.
bool init(bool erase_cache)
Initialise cache.
std::recursive_mutex m_mutex
Access mutex.
bool is_segment_finished(uint32_t segment_no) const
Return true if transcoding of the segment is finished.
static bool remove_file(const std::string &filename)
Remove (unlink) the file.
size_t write_frame(const uint8_t *data, size_t length, uint32_t frame_no)
Write image data for the frame number into the buffer.
CACHEINFO const * LPCCACHEINFO
Pointer to const version of CACHEINFO.
const std::string & cachefile(uint32_t segment_no) const
Get cache filename.
virtual size_t readio(void *data, size_t size) override
Not implemented.
bool have_frame(uint32_t frame_no)
Check if we have the requested frame number. Works only when processing a frame set.
bool flush()
Flush buffer to disk.
static const std::string & make_cachefile_name(std::string *cachefile, const std::string &filename, const std::string &fileext, bool is_idx)
Make up a cache file name, including the full path.
bool reserve(size_t size)
Reserve memory without changing size to reduce re-allocations.
uint32_t current_segment_no()
Get the currently selected segment.
bool reallocate(size_t newsize)
Reallocate the buffer to a new size.
virtual int error() const override
Get last error.
bool copy(std::vector< uint8_t > *out_data, size_t offset, uint32_t segment_no=0)
Copy buffered data into output buffer.
virtual size_t bufsize() const override
Size of this buffer.
LPCCACHEINFO const_cacheinfo(uint32_t segment_no) const
Get cache information.
uint32_t segment_count()
Get segment count.
virtual size_t tell() const override
Get the value of the internal read position pointer.
LPCACHEINFO m_cur_ci
Convenience pointer to current write segment.
bool set_segment(uint32_t segment_no, size_t size)
Set the current segment.
bool remove_cachefile(uint32_t segment_no=0) const
Remove the cachefile.
Buffer()
Create Buffer object.
bool is_open()
Check if the cache file is open.
virtual size_t size() const override
Get the value of the internal buffer size pointer.
bool open_file(uint32_t segment_no, uint32_t flags, size_t defaultsize=0)
Open the cache file if not already open.
bool close_file(uint32_t segment_no, uint32_t flags)
If it hasn't already been done, close the cache file.
size_t buffer_watermark(uint32_t segment_no=0) const
Return the current watermark of the file while transcoding.
size_t read_frame(std::vector< uint8_t > *data, uint32_t frame_no)
Write image data for the frame number into the buffer.
LPVIRTUALFILE virtualfile()
Get virtual file object.
void set_virtualfile(LPVIRTUALFILE virtualfile)
Set the virtual file object.
const std::string & filename() const
Get source filename.
static void warning(const T filename, const std::string &format_string, Args &&...args)
Write warning level log entry.
static void debug(const T filename, const std::string &format_string, Args &&...args)
Write debug level log entry.
static void trace(const T filename, const std::string &format_string, Args &&...args)
Write trace level log entry.
static void error(const T filename, const std::string &format_string, Args &&...args)
Write error level log entry.
int mktree(const std::string &path, mode_t mode)
Make directory tree.
std::shared_ptr< char[]> new_strdup(const std::string &str)
strdup() variant taking a std::string as input.
std::string make_filename(uint32_t file_no, const std::string &fileext)
Make a file name from file number and file extension.
bool file_exists(const std::string &filename)
Check if file exists.
std::string format_size(uint64_t value)
Format size.
FFMPEGFS_PARAMS params
FFmpegfs command line parameters.
Main include for FFmpegfs project.
void transcoder_cache_path(std::string *path)
Get transcoder cache path.
VIRTUALTYPE
Virtual file types enum.
IMAGE_FRAME const * LPCIMAGE_FRAME
Pointer version of IMAGE_FRAME.
#define VIRTUALFLAG_HLS
File is part of a set of HLS transport stream (ts) files.
#define VIRTUALFLAG_FRAME
File is part of a set of frames.
#define IMAGE_FRAME_TAG
Tag of an image frame header for the frame images buffer.
Provide various log facilities to stderr, disk or syslog.
Structure to hold current cache state.
int m_fd
File handle for buffer.
size_t m_buffer_write_size
Sum of bytes written to the buffer.
uint8_t * m_buffer
Pointer to buffer memory.
bool m_seg_finished
True if segment completely decoded.
unsigned int m_buffer_writes
Total number of writes to the buffer.
size_t m_buffer_size_idx
Size of index buffer.
uint8_t * m_buffer_idx
Pointer to index memory.
size_t m_buffer_size
Current buffer size.
std::string m_cachefile
Cache file name.
uint32_t m_flags
CACHE_FLAG_* options.
size_t m_buffer_watermark
Number of bytes in buffer.
size_t m_buffer_pos
Read/write position.
std::string m_cachefile_idx
Index file name.
const FFmpegfs_Format * current_format(LPCVIRTUALFILE virtualfile) const
Get FFmpegfs_Format for a virtual file.
std::string m_mountpath
Mount path: Files from m_mountpath will be mapped to this directory.
uint64_t m_offset
Offset in index file.
uint32_t m_size
Image size in bytes.
uint32_t m_frame_no
Number of the frame image. 0 if not yet decoded.
std::array< char, 8 > m_tag
Start tag, always ascii "IMGFRAME".
uint32_t get_segment_count() const
Number of HLS segments in set.
uint32_t m_video_frame_count
Number of frames in video or 0 if not a video.