On 01/21/2012 10:28 AM, Cyril Lavier wrote:
Good morning.
So the first tests on wheezy are now done.
Audacious runs well, but apparently, it requires a newer version of
ffmpeg, so for the moment, he can't decode MP3 files. Runs fine with OGG.
On the forum, a developer proposed a patch for using "older" version
of ffmpeg, but it don't seems to work on wheezy (either with sources
directly patched or included in the packaging process with quilt).
On unstable, I'm not able to make it work with quilt. I'm installing
an unstable VM to see if the patch works directly on the sources.
As the forum is down now (502 Bad Gateway error from nginx ^^), so I
can't post the link of the thread containing this.
So that's all for now, I will take some time later to merge my
modification with the git tree, and maybe push it later next week.
I think it's a not so bad start for audacious 3.2 as I don't want to
rush ffmpeg maintainers to upgrade packages and maybe break a lot of
stuff.
Thanks.
Hi again.
I sadly confirm, even with the patch applied directly to the sources on
debian sid, still no MP3 support.
For information, the patch is attached to this mail.
Thanks.
--
Cyril "Davromaniak" Lavier
--- ./configure.ac
+++ ./configure.new.ac
@@ -544,7 +544,7 @@ AC_ARG_ENABLE(ffaudio,
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
--- ./src/ffaudio/ffaudio-core.c
+++ ./src/ffaudio/ffaudio-core.new.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;
@@ -417,8 +425,11 @@ static gboolean ffaudio_play (InputPlayback * playback, const gchar * filename,
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;
@@ -454,14 +465,37 @@ static gboolean ffaudio_play (InputPlayback * playback, const gchar * filename,
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 */
@@ -475,6 +509,10 @@ static gboolean ffaudio_play (InputPlayback * playback, const gchar * filename,
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)
@@ -547,6 +585,9 @@ static gboolean ffaudio_play (InputPlayback * playback, const gchar * filename,
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)
@@ -564,25 +605,59 @@ static gboolean ffaudio_play (InputPlayback * playback, const gchar * filename,
}
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)
@@ -605,6 +680,10 @@ static gboolean ffaudio_play (InputPlayback * playback, const gchar * filename,
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)