FFmpegfs Fuse Multi Media Filesystem 2.16
cache_entry.cc
Go to the documentation of this file.
1/*
2 * Copyright (C) 2017-2024 Norbert Schlia (nschlia@oblivion-software.de)
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 3 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
17 *
18 * On Debian systems, the complete text of the GNU General Public License
19 * Version 3 can be found in `/usr/share/common-licenses/GPL-3'.
20 */
21
32#include "cache_entry.h"
33#include "ffmpegfs.h"
34#include "buffer.h"
35#include "logging.h"
36
37#include <cstring>
38
40 : m_owner(owner)
41 , m_ref_count(0)
42 , m_virtualfile(virtualfile)
43 , m_is_decoding(false)
44 , m_suspend_timeout(false)
45 , m_seek_to_no(0)
46{
49
50 m_cache_info.m_desttype[0] = '\0';
52
53 m_buffer = std::make_unique<Buffer>();
54
55 if (m_buffer != nullptr)
56 {
57 m_buffer->openio(virtualfile);
58 }
59
60 clear();
61
62 Logging::trace(filename(), "Created a new cache entry.");
63}
64
66{
67 std::unique_lock<std::recursive_mutex> lock_active_mutex(m_active_mutex);
68
69 unlock();
70
71 Logging::trace(filename(), "Deleted buffer.");
72}
73
75{
76 return new(std::nothrow) Cache_Entry(owner, virtualfile);
77}
78
80{
81 delete this;
82 return true;
83}
84
85void Cache_Entry::clear(bool fetch_file_time /*= true*/)
86{
87 m_is_decoding = false;
88
89 // Initialise ID3v1.1 tag structure
91
92 //m_cache_info.m_enable_ismv = params.m_enable_ismv;
103 m_cache_info.m_error = false;
108
109 if (fetch_file_time)
110 {
111 struct stat sb;
112
113 if (stat(filename(), &sb) == -1)
114 {
117 }
118 else
119 {
120 m_cache_info.m_file_time = sb.st_mtime;
121 m_cache_info.m_file_size = static_cast<size_t>(sb.st_size);
122 }
123 }
124
125 if (m_buffer != nullptr)
126 {
127 m_buffer->clear();
128 }
129}
130
132{
134}
135
137{
139}
140
142{
144}
145
146bool Cache_Entry::update_access(bool update_database /*= false*/)
147{
148 m_cache_info.m_access_time = time(nullptr);
149
150 if (update_database)
151 {
153 }
154 else
155 {
156 return true;
157 }
158}
159
160bool Cache_Entry::openio(bool create_cache /*= true*/)
161{
162 if (m_buffer == nullptr)
163 {
164 errno = EINVAL;
165 return false;
166 }
167
168 if (m_ref_count++ > 0) // fetch_and_add
169 {
170 // Already open
171 return true;
172 }
173
174 bool erase_cache = !read_info(); // If read_info fails, rebuild cache entry
175
176 if (!create_cache)
177 {
178 return true;
179 }
180
181 if (!is_finished())
182 {
183 // If no database entry found (database is not consistent),
184 // or file was not completely transcoded last time,
185 // simply create a new file.
186 erase_cache = true;
187 }
188
189 Logging::trace(filename(), "The last transcode was completed. Result %1 Erasing cache: %2.", static_cast<int>(m_cache_info.m_result), erase_cache);
190
191 // Store access time
192 update_access(true);
193
194 // Open the cache
195 if (m_buffer->init(erase_cache))
196 {
197 return true;
198 }
199 else
200 {
201 clear(false);
202 return false;
203 }
204}
205
207{
208 if (m_buffer->release(flags))
209 {
210 if (flags)
211 {
212 delete_info();
213 }
214 }
215}
216
217bool Cache_Entry::closeio(int flags)
218{
219 write_info();
220
221 if (m_buffer == nullptr)
222 {
223 errno = EINVAL;
224 return false;
225 }
226
227 if (!m_ref_count)
228 {
229 close_buffer(flags);
230
231 return true;
232 }
233
234 if (--m_ref_count > 0) // sub_and_fetch
235 {
236 // Just flush to disk
237 flush();
238 return false;
239 }
240
241 close_buffer(flags);
242
243 return true;
244}
245
247{
248 if (m_buffer == nullptr)
249 {
250 errno = EINVAL;
251 return false;
252 }
253
254 m_buffer->flush();
255 //write_info();
256
257 return true;
258}
259
260size_t Cache_Entry::size() const
261{
263 {
265 }
266 else
267 {
268 if (m_buffer == nullptr)
269 {
271 }
272 else
273 {
274 size_t current_size = m_buffer->buffer_watermark();
275
276 return std::max(current_size, m_cache_info.m_predicted_filesize);
277 }
278 }
279}
280
282{
284}
285
286time_t Cache_Entry::age() const
287{
288 return (time(nullptr) - m_cache_info.m_creation_time);
289}
290
292{
294}
295
297{
298 return (age() > params.m_expiry_time);
299}
300
302{
303 return (((time(nullptr) - m_cache_info.m_access_time) >= params.m_max_inactive_suspend) && m_ref_count <= 1);
304}
305
307{
308 return (((time(nullptr) - m_cache_info.m_access_time) >= params.m_max_inactive_abort) && m_ref_count <= 1);
309}
310
311const char * Cache_Entry::filename() const
312{
313 return (m_virtualfile != nullptr ? m_virtualfile->m_origfile.c_str() : "");
314}
315
316const char *Cache_Entry::destname() const
317{
318 return (m_virtualfile != nullptr ? m_virtualfile->m_destfile.c_str() : "");
319}
320
321const char * Cache_Entry::virtname() const
322{
323 return (m_virtualfile != nullptr ? m_virtualfile->m_virtfile.c_str() : "");
324}
325
327{
328 m_mutex.lock();
329}
330
332{
333 m_mutex.unlock();
334}
335
337{
338 return m_ref_count;
339}
340
342{
343 return m_ref_count++; // fetch_and_add
344}
345
347{
348 return --m_ref_count; // sub_and_fetch
349}
350
352{
353 struct stat sb;
354
356 {
358 {
359 // Report if old rate is known
360 Logging::debug(filename(), "Triggering re-transcode: Selected audio bitrate changed from %1 to %2.", m_cache_info.m_audiobitrate, params.m_audiobitrate);
361 }
362 return true;
363 }
364
366 {
368 {
369 // Report if old rate is known
370 Logging::debug(filename(), "Triggering re-transcode: Selected audio samplerate changed from %1 to %2.", m_cache_info.m_audiosamplerate, params.m_audiosamplerate);
371 }
372 return true;
373 }
374
376 {
378 {
379 // Report if old rate is known
380 Logging::debug(filename(), "Triggering re-transcode: Selected video bitrate changed from %1 to %2.", m_cache_info.m_audiobitrate, params.m_audiobitrate);
381 }
382 return true;
383 }
384
386 {
388 {
389 // Report if old dimensions is known
390 Logging::debug(filename(), "Triggering re-transcode: Selected video witdh/height changed from %1/%2 to %3/%4.", m_cache_info.m_videowidth, m_cache_info.m_videoheight, params.m_videowidth, params.m_videoheight);
391 }
392 return true;
393 }
394
395 if (m_cache_info.m_deinterlace != (params.m_deinterlace ? true : false))
396 {
397 Logging::debug(filename(), "Triggering re-transcode: Selected video deinterlace changed from %1 to %2.", m_cache_info.m_deinterlace, params.m_deinterlace);
398 return true;
399 }
400
401 if (stat(filename(), &sb) != -1)
402 {
403 // If source file exists, check file date/size
404 if (m_cache_info.m_file_time < sb.st_mtime)
405 {
406 Logging::debug(filename(), "Triggering re-transcode: File time has gone forward.");
407 return true;
408 }
409
410 if (m_cache_info.m_file_size != static_cast<size_t>(sb.st_size))
411 {
412 Logging::debug(filename(), "Triggering re-transcode: File size has changed.");
413 return true;
414 }
415 }
416
417 return false;
418}
419
421{
422 return m_virtualfile;
423}
424
426{
428}
429
430unsigned int Cache_Entry::read_count() const
431{
433}
434
436{
438}
439
441{
443}
444
446{
448}
449
451{
453}
Buffer class.
@ FINISHED_ERROR
Transcode finished with error.
@ FINISHED_INCOMPLETE
Transcode finished, but incomplete.
@ NONE
No result code available.
@ FINISHED_SUCCESS
Transcode finished successfully.
Cache entry
The Cache_Entry class.
Definition: cache_entry.h:49
size_t size() const
Return size of output file, as computed by encoder.
Definition: cache_entry.cc:260
CACHE_INFO m_cache_info
Info about cached object.
Definition: cache_entry.h:277
bool update_access(bool update_database=false)
Update last access time.
Definition: cache_entry.cc:146
bool is_finished_error() const
Get if cache has been finished and with an error.
Definition: cache_entry.cc:450
static Cache_Entry * create(Cache *owner, LPVIRTUALFILE virtualfile)
Create a new Cache_Entry object.
Definition: cache_entry.cc:74
time_t age() const
Get the age of the cache entry.
Definition: cache_entry.cc:286
bool is_finished() const
Get if cache has been finished.
Definition: cache_entry.cc:435
std::recursive_mutex m_mutex
Access mutex.
Definition: cache_entry.h:264
bool suspend_timeout() const
Check for decode suspend timeout.
Definition: cache_entry.cc:301
Cache * m_owner
Owner cache object.
Definition: cache_entry.h:263
int ref_count() const
Get the current reference counter.
Definition: cache_entry.cc:336
void lock()
Lock the access mutex.
Definition: cache_entry.cc:326
std::atomic_bool m_is_decoding
true while file is decoding
Definition: cache_entry.h:272
void close_buffer(int flags)
Close buffer object.
Definition: cache_entry.cc:206
const char * virtname() const
Return virtual filename. Same as destination filename, but with virtual (mount) path....
Definition: cache_entry.cc:321
LPVIRTUALFILE m_virtualfile
Underlying virtual file object.
Definition: cache_entry.h:268
void clear(bool fetch_file_time=true)
Clear the cache entry.
Definition: cache_entry.cc:85
const char * destname() const
Return destination filename.
Definition: cache_entry.cc:316
LPVIRTUALFILE virtualfile()
Get the underlying VIRTUALFILE object.
Definition: cache_entry.cc:420
bool write_info()
Write cache info.
Definition: cache_entry.cc:136
bool destroy()
Destroy this Cache_Entry object.
Definition: cache_entry.cc:79
bool openio(bool create_cache=true)
Open the cache file.
Definition: cache_entry.cc:160
Cache_Entry(Cache *owner, LPVIRTUALFILE virtualfile)
Create Cache_Entry object.
Definition: cache_entry.cc:39
void update_read_count()
Update read counter.
Definition: cache_entry.cc:425
std::atomic_int m_ref_count
Reference counter.
Definition: cache_entry.h:266
const char * filename() const
Return source filename.
Definition: cache_entry.cc:311
int decr_refcount()
Decrement the current reference counter.
Definition: cache_entry.cc:346
time_t last_access() const
Get last access time.
Definition: cache_entry.cc:291
std::recursive_mutex m_active_mutex
Mutex while thread is active.
Definition: cache_entry.h:273
ID3v1 m_id3v1
ID3v1 structure which is used to send to clients.
Definition: cache_entry.h:279
uint32_t video_frame_count() const
Get the video frame count.
Definition: cache_entry.cc:281
bool closeio(int flags)
Close the cache entry.
Definition: cache_entry.cc:217
unsigned int read_count() const
Get read counter.
Definition: cache_entry.cc:430
int inc_refcount()
Increment the current reference counter.
Definition: cache_entry.cc:341
bool flush()
Flush current memory cache to disk.
Definition: cache_entry.cc:246
bool decode_timeout() const
Check for decode timeout.
Definition: cache_entry.cc:306
void unlock()
Unlock the access mutex.
Definition: cache_entry.cc:331
bool is_finished_incomplete() const
Get if cache has been finished, but not completely filled.
Definition: cache_entry.cc:440
bool is_finished_success() const
Get if cache has been finished and filled successfully.
Definition: cache_entry.cc:445
bool outdated() const
Check if cache entry needs to be recoded.
Definition: cache_entry.cc:351
std::unique_ptr< Buffer > m_buffer
Buffer object.
Definition: cache_entry.h:271
bool delete_info()
Delete cache info.
Definition: cache_entry.cc:141
virtual ~Cache_Entry()
Destroy Cache_Entry object.
Definition: cache_entry.cc:65
bool read_info()
Read cache info.
Definition: cache_entry.cc:131
bool expired() const
Check if cache entry expired.
Definition: cache_entry.cc:296
The Cache class.
Definition: cache.h:105
bool delete_info(const std::string &filename, const std::string &desttype)
Delete cache file info.
Definition: cache.cc:978
bool write_info(LPCCACHE_INFO cache_info)
Write cache file info.
Definition: cache.cc:912
bool read_info(LPCACHE_INFO cache_info)
Read cache file info.
Definition: cache.cc:785
const std::string & desttype() const
Get destination type.
static void debug(const T filename, const std::string &format_string, Args &&...args)
Write debug level log entry.
Definition: logging.h:182
static void trace(const T filename, const std::string &format_string, Args &&...args)
Write trace level log entry.
Definition: logging.h:163
void init_id3v1(ID3v1 *id3v1)
Initialise ID3v1 tag.
FFMPEGFS_PARAMS params
FFmpegfs command line parameters.
Definition: ffmpegfs.cc:74
Main include for FFmpegfs project.
Provide various log facilities to stderr, disk or syslog.
uint32_t m_video_frame_count
Number of frames in video or 0 if not a video.
Definition: cache.h:84
int64_t m_audiobitrate
Audio bitrate in bit/s.
Definition: cache.h:75
size_t m_file_size
Source file file size.
Definition: cache.h:93
time_t m_access_time
Source file last access time.
Definition: cache.h:91
RESULTCODE m_result
Result code:
Definition: cache.h:86
bool m_deinterlace
true if video was deinterlaced
Definition: cache.h:80
size_t m_encoded_filesize
Actual file size after encode.
Definition: cache.h:83
int m_audiosamplerate
Audio sample rate in Hz.
Definition: cache.h:76
bool m_error
true if encode failed
Definition: cache.h:87
size_t m_predicted_filesize
Predicted file size.
Definition: cache.h:82
std::string m_destfile
Destination filename after transcode.
Definition: cache.h:73
int m_averror
FFmpeg error code if encode failed.
Definition: cache.h:89
std::string m_origfile
Original filename before transcode.
Definition: cache.h:72
time_t m_file_time
Source file file time.
Definition: cache.h:92
std::array< char, 11 > m_desttype
Destination type.
Definition: cache.h:74
int m_videowidth
Video width.
Definition: cache.h:78
int m_videoheight
Video height.
Definition: cache.h:79
int64_t m_videobitrate
Video bitrate in bit/s.
Definition: cache.h:77
unsigned int m_access_count
Read access counter.
Definition: cache.h:94
int m_errno
errno if encode failed
Definition: cache.h:88
time_t m_creation_time
Source file creation time.
Definition: cache.h:90
time_t m_max_inactive_suspend
Time (seconds) that must elapse without access until transcoding is suspended.
Definition: ffmpegfs.h:243
int m_deinterlace
1: deinterlace video, 0: no deinterlace
Definition: ffmpegfs.h:215
time_t m_expiry_time
Time (seconds) after which an cache entry is deleted.
Definition: ffmpegfs.h:242
const FFmpegfs_Format * current_format(LPCVIRTUALFILE virtualfile) const
Get FFmpegfs_Format for a virtual file.
Definition: ffmpegfs.cc:235
int m_videowidth
Output video width.
Definition: ffmpegfs.h:213
BITRATE m_videobitrate
Output video bit rate (bits per second)
Definition: ffmpegfs.h:212
int m_videoheight
Output video height.
Definition: ffmpegfs.h:214
BITRATE m_audiobitrate
Output audio bit rate (bits per second)
Definition: ffmpegfs.h:207
int m_audiosamplerate
Output audio sample rate (in Hz)
Definition: ffmpegfs.h:208
time_t m_max_inactive_abort
Time (seconds) that must elapse without access until transcoding is aborted.
Definition: ffmpegfs.h:244
Virtual file definition.
Definition: fileio.h:123
std::string m_destfile
Name and path of destination file.
Definition: fileio.h:150
std::string m_origfile
Sanitised name and path of original file.
Definition: fileio.h:152
std::string m_virtfile
Name and path of virtual file.
Definition: fileio.h:151