ffmpeg学习之音频解码数据

音频数据经过解码后会被保存为,pcm数据格式。而对应的处理流程如下所示。

avcodec_find_encoder() 

/**
 * 查找具有匹配编解码器ID的已注册编码器.
 *
 * @param id AVCodecID of the requested encoder
 * @return An encoder if one was found, NULL otherwise.
 */
const AVCodec *avcodec_find_encoder(enum AVCodecID id);

avcodec_find_encoder_by_name() 

/**
 * 查找具有指定名称的已注册编码器.
 *
 * @param name name of the requested encoder
 * @return An encoder if one was found, NULL otherwise.
 */
const AVCodec *avcodec_find_encoder_by_name(const char *name);

avcodec_alloc_context3() 

/**
分配AVCodecContext并将其字段设置为默认值。该应使用avcodec_free_context()释放结果结构。
 *
 * @param codec if non-NULL, allocate private data and initialize defaults
 *              for the given codec. It is illegal to then call avcodec_open2()
 *              with a different codec.
 *              If NULL, then the codec-specific defaults won't be initialized,
 *              which may result in suboptimal default settings (this is
 *              important mainly for encoders, e.g. libx264).
 *
 * @return An AVCodecContext filled with default values or NULL on failure.
 */
AVCodecContext *avcodec_alloc_context3(const AVCodec *codec);

 设置对应音频编码的数据类型

    codec_ctx->sample_fmt = AV_SAMPLE_FMT_S16;          //输入音频的采样大小
    codec_ctx->channel_layout = AV_CH_LAYOUT_STEREO;    //输入音频的channel layout
    codec_ctx->channels = 2;                            //输入音频 channel 个数
    codec_ctx->sample_rate = 44100;                     //输入音频的采样率
    codec_ctx->bit_rate = 0; //AAC_LC: 128K, AAC HE: 64K, AAC HE V2: 32K
    codec_ctx->profile = FF_PROFILE_AAC_HE_V2; //阅读 ffmpeg 代码

设置编码的frame的相关参数

//set parameters
    frame->nb_samples     = 512;                //单通道一个音频帧的采样数
    frame->format         = AV_SAMPLE_FMT_S16;  //每个采样的大小
    frame->channel_layout = AV_CH_LAYOUT_STEREO; //channel layout

整个代码:

#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
 extern "C"{
    
    
    #include <libavcodec/avcodec.h>
    #include <libavutil/channel_layout.h>
    #include <libavutil/common.h>
    #include <libavutil/frame.h>
    #include <libavutil/samplefmt.h>
 }

   

 
/* check that a given sample format is supported by the encoder */
static int check_sample_fmt(const AVCodec *codec, enum AVSampleFormat sample_fmt)
{
    const enum AVSampleFormat *p = codec->sample_fmts;
 
    while (*p != AV_SAMPLE_FMT_NONE) {
        if (*p == sample_fmt)
            return 1;
        p++;
    }
    return 0;
}
 
/* just pick the highest supported samplerate */
static int select_sample_rate(const AVCodec *codec)
{
    const int *p;
    int best_samplerate = 0;
 
    if (!codec->supported_samplerates)
        return 44100;
 
    p = codec->supported_samplerates;
    while (*p) {
        if (!best_samplerate || abs(44100 - *p) < abs(44100 - best_samplerate))
            best_samplerate = *p;
        p++;
    }
    return best_samplerate;
}
 
/* select layout with the highest channel count */
static int select_channel_layout(const AVCodec *codec, AVChannelLayout *dst){

    const AVChannelLayout *p, *best_ch_layout;
    int best_nb_channels   = 0;
 
    if (!codec->ch_layouts){
        AVChannelLayout src = (AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO;
        return av_channel_layout_copy(dst,&src);
    }
      
 
    p = codec->ch_layouts;
    while (p->nb_channels) {
        int nb_channels = p->nb_channels;
 
        if (nb_channels > best_nb_channels) {
            best_ch_layout   = p;
            best_nb_channels = nb_channels;
        }
        p++;
    }
    return av_channel_layout_copy(dst, best_ch_layout);
}
 
static void encode(AVCodecContext *ctx, AVFrame *frame, AVPacket *pkt,
                   FILE *output)
{
    int ret;
 
    /* send the frame for encoding */
    ret = avcodec_send_frame(ctx, frame);
    if (ret < 0) {
        fprintf(stderr, "Error sending the frame to the encoder\n");
        exit(1);
    }
 
    /* read all the available output packets (in general there may be any
     * number of them */
    while (ret >= 0) {
        ret = avcodec_receive_packet(ctx, pkt);
        if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)
            return;
        else if (ret < 0) {
            fprintf(stderr, "Error encoding audio frame\n");
            exit(1);
        }
 
        fwrite(pkt->data, 1, pkt->size, output);
        av_packet_unref(pkt);
    }
}
 
