[MPlayer-cvslog] r31737 - in trunk: libmpcodecs/ad_ffmpeg.c libmpcodecs/dec_audio.c mplayer.c
reimar
subversion at mplayerhq.hu
Thu Jul 15 19:59:46 CEST 2010
Author: reimar
Date: Thu Jul 15 19:59:46 2010
New Revision: 31737
Log:
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.
Modified:
trunk/libmpcodecs/ad_ffmpeg.c
trunk/libmpcodecs/dec_audio.c
trunk/mplayer.c
Modified: trunk/libmpcodecs/ad_ffmpeg.c
==============================================================================
--- trunk/libmpcodecs/ad_ffmpeg.c Wed Jul 14 23:36:06 2010 (r31736)
+++ trunk/libmpcodecs/ad_ffmpeg.c Thu Jul 15 19:59:46 2010 (r31737)
@@ -52,6 +52,41 @@ static int preinit(sh_audio_t *sh)
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 @@ static int init(sh_audio_t *sh_audio)
} 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 @@ static int decode_audio(sh_audio_t *sh_a
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;
}
Modified: trunk/libmpcodecs/dec_audio.c
==============================================================================
--- trunk/libmpcodecs/dec_audio.c Wed Jul 14 23:36:06 2010 (r31736)
+++ trunk/libmpcodecs/dec_audio.c Thu Jul 15 19:59:46 2010 (r31737)
@@ -388,8 +388,11 @@ static int filter_n_bytes(sh_audio_t *sh
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 @@ int decode_audio(sh_audio_t *sh_audio, i
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 @@ int decode_audio(sh_audio_t *sh_audio, i
/* 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;
}
Modified: trunk/mplayer.c
==============================================================================
--- trunk/mplayer.c Wed Jul 14 23:36:06 2010 (r31736)
+++ trunk/mplayer.c Thu Jul 15 19:59:46 2010 (r31737)
@@ -1652,6 +1652,7 @@ static void update_osd_msg(void) {
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 @@ void reinit_audio_chain(void) {
}
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 @@ void reinit_audio_chain(void) {
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 @@ static int fill_audio_out_buffers(void)
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 @@ static int fill_audio_out_buffers(void)
}
while (bytes_to_write) {
+ int res;
playsize = bytes_to_write;
if (playsize > MAX_OUTBURST)
playsize = MAX_OUTBURST;
@@ -2151,7 +2158,11 @@ static int fill_audio_out_buffers(void)
// 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 @@ static int fill_audio_out_buffers(void)
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 @@ static int fill_audio_out_buffers(void)
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;
}
More information about the MPlayer-cvslog
mailing list