一:关于音频分片的问题
enum AVSampleFormat {
AV_SAMPLE_FMT_NONE = -1,
AV_SAMPLE_FMT_U8, ///< unsigned 8 bits
AV_SAMPLE_FMT_S16, ///< signed 16 bits
AV_SAMPLE_FMT_S32, ///< signed 32 bits
AV_SAMPLE_FMT_FLT, ///< float
AV_SAMPLE_FMT_DBL, ///< double
AV_SAMPLE_FMT_U8P, ///< unsigned 8 bits, planar
AV_SAMPLE_FMT_S16P, ///< signed 16 bits, planar
AV_SAMPLE_FMT_S32P, ///< signed 32 bits, planar
AV_SAMPLE_FMT_FLTP, ///< float, planar
AV_SAMPLE_FMT_DBLP, ///< double, planar
AV_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:无论是不是分片的数据总量是相同的.
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:
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;