ffmpeg編碼之PCM到AAC
阿新 • • 發佈:2019-02-12
編碼前檔案
編碼後文件
編碼過程
實現方式
extern "C" { #include <libavformat\avformat.h> #include <libswscale\swscale.h> #include <libswresample\swresample.h> } #include <iostream> using namespace std; #pragma comment(lib,"avformat.lib") #pragma comment(lib,"avcodec.lib") #pragma comment(lib,"avutil.lib") #pragma comment(lib,"swscale.lib") #pragma comment(lib,"swresample.lib") int main() { char infile[] = "16.wav"; char outfile[] = "out.aac"; //register muxer,demuters 格式 av_register_all(); //register codec avcodec_register_all(); //1 開啟音訊編碼器 AVCodec *codec = avcodec_find_encoder(AV_CODEC_ID_AAC); if (!codec) { cout << "avcodec_find_encoder error" << endl; getchar(); return -1; } //編碼器上下文 AVCodecContext *c = avcodec_alloc_context3(codec); if (!c) { cout << "avcodec_alloc_context3 error" << endl; getchar(); return -1; } //編碼器引數設定 c->bit_rate = 64000;//位元率 :每秒傳輸的位元(bit)數,位元率越高,傳輸資料速度越快 //取樣率:每秒採集的樣本數 c->sample_rate = 44100; //樣本格式和儲存方式 float, planar c->sample_fmt = AV_SAMPLE_FMT_FLTP; //音訊通道佈局 先存放左聲道,然後右聲道 c->channel_layout = AV_CH_LAYOUT_STEREO; //通道數 c->channels = 2; c->flags |= AV_CODEC_FLAG_GLOBAL_HEADER; //開啟編碼器 int ret = avcodec_open2(c,codec,NULL); if (ret < 0) { cout << "avcodec_open2 error" << endl; getchar(); return -1; } cout << "avcodec_open2 success!" << endl; //2 開啟輸出封裝的上下文 AVFormatContext *oc = NULL; avformat_alloc_output_context2(&oc,NULL,NULL,outfile); if (!oc) { cout << "avformat_alloc_output_context2 error" << endl; getchar(); return -1; } //第二個引數為空,就是根據檔案格式,自動選擇合適的編碼器 AVStream *st = avformat_new_stream(oc,NULL); st->codecpar->codec_tag = 0; avcodec_parameters_from_context(st->codecpar,c); //3,open io,write head ret = avio_open(&oc->pb,outfile,AVIO_FLAG_WRITE); if (ret < 0) { cout << "avio_open error" << endl; getchar(); return -1; } //寫檔案頭 ret = avformat_write_header(oc,NULL); //4 建立音訊重取樣上下文 SwrContext *actx = NULL; actx = swr_alloc_set_opts(actx, c->channel_layout,c->sample_fmt,c->sample_rate,//輸出格式 AV_CH_LAYOUT_STEREO,AV_SAMPLE_FMT_S16,44100,//輸入格式 0,0); if (!actx) { cout << "swr_alloc_set_opts error" << endl; getchar(); return -1; } ret = swr_init(actx); if (ret < 0) { cout << "swr_init error" << endl; getchar(); return -1; } //5 開啟輸入音訊檔案,進行重取樣 AVFrame *frame = av_frame_alloc(); frame->format = AV_SAMPLE_FMT_FLTP; frame->channels = 2; //音訊通道佈局 frame->channel_layout = AV_CH_LAYOUT_STEREO; frame->nb_samples = 1024;//一幀音訊存放的樣本數量 ret = av_frame_get_buffer(frame,0); if (ret < 0) { cout << "av_frame_get_buffer error" << endl; getchar(); return -1; } int readSize = frame->nb_samples * 2 * 2; char *pcm = new char[readSize]; FILE *fp = fopen(infile,"rb"); //開始編碼 for (;;) { int len = fread(pcm,1,readSize,fp); if (len<=0) { break; } const uint8_t *data[1]; data[0] = (uint8_t*)pcm; len = swr_convert(actx, frame->data, frame->nb_samples, data, frame->nb_samples ); if (len <= 0) { break; } AVPacket pkt; av_init_packet(&pkt); //6 音訊編碼 ret = avcodec_send_frame(c,frame); if (ret != 0) continue; ret = avcodec_receive_packet(c,&pkt); if (ret != 0) continue; //7 音訊封裝成aac檔案 pkt.stream_index = 0; pkt.pts = 0; pkt.dts = 0; ret = av_interleaved_write_frame(oc,&pkt); cout << "[" << len << "]"; } delete pcm; pcm = NULL; //寫檔案尾 av_write_trailer(oc); //關閉輸出流 avio_close(oc->pb); //清理封裝輸出上下文 avformat_free_context(oc); //關閉編碼器 avcodec_close(c); //清理編碼器上下文 avcodec_free_context(&c); cout << "======================end=========================" << endl; getchar(); return 0; }