FFmpeg开发(1):pcm->aac

采样率 sample_rate 一般是44100

样本格式 sample_size(数据存储格式)

        AV_SAMPLE_FMT_S16 16位二字节        内存格式为c1,c2,c1,c2.......   

        AV_SAMPLE_FMT_FLTP 浮点数四字节32位   内存格式为c1,c1........c2,c2

        c1:左声道,c2:右声道

       

  • Packed: L R L R L R L R
  • Planar: L L L L R R R R       ffmpeg内部存储模式,我们实际使用的音频文件都是Packed模式的。

播放pcm数据  (7条消息) PCM数据格式介绍_SuperDali的博客-CSDN博客_pcm数据格式

        ffplay -ar 44100 channels 2 -f s16le -i 视频地址

AAC数据(8条消息) AAC文件格式详解_wd_cloud的博客-CSDN博客_aac格式

头文件

extern "C"
{
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libavutil/avutil.h>
#include <libswresample/swresample.h>

}

编码器配置

AVCodec *codec = avcodec_find_encoder(AV_CODEC_ID_AAC);//创建AAC音频编码器
AVCodecContext *ac = avcodec_alloc_context3(codec);//配置编码器的上下文
ac->sample_rate=44100;
ac->channels=2;
ac->channel_layout=AV_CH_LAYOUT_STEREO;//双声道立体声
ac->sample_fmt=AV_SAMPLE_FMT_FLTP;//32位空间
ac->bit_rate=64000;
ac->flags=AV_CODEC_FLAG_GLOBAL_GEADER;//头部

打开编码器,创建输出上下文,索引,头部,编码后数据都写入输出上下文

int ret;
ret=avcodec_open2(ac,codec,NULL);//打开音频编码器,成功返回0

AVFormatContext*oc=NULL;//创建输出上下文
avformat_alloc_output_context2(&oc,NULL,NULL,输出文件名)

AVStream*st=avformat_new_stream(oc,NULL);//音频流
st->codecpar->codec_tag=0;//音频文件设置为0,视频为1
avcodec_parameters_from_context(st->codecpar,ac);//将已初始化的编码器的格式拷贝至音频流

//打印配置好的信息,第二个数据音频为0,视频为1,第四个数据1打印,0不打印
av_dump_format(oc,0,输出文件名,1);

打开输出文件流

ret=avio_open(&oc->pb,outputflie,AVIO_FLAG_WRITE);//pb是io流
//写入头部信息
avformat_write_header(oc,NULL);

创建重采样上下文

SwrContext*ctx=NULL;//重采样上下文

//ctx参数配置
swr_alloc_set_opts(ctx,ac->channel_layouy,ac->sample_fmt,ac->sample_rate,//输出音频参数
                    AV_CH_LAYOUT_STEREO,AV_SAMPLE_FMT_S16,44100,//输入音频参数
                    0,0
                    );

//ctx初始化
int ret=swr_init(ctx);

预备重采样

//将PCM数据一帧一帧存放到frame,每一帧1024个样本
AVFrame*frame=av_frame_alloc();
frame->format=AV_SAMPLE_FMT_FLTP;//样本格式
frame->channels=2;
frame->channel_layout=AV_CH_LAYOUT_STEREO;
frame->nb_samples=1024;//一帧音频样本数量

av_frame_get_buffer(frame,0);//frame缓存空间

//采样率*位深度*声道数*时间
int readSize=frame->nb_samples*2*2;//一帧大小  1024*16*2*1/8
char*pcms=new char[readSize];

打开输入文件,并读取,重采样

FILE*fp=fopen(inputfile,"rb"//二进制);//打开输入文件
for(;;)
{
    int len=fread(pcms,1,readSize,fp);
    if(len<0)
    {
        break;
    }

    //重采样之前的数据
    const uint8_t*data[1];
    data[0]=(uint8_t*)pcms;//强转换

   
    //开始重采样
    len=swr_convert(ctx,frame->data,frame->nb_samples,//重采样之后的数据
                data,frame->nb_samples//重采样之前的数据

                );
    if(len<0)
    {
        break;
    }


//重采样之后进行编码并写入acc文件

    //frame 放原数据,packet放编码后数据
    AVPacket pkt;
    av_init_packet(&pkt);

    //将重采样数据发送到编码线程
    ret=avcodec_send_frame(ac,frame);
    if(ret<0)
    {
        continue;
    }


    ret=avcodec_recevice_packet(ac,&pkt);
    if(ret!=0)
    {
        continue
    }

    pkt.stream_index=0;//0:音频流
    pkt.dts=0;
    pkt.pts=0;   //解码时间,显示时间初始化为0
    av_interleaved_write_frame(oc,&pkt);
}

视频索引与结尾工作

delete pcms;
pcms=NULL;

//视频索引
av_write_trailer(oc);


avio_close(oc->pb);//关闭文件io流
avcodec_close(ac);//关闭编码器
avcodec_free_context(&ac)//清理编码器缓存
avformat_free_context(oc)//清理上下文

,释放空间

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值