如何使用FFmpeg将灰度视频流编码为MPEG-1格式?

9

我有一个从Firewire天文相机传输的灰度视频流,我想使用FFmpeg压缩视频流,但MPEG1VIDEO编解码器不接受单字节像素格式。我该如何使用FFmpeg API将灰度视频帧转换为FFmpeg可接受的帧格式?

4个回答

11

MPEG-1 只支持 YUV 格式,因此您需要将帧转换为 YUV 格式。使用 SwsContext 结构体,并使用 sws_getContext() 函数创建它,然后使用 sws_scale() 函数进行缩放。


是的,我的像素是灰度的,我已经尝试过“rawvideo”编解码器,但它并没有给我任何压缩,这正是我真正需要的。 - Gearoid Murphy
你应该使用rawvideo作为输入编解码器。对于输出编解码器,你可以指定任何你想要的,实际上你不需要指定 - ffmpeg会通过输出文件的扩展名猜测输出格式和编解码器。 - sashoalm
我正在使用C API,而不是命令行工具,我的代码将AVFrame缓冲区填充为灰度图像,然后调用编码器函数。 - Gearoid Murphy
1
好的,现在我明白了。你说MPEG1VIDEO不接受字节像素格式。这是真的 - 它只接受YUV。所以将你的帧转换为yuv。使用SwsContext结构,通过调用sws_getContext创建它,然后使用sws_scale。我认为还有img_convert,但我认为它已经过时了。我有一些可以做到这一点的代码,所以如果你有问题,我可以帮忙。 - sashoalm
我也是这么想的,我希望能找到一个可以原生处理灰度的编解码器,不过还是谢谢你的帮助。你能否编辑一下你的回答以反映这一点,我会接受它的。 - Gearoid Murphy
大多数编解码器只接受YUV格式。在开始使用FFmpeg之前,我从未听说过YUV。 - sashoalm

8
Gray scale和YUV之间的关系非常简单 - YUV中的"Y"与灰度图像完全相同。
将灰度图像转换为YUV的更简单方法是:
请参阅this 参考文献以了解比例尺之间的转换:
因此:
Y = (0.257 * R) + (0.504 * G) + (0.098 * B) + 16
Cr = V = (0.439 * R) - (0.368 * G) - (0.071 * B) + 128
Cb = U = -(0.148 * R) - (0.291 * G) + (0.439 * B) + 128
现在: 对于灰度图像(W):
R = W; G = W; B = W;
保持这样:
Y[i] = 0.895 * W[i] + 16. U[i] = 128(固定值) V[i] = 128(固定值)
你实际上可以使用Y[i] = W[i],这几乎是相同的。128的值在0-256有符号转无符号的缩放/移位基础上代表'0'。
所以,你需要做的就是创建另一个内存区域Y和U作为固定值,并将这些帧提供给ffmpeg。
我不确定,但通过适当地告诉FFMPEG,它只会在内部完成这项工作。你提供的RGB值也同样被涵盖在其中;这对于MPEG来说也不是本地的。
因此,寻找FFMPEG的API,它能够让你做到这一点。
额外奖励: 记住,在过去的好日子里,有黑白(灰度)电视机。新的彩色电视机需要遵守旧的标准,因此颜色信息以U和V的形式添加(有时也称为YCbCr - 在这种情况下,Cb和Cr分别是UV的线性变化)。

1
感谢提供的信息,幸运的是,sws_getContext和sws_scale函数可以相当有效地执行转换。 - Gearoid Murphy

0

如果你简单地使用“色调”过滤器,它就会起作用;像这样:

ffmpeg -i inputfile.ogv -vf hue=s=0 outputfile-unsat.ogv

1
我认为你误解了问题。 - evilsoup
虽然这个问题的答案比较老,但是它涉及到如何从科学设备中获取灰度视频并通过FFmpeg进行处理。 - Giacomo1968

-2

如果您遇到了FFmpeg的问题,那么您需要先下载最新版本,这将修复一些错误:

https://ffmpeg.org/download.html#build-windows

2
请不要在多个地方粘贴相同的答案。此外,这个问题已经有了一个被接受的答案——它与升级到最新版本无关。这是非常通用的建议,没有任何尝试回答具体问题的内容。 - Jeremy Caney

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接