Hi. On the audacious forum, Andrei Alin proposed a patch for this.
I tried to include it in the audacious-plugins source package (I rewrote it, using autoconf for regenerate the configure file). It builds fine and the ffaudio plugin is enabled again (not enabled in the 3.2-1).
I don't know if I will include it in the next upload (I don't even know if I will push it in the GIT repo), as it's a quite big patch. But audacious developers are not going to make the plugin compatible with older versions of ffmpeg.
I completely understand that upgrading the needed libs is quite risky and won't be done in the next days/weeks without risking to break a lot of packages.
So I would like to know what do you think about this patch, if this can be a good solution, and then I will perform the needed changes and push it to the git repo or if you think it's not a good solution, we won't have the plugin working for now.
Thanks. -- Cyril "Davromaniak" Lavier
Description: Make audacious work with current unstable version of FFAUDIO Author: Andrei Alin <and...@webupd8.org> Last-Update: 2012-01-28 --- a/configure.ac +++ b/configure.ac @@ -549,7 +549,7 @@ if test $enable_ffaudio = yes ; then PKG_CHECK_MODULES([FFMPEG], - [libavcodec >= 53.40.0 libavformat >= 53.5.0 libavutil >= 50.42.0], + [libavcodec >= 52.64.0 libavformat >= 52.110.0 libavutil >= 50.42.0], [have_ffaudio=yes], [have_ffaudio=no]) fi --- a/configure +++ b/configure @@ -10914,12 +10914,12 @@ pkg_cv_FFMPEG_CFLAGS="$FFMPEG_CFLAGS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ - { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libavcodec >= 53.40.0 libavformat >= 53.5.0 libavutil >= 50.42.0\""; } >&5 - ($PKG_CONFIG --exists --print-errors "libavcodec >= 53.40.0 libavformat >= 53.5.0 libavutil >= 50.42.0") 2>&5 + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libavcodec >= 52.64.0 libavformat >= 52.110.0 libavutil >= 50.42.0\""; } >&5 + ($PKG_CONFIG --exists --print-errors "libavcodec >= 52.64.0 libavformat >= 52.110.0 libavutil >= 50.42.0") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then - pkg_cv_FFMPEG_CFLAGS=`$PKG_CONFIG --cflags "libavcodec >= 53.40.0 libavformat >= 53.5.0 libavutil >= 50.42.0" 2>/dev/null` + pkg_cv_FFMPEG_CFLAGS=`$PKG_CONFIG --cflags "libavcodec >= 52.64.0 libavformat >= 52.110.0 libavutil >= 50.42.0" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes @@ -10931,12 +10931,12 @@ pkg_cv_FFMPEG_LIBS="$FFMPEG_LIBS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ - { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libavcodec >= 53.40.0 libavformat >= 53.5.0 libavutil >= 50.42.0\""; } >&5 - ($PKG_CONFIG --exists --print-errors "libavcodec >= 53.40.0 libavformat >= 53.5.0 libavutil >= 50.42.0") 2>&5 + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libavcodec >= 52.64.0 libavformat >= 52.110.0 libavutil >= 50.42.0\""; } >&5 + ($PKG_CONFIG --exists --print-errors "libavcodec >= 52.64.0 libavformat >= 52.110.0 libavutil >= 50.42.0") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then - pkg_cv_FFMPEG_LIBS=`$PKG_CONFIG --libs "libavcodec >= 53.40.0 libavformat >= 53.5.0 libavutil >= 50.42.0" 2>/dev/null` + pkg_cv_FFMPEG_LIBS=`$PKG_CONFIG --libs "libavcodec >= 52.64.0 libavformat >= 52.110.0 libavutil >= 50.42.0" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes @@ -10957,9 +10957,9 @@ _pkg_short_errors_supported=no fi if test $_pkg_short_errors_supported = yes; then - FFMPEG_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "libavcodec >= 53.40.0 libavformat >= 53.5.0 libavutil >= 50.42.0" 2>&1` + FFMPEG_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "libavcodec >= 52.64.0 libavformat >= 52.110.0 libavutil >= 50.42.0" 2>&1` else - FFMPEG_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "libavcodec >= 53.40.0 libavformat >= 53.5.0 libavutil >= 50.42.0" 2>&1` + FFMPEG_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "libavcodec >= 52.64.0 libavformat >= 52.110.0 libavutil >= 50.42.0" 2>&1` fi # Put the nasty error message in config.log where it belongs echo "$FFMPEG_PKG_ERRORS" >&5 --- a/src/ffaudio/ffaudio-core.c +++ b/src/ffaudio/ffaudio-core.c @@ -40,6 +40,14 @@ #endif #include <libaudcore/audstrings.h> +#if ! CHECK_LIBAVFORMAT_VERSION (53, 5, 0) +#define avformat_find_stream_info(i, o) av_find_stream_info (i) +#endif + +#if ! CHECK_LIBAVCODEC_VERSION (53, 8, 0) +#define avcodec_open2(a, c, o) avcodec_open (a, c) +#endif + static GMutex *ctrl_mutex = NULL; static GCond *ctrl_cond = NULL; static gint64 seek_value = -1; @@ -423,8 +431,11 @@ AVCodecContext *c = NULL; AVStream *s = NULL; AVPacket pkt = {.data = NULL}; + guint8 *outbuf = NULL, *resbuf = NULL; gint i, stream_id, errcount; - gboolean codec_opened = FALSE; + gint in_sample_size, out_sample_size, chunk_size; + ReSampleContext *resctx = NULL; + gboolean codec_opened = FALSE, do_resampling = FALSE; gint out_fmt; gboolean seekable; gboolean error = FALSE; @@ -460,14 +471,38 @@ codec_opened = TRUE; + /* Determine if audio conversion or resampling is needed */ + in_sample_size = av_get_bytes_per_sample (c->sample_fmt); + out_sample_size = av_get_bytes_per_sample (SAMPLE_FMT_S16); + + chunk_size = out_sample_size * c->channels * (c->sample_rate / 50); + + switch (c->sample_fmt) { case SAMPLE_FMT_U8: out_fmt = FMT_U8; break; case SAMPLE_FMT_S16: out_fmt = FMT_S16_NE; break; case SAMPLE_FMT_S32: out_fmt = FMT_S32_NE; break; case SAMPLE_FMT_FLT: out_fmt = FMT_FLOAT; break; - default: - fprintf (stderr, "ffaudio: Unsupported audio format %d\n", (int) c->sample_fmt); - goto error_exit; + default: do_resampling = TRUE; break; + } + + if (do_resampling) + { + /* Initialize resampling context */ + out_fmt = FMT_S16_NE; + + AUDDBG("resampling needed chn=%d, rate=%d, fmt=%d -> chn=%d, rate=%d, fmt=S16NE\n", + c->channels, c->sample_rate, c->sample_fmt, + c->channels, c->sample_rate); + + resctx = av_audio_resample_init( + c->channels, c->channels, + c->sample_rate, c->sample_rate, + SAMPLE_FMT_S16, c->sample_fmt, + 16, 10, 0, 0.8); + + if (resctx == NULL) + goto error_exit; } /* Open audio output */ @@ -481,6 +516,10 @@ playback->set_gain_from_playlist(playback); + /* Allocate output buffer aligned to 16 byte boundary */ + outbuf = av_malloc(AVCODEC_MAX_AUDIO_FRAME_SIZE); + resbuf = av_malloc(AVCODEC_MAX_AUDIO_FRAME_SIZE); + AUDDBG("setting parameters\n"); if (pause) @@ -553,6 +592,9 @@ memcpy(&tmp, &pkt, sizeof(tmp)); while (tmp.size > 0 && !stop_flag) { + gint len, out_size = AVCODEC_MAX_AUDIO_FRAME_SIZE; + guint8 *outbuf_p; + /* Check for seek request and bail out if we have one */ g_mutex_lock(ctrl_mutex); if (seek_value != -1) @@ -570,25 +612,60 @@ } g_mutex_unlock(ctrl_mutex); - AVFrame * frame = avcodec_alloc_frame (); - int decoded = 0; - int len = avcodec_decode_audio4 (c, frame, & decoded, & tmp); + /* Decode whatever we can of the frame data */ + len = avcodec_decode_audio3(c, (gint16 *)outbuf, &out_size, &tmp); if (len < 0) { - fprintf (stderr, "ffaudio: decode_audio() failed, code %d\n", len); + AUDDBG("codec failure, breaking out of loop\n"); break; } tmp.size -= len; tmp.data += len; - if (! decoded) + if (out_size <= 0) continue; - playback->output->write_audio (frame->data[0], FMT_SIZEOF (out_fmt) - * c->channels * frame->nb_samples); - av_free (frame); + /* Perform audio resampling if necessary */ + if (do_resampling) + { + out_size = audio_resample(resctx, + (gint16 *)resbuf, (gint16 *)outbuf, + out_size / in_sample_size) * out_sample_size; + outbuf_p = resbuf; + } + else + outbuf_p = outbuf; + + /* Output audio in small blocks */ + while (out_size > 0 && !stop_flag && (stop_time < 0 || + playback->output->written_time () < stop_time)) + { + gint writeoff = MIN (chunk_size, out_size); + + playback->output->write_audio((gint16 *)outbuf_p, writeoff); + + outbuf_p += writeoff; + out_size -= writeoff; + + /* Check for seek request and bail out if we have one */ + g_mutex_lock(ctrl_mutex); + if (seek_value != -1) + { + if (!seekable) + { + seek_value = -1; + g_cond_signal(ctrl_cond); + } + else + { + g_mutex_unlock(ctrl_mutex); + break; + } + } + g_mutex_unlock(ctrl_mutex); + } } if (pkt.data) @@ -611,6 +688,10 @@ stop_flag = TRUE; + av_free(outbuf); + av_free(resbuf); + if (resctx != NULL) + audio_resample_close(resctx); if (pkt.data) av_free_packet(&pkt); if (codec_opened)