精简但精确的PCM编码为AAC解析
来源:互联网 发布:顶尖恢复软件注册码 编辑:程序博客网 时间:2024/05/22 08:27
核心知识:
一、输出媒体文件所需的结构体:AVOutputFormat,AVFormatContext,AVStream,AVCodec,AVCodecContext,AVFrame,AVPacket(按出现先后顺序)。
二、AVOutputFormat是输出容器(container)句柄,直接关联文件,但只有句柄远远不够,我们需要设置相关参数;AVFormatContext就是容器上下文(用avformat_alloc_context初始化),我们于其设置目标容器文件名,目标容器句柄,I/O上下文(this->pb);
三、只有上面两个,我们还是不能对相应文件进行写入操作,需要对其进行流化操作,我们用avformat_new_stream(aacFormatCtx, NULL);初始化一个空流,但这时这个Stream还是不能用!因为这是一个真正的空流!里面的数据指针和流头都还未被初始化,我们需要avformat_write_header(aacFormatCtx, NULL);这次才是真正的生成了可以用的流。
四、AVCodec这个结构体包含了一个解码器的必要参数,好在ffmpeg为我们提供了简单的接口avcodec_find_encoder,这样就可以很容易的获取一个编码器(只是相关参数!)。
五、仅仅有AvCOdec是远远不够的,如果我们想要得到一个真正的编码器,还需要在AVCodecContext设置采样率、比特率等控制音频必要的参数。至此,我们有了编码所需的一切准备,不过别急,我们还需要打开它,恰好avcodec_open2就提供了这个功能!
六、我们这时可以初始化我们的编码帧AVFrame了,编码格式和帧大小是我们要特别注意的,也是我们必须要设置的,因为这是我们确定一个桢大小的必要条件。当然我们还需要填充它,为了我们更好的控制,ffmpeg把缓冲区的控制留给了我们,但是这也正是我们应该要特别小心的地方,不要忘记在不用这个Frame的时候释放它!别相信Av_malloc,它只是malloc的一个wrapper:)
七、我们的Rtp传输需要用包,所以这时就需要把frame写为AVPacket,但是我们要先给AVPacket设置内存空间av_new_packet(&pkt, aacBufferSize);后面一个是PayLoad,不知道PayLoad是什么的回家去读幼儿园:)
八、看起来这时我们可以把包写进文件了av_write_frame(aacFormatCtx, &pkt);(有坑:)相对于av_interleaved_writ e_frame()),但是我们最重要的流序号和时间戳可不要忘了先设置好:),而且发送一个包后不要忘了清空这个包,(用的流媒体模型:))。
九、尽情地写入或发送把!
十、最后结束时可不要忘了清理战场!
av_frame_free用来释放AvFrame,我看到过好多例子,在这个之后还要av_free(Avframe->data[0]),其实完全没有必要!这个函数可以清空Avframe里面所有的动态内存!然后我们关闭aacFormatCtx的I/O口;av_write_trailer(aacFormatCtx);只是用来清空流的,一点都没有碰aacFormatCtx!所以我们需要手动释放aacFormatCtx!最后我们关闭编码器:)
至此,Good Job and enjoy it by yourself!
// EncodeToAAC.cpp : 定义控制台应用程序的入口点。//#include "stdafx.h"extern "C"{#include"libavcodec/avcodec.h"#include"libavformat/avformat.h"#include"libavdevice/avdevice.h"#include<stdlib.h>}int _tmain(int argc, _TCHAR* argv[]){av_register_all();/*pcmfile:要打开的pcm波形文件* aacStream:将要编码的流* aacFormatCtx:目标句柄上下文* aacCodecCtx:要创建的aac编码器上下文* aacCodec:aac编码器*/FILE *pcmfile = NULL;fopen_s(&pcmfile,"audio.pcm", "rb");if (!pcmfile){printf("Find PCMfile error!\n");return -1;}int aacBufferSize = 0;uint8_t *aacBuffer = NULL;AVFrame *aacFrame = NULL;AVStream *aacStream = NULL;AVOutputFormat *aacOutFmt = NULL;AVFormatContext *aacFormatCtx = NULL;AVCodecContext *aacCodecCtx = NULL;AVCodec *aacCodec = NULL;//容器流的准备aacFormatCtx = avformat_alloc_context();aacOutFmt = av_guess_format(NULL, "audio.aac", NULL);aacFormatCtx->oformat = aacOutFmt;sprintf_s(aacFormatCtx->filename, "%s", "audio.aac");if (avio_open(&aacFormatCtx->pb, "audio.aac", AVIO_FLAG_READ_WRITE)<0){printf("open file failed(get handle failed!)");return -1;}aacStream = avformat_new_stream(aacFormatCtx, NULL);avformat_write_header(aacFormatCtx, NULL);//解码器相关准备aacCodec = avcodec_find_encoder(AV_CODEC_ID_AAC);aacCodecCtx = avcodec_alloc_context3(aacCodec);aacCodecCtx->codec_type = AVMEDIA_TYPE_AUDIO;aacCodecCtx->codec = aacCodec;aacCodecCtx->time_base.den = 1;aacCodecCtx->time_base.num = 3600;aacCodecCtx->channels = 2;aacCodecCtx->channel_layout = AV_CH_LAYOUT_STEREO;aacCodecCtx->bit_rate = 192000;aacCodecCtx->sample_rate = 44100;aacCodecCtx->sample_fmt = AV_SAMPLE_FMT_S16;if (avcodec_open2(aacCodecCtx, aacCodec, NULL)<0){printf("creat this encoder erro !");return -2;}//编码帧的准备aacFrame = av_frame_alloc();aacFrame->nb_samples = aacCodecCtx->frame_size;aacFrame->format = aacCodecCtx->sample_fmt;aacBufferSize = av_samples_get_buffer_size(NULL, aacCodecCtx->channels, aacCodecCtx->frame_size, aacCodecCtx->sample_fmt, NULL);aacBuffer = (uint8_t *)av_malloc(aacBufferSize);avcodec_fill_audio_frame(aacFrame, aacCodecCtx->channels, aacCodecCtx->sample_fmt, aacBuffer, aacBufferSize, NULL);//发送包:)AVPacket pkt;av_new_packet(&pkt, aacBufferSize);for (int i = 1;; i++){fread(aacBuffer, sizeof(uint8_t), aacBufferSize, pcmfile);if (feof(pcmfile)){printf("srcfile meet end! exiting....\n");break;}aacFrame->data[0] = aacBuffer;int gotFrame;if (avcodec_encode_audio2(aacCodecCtx, &pkt, aacFrame, &gotFrame)<0){printf("encode error!!\n");break;}if (gotFrame){printf("encode success %d frame(s)\n", i);pkt.stream_index = aacStream->index;if (pkt.pts == AV_NOPTS_VALUE){pkt.pts = i * 3600;printf("encoded pkt pts: %d\n", pkt.pts);}av_write_frame(aacFormatCtx, &pkt);av_free_packet(&pkt);}}av_free_packet(&pkt);av_frame_free(&aacFrame);printf("encode all file success!\n");av_write_trailer(aacFormatCtx);avio_close(aacFormatCtx->pb);avformat_free_context(aacFormatCtx);avcodec_close(aacCodecCtx);fclose(pcmfile);return 0;}
- 精简但精确的PCM编码为AAC解析
- PCM 编码为AAC
- 如何将裸码流pcm编码为aac文件
- ffmpeg pcm码流编码为aac
- PCM音频采样数据编码为AAC的压缩编码数据
- PCM编码AAC
- 最简单的基于FFMPEG的音频编码器(PCM编码为AAC)
- 最简单的基于FFMPEG的音频编码器(PCM编码为AAC)
- 最简单的基于FFMPEG的音频编码器(PCM编码为AAC)
- ffmpeg学习十:将pcm格式的音频编码为aac格式
- 【FFmpeg学习笔记006】 PCM编码为AAC
- 【FFmpeg(2016)】PCM编码AAC
- Android PCM音频的采集和编码成AAC
- MediaCodec编译pcm为aac
- MediaCodec编译pcm为aac
- FAAC转换PCM为AAC
- MediaCodec编译pcm为aac
- ffmpeg实战教程(三)音频PCM采样为AAC,视频YUV编码为H264/HEVC
- uva-439 - HDOJ-1372-Knight Moves-翻译详解-BFS
- iOS 调用音乐播放以及视频播放器
- 我们的征途是星辰与大海(四)
- Struts2 国际化
- [Intel汇编-MASM]栈
- 精简但精确的PCM编码为AAC解析
- ResultSet.TYPE_SCROLL_SENSITIVE
- 二叉树(12)----查找两个节点最低祖先节点(或最近公共父节点等),递归和非递归
- 神奇的取反运算
- 模板编程的几点疑惑及解释
- 战争迷雾的实现
- bootstrap2.3 与 bootstrap3.3 modal嵌入表单的样式改变
- TOMCAT 8080端口被占用怎么办
- uva10313(DP完全背包)