# HG changeset patch # User reimar # Date 1380907342 0 # Node ID de83009f96bdb977465de1b435deebcb4093b0ce # Parent 4f8cf378dba41754bcc699525f8234eb8d687ad8 mpeg123: Support in-stream format changes. Also fixes bugzilla #2149. Patch by Thomas Orgis [thomas-forum orgis org]. diff -r 4f8cf378dba4 -r de83009f96bd libmpcodecs/ad_mpg123.c --- a/libmpcodecs/ad_mpg123.c Fri Oct 04 01:10:58 2013 +0000 +++ b/libmpcodecs/ad_mpg123.c Fri Oct 04 17:22:22 2013 +0000 @@ -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 @@ -59,6 +59,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; @@ -116,7 +117,9 @@ * 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): @@ -205,6 +208,59 @@ 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) { + 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. @@ -234,6 +290,9 @@ * 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) { @@ -260,6 +319,15 @@ #endif 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. */ @@ -270,7 +338,7 @@ * 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) @@ -284,6 +352,15 @@ 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 @@ -293,8 +370,6 @@ 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; @@ -313,39 +388,29 @@ /* 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) { - 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. @@ -367,50 +432,11 @@ con->mean_count = 0; #endif con->vbr = (finfo.vbr != MPG123_CBR); - 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; } } @@ -455,6 +481,7 @@ 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 */