ffmpeg错误之[libvo_aacenc @ 03c62300] more samples than frame size (avcodec_encode_audio2)

1.背景

音频aac编码的时候,调用函数接口avcodec_encode_audio2)提示错误信息:[aac @ 0x7f7bb40184a0] more samples than frame size (avcodec_encode_audio2)

2.原因

代码块如下:

if (frame->nb_samples > avctx->frame_size) {
    av_log(avctx, AV_LOG_ERROR, "more samples than frame size (avcodec_encode_audio2)\n");
    ret = AVERROR(EINVAL);
    goto end;
}

解析: 
frame->nb_samples:实际编码时音频采样数的大小; 

avctx->frame_size:预设定的音频编码采样率;

3.解决的方案

根据原因可知道,是喂给编码器的每帧采样数和预设定的音频编码采样率不一致导致的,解决方法就是让他们达到一致即可。

方法:将每次采集到的音频frame数据保存到一个AUDIO FIFO中,每次凑齐到frame_size大小的数据时,把这些数据喂给音频编码器即可。


以下代码未解决

#include <stdio.h>
#include <iostream>
extern "C"
{
#include "libavcodec/avcodec.h"
#include "libavformat/avformat.h"
#include "libswscale/swscale.h"
#include "libavdevice/avdevice.h"
#include "libavutil/audio_fifo.h"
}
 
using namespace std;
//'1' Use Dshow
//'0' Use VFW
#define USE_DSHOW 0
 
static int init_fifo(AVAudioFifo **fifo, AVCodecContext *output_codec_context)
{
    /* Create the FIFO buffer based on the specified output sample format. */
    if (!(*fifo = av_audio_fifo_alloc(output_codec_context->sample_fmt,
                                      output_codec_context->channels, 1))) {
        fprintf(stderr, "Could not allocate FIFO\n");
        return AVERROR(ENOMEM);
    }
    return 0;
}
 