int main(int argc, char **argv)
{
    // 对应文件的编码数据
    const char *filename;

    // 编码器
    const AVCodec *codec;

    // 编码器上下文
    AVCodecContext *c= NULL;

    // 保存未曾解码的数据
    AVFrame *frame;
    // 对应的保存数据
    AVPacket *pkt;
    int i, j, k, ret;
    FILE *f;
    uint16_t *samples;
    float t, tincr;
 
    if (argc <= 1) {
        fprintf(stderr, "Usage: %s <output file>\n", argv[0]);
        return 0;
    }
    // 获得输出文件
    filename = argv[1];
 
    // 找到对应的编码器
    codec = avcodec_find_encoder(AV_CODEC_ID_MP2);
    if (!codec) {
        fprintf(stderr, "Codec not found\n");
        exit(1);
    }
    // 使用默认值设置编码器的内容数据
    c = avcodec_alloc_context3(codec);
    if (!c) {
        fprintf(stderr, "Could not allocate audio codec context\n");
        exit(1);
    }
 
    // 设置编码器的相关信息
    // 设置编码器的比特率
    c->bit_rate = 64000;
 
    // /采样的数据类型
    c->sample_fmt = AV_SAMPLE_FMT_S16;
    if (!check_sample_fmt(codec, c->sample_fmt)) {
        fprintf(stderr, "Encoder does not support sample format %s",
                av_get_sample_fmt_name(c->sample_fmt));
        exit(1);
    }
 
    // 对应的采样频率
    c->sample_rate    = select_sample_rate(codec);
    // 设置对应布局
    ret = select_channel_layout(codec, &c->ch_layout);
    if (ret < 0)
        exit(1);
 
    // 打开对应的编码器
    if (avcodec_open2(c, codec, NULL) < 0) {
        fprintf(stderr, "Could not open codec\n");
        exit(1);
    }
 
    f = fopen(filename, "wb");
    if (!f) {
        fprintf(stderr, "Could not open %s\n", filename);
        exit(1);
    }
 
    /* packet for holding encoded output */
    pkt = av_packet_alloc();
    if (!pkt) {
        fprintf(stderr, "could not allocate the packet\n");
        exit(1);
    }
 
    /* frame containing input raw audio */
    frame = av_frame_alloc();
    if (!frame) {
        fprintf(stderr, "Could not allocate audio frame\n");
        exit(1);
    }
    // 设置单通道数据采样大小
    frame->nb_samples     = c->frame_size;
    // 数据采样的大小
    frame->format         = c->sample_fmt;
    // 设置对用的通道大小
    ret = av_channel_layout_copy(&frame->ch_layout, &c->ch_layout);
    if (ret < 0)
        exit(1);
 
    /* 设置对应数据的缓冲区 */
    ret = av_frame_get_buffer(frame, 0);
    if (ret < 0) {
        fprintf(stderr, "Could not allocate audio data buffers\n");
        exit(1);
    }
 
    /* encode a single tone sound */
    t = 0;
    tincr = 2 * M_PI * 440.0 / c->sample_rate;
    for (i = 0; i < 200; i++) {
        /* make sure the frame is writable -- makes a copy if the encoder
         * kept a reference internally */
        ret = av_frame_make_writable(frame);
        if (ret < 0)
            exit(1);
        samples = (uint16_t*)frame->data[0];
 
        for (j = 0; j < c->frame_size; j++) {
            samples[2*j] = (int)(sin(t) * 10000);
 
            for (k = 1; k < c->ch_layout.nb_channels; k++)
                samples[2*j + k] = samples[2*j];
            t += tincr;
        }
        encode(c, frame, pkt, f);
    }
 
    /* flush the encoder */
    encode(c, NULL, pkt, f);
 
    fclose(f);
 
    av_frame_free(&frame);
    av_packet_free(&pkt);
    avcodec_free_context(&c);
 
    return 0;
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

docker k8s

Docker docker到底与一般的虚拟机有什么不同呢&#xff1f; 我们知道一般的linux系统即GNU/Linux系统包括两个部分&#xff0c;linux系统内核GNU提供的大量自由软件&#xff0c;而centos就是众多GNU/Linux系统中的一个。 虚拟机会在宿主机上虚拟出一个完整的操作系统与宿主机完…

数智领航 信创强基 | GBASE南大通用携手金仕达共助金融用户合规风控

GBASE南大通用董事长丁明峰先生应邀出席大会并在主论坛发表题为《去全球化背景下的中国数据库发展策略》的主题分享。 技术的迭代发展是经济增长、产业升级的核心动力。纵观近现代社会史&#xff0c;信息技术和通信技术的迅猛发展&#xff0c;帮助人类实现了PC互联网到移动互联…

MyBatis全篇

文章目录 MyBatis特性下载持久化层技术对比 搭建MyBatis创建maven工程创建MyBatis的核心配置文件创建mapper接口创建MyBatis的映射文件测试功能加入log4j日志功能加入log4j的配置文件 核心配置文件的完善与详解MyBatis的增删改查测试功能 MyBatis获取参数值在IDEA中设置中配置文…

Java遍历集合方法分析(实现原理、算法性能、适用场合)

Java遍历集合方法分析&#xff08;实现原理、算法性能、适用场合&#xff09; 概述 java语言中&#xff0c;提供了一套数据集合框架&#xff0c;其中定义了一些诸如List、Set等抽象数据类型&#xff0c;每个抽象数据类型的各个具体实现&#xff0c;底层又采用了不同的实现方式…

Web3时代来临:你准备好了吗?

如果你正在浏览本文&#xff0c;那么很可能你已经是Web3时代的一部分了&#xff0c;或者至少是将要成为其中的一员。因为Web3时代即将来临&#xff0c;它将彻底改变我们对互联网的认识和使用方式。 那么&#xff0c;什么是Web3时代呢&#xff1f;简单来说&#xff0c;它是指基于…

Kubernetes集群故障排查—审计

Kubernetes 审计&#xff08;Auditing&#xff09; 功能提供了与安全相关的、按时间顺序排列的记录集&#xff0c; 记录每个用户、使用 Kubernetes API 的应用以及控制面自身引发的活动。 审计功能使得集群管理员能够回答以下问题&#xff1a; 发生了什么&#xff1f;什么时候…

【微信小程序-uniapp】CustomPickerMul 自定义多选选择器组件

1. 效果图 2. 组件完整代码 <template><view class="custom-picker-mul"><view :class&#

MySQL(十):MySQL语法-进阶

MySQL语法-进阶 数据类型Text 类型Number 类型Date 类型 ASALTER TABLEconcat、group_concatSQL注入阻止SQL注入方案一方案二方案三 HAVING 子句临时表正则表达式获取服务器元数据事务导出数据导出数据导出表作为原始数导出SQL格式的数据 导入数据解决无法导入问题使用 LOAD DA…

西安---高时空分辨率、高精度一体化预测技术之风、光、水能源自动化预测技术应用

能源是国民经济发展和人民生活必须的重要物质基础。在过去的200多年里&#xff0c;建立在煤炭、石油、天然气等化石燃料基础上的能源体系极大的推动了人类社会的发展。但是人类在使用化石燃料的同时&#xff0c;也带来了严重的环境污染和生态系统破坏。近年来&#xff0c;世界各…

C语言 —— 浮点类型详解及 IEEE754 规定

【C语言趣味教程】(3) 浮点类型&#xff1a;单精度浮点数 | 双精度浮点型 | IEEE754 标准 &#x1f517; 《C语言趣味教程》&#x1f448; 猛戳订阅&#xff01;&#xff01;&#xff01; ​—— 热门专栏《维生素C语言》的重制版 —— &#x1f4ad; 写在前面&#xff1a;这是…

后端Long类型传到前端精度丢失的问题

问题出现&#xff1a;后端的Java Bean的id属性是用的Long类型对应数据库主键使用bigint类型&#xff0c;当使用JSON方式传递该数据给前端时&#xff0c;前端接收到的数据末尾会变成0。&#xff08;发生的精度丢失问题&#xff09; 问题原因&#xff1a;Java中的long能表示的范围…

谷歌黑客语法与漏洞寻找

谷歌黑客语法与漏洞寻找 一、常见的搜索引擎二、Google部分语法三、通配符四、FOFA五、Shodan六、例子&#xff1a;常见的后台地址 一、常见的搜索引擎 浏览器 浏览器是用来检索、展示以及传递Web信息资源的应用程序。 搜索引擎 所谓搜索引擎&#xff0c;就是根据用户需求与一…

SQL28 计算用户8月每天的练题数量

select day(date) as day,count(question_id) from question_practice_detail where month(date)8 and year(date)2021 group by date

谈一谈,Spring Boot 中的 starter 到底是什么 ?

1. 为什么要用Starter? 现在我们就来回忆一下&#xff0c;在还没有Spring-boot框架的时候&#xff0c;我们使用Spring 开发项目&#xff0c;如果需要某一个框架&#xff0c;例如mybatis&#xff0c;我们的步骤一般都是&#xff1a;到maven仓库去找需要引入的mybatis jar包&am…

【C++】-stack和queue的具体使用以及模拟实现(dqeue的介绍+容器适配器的介绍)

&#x1f496;作者&#xff1a;小树苗渴望变成参天大树&#x1f388; &#x1f389;作者宣言&#xff1a;认真写好每一篇博客&#x1f4a4; &#x1f38a;作者gitee:gitee✨ &#x1f49e;作者专栏&#xff1a;C语言,数据结构初阶,Linux,C 动态规划算法&#x1f384; 如 果 你 …

TCP四次挥手过程

TCP 断开连接是通过四次挥手方式。 双方都可以主动断开连接&#xff0c;断开连接后主机中的「资源」将被释放&#xff0c; 刚开始双方都处于 establised 状态&#xff0c;假如是客户端先发起关闭请求&#xff0c;过程如下图&#xff1a; 第一次挥手&#xff1a;客户端打算关闭…

【机器学习】基于卷积神经网络 CNN 的猫狗分类问题

文章目录 一、卷积神经网络的介绍1.1 什么是卷积神经网络1.2 重要层的说明1.3 应用领域二、 软件、环境配置2.1 安装Anaconda2.2 环境准备 三、猫狗分类示例3.1 图像数据预处理3.2 基准模型3.3 数据增强3.4 dropout层四、总结 一、卷积神经网络的介绍 1.1 什么是卷积神经网络 …

师承AI世界新星|7天获新加坡南洋理工大学访学邀请函

能够拜师在“人工智能10大新星”名下&#xff0c;必定可以学习到前沿技术&#xff0c;受益良多&#xff0c;本案例中的C老师无疑就是这个幸运儿。我们只用了7天时间就取得了这位AI新星导师的邀请函&#xff0c;最终C老师顺利获批CSC&#xff0c;如愿出国。 C老师背景&#xff1…

基于单片机的盲人导航智能拐杖老人防丢防摔倒发短息定位

功能介绍 以STM32单片机作为主控系统&#xff1b; OLED液晶当前实时距离&#xff0c;安全距离&#xff0c;当前经纬度信息&#xff1b;超声波检测小于设置的安全距离&#xff0c;蜂鸣器报警提示&#xff1a;低于安全距离&#xff01;超声波检测当前障碍物距离&#xff0c;GPS进…

【分布式系统案例课】查询服务设计、计数栈选型、总结

查询服务设计 数据获取路径 两个问题考虑&#xff1a; 1、老数据归档的问题。 如果所有分钟小时级的数据一直存在这个DB当中&#xff0c;那么DB的存储空间会被不断的消耗&#xff0c;性能也会不断的下降。所以一旦小时天月的数据聚合完成&#xff0c;我们就可以将一些老的原始…