1 /*
2 * Input cache protocol.
3 * Copyright (c) 2011,2014 Michael Niedermayer
4 *
5 * This file is part of FFmpeg.
6 *
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.
11 *
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.
16 *
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
20 *
21 * Based on file.c by Fabrice Bellard
22 */
23
24 /**
25 * @TODO
26 * support keeping files
27 * support filling with a background thread
28 */
29
36 #include <fcntl.h>
37 #if HAVE_IO_H
38 #include <io.h>
39 #endif
40 #if HAVE_UNISTD_H
41 #include <unistd.h>
42 #endif
43 #include <sys/stat.h>
44 #include <stdlib.h>
47
53
67
68 static int cmp(
void *key,
const void *node)
69 {
70 return (*(int64_t *) key) - ((
const CacheEntry *) node)->logical_pos;
71 }
72
74 {
75 char *buffername;
77
79
84 }
85
86 unlink(buffername);
88
90 }
91
93 {
95 int64_t pos = -1;
100
101 //FIXME avoid lseek
102 pos = lseek(c->
fd, 0, SEEK_END);
103 if (pos < 0) {
106 goto fail;
107 }
109
110 ret = write(c->
fd, buf, size);
111 if (ret < 0) {
114 goto fail;
115 }
117
119
120 if (!entry)
121 entry = next[0];
122
123 if (!entry ||
126 ) {
129 if (!entry || !node) {
131 goto fail;
132 }
136
138 if (entry_ret && entry_ret != entry) {
139 ret = -1;
141 goto fail;
142 }
143 } else
145
146 return 0;
147 fail:
148 //we could truncate the file to pos here if pos >=0 but ftruncate isn't available in VS so
149 //for simplicty we just leave the file a bit larger
153 }
154
156 {
160
162
163 if (!entry)
164 entry = next[0];
165
166 if (entry) {
169 if (in_block_pos < entry->size) {
170 int64_t physical_target = entry->
physical_pos + in_block_pos;
171
173 r = lseek(c->
fd, physical_target, SEEK_SET);
174 } else
176
177 if (r >= 0) {
179 r = read(c->
fd, buf,
FFMIN(size, entry->
size - in_block_pos));
180 }
181
182 if (r > 0) {
187 }
188 }
189 }
190
191 // Cache miss or some kind of fault with the cache
192
195 if (r<0) {
198 }
200 }
201
203 if (r == 0 && size>0) {
206 }
207 if (r<=0)
210
212
216
218 }
219
221 {
224
227 if(pos <= 0){
231 }
232 if (pos > 0)
235 return pos;
236 }
237
238 if (whence == SEEK_CUR) {
239 whence = SEEK_SET;
242 resolve_eof:
243 whence = SEEK_SET;
245 }
246
247 if (whence == SEEK_SET && pos >= 0 && pos < c->
end) {
248 //Seems within filesize, assume it will not fail.
250 return pos;
251 }
252
253 //cache miss
255 if ((whence == SEEK_SET && pos >= c->
logical_pos ||
256 whence == SEEK_END && pos <= 0) && ret < 0) {
260 while (c->
logical_pos < pos || whence == SEEK_END) {
261 int size =
sizeof(tmp);
262 if (whence == SEEK_SET)
265 if (ret == 0 && whence == SEEK_END) {
267 goto resolve_eof;
268 }
269 if (ret < 0) {
271 }
272 }
274 }
275 }
276
277 if (ret >= 0) {
280 }
281
283 }
284
286 {
288
289 av_log(h,
AV_LOG_INFO,
"Statistics, cache hits:%"PRId64
" cache misses:%"PRId64
"\n",
291
295
296 return 0;
297 }
298
299 #define OFFSET(x) offsetof(Context, x)
300 #define D AV_OPT_FLAG_DECODING_PARAM
301
303 {
"read_ahead_limit",
"Amount in bytes that may be read ahead when seeking isn't supported, -1 for unlimited",
OFFSET(read_ahead_limit),
AV_OPT_TYPE_INT, { .i64 = 65536 }, -1, INT_MAX,
D },
305 };
306
312 };
313
320 .priv_data_size =
sizeof(
Context),
321 .priv_data_class = &cache_context_class,
322 };
support keeping files support filling with a background thread
#define LIBAVUTIL_VERSION_INT
AVIOInterruptCB interrupt_callback
static const AVClass cache_context_class
static const AVOption options[]
struct AVTreeNode * av_tree_node_alloc(void)
Allocate an AVTreeNode.
const char * class_name
The name of the class; usually it is the same name as the context structure type to which the AVClass...
#define av_assert0(cond)
assert() equivalent, that is always enabled.
void * av_tree_find(const AVTreeNode *t, void *key, int(*cmp)(void *key, const void *b), void *next[2])
miscellaneous OS support macros and functions.
static av_cold int end(AVCodecContext *avctx)
URLProtocol ff_cache_protocol
void av_tree_destroy(AVTreeNode *t)
void * av_tree_insert(AVTreeNode **tp, void *key, int(*cmp)(void *key, const void *b), AVTreeNode **next)
Insert or remove an element.
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
simple assert() macros that are a bit more flexible than ISO C assert().
static int cache_open(URLContext *h, const char *arg, int flags, AVDictionary **options)
static int cmp(void *key, const void *node)
static int cache_close(URLContext *h)
static int64_t cache_seek(URLContext *h, int64_t pos, int whence)
int av_tempfile(const char *prefix, char **filename, int log_offset, void *log_ctx)
Wrapper to work around the lack of mkstemp() on mingw.
#define AV_LOG_INFO
Standard information.
static int cache_read(URLContext *h, unsigned char *buf, int size)
Describe the class of an AVClass context structure.
int ffurl_close(URLContext *h)
int av_strstart(const char *str, const char *pfx, const char **ptr)
Return non-zero if pfx is a prefix of str.
int64_t ffurl_seek(URLContext *h, int64_t pos, int whence)
Change the position that will be used by the next read/write operation on the resource accessed by h...
int ffurl_open(URLContext **puc, const char *filename, int flags, const AVIOInterruptCB *int_cb, AVDictionary **options)
Create an URLContext for accessing to the resource indicated by url, and open it. ...
#define AVSEEK_SIZE
Passing this as the "whence" parameter to a seek function causes it to return the filesize without se...
static int add_entry(URLContext *h, const unsigned char *buf, int size)
unbuffered private I/O API
int ffurl_read(URLContext *h, unsigned char *buf, int size)
Read up to size bytes from the resource accessed by h, and store the read bytes in buf...