Linux给FFmpeg集成LC3音频的编码器liblc3

在Linux环境下为FFmpeg集成LC3音频编码器(liblc3)需要以下步骤。LC3是新一代低复杂度音频编解码器,广泛应用于蓝牙LE Audio等场景:


1. 环境准备

# 安装基础编译工具
sudo apt update
sudo apt install build-essential git cmake ninja-build nasm pkg-config

# 安装FFmpeg依赖
sudo apt install libssl-dev zlib1g-dev

2. 编译安装liblc3

2.1 获取源码
git clone https://github.com/google/liblc3.git
cd liblc3
2.2 编译安装
mkdir build && cd build
cmake -GNinja -DCMAKE_BUILD_TYPE=Release ..
ninja
sudo ninja install
2.3 验证安装
# 检查头文件和库
ls /usr/local/include/lc3.h
ls /usr/local/lib/liblc3.so

3. 修改FFmpeg源码

3.1 获取FFmpeg源码
git clone https://git.ffmpeg.org/ffmpeg.git ffmpeg
cd ffmpeg
3.2 添加LC3编码器支持

libavcodec/Makefile中添加:

OBJS-$(CONFIG_LC3_ENCODER)        += lc3enc.o
3.3 创建编码器文件

新建libavcodec/lc3enc.c

#include <lc3.h>
#include "libavutil/opt.h"
#include "avcodec.h"
#include "internal.h"

typedef struct LC3EncContext {
    AVClass *class;
    lc3_encoder_t encoder;
    int frame_ms;      // 帧时长(毫秒)
    int bitrate;       // 目标比特率
} LC3EncContext;

static av_cold int lc3_encode_init(AVCodecContext *avctx)
{
    LC3EncContext *s = avctx->priv_data;
    int dt_us = s->frame_ms * 1000;
    int sr_hz = avctx->sample_rate;
    
    // 创建LC3编码器实例
    s->encoder = lc3_encoder_create(dt_us, sr_hz, 0);
    if (!s->encoder) {
        av_log(avctx, AV_LOG_ERROR, "Failed to create LC3 encoder\n");
        return AVERROR(ENOMEM);
    }
    
    // 设置输出参数
    avctx->frame_size = (sr_hz * s->frame_ms) / 1000;
    avctx->bit_rate = s->bitrate;
    
    return 0;
}

static int lc3_encode_frame(AVCodecContext *avctx, AVPacket *avpkt,
                            const AVFrame *frame, int *got_packet)
{
    LC3EncContext *s = avctx->priv_data;
    int ret, frame_bytes;
    
    // 计算输出帧大小
    frame_bytes = lc3_encoder_get_frame_bytes(s->encoder);
    
    // 分配输出包
    if ((ret = ff_alloc_packet2(avctx, avpkt, frame_bytes, 0)) 
        return ret;
    
    // 执行编码
    const int16_t *pcm = (const int16_t *)frame->data[0];
    lc3_encoder_encode(s->encoder, pcm, avpkt->data);
    avpkt->size = frame_bytes;
    
    *got_packet = 1;
    return 0;
}

static av_cold int lc3_encode_close(AVCodecContext *avctx)
{
    LC3EncContext *s = avctx->priv_data;
    if (s->encoder) lc3_encoder_destroy(s->encoder);
    return 0;
}

#define OFFSET(x) offsetof(LC3EncContext, x)
static const AVOption options[] = {
    { "frame_ms", "Frame duration (ms)", OFFSET(frame_ms), AV_OPT_TYPE_INT, {.i64=10}, 5, 20, AV_OPT_FLAG_ENCODING_PARAM },
    { "bitrate",  "Target bitrate",       OFFSET(bitrate),  AV_OPT_TYPE_INT, {.i64=160000}, 24000, 960000, AV_OPT_FLAG_ENCODING_PARAM },
    { NULL }
};

static const AVClass lc3_enc_class = {
    .class_name = "LC3 Encoder",
    .item_name  = av_default_item_name,
    .option     = options,
    .version    = LIBAVUTIL_VERSION_INT,
};

AVCodec ff_lc3_encoder = {
    .name           = "lc3",
    .long_name      = NULL_IF_CONFIG_SMALL("LC3 (Low Complexity Communication Codec)"),
    .type           = AVMEDIA_TYPE_AUDIO,
    .id             = AV_CODEC_ID_LC3,
    .priv_data_size = sizeof(LC3EncContext),
    .init           = lc3_encode_init,
    .encode2        = lc3_encode_frame,
    .close          = lc3_encode_close,
    .capabilities   = AV_CODEC_CAP_DR1,
    .sample_fmts    = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_NONE },
    .priv_class     = &lc3_enc_class,
};
3.4 注册编码器

libavcodec/allcodecs.c中添加:

extern AVCodec ff_lc3_encoder;
// 在音频编码器部分添加
if (CONFIG_LC3_ENCODER) REGISTER_ENCODER(LC3, lc3);
3.5 添加Codec ID

libavcodec/codec_id.henum AVCodecID中添加:

AV_CODEC_ID_LC3,

4. 配置与编译FFmpeg

4.1 配置编译选项
./configure \
  --extra-cflags="-I/usr/local/include" \
  --extra-ldflags="-L/usr/local/lib" \
  --enable-libshaderc \
  --enable-lc3 \
  --enable-gpl
4.2 编译安装
make -j$(nproc)
sudo make install

5. 验证集成

5.1 检查编码器
ffmpeg -encoders | grep lc3
# 应输出: A..... lc3  LC3 (Low Complexity Communication Codec)

ffmpeg -h encoder=lc3
5.2 测试编码
# 转换PCM文件为LC3
ffmpeg -f s16le -ar 48000 -ac 1 -i input.pcm -c:a lc3 -b:a 160k output.lc3

# 播放测试
ffplay -f lc3 -ar 48000 -ac 1 output.lc3

6. 调试与问题解决

常见问题:
  1. 链接错误

    export LD_LIBRARY_PATH=/usr/local/lib:$LD_LIBRARY_PATH
    
  2. API不匹配
    检查liblc3版本,最新API参考:

    // 新版本API示例
    lc3_encoder_t enc = lc3_setup_encoder(LC3_DT_10MS, 48000, NULL);
    
  3. 采样格式支持
    LC3目前仅支持S16格式,如需浮点支持需添加转换:

    // 在lc3enc.c的encode_frame中添加
    if (frame->format != AV_SAMPLE_FMT_S16) {
        // 使用swresample转换格式
    }
    

7. 高级功能扩展

添加参数支持:
// 在options数组中新增
{ "complexity", "Encoding complexity", OFFSET(complexity), AV_OPT_TYPE_INT, {.i64=3}, 0, 10, ... }
支持多声道:
// 初始化时创建多实例
s->encoders = av_malloc_array(avctx->channels, sizeof(lc3_encoder_t));
for (int ch = 0; ch < avctx->channels; ch++) {
    s->encoders[ch] = lc3_encoder_create(...);
}

技术要点总结

  1. 帧长处理:LC3支持5/7.5/10ms帧长,需与采样率匹配
  2. 比特率范围:单声道24-320kbps,立体声48-640kbps
  3. 延迟控制:总延迟 = 帧长 + 编码延迟(典型2.5ms)
  4. 实时性优化
    // 禁用内存分配
    avctx->internal->allocate_progress = 0;
    

完整实现参考:FFmpeg LC3补丁示例 (需查找最新补丁)

注意:LC3标准仍在演进中,建议跟踪liblc3的GitHub仓库获取最新API变更。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值