1
0
mirror of https://github.com/FFmpeg/FFmpeg.git synced 2024-12-23 12:43:46 +02:00

add cache protocol

This allows backward seeking on top of some non seekable streams.

Signed-off-by: Michael Niedermayer <michaelni@gmx.at>
This commit is contained in:
Michael Niedermayer 2011-10-16 16:02:35 +02:00
parent 5746f91036
commit e9f62a8b2b
3 changed files with 132 additions and 0 deletions

View File

@ -333,6 +333,7 @@ OBJS-$(CONFIG_LIBNUT_MUXER) += libnut.o riff.o
OBJS+= avio.o aviobuf.o
OBJS-$(CONFIG_APPLEHTTP_PROTOCOL) += applehttpproto.o
OBJS-$(CONFIG_CACHE_PROTOCOL) += cache.o
OBJS-$(CONFIG_CONCAT_PROTOCOL) += concat.o
OBJS-$(CONFIG_CRYPTO_PROTOCOL) += crypto.o
OBJS-$(CONFIG_FILE_PROTOCOL) += file.o

View File

@ -249,6 +249,7 @@ void av_register_all(void)
/* protocols */
REGISTER_PROTOCOL (APPLEHTTP, applehttp);
REGISTER_PROTOCOL (CACHE, cache);
REGISTER_PROTOCOL (CONCAT, concat);
REGISTER_PROTOCOL (CRYPTO, crypto);
REGISTER_PROTOCOL (FILE, file);

130
libavformat/cache.c Normal file
View File

@ -0,0 +1,130 @@
/*
* Input cache protocol.
* Copyright (c) 2011 Michael Niedermayer
*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Based on file.c by Fabrice Bellard
*/
#include "libavutil/avassert.h"
#include "libavutil/avstring.h"
#include "libavutil/file.h"
#include "avformat.h"
#include <fcntl.h>
#if HAVE_SETMODE
#include <io.h>
#endif
#include <unistd.h>
#include <sys/stat.h>
#include <stdlib.h>
#include "os_support.h"
#include "url.h"
typedef struct Context {
int fd;
int64_t end;
int64_t pos;
URLContext *inner;
} Context;
static int cache_open(URLContext *h, const char *arg, int flags)
{
int access;
const char *buffername;
Context *c;
c = av_mallocz(sizeof(Context));
if (!c) {
return AVERROR(ENOMEM);
}
h->priv_data = c;
av_strstart(arg, "cache:", &arg);
c->fd = av_tempfile("ffcache", &buffername);
if (c->fd < 0){
av_log(h, AV_LOG_ERROR, "Failed to create tempfile\n");
return c->fd;
}
unlink(buffername);
av_free(buffername);
return ffurl_open(&c->inner, arg, flags);
}
static int cache_read(URLContext *h, unsigned char *buf, int size)
{
Context *c= h->priv_data;
int r;
if(c->pos<c->end){
r = read(c->fd, buf, FFMIN(size, c->end - c->pos));
if(r>0)
c->pos += r;
return (-1 == r)?AVERROR(errno):r;
}else{
r = ffurl_read(c->inner, buf, size);
if(r > 0){
int r2= write(c->fd, buf, r);
av_assert0(r2==r); // FIXME handle cache failure
c->pos += r;
c->end += r;
}
return r;
}
}
static int64_t cache_seek(URLContext *h, int64_t pos, int whence)
{
Context *c= h->priv_data;
if (whence == AVSEEK_SIZE) {
return ffurl_seek(c->inner, pos, whence);
}
pos= lseek(c->fd, pos, whence);
if(pos<0){
return pos;
}else if(pos <= c->end){
c->pos= pos;
return pos;
}else{
lseek(c->fd, c->pos, SEEK_SET);
return AVERROR(EPIPE);
}
}
static int cache_close(URLContext *h)
{
Context *c= h->priv_data;
close(c->fd);
ffurl_close(c->inner);
av_freep(&h->priv_data);
return 0;
}
URLProtocol ff_cache_protocol = {
.name = "cache",
.url_open = cache_open,
.url_read = cache_read,
.url_seek = cache_seek,
.url_close = cache_close,
};