ffmpeg学习之音频解码数据

这篇具有很好参考价值的文章主要介绍了ffmpeg学习之音频解码数据。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

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

ffmpeg学习之音频解码数据,FFmpeg学习,ffmpeg,学习,音视频

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

整个代码:文章来源地址https://www.toymoban.com/news/detail-593288.html

#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;
}

到了这里,关于ffmpeg学习之音频解码数据的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 音视频八股文(11)-- ffmpeg 音频重采样

    所谓的重采样,就是改变⾳频的采样率、sample format、声道数等参数,使之按照我们期望的参数输出。 为什么要重采样?当然是原有的⾳频参数不满⾜我们的需求,⽐如在FFmpeg解码⾳频的时候,不同的⾳源有不同的格式,采样率等,在解码后的数据中的这些参数也会不⼀致(最

    2024年02月04日
    浏览(102)
  • qt+ffmpeg 实现音视频播放(二)之音频播放

    通过  avformat_open_input () 打开媒体文件并分配和初始化  AVFormatContext   结构体。 函数原型如下: int avformat_open_input(AVFormatContext **ps, const char *url, AVInputFormat *fmt, AVDictionary **options); 参数说明: - `ps`:指向 `AVFormatContext` 结构体指针的指针,用于存储打开的媒体文件的信息。

    2024年04月22日
    浏览(57)
  • 【配置环境】安装Ffmpeg音视频编解码工具和搭建EasyDarwin开源流媒体服务器

    目录 一,安装Ffmpeg音视频编解码工具 1,简介 2,开发文档 3,安装部署 二,搭建EasyDarwin开源流媒体服务器 1,简介 2,主要功能特点 3,安装部署 4,效果图 三,简单测试 Ffmpeg是一套可以用来记录、转换数字音频、视频,并能将其转化为流的开源计算机程序。采用LGPL或GPL许

    2024年02月07日
    浏览(80)
  • 音视频剪辑|FFMPEG|windows10下的音视频格式转换,遮挡填充,GIF动图制作,背景音频抽取,替换

    最近对于音视频和图像的处理问题比较感兴趣,但发现很多目前需要的功能要么需要付费但不会过于麻烦,要么比较麻烦,很可能某个功能实现需要安装很多软件 例如,视频转GIF动图,该功能的实现要么使用Photoshop全家桶,要么找在线网站,或者是wps充会员,或者找其它方法

    2024年02月20日
    浏览(58)
  • ffmpeg系列学习——FFmpeg的音视频处理

    1.音视频的采样率、采样位深度和声道数 音频和视频的采样率、采样位深度和声道数是媒体文件中的重要参数,它们会直接影响到音视频的质量和文件大小。下面对它们进行详细解释: 采样率 采样率指音频每秒钟采样的次数,用赫兹(Hz)表示。采样率越高,音频的还原度越

    2024年02月04日
    浏览(63)
  • FFmpeg源码分析:avcodec_send_packet()与avcodec_receive_frame()音视频解码

    FFmpeg在libavcodec模块,旧版本提供avcodec_decode_video2()作为视频解码函数,avcodec_decode_audio4()作为音频解码函数。在FFmpeg 3.1版本新增avcodec_send_packet()与avcodec_receive_frame()作为音视频解码函数。后来,在3.4版本把avcodec_decode_video2()和avcodec_decode_audio4()标记为过时API。版本变更描述如下

    2024年02月03日
    浏览(54)
  • 音视频 ffmpeg命令提取音视频数据

    保留封装格式 提取视频 提取音频 推荐一个零声学院项目课,个人觉得老师讲得不错,分享给大家: 零声白金学习卡(含基础架构/高性能存储/golang云原生/音视频/Linux内核) https://xxetb.xet.tech/s/VsFMs

    2024年02月10日
    浏览(62)
  • 音视频 ffmpeg命令提取PCM数据

    提取PCM 推荐一个零声学院项目课,个人觉得老师讲得不错,分享给大家: 零声白金学习卡(含基础架构/高性能存储/golang云原生/音视频/Linux内核) https://xxetb.xet.tech/s/VsFMs

    2024年02月09日
    浏览(59)
  • 【音视频 ffmpeg 学习】 RTMP推流 mp4文件

    1.RTMP(实时消息传输协议)是Adobe 公司开发的一个基于TCP的应用层协议。 2.RTMP协议中基本的数据单元称为消息(Message)。 3.当RTMP协议在互联网中传输数据的时候,消息会被拆分成更小的单元,称为消息块(Chunk)。 (1). linux 环境准备 安装nginx 和 rtmp模块 下载nginx安装包 下载

    2024年02月03日
    浏览(67)
  • 【FFmpeg】ffmpeg 命令行参数 ⑤ ( 使用 ffmpeg 命令提取 音视频 数据 | 保留封装格式 | 保留编码格式 | 重新编码 )

    使用 ffmpeg 命令 从 视频数据 中 提取 音频数据 / 视频数据 保留封装格式 , 封装格式 指的就是 封装 视频数据 的 容器 ; 一个 mp4 格式的视频 , 其 封装容器 就是 mp4 容器 , 其中 封装了 h.264 格式的视频数据 和 aac 格式的 音频数据 ; 执行 命令 , 从 input.mp4 输入文件中 , 提取 音频

    2024年03月23日
    浏览(59)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包