Decodeing now supports adding different decoder modules. Currently only decode-ffmpeg exists.
This commit is contained in:
3
.gitignore
vendored
3
.gitignore
vendored
@@ -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
|
||||
|
||||
@@ -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
164
src/decode-ffmpeg.c
Normal 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
15
src/decode-ffmpeg.h
Normal 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
|
||||
|
||||
132
src/decode.c
132
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);
|
||||
}
|
||||
|
||||
16
src/decode.h
16
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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user