为了账号安全,请及时绑定邮箱和手机立即绑定

【金秋打卡】第21天 AAC 编码器编码

标签:
Android

课程名称音视频基础+ffmpeg原理 入门音视频技术开发
课程章节:【实战】音频编码
课程讲师李超

课程内容

创建 AVFrame

查找编码器,分配上下文,设置上下文参数,打开编码器后。接下来就应该将数据输入编码器。

由于以下的原因,需要把 AVPacket 数据存进AVFrame当中。

  • ffmpeg 的 avformat_open_input() 是将多媒体文件打开。
  • avformat_open_input() 既可以打开文件,也可以打开设备。
  • avformat_open_input() 就是将所有的东西当做多媒体文件打开,所以通过 av_read_frame() 读出 AVPacket 数据,按道理说 AVPacket 存的是编码后的数据,可是这里存储的是PCM原始数据。
  • 编码器需要的是AVFrame原始数据。

创建 AVFrame 的关键代码:

AVFrame* create_frame(){
    AVFrame *frame = av_frame_alloc(); //其中的buffer才是存着主要的数据
    if(!frame){
        return NULL;
    }
    frame->nb_samples = 512; //这里每个包的大小是2048/位深32位(4个字节)/1个通道 所以就是2048/4/1=512
    frame->format = AV_SAMPLE_FMT_S16;//AAC需要的位深
    frame->channel_layout = AV_CH_LAYOUT_STEREO; //AAC需要的通道
    av_frame_get_buffer(frame, 0);
    if(!frame->data[0]){
        printf("Error, Failed to alloc buf in frame!\n");
        //内存泄漏
        goto __ERROR;
    }
    return frame;
__ERROR:
    if(frame){
        av_frame_free(&frame);
    }
    return NULL;
}

创建 AVFrame 主要用到了两个函数,av_frame_alloc() 和 av_frame_get_buffer(),实际上数据是存在AVFrame 中 buffer 当中,会根据设置的 frame 的采样大小(位深),通道个数,采样个数进行分配 buffer。

将 AVPacket 数据存进 AVFrame

1.创建缓存区

 av_samples_alloc_array_and_samples(&dst_data,
                                       &dst_linesize,
                                       2,
                                       512,
                                       AV_SAMPLE_FMT_S16,
                                       0);

2.将AVPacket中的数据放进缓存区

memcpy((void *)dst_data[0], (void *)pkt.data, pkt.size);

3.将缓存区的数据放进AVFrame

memcpy((void *)frame->data[0], (void*)dst_data[0], dst_linesize);

4.将frame数据送给编码器

ret = avcodec_send_frame(codec_ctx, frame);

5.接受编码后的数据AVPacket

ret = avcodec_receive_packet(codec_ctx, pkt);

由于 avcodec_send_frame() 传入要编码的数据不一定传入就会马上返回编码后的数据,而是编码好多数据后多次返回。所以获取编码后的数据需要用while循环来处理 avcodec_receive_packet()的状态。直到avcodec_receive_packet()的返回值 <= 0,说明当前没有要处理的数据了,可以接受下一个AVFrame数据进行处理了。

 while(ret > 0){
        ret = avcodec_receive_packet(codec_ctx, pkt);
        if(ret < 0 ){
            if(ret == AVERROR(EAGAIN) || ret == AVERROR_EOF){
                break;
            }else{
                printf("error encodeing avframe");
                exit(-1);
            }
        }
        fwrite(pkt->data,pkt->size, 1, outFile);
        fflush(outFile);
        av_packet_unref(&pkt);
    }

6.读取到编码后的数据后写入文件

fwrite(pkt->data,pkt->size, 1, outFile);
fflush(outFile);

图片描述

图片描述

点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
移动开发工程师
手记
粉丝
12
获赞与收藏
17

关注作者,订阅最新文章

阅读免费教程

  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消