- Added LAME mp3 encode module

- Redesigned encode/decode API
- misc. changes and debugging
This commit is contained in:
2011-04-15 13:49:57 +02:00
parent c2bbe2ef69
commit 107be06038
16 changed files with 426 additions and 61 deletions

View File

@@ -1,7 +1,18 @@
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 src/decode-ffmpeg.c src/encode-ffmpeg.c
bin_PROGRAMS=tcfs
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 src/encode-ffmpeg.c
if MP3LAME
tcfs_SOURCES += src/encode-mp3lame.c
endif
tcfs_LDADD = $(LIBOBJS) $(FUSE_LIBS) $(libavcore_LIBS) $(libavutil_LIBS) $(libavformat_LIBS) $(libavcodec_LIBS)
if MP3LAME
tcfs_LDADD += -lmp3lame
endif
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 src/decode-ffmpeg.c src/encode-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)
if MP3LAME
tcfs_CFLAGS += -I/usr/include/lame -DHAVE_LIBMP3LAME
endif
#test_encode_SOURCES = src/decode.c src/encode.c src/tcfs_buf.c src/util.c src/test_encode.c src/decode-ffmpeg.c src/encode-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)

View File

@@ -16,9 +16,11 @@ PKG_CHECK_MODULES([libavcodec], [libavcodec >= 52.94])
PKG_CHECK_MODULES([libavformat], [libavformat >= 52.84])
PKG_CHECK_MODULES([libavcore], [libavcore >= 0.12])
PKG_CHECK_MODULES([libavutil], [libavutil >= 50.32])
PKG_CHECK_MODULES([taglib_c], [taglib_c >= 1.7])
# Checks for header files.
AC_CHECK_HEADERS([fcntl.h stddef.h stdlib.h string.h errno.h dirent.h])
AC_CHECK_HEADERS([fcntl.h stddef.h stdlib.h string.h errno.h dirent.h assert.h])
# Checks for typedefs, structures, and compiler characteristics.
AC_PROG_CC_C99
@@ -29,5 +31,14 @@ AX_TLS
AC_CHECK_FUNCS([memset strerror])
AC_CHECK_FUNCS([asprintf], [], [AC_MSG_ERROR([asprintf emulation for non-GNU systems NYI])])
# Check for optional encoders
# libmp3lame
AC_ARG_ENABLE(mp3lame, [ --enable-mp3lame Enable support for MP3 encoding with libmp3lame],
[AC_CHECK_LIB(mp3lame, get_lame_version, [mp3lame=true], [AC_MSG_WARN([libmp3lame not found]);mp3lame=false])]
[]
)
AM_CONDITIONAL([MP3LAME], [test x$mp3lame = xtrue])
# finish
AC_CONFIG_FILES([Makefile])
AC_OUTPUT

View File

@@ -58,6 +58,10 @@
# include <dirent.h>
#endif
#ifdef HAVE_ASSERT_H
# include <assert.h>
#endif
#include <libavcore/avcore.h>
#include <libavutil/avutil.h>
#include <libavcodec/avcodec.h>

View File