//Show Dshow Device
void show_dshow_device(){
    AVFormatContext *pFormatCtx = avformat_alloc_context();
    AVDictionary* options = NULL;
    av_dict_set(&options,"list_devices","true",0);
    AVInputFormat *iformat = av_find_input_format("dshow");
    printf("========Device Info=============\n");
    avformat_open_input(&pFormatCtx,"video=dummy",iformat,&options);
    printf("================================\n");
}
//Show Dshow Device Option
void show_dshow_device_option(){
    AVFormatContext *pFormatCtx = avformat_alloc_context();
    AVDictionary* options = NULL;
    av_dict_set(&options,"list_options","true",0);
    AVInputFormat *iformat = av_find_input_format("dshow");
    printf("========Device Option Info======\n");
    avformat_open_input(&pFormatCtx,"video=Integrated Camera",iformat,&options);
    printf("================================\n");
}
//Show VFW Device
void show_vfw_device(){
    AVFormatContext *pFormatCtx = avformat_alloc_context();
    AVInputFormat *iformat = av_find_input_format("vfwcap");
    printf("========VFW Device Info======\n");
    avformat_open_input(&pFormatCtx,"list",iformat,NULL);
    printf("=============================\n");
}
//Show AVFoundation Device
void show_avfoundation_device(){
    AVFormatContext *pFormatCtx = avformat_alloc_context();
    AVDictionary* options = NULL;
    av_dict_set(&options,"list_devices","true",0);
    AVInputFormat *iformat = av_find_input_format("avfoundation");
    printf("==AVFoundation Device Info===\n");
    avformat_open_input(&pFormatCtx,"",iformat,&options);
    printf("=============================\n");
}
#define USE_DSHOW 1
int main(int argc, char* argv[])
{
    AVFormatContext	*pFormatCtx;
    int				i, audioindex;
    AVCodecContext	*pCodecCtx;
    AVCodec			*pCodec;
    av_register_all();
    avformat_network_init();
    avdevice_register_all();//Register Device
 
    pFormatCtx = avformat_alloc_context();
#if 1
    AVInputFormat *ifmt=av_find_input_format("dshow");
    //Set own audio device's name
    if(avformat_open_input(&pFormatCtx,"audio=麦克风 (Realtek High Definition Au",ifmt,NULL)!=0){
        printf("Couldn't open input stream.\n");
        return -1;
    }
#else
    AVInputFormat *ifmt=av_find_input_format("vfwcap");
    if(avformat_open_input(&pFormatCtx,"audio=麦克风 (Realtek High Definition Au0",ifmt,NULL)!=0){
        printf("Couldn't open input stream.\n");
        return -1;
    }
#endif
    if(avformat_find_stream_info(pFormatCtx,NULL)<0)
    {
        printf("Couldn't find stream information.\n");
        return -1;
    }
    audioindex=-1;
    for(i=0; i<pFormatCtx->nb_streams; i++)
    {
        if(pFormatCtx->streams[i]->codec->codec_type==AVMEDIA_TYPE_AUDIO)
        {
            audioindex=i;
        }
    }
    if(audioindex==-1)
    {
        printf("Couldn't find a audio stream.\n");
        return -1;
    }
    pCodecCtx=pFormatCtx->streams[audioindex]->codec;
    pCodec=avcodec_find_decoder(pCodecCtx->codec_id);
    if(pCodec==NULL)
    {
        printf("Codec not found.\n");
        return -1;
    }
    if(avcodec_open2(pCodecCtx, pCodec,NULL)<0)
    {
        printf("Could not open codec.\n");
        return -1;
    }
 
    ///这里打印出音频的信息
    cout<<"audio info:"<<pCodecCtx->sample_fmt<<pCodecCtx->bit_rate<<pCodecCtx->sample_rate<<pCodecCtx->channels<<endl;
 
    FILE *fp_pcm=fopen("output.pcm","wb");
    FILE *fp_aac=fopen("output.aac", "wb");
 
 
    //查找编码器
    AVCodecContext* pAAC_CodecCtx;
    AVCodec*  pAAC_Codec;
    pAAC_Codec = avcodec_find_encoder(AV_CODEC_ID_AAC);
    if(!pAAC_Codec)
    {
      fprintf(stderr, "---------AAC codec not found----\n");
      exit(1);
    }
 
    pAAC_CodecCtx = avcodec_alloc_context3(pAAC_Codec);
    pAAC_CodecCtx->codec_id = AV_CODEC_ID_AAC;
    pAAC_CodecCtx->codec_type = AVMEDIA_TYPE_AUDIO;
    pAAC_CodecCtx->sample_fmt = AV_SAMPLE_FMT_S16;
    pAAC_CodecCtx->sample_rate= 44100;
    pAAC_CodecCtx->channel_layout=AV_CH_LAYOUT_STEREO; //
    pAAC_CodecCtx->channels = av_get_channel_layout_nb_channels(pAAC_CodecCtx->channel_layout);
    pAAC_CodecCtx->bit_rate = 64000;
 
 
    pAAC_Codec = avcodec_find_encoder(pAAC_CodecCtx->codec_id);
    if (!pAAC_Codec)
    {
        printf("没有找到合适的编码器!\n");
        return -1;
    }
    if (avcodec_open2(pAAC_CodecCtx, pAAC_Codec,NULL) < 0)
    {
        printf("编码器打开失败!\n");
        return -1;
    }
 
    AVPacket *packet= (AVPacket*)av_malloc(sizeof(AVPacket));
    AVFrame *pFrame = av_frame_alloc();
    //uint8_t *out_buffer=(uint8_t *)av_malloc(avpicture_get_size(PIX_FMT_YUV420P, pCodecCtx->width, pCodecCtx->height));
    //avpicture_fill((AVPicture *)pFrame, out_buffer, PIX_FMT_YUV420P, pCodecCtx->width, pCodecCtx->height);
 
    int got_picture = 0;
    float Time = 0;
 
    AVAudioFifo *fifo = NULL;
    if (init_fifo(&fifo, pAAC_CodecCtx))
    {
       cout<<"init_fifo failed"<<endl;
       return -1;
    }
 
 
    for(int i=0;;i++)
    {
 
        if (Time > 10) break; //就采集10秒
        if(av_read_frame(pFormatCtx, packet) < 0)
        {
            break;
        }
 
        if(packet->stream_index==audioindex)
        {
            int ret = avcodec_decode_audio4(pCodecCtx, pFrame, &got_picture, packet);
            if(ret < 0){
                printf("Decode Error.\n");
                return -1;
            }
 
            if(got_picture)
            {
               int pcmSize = av_samples_get_buffer_size(NULL,pCodecCtx->channels, pFrame->nb_samples,pCodecCtx->sample_fmt, 1);
               uint8_t * pcmBuffer = pFrame->data[0];
               //pFrame->data[0] =
               float useTime = pFrame->nb_samples * 1.0 / pCodecCtx->sample_rate;
               Time += useTime;
               cout<<i<<Time<<useTime;
 
               //编码为aac
              //int avcodec_encode_audio2(AVCodecContext *avctx, AVPacket *avpkt,
               //const AVFrame *frame, int *got_packet_ptr);
               int got_packet_ptr=0;
 
               uint8_t data_aac;
               int ret = avcodec_encode_audio2(pAAC_CodecCtx, packet , pFrame, &got_packet_ptr);
               if (0 > ret)
               {
                    cout<<"encoded aac failed"<<endl;
                    return -1;
               }
               if (got_packet_ptr == 1)
               {
                   fwrite(packet->data,1,packet->size,fp_aac); //写入文件
               }
 
            }
        }
        av_free_packet(packet);
    }
 
    fclose(fp_pcm);
    av_free(pFrame);
    avcodec_close(pAAC_CodecCtx);
    avcodec_close(pCodecCtx);
    avformat_close_input(&pFormatCtx);
    return 0;
}
 




评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值