From 8012d6cb4bb65a858105ef878c5b98d91b24e1cd Mon Sep 17 00:00:00 2001 From: Lars-Dominik Braun Date: Mon, 7 Apr 2014 17:25:20 +0200 Subject: ffmpeg compatibility Adds support for ffmpeg 2.2 and 1.2. Right now the maintenance overhead of supporting both libav implementations is not that big. Fixes #437 and #435. --- Makefile | 54 +++++++++++++++++++++++++++++++++++------------------- src/player.c | 40 ++++++++++++++++++++++++++++------------ src/player.h | 4 +++- 3 files changed, 66 insertions(+), 32 deletions(-) diff --git a/Makefile b/Makefile index 2267419..53b5cb0 100644 --- a/Makefile +++ b/Makefile @@ -85,30 +85,52 @@ LIBGCRYPT_LDFLAGS:=-lgcrypt LIBJSONC_CFLAGS:=$(shell pkg-config --cflags json-c 2>/dev/null || pkg-config --cflags json) LIBJSONC_LDFLAGS:=$(shell pkg-config --libs json-c 2>/dev/null || pkg-config --libs json) +# simple feature testing +define TEST_AV_BUFFERSINK_GET_BUFFER_REF +#include \n +int main() { + void *foo = av_buffersink_get_buffer_ref; +} +endef + +define TEST_AVFILTER_GRAPH_SEND_COMMAND +#include \n +int main() { + void *foo = avfilter_graph_send_command; +} +endef + +EXTRA_CFLAGS:=\ + $(shell echo -e "${TEST_AV_BUFFERSINK_GET_BUFFER_REF}" | ${CC} ${LIBAV_CFLAGS} ${LIBAV_LDFLAGS} -x c -c -o /dev/null - 2>/dev/null && echo "-DHAVE_AV_BUFFERSINK_GET_BUFFER_REF") \ + $(shell echo -e "${TEST_AVFILTER_GRAPH_SEND_COMMAND}" | ${CC} ${LIBAV_CFLAGS} ${LIBAV_LDFLAGS} -x c -c -o /dev/null - 2>/dev/null && echo "-DHAVE_AVFILTER_GRAPH_SEND_COMMAND") + +# combine all flags +ALL_CFLAGS:=${CFLAGS} -I ${LIBPIANO_INCLUDE} -I ${LIBWAITRESS_INCLUDE} \ + ${LIBAV_CFLAGS} ${LIBGNUTLS_CFLAGS} \ + ${LIBGCRYPT_CFLAGS} ${LIBJSONC_CFLAGS} ${EXTRA_CFLAGS} +ALL_LDFLAGS:=${LDFLAGS} -lao -lpthread -lm \ + ${LIBAV_LDFLAGS} ${LIBGNUTLS_LDFLAGS} \ + ${LIBGCRYPT_LDFLAGS} ${LIBJSONC_LDFLAGS} + # build pianobar ifeq (${DYNLINK},1) pianobar: ${PIANOBAR_OBJ} ${PIANOBAR_HDR} libpiano.so.0 @echo " LINK $@" - @${CC} -o $@ ${PIANOBAR_OBJ} ${LDFLAGS} -lao -lpthread -lm -L. -lpiano \ - ${LIBAV_LDFLAGS} ${LIBGNUTLS_LDFLAGS} ${LIBGCRYPT_LDFLAGS} + @${CC} -o $@ ${PIANOBAR_OBJ} -L. -lpiano ${ALL_LDFLAGS} else pianobar: ${PIANOBAR_OBJ} ${PIANOBAR_HDR} ${LIBPIANO_OBJ} ${LIBWAITRESS_OBJ} \ ${LIBWAITRESS_HDR} @echo " LINK $@" - @${CC} ${CFLAGS} ${LDFLAGS} ${PIANOBAR_OBJ} ${LIBPIANO_OBJ} \ - ${LIBWAITRESS_OBJ} -lao -lpthread -lm \ - ${LIBAV_LDFLAGS} ${LIBGNUTLS_LDFLAGS} \ - ${LIBGCRYPT_LDFLAGS} ${LIBJSONC_LDFLAGS} -o $@ + @${CC} -o $@ ${PIANOBAR_OBJ} ${LIBPIANO_OBJ} ${LIBWAITRESS_OBJ} \ + ${ALL_LDFLAGS} endif # build shared and static libpiano libpiano.so.0: ${LIBPIANO_RELOBJ} ${LIBPIANO_HDR} ${LIBWAITRESS_RELOBJ} \ ${LIBWAITRESS_HDR} ${LIBPIANO_OBJ} ${LIBWAITRESS_OBJ} @echo " LINK $@" - @${CC} -shared -Wl,-soname,libpiano.so.0 ${CFLAGS} ${LDFLAGS} \ - -o libpiano.so.0.0.0 ${LIBPIANO_RELOBJ} \ - ${LIBWAITRESS_RELOBJ} ${LIBGNUTLS_LDFLAGS} ${LIBGCRYPT_LDFLAGS} \ - ${LIBJSONC_LDFLAGS} + @${CC} -shared -Wl,-soname,libpiano.so.0 -o libpiano.so.0.0.0 \ + ${LIBPIANO_RELOBJ} ${LIBWAITRESS_RELOBJ} ${ALL_LDFLAGS} @ln -s libpiano.so.0.0.0 libpiano.so.0 @ln -s libpiano.so.0 libpiano.so @echo " AR libpiano.a" @@ -118,9 +140,7 @@ libpiano.so.0: ${LIBPIANO_RELOBJ} ${LIBPIANO_HDR} ${LIBWAITRESS_RELOBJ} \ # build dependency files %.d: %.c @set -e; rm -f $@; \ - $(CC) -M ${CFLAGS} -I ${LIBPIANO_INCLUDE} -I ${LIBWAITRESS_INCLUDE} \ - ${LIBAV_CFLAGS} ${LIBGNUTLS_CFLAGS} \ - ${LIBGCRYPT_CFLAGS} ${LIBJSONC_CFLAGS} $< > $@.$$$$; \ + $(CC) -M ${ALL_CFLAGS} $< > $@.$$$$; \ sed '1 s,^.*\.o[ :]*,$*.o $@ : ,g' < $@.$$$$ > $@; \ rm -f $@.$$$$ @@ -131,16 +151,12 @@ libpiano.so.0: ${LIBPIANO_RELOBJ} ${LIBPIANO_HDR} ${LIBWAITRESS_RELOBJ} \ # build standard object files %.o: %.c @echo " CC $<" - @${CC} ${CFLAGS} -I ${LIBPIANO_INCLUDE} -I ${LIBWAITRESS_INCLUDE} \ - ${LIBAV_CFLAGS} ${LIBGNUTLS_CFLAGS} \ - ${LIBGCRYPT_CFLAGS} ${LIBJSONC_CFLAGS} -c -o $@ $< + @${CC} -c -o $@ ${ALL_CFLAGS} $< # create position independent code (for shared libraries) %.lo: %.c @echo " CC $< (PIC)" - @${CC} ${CFLAGS} -I ${LIBPIANO_INCLUDE} -I ${LIBWAITRESS_INCLUDE} \ - ${LIBJSONC_CFLAGS} \ - -c -fPIC -o $@ $< + @${CC} -c -fPIC -o $@ ${ALL_CFLAGS} $< clean: @echo " CLEAN" diff --git a/src/player.c b/src/player.c index ac5c42b..f3d9838 100644 --- a/src/player.c +++ b/src/player.c @@ -73,19 +73,28 @@ void BarPlayerDestroy () { } /* Update volume filter - * - * XXX: I’m not sure whether this is thread-safe or not */ void BarPlayerSetVolume (struct audioPlayer * const player) { assert (player != NULL); assert (player->fvolume != NULL); int ret; +#ifdef HAVE_AVFILTER_GRAPH_SEND_COMMAND + /* ffmpeg and libav disagree on the type of this option (string vs. double) + * -> print to string and let them parse it again */ + char strbuf[16]; + snprintf (strbuf, sizeof (strbuf), "%fdB", + player->settings->volume + player->gain); + if ((ret = avfilter_graph_send_command (player->fgraph, "volume", "volume", + strbuf, NULL, 0, 0)) < 0) { +#else /* convert from decibel */ const double volume = pow (10, (player->settings->volume + player->gain) / 20); - /* XXX: can we avoid accessing ->priv here? */ + /* libav does not provide other means to set this right now. it might not + * even work everywhere. */ if ((ret = av_opt_set_double (player->fvolume->priv, "volume", volume, 0)) != 0) { +#endif printError (player->settings, "Cannot set volume", ret); } } @@ -110,7 +119,6 @@ void *BarPlayerThread (void *data) { ao_device *aoDev = NULL; ao_sample_format aoFmt; - AVFilterGraph *fgraph = NULL; AVFrame *frame = NULL, *filteredFrame = NULL; AVFormatContext *fctx = NULL; AVCodecContext *cctx = NULL; @@ -162,7 +170,7 @@ void *BarPlayerThread (void *data) { /* filter setup */ char strbuf[256]; - if ((fgraph = avfilter_graph_alloc ()) == NULL) { + if ((player->fgraph = avfilter_graph_alloc ()) == NULL) { softfail ("graph_alloc"); } @@ -175,13 +183,15 @@ void *BarPlayerThread (void *data) { av_get_sample_fmt_name (cctx->sample_fmt), cctx->channel_layout); if ((ret = avfilter_graph_create_filter (&fabuf, - avfilter_get_by_name ("abuffer"), NULL, strbuf, NULL, fgraph)) < 0) { + avfilter_get_by_name ("abuffer"), NULL, strbuf, NULL, + player->fgraph)) < 0) { softfail ("create_filter abuffer"); } /* volume */ if ((ret = avfilter_graph_create_filter (&player->fvolume, - avfilter_get_by_name ("volume"), NULL, NULL, NULL, fgraph)) < 0) { + avfilter_get_by_name ("volume"), NULL, NULL, NULL, + player->fgraph)) < 0) { softfail ("create_filter volume"); } BarPlayerSetVolume (player); @@ -192,14 +202,15 @@ void *BarPlayerThread (void *data) { av_get_sample_fmt_name (avformat)); if ((ret = avfilter_graph_create_filter (&fafmt, avfilter_get_by_name ("aformat"), NULL, strbuf, NULL, - fgraph)) < 0) { + player->fgraph)) < 0) { softfail ("create_filter aformat"); } /* abuffersink */ AVFilterContext *fbufsink = NULL; if ((ret = avfilter_graph_create_filter (&fbufsink, - avfilter_get_by_name ("abuffersink"), NULL, NULL, NULL, fgraph)) < 0) { + avfilter_get_by_name ("abuffersink"), NULL, NULL, NULL, + player->fgraph)) < 0) { softfail ("create_filter abuffersink"); } @@ -210,7 +221,7 @@ void *BarPlayerThread (void *data) { softfail ("filter_link"); } - if ((ret = avfilter_graph_config (fgraph, NULL)) < 0) { + if ((ret = avfilter_graph_config (player->fgraph, NULL)) < 0) { softfail ("graph_config"); } @@ -277,7 +288,12 @@ void *BarPlayerThread (void *data) { while (true) { AVFilterBufferRef *audioref = NULL; +#ifdef TEST_AV_BUFFERSINK_GET_BUFFER_REF + /* ffmpeg’s compatibility layer is broken in some releases */ + if (av_buffersink_get_buffer_ref (fbufsink, &audioref, 0) < 0) { +#else if (av_buffersink_read (fbufsink, &audioref) < 0) { +#endif /* try again next frame */ break; } @@ -306,8 +322,8 @@ void *BarPlayerThread (void *data) { finish: ao_close (aoDev); - if (fgraph != NULL) { - avfilter_graph_free (&fgraph); + if (player->fgraph != NULL) { + avfilter_graph_free (&player->fgraph); } if (cctx != NULL) { avcodec_close (cctx); diff --git a/src/player.h b/src/player.h index 562c12d..f9e94ef 100644 --- a/src/player.h +++ b/src/player.h @@ -1,5 +1,5 @@ /* -Copyright (c) 2008-2013 +Copyright (c) 2008-2014 Lars-Dominik Braun Permission is hereby granted, free of charge, to any person obtaining a copy @@ -32,6 +32,7 @@ THE SOFTWARE. #include #include +#include #include #include @@ -52,6 +53,7 @@ struct audioPlayer { } mode; AVFilterContext *fvolume; + AVFilterGraph *fgraph; volatile double volume; double gain; -- cgit v1.2.3