ffmpeg关于音频的总结(一)
来源:互联网 发布:淘宝店铺新手上路 编辑:程序博客网 时间:2024/05/16 10:53
一:关于音频分片的问题
enum AVSampleFormat {AV_SAMPLE_FMT_NONE = -1,AV_SAMPLE_FMT_U8, ///< unsigned 8 bitsAV_SAMPLE_FMT_S16, ///< signed 16 bitsAV_SAMPLE_FMT_S32, ///< signed 32 bitsAV_SAMPLE_FMT_FLT, ///< floatAV_SAMPLE_FMT_DBL, ///< doubleAV_SAMPLE_FMT_U8P, ///< unsigned 8 bits, planarAV_SAMPLE_FMT_S16P, ///< signed 16 bits, planarAV_SAMPLE_FMT_S32P, ///< signed 32 bits, planarAV_SAMPLE_FMT_FLTP, ///< float, planarAV_SAMPLE_FMT_DBLP, ///< double, planarAV_SAMPLE_FMT_NB ///< Number of sample formats. DO NOT USE if linking dynamically};int sample_size = av_get_bytes_per_sample(sample_fmt);int planar = av_sample_fmt_is_planar(sample_fmt);//上面带P的都是分片的,和不分片的区别是:看下ffmpeg源代码line_size = planar ? FFALIGN(nb_samples * sample_size,align) :FFALIGN(nb_samples * sample_size * nb_channels, align);if (linesize){*linesize = line_size;}return planar ? line_size * nb_channels : line_size;1:无论是不是分片的数据总量是相同的.
2:分片的存储在内存中linesize如果两声道则左右分开占用linesize[0]和linesize[1].
3:不是分片的存储在内存中两声道不分开,左右左右....这样存储,只占用linesize[0].
二:音频信息
如果音频,样本:s16;采样率:44100;声道:2。
av_get_bytes_per_sample(s16) == 2;
1:假设从麦克风或者文件读出来的通过av_read_frame得到一个数据总量是88200个字节。
这个88200个字节是和帧无关的数据量。
2:如果接下来需要将这些数据编码成:
ffmpeg源码如下,AAC格式nb_samples和frame_size是1024,其他如下:
switch (id) {case AV_CODEC_ID_ADPCM_ADX: return 32;case AV_CODEC_ID_ADPCM_IMA_QT: return 64;case AV_CODEC_ID_ADPCM_EA_XAS: return 128;case AV_CODEC_ID_AMR_NB:case AV_CODEC_ID_EVRC:case AV_CODEC_ID_GSM:case AV_CODEC_ID_QCELP:case AV_CODEC_ID_RA_288: return 160;case AV_CODEC_ID_AMR_WB:case AV_CODEC_ID_GSM_MS: return 320;case AV_CODEC_ID_MP1: return 384;case AV_CODEC_ID_ATRAC1: return 512;case AV_CODEC_ID_ATRAC3: return 1024 * framecount;case AV_CODEC_ID_ATRAC3P: return 2048;case AV_CODEC_ID_MP2:case AV_CODEC_ID_MUSEPACK7: return 1152;case AV_CODEC_ID_AC3: return 1536;}1) AAC:
nb_samples和frame_size = 1024
一帧数据量:1024*2*av_get_bytes_per_sample(s16) = 4096个字节。
会编码:88200/(1024*2*av_get_bytes_per_sample(s16)) = 21.5帧数据
2) MP3:
nb_samples和frame_size = 1152
一帧数据量:1152*2*av_get_bytes_per_sample(s16) = 4608个字节。
MP3:则会编码:88200/(1152*2*av_get_bytes_per_sample(s16)) = 19.1帧数据
无论要编码成AAC还MP3都需要用到ffmpeg的fifo或者AVAudioFifo做数据缓冲。
3:持续时间方面
1) AAC
音频帧的播放时间=一个AAC帧对应的采样样本的个数/采样频率(单位为s)
一帧 1024个 sample。采样率 Samplerate 44100KHz,每秒44100个sample, 所以根据公式 音频帧的播放时间=一个AAC帧对应的采样样本的个数/采样频率
当前AAC一帧的播放时间是= 1024*1000000/44100= 22.2ms(单位为ms)
2) MP3
mp3 每帧均为1152个字节, 则:
frame_duration = 1152 * 1000000 / sample_rate
例如:sample_rate = 44100HZ时,计算出的时长为26.122ms,这就是经常听到的mp3每帧播放时间固定为26ms的由来
三:关于avcodec_fill_audio_frame
看下面ffmpeg源码:
AVFrame的nb_samples需要算出一帧数据,然后和buf做比较是否满足。剩下在这个函数里面没什么用,
int avcodec_fill_audio_frame(AVFrame *frame, int nb_channels,enum AVSampleFormat sample_fmt, const uint8_t *buf,int buf_size, int align){int ch, planar, needed_size, ret = 0;needed_size = av_samples_get_buffer_size(NULL, nb_channels,frame->nb_samples, sample_fmt,align);if (buf_size < needed_size)return AVERROR(EINVAL);planar = av_sample_fmt_is_planar(sample_fmt);if (planar && nb_channels > AV_NUM_DATA_POINTERS) {if (!(frame->extended_data = av_mallocz_array(nb_channels,sizeof(*frame->extended_data))))return AVERROR(ENOMEM);} else {frame->extended_data = frame->data;}if ((ret = av_samples_fill_arrays(frame->extended_data, &frame->linesize[0],(uint8_t *)(intptr_t)buf, nb_channels, frame->nb_samples,sample_fmt, align)) < 0) {if (frame->extended_data != frame->data)av_freep(&frame->extended_data);return ret;}if (frame->extended_data != frame->data) {for (ch = 0; ch < AV_NUM_DATA_POINTERS; ch++)frame->data[ch] = frame->extended_data[ch];}return ret;}//这里关于分片的问题在上面已经讲过了。int av_samples_get_buffer_size(int *linesize, int nb_channels, int nb_samples,enum AVSampleFormat sample_fmt, int align){int line_size;int sample_size = av_get_bytes_per_sample(sample_fmt);int planar = av_sample_fmt_is_planar(sample_fmt);/* validate parameter ranges */if (!sample_size || nb_samples <= 0 || nb_channels <= 0)return AVERROR(EINVAL);/* auto-select alignment if not specified */if (!align) {if (nb_samples > INT_MAX - 31)return AVERROR(EINVAL);align = 1;nb_samples = FFALIGN(nb_samples, 32);}/* check for integer overflow */if (nb_channels > INT_MAX / align ||(int64_t)nb_channels * nb_samples > (INT_MAX - (align * nb_channels)) / sample_size)return AVERROR(EINVAL);line_size = planar ? FFALIGN(nb_samples * sample_size, align) :FFALIGN(nb_samples * sample_size * nb_channels, align);if (linesize)*linesize = line_size;return planar ? line_size * nb_channels : line_size;}
//开始转换/** @param s allocated Swr context, with parameters set* @param out output buffers, only the first one need be set in case of packed audio* @param out_count amount of space available for output in samples per channel* @param in input buffers, only the first one need to be set in case of packed audio* @param in_count number of input samples available in one channel** @return number of samples output per channel, negative value on error*/这里看到:out_count是为每一个声道resample后准备的buf大小in_count是输入的每一个声道的buf长度,如果是摄像头采集的用av_read_frame得到的packet.size/channel.//开始转换(如果是分片的关于in_size需要测试后改正,或本代码可以适应)ret = swr_convert(swrcontext, pOutputFrame->data,buf_size_out/Channel_out,(const uint8_t**)pInputFrame->data,buf_ActualLen_in/Channel_in);//得到resample后的buf大小(如果是分片的关于in_size需要测试后改正,或本代码可以适应)int outsize = ret * Channel_out;
交流请加QQ群:62054820
QQ:379969650.
0 0
- ffmpeg关于音频的总结(一)
- 关于ffmpeg 的总结
- [总结]FFMPEG视音频编解码零基础学习方法一
- 关于ffmpeg 的命令总结
- 关于ffmpeg 的命令总结
- FFmpeg音频转码总结
- flv封装ffmpeg编码的视音频笔记(一)
- 关于ffmpeg工具的使用总结
- ffmpeg 解码音频的方法
- ffmpeg 解码音频的方法
- ffmpeg的音频解码部分
- 基于FFMPEG的音频编码器
- 基于FFMPEG的音频解码器
- FFmpeg教程(一) 视音频基础知识
- FFMPEG学习【libavutil】:音频相关(一)
- ffmpeg提取音频播放器总结
- ffmpeg提取音频播放器总结
- ffmpeg提取音频播放器总结
- 最简单的基于FFmpeg的AVfilter例子(水印叠加)
- HDU——2066一个人的旅行(优先队列SPFA水题)
- 动态改变ListView布局
- MBProgressHUD
- 依赖名称不是类型
- ffmpeg关于音频的总结(一)
- qtestlib去掉console
- StartUml 官网下载地址
- 免费超大量邮件发送服务Amazon SES和Mailgun提供SMTP和API支持
- Java中的事件处理与异常处理机制-解析
- Weblogic Jms简单使用
- 用户空间和内核空间通讯之【Netlink 上】
- js 全局变量 局部变量 隐式声明 显式声明,作用域
- OSCache缓存过滤器