音频数据经过解码后会被保存为,pcm数据格式。而对应的处理流程如下所示。
/**
* 查找具有匹配编解码器ID的已注册编码器.
*
* @param id AVCodecID of the requested encoder
* @return An encoder if one was found, NULL otherwise.
*/
const AVCodec *avcodec_find_encoder(enum AVCodecID id);
/**
* 查找具有指定名称的已注册编码器.
*
* @param name name of the requested encoder
* @return An encoder if one was found, NULL otherwise.
*/
const AVCodec *avcodec_find_encoder_by_name(const char *name);
/**
分配AVCodecContext并将其字段设置为默认值。该应使用avcodec_free_context()释放结果结构。
*
* @param codec if non-NULL, allocate private data and initialize defaults
* for the given codec. It is illegal to then call avcodec_open2()
* with a different codec.
* If NULL, then the codec-specific defaults won't be initialized,
* which may result in suboptimal default settings (this is
* important mainly for encoders, e.g. libx264).
*
* @return An AVCodecContext filled with default values or NULL on failure.
*/
AVCodecContext *avcodec_alloc_context3(const AVCodec *codec);
设置对应音频编码的数据类型
codec_ctx->sample_fmt = AV_SAMPLE_FMT_S16; //输入音频的采样大小
codec_ctx->channel_layout = AV_CH_LAYOUT_STEREO; //输入音频的channel layout
codec_ctx->channels = 2; //输入音频 channel 个数
codec_ctx->sample_rate = 44100; //输入音频的采样率
codec_ctx->bit_rate = 0; //AAC_LC: 128K, AAC HE: 64K, AAC HE V2: 32K
codec_ctx->profile = FF_PROFILE_AAC_HE_V2; //阅读 ffmpeg 代码
设置编码的frame的相关参数
//set parameters
frame->nb_samples = 512; //单通道一个音频帧的采样数
frame->format = AV_SAMPLE_FMT_S16; //每个采样的大小
frame->channel_layout = AV_CH_LAYOUT_STEREO; //channel layout
整个代码:
#include
#include
#include
extern "C"{
#include
#include
#include
#include
#include
}
/* check that a given sample format is supported by the encoder */
static int check_sample_fmt(const AVCodec *codec, enum AVSampleFormat sample_fmt)
{
const enum AVSampleFormat *p = codec->sample_fmts;
while (*p != AV_SAMPLE_FMT_NONE) {
if (*p == sample_fmt)
return 1;
p++;
}
return 0;
}
/* just pick the highest supported samplerate */
static int select_sample_rate(const AVCodec *codec)
{
const int *p;
int best_samplerate = 0;
if (!codec->supported_samplerates)
return 44100;
p = codec->supported_samplerates;
while (*p) {
if (!best_samplerate || abs(44100 - *p) < abs(44100 - best_samplerate))
best_samplerate = *p;
p++;
}
return best_samplerate;
}
/* select layout with the highest channel count */
static int select_channel_layout(const AVCodec *codec, AVChannelLayout *dst){
const AVChannelLayout *p, *best_ch_layout;
int best_nb_channels = 0;
if (!codec->ch_layouts){
AVChannelLayout src = (AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO;
return av_channel_layout_copy(dst,&src);
}
p = codec->ch_layouts;
while (p->nb_channels) {
int nb_channels = p->nb_channels;
if (nb_channels > best_nb_channels) {
best_ch_layout = p;
best_nb_channels = nb_channels;
}
p++;
}
return av_channel_layout_copy(dst, best_ch_layout);
}
static void encode(AVCodecContext *ctx, AVFrame *frame, AVPacket *pkt,
FILE *output)
{
int ret;
/* send the frame for encoding */
ret = avcodec_send_frame(ctx, frame);
if (ret < 0) {
fprintf(stderr, "Error sending the frame to the encoder\n");
exit(1);
}
/* read all the available output packets (in general there may be any
* number of them */
while (ret >= 0) {
ret = avcodec_receive_packet(ctx, pkt);
if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)
return;
else if (ret < 0) {
fprintf(stderr, "Error encoding audio frame\n");
exit(1);
}
fwrite(pkt->data, 1, pkt->size, output);
av_packet_unref(pkt);
}
}
int main(int argc, char **argv)
{
// 对应文件的编码数据
const char *filename;
// 编码器
const AVCodec *codec;
// 编码器上下文
AVCodecContext *c= NULL;
// 保存未曾解码的数据
AVFrame *frame;
// 对应的保存数据
AVPacket *pkt;
int i, j, k, ret;
FILE *f;
uint16_t *samples;
float t, tincr;
if (argc <= 1) {
fprintf(stderr, "Usage: %s