将未压缩视频写入 FLV 文件的可行性
Viability of Writing Uncompressed Video to an FLV File
我很有可能在这方面走上了一条毫无意义的道路,所以如果这是浪费时间,我深表歉意。我一直在尝试将未压缩的视频写入FLV文件,但不确定是否可行。
根据维基百科,有效的视频编码选项为 0,表示 "RGB" 视频编码:https://en.wikipedia.org/wiki/Flash_Video#Packets。但是,我在 Adobe 的文档中没有看到任何提及此编解码器 ID 选项的信息; "Video File Format Specification Version 10" 和 "Adobe Flash Video File Format Specification Version 10.1".
都不是
我假设允许使用 0/RGB 编解码器 ID。我在 C 中硬编码了一个 unsigned char 数组,并使用 fwrite 将以下 Double/Number 元数据写入一个新的二进制 FLV 文件(无可否认,我假设我写得正确):
- 持续时间:4(秒)
- 宽度:16(像素)
- 高度:16(像素)
- 视频数据速率:6 (Kbps)
- 帧率:1 (fps)
- videocodecid: 0
- 文件大小:3323(字节)
然后我添加了 4 个 VIDEODATA 标签,1 个用于我希望写入的每个 RGB 帧。它们的时间戳是 0、1000、2000 和 3000(毫秒)。这四个都有一个 769 字节的有效负载:指定它的第一个字节是编解码器 ID 为 0 的关键帧,其余 768 个字节表示 16x16x3 (RGB) 图像。我为所有值都写了 255/0xFF,希望看到一个小的白色屏幕出现 4 秒。
当它在 VLC 媒体播放器中无法正常播放时,正如我担心的那样,我尝试为每一帧使用 RGBA 颜色。我还将视频数据速率和文件大小元数据分别更改为数值 8 (Kbps) 和 4347 (字节)。
不幸的是,这也没有在 VLC 媒体播放器中播放。我想知道是否有人确切知道 FLV 文件中的未压缩视频是否可行?如果是这样,我很好奇视频数据应该是什么格式(RGB、RGBA、多个 VIDEODATA 标签、只有一个 VIDEODATA 标签等)?
我的 C 代码主要是一个巨大的 unsigned char 数组,但如果有人想看它,我可以尝试添加它。非常感谢任何建议。
谢谢,
米切尔 A
根据 SirDarius,"the video encoding types listed in the Wikipedia page do not come from an official source. I would not recommend relying on those."考虑到 Adobe 本身的 FLV 格式文档没有提及视频编码的未压缩 RGB 选项,这是有道理的。
我一直希望维基百科的编辑和其他人知道 FLV 格式的一些未记录的复活节彩蛋,但我现在确信情况并非如此。
"...The FLV Format documentation from Adobe itself makes no mention of an uncompressed,
RGB option for video encoding."
对于 RGB(原始位图数据),您必须使用Screen 1
编解码器 (id=3)。
奇怪的是,它隐藏在 SWF Format documentation(不是 FLV 格式文档)中。
请参阅第 14 章(第 204 页),即视频部分...
您需要特别说明 Screen Video
编解码器的第 208 页。
检查 this example code (AS3) 将 RGB 编码为屏幕视频。
应用逻辑,尤其是函数 videoData()
,可以将其调整为读取像素单位(通过某些 getPixel
类型调用)或仅从 Array
.[=19 读取=]
示例:
for (var x2:int = 0; x2 < xLimit; x2++)
{
var px:int = (x1 * blockWidth) + x2;
var py:int = frameHeight - ((y1 * blockHeight) + y2); // (flv's save image from bottom to top)
var p:uint = YOUR_INPUT_BITMAP.getPixel(px, py); // sample a pixel's RGB (3-bytes unsigned int)
//# IF reading from Pixel's uint value
block.writeByte( p & 0xff ); // blue
block.writeByte( p >> 8 & 0xff ); // green
block.writeByte( p >> 16 ); // red
//# ELSE IF reading from Array of R-G-B values(FLV writes in BGR format)
block.writeByte( myRGB_Array[x+2] ); // blue
block.writeByte( myRGB_Array[x+1] ); // green
block.writeByte( myRGB_Array[x] ); // red
}
我很有可能在这方面走上了一条毫无意义的道路,所以如果这是浪费时间,我深表歉意。我一直在尝试将未压缩的视频写入FLV文件,但不确定是否可行。
根据维基百科,有效的视频编码选项为 0,表示 "RGB" 视频编码:https://en.wikipedia.org/wiki/Flash_Video#Packets。但是,我在 Adobe 的文档中没有看到任何提及此编解码器 ID 选项的信息; "Video File Format Specification Version 10" 和 "Adobe Flash Video File Format Specification Version 10.1".
都不是我假设允许使用 0/RGB 编解码器 ID。我在 C 中硬编码了一个 unsigned char 数组,并使用 fwrite 将以下 Double/Number 元数据写入一个新的二进制 FLV 文件(无可否认,我假设我写得正确):
- 持续时间:4(秒)
- 宽度:16(像素)
- 高度:16(像素)
- 视频数据速率:6 (Kbps)
- 帧率:1 (fps)
- videocodecid: 0
- 文件大小:3323(字节)
然后我添加了 4 个 VIDEODATA 标签,1 个用于我希望写入的每个 RGB 帧。它们的时间戳是 0、1000、2000 和 3000(毫秒)。这四个都有一个 769 字节的有效负载:指定它的第一个字节是编解码器 ID 为 0 的关键帧,其余 768 个字节表示 16x16x3 (RGB) 图像。我为所有值都写了 255/0xFF,希望看到一个小的白色屏幕出现 4 秒。
当它在 VLC 媒体播放器中无法正常播放时,正如我担心的那样,我尝试为每一帧使用 RGBA 颜色。我还将视频数据速率和文件大小元数据分别更改为数值 8 (Kbps) 和 4347 (字节)。
不幸的是,这也没有在 VLC 媒体播放器中播放。我想知道是否有人确切知道 FLV 文件中的未压缩视频是否可行?如果是这样,我很好奇视频数据应该是什么格式(RGB、RGBA、多个 VIDEODATA 标签、只有一个 VIDEODATA 标签等)?
我的 C 代码主要是一个巨大的 unsigned char 数组,但如果有人想看它,我可以尝试添加它。非常感谢任何建议。
谢谢,
米切尔 A
根据 SirDarius,"the video encoding types listed in the Wikipedia page do not come from an official source. I would not recommend relying on those."考虑到 Adobe 本身的 FLV 格式文档没有提及视频编码的未压缩 RGB 选项,这是有道理的。
我一直希望维基百科的编辑和其他人知道 FLV 格式的一些未记录的复活节彩蛋,但我现在确信情况并非如此。
"...The FLV Format documentation from Adobe itself makes no mention of an uncompressed,
RGB option for video encoding."
对于 RGB(原始位图数据),您必须使用Screen 1
编解码器 (id=3)。
奇怪的是,它隐藏在 SWF Format documentation(不是 FLV 格式文档)中。
请参阅第 14 章(第 204 页),即视频部分...
您需要特别说明
Screen Video
编解码器的第 208 页。检查 this example code (AS3) 将 RGB 编码为屏幕视频。
应用逻辑,尤其是函数 videoData()
,可以将其调整为读取像素单位(通过某些 getPixel
类型调用)或仅从 Array
.[=19 读取=]
示例:
for (var x2:int = 0; x2 < xLimit; x2++)
{
var px:int = (x1 * blockWidth) + x2;
var py:int = frameHeight - ((y1 * blockHeight) + y2); // (flv's save image from bottom to top)
var p:uint = YOUR_INPUT_BITMAP.getPixel(px, py); // sample a pixel's RGB (3-bytes unsigned int)
//# IF reading from Pixel's uint value
block.writeByte( p & 0xff ); // blue
block.writeByte( p >> 8 & 0xff ); // green
block.writeByte( p >> 16 ); // red
//# ELSE IF reading from Array of R-G-B values(FLV writes in BGR format)
block.writeByte( myRGB_Array[x+2] ); // blue
block.writeByte( myRGB_Array[x+1] ); // green
block.writeByte( myRGB_Array[x] ); // red
}