From 794a7795d714468074ce3c57d6b55e9e1f0ae50a Mon Sep 17 00:00:00 2001 From: Matthias Blankertz Date: Mon, 15 Nov 2010 13:32:09 +0100 Subject: [PATCH] Decodeing now supports adding different decoder modules. Currently only decode-ffmpeg exists. --- .gitignore | 3 +- Makefile.am | 4 +- src/decode-ffmpeg.c | 164 ++++++++++++++++++++++++++++++++++++++++++++ src/decode-ffmpeg.h | 15 ++++ src/decode.c | 132 +++++------------------------------ src/decode.h | 16 ++--- src/test_encode.c | 8 +-- src/transcode.c | 2 +- src/util.c | 4 +- src/util.h | 1 + 10 files changed, 217 insertions(+), 132 deletions(-) create mode 100644 src/decode-ffmpeg.c create mode 100644 src/decode-ffmpeg.h diff --git a/.gitignore b/.gitignore index 6b96f59..09048f6 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,7 @@ tcfs test_encode *.mp3 +*.wav *.o *~ testmnt/ @@ -20,4 +21,4 @@ INSTALL install-sh missing stamp-h1 -config.h.in \ No newline at end of file +config.h.in diff --git a/Makefile.am b/Makefile.am index bcb9f81..15bb9e4 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,7 +1,7 @@ bin_PROGRAMS=tcfs test_encode -tcfs_SOURCES=src/tcfs.c src/transcode.c src/decode.c src/encode.c src/util.c src/tcfs_buf.c +tcfs_SOURCES=src/tcfs.c src/transcode.c src/decode.c src/encode.c src/util.c src/tcfs_buf.c src/decode-ffmpeg.c tcfs_LDADD = $(LIBOBJS) $(FUSE_LIBS) $(libavcore_LIBS) $(libavutil_LIBS) $(libavformat_LIBS) $(libavcodec_LIBS) tcfs_CFLAGS = $(FUSE_CFLAGS) $(libavcore_CFLAGS) $(libavutil_CFLAGS) $(libavformat_CFLAGS) $(libavcodec_CFLAGS) -DFUSE_USE_VERSION=28 -test_encode_SOURCES=src/decode.c src/encode.c src/tcfs_buf.c src/util.c src/test_encode.c +test_encode_SOURCES=src/decode.c src/encode.c src/tcfs_buf.c src/util.c src/test_encode.c src/decode-ffmpeg.c test_encode_LDADD = $(LIBOBJS) $(libavcore_LIBS) $(libavutil_LIBS) $(libavformat_LIBS) $(libavcodec_LIBS) test_encode_CFLAGS = $(libavcore_CFLAGS) $(libavutil_CFLAGS) $(libavformat_CFLAGS) $(libavcodec_CFLAGS) \ No newline at end of file diff --git a/src/decode-ffmpeg.c b/src/decode-ffmpeg.c new file mode 100644 index 0000000..3e57f82 --- /dev/null +++ b/src/decode-ffmpeg.c @@ -0,0 +1,164 @@ +/* + Copyright (c) 2010 Matthias Blankertz + + This work is licensed under the Open Software License ("OSL") v. 3.0. + */ + +#include "common.h" +#include "util.h" +#include "decode.h" +#include "decode-ffmpeg.h" + +struct decode_ffmpeg_ctx +{ + AVFormatContext *avfctx; + int stream; + AVCodec *avc; + char *bod; + int len, offs; + void *metadata; +}; + +struct decode_ctx *decode_ffmpeg_open(const char *src); +int decode_ffmpeg_read(char *buf, size_t size, struct decode_ctx *fd); +int decode_ffmpeg_close(struct decode_ctx *fd); + +struct decode_ops decode_ffmpeg_ops = { + decode_ffmpeg_open, + decode_ffmpeg_read, + decode_ffmpeg_close +}; + +struct decode_ctx *decode_ffmpeg_open(const char *src) +{ + struct decode_ctx *fd = (struct decode_ctx*)malloc(sizeof(struct decode_ctx)+sizeof(struct decode_ffmpeg_ctx)); + if(!fd) + return NULL; + + struct decode_ffmpeg_ctx *ctx = (struct decode_ffmpeg_ctx*)(fd+1); + fd->ops = &decode_ffmpeg_ops; + + int ret; + if((ret = av_open_input_file(&ctx->avfctx, src, NULL, 0, NULL)) != 0) { + char err[512]; + av_strerror(ret, err, 512); + fprintf(stderr, "ffmpeg error: %s\n", err); + free(fd); + errno = EIO; + return NULL; + } + + if((ret = av_find_stream_info(ctx->avfctx)) < 0) { + char err[512]; + av_strerror(ret, err, 512); + fprintf(stderr, "ffmpeg error: %s\n", err); + av_close_input_file(ctx->avfctx); + free(fd); + errno = EIO; + return NULL; + } + + + dump_format(ctx->avfctx, 0, src, 0); + + int i; + for(i = 0;i < ctx->avfctx->nb_streams;++i) { + if(ctx->avfctx->streams[i]->codec->codec_type == CODEC_TYPE_AUDIO) + break; + } + if(i == ctx->avfctx->nb_streams) { + // no audio stream + av_close_input_file(ctx->avfctx); + free(fd); + errno = EIO; + return NULL; + } + + ctx->stream = i; + ctx->metadata = ctx->avfctx->streams[i]->metadata; + + ctx->avc = avcodec_find_decoder(ctx->avfctx->streams[ctx->stream]->codec->codec_id); + if(!ctx->avc) { + fprintf(stderr, "ffmpeg error: Could not find decoder.\n"); + av_close_input_file(ctx->avfctx); + free(fd); + errno = EIO; + return NULL; + } + + if((ret = avcodec_open(ctx->avfctx->streams[ctx->stream]->codec, ctx->avc)) < 0) { + char err[512]; + av_strerror(ret, err, 512); + fprintf(stderr, "ffmpeg error: %s\n", err); + av_close_input_file(ctx->avfctx); + free(fd); + errno = EIO; + return NULL; + } + + ctx->bod = malloc(128*1024*1024); + if(!ctx->bod) + return NULL; + + AVPacket pack; + int pos = 0; + int fsp = 128*1024*1024; + while(av_read_frame(ctx->avfctx, &pack) == 0) { + if(pack.stream_index == ctx->stream) { + if(avcodec_decode_audio3(ctx->avfctx->streams[ctx->stream]->codec, ctx->bod+pos, &fsp, &pack) < 0) { + printf("Decode error.\n"); + return NULL; + } + pos += fsp; + fsp = 128*1024*1024-pos; + } + } + ctx->len = pos; + ctx->offs = 0; + + return fd; +} + +int decode_ffmpeg_read(char *buf, size_t size, struct decode_ctx *fd) +{ + if(!fd || (fd->ops != &decode_ffmpeg_ops)) { + tcfs_errno = EINVAL; + return -1; + } + + struct decode_ffmpeg_ctx *ctx = (struct decode_ffmpeg_ctx*)(fd+1); + + if(size < ctx->len-ctx->offs) { + memcpy(buf, ctx->bod+ctx->offs, size); + ctx->offs += size; + return size; + } else { + memcpy(buf, ctx->bod+ctx->offs, ctx->len-ctx->offs); + int ret = ctx->len - ctx->offs; + ctx->offs = ctx->len; + return ret; + } +} + +int decode_ffmpeg_close(struct decode_ctx *fd) +{ + if(!fd || (fd->ops != &decode_ffmpeg_ops)) { + tcfs_errno = EINVAL; + return -1; + } + + struct decode_ffmpeg_ctx *ctx = (struct decode_ffmpeg_ctx*)(fd+1); + + if(!ctx->avfctx || !ctx->avc) { + free(fd); + return 0; + } + + free(ctx->bod); + avcodec_close(ctx->avfctx->streams[ctx->stream]->codec); + av_close_input_file(ctx->avfctx); + free(fd); + return 0; +} + + diff --git a/src/decode-ffmpeg.h b/src/decode-ffmpeg.h new file mode 100644 index 0000000..07868f9 --- /dev/null +++ b/src/decode-ffmpeg.h @@ -0,0 +1,15 @@ +/* + Copyright (c) 2010 Matthias Blankertz + + This work is licensed under the Open Software License ("OSL") v. 3.0. + */ + +#ifndef TCFS_DECODE_FFMPEG_H +#define TCFS_DECODE_FFMPEG_H 1 + +#include "decode.h" + +extern struct decode_ops decode_ffmpeg_ops; + +#endif + diff --git a/src/decode.c b/src/decode.c index 380ceef..48d736d 100644 --- a/src/decode.c +++ b/src/decode.c @@ -5,131 +5,33 @@ */ #include "common.h" +#include "util.h" #include "decode.h" -/*struct decode_ctx { - AVFormatContext *avfctx; - int stream; - AVCodec *avc; - char *bod; - int len, offs; - };*/ - -struct decode_ctx *decode_open(const char *src) -{ - struct decode_ctx *fd = (struct decode_ctx*)malloc(sizeof(struct decode_ctx)); - if(!fd) - return NULL; - - int ret; - if((ret = av_open_input_file(&fd->avfctx, src, NULL, 0, NULL)) != 0) { - char err[512]; - av_strerror(ret, err, 512); - fprintf(stderr, "ffmpeg error: %s\n", err); - free(fd); - errno = EIO; - return NULL; - } - - if((ret = av_find_stream_info(fd->avfctx)) < 0) { - char err[512]; - av_strerror(ret, err, 512); - fprintf(stderr, "ffmpeg error: %s\n", err); - av_close_input_file(fd->avfctx); - free(fd); - errno = EIO; - return NULL; - } - - - dump_format(fd->avfctx, 0, src, 0); - - int i; - for(i = 0;i < fd->avfctx->nb_streams;++i) { - if(fd->avfctx->streams[i]->codec->codec_type == CODEC_TYPE_AUDIO) - break; - } - if(i == fd->avfctx->nb_streams) { - // no audio stream - av_close_input_file(fd->avfctx); - free(fd); - errno = EIO; - return NULL; - } - - fd->stream = i; - fd->metadata = fd->avfctx->streams[i]->metadata; - - fd->avc = avcodec_find_decoder(fd->avfctx->streams[fd->stream]->codec->codec_id); - if(!fd->avc) { - fprintf(stderr, "ffmpeg error: Could not find decoder.\n"); - av_close_input_file(fd->avfctx); - free(fd); - errno = EIO; - return NULL; - } - - if((ret = avcodec_open(fd->avfctx->streams[fd->stream]->codec, fd->avc)) < 0) { - char err[512]; - av_strerror(ret, err, 512); - fprintf(stderr, "ffmpeg error: %s\n", err); - av_close_input_file(fd->avfctx); - free(fd); - errno = EIO; - return NULL; - } - - fd->bod = malloc(128*1024*1024); - if(!fd->bod) - return NULL; - - AVPacket pack; - int pos = 0; - int fsp = 128*1024*1024; - while(av_read_frame(fd->avfctx, &pack) == 0) { - if(pack.stream_index == fd->stream) { - if(avcodec_decode_audio3(fd->avfctx->streams[fd->stream]->codec, fd->bod+pos, &fsp, &pack) < 0) { - printf("Decode error.\n"); - return NULL; - } - pos += fsp; - fsp = 128*1024*1024-pos; - } - } - fd->len = pos; - fd->offs = 0; - - return fd; -} - int decode_read(char *buf, size_t size, struct decode_ctx *fd) { - if(size < fd->len-fd->offs) { - memcpy(buf, fd->bod+fd->offs, size); - fd->offs += size; - return size; - } else { - memcpy(buf, fd->bod+fd->offs, fd->len-fd->offs); - int ret = fd->len - fd->offs; - fd->offs = fd->len; - return ret; + if(!fd) { + tcfs_errno = EINVAL; + return -1; } + if(!fd->ops) { + tcfs_errno = EINVAL; + return -1; + } + + return fd->ops->read(buf, size, fd); } int decode_close(struct decode_ctx *fd) -{ +{ if(!fd) { - errno = EINVAL; + tcfs_errno = EINVAL; return -1; } - if(!fd->avfctx || !fd->avc) { - free(fd); - return 0; + if(!fd->ops) { + tcfs_errno = EINVAL; + return -1; } - - free(fd->bod); - avcodec_close(fd->avfctx->streams[fd->stream]->codec); - av_close_input_file(fd->avfctx); - free(fd); - return 0; + + return fd->ops->close(fd); } diff --git a/src/decode.h b/src/decode.h index 8e678c8..b9d3f31 100644 --- a/src/decode.h +++ b/src/decode.h @@ -7,14 +7,14 @@ #ifndef TCFS_DECODE_H #define TCFS_DECODE_H 1 -struct decode_ctx -{ - AVFormatContext *avfctx; - int stream; - AVCodec *avc; - char *bod; - int len, offs; - void *metadata; +struct decode_ctx { + struct decode_ops *ops; +}; + +struct decode_ops { + struct decode_ctx *(*open)(const char *src); + int (*read)(void *buf, size_t size, struct decode_ctx *fd); + int (*close)(struct decode_ctx *fd); }; struct decode_ctx *decode_open(const char *src); diff --git a/src/test_encode.c b/src/test_encode.c index ba8e309..4655dfa 100644 --- a/src/test_encode.c +++ b/src/test_encode.c @@ -6,7 +6,7 @@ #include "common.h" #include -#include <../../ffmpeg/libavformat/metadata.h> +#include "../../ffmpeg/libavformat/metadata.h" #include "util.h" #include "decode.h" @@ -53,7 +53,7 @@ int main(int argc, char *argv[]) tcfs_buf_register(); - struct decode_ctx *decode = decode_open("testbase/fmc/Sinn/01 - Das frivole Burgfräulein - Erwachsen.ogg"); + struct decode_ctx *decode = decode_ffmpeg_open("testbase/fmc/Sinn/01 - Das frivole Burgfräulein - Erwachsen.ogg"); if(!decode) { printf("Can't decode source.\n"); return -1; @@ -106,12 +106,12 @@ int main(int argc, char *argv[]) choose_sample_fmt(st, codec); choose_sample_rate(st, codec); - avfctx->metadata = decode->metadata; + /*avfctx->metadata = decode->metadata; AVMetadataTag *tag = NULL; while((tag=av_metadata_get(decode->metadata, "", tag, AV_METADATA_IGNORE_SUFFIX))) { printf("%s: %s\n", tag->key, tag->value); } - + */ if((ret=avcodec_open(st->codec, codec)) < 0) { char err[512]; av_strerror(ret, err, 512); diff --git a/src/transcode.c b/src/transcode.c index aa23914..fa018e7 100644 --- a/src/transcode.c +++ b/src/transcode.c @@ -20,7 +20,7 @@ struct TC_FILE *tc_open(const char *src, const char *tfmt) return NULL; } - fd->decode = decode_open(src); + fd->decode = decode_ffmpeg_open(src); if(!fd->decode) { free(fd); return NULL; diff --git a/src/util.c b/src/util.c index c189ab4..eec2008 100644 --- a/src/util.c +++ b/src/util.c @@ -8,6 +8,8 @@ #include "util.h" #include "decode.h" +int tcfs_errno = 0; + // Get the filename from a path, i.e. a pointer to the character after the last / in path. // If path contains no /, returns path. const char *get_file_from_path(const char *path) @@ -96,7 +98,7 @@ int is_tc_audio_file(const char *path) return 0; // file already has right format // try to open file as transcode source - struct decode_ctx *tcfd = decode_open(path); + struct decode_ctx *tcfd = decode_ffmpeg_open(path); if(tcfd) { decode_close(tcfd); return 1; diff --git a/src/util.h b/src/util.h index 94e3700..504a7fe 100644 --- a/src/util.h +++ b/src/util.h @@ -13,6 +13,7 @@ struct options { }; extern struct options options; +extern int tcfs_errno; const char *get_file_from_path(const char *path); const char *get_ext_from_file(const char *file);