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
68
69 static int cmp(
const void *
key,
const void *node)
70 {
72 }
73
75 {
77 char *buffername;
79
81
86 }
87
88 ret = unlink(buffername);
89
92 else
93 c->filename = buffername;
94
96 options,
h->protocol_whitelist,
h->protocol_blacklist,
h);
97 }
98
100 {
107
108 //FIXME avoid lseek
109 pos = lseek(
c->fd, 0, SEEK_END);
114 }
116
122 }
124
126
127 if (!entry)
128 entry = next[0];
129
130 if (!entry ||
133 ) {
136 if (!entry || !node) {
139 }
143
145 if (entry_ret && entry_ret != entry) {
149 }
150 } else
152
153 return 0;
155 //we could truncate the file to pos here if pos >=0 but ftruncate isn't available in VS so
156 //for simplicty we just leave the file a bit larger
160 }
161
163 {
167
169
170 if (!entry)
171 entry = next[0];
172
173 if (entry) {
174 int64_t in_block_pos =
c->logical_pos - entry->
logical_pos;
176 if (in_block_pos < entry->
size) {
177 int64_t physical_target = entry->
physical_pos + in_block_pos;
178
179 if (
c->cache_pos != physical_target) {
180 r = lseek(
c->fd, physical_target, SEEK_SET);
181 } else
183
187 }
188
194 }
195 }
196 }
197
198 // Cache miss or some kind of fault with the cache
199
200 if (
c->logical_pos !=
c->inner_pos) {
205 }
207 }
208
213 }
217
219
222 c->end =
FFMAX(
c->end,
c->logical_pos);
223
225 }
226
228 {
231
238 }
243 }
244
245 if (whence == SEEK_CUR) {
246 whence = SEEK_SET;
247 pos +=
c->logical_pos;
248 }
else if (whence == SEEK_END &&
c->is_true_eof) {
249 resolve_eof:
250 whence = SEEK_SET;
252 }
253
254 if (whence == SEEK_SET &&
pos >= 0 && pos < c->end) {
255 //Seems within filesize, assume it will not fail.
256 c->logical_pos =
pos;
258 }
259
260 //cache miss
262 if ((whence == SEEK_SET &&
pos >=
c->logical_pos ||
263 whence == SEEK_END &&
pos <= 0) &&
ret < 0) {
264 if ( (whence == SEEK_SET &&
c->read_ahead_limit >=
pos -
c->logical_pos)
265 ||
c->read_ahead_limit < 0) {
267 while (
c->logical_pos <
pos || whence == SEEK_END) {
269 if (whence == SEEK_SET)
274 goto resolve_eof;
275 }
278 }
279 }
280 return c->logical_pos;
281 }
282 }
283
285 c->logical_pos =
ret;
287 }
288
290 }
291
293 {
295 return 0;
296 }
297
299 {
302
304 c->cache_hit,
c->cache_miss);
305
308 ret = unlink(
c->filename);
312 }
316
317 return 0;
318 }
319
320 #define OFFSET(x) offsetof(Context, x)
321 #define D AV_OPT_FLAG_DECODING_PARAM
322
324 {
"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 },
326 };
327
333 };
334
341 .priv_data_size =
sizeof(
Context),
343 };