准备
ffmpeg 版本4.4
准备一段48000Hz 2 channel f32le 格式的PCM原始数据
这里我们直接使用ffmpeg命令行提取
ffmpeg -i beautlWorld.mp4 -ar 48000 -ac 2 -f f32le 48000_2_f32le.pcm
-ar 采样率
-ac 音频通道
-f f32le 音频样本数据存储格式(f32 ---- float 32位 le ----小端)
使用下面命令进行播放:
ffplay -ar 48000 -ac 2 -f f32le 48000_2_f32le.pcm
编码流程
基本上面的流程已经很清晰了,按照步骤编写代码即可,下面贴出源码
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
extern "C" {
#include <libavcodec/avcodec.h>
#include <libavutil/channel_layout.h>
#include <libavutil/common.h>
#include <libavutil/frame.h>
#include <libavutil/samplefmt.h>
#include <libavutil/opt.h>
}
/* 检测该编码器是否支持该采样格式 */
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) { // 通过AV_SAMPLE_FMT_NONE作为结束符
if (*p == sample_fmt)
return 1;
p++;
}
return 0;
}
/* 检测该编码器是否支持该采样率 */
static int check_sample_rate(const AVCodec* codec, const int sample_rate)
{
const int* p = codec->supported_samplerates;
while (*p != 0) {// 0作为退出条件,比如libfdk-aacenc.c的aac_sample_rates
printf("%s support %dhz\n", codec->name, *p);
if (*p == sample_rate)
return 1;
p++;
}
return 0;
}
/* 检测该编码器是否支持该采样率, 该函数只是作参考 */
static int check_channel_layout(const AVCodec* codec, const uint64_t channel_layout)
{
// 不是每个codec都给出支持的channel_layout
const uint64_t* p = codec->channel_layouts;
if (!p) {
printf("the codec %s no set channel_layouts\n", codec->name);
return 1;
}
while (*p != 0) { // 0作为退出条件,比如libfdk-aacenc.c的aac_channel_layout
printf("%s support channel_layout %d\n", codec->name, *p);
if (*p == channel_layout)
return 1;
p++;
}
return 0;
}
static int check_codec(AVCodec* codec, AVCodecContext* codec_ctx)
{
if (!check_sample_fmt(codec, codec_ctx->sample_fmt)) {
fprintf(stderr, "Encoder does not support sample format %s",
av_get_sample_fmt_name(codec_ctx->sample_fmt));
return 0;
}
if (!check_sample_rate(codec, codec_ctx->sample_rate)) {
fprintf(stderr, "Encoder does not support sample rate %d", codec_ctx->sample_rate);
return 0;
}
if (!check_channel_layout(codec, codec_ctx->channel_layout)) {
fprintf(stderr, "Encoder does not support channel layout %lu", codec_ctx->cha