FFMPEG编码实现:pcm编码为acc_pcm转换为acc-程序员宅基地

技术标签: FFMPEG  ffmpeg  

 本程序流程:
1、创建输出码流的上下文AVFormatContext,并初始化
2、打开输出文件:avio_open2()
3、创建新流:avformat_new_stream()   //用于保存音频流信息,一个完整的视频文件包含多个流信息:视频流、音频流、字幕流等
4、创建编码器上下文并设置编码参数
5、查找编码器并打开编码器
6、写入文件头信息:avformat_write_header()
7、打开输入文件
8、循环读取输入文件的yuv值,并进行编码;编码成功写入文件:av_write_frame()
9、对编码器中剩余数据编码
10、写入文件尾信息:av_write_trailer()
11、释放资源

音频编码流程和视频编码大致相同,部分解析可查看FFMPEG编码实现:将YUV文件编码为H264

/*
* 编码 pcm->acc
*/
#include <iostream>
#include <cstdio>
using namespace std;
extern "C"
{
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libavutil/opt.h>
//#include <libswresample/swresample.h> //音频重采样库
}a
const char* infile = "out.pcm";
const char* outfile = "out.aac";
int audiocount = 0;

int encodec_one_frame_audio(AVFormatContext *ctx, AVCodecContext *codec_ctx, AVPacket pkt, AVFrame *frame)
{
    int ret = 0;
    if (ret = avcodec_send_frame(codec_ctx, frame) != 0)
    {
        cout << "send audio packet to decodec error" << endl;
        return -1; 
    }
    while(ret >= 0)
    {
        ret = avcodec_receive_packet(codec_ctx, &pkt);
        if (ret == 0)
        {
            //int audio_buffersize = av_samples_get_buffer_size(NULL, codec_ctx->channels, codec_ctx->frame_size, AV_SAMPLE_FMT_S16P, 1); //获取音频数据大小
            cout << "channels = " << codec_ctx->channels << "rate = " << codec_ctx->sample_rate  << "sample_fmt = " << codec_ctx->sample_fmt << endl; //输出音频的通道数、采样率和采样格式(这里输出8,为AV_SAMPLE_FMT_FLTP)
            if(av_write_frame(ctx, &pkt) < 0)
            {
                cout << "write error" << endl;
                return -4;//写入文件失败,可选择退出程序
            }
            audiocount++; //计数,输出看写入的第几个数据包
            cout << "write pcm one frame succeed, this is " << audiocount << endl;
        }
        else if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)
        {
            cout << "receive audio frame  error, need again" << endl;
            return -2; //接收到的数据无效 需要重新读入
        }
        else
        {
            cout << "avcodec_receive_frame audio error  code:" << ret << endl;
            return -3; //编码错误,可选择直接退出程序
        }
    }
    return 0; //解码成功
}
int main(int argc, char** argv)
{
    AVFormatContext* afc = avformat_alloc_context(); //初始化上下文结构体AVFormatContext
    AVOutputFormat* outformate;
    outformate = av_guess_format(NULL, outfile, NULL);
    if(outformate == NULL)
    {
        cout << "outformat error" << endl;
        return -1;
    }
    afc->oformat = outformate;
    if(avio_open2(&afc->pb, outfile, AVIO_FLAG_READ_WRITE, NULL, NULL) < 0) //已读写的方式打开输出文件,赋值IO上下文pb
    {
        cout << "open outfile error" << endl;
        return -1;
    }
    AVStream *newstream = avformat_new_stream(afc, NULL); //创建新流,用作音频流
    if(newstream == NULL)
    {
        cout << "new stream create error" << endl;
        return -1;
    }

    AVCodec *codec =  avcodec_find_encoder(acc->codec_id); //这里也可以使用avcodec_find_encoder_by_name("aac")
    if(codec == NULL)
    {
        cout << "open encodec error" << endl;
        return -1;
    }

    //设置编码参数
    AVCodecContext* acc = avcodec_alloc_context3(NULL);
    avcodec_parameters_to_context(acc, newstream->codecpar);//acc = newstream->codec;新版本丢弃了AVStream::codec成员,增加了codecpar成员,利用avcodec_parameters_to_context()赋值
    acc->codec_id = afc->oformat->audio_codec;
    acc->codec_type = AVMEDIA_TYPE_AUDIO; //编码器类型
    acc->sample_fmt =  AV_SAMPLE_FMT_FLTP; //音频采样格式//AV_SAMPLE_FMT_S16有些库不支持AV_SAMPLE_FMT_S16
    acc->sample_rate = 48000; //采样率
    acc->channel_layout = AV_CH_LAYOUT_STEREO; //声道布局
    acc->channels = 2; //通道数

    if (avcodec_open2(acc, codec, NULL) < 0)
    {
        cout << "open encodec error" << endl;
        return -1;
    }

    AVFrame* aframe = av_frame_alloc();
    aframe->nb_samples = acc->frame_size;
    aframe->format = acc->sample_fmt;
    int audiosize = av_samples_get_buffer_size(NULL, acc->channels, acc->frame_size, acc->sample_fmt, 1);
    uint8_t *pcmdata; //用于存放输入文件的pcm数据信息
    pcmdata = (uint8_t*)av_malloc(audiosize);

    AVPacket pkt;
    av_new_packet(&pkt, audiosize);//av_packet_init(&pkt);//(AVPacket*)av_malloc(sizeof(AVPacket));
    //写文件头信息
    avformat_write_header(afc, NULL);

    FILE* inF = fopen(infile, "rb");
    
    while (true)
    {
        if(fread(pcmdata, 1, audiosize, inF) <= 0)
        {
            if(feof(inF))
                break;
            else
            {
                cout << "read data error" << endl;
                return -1;
            }
        }
        aframe->data[0] = pcmdata;

        int re = encodec_one_frame_audio(afc, acc, pkt, aframe);
        if (re == -3 || re == -1 || re == -4)
        {
            cout << "encodec error" << endl;
            return -1;
        }
    }
    //再次编码输出解码器中的数据,否则会丢失部分数据
    int re = encodec_one_frame_audio(afc, acc, pkt, NULL);
    if (re == -3 || re == -1 || re == -4)
    {
        cout << "encodec error" << endl;
        return -1;
    }
    //写文件尾
    av_write_trailer(afc, NULL);
    //释放资源
    fclose(inF);
    av_packet_unref(&pkt);
    av_frame_free(&aframe);
    avcodec_free_context(&acc);
    avformat_close_input(&afc);
    return 0;
}

 

 
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/JHXXH/article/details/108590001

