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"
44 #include "os_support.h"
47 typedef struct Context
{
54 static int cache_open(URLContext
*h
, const char *arg
, int flags
)
57 Context
*c
= h
->priv_data
;
59 av_strstart(arg
, "cache:", &arg
);
61 c
->fd
= av_tempfile("ffcache", &buffername
, 0, h
);
63 av_log(h
, AV_LOG_ERROR
, "Failed to create tempfile\n");
68 av_freep(&buffername
);
70 return ffurl_open(&c
->inner
, arg
, flags
, &h
->interrupt_callback
, NULL
);
73 static int cache_read(URLContext
*h
, unsigned char *buf
, int size
)
75 Context
*c
= h
->priv_data
;
79 r
= read(c
->fd
, buf
, FFMIN(size
, c
->end
- c
->pos
));
82 return (-1 == r
)?AVERROR(errno
):r
;
84 r
= ffurl_read(c
->inner
, buf
, size
);
86 int r2
= write(c
->fd
, buf
, r
);
87 av_assert0(r2
==r
); // FIXME handle cache failure
95 static int64_t cache_seek(URLContext
*h
, int64_t pos
, int whence
)
97 Context
*c
= h
->priv_data
;
99 if (whence
== AVSEEK_SIZE
) {
100 pos
= ffurl_seek(c
->inner
, pos
, whence
);
102 pos
= ffurl_seek(c
->inner
, -1, SEEK_END
);
103 ffurl_seek(c
->inner
, c
->end
, SEEK_SET
);
110 pos
= lseek(c
->fd
, pos
, whence
);
113 }else if(pos
<= c
->end
){
117 if(lseek(c
->fd
, c
->pos
, SEEK_SET
) < 0) {
118 av_log(h
, AV_LOG_ERROR
, "Failure to seek in cache\n");
120 return AVERROR(EPIPE
);
124 static int cache_close(URLContext
*h
)
126 Context
*c
= h
->priv_data
;
128 ffurl_close(c
->inner
);
133 URLProtocol ff_cache_protocol
= {
135 .url_open
= cache_open
,
136 .url_read
= cache_read
,
137 .url_seek
= cache_seek
,
138 .url_close
= cache_close
,
139 .priv_data_size
= sizeof(Context
),