annotate ffmpeg/libavformat/cache.c @ 13:844d341cf643 tip

Back up before ISMIR
author Yading Song <yading.song@eecs.qmul.ac.uk>
date Thu, 31 Oct 2013 13:17:06 +0000
parents f445c3017523
children
rev   line source
yading@11 1 /*
yading@11 2 * Input cache protocol.
yading@11 3 * Copyright (c) 2011 Michael Niedermayer
yading@11 4 *
yading@11 5 * This file is part of FFmpeg.
yading@11 6 *
yading@11 7 * FFmpeg is free software; you can redistribute it and/or
yading@11 8 * modify it under the terms of the GNU Lesser General Public
yading@11 9 * License as published by the Free Software Foundation; either
yading@11 10 * version 2.1 of the License, or (at your option) any later version.
yading@11 11 *
yading@11 12 * FFmpeg is distributed in the hope that it will be useful,
yading@11 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
yading@11 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
yading@11 15 * Lesser General Public License for more details.
yading@11 16 *
yading@11 17 * You should have received a copy of the GNU Lesser General Public
yading@11 18 * License along with FFmpeg; if not, write to the Free Software
yading@11 19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
yading@11 20 *
yading@11 21 * Based on file.c by Fabrice Bellard
yading@11 22 */
yading@11 23
yading@11 24 /**
yading@11 25 * @TODO
yading@11 26 * support non continuous caching
yading@11 27 * support keeping files
yading@11 28 * support filling with a background thread
yading@11 29 */
yading@11 30
yading@11 31 #include "libavutil/avassert.h"
yading@11 32 #include "libavutil/avstring.h"
yading@11 33 #include "libavutil/file.h"
yading@11 34 #include "avformat.h"
yading@11 35 #include <fcntl.h>
yading@11 36 #if HAVE_IO_H
yading@11 37 #include <io.h>
yading@11 38 #endif
yading@11 39 #if HAVE_UNISTD_H
yading@11 40 #include <unistd.h>
yading@11 41 #endif
yading@11 42 #include <sys/stat.h>
yading@11 43 #include <stdlib.h>
yading@11 44 #include "os_support.h"
yading@11 45 #include "url.h"
yading@11 46
yading@11 47 typedef struct Context {
yading@11 48 int fd;
yading@11 49 int64_t end;
yading@11 50 int64_t pos;
yading@11 51 URLContext *inner;
yading@11 52 } Context;
yading@11 53
yading@11 54 static int cache_open(URLContext *h, const char *arg, int flags)
yading@11 55 {
yading@11 56 char *buffername;
yading@11 57 Context *c= h->priv_data;
yading@11 58
yading@11 59 av_strstart(arg, "cache:", &arg);
yading@11 60
yading@11 61 c->fd = av_tempfile("ffcache", &buffername, 0, h);
yading@11 62 if (c->fd < 0){
yading@11 63 av_log(h, AV_LOG_ERROR, "Failed to create tempfile\n");
yading@11 64 return c->fd;
yading@11 65 }
yading@11 66
yading@11 67 unlink(buffername);
yading@11 68 av_freep(&buffername);
yading@11 69
yading@11 70 return ffurl_open(&c->inner, arg, flags, &h->interrupt_callback, NULL);
yading@11 71 }
yading@11 72
yading@11 73 static int cache_read(URLContext *h, unsigned char *buf, int size)
yading@11 74 {
yading@11 75 Context *c= h->priv_data;
yading@11 76 int r;
yading@11 77
yading@11 78 if(c->pos<c->end){
yading@11 79 r = read(c->fd, buf, FFMIN(size, c->end - c->pos));
yading@11 80 if(r>0)
yading@11 81 c->pos += r;
yading@11 82 return (-1 == r)?AVERROR(errno):r;
yading@11 83 }else{
yading@11 84 r = ffurl_read(c->inner, buf, size);
yading@11 85 if(r > 0){
yading@11 86 int r2= write(c->fd, buf, r);
yading@11 87 av_assert0(r2==r); // FIXME handle cache failure
yading@11 88 c->pos += r;
yading@11 89 c->end += r;
yading@11 90 }
yading@11 91 return r;
yading@11 92 }
yading@11 93 }
yading@11 94
yading@11 95 static int64_t cache_seek(URLContext *h, int64_t pos, int whence)
yading@11 96 {
yading@11 97 Context *c= h->priv_data;
yading@11 98
yading@11 99 if (whence == AVSEEK_SIZE) {
yading@11 100 pos= ffurl_seek(c->inner, pos, whence);
yading@11 101 if(pos <= 0){
yading@11 102 pos= ffurl_seek(c->inner, -1, SEEK_END);
yading@11 103 ffurl_seek(c->inner, c->end, SEEK_SET);
yading@11 104 if(pos <= 0)
yading@11 105 return c->end;
yading@11 106 }
yading@11 107 return pos;
yading@11 108 }
yading@11 109
yading@11 110 pos= lseek(c->fd, pos, whence);
yading@11 111 if(pos<0){
yading@11 112 return pos;
yading@11 113 }else if(pos <= c->end){
yading@11 114 c->pos= pos;
yading@11 115 return pos;
yading@11 116 }else{
yading@11 117 if(lseek(c->fd, c->pos, SEEK_SET) < 0) {
yading@11 118 av_log(h, AV_LOG_ERROR, "Failure to seek in cache\n");
yading@11 119 }
yading@11 120 return AVERROR(EPIPE);
yading@11 121 }
yading@11 122 }
yading@11 123
yading@11 124 static int cache_close(URLContext *h)
yading@11 125 {
yading@11 126 Context *c= h->priv_data;
yading@11 127 close(c->fd);
yading@11 128 ffurl_close(c->inner);
yading@11 129
yading@11 130 return 0;
yading@11 131 }
yading@11 132
yading@11 133 URLProtocol ff_cache_protocol = {
yading@11 134 .name = "cache",
yading@11 135 .url_open = cache_open,
yading@11 136 .url_read = cache_read,
yading@11 137 .url_seek = cache_seek,
yading@11 138 .url_close = cache_close,
yading@11 139 .priv_data_size = sizeof(Context),
yading@11 140 };