音频编码流程 ----- PCM编码为AAC格式

news2024/9/22 3:42:18

文章目录

  • 1.音频编码流程
  • 2.编码函数API含义解释
  • 3.音频编码实战Demo PCM转AAC格式

1.音频编码流程

在这里插入图片描述

2.编码函数API含义解释

av_frame_make_writable 确保帧数据可写,尽可能避免数据复制.如果帧可写,则不执行任何操作,如果不可写,则分配新缓冲区并复制数据.返回: 成功时为 0,错误时为负 AVERROR.

av_samples_fill_arrays 这个函数就是将你输入的一帧数据写入AVFrame格式输出,便于后面编码send,recvice使用

3.音频编码实战Demo PCM转AAC格式

编码注意点:

  1. 编码器相关配置得设置正确,比如码率,采样率,声道,采样格式等
  2. 也要设置AVFrame的格式,主要是采样率,声道,采样格式
  3. 如果数据不是FLTP格式的花,需要转化为FLTP格式.
  4. PCM编码后的数据想要编码为AAC格式,得在前面加上adtsheader.
#ifndef MAINBACK_C
#define MAINBACK_C
#endif // MAINBACK_C
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <libavcodec/avcodec.h>
#include <libavutil/channel_layout.h>
#include <libavutil/common.h>
#include <libavutil/frame.h>
#include <libavutil/samplefmt.h>
#include <libavutil/opt.h>
void f32le_convert_to_fltp(float *f32le, float *fltp, int nb_samples) {
    float *fltp_l = fltp;   // 左通道
    float *fltp_r = fltp + nb_samples;   // 右通道
    for(int i = 0; i < nb_samples; i++) {
        fltp_l[i] = f32le[i*2];     // 0 1   - 2 3
        fltp_r[i] = f32le[i*2+1];   // 可以尝试注释左声道或者右声道听听声音
    }
}
static void get_adts_header(AVCodecContext *ctx, uint8_t *adts_header, int aac_length)
{
    uint8_t freq_idx = 0;    //0: 96000 Hz  3: 48000 Hz 4: 44100 Hz
    switch (ctx->sample_rate) {
        case 96000: freq_idx = 0; break;
        case 88200: freq_idx = 1; break;
        case 64000: freq_idx = 2; break;
        case 48000: freq_idx = 3; break;
        case 44100: freq_idx = 4; break;
        case 32000: freq_idx = 5; break;
        case 24000: freq_idx = 6; break;
        case 22050: freq_idx = 7; break;
        case 16000: freq_idx = 8; break;
        case 12000: freq_idx = 9; break;
        case 11025: freq_idx = 10; break;
        case 8000: freq_idx = 11; break;
        case 7350: freq_idx = 12; break;
        default: freq_idx = 4; break;
    }
    uint8_t chanCfg = ctx->channels;
    uint32_t frame_length = aac_length + 7;
    adts_header[0] = 0xFF;
    adts_header[1] = 0xF1;
    adts_header[2] = ((ctx->profile) << 6) + (freq_idx << 2) + (chanCfg >> 2);
    adts_header[3] = (((chanCfg & 3) << 6) + (frame_length  >> 11));
    adts_header[4] = ((frame_length & 0x7FF) >> 3);
    adts_header[5] = (((frame_length & 7) << 5) + 0x1F);
    adts_header[6] = 0xFC;
}
int encode(AVCodecContext* codec_ctx,AVFrame* frame,AVPacket* pkt,FILE* out)
{
    int ret=0;
    ret = avcodec_send_frame(codec_ctx,frame);
    if(ret<0){
        printf("avcodec_send_frame failed\n");
        return ret;
    }

    while(1)
    {
        ret=avcodec_receive_packet(codec_ctx,pkt);
        if(ret==AVERROR(EAGAIN)||ret==AVERROR(AVERROR_EOF))
            break;
        if(ret<0)return ret;
        if(codec_ctx->flags&AV_CODEC_FLAG_GLOBAL_HEADER)
        {
            char header[7]={0};
            get_adts_header(codec_ctx,header,pkt->size);
            int size=fwrite(header,1,7,out);
            if(size!=7)
            {
                printf("fwrite error\n");
                return 0;
            }
        }

        fwrite(pkt->data,1,pkt->size,out);
    }

}
//编码流程  先初始化编码器,读取原始文件,send,recvice,写入
int main(int argc,char* argv[])
{
    if(argv<3)
    {
        printf("argv<3\n");
        return -1;
    }
    char* pcm_path=argv[1];
    char* out_path=argv[2];
    FILE* pcm_file=fopen(pcm_path,"rb");
    FILE* out_file=fopen(out_path,"wb");
    AVCodec* codec=avcodec_find_encoder(AV_CODEC_ID_AAC);
    AVCodecContext* codec_ctx=avcodec_alloc_context3(codec);

    codec_ctx->bit_rate=100000;
    codec_ctx->channel_layout=AV_CH_LAYOUT_STEREO;
    codec_ctx->channels=av_get_channel_layout_nb_channels(codec_ctx->channel_layout);
    codec_ctx->sample_fmt=AV_SAMPLE_FMT_FLTP;
//    codec_ctx->codec_id=AV_CODEC_ID_AAC;
//    codec_ctx->codec_type=AVMEDIA_TYPE_AUDIO;
    codec_ctx->sample_rate=48000;
    codec_ctx->profile=FF_PROFILE_AAC_LOW;
    codec_ctx->flags|=AV_CODEC_FLAG_GLOBAL_HEADER;
    avcodec_open2(codec_ctx,codec,NULL);

    AVFrame* frame=av_frame_alloc();
    AVPacket* pkt=av_packet_alloc();
//    frame->channel_layout=codec_ctx->channel_layout;
    frame->channels=codec_ctx->channels;
//    frame->sample_rate=codec_ctx->sample_rate;
    frame->format=codec_ctx->sample_fmt;
    frame->nb_samples=codec_ctx->frame_size;
    av_frame_get_buffer(frame,0);//分配frame的buff
    int frame_bytes=av_get_bytes_per_sample(frame->format)*frame->channels*frame->nb_samples;
    uint8_t* pcm_buff=av_malloc(frame_bytes);
    memset(pcm_buff,0,frame_bytes);
    uint8_t *pcm_temp_buf = (uint8_t *)malloc(frame_bytes);
    memset(pcm_temp_buf,0,frame_bytes);
    int pts=0;
    int ret=0;
    while(1)
    {
        int rsize=fread(pcm_buff,1,frame_bytes,pcm_file);
        ret = av_frame_make_writable(frame);
        if(ret != 0)
            printf("av_frame_make_writable failed, ret = %d\n", ret);
        f32le_convert_to_fltp(pcm_buff,pcm_temp_buf,frame->nb_samples);
        int need_size=av_samples_fill_arrays(frame->data,frame->linesize,pcm_temp_buf,frame->channels,frame->nb_samples,frame->format,0);
        if(rsize!=need_size)break;
        frame->pts=pts;
        pts+=1;
        printf("frame pts:%d\n",pts);
        encode(codec_ctx,frame,pkt,out_file);
    }
    encode(codec_ctx,NULL,pkt,out_file);
    return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/733098.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

ssm整合shiro安全框架 前后端分离项目

上一篇文章我们使用ssm整合了shiro安全框架前后端没有进行分离 本篇文章在上一章的项目基础上进行前后端代码分离操作 一、根据账号和密码登录后前后端代码分离&#x1f349; (1)定义一个统一的json类 统一返回的格式&#x1f95d; package com.lzq.vo;import lombok.AllArg…

免费开源 | 基于SpringBoot的博客系统

介绍 基于springboot后端架构&#xff0c;websocket实现私信&#xff0c;前端采用thymeleafbootstraplayuiRedis 注册使用邮箱验证注册&#xff0c;且验证码存在redis中&#xff0c;所以需要有redis环境 软件架构 springbootwebsocketthymeleafbootstraplayuiRedismysql 8.…

设计模式--代理设计模式

&#x1f389;&#x1f389;&#x1f389;写在前面&#xff1a; 博主主页&#xff1a;&#x1f339;&#x1f339;&#x1f339;戳一戳&#xff0c;欢迎大佬指点&#xff01; 目标梦想&#xff1a;进大厂&#xff0c;立志成为一个牛掰的Java程序猿&#xff0c;虽然现在还是一个…

C++之std::function和lambda表达式回调函数(一百五十二)

简介&#xff1a; CSDN博客专家&#xff0c;专注Android/Linux系统&#xff0c;分享多mic语音方案、音视频、编解码等技术&#xff0c;与大家一起成长&#xff01; 优质专栏&#xff1a;Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 人生格言&#xff1a; 人生…

新版本FasterTransformer的FUSED_MHA

关于 UNFUSED_PADDED_MHA VS FUSED_MHA FUSED_MHA用了另一种kernel的执行方法(和添加链接描述相同,将在下一个section说明)UNFUSED_PADDED 的 KERNELS执行代码在 src/fastertransformer/kernels/unfused_attention_kernels.cu enum class AttentionType {UNFUSED_MHA,UNFUSED…

C#,中国福利彩票《刮刮乐》的数学算法(01)——幸运123

彩票名称&#xff1a;幸运123面值&#xff1a;20元/张最高奖&#xff1a;100万&#xff08;人民币&#xff09;全套款式&#xff1a;2款玩法介绍&#xff1a; 一份好运&#xff0c;二倍快乐&#xff0c;三重惊喜。福彩刮刮乐新游戏“幸运123”&#xff0c;红色的票面上点缀着礼…

基于simulink使用同步图像跟踪白板上的标记(附源码)

一、前言 此示例演示如何使用Simulink基于图像跟踪白板上的标记。 二、模型 示例模型包含模型引用层次结构。每个模型都有助于图像处理算法。 ex_tracking_marker- 跟踪输入视频中的标记的顶级模型。此模型使用视频查看器块呈现输出视频&#xff0c;并将输出帧记录在工作区变…

Unity桌面弹球小游戏Finger Soccer Game Kit 1.1

按住鼠标左键发射打球 还可以开启双人模式来玩 地址&#xff1a;https://download.csdn.net/download/Highning0007/88020441

《分布式中间件技术实战:Java版》学习笔记(三):Redis实现点赞、取消赞功能

用户在发布内容&#xff08;包括博客、想法、日记等等&#xff09;时&#xff0c;后台数据入库后&#xff0c;要往Redis的有序集合添加一条分数为0的记录。这个有序集合是用来对内容点赞量做排序的。同时&#xff0c;可以记录用户操作日志。 Override public String insertArt…

C++常用库函数 4.数学函数

函数名&#xff1a;abs 函数原型&#xff1a;int abs(int n) ; 参数 in 需要求绝对值的整数。 所需头文件&#xff1a;<cstdlib>或<cmath> 功能和返回值&#xff1a;返回 n 的绝对值&#xff1b;没有错误返回函数名&#xff1a;acos 函数原型&#xff1a;doubl…

Cocos Creator 打包 Android 原生,如何配置构建环境?关键就一点

前段时间&#xff0c;有好几位老铁留言 Cocos Creator 打包 Android 原生出现问题&#xff1a;一种是构建失败&#xff0c;一种是运行起来报错&#xff01; 其实&#xff0c;我也是有好长一段时间没有碰过 Android 原生了&#xff0c;而且我这台电脑&#xff0c;环境都没有配置…

idea创建web项目没有jsp选项,不识别jsp,没有tomcat选项

如果你的idea的web项目中没有jsp选项 同时也不识别jsp 那么建议你检查一下你的idea是否为社区版 如果是社区版那么没有jsp的问题无法解决&#xff0c;这只是无法识别&#xff0c;但是语句对的可以正常运行 解决这个问题建议换个idea 至于tomcat&#xff0c; 在plugins中搜s…

axios的学习

axios是基于promise对ajax的一种封装 //将省份信息打印到网页上 <p class"my-p"></p> <script src"https://unpkg.com/axios/dist/axios.min.js"></script> <script>axios({url:http://hmajax.itheima.net/api/province}).…

【PCIE】hot-reset和link disable

Hot reset 规则 如果上游伪端口&#xff08;Pseudo Port&#xff09;的任何一个通道连续接收到两个带有热复位位设置为1b、禁用链路位和回环位设置为0b的TS1有序集合&#xff0c;并且两个伪端口上的任何一个通道&#xff08;接收到TS1有序集合&#xff09;要么收到EIOS&#xf…

java方法的覆盖(Overriding )和隐藏(Hiding)

Java方法的覆盖&#xff08;Overriding &#xff09;针对的是实例方法&#xff08;即非静态方法&#xff09;&#xff0c;而方法的隐藏&#xff08;Hiding&#xff09;针对的是类方法&#xff08;即静态方法&#xff09;。 方法的覆盖和隐藏指的是子类对从父类继承的方法进行重…

基于simulink基于颜色分割方法跟踪人员的面部和手部(附源码)

一、前言 此示例演示如何使用基于颜色的分割方法跟踪人员的面部和手部。 二、模型 下图显示了颜色分割示例模型&#xff1a; 三、颜色分割结果 为了为示例创建准确的颜色模型&#xff0c;处理了许多包含肤色样本的图像&#xff0c;以计算 Cb 和 Cr 颜色通道的均值 &#xf…

基于Unity2017版本的2D3D Infinite Runner Engine 1.5.1二维三维跑酷游戏模板

基于Unity2017版本的2D3D Infinite Runner Engine 1.5.1二维三维跑酷游戏模板 有多种游戏模式 还有个竖屏的玩法 工程地址&#xff1a;https://download.csdn.net/download/Highning0007/88020755

MFC学习日记(一)——创建新项目

此系列所有文章参考链接&#xff1a;http://www.jizhuomi.com/software/141.html 点击file新建项目创建一个MFC新项目 点击确定 点击下一步 选择应用程序类型 我们看到有四种类型&#xff1a;Single document&#xff08;单文档&#xff09;、Multiple documents&#xff…

传统图像处理之目标检测——人脸识别

代码实战&#xff1a;人脸识别 import numpy as np import cv2 img cv2.imread("3.webp")face_cascade cv2.CascadeClassifier(r./haarcascade_frontalface_default.xml)gray cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)#探测图片中的人脸 faces face_cascade.detec…

Android kotlin 实现把多个控件整体上下拉回弹功能(添加是否禁用顶部和底部回弹的参数设置,以及回弹效果结束监听)

目录 一、实现效果二、源码1、上下拉回弹,自定义ScrollView2、主activity一、实现效果 二、源码 1、上下拉回弹,自定义ScrollView 上下拉回弹,自定义ScrollView,ReboundScrollView.kt package com.example.myapplication3.myviewimport android.content.Context import