FFmpeg学习—ffmpeg 利用 swr_convert 函数将AV_SAMPLE_FMT_S16 转 AV_SAMPLE_FMT_FLTP
来源:互联网 发布:淘宝店铺的经营类目 编辑:程序博客网 时间:2024/05/22 08:24
在Android 平台下利用AudioRecord 录制音频数据时基于 ENCODING_PCM_16BIT 进行采样,然后在利用ffmpeg 进行编码成aac格式的音频文件,由于最新ffmpeg 库的sample_fmt必须以AV_SAMPLE_FMT_FLTP这种方式进行存储,而ENCODING_PCM_16BIT 是AV_SAMPLE_FMT_S16格式的。如果是单声道的话两者区别不大,都可以存在AVFrame->data[0] 里面,只是AV_SAMPLE_FMT_FLTP是以浮点数的方式存储,后者是以有符号整形16位存贮的。如果是双声道的话二者的区别就比较大了。AV_SAMPLE_FMT_S16的存贮方式如下图:
AV_SAMPLE_FMT_FLTP的存储方式如下图:
AV_SAMPLE_FMT_S16是非平坦的,左右声道以LRLR....的方式连续的存在一个数组里面,AV_SAMPLE_FMT_FLTP是平坦的存贮方式,左右声道是分开存在两个数组里面的。
如何将Android 以 CHANNEL_IN_STEREO(双声道) ENCODING_PCM_16BIT (AV_SAMPLE_FMT_S16) 录制方式用ffmpeg 用AV_SAMPLE_FMT_FLTP编码为aac音频文件呢?其实ffmepg 已经提供了这样的接口,就是swr_convert 函数,转换方式如下:
在android 里面初始化AudioRecord:
minBufferSize = 4096; audioRecord = new AudioRecord(MediaRecorder.AudioSource.MIC, sampleRate, AudioFormat.CHANNEL_IN_STEREO, AudioFormat.ENCODING_PCM_16BIT, minBufferSize);
其中minBufferSize 要设置为4096,因为ffmpeg 的frame_size 默认为1024,所以一次采样次数至少为1024次,由于一次采集两个声道,每个声道占两个字节,采集1024次就是1024*2*2=4096个字节,我开始做的时候没注意这个就一直不对。
swr_convert 函数的定义如下:
int swr_convert(struct SwrContext *s, uint8_t **out, int out_count, const uint8_t **in , int in_count);
第一个参数是SwrContext 结构体,第二个参数是输出数据保存的地方,第三个参数是out的大小,第四个参数是输入数据就是要待转换的数据,第五个参数是输入数据采样的个数。
SwrContext 的初始化:
SwrContext *swr;
swr = swr_alloc();av_opt_set_int(swr, "in_channel_layout", AV_CH_LAYOUT_STEREO, 0); av_opt_set_int(swr, "out_channel_layout", AV_CH_LAYOUT_STEREO, 0); av_opt_set_int(swr, "in_sample_rate", 16000, 0); av_opt_set_int(swr, "out_sample_rate", 16000, 0); av_opt_set_sample_fmt(swr, "in_sample_fmt", AV_SAMPLE_FMT_S16, 0); av_opt_set_sample_fmt(swr, "out_sample_fmt", AV_SAMPLE_FMT_FLTP, 0); swr_init(swr);
定义输出数据保存的数组:
uint8_t *outs[2]; outs[0]=(uint8_t *)malloc(len);//len 为4096 outs[1]=(uint8_t *)malloc(len);
进行转换
uint8_t* srcBuf = (uint8_t*) (*env)->GetByteArrayElements(env, pcmData, 0);//pcmData是android 传下来的的pcm 数据,为4096个字节,1024次采样。int count=swr_convert(swr,&outs,len*4,&srcBuf,len/4);//len 为4096audioFrame->data[0] =(uint8_t*)outs[0];//audioFrame 是VFrame audioFrame->data[1] =(uint8_t*)outs[1];
如果是单声道转的话
AudioRecord 的初始化如下:
minBufferSize = 2048;//1024*2 audioRecord = new AudioRecord(MediaRecorder.AudioSource.MIC, sampleRate, AudioFormat.CHANNEL_IN_STEREO, AudioFormat.ENCODING_PCM_16BIT, minBufferSize);
SwrContext 的初始化:
SwrContext *swr;
swr = swr_alloc();av_opt_set_int(swr, "in_channel_layout", AV_CH_LAYOUT_MONO, 0); av_opt_set_int(swr, "out_channel_layout", AV_CH_LAYOUT_MONO, 0); av_opt_set_int(swr, "in_sample_rate", 16000, 0); av_opt_set_int(swr, "out_sample_rate", 16000, 0); av_opt_set_sample_fmt(swr, "in_sample_fmt", AV_SAMPLE_FMT_S16, 0); av_opt_set_sample_fmt(swr, "out_sample_fmt", AV_SAMPLE_FMT_FLTP, 0); swr_init(swr);定义输出数据保存的数组:
uint8_t *outs[1]; outs[0]=(uint8_t *)malloc(len*2);//len 为2048
进行转换
uint8_t* srcBuf = (uint8_t*) (*env)->GetByteArrayElements(env, pcmData, 0);//pcmData是android 传下来的的pcm 数据,为2048个字节,1024次采样。int count=swr_convert(swr,&outs,len*2,&srcBuf,len/2);//len 为2048audioFrame->data[0] =(uint8_t*)outs[0];//audioFrame 是VFrame
转换例子
https://github.com/XIAIBIANCHENG/OggRecord/tree/master
- FFmpeg学习—ffmpeg 利用 swr_convert 函数将AV_SAMPLE_FMT_S16 转 AV_SAMPLE_FMT_FLTP
- ffmpeg AV_SAMPLE_FMT_FLTP to AV_SAMPLE_FMT_S16
- ffmpeg AV_SAMPLE_FMT_FLTP to AV_SAMPLE_FMT_S16
- ffmpeg avcodec_decode_audio4解码 swr_convert 转换为AV_SAMPLE_FMT_S16格式
- FFmpeg学习—解决ffmpeg 进行Audio 编码 采用AV_SAMPLE_FMT_S16 格式报 Input contains NaN/+-Inf 错误的问题
- ffmpeg音频转码,采用swr_convert重取样
- ffmpeg音频转码,采用swr_convert重取样
- ffmpeg音频转码,采用swr_convert重取样
- FFmpeg学习—android 利用ffmpeg 录制ogg格式音频文件
- convert sample rate from AV_SAMPLE_FMT_FLTP to AV_SAMPLE_FMT_S16
- swr_convert音频重采样成AV_SAMPLE_FMT_FLTP
- java利用ffmpeg将amr、caf转mp3格式
- 最新(2.44)FFmpeg音频播放 ----- 关键点swr_convert
- 最新(2.44)FFmpeg音频播放 ----- 关键点swr_convert
- ffmpeg重采样中swr_convert和swr_get_out_samples的用法
- FFmpeg swr_convert 音频重采样,编码的噪音问题
- 利用ffmpeg将H264解码为RGB
- 利用ffmpeg将H264解码为RGB
- css样式学习3
- replace方法全部替换的写法
- 项目 功能: > 注册 > 登录
- Spring核心概念
- 【JSOI2015】bzoj4484 最小表示
- FFmpeg学习—ffmpeg 利用 swr_convert 函数将AV_SAMPLE_FMT_S16 转 AV_SAMPLE_FMT_FLTP
- 程序性能优化(包括数据库优化、服务器优化等)
- css样式学习4
- 数据科学入门,使用 xgboost 初试 kaggle
- 清除浮动的四种方法(详解)
- 深入理解Java的接口和抽象类
- latex中插入伪代码
- a+bproblem(0+EOF)
- 1001 数组中和等于K的数对