From 55883943c5da2cc224753daeeca0124ebbbd30d9 Mon Sep 17 00:00:00 2001 From: Thomas Orgis Date: Fri, 4 Oct 2013 17:22:22 +0000 Subject: ad_mpeg123: support in-stream format changes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@36461 b3059339-0415-0410-9bf9-f77b7e298cf2 Fixes playback of http://mpg123.org/test/44and22.mp3 Cherry-picked from MPlayer SVN rev. #36461, a patch by Thomas Orgis, committed by by Reimar Döffinger. --- audio/decode/ad_mpg123.c | 149 ++++++++++++++++++++++++++++------------------- 1 file changed, 88 insertions(+), 61 deletions(-) (limited to 'audio') diff --git a/audio/decode/ad_mpg123.c b/audio/decode/ad_mpg123.c index 9594cb61ef..df9e82306d 100644 --- a/audio/decode/ad_mpg123.c +++ b/audio/decode/ad_mpg123.c @@ -1,7 +1,7 @@ /* * MPEG 1.0/2.0/2.5 audio layer I, II, III decoding with libmpg123 * - * Copyright (C) 2010-2012 Thomas Orgis + * Copyright (C) 2010-2013 Thomas Orgis * * MPlayer is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -47,6 +47,7 @@ struct ad_mpg123_context { mpg123_handle *handle; + char new_format; #ifdef AD_MPG123_MEAN_BITRATE /* Running mean for bit rate, stream length estimation. */ float mean_rate; @@ -95,7 +96,9 @@ static int preinit(sh_audio_t *sh) * 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. */ + * 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): @@ -184,6 +187,59 @@ static void print_header_compact(struct mpg123_frameinfo *i) smodes[i->mode]); } +/* 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) +{ + 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; + sh->samplesize = 1; + break; + case MPG123_ENC_SIGNED_16: + sh->sample_format = AF_FORMAT_S16_NE; + sh->samplesize = 2; + break; + /* To stay compatible with the oldest libmpg123 headers, do not rely + * on float and 32 bit encoding symbols being defined. + * Those formats came later */ + case 0x1180: /* MPG123_ENC_SIGNED_32 */ + sh->sample_format = AF_FORMAT_S32_NE; + sh->samplesize = 4; + break; + case 0x200: /* MPG123_ENC_FLOAT_32 */ + sh->sample_format = AF_FORMAT_FLOAT_NE; + sh->samplesize = 4; + 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; + } +#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 + con->new_format = 0; + } + return ret; +} + /* 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. @@ -213,6 +269,9 @@ static int decode_a_bit(sh_audio_t *sh, unsigned char *buf, int count) * This will be handled in init(). */ do { size_t got_now = 0; + /* Fetch new format now, after old data has been used. */ + if(con->new_format) + ret = set_format(sh, con); /* Feed the decoder. This will only fire from the second round on. */ if (ret == MPG123_NEED_MORE) { @@ -237,6 +296,15 @@ static int decode_a_bit(sh_audio_t *sh, unsigned char *buf, int count) talloc_free(pkt); if (ret == MPG123_ERR) break; + + /* Indication of format change is possible here (from mpg123_decode()). */ + if(ret == MPG123_NEW_FORMAT) { + con->new_format = 1; + if(got) + break; /* Do not switch format during a chunk. */ + + ret = set_format(sh, con); + } } /* Theoretically, mpg123 could return MPG123_DONE, so be prepared. * Should not happen in our usage, but it is a valid return code. */ @@ -247,7 +315,7 @@ static int decode_a_bit(sh_audio_t *sh, unsigned char *buf, int count) * for the loop condition. */ #ifdef AD_MPG123_FRAMEWISE if (!buf) { /* fake call just for feeding to get format */ - ret = mpg123_getformat(con->handle, NULL, NULL, NULL); + ret = set_format(sh, con); } else { /* This is the decoding. One frame at a time. */ ret = mpg123_replace_buffer(con->handle, buf, count); if (ret == MPG123_OK) @@ -261,6 +329,15 @@ static int decode_a_bit(sh_audio_t *sh, unsigned char *buf, int count) got += got_now; sh->pts_bytes += got_now; + /* Indication of format change should happen here. */ + if(ret == MPG123_NEW_FORMAT) { + con->new_format = 1; + if(got) + break; /* Do not switch format during a chunk. */ + + ret = set_format(sh, con); + } + #ifdef AD_MPG123_FRAMEWISE } while (ret == MPG123_NEED_MORE || (got == 0 && count != 0)); #else @@ -270,8 +347,6 @@ static int decode_a_bit(sh_audio_t *sh, unsigned char *buf, int count) if (ret == MPG123_ERR) { mp_msg(MSGT_DECAUDIO, MSGL_ERR, "mpg123 decoding failed: %s\n", mpg123_strerror(con->handle)); - mpg123_close(con->handle); - return -1; } return got; @@ -290,39 +365,29 @@ static int reopen_stream(sh_audio_t *sh) /* 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)) { + !decode_a_bit(sh, NULL, 0) && + set_format(sh, con) == MPG123_OK) { /* format setting again just for return value */ return 1; } else { mp_msg(MSGT_DECAUDIO, MSGL_ERR, "mpg123 failed to reopen stream: %s\n", mpg123_strerror(con->handle)); - mpg123_close(con->handle); return 0; } } /* Now we really start accessing some data and determining file format. - * Paranoia note: The mpg123_close() on errors is not really necessary, - * But it ensures that we don't accidentally continue decoding with a - * bad state (possibly interpreting the format badly or whatnot). */ + * 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) { - long rate = 0; - int channels = 0; - int encoding = 0; mpg123_id3v2 *v2; struct mpg123_frameinfo finfo; struct ad_mpg123_context *con = sh->context; - /* We're open about any output format that libmpg123 will suggest. - * Note that a standard build will always default to 16 bit signed and - * the native sample rate of the file. */ - if (MPG123_OK == mpg123_format_all(con->handle) && - reopen_stream(sh) && - MPG123_OK == mpg123_getformat(con->handle, &rate, &channels, &encoding) && - /* Forbid the format to change later on. */ - MPG123_OK == mpg123_format_none(con->handle) && - MPG123_OK == mpg123_format(con->handle, rate, channels, encoding) && + con->new_format = 0; + if (reopen_stream(sh) && /* Get MPEG header info. */ MPG123_OK == mpg123_info(con->handle, &finfo) && /* Since we queried format, mpg123 should have read past ID3v2 tags. @@ -344,50 +409,11 @@ static int init(sh_audio_t *sh, const char *decoder) con->mean_count = 0; #endif con->vbr = (finfo.vbr != MPG123_CBR); - 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; - sh->samplesize = 1; - break; - case MPG123_ENC_SIGNED_16: - sh->sample_format = AF_FORMAT_S16_NE; - sh->samplesize = 2; - break; - /* To stay compatible with the oldest libmpg123 headers, do not rely - * on float and 32 bit encoding symbols being defined. - * Those formats came later */ - case 0x1180: /* MPG123_ENC_SIGNED_32 */ - sh->sample_format = AF_FORMAT_S32_NE; - sh->samplesize = 4; - break; - case 0x200: /* MPG123_ENC_FLOAT_32 */ - sh->sample_format = AF_FORMAT_FLOAT_NE; - sh->samplesize = 4; - break; - default: - mp_msg(MSGT_DECAUDIO, MSGL_ERR, - "Bad encoding from mpg123: %i.\n", encoding); - 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 { mp_msg(MSGT_DECAUDIO, MSGL_ERR, "mpg123 init error: %s\n", mpg123_strerror(con->handle)); - mpg123_close(con->handle); return 0; } } @@ -432,6 +458,7 @@ static int decode_audio(sh_audio_t *sh, unsigned char *buf, int minlen, int bytes; bytes = decode_a_bit(sh, buf, maxlen); + /* This EOF is ignored, apparently, until input data is exhausted. */ if (bytes == 0) return -1; /* EOF */ -- cgit v1.2.3