Decodeing now supports adding different decoder modules. Currently only decode-ffmpeg exists.

This commit is contained in:
2010-11-15 13:32:09 +01:00
parent 62041710e1
commit 794a7795d7
10 changed files with 217 additions and 132 deletions

3
.gitignore vendored
View File

@@ -1,6 +1,7 @@
tcfs
test_encode
*.mp3
*.wav
*.o
*~
testmnt/
@@ -20,4 +21,4 @@ INSTALL
install-sh
missing
stamp-h1
config.h.in
config.h.in

View File

@@ -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)

164
src/decode-ffmpeg.c Normal file
View File

@@ -0,0 +1,164 @@
/*
Copyright (c) 2010 Matthias Blankertz <matthias@blankertz.org>
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;
}

15
src/decode-ffmpeg.h Normal file
View File

@@ -0,0 +1,15 @@
/*
Copyright (c) 2010 Matthias Blankertz <matthias@blankertz.org>
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

View File

@@ -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);
}

View File

@@ -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);

View File

@@ -6,7 +6,7 @@
#include "common.h"
#include <libavformat/avformat.h>
#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);

View File

@@ -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;

View File

@@ -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;

View File

@@ -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);