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);
358bool Buffer::map_file(
const std::string & filename,
volatile int *fd, uint8_t **p,
size_t *filesize,
bool *isdefaultsize,
size_t defaultsize,
bool truncate)
const
375 *fd = ::open(
filename.c_str(), O_CREAT | O_RDWR | (truncate ? O_TRUNC : 0),
static_cast<mode_t
>(0644));
378 Logging::error(
filename,
"The cache file could not be opened due to an error: (%1) %2", errno, strerror(errno));
382 if (fstat(*fd, &sb) == -1)
388 if (!S_ISREG(sb.st_mode))
394 if (!sb.st_size || defaultsize)
400 defaultsize =
static_cast<size_t>(sysconf(_SC_PAGESIZE));
403 if (ftruncate(*fd,
static_cast<off_t
>(defaultsize)) == -1)
405 Logging::error(
filename,
"Error calling ftruncate() to 'stretch' the file: (%1) %2 (fd = %3)", errno, strerror(errno), *fd);
409 *filesize = defaultsize;
410 *isdefaultsize =
true;
415 *filesize =
static_cast<size_t>(sb.st_size);
416 *isdefaultsize =
false;
419 *p =
static_cast<uint8_t *
>(mmap(
nullptr, *filesize, PROT_READ | PROT_WRITE, MAP_SHARED, *fd, 0));
420 if (*p == MAP_FAILED)
427 catch (
bool _success)
431 if (!success && *fd != -1)
441bool Buffer::unmap_file(
const std::string &filename,
volatile int *fd, uint8_t **p,
size_t len,
size_t * filesize)
const
448 size_t _filesize = *filesize;
458 if (munmap(_p, len ? len :
static_cast<size_t>(sysconf(_SC_PAGESIZE))) == -1)
469 if (ftruncate(_fd,
static_cast<off_t
>(_filesize)) == -1)
471 Logging::error(
filename,
"Error calling ftruncate() to resize and close the cache file: (%1) %2 (fd = %3) Size: %5", errno, strerror(errno), _fd, _filesize);
480 if (unlink(
filename.c_str()) && errno != ENOENT)
482 Logging::error(
filename,
"Error removing the cache file: (%1) %2 (fd = %3)", errno, strerror(errno), _fd);
493 std::lock_guard<std::recursive_mutex> lock_mutex(
m_mutex);
530 if (!
m_ci[0].m_cachefile_idx.empty())
558 std::lock_guard<std::recursive_mutex> lock_mutex(
m_mutex);
586 std::lock_guard<std::recursive_mutex> lock_mutex(
m_mutex);
593 ci.m_buffer_watermark = 0;
594 ci.m_buffer_size = 0;
595 ci.m_seg_finished =
false;
596 ci.m_buffer_write_size = 0;
597 ci.m_buffer_writes = 0;
602 long filesize = sysconf(_SC_PAGESIZE);
604 if (ftruncate(ci.m_fd, filesize) == -1)
606 Logging::error(ci.m_cachefile,
"Error calling ftruncate() to clear the file: (%1) %2 (fd = %3)", errno, strerror(errno), ci.m_fd);
615 if (ci.m_fd_idx != -1)
617 std::memset(ci.m_buffer_idx, 0, ci.m_buffer_size_idx);
626 std::lock_guard<std::recursive_mutex> lock_mutex(
m_mutex);
631 Logging::error(
nullptr,
"INTERNAL ERROR: Buffer::reserve() - m_cur_ci == nullptr!");
638 Logging::error(
nullptr,
"INTERNAL ERROR: Buffer::reserve() - m_cur_ci->m_buffer == nullptr!");
670 std::lock_guard<std::recursive_mutex> lock_mutex(
m_mutex);
679 if (write_ptr ==
nullptr)
688 std::memcpy(write_ptr, data, length);
697 std::lock_guard<std::recursive_mutex> lock_mutex(
m_mutex);
708 size_t bytes_written;
709 size_t start =
static_cast<size_t>(frame_no - 1) *
sizeof(
IMAGE_FRAME);
713 if (old_image_frame->
m_frame_no && (old_image_frame->
m_size <=
static_cast<uint32_t
>(length)))
716 old_image_frame->
m_size =
static_cast<uint32_t
>(length);
719 seek(
static_cast<long>(old_image_frame->
m_offset), SEEK_SET);
721 if (bytes_written != old_image_frame->
m_size)
729 std::memset(&new_image_frame, 0xFF,
sizeof(new_image_frame));
733 new_image_frame.
m_size =
static_cast<uint32_t
>(length);
736 seek(
static_cast<long>(new_image_frame.
m_offset), SEEK_SET);
738 if (bytes_written != new_image_frame.
m_size)
746 return bytes_written;
773 return seek(offset, whence, 0);
780 if (ci ==
nullptr || ci->
m_buffer ==
nullptr)
797 seek_pos =
static_cast<off_t
>(
tell(segment_no)) + offset;
802 seek_pos =
static_cast<off_t
>(
size(segment_no)) + offset;
812 if (seek_pos >
static_cast<off_t
>(
size(segment_no)))
843 return ci->m_buffer_pos;
848 return AV_NOPTS_VALUE;
866 return ci->m_buffer_size;
879 return ci->m_buffer_watermark;
882bool Buffer::copy(std::vector<uint8_t> * out_data,
size_t offset, uint32_t segment_no)
884 return copy(out_data->data(), offset, out_data->size(), segment_no);
887bool Buffer::copy(uint8_t* out_data,
size_t offset,
size_t bufsize, uint32_t segment_no)
889 std::lock_guard<std::recursive_mutex> lock_mutex(
m_mutex);
899 if (ci->m_buffer ==
nullptr)
905 size_t segment_size = ci->m_buffer_size;
907 if (!segment_size && errno)
909 Logging::error(ci->m_cachefile,
"INTERNAL ERROR: Buffer::copy()! size(segment_no) returned error. Segment: %1 (%2) %3", segment_no, errno, strerror(errno));
913 if (segment_size > offset)
915 if (segment_size < offset +
bufsize)
917 bufsize = segment_size - offset - 1;
920 std::memcpy(out_data, ci->m_buffer + offset,
bufsize);
926 Logging::error(ci->m_cachefile,
"INTERNAL ERROR: Buffer::copy()! segment_size <= offset - Segment: %1 Segment Size: %2 Offset: %3", segment_no, segment_size, offset);
935 if (newsize >
size())
939 size_t alloc_size = newsize -
size();
942 if (write_size > alloc_size)
944 alloc_size = write_size;
946 newsize =
size() + alloc_size;
967 static std::string empty;
972 return ci->m_cachefile;
997 if (unlink(
filename.c_str()) && errno != ENOENT)
1018 std::lock_guard<std::recursive_mutex> lock_mutex(
m_mutex);
1028 size_t start =
static_cast<size_t>(frame_no - 1) *
sizeof(
IMAGE_FRAME);
1032 if (!image_frame->m_frame_no)
1038 data->resize(image_frame->m_size);
1040 return copy(data,
static_cast<size_t>(image_frame->m_offset));
1055 return (
tell(segment_no) ==
size(segment_no));
1065 std::lock_guard<std::recursive_mutex> lock_mutex(
m_mutex);
1075 size_t start =
static_cast<size_t>(frame_no - 1) *
sizeof(
IMAGE_FRAME);
1079 return (image_frame->m_frame_no ?
true :
false);
1084 std::lock_guard<std::recursive_mutex> lock_mutex(
m_mutex);
1088 if ((ci.m_fd != -1 && (fcntl(ci.m_fd, F_GETFL) != -1 || errno != EBADF)))
1119 return ci->m_seg_finished;
1132 return (&
m_ci[segment_no]);
1144 if (segment_no >=
m_ci.size())
1148 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.
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.
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.
struct IMAGE_FRAME IMAGE_FRAME
Image frame header.
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.
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.
volatile int m_fd
File handle for buffer.
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.