|
|
|
@@ -2424,105 +2424,101 @@ static int audio_decode_frame(VideoState *is) |
|
|
|
int wanted_nb_samples; |
|
|
|
Frame *af; |
|
|
|
|
|
|
|
{ |
|
|
|
if (is->paused) |
|
|
|
return -1; |
|
|
|
if (is->paused) |
|
|
|
return -1; |
|
|
|
|
|
|
|
do { |
|
|
|
if (!(af = frame_queue_peek_readable(&is->sampq))) |
|
|
|
do { |
|
|
|
if (!(af = frame_queue_peek_readable(&is->sampq))) |
|
|
|
return -1; |
|
|
|
frame_queue_next(&is->sampq); |
|
|
|
} while (af->serial != is->audioq.serial); |
|
|
|
|
|
|
|
data_size = av_samples_get_buffer_size(NULL, av_frame_get_channels(af->frame), |
|
|
|
af->frame->nb_samples, |
|
|
|
af->frame->format, 1); |
|
|
|
|
|
|
|
dec_channel_layout = |
|
|
|
(af->frame->channel_layout && av_frame_get_channels(af->frame) == av_get_channel_layout_nb_channels(af->frame->channel_layout)) ? |
|
|
|
af->frame->channel_layout : av_get_default_channel_layout(av_frame_get_channels(af->frame)); |
|
|
|
wanted_nb_samples = synchronize_audio(is, af->frame->nb_samples); |
|
|
|
|
|
|
|
if (af->frame->format != is->audio_src.fmt || |
|
|
|
dec_channel_layout != is->audio_src.channel_layout || |
|
|
|
af->frame->sample_rate != is->audio_src.freq || |
|
|
|
(wanted_nb_samples != af->frame->nb_samples && !is->swr_ctx)) { |
|
|
|
swr_free(&is->swr_ctx); |
|
|
|
is->swr_ctx = swr_alloc_set_opts(NULL, |
|
|
|
is->audio_tgt.channel_layout, is->audio_tgt.fmt, is->audio_tgt.freq, |
|
|
|
dec_channel_layout, af->frame->format, af->frame->sample_rate, |
|
|
|
0, NULL); |
|
|
|
if (!is->swr_ctx || swr_init(is->swr_ctx) < 0) { |
|
|
|
av_log(NULL, AV_LOG_ERROR, |
|
|
|
"Cannot create sample rate converter for conversion of %d Hz %s %d channels to %d Hz %s %d channels!\n", |
|
|
|
af->frame->sample_rate, av_get_sample_fmt_name(af->frame->format), av_frame_get_channels(af->frame), |
|
|
|
is->audio_tgt.freq, av_get_sample_fmt_name(is->audio_tgt.fmt), is->audio_tgt.channels); |
|
|
|
swr_free(&is->swr_ctx); |
|
|
|
return -1; |
|
|
|
} |
|
|
|
is->audio_src.channel_layout = dec_channel_layout; |
|
|
|
is->audio_src.channels = av_frame_get_channels(af->frame); |
|
|
|
is->audio_src.freq = af->frame->sample_rate; |
|
|
|
is->audio_src.fmt = af->frame->format; |
|
|
|
} |
|
|
|
|
|
|
|
if (is->swr_ctx) { |
|
|
|
const uint8_t **in = (const uint8_t **)af->frame->extended_data; |
|
|
|
uint8_t **out = &is->audio_buf1; |
|
|
|
int out_count = (int64_t)wanted_nb_samples * is->audio_tgt.freq / af->frame->sample_rate + 256; |
|
|
|
int out_size = av_samples_get_buffer_size(NULL, is->audio_tgt.channels, out_count, is->audio_tgt.fmt, 0); |
|
|
|
int len2; |
|
|
|
if (out_size < 0) { |
|
|
|
av_log(NULL, AV_LOG_ERROR, "av_samples_get_buffer_size() failed\n"); |
|
|
|
return -1; |
|
|
|
} |
|
|
|
if (wanted_nb_samples != af->frame->nb_samples) { |
|
|
|
if (swr_set_compensation(is->swr_ctx, (wanted_nb_samples - af->frame->nb_samples) * is->audio_tgt.freq / af->frame->sample_rate, |
|
|
|
wanted_nb_samples * is->audio_tgt.freq / af->frame->sample_rate) < 0) { |
|
|
|
av_log(NULL, AV_LOG_ERROR, "swr_set_compensation() failed\n"); |
|
|
|
return -1; |
|
|
|
frame_queue_next(&is->sampq); |
|
|
|
} while (af->serial != is->audioq.serial); |
|
|
|
|
|
|
|
{ |
|
|
|
data_size = av_samples_get_buffer_size(NULL, av_frame_get_channels(af->frame), |
|
|
|
af->frame->nb_samples, |
|
|
|
af->frame->format, 1); |
|
|
|
|
|
|
|
dec_channel_layout = |
|
|
|
(af->frame->channel_layout && av_frame_get_channels(af->frame) == av_get_channel_layout_nb_channels(af->frame->channel_layout)) ? |
|
|
|
af->frame->channel_layout : av_get_default_channel_layout(av_frame_get_channels(af->frame)); |
|
|
|
wanted_nb_samples = synchronize_audio(is, af->frame->nb_samples); |
|
|
|
|
|
|
|
if (af->frame->format != is->audio_src.fmt || |
|
|
|
dec_channel_layout != is->audio_src.channel_layout || |
|
|
|
af->frame->sample_rate != is->audio_src.freq || |
|
|
|
(wanted_nb_samples != af->frame->nb_samples && !is->swr_ctx)) { |
|
|
|
swr_free(&is->swr_ctx); |
|
|
|
is->swr_ctx = swr_alloc_set_opts(NULL, |
|
|
|
is->audio_tgt.channel_layout, is->audio_tgt.fmt, is->audio_tgt.freq, |
|
|
|
dec_channel_layout, af->frame->format, af->frame->sample_rate, |
|
|
|
0, NULL); |
|
|
|
if (!is->swr_ctx || swr_init(is->swr_ctx) < 0) { |
|
|
|
av_log(NULL, AV_LOG_ERROR, |
|
|
|
"Cannot create sample rate converter for conversion of %d Hz %s %d channels to %d Hz %s %d channels!\n", |
|
|
|
af->frame->sample_rate, av_get_sample_fmt_name(af->frame->format), av_frame_get_channels(af->frame), |
|
|
|
is->audio_tgt.freq, av_get_sample_fmt_name(is->audio_tgt.fmt), is->audio_tgt.channels); |
|
|
|
swr_free(&is->swr_ctx); |
|
|
|
return -1; |
|
|
|
} |
|
|
|
is->audio_src.channel_layout = dec_channel_layout; |
|
|
|
is->audio_src.channels = av_frame_get_channels(af->frame); |
|
|
|
is->audio_src.freq = af->frame->sample_rate; |
|
|
|
is->audio_src.fmt = af->frame->format; |
|
|
|
} |
|
|
|
|
|
|
|
if (is->swr_ctx) { |
|
|
|
const uint8_t **in = (const uint8_t **)af->frame->extended_data; |
|
|
|
uint8_t **out = &is->audio_buf1; |
|
|
|
int out_count = (int64_t)wanted_nb_samples * is->audio_tgt.freq / af->frame->sample_rate + 256; |
|
|
|
int out_size = av_samples_get_buffer_size(NULL, is->audio_tgt.channels, out_count, is->audio_tgt.fmt, 0); |
|
|
|
int len2; |
|
|
|
if (out_size < 0) { |
|
|
|
av_log(NULL, AV_LOG_ERROR, "av_samples_get_buffer_size() failed\n"); |
|
|
|
return -1; |
|
|
|
} |
|
|
|
if (wanted_nb_samples != af->frame->nb_samples) { |
|
|
|
if (swr_set_compensation(is->swr_ctx, (wanted_nb_samples - af->frame->nb_samples) * is->audio_tgt.freq / af->frame->sample_rate, |
|
|
|
wanted_nb_samples * is->audio_tgt.freq / af->frame->sample_rate) < 0) { |
|
|
|
av_log(NULL, AV_LOG_ERROR, "swr_set_compensation() failed\n"); |
|
|
|
return -1; |
|
|
|
} |
|
|
|
} |
|
|
|
av_fast_malloc(&is->audio_buf1, &is->audio_buf1_size, out_size); |
|
|
|
if (!is->audio_buf1) |
|
|
|
return AVERROR(ENOMEM); |
|
|
|
len2 = swr_convert(is->swr_ctx, out, out_count, in, af->frame->nb_samples); |
|
|
|
if (len2 < 0) { |
|
|
|
av_log(NULL, AV_LOG_ERROR, "swr_convert() failed\n"); |
|
|
|
return -1; |
|
|
|
} |
|
|
|
if (len2 == out_count) { |
|
|
|
av_log(NULL, AV_LOG_WARNING, "audio buffer is probably too small\n"); |
|
|
|
if (swr_init(is->swr_ctx) < 0) |
|
|
|
swr_free(&is->swr_ctx); |
|
|
|
} |
|
|
|
is->audio_buf = is->audio_buf1; |
|
|
|
resampled_data_size = len2 * is->audio_tgt.channels * av_get_bytes_per_sample(is->audio_tgt.fmt); |
|
|
|
} else { |
|
|
|
is->audio_buf = af->frame->data[0]; |
|
|
|
resampled_data_size = data_size; |
|
|
|
} |
|
|
|
} |
|
|
|
av_fast_malloc(&is->audio_buf1, &is->audio_buf1_size, out_size); |
|
|
|
if (!is->audio_buf1) |
|
|
|
return AVERROR(ENOMEM); |
|
|
|
len2 = swr_convert(is->swr_ctx, out, out_count, in, af->frame->nb_samples); |
|
|
|
if (len2 < 0) { |
|
|
|
av_log(NULL, AV_LOG_ERROR, "swr_convert() failed\n"); |
|
|
|
return -1; |
|
|
|
} |
|
|
|
if (len2 == out_count) { |
|
|
|
av_log(NULL, AV_LOG_WARNING, "audio buffer is probably too small\n"); |
|
|
|
if (swr_init(is->swr_ctx) < 0) |
|
|
|
swr_free(&is->swr_ctx); |
|
|
|
} |
|
|
|
is->audio_buf = is->audio_buf1; |
|
|
|
resampled_data_size = len2 * is->audio_tgt.channels * av_get_bytes_per_sample(is->audio_tgt.fmt); |
|
|
|
} else { |
|
|
|
is->audio_buf = af->frame->data[0]; |
|
|
|
resampled_data_size = data_size; |
|
|
|
} |
|
|
|
|
|
|
|
audio_clock0 = is->audio_clock; |
|
|
|
/* update the audio clock with the pts */ |
|
|
|
if (!isnan(af->pts)) |
|
|
|
is->audio_clock = af->pts + (double) af->frame->nb_samples / af->frame->sample_rate; |
|
|
|
else |
|
|
|
is->audio_clock = NAN; |
|
|
|
is->audio_clock_serial = af->serial; |
|
|
|
audio_clock0 = is->audio_clock; |
|
|
|
/* update the audio clock with the pts */ |
|
|
|
if (!isnan(af->pts)) |
|
|
|
is->audio_clock = af->pts + (double) af->frame->nb_samples / af->frame->sample_rate; |
|
|
|
else |
|
|
|
is->audio_clock = NAN; |
|
|
|
is->audio_clock_serial = af->serial; |
|
|
|
#ifdef DEBUG |
|
|
|
{ |
|
|
|
static double last_clock; |
|
|
|
printf("audio: delay=%0.3f clock=%0.3f clock0=%0.3f\n", |
|
|
|
is->audio_clock - last_clock, |
|
|
|
is->audio_clock, audio_clock0); |
|
|
|
last_clock = is->audio_clock; |
|
|
|
} |
|
|
|
#endif |
|
|
|
return resampled_data_size; |
|
|
|
} |
|
|
|
{ |
|
|
|
static double last_clock; |
|
|
|
printf("audio: delay=%0.3f clock=%0.3f clock0=%0.3f\n", |
|
|
|
is->audio_clock - last_clock, |
|
|
|
is->audio_clock, audio_clock0); |
|
|
|
last_clock = is->audio_clock; |
|
|
|
} |
|
|
|
#endif |
|
|
|
return resampled_data_size; |
|
|
|
} |
|
|
|
|
|
|
|
/* prepare a new audio buffer */ |
|
|
|
|