在 C 中使用 x264 和 AVCodec 编码 RGB 帧

gam*_*n02 5 c rgb ffmpeg x264 libavcodec

我有从相机流式传输的 RGB24 帧,我想将它们编码为 h264 ,我发现 AVCodec 和 x264 可以这样做,问题是默认情况下 x264 接受 YUV420 作为输入,所以我编写的是一个将 RGB 帧转换为 YUV420 的程序。这是由 sws_scale 函数实现的。除了它不满足所需的 FPS 之外,它运行良好,因为转换 (RGB->YUV420) 需要时间。

这就是我设置编码器上下文的方式:

videoStream->id = 0;
vCodecCtx = videoStream->codec;

vCodecCtx->coder_type       = AVMEDIA_TYPE_VIDEO;
vCodecCtx->codec_id         = AV_CODEC_ID_H264;
vCodecCtx->bit_rate         = 400000;
vCodecCtx->width            = Width;
vCodecCtx->height           = Height;
vCodecCtx->time_base.den    = FPS;
vCodecCtx->time_base.num    = 1;
//vCodecCtx->time_base      = (AVRational){1,};
vCodecCtx->gop_size         = 12;
vCodecCtx->max_b_frames     = 1;
vCodecCtx->pix_fmt          = AV_PIX_FMT_YUV420P;

if(formatCtx->oformat->flags & AVFMT_GLOBALHEADER)
    vCodecCtx->flags |= CODEC_FLAG_GLOBAL_HEADER;

av_opt_set(vCodecCtx->priv_data, "preset", "ultrafast", 0);
av_opt_set(vCodecCtx->priv_data, "profile", "baseline", AV_OPT_SEARCH_CHILDREN);

if (avcodec_open2(vCodecCtx, h264Codec, NULL) < 0){
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

当我将 AV_PIX_FMT_YUV420P 更改为 AV_PIX_FMT_RGB24 时,avcodec_open2 将失败。我读到有一个名为 libx264rgb 的 RGB 的 libx264 版本,但我什至不知道我是否必须通过启用此选项重建 x264 或下载另一个源,或者我必须使用第一个 x264 库以编程方式进行。

问题是如何启用 RGB 作为 libx264 的输入以与 C 中的 libavcodec 一起使用,或者如何使编码或 sws_scale 更快。

编辑:

我是如何构建 ffmpeg 的:

NDK=D:/AndroidDev/android-ndk-r9
PLATFORM=$NDK/platforms/android-18/arch-arm/
PREBUILT=$NDK/toolchains/arm-linux-androideabi-4.8/prebuilt/windows-x86_64

GENERAL="\
--enable-small \
--enable-cross-compile \
--extra-libs="-lgcc" \
--arch=arm \
--cc=$PREBUILT/bin/arm-linux-androideabi-gcc \
--cross-prefix=$PREBUILT/bin/arm-linux-androideabi- \
--nm=$PREBUILT/bin/arm-linux-androideabi-nm \
--extra-cflags="-I../x264/android/arm/include" \
--extra-ldflags="-L../x264/android/arm/lib" "


MODULES="\
--enable-gpl \
--enable-libx264"

function build_ARMv6
{
  ./configure \
  --target-os=linux \
  --prefix=./android/armeabi \
  ${GENERAL} \
  --sysroot=$PLATFORM \
  --enable-shared \
  --disable-static \
  --extra-cflags=" -O3 -fpic -fasm -Wno-psabi -fno-short-enums -fno-strict-aliasing -finline-limit=300 -mfloat-abi=softfp -mfpu=vfp -marm -march=armv6" \
  --extra-ldflags="-lx264 -Wl,-rpath-link=$PLATFORM/usr/lib -L$PLATFORM/usr/lib -nostdlib -lc -lm -ldl -llog" \
  --enable-zlib \
  ${MODULES} \
  --disable-doc \
  --enable-neon

  make clean
  make
  make install
}

build_ARMv6

echo Android ARMEABI builds finished
Run Code Online (Sandbox Code Playgroud)

我是如何构建 x264 的:

NDK=D:/AndroidDev/android-ndk-r9
PLATFORM=$NDK/platforms/android-18/arch-arm/
TOOLCHAIN=$NDK/toolchains/arm-linux-androideabi-4.8/prebuilt/windows-x86_64
PREFIX=./android/arm

function build_one
{
  ./configure \
  --prefix=$PREFIX \
  --enable-static \
  --enable-pic \
  --host=arm-linux \
  --cross-prefix=$TOOLCHAIN/bin/arm-linux-androideabi- \
  --sysroot=$PLATFORM

  make clean
  make
  make install
}

build_one

echo Android ARM builds finished
Run Code Online (Sandbox Code Playgroud)

nob*_*555 2

要在 libavcodec 中将 RGB 像素格式(AV_PIX_FMT_BGR0、AV_PIX_FMT_BGR24、AV_PIX_FMT_RGB24)与 libx264 一起使用,您需要:

  1. 使用 ffmpeg 项目中的 libavcodec,而不是 libav 项目中的 libavcodec,因为目前它仅在其中可用;
  2. 确保 libavcodec 是使用 libx264rgb (CONFIG_LIBX264RGB_ENCODER) 进行编译的,据我了解,如果您使用足够新的 8 位 libx264 (使用 --enable-libx264 配置),则将启用该功能;
  3. 使用 avcodec_find_encoder_by_name("libx264rgb") 而不是 avcodec_find_encoder(AV_CODEC_ID_H264)。