智能推荐

基于Java ssm mysql的高校跳蚤市场管理系统的设计与实现_基于java的校园跳蚤市场系统-程序员宅基地

文章浏览阅读260次。随着信息技术的发展和网络购物的普及,人们逐渐从实体店购物转向网上购物。在物质更替迅速的当今社会,大学生产生的闲置物品逐渐增多,但目前的处理方式仍停留在传统跳蚤市场。为了提高大学生处理闲置物品的便捷性、实现资源循环利用,同时倡导环保节约理念,开发一款专门针对大学生的二手物品交易系统显得非常必要。系统采用MVC开发框架、B/S架构结合SSM框架技术进行系统构建。为保证数据持久化,选择MySQL关系型数据库保存数据。前端使用HTML5、CSS和jQuery等技术进行页面展示。_基于java的校园跳蚤市场系统

h5 在ios端常见bug_ios h5 文字偏移显示不完整-程序员宅基地

文章浏览阅读562次。记录一些h5页面在ios端呢遇见的bugios上日期问题在ios上 日期不能识别 "2018- 09 - 09"这样格式的识别不了,所以需要转换一下 const data1 = '2018- 09 - 09' function clear(str) { str = str.replace(/-/g, "/");//取消字符串中出现的所有逗号 str = str.replace(/\s/g, "") //去掉字符串内出现的所有空格 return str; } con_ios h5 文字偏移显示不完整

chromebook刷机_Chromebook辅助功能指南-程序员宅基地

文章浏览阅读1.2k次。chromebook刷机If you have trouble reading text, seeing specific colors, or making out things on the screen, Chrome OS has accessibility features bursting at the seams designed to help you. You can manag..._hp chromebook c640 刷win

html标签特效代码大全(让你制作漂亮的页面效果)_html代码特效-程序员宅基地

文章浏览阅读1.8w次,点赞11次,收藏90次。html标签特效代码大全(让你制作漂亮的页面效果) (2012-03-19 19:11:33)转载http://blog.sina.com.cn/s/blog_780a9427010123yh.html▼标签: 杂谈 分类: CSS 跑马灯...普通卷动...滑动...预设卷动...来回卷动...向下卷动...向上卷动向右卷动_html代码特效

chatgpt赋能python:Python宏替换:让你的代码更高效_python 宏替换-程序员宅基地

文章浏览阅读156次。Python宏替换是一种代码生成技术,它可以通过在代码中使用宏定义,将编写代码的过程自动化。Python宏替换的思想来自于C语言中的宏替换。Python宏替换可以在代码中进行文本替换,实现代码的自动生成。Python宏替换通常用于定义一些常见的代码模式、复杂的重复代码、甚至是整个类和对象。本文由chatgpt生成,文章没有在chatgpt生成的基础上进行任何的修改。以上只是chatgpt能力的冰山一角。作为通用的Aigc大模型,只是展现它原本的实力。对于颠覆工作方式的ChatGPT。_python 宏替换

分享63个广告代码JS特效,总有一款适合您-程序员宅基地

文章浏览阅读834次,点赞20次,收藏21次。jquery实现鼠标移动到图片上显示大图广告代码。jquery实现led广告牌旋转系统图片切换效果。全屏图片广告随机漂浮可点击关闭jQuery特效。jquery实现网页顶部定时广告,支持关闭隐藏。jQuery仿QQ空间鼠标感应图片滚动预览代码。jQuery关闭后不再显示的全屏图片广告代码。jQuery-实现仿QQ空间鼠标感应图片滚动。分享63个广告代码JS特效,总有一款适合您。简洁易用的jQuery左右对称浮动广告代码。jQuery图文左右滚动代码(箭头控制)图片无缝滚动插件上下左右图片无缝滚动代码。

随便推点

工控机AllInOne——篇2,pve下安装windows10_pve安装win10-程序员宅基地

文章浏览阅读2.8k次。加载virtio中的amd64中的驱动,这样才能打上网卡驱动,之后遵循正常的win10安装过程即可,进入系统后还是没网卡的,右键我的电脑-管理,在设备管理里更新驱动,选择virtio的本地驱动,这时候才能更新驱动连上网络,到此,win10安装基本完成。_pve安装win10

Android7.0以上如何获取头像(拍照或者从相册中选择)_android 头像采集-程序员宅基地

文章浏览阅读1.3k次。大概的流程动态权限管理 创建布局文件,这里不多说了 拍照的实现 2.1创建存放图片的文件夹 2.2将文件夹路径转换为uri 2.3隐式启动相机的Activity,uri作为intent的一个参数. 2.4拍照结束后,执行onActivityResult(…)获得图片 相册选取图片 3.1启动相册Activity 3.2选择结束后,执行onActivityResult(…)获得..._android 头像采集

今天注册了-程序员宅基地

文章浏览阅读102次。以后多来看看~

openlayers学习(八)加载天地图各种底图_openlayer引入天地图所有底图-程序员宅基地

文章浏览阅读3k次,点赞2次,收藏10次。加载天地图的各种在线地图资源天地图在线地图资源地址:http://lbs.tianditu.gov.cn/server/MapService.html1、初始化地图var rootLayer = new ol.layer.Tile({ source: new ol.source.XYZ({ url: 'http://mt2.google.cn/vt/lyrs=y&hl=zh-CN&gl=CN&src=app&x={x}&y={_openlayer引入天地图所有底图

Linux重签名工具程序及命令行重签ipa文档_ausign-程序员宅基地

文章浏览阅读3.6k次。au-signer推出了Linux系统命令行重签名ipa的程序适用于自动化签名的实现au-signer工具官网http://sign.applicationloader.net/命令行签名包括了用户登录管理、重签名ipa,应用管理,时间锁管理4部分功能!下面一一介绍1、用户登录管理登录命名行,先创建账号或者登录..._ausign

CorelDRAW是什么软件?CDR2024版本如何下载-程序员宅基地

文章浏览阅读465次,点赞19次,收藏13次。CorelDRAW Graphics Suite适合初学者。对于初学者来说,CorelDRAW提供了友好的界面和易于理解的操作方式。虽然它拥有许多高级功能和工具,但用户可以从基础开始,逐步学习并掌握这些功能。此外,CorelDRAW还提供了大量的教程和在线资源,帮助初学者快速上手并熟悉软件的使用。因此,即使是没有任何图形设计经验的初学者,也可以通过CorelDRAW Graphics Suite来学习和提升自己的图形设计能力。

推荐文章

热门文章

相关标签