Mercurial > mplayer.hg
changeset 34722:2d928e78d248
Update ad_mpg123 in preparation to replace mp3lib.
patch by Thomas Orgis, thomas-forum orgis org
author | diego |
---|---|
date | Tue, 13 Mar 2012 11:44:05 +0000 |
parents | 9944765ea06b |
children | b9a160ba5817 |
files | configure libmpcodecs/ad_mpg123.c |
diffstat | 2 files changed, 96 insertions(+), 168 deletions(-) [+] |
line wrap: on
line diff
--- a/configure Sun Mar 11 16:27:32 2012 +0000 +++ b/configure Tue Mar 13 11:44:05 2012 +0000 @@ -6298,12 +6298,14 @@ fi echores "$_mp3lib" -# Any version of libmpg123 shall be fine. +# Any version of libmpg123 that knows MPG123_RESYNC_LIMIT shall be fine. +# That is, 1.2.0 onwards. Recommened is 1.14 onwards, though. echocheck "mpg123 support" def_mpg123='#undef CONFIG_MPG123' if test "$_mpg123" = auto; then _mpg123=no - statement_check mpg123.h 'mpg123_init()' -lmpg123 && _mpg123=yes && extra_ldflags="$extra_ldflags -lmpg123" + statement_check mpg123.h 'mpg123_param(NULL, MPG123_RESYNC_LIMIT, -1, 0.)' -lmpg123 && + _mpg123=yes && extra_ldflags="$extra_ldflags -lmpg123" fi if test "$_mpg123" = yes ; then def_mpg123='#define CONFIG_MPG123 1'
--- a/libmpcodecs/ad_mpg123.c Sun Mar 11 16:27:32 2012 +0000 +++ b/libmpcodecs/ad_mpg123.c Tue Mar 13 11:44:05 2012 +0000 @@ -1,7 +1,7 @@ /* * MPEG 1.0/2.0/2.5 audio layer I, II, III decoding with libmpg123 * - * Copyright (C) 2010 Thomas Orgis <thomas@orgis.org> + * Copyright (C) 2010-2012 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 @@ -39,36 +39,20 @@ #include "libvo/fastmemcpy.h" -/* We avoid any usage of mpg123 API that is sensitive to the large file - * support setting. This ensures compatibility with a wide range of libmpg123 - * installs. This code is intended to work with version 1.0.0 of libmpg123. - * - * Though the chosen API subset is not affected by the choice of large file - * support, the mpg123 header (old versions of which) might include a check - * for matching _FILE_OFFSET_BITS. Since MPlayer does always define this one - * for large file support, we are safe for any default mpg123 install that - * either doesn't have such checks or defaults to the large value of - * _FILE_OFFSET_BITS . - * So, in short: There's no worry unless you have a non-default libmpg123 - * with intentionally disabled large file support. */ -/* You might need to #undef _FILE_OFFSET_BITS here on a 64 bit system - with released mpg123 1.12 when using callback API. SVN snapshots - should work fine. */ +/* Reducing the ifdeffery to two main variants: + * 1. most compatible to any libmpg123 version + * 2. fastest variant with recent libmpg123 (>=1.14) + * Running variant 2 on older libmpg123 versions may work in + * principle, but is not supported. + * So, please leave the check for MPG123_API_VERSION there, m-kay? + */ #include <mpg123.h> -/* Selection of mpg123 usage patterns: - * AD_MPG123_CALLBACK: Use callback API instead of feeding of memory buffers. - * That needs mpg123>=1.12, on x86-64 SVN snapshot because of - * _FILE_OFFSET_BITS being defined (see above). - * AD_MPG123_PACKET: Use packet-based input (including pts handling). - * AD_MPG123_SEEKBUFFER: Use internal mpg123 buffer to enhance stream parsing. - * Makes sense with callback API only. - * Any of those might affect I/O performance, might be significant compared - * to the excessively optimized decoding. - */ -/* #define AD_MPG123_CALLBACK */ -#define AD_MPG123_PACKET -/* #define AD_MPG123_SEEKBUFFER */ +/* Enable faster mode of operation with newer libmpg123, avoiding + * unnecessary memcpy() calls. */ +#if (defined MPG123_API_VERSION) && (MPG123_API_VERSION >= 33) +#define AD_MPG123_FRAMEWISE +#endif /* Switch for updating bitrate info of VBR files. Not essential. */ #define AD_MPG123_MEAN_BITRATE @@ -84,77 +68,8 @@ #endif /* If the stream is actually VBR. */ char vbr; -#if (defined AD_MPG123_CALLBACK) && (defined AD_MPG123_PACKET) - unsigned char *packet; - int packleft; -#endif }; -static void context_reset(struct ad_mpg123_context *con) -{ -#ifdef AD_MPG123_MEAN_BITRATE - con->mean_rate = 0.; - con->mean_count = 0; - con->delay = 1; -#endif -#if (defined AD_MPG123_CALLBACK) && (defined AD_MPG123_PACKET) - con->packet = NULL; - con->packleft = 0; -#endif -} - - -#ifdef AD_MPG123_CALLBACK -/* Mpg123 calls that for retrieving data. - * This wrapper is at least needed for the call frame (ssize_t vs. int). */ -static ssize_t read_callback(void *ash, void *buf, size_t count) -{ - sh_audio_t *sh = ash; -#ifdef AD_MPG123_PACKET - struct ad_mpg123_context *con = sh->context; - unsigned char *target = buf; - int need = count; - ssize_t got = 0; - while (need > 0) { - if (con->packleft > 0) { - int get = need > con->packleft ? con->packleft : need; - /* Any difference to normal memcpy? */ - fast_memcpy(target, con->packet, get); - /* OK, that does look redundant. */ - con->packet += get; - con->packleft -= get; - target += get; - need -= get; - got += get; - } else { - double pts; - /* Feed more input data. */ - con->packleft = ds_get_packet_pts(sh->ds, &con->packet, &pts); - if (con->packleft <= 0) - break; /* Apparently that's it. EOF. */ - - /* Next bytes from that presentation time. */ - if (pts != MP_NOPTS_VALUE) { - sh->pts = pts; - sh->pts_bytes = 0; - } - } - } - return got; -#else - /* It returns int... with the meaning of byte count. */ - return (ssize_t) demux_read_data(sh->ds, buf, count); -#endif -} - -/* Arbitrary input seeking is not supported with this MPlayer API(?). - That also means that we won't read any ID3v1 tags. */ -static off_t seek_callback(void *sh, off_t pos, int whence) -{ - return -1; -} -#endif - /* This initializes libmpg123 and prepares the handle, including funky * parameters. */ static int preinit(sh_audio_t *sh) @@ -170,8 +85,6 @@ sh->context = malloc(sizeof(struct ad_mpg123_context)); con = sh->context; - context_reset(con); - /* Auto-choice of optimized decoder (first argument NULL). */ con->handle = mpg123_new(NULL, &err); if (!con->handle) @@ -185,17 +98,6 @@ if (mpg123_param(con->handle, MPG123_ADD_FLAGS, flag, 0.0) != MPG123_OK) goto bad_end; #endif -#ifdef AD_MPG123_CALLBACK - /* The I/O is handled via callbacks to MPlayer stream functions, - * actually only the reading, as general seeking does not seem to be available */ - if (mpg123_replace_reader_handle(con->handle, read_callback, - seek_callback, NULL) != MPG123_OK) { - mp_msg(MSGT_DECAUDIO, MSGL_ERR, "mpg123 error: %s\n", - mpg123_strerror(con->handle)); - mpg123_exit(); - return 0; - } -#endif /* Basic settings. * Don't spill messages, enable better resync with non-seekable streams. @@ -203,10 +105,6 @@ * old libmpg123. Generally, it is not fatal if the flags are not * honored */ mpg123_param(con->handle, MPG123_ADD_FLAGS, MPG123_QUIET, 0.0); - /* Old headers don't know MPG123_SEEKBUFFER yet, so use the plain 0x100. */ -#ifdef AD_MPG123_SEEKBUFFER - mpg123_param(con->handle, MPG123_ADD_FLAGS, 0x100, 0.0); -#endif /* 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); @@ -217,9 +115,25 @@ * 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. */ + /* 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) */ +#ifdef AD_MPG123_FRAMEWISE + /* Prevent funky automatic resampling. + * This way, we can be sure that one frame will never produce + * more than 1152 stereo samples. */ + mpg123_param(con->handle, MPG123_REMOVE_FLAGS, MPG123_AUTO_RESAMPLE, 0.); +#else + /* Older mpg123 is vulnerable to concatenated streams when gapless cutting + * is enabled (will only play the jingle of a badly constructed radio + * stream). The versions using framewise decoding are fine with that. */ + mpg123_param(con->handle, MPG123_REMOVE_FLAGS, MPG123_GAPLESS, 0.); +#endif + return 1; bad_end: @@ -291,7 +205,19 @@ smodes[i->mode]); } -#ifndef AD_MPG123_CALLBACK +/* return MPG123_OK if decoder is ready to produce output + * the other usual return code would be MPG123_NEED_MORE. */ +static int have_initial_frame(mpg123_handle *mh) +{ + long rate; + int chan, enc; + /* Abusing the format query function. + * It returns MPG123_OK if an intial frame has been parsed. + * It returns MPG123_NEED_MORE if input data is needed. + * Not handing NULL pointers for compatibility with old libmpg123. */ + return mpg123_getformat(mh, &rate, &chan, &enc); +} + /* This tries to extract a requested amount of decoded data. * Even when you request 0 bytes, it will feed enough input so that * the decoder _could_ have delivered something. @@ -318,19 +244,13 @@ struct ad_mpg123_context *con = sh->context; /* There will be one MPG123_NEW_FORMAT message on first open. - * This will be implicitly handled in reopen_stream(). */ + * This will be handled in init(). */ do { size_t got_now = 0; - ret = mpg123_decode(con->handle, NULL, 0, buf + got, count - got, - &got_now); - got += got_now; -#ifdef AD_MPG123_PACKET - sh->pts_bytes += got_now; -#endif + /* Feed the decoder. This will only fire from the second round on. */ if (ret == MPG123_NEED_MORE) { int incount; -#ifdef AD_MPG123_PACKET double pts; unsigned char *inbuf; /* Feed more input data. */ @@ -343,26 +263,45 @@ sh->pts = pts; sh->pts_bytes = 0; } + +#ifdef AD_MPG123_FRAMEWISE + /* Have to use mpg123_feed() to avoid decoding here. */ + ret = mpg123_feed(con->handle, inbuf, incount); #else - const int inbufsize = 4096; - unsigned char inbuf[inbufsize]; - /* Feed more input data. */ - incount = demux_read_data(((sh_audio_t *) sh)->ds, - inbuf, inbufsize); - if (incount == 0) - break; /* Apparently that's it. EOF. */ -#endif - /* Do not use mpg123_feed(), added in later libmpg123 versions. */ ret = mpg123_decode(con->handle, inbuf, incount, NULL, 0, NULL); - /* Return value is checked in the loop condition. - * It could be MPG12_OK now, it could need more. */ +#endif + if (ret == MPG123_ERR) + break; } - /* Older mpg123 versions might indicate MPG123_DONE, so be prepared. */ + /* Theoretically, mpg123 could return MPG123_DONE, so be prepared. + * Should not happen in our usage, but it is a valid return code. */ else if (ret == MPG123_ERR || ret == MPG123_DONE) break; + /* Try to decode a bit. This is the return value that counts + * for the loop condition. */ +#ifdef AD_MPG123_FRAMEWISE + if (!buf) { /* fake call just for feeding to get format */ + ret = have_initial_frame(con->handle); + } else { /* This is the decoding. One frame at a time. */ + ret = mpg123_replace_buffer(con->handle, buf, count); + if (ret == MPG123_OK) + ret = mpg123_decode_frame(con->handle, NULL, NULL, &got_now); + } +#else + ret = mpg123_decode(con->handle, NULL, 0, buf + got, count - got, + &got_now); +#endif + + got += got_now; + sh->pts_bytes += got_now; + +#ifdef AD_MPG123_FRAMEWISE + } while (ret == MPG123_NEED_MORE || (got == 0 && count != 0)); +#else } while (ret == MPG123_NEED_MORE || got < count); +#endif if (ret == MPG123_ERR) { mp_msg(MSGT_DECAUDIO, MSGL_ERR, "mpg123 decoding failed: %s\n", @@ -373,29 +312,22 @@ return got; } -#endif /* Close, reopen stream. Feed data until we know the format of the stream. * 1 on success, 0 on error */ static int reopen_stream(sh_audio_t *sh) { - long rate; - int chan, enc; struct ad_mpg123_context *con = (struct ad_mpg123_context*) sh->context; mpg123_close(con->handle); - context_reset(con); + /* No resetting of the context: + * We do not want to loose the mean bitrate data. */ -#ifdef AD_MPG123_CALLBACK - if (MPG123_OK == mpg123_open_handle(con->handle, sh) && -#else - if (/* Open and make sure we have fed enough data to get stream properties. */ - MPG123_OK == mpg123_open_feed(con->handle) && + /* Open and make sure we have fed enough data to get stream properties. */ + if (MPG123_OK == mpg123_open_feed(con->handle) && /* Feed data until mpg123 is ready (has found stream beginning). */ !decode_a_bit(sh, NULL, 0) && -#endif - /* Not handing NULL pointers for compatibility with old libmpg123. */ - MPG123_OK == mpg123_getformat(con->handle, &rate, &chan, &enc)) { + MPG123_OK == have_initial_frame(con->handle)) { return 1; } else { mp_msg(MSGT_DECAUDIO, MSGL_ERR, @@ -443,7 +375,11 @@ * For VBR, the first frame will be a bad estimate. */ sh->i_bps = (finfo.bitrate ? finfo.bitrate : compute_bitrate(&finfo)) * 1000 / 8; - context_reset(con); +#ifdef AD_MPG123_MEAN_BITRATE + con->delay = 1; + con->mean_rate = 0.; + con->mean_count = 0; +#endif con->vbr = (finfo.vbr != MPG123_CBR); sh->channels = channels; sh->samplerate = rate; @@ -477,6 +413,12 @@ mpg123_close(con->handle); return 0; } +#ifdef AD_MPG123_FRAMEWISE + /* Going to decode directly to MPlayer's memory. It is important + * to have MPG123_AUTO_RESAMPLE disabled for the buffer size + * being an all-time limit. */ + sh->audio_out_minsize = 1152 * 2 * sh->samplesize; +#endif return 1; } else { @@ -526,29 +468,13 @@ { int bytes; -#ifdef AD_MPG123_CALLBACK - struct ad_mpg123_context *con = sh->context; - size_t got_bytes = 0; - if (MPG123_ERR == mpg123_read(con->handle, buf, minlen, &got_bytes)) { - mp_msg(MSGT_DECAUDIO, MSGL_ERR, "Decoding error in mpg123: %s\n", - mpg123_strerror(con->handle)); - return -1; - } -#ifdef AD_MPG123_PACKET - sh->pts_bytes += got_bytes; -#endif - bytes = got_bytes; -#else - bytes = decode_a_bit(sh, buf, minlen); -#endif - + bytes = decode_a_bit(sh, buf, maxlen); if (bytes == 0) return -1; /* EOF */ #ifdef AD_MPG123_MEAN_BITRATE update_info(sh); #endif - return bytes; }