This is an automated email from the git hooks/post-receive script.

Git pushed a commit to branch master
in repository ffmpeg.

commit afce637550dea772da604afe1d284a12731a25f9
Author:     Niklas Haas <[email protected]>
AuthorDate: Thu Mar 26 16:45:29 2026 +0100
Commit:     Niklas Haas <[email protected]>
CommitDate: Thu Jun 4 17:48:12 2026 +0200

    avformat/shared: add option to verify cache file contents
    
    This will effectively disable the cache but allows the cache layer to verify
    cached files against the original input file. Useful only for debugging
    the shared cache protocol itself, as file corruption can already be caught 
by
    the CRC check.
---
 doc/protocols.texi   |  5 +++++
 libavformat/shared.c | 25 +++++++++++++++++++++----
 2 files changed, 26 insertions(+), 4 deletions(-)

diff --git a/doc/protocols.texi b/doc/protocols.texi
index 1fbf2ef873..a5ebd98a65 100644
--- a/doc/protocols.texi
+++ b/doc/protocols.texi
@@ -1601,6 +1601,11 @@ If true, use the shared cache for reads but don't write 
any new blocks to it.
 Default is false. Note that even with this option enabled, the cache file will
 be initialized if it does not already exist.
 
+@item cache_verify
+If true, verify any data read from the cache against the underlying input
+stream, and report any mismatches. Note that this will make the cache layer
+effectively useless. This is purely a debug option.
+
 @item cache_timeout
 If set to a nonzero value, specifies the maximum time (in microseconds) to wait
 for data to become available, if another process is currently trying to fetch
diff --git a/libavformat/shared.c b/libavformat/shared.c
index e0c06ef8b7..a7a85f41bd 100644
--- a/libavformat/shared.c
+++ b/libavformat/shared.c
@@ -148,6 +148,7 @@ typedef struct SharedContext {
     int read_only;
     int64_t timeout;
     int retry_errors;
+    int verify;
 
     /* misc state */
     int64_t pos; ///< current logical position
@@ -596,6 +597,7 @@ static int shared_read(URLContext *h, unsigned char *buf, 
int size)
     Block *const block = &s->spacemap->blocks[block_id];
     unsigned short state = atomic_load_explicit(&block->state, 
memory_order_acquire);
     int64_t pending_since = 0;
+    int verify_read = 0;
 
 retry:
     switch (state) {
@@ -622,9 +624,14 @@ retry:
             return AVERROR(EIO);
         }
 
+        tmp += (ptrdiff_t) offset;
         size = FFMIN(size, block_size - offset);
-        memcpy(buf, tmp + offset, size);
+        if (s->verify) {
+            verify_read = 1;
+            break; /* fall through to the cache miss logic */
+        }
 
+        memcpy(buf, tmp, size);
         s->nb_hit++;
         s->pos += size;
         return size;
@@ -669,7 +676,7 @@ retry:
     /* Cache miss, fetch this block from underlying protocol */
     s->nb_miss++;
 
-    const int read_only = s->read_only || s->write_err;
+    const int read_only = s->read_only || s->write_err || verify_read;
     int64_t inner_pos = read_only ? s->pos : block_pos;
     if (s->inner_pos != inner_pos) {
         inner_pos = ffurl_seek(s->inner, inner_pos, SEEK_SET);
@@ -695,8 +702,17 @@ retry:
     if (read_only) {
         /* Directly defer to the underlying protocol */
         ret = ffurl_read(s->inner, buf, size);
-        if (ret >= 0)
-            s->pos = s->inner_pos = inner_pos + ret;
+        if (ret < 0)
+            return ret;
+
+        /* Verify the read data against the cached data if requested */
+        if (verify_read && memcmp(buf, tmp, ret)) {
+            av_log(h, AV_LOG_ERROR, "Cache verification failed for %d bytes "
+                   "in block 0x%"PRIx64" at offset 0x%"PRIx64" + %"PRId64"!\n",
+                   ret, block_id, block_pos, offset);
+        }
+
+        s->pos = s->inner_pos = inner_pos + ret;
         return ret;
     }
 
@@ -839,6 +855,7 @@ static const AVOption options[] = {
     { "cache_dir",      "Directory path for shared file cache",             
OFFSET(cache_dir),      AV_OPT_TYPE_STRING, {.str = NULL}, .flags = D },
     { "block_shift",    "Set the base 2 logarithm of the block size",       
OFFSET(block_shift),    AV_OPT_TYPE_INT, {.i64 = 15}, 9, 30, .flags = D },
     { "read_only",      "Don't write data to the cache, only read from it", 
OFFSET(read_only),      AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, .flags = D },
+    { "cache_verify",   "Verify correctness of the cache against the source",  
 OFFSET(verify),     AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, .flags = D },
     { "cache_timeout",  "Time in us to wait before re-fetching pending 
blocks", OFFSET(timeout),    AV_OPT_TYPE_INT64, {.i64 = 0}, 0, INT64_MAX, 
.flags = D },
     { "retry_errors",   "Re-request blocks even if they previously failed", 
OFFSET(retry_errors),   AV_OPT_TYPE_BOOL, {.i64 = 1}, 0, 1, .flags = D },
     {0},

_______________________________________________
ffmpeg-cvslog mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to