【问题标题】:Encode Frames to Video with C Library使用 C 库将帧编码为视频
【发布时间】:2018-12-31 13:23:58
【问题描述】:

为了连续性,让我们假设“RGB值”如下:

typedef struct RGB {
    uint8_t r, g, b;
} rgb;

但是,如果您觉得不同的色彩空间更适合这个问题,请改用它。

在给定输出格式和帧率的情况下,如何将 RGB 值的二维数组写入 C 语言的视频?

在继续之前,我应该说明我希望能够在一个程序中完成所有操作。我正在尝试向应用程序添加功能,使其能够逐帧编译视频而不必离开它

此外,我对这个功能的需求非常基本;我只需要能够将单个像素设置为某些颜色。

到目前为止,我最接近的解决方案是 C 库 FFmpeg。请允许我描述一下我自己学到了什么:

查看其文档后,我发现了函数avcodec_send_frame(avctx, frame),其参数类型分别为AVCodexContext*const AVFrame*如果这些不是我想要做的正确工具,请忽略问题的其余部分,而是指出我应该使用什么。

但是,我不知道avctxframe的哪些字段必须手动设置,哪些不需要。我假设有些不是的原因是因为两者都是非常大的结构,但如果我错了,请纠正我。

问题 1: 必须设置 AVCodecContextAVFrame 的哪些值?其中,每一个的推荐值是多少?

此外,我只能找到有关如何初始化 AVFrame(使用 av_frame_alloc()av_frame_get_buffer())的说明,但找不到有关 AVCodexConstant 的说明。

问题 2: 是否有正确的方法来初始化 AVCodexConstant?以防万一,上述初始化AVFrame 的方法是否正确?两者中的任何一个字段是否有适当的初始化方法?

此外,我无法找到有关如何获取此AVCodexConstant(我假设其中包含视频信息)并将其转换为视频的官方文档。如果这方面的文档很容易找到而我只是错过了,我深表歉意。

问题 3:如何将AVCodexConstant 转换为给定格式的文件?

而且,鉴于我的知识有限:

问题 4:我在此过程中是否还有其他部分遗漏,我是否有任何上述部分错误?


请记住,我最近第一次发现了 FFmpeg,因此,我完全是初学者。此外,我对 C 语言的经验非常有限,如果您能指出哪些文件需要包含在 #include 中,我将不胜感激。

甚至可以随意推荐 FFmpeg 以外的东西,只要它是用 C 编写的。我不需要高级用户选项,但我更喜欢灵活的音频和视频文件类型图书馆可以处理。


解决潜在的重复问题

我很抱歉这部分有多长;我只想覆盖我的基地。但是,如果这实际上是我无法找到的问题的重复,我深表歉意。

【问题讨论】:

  • 这里是一个ffmpeg API使用示例:muxing.c 可以看到fill_yuv_image().中的AVFrame是如何填充的
  • @GalaDOS 不幸的是,该代码似乎使用了avcodec_encode_audio2()avcodec_encode_video2(),FFmpeg 官方文档称它们已被弃用,并已被avcodec_send_frame() 取代,这是我在问题中提到的功能。看到可以使用data 字段写入AVFrame 是很有用的,但是代码向data 写入任意值以产生“虚拟图像”,所以我无法收集除事实之外的任何内容使用data。不过,谢谢你分享。

标签: video encoding ffmpeg video-encoding


【解决方案1】:

检查此工具bmdplay.cpp 这是一个专门为某些品牌的 PCI-E 卡编写的 linux 工具。只需忽略卡特定的调用和功能。

main() 函数有问题 1-4 的答案。 它的Player::ScheduleNextFrame() 函数通过新的 API 解码帧部分。

据我所知,您真正要问的是在现有视频帧上叠加一张(小)图片。

您几乎总是会发现视频文件使用 YUV 格式的视频帧。大多数命令是 YUV420P。您可以将每个帧转换为 RGB,然后对其进行处理,但这会产生额外的开销。所以最好使用原生格式。

这里的重点是图片和视频帧应该有相同的格式。所以你应该事先将图片转换为视频帧格式(我假设它是静止图片)。

RGB 是线性格式,所以如果你的源恰好是这种格式,只需编写一个算法将图片复制到视频帧。 (即AVFrame::data[0]

YUV420P 是平面格式。 由3个平面组成:
Y (AVFrame::data[0])
U (AVFrame::data[1])
V (AVFrame::data[2])
linesizes(也称为strides)可以从(AVFrame::linesize[0-2])获得

这种格式很棘手,U 和 V 平面只有 Y 框架的 1/4 大小。但这不是问题,因为您将在图片上使用与视频帧中相同的格式。

希望这些有所帮助。

【讨论】:

    猜你喜欢
    • 2018-02-12
    • 1970-01-01
    • 1970-01-01
    • 2012-11-12
    • 2019-02-15
    • 2014-01-08
    • 1970-01-01
    • 2018-07-05
    • 1970-01-01
    相关资源
    最近更新 更多