Added infrastructure for different encode modules.
Made tcfs_errno thread-local and added TLS autoconf check.
This commit is contained 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 src/decode-ffmpeg.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 src/encode-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 src/decode-ffmpeg.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 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)
|
||||
76
acinclude.m4
Normal file
76
acinclude.m4
Normal file
@@ -0,0 +1,76 @@
|
||||
# ===========================================================================
|
||||
# http://www.gnu.org/software/autoconf-archive/ax_tls.html
|
||||
# ===========================================================================
|
||||
#
|
||||
# SYNOPSIS
|
||||
#
|
||||
# AX_TLS([action-if-found], [action-if-not-found])
|
||||
#
|
||||
# DESCRIPTION
|
||||
#
|
||||
# Provides a test for the compiler support of thread local storage (TLS)
|
||||
# extensions. Defines TLS if it is found. Currently knows about GCC/ICC
|
||||
# and MSVC. I think SunPro uses the same as GCC, and Borland apparently
|
||||
# supports either.
|
||||
#
|
||||
# LICENSE
|
||||
#
|
||||
# Copyright (c) 2008 Alan Woodland <ajw05@aber.ac.uk>
|
||||
# Copyright (c) 2010 Diego Elio Petteno` <flameeyes@gmail.com>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify it
|
||||
# under the terms of the GNU General Public License as published by the
|
||||
# Free Software Foundation, either version 3 of the License, or (at your
|
||||
# option) any later version.
|
||||
#
|
||||
# This program 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 General
|
||||
# Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along
|
||||
# with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
# As a special exception, the respective Autoconf Macro's copyright owner
|
||||
# gives unlimited permission to copy, distribute and modify the configure
|
||||
# scripts that are the output of Autoconf when processing the Macro. You
|
||||
# need not follow the terms of the GNU General Public License when using
|
||||
# or distributing such scripts, even though portions of the text of the
|
||||
# Macro appear in them. The GNU General Public License (GPL) does govern
|
||||
# all other use of the material that constitutes the Autoconf Macro.
|
||||
#
|
||||
# This special exception to the GPL applies to versions of the Autoconf
|
||||
# Macro released by the Autoconf Archive. When you make and distribute a
|
||||
# modified version of the Autoconf Macro, you may extend this special
|
||||
# exception to the GPL to apply to your modified version as well.
|
||||
|
||||
#serial 10
|
||||
|
||||
AC_DEFUN([AX_TLS], [
|
||||
AC_MSG_CHECKING(for thread local storage (TLS) class)
|
||||
AC_CACHE_VAL(ac_cv_tls, [
|
||||
ax_tls_keywords="__thread __declspec(thread) none"
|
||||
for ax_tls_keyword in $ax_tls_keywords; do
|
||||
AS_CASE([$ax_tls_keyword],
|
||||
[none], [ac_cv_tls=none ; break],
|
||||
[AC_TRY_COMPILE(
|
||||
[#include <stdlib.h>
|
||||
static void
|
||||
foo(void) {
|
||||
static ] $ax_tls_keyword [ int bar;
|
||||
exit(1);
|
||||
}],
|
||||
[],
|
||||
[ac_cv_tls=$ax_tls_keyword ; break],
|
||||
ac_cv_tls=none
|
||||
)])
|
||||
done
|
||||
])
|
||||
AC_MSG_RESULT($ac_cv_tls)
|
||||
|
||||
AS_IF([test "$ac_cv_tls" != "none"],
|
||||
AC_DEFINE_UNQUOTED([TLS], $ac_cv_tls, [If the compiler supports a TLS storage class define it to that here])
|
||||
m4_ifnblank([$1], [$1]),
|
||||
m4_ifnblank([$2], [$2])
|
||||
)
|
||||
])
|
||||
@@ -23,6 +23,7 @@ AC_CHECK_HEADERS([fcntl.h stddef.h stdlib.h string.h errno.h dirent.h])
|
||||
# Checks for typedefs, structures, and compiler characteristics.
|
||||
AC_PROG_CC_C99
|
||||
AM_PROG_CC_C_O
|
||||
AX_TLS
|
||||
|
||||
# Checks for library functions.
|
||||
AC_CHECK_FUNCS([memset strerror])
|
||||
|
||||
@@ -20,7 +20,7 @@ struct decode_ffmpeg_ctx
|
||||
};
|
||||
|
||||
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_read(void *buf, size_t size, struct decode_ctx *fd);
|
||||
int decode_ffmpeg_close(struct decode_ctx *fd);
|
||||
|
||||
struct decode_ops decode_ffmpeg_ops = {
|
||||
@@ -44,7 +44,10 @@ struct decode_ctx *decode_ffmpeg_open(const char *src)
|
||||
av_strerror(ret, err, 512);
|
||||
fprintf(stderr, "ffmpeg error: %s\n", err);
|
||||
free(fd);
|
||||
errno = EIO;
|
||||
if((ret == AVERROR_NOFMT) || (ret == AVERROR_INVALIDDATA) || (ret == AVERROR_PATCHWELCOME))
|
||||
tcfs_errno = ECODEC;
|
||||
else
|
||||
tcfs_errno = AVUNERROR(ret);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -54,7 +57,10 @@ struct decode_ctx *decode_ffmpeg_open(const char *src)
|
||||
fprintf(stderr, "ffmpeg error: %s\n", err);
|
||||
av_close_input_file(ctx->avfctx);
|
||||
free(fd);
|
||||
errno = EIO;
|
||||
if((ret == AVERROR_NOFMT) || (ret == AVERROR_INVALIDDATA) || (ret == AVERROR_PATCHWELCOME))
|
||||
tcfs_errno = ECODEC;
|
||||
else
|
||||
tcfs_errno = AVUNERROR(ret);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -70,7 +76,7 @@ struct decode_ctx *decode_ffmpeg_open(const char *src)
|
||||
// no audio stream
|
||||
av_close_input_file(ctx->avfctx);
|
||||
free(fd);
|
||||
errno = EIO;
|
||||
tcfs_errno = ECODEC;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -82,7 +88,7 @@ struct decode_ctx *decode_ffmpeg_open(const char *src)
|
||||
fprintf(stderr, "ffmpeg error: Could not find decoder.\n");
|
||||
av_close_input_file(ctx->avfctx);
|
||||
free(fd);
|
||||
errno = EIO;
|
||||
tcfs_errno = ECODEC;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -92,20 +98,26 @@ struct decode_ctx *decode_ffmpeg_open(const char *src)
|
||||
fprintf(stderr, "ffmpeg error: %s\n", err);
|
||||
av_close_input_file(ctx->avfctx);
|
||||
free(fd);
|
||||
errno = EIO;
|
||||
if((ret == AVERROR_NOFMT) || (ret == AVERROR_INVALIDDATA) || (ret == AVERROR_PATCHWELCOME))
|
||||
tcfs_errno = ECODEC;
|
||||
else
|
||||
tcfs_errno = AVUNERROR(ret);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ctx->bod = malloc(128*1024*1024);
|
||||
if(!ctx->bod)
|
||||
if(!ctx->bod) {
|
||||
tcfs_errno = ENOMEM;
|
||||
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) {
|
||||
if(avcodec_decode_audio3(ctx->avfctx->streams[ctx->stream]->codec,
|
||||
(int16_t*)(ctx->bod+pos), &fsp, &pack) < 0) {
|
||||
printf("Decode error.\n");
|
||||
return NULL;
|
||||
}
|
||||
@@ -119,7 +131,7 @@ struct decode_ctx *decode_ffmpeg_open(const char *src)
|
||||
return fd;
|
||||
}
|
||||
|
||||
int decode_ffmpeg_read(char *buf, size_t size, struct decode_ctx *fd)
|
||||
int decode_ffmpeg_read(void *buf, size_t size, struct decode_ctx *fd)
|
||||
{
|
||||
if(!fd || (fd->ops != &decode_ffmpeg_ops)) {
|
||||
tcfs_errno = EINVAL;
|
||||
|
||||
25
src/decode.c
25
src/decode.c
@@ -7,6 +7,31 @@
|
||||
#include "common.h"
|
||||
#include "util.h"
|
||||
#include "decode.h"
|
||||
#include "decode-ffmpeg.h"
|
||||
|
||||
struct decoders_entry decoders[] = {
|
||||
{&decode_ffmpeg_ops, "ffmpeg"},
|
||||
{NULL, ""}
|
||||
};
|
||||
|
||||
struct decode_ctx *decode_open(const char *src)
|
||||
{
|
||||
struct decode_ctx *ctx;
|
||||
int i = 0;
|
||||
while(decoders[i].ops) {
|
||||
ctx = decoders[i++].ops->open(src);
|
||||
if(!ctx) { // open failed
|
||||
if(tcfs_errno == ECODEC) // the codec doesn't support this file, try the next one
|
||||
continue;
|
||||
// something else went wrong, give up
|
||||
return NULL;
|
||||
}
|
||||
return ctx;
|
||||
}
|
||||
|
||||
// no codec found
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int decode_read(char *buf, size_t size, struct decode_ctx *fd)
|
||||
{
|
||||
|
||||
@@ -17,6 +17,13 @@ struct decode_ops {
|
||||
int (*close)(struct decode_ctx *fd);
|
||||
};
|
||||
|
||||
struct decoders_entry {
|
||||
struct decode_ops *ops;
|
||||
char name[];
|
||||
};
|
||||
|
||||
extern struct decoders_entry decoders[];
|
||||
|
||||
struct decode_ctx *decode_open(const char *src);
|
||||
int decode_read(char *buf, size_t size, struct decode_ctx *fd);
|
||||
int decode_close(struct decode_ctx *fd);
|
||||
|
||||
41
src/encode-ffmpeg.c
Normal file
41
src/encode-ffmpeg.c
Normal file
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
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 "encode.h"
|
||||
#include "encode-ffmpeg.h"
|
||||
|
||||
struct encode_ffmpeg_ctx
|
||||
{
|
||||
|
||||
};
|
||||
|
||||
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_ops encode_ffmpeg_ops = {
|
||||
encode_ffmpeg_open,
|
||||
encode_ffmpeg_encode,
|
||||
encode_ffmpeg_close
|
||||
};
|
||||
|
||||
struct encode_ctx *encode_ffmpeg_open(const char *tfmt)
|
||||
{
|
||||
tcfs_errno = ENOSYS;
|
||||
}
|
||||
|
||||
int encode_ffmpeg_encode(void *dst, size_t dst_size, const void *src, size_t src_size, struct encode_ctx *ctx)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int encode_ffmpeg_close(struct encode_ctx *ctx)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
14
src/encode-ffmpeg.h
Normal file
14
src/encode-ffmpeg.h
Normal 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_FFMPEG_H
|
||||
#define TCFS_ENCODE_FFMPEG_H 1
|
||||
|
||||
#include "encode.h"
|
||||
|
||||
extern struct encode_ops encode_ffmpeg_ops;
|
||||
|
||||
#endif
|
||||
62
src/encode.c
62
src/encode.c
@@ -5,46 +5,40 @@
|
||||
*/
|
||||
|
||||
#include "common.h"
|
||||
#include "util.h"
|
||||
#include "encode.h"
|
||||
#include "encode-ffmpeg.h"
|
||||
|
||||
struct encode_ctx {
|
||||
AVFormatContext *avfctx;
|
||||
struct encoders_entry encoders[] = {
|
||||
{&encode_ffmpeg_ops, "ffmpeg"},
|
||||
{NULL, ""}
|
||||
};
|
||||
|
||||
struct encode_ctx *encode_open(const char *tfmt)
|
||||
{
|
||||
struct encode_ctx *ctx = (struct encode_ctx*)malloc(sizeof(struct encode_ctx));
|
||||
if(!ctx) {
|
||||
errno = ENOMEM;
|
||||
struct encode_ctx *ctx;
|
||||
int i = 0;
|
||||
while(encoders[i].ops) {
|
||||
ctx = encoders[i++].ops->open(tfmt);
|
||||
if(!ctx) { // open failed
|
||||
if(tcfs_errno == ECODEC) // the codec doesn't support this format, try the next one
|
||||
continue;
|
||||
// something else went wrong, give up
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ctx->avfctx = avformat_alloc_context();
|
||||
if(!ctx->avfctx) {
|
||||
free(ctx);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int ret;
|
||||
URLContext *urlctx;
|
||||
if((ret = url_open_protocol(&urlctx, tcfs_buf_get_protocol(), "", 0)) != 0) {
|
||||
char err[512];
|
||||
av_strerror(ret, err, 512);
|
||||
fprintf(stderr, "ffmpeg error: %s\n", err);
|
||||
free(ctx->avfctx);
|
||||
free(ctx);
|
||||
errno = EIO;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if((ret = url_fdopen(&ctx->avfctx->pb, urlctx)) != 0) {
|
||||
char err[512];
|
||||
av_strerror(ret, err, 512);
|
||||
fprintf(stderr, "ffmpeg error: %s\n", err);
|
||||
free(ctx->avfctx);
|
||||
free(ctx);
|
||||
errno = EIO;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return ctx;
|
||||
}
|
||||
|
||||
// no codec found
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int encode_encode(void *dst, size_t dst_size, const void *src, size_t src_size, struct encode_ctx *ctx)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int encode_close(struct encode_ctx *ctx)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
19
src/encode.h
19
src/encode.h
@@ -7,8 +7,25 @@
|
||||
#ifndef TCFS_ENCODE_H
|
||||
#define TCFS_ENCODE_H 1
|
||||
|
||||
struct encode_ctx;
|
||||
struct encode_ctx {
|
||||
struct encode_ops *ops;
|
||||
};
|
||||
|
||||
struct encode_ops {
|
||||
struct encode_ctx *(*open)(const char *);
|
||||
int (*encode)(void *, size_t, const void *, size_t, struct encode_ctx *);
|
||||
int (*close)(struct encode_ctx *);
|
||||
};
|
||||
|
||||
struct encoders_entry {
|
||||
struct encode_ops *ops;
|
||||
char name[];
|
||||
};
|
||||
|
||||
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);
|
||||
int encode_close(struct encode_ctx *ctx);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -53,7 +53,7 @@ int main(int argc, char *argv[])
|
||||
|
||||
tcfs_buf_register();
|
||||
|
||||
struct decode_ctx *decode = decode_ffmpeg_open("testbase/fmc/Sinn/01 - Das frivole Burgfräulein - Erwachsen.ogg");
|
||||
struct decode_ctx *decode = decode_open("testbase/fmc/Sinn/01 - Das frivole Burgfräulein - Erwachsen.ogg");
|
||||
if(!decode) {
|
||||
printf("Can't decode source.\n");
|
||||
return -1;
|
||||
|
||||
@@ -20,7 +20,7 @@ struct TC_FILE *tc_open(const char *src, const char *tfmt)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
fd->decode = decode_ffmpeg_open(src);
|
||||
fd->decode = decode_open(src);
|
||||
if(!fd->decode) {
|
||||
free(fd);
|
||||
return NULL;
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
#include "util.h"
|
||||
#include "decode.h"
|
||||
|
||||
int tcfs_errno = 0;
|
||||
TLS 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.
|
||||
@@ -98,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_ffmpeg_open(path);
|
||||
struct decode_ctx *tcfd = decode_open(path);
|
||||
if(tcfd) {
|
||||
decode_close(tcfd);
|
||||
return 1;
|
||||
|
||||
@@ -7,13 +7,17 @@
|
||||
#ifndef TCFS_UTIL_H
|
||||
#define TCFS_UTIL_H 1
|
||||
|
||||
#include "common.h"
|
||||
|
||||
struct options {
|
||||
char *base;
|
||||
char *tfmt;
|
||||
};
|
||||
|
||||
extern struct options options;
|
||||
extern int tcfs_errno;
|
||||
extern TLS int tcfs_errno;
|
||||
|
||||
#define ECODEC 1001
|
||||
|
||||
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