今天分析encode_audio.c学习ffmpeg如何编码音频数据。
直接贴代码
##main函数
C++音视频开发学习资料:点击领取→音视频开发(资料文档+视频教程+面试题)(FFmpeg+WebRTC+RTMP+RTSP+HLS+RTP)
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
验证采样格式,找最大采样率,声道数
/* check that a given sample format is supported by the encoder */
static int check_sample_fmt(const AVCodec *codec, enum AVSampleFormat sample_fmt)
{
//sample_fmts: array of supported sample formats, or NULL if unknown, array is terminated by -1
//支持的采样格式数组,为空,或者以-1结尾
const enum AVSampleFormat *p = codec->sample_fmts;
//判断设置的采样格式是否支持,1 支持 0 不支持
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;
//supported_samplerates: array of supported audio samplerates, or NULL if unknown, array is terminated by 0
//supported_samplerates 保存了支持的采样率的数组,为空,或者以 0 结尾
if (!codec->supported_samplerates)
//为空,返回44100
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)
{
const uint64_t *p;
uint64_t best_ch_layout = 0;
int best_nb_channels = 0;
//channel_layouts: array of support channel layouts, or NULL if unknown. array is terminated by 0
//channel_layouts 保存了支持的所有声道布局数组,为空,或者以 0 结尾
if (!codec->channel_layouts)
//为空,返回AV_CH_LAYOUT_STEREO
return AV_CH_LAYOUT_STEREO;
//找声道数最多的那个
p = codec->channel_layouts;
while (*p) {
int nb_channels = av_get_channel_layout_nb_channels(*p);
if (nb_channels > best_nb_channels) {
best_ch_layout = *p;
best_nb_channels = nb_channels;
}
p++;
}
return best_ch_layout;
}
encode
static void encode(AVCodecContext *ctx, AVFrame *frame, AVPacket *pkt,
FILE *output)
{
int ret;
/* 给编码器发送frame */
ret = avcodec_send_frame(ctx, frame);
if (ret < 0) {
fprintf(stderr, "Error sending the frame to the encoder
");
exit(1);
}
/* read all the available output packets (in general there may be any
* number of them */
while (ret >= 0) {
//从编码器中读pkt,pkt里面保存了编码后的数据
ret = avcodec_receive_packet(ctx, pkt);
if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)
//EAGAIN编码器还需要更多的frame才能继续输出pkt
//AVERROR_EOF编码器没有更多数据可以读取了,例如被冲洗了
return;
else if (ret < 0) {
fprintf(stderr, "Error encoding audio frame
");
exit(1);
}
//写入文件
fwrite(pkt->data, 1, pkt->size, output);
//取消引用pkt
av_packet_unref(pkt);
}
}
ffmpeg 支持的音频编码器
ffmpeg -codecs | grep encoder | grep -i audio
DEAIL. aac AAC (Advanced Audio Coding) (decoders: aac aac_fixed aac_at ) (encoders: aac aac_at )
DEAI.S alac ALAC (Apple Lossless Audio Codec) (decoders: alac alac_at ) (encoders: alac alac_at )
DEAIL. mp2 MP2 (MPEG audio layer 2) (decoders: mp2 mp2float mp2_at ) (encoders: mp2 mp2fixed )
DEAIL. mp3 MP3 (MPEG audio layer 3) (decoders: mp3float mp3 mp3_at ) (encoders: libmp3lame )
DEAIL. opus Opus (Opus Interactive Audio Codec) (decoders: opus libopus ) (encoders: opus libopus )
DEAIL. ra_144 RealAudio 1.0 (14.4K) (decoders: real_144 ) (encoders: real_144 )
示例中选择的是AV_CODEC_ID_MP2
通过avcodec_find_encoder(AV_CODEC_ID_MP2)来找到对应的编码器
你也可以尝试mp3,aac ,opus 之类的。
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_S64, ///< signed 64 bits
AV_SAMPLE_FMT_S64P, ///< signed 64 bits, planar
AV_SAMPLE_FMT_NB ///< Number of sample formats. DO NOT USE if linking dynamically
};
后缀带P的就是平面型的,不带P的就是交错型的。
留言与评论(共有 0 条评论) “” |