Mercurial > mplayer.hg
changeset 31671:4541f1921482
Add support for parameter changes (e.g. channel count) during playback.
This makes decoding AAC files that switch between 2 and 6 channels
work reasonably well even with -channels 6 and ffaac decoder.
author | reimar |
---|---|
date | Thu, 15 Jul 2010 17:59:46 +0000 |
parents | 05a6d70df204 |
children | 61eac0d05f20 |
files | libmpcodecs/ad_ffmpeg.c libmpcodecs/dec_audio.c mplayer.c |
diffstat | 3 files changed, 75 insertions(+), 31 deletions(-) [+] |
line wrap: on
line diff
--- a/libmpcodecs/ad_ffmpeg.c Wed Jul 14 21:36:06 2010 +0000 +++ b/libmpcodecs/ad_ffmpeg.c Thu Jul 15 17:59:46 2010 +0000 @@ -52,6 +52,41 @@ return 1; } +static int setup_format(sh_audio_t *sh_audio, const AVCodecContext *lavc_context) +{ + int samplerate = lavc_context->sample_rate; + int sample_format = sh_audio->sample_format; + switch (lavc_context->sample_fmt) { + case SAMPLE_FMT_U8: sample_format = AF_FORMAT_U8; break; + case SAMPLE_FMT_S16: sample_format = AF_FORMAT_S16_NE; break; + case SAMPLE_FMT_S32: sample_format = AF_FORMAT_S32_NE; break; + case SAMPLE_FMT_FLT: sample_format = AF_FORMAT_FLOAT_NE; break; + default: + mp_msg(MSGT_DECAUDIO, MSGL_FATAL, "Unsupported sample format\n"); + } + if(sh_audio->wf){ + // If the decoder uses the wrong number of channels all is lost anyway. + // sh_audio->channels=sh_audio->wf->nChannels; + + if (lavc_context->codec_id == CODEC_ID_AAC && + samplerate == 2*sh_audio->wf->nSamplesPerSec) { + mp_msg(MSGT_DECAUDIO, MSGL_WARN, + "Ignoring broken container sample rate for ACC with SBR\n"); + } else if (sh_audio->wf->nSamplesPerSec) + samplerate=sh_audio->wf->nSamplesPerSec; + } + if (lavc_context->channels != sh_audio->channels || + samplerate != sh_audio->samplerate || + sample_format != sh_audio->sample_format) { + sh_audio->channels=lavc_context->channels; + sh_audio->samplerate=samplerate; + sh_audio->sample_format = sample_format; + sh_audio->samplesize=af_fmt2bits(sh_audio->sample_format)/ 8; + return 1; + } + return 0; +} + static int init(sh_audio_t *sh_audio) { int tries = 0; @@ -132,33 +167,19 @@ } while (x <= 0 && tries++ < 5); if(x>0) sh_audio->a_buffer_len=x; - sh_audio->channels=lavc_context->channels; - sh_audio->samplerate=lavc_context->sample_rate; sh_audio->i_bps=lavc_context->bit_rate/8; + if (sh_audio->wf && sh_audio->wf->nAvgBytesPerSec) + sh_audio->i_bps=sh_audio->wf->nAvgBytesPerSec; + switch (lavc_context->sample_fmt) { - case SAMPLE_FMT_U8: sh_audio->sample_format = AF_FORMAT_U8; break; - case SAMPLE_FMT_S16: sh_audio->sample_format = AF_FORMAT_S16_NE; break; - case SAMPLE_FMT_S32: sh_audio->sample_format = AF_FORMAT_S32_NE; break; - case SAMPLE_FMT_FLT: sh_audio->sample_format = AF_FORMAT_FLOAT_NE; break; + case SAMPLE_FMT_U8: + case SAMPLE_FMT_S16: + case SAMPLE_FMT_S32: + case SAMPLE_FMT_FLT: + break; default: - mp_msg(MSGT_DECAUDIO, MSGL_FATAL, "Unsupported sample format\n"); return 0; } - if(sh_audio->wf){ - // If the decoder uses the wrong number of channels all is lost anyway. - // sh_audio->channels=sh_audio->wf->nChannels; - - if (lavc_context->codec_id == CODEC_ID_AAC && - sh_audio->samplerate == 2*sh_audio->wf->nSamplesPerSec) { - mp_msg(MSGT_DECAUDIO, MSGL_WARN, - "Ignoring broken container sample rate for ACC with SBR\n"); - } else if (sh_audio->wf->nSamplesPerSec) - sh_audio->samplerate=sh_audio->wf->nSamplesPerSec; - - if (sh_audio->wf->nAvgBytesPerSec) - sh_audio->i_bps=sh_audio->wf->nAvgBytesPerSec; - } - sh_audio->samplesize=af_fmt2bits(sh_audio->sample_format)/ 8; return 1; } @@ -232,6 +253,9 @@ sh_audio->pts_bytes += len2; } mp_dbg(MSGT_DECAUDIO,MSGL_DBG2,"Decoded %d -> %d \n",y,len2); + + if (setup_format(sh_audio, sh_audio->context)) + break; } return len; }
--- a/libmpcodecs/dec_audio.c Wed Jul 14 21:36:06 2010 +0000 +++ b/libmpcodecs/dec_audio.c Thu Jul 15 17:59:46 2010 +0000 @@ -388,8 +388,11 @@ int minlen = len - sh->a_buffer_len; int maxlen = sh->a_buffer_size - sh->a_buffer_len; int ret = sh->ad_driver->decode_audio(sh, buf, minlen, maxlen); - if (ret <= 0) { - error = -1; + int format_change = sh->samplerate != filter_input.rate || + sh->channels != filter_input.nch || + sh->sample_format != filter_input.format; + if (ret <= 0 || format_change) { + error = format_change ? -2 : -1; len = sh->a_buffer_len; break; } @@ -446,6 +449,7 @@ max_decode_len -= max_decode_len % unitsize; while (sh_audio->a_out_buffer_len < minlen) { + int res; int declen = (minlen - sh_audio->a_out_buffer_len) / filter_multiplier + (unitsize << 5); // some extra for possible filter buffering if (huge_filter_buffer) @@ -465,8 +469,9 @@ /* if this iteration does not fill buffer, we must have lots * of buffering in filters */ huge_filter_buffer = 1; - if (filter_n_bytes(sh_audio, declen) < 0) - return -1; + res = filter_n_bytes(sh_audio, declen); + if (res < 0) + return res; } return 0; }
--- a/mplayer.c Wed Jul 14 21:36:06 2010 +0000 +++ b/mplayer.c Thu Jul 15 17:59:46 2010 +0000 @@ -1652,6 +1652,7 @@ void reinit_audio_chain(void) { if (!mpctx->sh_audio) return; + if (!(initialized_flags & INITIALIZED_ACODEC)) { current_module="init_audio_codec"; mp_msg(MSGT_CPLAYER,MSGL_INFO,"==========================================================================\n"); if(!init_best_audio_codec(mpctx->sh_audio,audio_codec_list,audio_fm_list)){ @@ -1659,8 +1660,10 @@ } initialized_flags|=INITIALIZED_ACODEC; mp_msg(MSGT_CPLAYER,MSGL_INFO,"==========================================================================\n"); - - + } + + + if (!(initialized_flags & INITIALIZED_AO)) { current_module="af_preinit"; ao_data.samplerate=force_srate; ao_data.channels=0; @@ -1694,6 +1697,8 @@ mpctx->audio_out->info->name, mpctx->audio_out->info->author); if(strlen(mpctx->audio_out->info->comment) > 0) mp_msg(MSGT_CPLAYER,MSGL_V,"AO: Comment: %s\n", mpctx->audio_out->info->comment); + } + // init audio filters: current_module="af_init"; if(!build_afilter_chain(mpctx->sh_audio, &ao_data)) { @@ -2120,6 +2125,7 @@ int playflags=0; int audio_eof=0; int bytes_to_write; + int format_change = 0; sh_audio_t * const sh_audio = mpctx->sh_audio; current_module="play_audio"; @@ -2143,6 +2149,7 @@ } while (bytes_to_write) { + int res; playsize = bytes_to_write; if (playsize > MAX_OUTBURST) playsize = MAX_OUTBURST; @@ -2151,7 +2158,11 @@ // Fill buffer if needed: current_module="decode_audio"; t = GetTimer(); - if (decode_audio(sh_audio, playsize) < 0) // EOF or error + if (!format_change) { + res = decode_audio(sh_audio, playsize); + format_change = res == -2; + } + if (!format_change && res < 0) // EOF or error if (mpctx->d_audio->eof) { audio_eof = 1; if (sh_audio->a_out_buffer_len == 0) @@ -2161,7 +2172,7 @@ tt = t*0.000001f; audio_time_usage+=tt; if (playsize > sh_audio->a_out_buffer_len) { playsize = sh_audio->a_out_buffer_len; - if (audio_eof) + if (audio_eof || format_change) playflags |= AOPLAY_FINAL_CHUNK; } if (!playsize) @@ -2182,13 +2193,17 @@ sh_audio->a_out_buffer_len); mpctx->delay += playback_speed*playsize/(double)ao_data.bps; } - else if (audio_eof && mpctx->audio_out->get_delay() < .04) { + else if ((format_change || audio_eof) && mpctx->audio_out->get_delay() < .04) { // Sanity check to avoid hanging in case current ao doesn't output // partial chunks and doesn't check for AOPLAY_FINAL_CHUNK mp_msg(MSGT_CPLAYER, MSGL_WARN, "Audio output truncated at end.\n"); sh_audio->a_out_buffer_len = 0; } } + if (format_change) { + uninit_player(INITIALIZED_AO); + reinit_audio_chain(); + } return 1; }