FFMPEG编码实现:pcm编码为acc

news/2024/11/29 23:48:50/

 本程序流程:
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(); //初始化上下文结构体AVFormatContextAVOutputFormat* 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_S16acc->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;
}

 


http://www.ppmy.cn/news/805870.html

相关文章

java解码acc音频文件_g711a音频文件转aac格式

实现g711a音频文件转换成aac文件的控件 编译成exe可执行文件 传入两个参数,第一个为g711a格式的源文件,第二个为目标文件 readme 控制台应用程序&#xff1a;Convert2ACC 项目概述 应用程序向导已为您创建了此 Convert2ACC 应用程序。 本文件概要介绍组成 Convert2ACC 应用程…

java实现将.acc格式转化为mp3格式

最近接到一个需求&#xff0c;将腾讯云的音频.acc格式的转为mp3格式 这里用到的是jave&#xff0c; jave2&#xff08;Java音频视频编码器&#xff09;库是Java对ffmpeg的包装,它可以很方便的实现视频音频格式的转换&#xff0c;本文简单记录一下将wav格式的音频转换成mp3格式…

蓝牙音频传输格式:ACC,SBC,APTX和LDAC

因为最近接触了一些蓝牙和高品质音乐传输上的知识&#xff0c;先记录一下当前较为常用的几种音频传输格式和支持厂商。下面按照编码的码率由低到高列举。 1. SBC &#xff08;Sub-band coding&#xff0c;子带编码&#xff09; 最早的格式应该是SBC&#xff0c;SBC是A2DP&…

网页视频之ACC格式解析

H264封装成fmp4再到H5MSE播放已经告一段落&#xff0c;现在来攻关音频封装到fmp4&#xff0c;音频主要选择AAC编码。今天就研究一下AAC编码的结构。 AAC音频前面有个头为ADTS&#xff0c;后面才是AAC的音频数据。 ADTS&#xff08;Audio Data Transport Stream&#xff09;…

音视频学习(十二、AAC格式介绍)

每次都普及这些基础的时候&#xff0c;都是要转载别人的文章&#xff0c;因为我也不熟&#xff0c;也是一边学习一边记录学习的过程&#xff0c;这些基础知识都是需要补的。 转载链接&#xff1a;AAC ADTS格式分析 12.1 AAC基本介绍 AAC音频格式&#xff1a;Advanced Audio …

货仓选址----贪心1 (爱思创)

题目描述 在一条数轴上有 N 家商店&#xff0c;它们的坐标分别为 A1​∼AN​。 现在需要在数轴上建立一家货仓&#xff0c;每天清晨&#xff0c;从货仓到每家商店都要运送一车商品。 为了提高效率&#xff0c;求把货仓建在何处&#xff0c;可以使得货仓到每家商店的距离之和最小…

LinuxCP插件virtio与内核vhost

以下为LCP创建的接口对&#xff0c;VPP侧为物理接口port7&#xff0c;映射到Linux侧的为虚拟接口hostap1&#xff0c;接口hostap1作为vhost的后端存在。VPP侧接口tap1为前端的virtio接口。 vpp# show lcp itf-pair: [0] port7 tap1 hostap1 24 type tap vdp# vdp# show interf…

HTML特殊符号表示方法

个人总结&#xff0c;不便记忆&#xff0c;便于查找&#xff0c;希望帮到大家 &#xff08; &#xff09;空格符&#xff1a;&nbsp&#xff1b; &#xff08;<&#xff09;小于号: &It&#xff1b; &#xff08;>&#xff09;大于号&#xff1a; &gt&#…