原因:
音頻編碼器AVCodecContext (編碼器的能力)的frame_size 比編入幀AVFrame的nb_samples小 。
解決方法:
通過調試可以得到aac編碼器的frame_size 爲1024 所以每次應該給編碼器1024個採樣。可以採樣AVAudioFifo緩存確保每次編入aac的數據爲編碼器的frame_size(1024)。
代碼如下:
while (( ret=av_audio_fifo_size(fifo)) < output_frame_size)
{
if (init_converted_samples(&converted_input_samples, ac,
oAFrame->nb_samples))
{
}
if (convert_samples((const uint8_t**)oAFrame->extended_data, converted_input_samples,
oAFrame->nb_samples, resample_context))
{
}
add_samples_to_fifo(fifo, converted_input_samples,oAFrame->nb_samples);
if (converted_input_samples)
{
av_freep(&converted_input_samples[0]);
free(converted_input_samples);
}
}
while(av_audio_fifo_size(fifo) >= output_frame_size)
{
AVFrame *frame;
frame = av_frame_alloc();
const int frame_size = FFMIN(av_audio_fifo_size(fifo),ac->frame_size);
(frame)->nb_samples = frame_size;
(frame)->channel_layout = ac->channel_layout;
(frame)->format = ac->sample_fmt;
(frame)->sample_rate = ac->sample_rate;
int error;
if ((error = av_frame_get_buffer(frame, 0)) < 0)
{
av_frame_free(&frame);
return error;
}
if (av_audio_fifo_read(fifo, (void **)frame->data, frame_size) < frame_size)
{
av_frame_free(&frame);
return AVERROR_EXIT;
}
AVPacket pkt;
av_init_packet(&pkt);
pkt.data = NULL;
pkt.size = 0;
//fflush(stdout);
frame->pts = av_frame_get_best_effort_timestamp(frame);
frame->pict_type=AV_PICTURE_TYPE_NONE;
if ((error = avcodec_encode_audio2(ac, &pkt,frame, &data_present)) < 0)
{
av_free_packet(&pkt);
return error;
}
av_frame_free(&frame);
if (data_present)
{
pkt.stream_index = audio_st->index;
pkt.dts = av_rescale_q_rnd(pkt.dts,
oc->streams[audioindex]->codec->time_base,
oc->streams[audioindex]->time_base,
(AVRounding)(AV_ROUND_NEAR_INF|AV_ROUND_PASS_MINMAX));
pkt.pts = av_rescale_q_rnd(pkt.pts,
oc->streams[audioindex]->codec->time_base,
oc->streams[audioindex]->time_base,
(AVRounding)(AV_ROUND_NEAR_INF|AV_ROUND_PASS_MINMAX));
pkt.duration = av_rescale_q(pkt.duration,
oc->streams[audioindex]->codec->time_base,
oc->streams[audioindex]->time_base);
if ((error = av_interleaved_write_frame(oc, &pkt)) < 0)
{
av_free_packet(&pkt);
return error;
}
}//end if(data_present)
av_free_packet(&pkt);
}
output_frame_size 即爲AVCodecContext 的frame_size