织梦CMS - 轻松建站从此开始!

罗索

y4m to YUV

落鹤生 发布于 2013-07-11 14:56 点击:次 
只要把头文件和每帧的标志位去除即可,剩下的生肉既是原封不动的yuv数据,如果是4:2:0也不需 要进一步的转换修整工作。这次的练习是将一个3840*2160的500帧y4m转换成yuv序列,进行接下来的jm和j264编码练习。转换的思路
TAG:

先要下载一个mencoder,然后 用命令行
mencoder **.y4m -ovc raw -of rawvideo -vf format=i420 -o **.yuv
就可以啦!

 mencoder **.y4m -ovc raw -of rawvideo -vf format=i420 -o **.yuv
y4m to yuv conversion note

1. YUV4MPEG2 format

YUV4MPEG2 这种文件格式是一种以头文件存储视频规格的未压缩视频序列。简单来说,在原始的yuv序列的起始和每一帧的头部都加入了纯文字形式的视频参数信息,包括分 辨率、帧率、逐行/隔行扫描方式、高宽比(aspect ratio),以及每一帧起始的”FRAME ”标志位。具体的定义可以参考这里的wiki。也可以下载相应的.y4m序列样本观察。

2. y4m序列的播放

太笨,除了mplayer没有找到更好的播放器(单独的yuv序列可以用基本的yuvviewerplus,到处都可以找到)。因为主流的桌面linux发行版安装mplayer以及GUI界面smplayer都很方便,所以就不在windows下面折腾了。

在终端输入

mplayer xxxx.y4m

会自动调用y4m的demuxer和decoder之类的东西,因为头文件信息包含了帧率和分辨率因此无须手动指定。一些常见的快捷键在mplayer的man里面都有说明,比如p暂停,左右键快速前进后退等等。对比来看下yuv序列播放,在终端输入:

mplayer sample-720x576.yuv -demuxer rawvideo -rawvideo w=720:h=576

因为yuv序列只有luma分量和chroma分量的生肉(raw)数据所以必须指定宽高参数。

3. y4m到yuv的转换

了 解了y4m的封装形式后,我们的工作就变得相当机械。只要把头文件和每帧的标志位去除即可,剩下的生肉既是原封不动的yuv数据,如果是4:2:0也不需 要进一步的转换修整工作。这次的练习是将一个3840*2160的500帧y4m转换成yuv序列,进行接下来的jm和j264编码练习。转换的思路

pFile跳过头文件
for frame=0, frame<500, frame++
(
pFile跳过FRAME 标志位
for (line=0;line;Heigth;line++)
(读Width字节的Y分量数据并写到yuv中)
for (line=Height;line<2*Heigth;line++)
(读0.5Width字节UV分量数据并写到yuv中)
)

照 这样写的y4m2yuv.c工作有一个问题,生成的.yuv序列使用yuvviewerplus到#172帧的时候直接报错退出,而用mplayer播放 会出现跳变、色彩大幅偏移的现象。我们开始怀疑.y4m源在172-175帧的头文件标记不那么规整,于是做了一个头文件抽取函数 head_drawer(char filename[18])。把上一段算法小小改动跳过大段的像素值只提取header生成header.dat。来看看header.dat里面都是什 么(notepad++,vi,emacs都行)

100419    func head_drawer() to show how does the header data stored in file. Issue found.
Line 1:YUV4MPEG2 W3840 H2160 F50:1 Ip A1:1
Line 2:FRAME
...
Line 174:FRAME
see->    Line 175:蔼报抱饭腐亢房文.....
That would be the reason why .yuv sequence found error when playing through #172 frame.
Next step, discussing the problem.
Keypoint found:fopen() cannot past 2GB file size limit.

这 样的header更让人怀疑是.y4m源的问题了。但boss指导说看看是不是文件操作有2GB限制,因为长整形最大2^32-1。找了一圈,又是要用 Win API又是要用内存地址映射又是在linux环境下define BIT_OFFSET 64之类的……浪费了很多时间才想起来MSDN,终于扒出了有用的东西。fseek()->_fseeki64(),编译,问题解决。

C文件放在这里备忘。可能要被嘲笑的吧哈哈


新 的问题是,实验室内网(物理隔离)的机器只有vc6,vc6的stdio库里似乎没有定义_fseeki64这个函数。啊啊好烦。然后又被老板批了,因为 vc6不支持就不去想办法解决只会伸手要高版本的vs2005。。。可,可是vc6也有一些东西不是通用的ANSI C阿真是的……

bonus:在心烦大文件操作时候找到了个好用的工具,emacs的hex view插件,瞬间打开5G大文件不是问题。

(spencer)
本站文章除注明转载外,均为本站原创或编译欢迎任何形式的转载,但请务必注明出处,尊重他人劳动,同学习共成长。转载请注明:文章转载自:罗索实验室 [http://www.rosoo.net/a/201307/16687.html]
本文出处:eefocus 作者:spencer 原文
顶一下
(0)
0%
踩一下
(0)
0%
------分隔线----------------------------
发表评论
请自觉遵守互联网相关的政策法规,严禁发布色情、暴力、反动的言论。
评价:
表情:
用户名: 验证码:点击我更换图片
栏目列表
将本文分享到微信
织梦二维码生成器
推荐内容