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)
54 const char *buffername;
55 Context *c= h->priv_data;
57 av_strstart(arg, "cache:", &arg);
59 c->fd = av_tempfile("ffcache", &buffername, 0, h);
61 av_log(h, AV_LOG_ERROR, "Failed to create tempfile\n");
66 av_freep(&buffername);
68 return ffurl_open(&c->inner, arg, flags, &h->interrupt_callback, NULL);
71 static int cache_read(URLContext *h, unsigned char *buf, int size)
73 Context *c= h->priv_data;
77 r = read(c->fd, buf, FFMIN(size, c->end - c->pos));
80 return (-1 == r)?AVERROR(errno):r;
82 r = ffurl_read(c->inner, buf, size);
84 int r2= write(c->fd, buf, r);
85 av_assert0(r2==r); // FIXME handle cache failure
93 static int64_t cache_seek(URLContext *h, int64_t pos, int whence)
95 Context *c= h->priv_data;
97 if (whence == AVSEEK_SIZE) {
98 pos= ffurl_seek(c->inner, pos, whence);
100 pos= ffurl_seek(c->inner, -1, SEEK_END);
101 ffurl_seek(c->inner, c->end, SEEK_SET);
108 pos= lseek(c->fd, pos, whence);
111 }else if(pos <= c->end){
115 lseek(c->fd, c->pos, SEEK_SET);
116 return AVERROR(EPIPE);
120 static int cache_close(URLContext *h)
122 Context *c= h->priv_data;
124 ffurl_close(c->inner);
129 URLProtocol ff_cache_protocol = {
131 .url_open = cache_open,
132 .url_read = cache_read,
133 .url_seek = cache_seek,
134 .url_close = cache_close,
135 .priv_data_size = sizeof(Context),