• Main Page
  • Related Pages
  • Modules
  • Data Structures
  • Files
  • File List
  • Globals

libavformat/cache.c

Go to the documentation of this file.
00001 /*
00002  * Input cache protocol.
00003  * Copyright (c) 2011 Michael Niedermayer
00004  *
00005  * This file is part of FFmpeg.
00006  *
00007  * FFmpeg is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU Lesser General Public
00009  * License as published by the Free Software Foundation; either
00010  * version 2.1 of the License, or (at your option) any later version.
00011  *
00012  * FFmpeg is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015  * Lesser General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU Lesser General Public
00018  * License along with FFmpeg; if not, write to the Free Software
00019  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
00020  *
00021  * Based on file.c by Fabrice Bellard
00022  */
00023 
00031 #include "libavutil/avassert.h"
00032 #include "libavutil/avstring.h"
00033 #include "libavutil/file.h"
00034 #include "avformat.h"
00035 #include <fcntl.h>
00036 #if HAVE_SETMODE
00037 #include <io.h>
00038 #endif
00039 #include <unistd.h>
00040 #include <sys/stat.h>
00041 #include <stdlib.h>
00042 #include "os_support.h"
00043 #include "url.h"
00044 
00045 typedef struct Context {
00046     int fd;
00047     int64_t end;
00048     int64_t pos;
00049     URLContext *inner;
00050 } Context;
00051 
00052 static int cache_open(URLContext *h, const char *arg, int flags)
00053 {
00054     const char *buffername;
00055     Context *c= h->priv_data;
00056 
00057     av_strstart(arg, "cache:", &arg);
00058 
00059     c->fd = av_tempfile("ffcache", &buffername, 0, h);
00060     if (c->fd < 0){
00061         av_log(h, AV_LOG_ERROR, "Failed to create tempfile\n");
00062         return c->fd;
00063     }
00064 
00065     unlink(buffername);
00066     av_freep(&buffername);
00067 
00068     return ffurl_open(&c->inner, arg, flags, &h->interrupt_callback, NULL);
00069 }
00070 
00071 static int cache_read(URLContext *h, unsigned char *buf, int size)
00072 {
00073     Context *c= h->priv_data;
00074     int r;
00075 
00076     if(c->pos<c->end){
00077         r = read(c->fd, buf, FFMIN(size, c->end - c->pos));
00078         if(r>0)
00079             c->pos += r;
00080         return (-1 == r)?AVERROR(errno):r;
00081     }else{
00082         r = ffurl_read(c->inner, buf, size);
00083         if(r > 0){
00084             int r2= write(c->fd, buf, r);
00085             av_assert0(r2==r); // FIXME handle cache failure
00086             c->pos += r;
00087             c->end += r;
00088         }
00089         return r;
00090     }
00091 }
00092 
00093 static int64_t cache_seek(URLContext *h, int64_t pos, int whence)
00094 {
00095     Context *c= h->priv_data;
00096 
00097     if (whence == AVSEEK_SIZE) {
00098         pos= ffurl_seek(c->inner, pos, whence);
00099         if(pos <= 0){
00100             pos= ffurl_seek(c->inner, -1, SEEK_END);
00101             ffurl_seek(c->inner, c->end, SEEK_SET);
00102             if(pos <= 0)
00103                 return c->end;
00104         }
00105         return pos;
00106     }
00107 
00108     pos= lseek(c->fd, pos, whence);
00109     if(pos<0){
00110         return pos;
00111     }else if(pos <= c->end){
00112         c->pos= pos;
00113         return pos;
00114     }else{
00115         lseek(c->fd, c->pos, SEEK_SET);
00116         return AVERROR(EPIPE);
00117     }
00118 }
00119 
00120 static int cache_close(URLContext *h)
00121 {
00122     Context *c= h->priv_data;
00123     close(c->fd);
00124     ffurl_close(c->inner);
00125 
00126     return 0;
00127 }
00128 
00129 URLProtocol ff_cache_protocol = {
00130     .name                = "cache",
00131     .url_open            = cache_open,
00132     .url_read            = cache_read,
00133     .url_seek            = cache_seek,
00134     .url_close           = cache_close,
00135     .priv_data_size      = sizeof(Context),
00136 };
Generated on Fri Feb 1 2013 14:34:51 for FFmpeg by doxygen 1.7.1