mirror of
https://github.com/mpv-player/mpv
synced 2025-02-17 04:58:06 +00:00
audio: remove internal libmpg123 wrapper
We've been prefering the libavcodec mp3 decoder for half a year now. There is likely no benefit at all for using the libmpg123 one. It's just a maintenance burden, and tricks users into thinking it's a required dependency.
This commit is contained in:
parent
170a2e0568
commit
d5318e5e09
@ -1,304 +0,0 @@
|
||||
/*
|
||||
* 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 "common/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;
|
||||
int sample_size;
|
||||
/* 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;
|
||||
struct mp_audio frame;
|
||||
};
|
||||
|
||||
static void uninit(struct dec_audio *da)
|
||||
{
|
||||
struct ad_mpg123_context *con = da->priv;
|
||||
|
||||
mpg123_close(con->handle);
|
||||
mpg123_delete(con->handle);
|
||||
mpg123_exit();
|
||||
}
|
||||
|
||||
/* This initializes libmpg123 and prepares the handle, including funky
|
||||
* parameters. */
|
||||
static int init(struct dec_audio *da, const char *decoder)
|
||||
{
|
||||
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;
|
||||
|
||||
da->priv = talloc_zero(NULL, struct ad_mpg123_context);
|
||||
con = da->priv;
|
||||
/* 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.);
|
||||
|
||||
err = mpg123_open_feed(con->handle);
|
||||
if (err != MPG123_OK)
|
||||
goto bad_end;
|
||||
|
||||
return 1;
|
||||
|
||||
bad_end:
|
||||
if (!con->handle) {
|
||||
MP_ERR(da, "mpg123 preinit error: %s\n", mpg123_plain_strerror(err));
|
||||
} else {
|
||||
MP_ERR(da, "mpg123 preinit error: %s\n", mpg123_strerror(con->handle));
|
||||
}
|
||||
|
||||
uninit(da);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mpg123_format_to_af(int mpg123_encoding)
|
||||
{
|
||||
/* 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 (mpg123_encoding) {
|
||||
case MPG123_ENC_SIGNED_8: return AF_FORMAT_S8;
|
||||
case MPG123_ENC_SIGNED_16: return AF_FORMAT_S16;
|
||||
case MPG123_ENC_SIGNED_32: return AF_FORMAT_S32;
|
||||
case MPG123_ENC_FLOAT_32: return AF_FORMAT_FLOAT;
|
||||
}
|
||||
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 /
|
||||
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(struct dec_audio *da)
|
||||
{
|
||||
struct ad_mpg123_context *con = da->priv;
|
||||
struct mpg123_frameinfo finfo;
|
||||
if (mpg123_info(con->handle, &finfo) != MPG123_OK)
|
||||
return;
|
||||
|
||||
/* finfo.bitrate is expressed in kilobits */
|
||||
const int bitrate = finfo.bitrate * 1000;
|
||||
|
||||
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 +
|
||||
bitrate) / con->mean_count;
|
||||
da->bitrate = (int) (con->mean_rate + 0.5);
|
||||
|
||||
con->delay = 10;
|
||||
}
|
||||
} else {
|
||||
da->bitrate = bitrate ? bitrate : compute_bitrate(&finfo);
|
||||
con->delay = 1;
|
||||
con->mean_rate = 0.;
|
||||
con->mean_count = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* libmpg123 has a new format ready; query and store, return return value
|
||||
of mpg123_getformat() */
|
||||
static int set_format(struct dec_audio *da)
|
||||
{
|
||||
struct ad_mpg123_context *con = da->priv;
|
||||
int ret;
|
||||
long rate;
|
||||
int channels;
|
||||
int encoding;
|
||||
ret = mpg123_getformat(con->handle, &rate, &channels, &encoding);
|
||||
if (ret == MPG123_OK) {
|
||||
mp_audio_set_num_channels(&con->frame, channels);
|
||||
con->frame.rate = rate;
|
||||
int af = mpg123_format_to_af(encoding);
|
||||
if (!af) {
|
||||
/* This means we got a funny custom build of libmpg123 that only supports an unknown format. */
|
||||
MP_ERR(da, "Bad encoding from mpg123: %i.\n", encoding);
|
||||
return MPG123_ERR;
|
||||
}
|
||||
mp_audio_set_format(&con->frame, af);
|
||||
con->sample_size = channels * af_fmt2bps(af);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int decode_packet(struct dec_audio *da, struct mp_audio **out)
|
||||
{
|
||||
struct ad_mpg123_context *con = da->priv;
|
||||
int ret;
|
||||
|
||||
struct demux_packet *pkt;
|
||||
if (demux_read_packet_async(da->header, &pkt) == 0)
|
||||
return AD_WAIT;
|
||||
if (!pkt)
|
||||
return AD_EOF;
|
||||
|
||||
/* Next bytes from that presentation time. */
|
||||
if (pkt->pts != MP_NOPTS_VALUE) {
|
||||
da->pts = pkt->pts;
|
||||
da->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_OK)
|
||||
goto mpg123_fail;
|
||||
|
||||
unsigned char *audio = NULL;
|
||||
size_t bytes = 0;
|
||||
ret = mpg123_decode_frame(con->handle, NULL, &audio, &bytes);
|
||||
|
||||
if (ret == MPG123_NEED_MORE)
|
||||
return 0;
|
||||
|
||||
if (ret != MPG123_OK && ret != MPG123_DONE && ret != MPG123_NEW_FORMAT)
|
||||
goto mpg123_fail;
|
||||
|
||||
ret = set_format(da);
|
||||
if (ret != MPG123_OK)
|
||||
goto mpg123_fail;
|
||||
|
||||
if (con->sample_size < 1) {
|
||||
MP_ERR(da, "no sample size\n");
|
||||
return AD_ERR;
|
||||
}
|
||||
|
||||
int got_samples = bytes / con->sample_size;
|
||||
*out = mp_audio_pool_get(da->pool, &con->frame, got_samples);
|
||||
if (!*out)
|
||||
return AD_ERR;
|
||||
|
||||
memcpy((*out)->planes[0], audio, bytes);
|
||||
|
||||
update_info(da);
|
||||
return 0;
|
||||
|
||||
mpg123_fail:
|
||||
MP_ERR(da, "mpg123 decoding error: %s\n", mpg123_strerror(con->handle));
|
||||
return AD_ERR;
|
||||
}
|
||||
|
||||
static int control(struct dec_audio *da, int cmd, void *arg)
|
||||
{
|
||||
struct ad_mpg123_context *con = da->priv;
|
||||
|
||||
switch (cmd) {
|
||||
case ADCTRL_RESET:
|
||||
mpg123_close(con->handle);
|
||||
|
||||
if (mpg123_open_feed(con->handle) != MPG123_OK) {
|
||||
MP_ERR(da, "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,
|
||||
.init = init,
|
||||
.uninit = uninit,
|
||||
.control = control,
|
||||
.decode_packet = decode_packet,
|
||||
};
|
@ -25,7 +25,6 @@
|
||||
|
||||
#include "demux/codec_tags.h"
|
||||
|
||||
#include "config.h"
|
||||
#include "common/codecs.h"
|
||||
#include "common/msg.h"
|
||||
#include "misc/bstr.h"
|
||||
@ -43,15 +42,11 @@
|
||||
|
||||
#include "audio/filter/af.h"
|
||||
|
||||
extern const struct ad_functions ad_mpg123;
|
||||
extern const struct ad_functions ad_lavc;
|
||||
extern const struct ad_functions ad_spdif;
|
||||
|
||||
static const struct ad_functions * const ad_drivers[] = {
|
||||
&ad_lavc,
|
||||
#if HAVE_MPG123
|
||||
&ad_mpg123,
|
||||
#endif
|
||||
&ad_spdif,
|
||||
NULL
|
||||
};
|
||||
|
@ -187,7 +187,6 @@ options_state_machine() {
|
||||
opt_yes_no _ffmpeg "skip FFmpeg/Libav autodetection"
|
||||
opt_yes_no _ladspa "LADSPA plugin support"
|
||||
opt_yes_no _libbs2b "libbs2b audio filter support"
|
||||
opt_yes_no _mpg123 " libmpg123 MP3 decoding support"
|
||||
opt_yes_no _libavresample "libavresample (preferred over libswresample)"
|
||||
opt_yes_no _libswresample "libswresample"
|
||||
opt_yes_no _caca "CACA video output"
|
||||
@ -737,8 +736,6 @@ check_pkg_config "ENCA" $_enca ENCA 'enca'
|
||||
check_pkg_config "zlib" auto ZLIB 'zlib'
|
||||
test $(defretval) = no && die "Unable to find development files for zlib."
|
||||
|
||||
check_pkg_config "mpg123 support" $_mpg123 MPG123 'libmpg123 >= 1.14.0'
|
||||
|
||||
test "$_dl" = no && _ladspa=no
|
||||
check_statement_libs "LADSPA plugin support" $_ladspa LADSPA ladspa.h 'LADSPA_Descriptor ld = {0}'
|
||||
|
||||
|
@ -45,8 +45,6 @@ SOURCES-$(LIBBS2B) += audio/filter/af_bs2b.c
|
||||
|
||||
SOURCES-$(LIBSMBCLIENT) += stream/stream_smb.c
|
||||
|
||||
SOURCES-$(MPG123) += audio/decode/ad_mpg123.c
|
||||
|
||||
SOURCES-$(PVR) += stream/stream_pvr.c
|
||||
|
||||
SOURCES-$(TV) += stream/stream_tv.c stream/tv.c \
|
||||
|
4
wscript
4
wscript
@ -338,10 +338,6 @@ iconv support use --disable-iconv.",
|
||||
'name': '--enca',
|
||||
'desc': 'ENCA support',
|
||||
'func': check_statement('enca.h', 'enca_get_languages(NULL)', lib='enca'),
|
||||
}, {
|
||||
'name': '--mpg123',
|
||||
'desc': 'mpg123 support',
|
||||
'func': check_pkg_config('libmpg123', '>= 1.14.0'),
|
||||
}, {
|
||||
'name': '--ladspa',
|
||||
'desc': 'LADSPA plugin support',
|
||||
|
@ -90,7 +90,6 @@ def build(ctx):
|
||||
( "audio/format.c" ),
|
||||
( "audio/mixer.c" ),
|
||||
( "audio/decode/ad_lavc.c" ),
|
||||
( "audio/decode/ad_mpg123.c", "mpg123" ),
|
||||
( "audio/decode/ad_spdif.c" ),
|
||||
( "audio/decode/dec_audio.c" ),
|
||||
( "audio/filter/af.c" ),
|
||||
|
Loading…
Reference in New Issue
Block a user