1
0
mirror of https://github.com/mpv-player/mpv synced 2024-12-23 07:12:39 +00:00
mpv/audio/decode/ad_mpg123.c
wm4 8f1151a00e audio: fix mid-stream audio reconfiguration
Commit 22b3f522 not only redid major aspects of audio decoding, but also
attempted to fix audio format change handling. Before that commit, data
that was already decoded but not yet filtered was thrown away on a
format change. After that commit, data was supposed to finish playing
before rebuilding filters and so on.

It was still buggy, though: the decoder buffer was initialized to the
new format too early, triggering an assertion failure. Move the reinit
call below filtering to fix this.

ad_mpg123.c needs to be adjusted so that it doesn't decode new data
before the format change is actually executed.

Add some more assertions to af_play() (audio filtering) to make sure
input data and configured format don't mismatch. This will also catch
filters which don't set the format on their output data correctly.

Regression due to planar_audio branch.
2013-11-18 14:20:59 +01:00

380 lines
12 KiB
C

/*
* MPEG 1.0/2.0/2.5 audio layer I, II, III decoding with libmpg123
*
* Copyright (C) 2010-2013 Thomas Orgis <thomas@orgis.org>
*
* MPlayer 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 2 of the License, or
* (at your option) any later version.
*
* MPlayer 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 MPlayer; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include "config.h"
#include "ad.h"
#include "mpvcore/mp_msg.h"
#include <mpg123.h>
#if (defined MPG123_API_VERSION) && (MPG123_API_VERSION < 33)
#error "This should not happen"
#endif
struct ad_mpg123_context {
mpg123_handle *handle;
bool new_format;
int sample_size;
bool need_data;
/* Running mean for bit rate, stream length estimation. */
float mean_rate;
unsigned int mean_count;
/* Time delay for updates. */
short delay;
/* If the stream is actually VBR. */
char vbr;
};
static void uninit(sh_audio_t *sh)
{
struct ad_mpg123_context *con = (struct ad_mpg123_context*) sh->context;
mpg123_close(con->handle);
mpg123_delete(con->handle);
talloc_free(sh->context);
sh->context = NULL;
mpg123_exit();
}
/* This initializes libmpg123 and prepares the handle, including funky
* parameters. */
static int preinit(sh_audio_t *sh)
{
int err;
struct ad_mpg123_context *con;
/* Assumption: You always call preinit + init + uninit, on every file.
* But you stop at preinit in case it fails.
* If that is not true, one must ensure not to call mpg123_init / exit
* twice in a row. */
if (mpg123_init() != MPG123_OK)
return 0;
sh->context = talloc_zero(NULL, struct ad_mpg123_context);
con = sh->context;
/* Auto-choice of optimized decoder (first argument NULL). */
con->handle = mpg123_new(NULL, &err);
if (!con->handle)
goto bad_end;
/* Basic settings.
* Don't spill messages, enable better resync with non-seekable streams.
* Give both flags individually without error checking to keep going with
* old libmpg123. Generally, it is not fatal if the flags are not
* honored */
mpg123_param(con->handle, MPG123_ADD_FLAGS, MPG123_QUIET, 0.0);
/* Do not bail out on malformed streams at all.
* MPlayer does not handle a decoder throwing the towel on crappy input. */
mpg123_param(con->handle, MPG123_RESYNC_LIMIT, -1, 0.0);
/* Open decisions: Configure libmpg123 to force encoding (or stay open about
* library builds that support only float or int32 output), (de)configure
* gapless decoding (won't work with seeking in MPlayer, though).
* Don't forget to eventually enable ReplayGain/RVA support, too.
* Let's try to run with the default for now. */
/* That would produce floating point output.
* You can get 32 and 24 bit ints, even 8 bit via format matrix.
* If wanting a specific encoding here, configure format matrix and
* make sure it is in set_format(). */
/* mpg123_param(con->handle, MPG123_ADD_FLAGS, MPG123_FORCE_FLOAT, 0.); */
/* Example for RVA choice (available since libmpg123 1.0.0):
mpg123_param(con->handle, MPG123_RVA, MPG123_RVA_MIX, 0.0) */
/* Prevent funky automatic resampling.
* This way, we can be sure that one frame will never produce
* more than 1152 stereo samples.
* Background:
* Going to decode directly to the output buffer. It is important to have
* MPG123_AUTO_RESAMPLE disabled for the buffer size being an all-time
* limit.
* We need at least 1152 samples. dec_audio.c normally guarantees this. */
mpg123_param(con->handle, MPG123_REMOVE_FLAGS, MPG123_AUTO_RESAMPLE, 0.);
return 1;
bad_end:
if (!con->handle)
mp_msg(MSGT_DECAUDIO, MSGL_ERR, "mpg123 preinit error: %s\n",
mpg123_plain_strerror(err));
else
mp_msg(MSGT_DECAUDIO, MSGL_ERR, "mpg123 preinit error: %s\n",
mpg123_strerror(con->handle));
uninit(sh);
return 0;
}
/* libmpg123 has a new format ready; query and store, return return value
of mpg123_getformat() */
static int set_format(sh_audio_t *sh)
{
struct ad_mpg123_context *con = sh->context;
int ret;
long rate;
int channels;
int encoding;
ret = mpg123_getformat(con->handle, &rate, &channels, &encoding);
if (ret == MPG123_OK) {
mp_chmap_from_channels(&sh->channels, channels);
sh->samplerate = rate;
/* Without external force, mpg123 will always choose signed encoding,
* and non-16-bit only on builds that don't support it.
* Be reminded that it doesn't matter to the MPEG file what encoding
* is produced from it. */
switch (encoding) {
case MPG123_ENC_SIGNED_8:
sh->sample_format = AF_FORMAT_S8;
break;
case MPG123_ENC_SIGNED_16:
sh->sample_format = AF_FORMAT_S16;
break;
case MPG123_ENC_SIGNED_32:
sh->sample_format = AF_FORMAT_S32;
break;
case MPG123_ENC_FLOAT_32:
sh->sample_format = AF_FORMAT_FLOAT;
break;
default:
/* This means we got a funny custom build of libmpg123 that only supports an unknown format. */
mp_msg(MSGT_DECAUDIO, MSGL_ERR,
"Bad encoding from mpg123: %i.\n", encoding);
return MPG123_ERR;
}
con->sample_size = channels * (af_fmt2bits(sh->sample_format) / 8);
con->new_format = 0;
}
return ret;
}
static int feed_new_packet(sh_audio_t *sh)
{
struct ad_mpg123_context *con = sh->context;
int ret;
struct demux_packet *pkt = demux_read_packet(sh->gsh);
if (!pkt)
return -1; /* EOF. */
/* Next bytes from that presentation time. */
if (pkt->pts != MP_NOPTS_VALUE) {
sh->pts = pkt->pts;
sh->pts_offset = 0;
}
/* Have to use mpg123_feed() to avoid decoding here. */
ret = mpg123_feed(con->handle, pkt->buffer, pkt->len);
talloc_free(pkt);
if (ret == MPG123_ERR)
return -1;
if (ret == MPG123_NEW_FORMAT)
con->new_format = 1;
return 0;
}
/* Now we really start accessing some data and determining file format.
* Format now is allowed to change on-the-fly. Here is the only point
* that has MPlayer react to errors. We have to pray that exceptional
* erros in other places simply cannot occur. */
static int init(sh_audio_t *sh, const char *decoder)
{
struct ad_mpg123_context *con = sh->context;
int ret;
ret = mpg123_open_feed(con->handle);
if (ret != MPG123_OK)
goto fail;
for (int n = 0; ; n++) {
if (feed_new_packet(sh) < 0) {
ret = MPG123_NEED_MORE;
goto fail;
}
size_t got_now = 0;
ret = mpg123_decode_frame(con->handle, NULL, NULL, &got_now);
if (ret == MPG123_OK || ret == MPG123_NEW_FORMAT) {
ret = set_format(sh);
if (ret == MPG123_OK)
break;
}
if (ret != MPG123_NEED_MORE)
goto fail;
// max. 16 retries (randomly chosen number)
if (n > 16) {
ret = MPG123_NEED_MORE;
goto fail;
}
}
return 1;
fail:
if (ret == MPG123_NEED_MORE) {
mp_msg(MSGT_DECAUDIO, MSGL_ERR, "Could not find mp3 stream.\n");
} else {
mp_msg(MSGT_DECAUDIO, MSGL_ERR, "mpg123 init error: %s\n",
mpg123_strerror(con->handle));
}
uninit(sh);
return 0;
}
/* Compute bitrate from frame size. */
static int compute_bitrate(struct mpg123_frameinfo *i)
{
static const int samples_per_frame[4][4] = {
{-1, 384, 1152, 1152}, /* MPEG 1 */
{-1, 384, 1152, 576}, /* MPEG 2 */
{-1, 384, 1152, 576}, /* MPEG 2.5 */
{-1, -1, -1, -1}, /* Unknown */
};
return (int) ((i->framesize + 4) * 8 * i->rate * 0.001 /
samples_per_frame[i->version][i->layer] + 0.5);
}
/* Update mean bitrate. This could be dropped if accurate time display
* on audio file playback is not desired. */
static void update_info(sh_audio_t *sh)
{
struct ad_mpg123_context *con = sh->context;
struct mpg123_frameinfo finfo;
if (mpg123_info(con->handle, &finfo) != MPG123_OK)
return;
if (finfo.vbr != MPG123_CBR) {
if (--con->delay < 1) {
if (++con->mean_count > ((unsigned int) -1) / 2)
con->mean_count = ((unsigned int) -1) / 4;
/* Might not be numerically optimal, but works fine enough. */
con->mean_rate = ((con->mean_count - 1) * con->mean_rate +
finfo.bitrate) / con->mean_count;
sh->i_bps = (int) (con->mean_rate * 1000 / 8);
con->delay = 10;
}
} else {
sh->i_bps = (finfo.bitrate ? finfo.bitrate : compute_bitrate(&finfo))
* 1000 / 8;
con->delay = 1;
con->mean_rate = 0.;
con->mean_count = 0;
}
}
static int decode_audio(sh_audio_t *sh, struct mp_audio *buffer, int maxlen)
{
struct ad_mpg123_context *con = sh->context;
void *buf = buffer->planes[0];
int ret;
if (con->new_format) {
ret = set_format(sh);
if (ret == MPG123_OK) {
return 0; // let caller handle format change
} else if (ret == MPG123_NEED_MORE) {
con->need_data = true;
} else {
goto mpg123_fail;
}
}
if (con->need_data) {
if (feed_new_packet(sh) < 0)
return -1;
}
if (sh->samplerate != buffer->rate ||
!mp_chmap_equals(&sh->channels, &buffer->channels) ||
sh->sample_format != buffer->format)
return 0;
size_t got_now = 0;
ret = mpg123_replace_buffer(con->handle, buf, maxlen * con->sample_size);
if (ret != MPG123_OK)
goto mpg123_fail;
ret = mpg123_decode_frame(con->handle, NULL, NULL, &got_now);
int got_samples = got_now / con->sample_size;
buffer->samples += got_samples;
sh->pts_offset += got_samples;
if (ret == MPG123_NEW_FORMAT) {
con->new_format = true;
} else if (ret == MPG123_NEED_MORE) {
con->need_data = true;
} else if (ret != MPG123_OK && ret != MPG123_DONE) {
goto mpg123_fail;
}
update_info(sh);
return 0;
mpg123_fail:
mp_msg(MSGT_DECAUDIO, MSGL_ERR, "mpg123 decoding error: %s\n",
mpg123_strerror(con->handle));
return -1;
}
static int control(sh_audio_t *sh, int cmd, void *arg)
{
struct ad_mpg123_context *con = sh->context;
switch (cmd) {
case ADCTRL_RESYNC_STREAM:
mpg123_close(con->handle);
if (mpg123_open_feed(con->handle) != MPG123_OK) {
mp_msg(MSGT_DECAUDIO, MSGL_ERR,
"mpg123 failed to reopen stream: %s\n",
mpg123_strerror(con->handle));
return CONTROL_FALSE;
}
return CONTROL_TRUE;
}
return CONTROL_UNKNOWN;
}
static void add_decoders(struct mp_decoder_list *list)
{
mp_add_decoder(list, "mpg123", "mp3", "mp3",
"High-performance decoder using libmpg123");
}
const struct ad_functions ad_mpg123 = {
.name = "mpg123",
.add_decoders = add_decoders,
.preinit = preinit,
.init = init,
.uninit = uninit,
.control = control,
.decode_audio = decode_audio,
};