2 * Input cache protocol.
3 * Copyright (c) 2011 Michael Niedermayer
5 * This file is part of FFmpeg.
7 * FFmpeg is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * FFmpeg is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with FFmpeg; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 * Based on file.c by Fabrice Bellard
26 * support non continuous caching
27 * support keeping files
28 * support filling with a background thread
31 #include "libavutil/avassert.h"
32 #include "libavutil/avstring.h"
33 #include "libavutil/file.h"
42 #include "os_support.h"
45 typedef struct Context {
52 static int cache_open(URLContext *h, const char *arg, int flags)
55 const char *buffername;
56 Context *c= h->priv_data;
58 av_strstart(arg, "cache:", &arg);
60 c->fd = av_tempfile("ffcache", &buffername, 0, h);
62 av_log(h, AV_LOG_ERROR, "Failed to create tempfile\n");
69 return ffurl_open(&c->inner, arg, flags, &h->interrupt_callback, NULL);
72 static int cache_read(URLContext *h, unsigned char *buf, int size)
74 Context *c= h->priv_data;
78 r = read(c->fd, buf, FFMIN(size, c->end - c->pos));
81 return (-1 == r)?AVERROR(errno):r;
83 r = ffurl_read(c->inner, buf, size);
85 int r2= write(c->fd, buf, r);
86 av_assert0(r2==r); // FIXME handle cache failure
94 static int64_t cache_seek(URLContext *h, int64_t pos, int whence)
96 Context *c= h->priv_data;
98 if (whence == AVSEEK_SIZE) {
99 pos= ffurl_seek(c->inner, pos, whence);
101 pos= ffurl_seek(c->inner, -1, SEEK_END);
102 ffurl_seek(c->inner, c->end, SEEK_SET);
109 pos= lseek(c->fd, pos, whence);
112 }else if(pos <= c->end){
116 lseek(c->fd, c->pos, SEEK_SET);
117 return AVERROR(EPIPE);
121 static int cache_close(URLContext *h)
123 Context *c= h->priv_data;
125 ffurl_close(c->inner);
130 URLProtocol ff_cache_protocol = {
132 .url_open = cache_open,
133 .url_read = cache_read,
134 .url_seek = cache_seek,
135 .url_close = cache_close,
136 .priv_data_size = sizeof(Context),