@@ -14,12 +14,12 @@ struct decode_ffmpeg_ctx
AVFormatContext *avfctx;
int stream;
AVCodec *avc;
char *bod;
int16_t *bod;
int len, offs;
void *metadata;
};
struct decode_ctx *decode_ffmpeg_open(const char *src);
struct decode_ctx *decode_ffmpeg_open(const char *src, struct source_info *src_info);
int decode_ffmpeg_read(void *buf, size_t size, struct decode_ctx *fd);
int decode_ffmpeg_close(struct decode_ctx *fd);
@@ -29,7 +29,7 @@ struct decode_ops decode_ffmpeg_ops = {
decode_ffmpeg_close
};
struct decode_ctx *decode_ffmpeg_open(const char *src)
struct decode_ctx *decode_ffmpeg_open(const char *src, struct source_info *src_info)
{
struct decode_ctx *fd = (struct decode_ctx*)malloc(sizeof(struct decode_ctx)+sizeof(struct decode_ffmpeg_ctx));
if(!fd)
@@ -105,24 +105,28 @@ struct decode_ctx *decode_ffmpeg_open(const char *src)
return NULL;
}
ctx->bod = malloc(128*1024*1024);
ctx->bod = (int16_t*)malloc(128*1024*1024);
if(!ctx->bod) {
tcfs_errno = ENOMEM;
return NULL;
}
src_info->sample_rate = ctx->avfctx->streams[ctx->stream]->codec->sample_rate;
src_info->channels = ctx->avfctx->streams[ctx->stream]->codec->channels;
src_info->depth = 16;
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,
(int16_t*)(ctx->bod+pos), &fsp, &pack) < 0) {
ctx->bod+pos, &fsp, &pack) < 0) {
printf("Decode error.\n");
return NULL;
}
pos += fsp;
fsp = 128*1024*1024-pos;
pos += fsp/sizeof(int16_t);
fsp = 128*1024*1024-pos*sizeof(int16_t);
}
}
ctx->len = pos;
@@ -140,12 +144,14 @@ int decode_ffmpeg_read(void *buf, size_t size, struct decode_ctx *fd)
struct decode_ffmpeg_ctx *ctx = (struct decode_ffmpeg_ctx*)(fd+1);
if(size < ctx->len-ctx->offs) {
memcpy(buf, ctx->bod+ctx->offs, size);
if(ctx->offs == ctx->len) { // EOF
return 0;
} else if(size < ctx->len-ctx->offs) {
memcpy(buf, ctx->bod+ctx->offs, size*sizeof(int16_t));
ctx->offs += size;
return size;
} else {
memcpy(buf, ctx->bod+ctx->offs, ctx->len-ctx->offs);
memcpy(buf, ctx->bod+ctx->offs, (ctx->len-ctx->offs)*sizeof(int16_t));
int ret = ctx->len - ctx->offs;
ctx->offs = ctx->len;
return ret;

View File

@@ -9,17 +9,18 @@
#include "decode.h"
#include "decode-ffmpeg.h"
struct decoders_entry decoders[] = {
const struct decoders_entry decoders[] = {
{&decode_ffmpeg_ops, "ffmpeg"},
{NULL, ""}
};
struct decode_ctx *decode_open(const char *src)
struct decode_ctx *decode_open(const char *src, struct source_info *src_info)
{
struct decode_ctx *ctx;
int i = 0;
while(decoders[i].ops) {
ctx = decoders[i++].ops->open(src);
assert(decoders[i].ops->open != NULL);
ctx = decoders[i++].ops->open(src, src_info);
if(!ctx) { // open failed
if(tcfs_errno == ECODEC) // the codec doesn't support this file, try the next one
continue;
@@ -33,7 +34,7 @@ struct decode_ctx *decode_open(const char *src)
return NULL;
}
int decode_read(char *buf, size_t size, struct decode_ctx *fd)
int decode_read(void *buf, size_t size, struct decode_ctx *fd)
{
if(!fd) {
tcfs_errno = EINVAL;

View File

@@ -7,25 +7,27 @@
#ifndef TCFS_DECODE_H
#define TCFS_DECODE_H 1
#include "util.h"
struct decode_ctx {
struct decode_ops *ops;
};
struct decode_ops {
struct decode_ctx *(*open)(const char *src);
struct decode_ctx *(*open)(const char *src, struct source_info *src_info);
int (*read)(void *buf, size_t size, struct decode_ctx *fd);
int (*close)(struct decode_ctx *fd);
};
struct decoders_entry {
struct decode_ops *ops;
char name[];
char name[TCFS_MAX_NAME_LENGTH];
};
extern struct decoders_entry decoders[];
extern const struct decoders_entry decoders[];
struct decode_ctx *decode_open(const char *src);
int decode_read(char *buf, size_t size, struct decode_ctx *fd);
struct decode_ctx *decode_open(const char *src, struct source_info *src_info);
int decode_read(void *buf, size_t size, struct decode_ctx *fd);
int decode_close(struct decode_ctx *fd);
#endif

View File

@@ -9,33 +9,136 @@
#include "encode.h"
#include "encode-ffmpeg.h"
struct encode_ffmpeg_ctx
{
struct ffmpeg_formats {
char name[32];
char codec[32];
char format[32];
int raw;
};
struct encode_ctx *encode_ffmpeg_open(const char *tfmt);
int encode_ffmpeg_encode(void *dst, size_t dst_size, const void *src, size_t src_size, struct encode_ctx *ctx);
int encode_ffmpeg_close(struct encode_ctx *ctx);
struct encode_ffmpeg_ctx
{
struct ffmpeg_formats format;
AVCodecContext *codecctx;
AVCodec *codec;
AVFormatContext *formatctx;
};
struct encode_ctx *encode_ffmpeg_init(struct decode_ctx *src, const char *tfmt, const struct source_info *src_info);
int encode_ffmpeg_encode(void **dst, size_t *dst_size, struct encode_ctx *fd);
int encode_ffmpeg_close(struct encode_ctx *fd);
struct encode_ops encode_ffmpeg_ops = {
encode_ffmpeg_open,
encode_ffmpeg_init,
encode_ffmpeg_encode,
encode_ffmpeg_close
};
struct encode_ctx *encode_ffmpeg_open(const char *tfmt)
// special handling instructions for certain encoders
static struct ffmpeg_formats ffmpeg_formats[] = {
{"mp3", "libmp3lame", "", 1},
{"ogg", "libvorbis", "ogg", 0},
{"flac", "flac", "ogg", 0},
{"", "", 0} // END
};
struct encode_ctx *encode_ffmpeg_init(struct decode_ctx *src, const char *tfmt, const struct source_info *src_info)
{
tcfs_errno = ENOSYS;
struct encode_ctx *fd = (struct encode_ctx*)malloc(sizeof(struct encode_ctx)+sizeof(struct encode_ffmpeg_ctx));
if(!fd) {
tcfs_errno = ENOMEM;
return NULL;
}
struct encode_ffmpeg_ctx *ctx = (struct encode_ffmpeg_ctx*)(fd+1);
fd->src = src;
fd->ops = &encode_ffmpeg_ops;
int i = 0, found = 0;
while(ffmpeg_formats[i].name[0]) {
if(strcmp(tfmt, ffmpeg_formats[i].name) == 0) {
memcpy(&ctx->format, ffmpeg_formats+i, sizeof(struct ffmpeg_formats));
found = 1;
break;
}
}
// try default settings
if(!found) {
strncpy(ctx->format.name, tfmt, 32);
strncpy(ctx->format.codec, tfmt, 32);
strncpy(ctx->format.format, tfmt, 32);
ctx->format.raw = 0;
}
if(ctx->format.raw) {
ctx->formatctx = NULL;
ctx->codec = avcodec_find_encoder_by_name(ctx->format.codec);
if(!ctx->codec) {
tcfs_errno = ECODEC;
free(fd);
return NULL;
}
ctx->codecctx = (AVCodecContext*)malloc(sizeof(AVCodecContext));
if(!ctx->codecctx) {
free(fd);
tcfs_errno = ENOMEM;
return NULL;
}
avcodec_get_context_defaults3(ctx->codecctx, ctx->codec);
//avcodec_thread_init(st->codec, 1);
ctx->codecctx->codec_type = AVMEDIA_TYPE_AUDIO;
ctx->codecctx->channels = 2;
ctx->codecctx->sample_fmt = AV_SAMPLE_FMT_S16;
ctx->codecctx->sample_rate = 44100;
ctx->codecctx->channel_layout = 0;
// ctx->codecctx->flags |= CODEC_FLAG_QSCALE;
// ctx->codecctx->global_quality = 5;
ctx->codecctx->bit_rate = 160000;
ctx->codecctx->time_base = (AVRational){1, 44100};
ctx->codecctx->compression_level = FF_COMPRESSION_DEFAULT;
if(avcodec_open(ctx->codecctx, ctx->codec) < 0) {
free(fd);
tcfs_errno = ECODEC;
return NULL;
}
} else {
tcfs_errno = ENOSYS;
free(fd);
return NULL;
}
}
int encode_ffmpeg_encode(void *dst, size_t dst_size, const void *src, size_t src_size, struct encode_ctx *ctx)
int encode_ffmpeg_encode(void **dst, size_t *dst_size, struct encode_ctx *fd)
{
if(!fd || (fd->ops != &encode_ffmpeg_ops)) {
tcfs_errno = EINVAL;
return -1;
}
struct encode_ffmpeg_ctx *ctx = (struct encode_ffmpeg_ctx*)(fd+1);
return 0;
}
int encode_ffmpeg_close(struct encode_ctx *ctx)
int encode_ffmpeg_close(struct encode_ctx *fd)
{
if(!fd || (fd->ops != &encode_ffmpeg_ops)) {
tcfs_errno = EINVAL;
return -1;
}
struct encode_ffmpeg_ctx *ctx = (struct encode_ffmpeg_ctx*)(fd+1);
return 0;
}

127
src/encode-mp3lame.c Normal file
View File

@@ -0,0 +1,127 @@
/*
Copyright (c) 2010-2011 Matthias Blankertz <matthias@blankertz.org>
This work is licensed under the Open Software License ("OSL") v. 3.0.
*/
#include "common.h"
#include <lame.h>
#include "util.h"
#include "encode.h"
#include "encode-mp3lame.h"
struct encode_ctx *encode_mp3lame_init(struct decode_ctx *src, const char *tfmt, const struct source_info *src_info);
int encode_mp3lame_encode(void **dst, size_t *dst_size, struct encode_ctx *fd);
int encode_mp3lame_close(struct encode_ctx *fd);
struct encode_ops encode_mp3lame_ops = {
encode_mp3lame_init,
encode_mp3lame_encode,
encode_mp3lame_close
};
struct encode_mp3lame_ctx
{
lame_global_flags *gfp;
struct source_info src_info;
};
struct encode_ctx *encode_mp3lame_init(struct decode_ctx *src, const char *tfmt, const struct source_info* src_info)
{
assert(tfmt != NULL);
assert(src_info != NULL);
if(strcmp(tfmt, "mp3") != 0) {
tcfs_errno = ECODEC;
return NULL;
}
struct encode_ctx *fd = (struct encode_ctx*)malloc(sizeof(struct encode_ctx)+sizeof(struct encode_mp3lame_ctx));
if(!fd) {
tcfs_errno = ENOMEM;
return NULL;
}
struct encode_mp3lame_ctx *ctx = (struct encode_mp3lame_ctx*)(fd+1);
fd->src = src;
fd->ops = &encode_mp3lame_ops;
ctx->src_info = *src_info;
ctx->gfp = lame_init();
if(!ctx->gfp) {
free(fd);
tcfs_errno = ENOMEM;
return NULL;
}
if(src_info->samples != 0)
lame_set_num_samples(ctx->gfp, src_info->samples);
if(src_info->sample_rate != 0)
lame_set_in_samplerate(ctx->gfp, src_info->sample_rate);
lame_set_quality(ctx->gfp, 2);
lame_set_VBR(ctx->gfp, vbr_mtrh);
lame_set_VBR_q(ctx->gfp, 3);
lame_set_strict_ISO(ctx->gfp, 1);
if(lame_init_params(ctx->gfp) < 0) {
tcfs_errno = EINVAL;
return NULL;
}
return fd;
}
int encode_mp3lame_encode(void **dst, size_t *dst_size, struct encode_ctx *fd)
{
if(!fd || (fd->ops != &encode_mp3lame_ops)) {
tcfs_errno = EINVAL;
return -1;
}
struct encode_mp3lame_ctx *ctx = (struct encode_mp3lame_ctx*)(fd+1);
int dst_bufsize = 1.25*ctx->src_info.samples+7200;
int dst_pos = 0;
char *dst_buffer = (char*)malloc(dst_bufsize);
if(!dst_buffer) {
tcfs_errno = ENOMEM;
return -1;
}
int16_t *src_buffer = (int16_t*)malloc(1024*ctx->src_info.channels*sizeof(int16_t));
int dec_ret;
while((dec_ret = decode_read((void*)src_buffer, 1024*ctx->src_info.channels, fd->src)) > 0) {
int enc_ret = lame_encode_buffer_interleaved(ctx->gfp, src_buffer, dec_ret/ctx->src_info.channels, dst_buffer+dst_pos, dst_bufsize-dst_pos);
if(enc_ret < 0) {
tcfs_errno = ECODEC;
return -1;
}
dst_pos += enc_ret;
}
int enc_ret = lame_encode_flush(ctx->gfp, dst_buffer+dst_pos, dst_bufsize-dst_pos);
dst_pos += enc_ret;
dst_buffer = (char*)realloc((void*)dst_buffer, dst_pos);
*dst = dst_buffer;
*dst_size = dst_pos;
return 0;
}
int encode_mp3lame_close(struct encode_ctx *fd)
{
if(!fd || (fd->ops != &encode_mp3lame_ops)) {
tcfs_errno = EINVAL;
return -1;
}
struct encode_mp3lame_ctx *ctx = (struct encode_mp3lame_ctx*)(fd+1);
return 0;
}

14
src/encode-mp3lame.h Normal file
View File

@@ -0,0 +1,14 @@
/*
Copyright (c) 2010 Matthias Blankertz <matthias@blankertz.org>
This work is licensed under the Open Software License ("OSL") v. 3.0.
*/
#ifndef TCFS_ENCODE_MP3LAME_H
#define TCFS_ENCODE_MP3LAME_H 1
#include "encode.h"
extern struct encode_ops encode_mp3lame_ops;
#endif

View File

@@ -8,18 +8,22 @@
#include "util.h"
#include "encode.h"
#include "encode-ffmpeg.h"
#include "encode-mp3lame.h"
struct encoders_entry encoders[] = {
{&encode_ffmpeg_ops, "ffmpeg"},
#ifdef HAVE_LIBMP3LAME
{&encode_mp3lame_ops, "mp3lame", 0},
#endif
{&encode_ffmpeg_ops, "ffmpeg", 1},
{NULL, ""}
};
struct encode_ctx *encode_open(const char *tfmt)
struct encode_ctx *encode_init(struct decode_ctx *src, const char *tfmt, const struct source_info *src_info)
{
struct encode_ctx *ctx;
int i = 0;
while(encoders[i].ops) {
ctx = encoders[i++].ops->open(tfmt);
ctx = encoders[i++].ops->init(src, tfmt, src_info);
if(!ctx) { // open failed
if(tcfs_errno == ECODEC) // the codec doesn't support this format, try the next one
continue;
@@ -33,12 +37,18 @@ struct encode_ctx *encode_open(const char *tfmt)
return NULL;
}
int encode_encode(void *dst, size_t dst_size, const void *src, size_t src_size, struct encode_ctx *ctx)
int encode_encode(void **dst, size_t *dst_size, struct encode_ctx *ctx)
{
return 0;
assert(ctx);
assert(ctx->ops);
assert(ctx->ops->encode);
return ctx->ops->encode(dst, dst_size, ctx);
}
int encode_close(struct encode_ctx *ctx)
{
return 0;
assert(ctx);
assert(ctx->ops);
assert(ctx->ops->close);
return ctx->ops->close(ctx);
}

View File

@@ -7,25 +7,30 @@
#ifndef TCFS_ENCODE_H
#define TCFS_ENCODE_H 1
#include "util.h"
#include "decode.h"
struct encode_ctx {
struct encode_ops *ops;
struct decode_ctx *src;
};
struct encode_ops {
struct encode_ctx *(*open)(const char *);
int (*encode)(void *, size_t, const void *, size_t, struct encode_ctx *);
struct encode_ctx *(*init)(struct decode_ctx *, const char *, const struct source_info *);
int (*encode)(void **, size_t *, struct encode_ctx *);
int (*close)(struct encode_ctx *);
};
struct encoders_entry {
struct encode_ops *ops;
char name[];
char name[TCFS_MAX_NAME_LENGTH];
unsigned stream:1;
};
extern struct encoders_entry encoders[];
struct encode_ctx *encode_open(const char *tfmt);
int encode_encode(void *dst, size_t dst_size, const void *src, size_t src_size, struct encode_ctx *ctx);
struct encode_ctx *encode_init(struct decode_ctx *src, const char *tfmt, const struct source_info *src_info);
int encode_encode(void **dst, size_t *dst_size, struct encode_ctx *ctx);
int encode_close(struct encode_ctx *ctx);
#endif

View File

@@ -27,6 +27,7 @@ int tcfs_getattr(const char *path, struct stat *stbuf)
if(tc_src) {
ret = stat(tc_src, stbuf);
stbuf->st_size = 0;
free(tc_src);
if(ret == -1) {
free(base_path);
return -errno;
@@ -117,10 +118,11 @@ int tcfs_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
}
}
filler(buf, file_new_ext, NULL, 0);
free(file_new_ext);
}
}
free(base_path);
free(base_path);
closedir(dir);
return 0;
}
@@ -131,6 +133,7 @@ struct tcfs_file_info {
TRANSCODE
} type;
FILE *fd;
struct TC_FILE *tc_fd;
};
int tcfs_open(const char *path, struct fuse_file_info *fi)
@@ -150,15 +153,19 @@ int tcfs_open(const char *path, struct fuse_file_info *fi)
if(!tcfs_fi->fd) {
char *src_name = get_tc_source_name(base_path);
if(src_name) {
tcfs_fi->fd = fopen(src_name, "r");
if(!tcfs_fi->fd) {
tcfs_fi->tc_fd = tc_open(src_name, base_path, options.tfmt);
free(src_name);
if(!tcfs_fi->tc_fd) {
return -errno;
}
tcfs_fi->type = TRANSCODE;
} else {
return -errno;
}
} else {
tcfs_fi->type = DIRECT;
}
fi->fh = (uint64_t)tcfs_fi;
fi->direct_io = 1;
return 0;
@@ -170,12 +177,15 @@ int tcfs_read(const char *path, char *buf, size_t size, off_t offset, struct fus
if(!tcfs_fi)
return -EINVAL;
errno = 0;
int ret = fread(buf, 1, size, tcfs_fi->fd);
if((ret == 0) && (errno != 0))
return -errno;
return ret;
if(tcfs_fi->type == DIRECT) {
errno = 0;
int ret = fread(buf, 1, size, tcfs_fi->fd);
if((ret == 0) && (errno != 0))
return -errno;
return ret;
} else {
return -ENOSYS;
}
}
void *tcfs_init(struct fuse_conn_info *conn)

View File

@@ -10,9 +10,13 @@
struct TC_FILE {
struct decode_ctx *decode;
struct encode_ctx *encode;
char *encoded_data;
size_t encoded_size;
size_t pos;
};
struct TC_FILE *tc_open(const char *src, const char *tfmt)
struct TC_FILE *tc_open(const char *src, const char *dst, const char *tfmt)
{
struct TC_FILE *fd = (struct TC_FILE*)malloc(sizeof(struct TC_FILE));
if(!fd) {
@@ -20,11 +24,59 @@ struct TC_FILE *tc_open(const char *src, const char *tfmt)
return NULL;
}
fd->decode = decode_open(src);
struct source_info src_info;
fd->decode = decode_open(src, &src_info);
if(!fd->decode) {
free(fd);
return NULL;
}
fd->encode = encode_init(fd->decode, tfmt, &src_info);
if(!fd->encode) {
decode_close(fd->decode);
free(fd);
return NULL;
}
if(encode_encode(&fd->encoded_data, &fd->encoded_size, fd->encode) < 0) {
encode_close(fd->encode);
decode_close(fd->decode);
free(fd);
return NULL;
}
// debug dump
char name[11+strlen(tfmt)];
strcpy(name,"debugdump.");
strcpy(name+10, tfmt);
FILE *debugdump = fopen(name, "w");
fwrite(fd->encoded_data, fd->encoded_size, 1, debugdump);
fclose(debugdump);
return fd;
}
int tc_read(char *buf, size_t size, struct TC_FILE *fd)
{
assert(fd);
size_t readsize = (size+fd->pos<fd->encoded_size)?size:(fd->encoded_size-fd->pos);
if(!readsize)
return 0;
memcpy(buf, fd->encoded_data, readsize);
fd->pos += readsize;
return readsize;
}
int tc_close(struct TC_FILE *fd)
{
assert(fd);
encode_close(fd->encode);
decode_close(fd->decode);
free(fd->encoded_data);
return 0;
}

View File

@@ -9,7 +9,7 @@
struct TC_FILE;
struct TC_FILE *tc_open(const char *src, const char *tfmt);
struct TC_FILE *tc_open(const char *src, const char *dst, const char *tfmt);
int tc_read(char *buf, size_t size, struct TC_FILE *fd);
int tc_close(struct TC_FILE *fd);

View File

@@ -97,8 +97,9 @@ int is_tc_audio_file(const char *path)
if(strcmp(ext,options.tfmt) == 0)
return 0; // file already has right format
struct source_info src_info;
// try to open file as transcode source
struct decode_ctx *tcfd = decode_open(path);
struct decode_ctx *tcfd = decode_open(path, &src_info);
if(tcfd) {
decode_close(tcfd);
return 1;

View File

@@ -17,7 +17,15 @@ struct options {
extern struct options options;
extern TLS int tcfs_errno;
struct source_info {
unsigned long samples;
int sample_rate;
int depth;
int channels;
};
#define ECODEC 1001
#define TCFS_MAX_NAME_LENGTH 64
const char *get_file_from_path(const char *path);
const char *get_ext_from_file(const char *file);