将H.264采集卡的输出格式,转换为标准H.264
2011-03-12 23:14
218 查看
市面上有很多种H.264硬压采集, 海康/大华/等等等等
找了半天发现所有的卡接口及其相似,在开发包中都是使用 RegisterStreamDirectReadCallback 注册回调函数来获取压缩后的数据流。
在它的回调函数中输出的码流不知道是啥子格式,而我需要标准的H.264码流,保存成flv并同时使用RTMP发布。如果解码后重新编码加重了CPU的负担,不符合要求。难道这就是传说中的海康码?
找啊找啊找啊找,在几乎绝望的情况下发现大华的工具里面居然有一个将 采集卡的录像文件 转换成 标准AVI 的小工具 StreamToAVI.exe。
马上一试,输出的AVI能够被MediaInfo识别,且显示AVI容器的 codec 是 AVC, Main profile. 哟西,看来还是标准的H.264码流啊。
只要能够反向这个工具就能够解析出可爱的NALU了。
打开IDA,首先盯上的就是ReadFile API调用
每次读取长度为0x10000 的文件块到内存,然后就call sub_401E30进行处理, 看来 401E30这个函数就是要反向的目标
这个函数是某个类的成员函数,成员变量是由ebp寄存器(this指针)加上偏移量进行操作,看起来真头疼啊
理清类的内存布局以及推测其中某些变量含义,花了3天时间, 虽然人是笨了点,不过好在有耐心。再结合调试跟踪,又花了一个周末的时间摸清了基本的来龙去脉。终于搞出点东西来了!
这个1FD 1FC 1FB 1FA 1F0 应该是类型字段,标明当前的数据类型
1F0 是音频编码,略过, 不感兴趣
1FD 和 1FC 是 H.264编码 , 1FD应该是 I帧
1FB 和 1FA 不知道是什么,调试中发现, 我的录像文件从不进入这个分支执行,它应该是另一种编码类型(0x3447504D?),可能是为其它某种型号的硬件准备的。这个就略过了,反正没用。
在0x403030处发现一个重要函数
这个函数的特征太明显了,连续设置0x00 0x00 0x00 0x01 以及 连续2个零后小于3做处理。
一眼就认出0x40303这个函数肯定是转换成H.264 Annex B format输出
围绕这个函数分析,发现卡输出的H.264分2种, 一种就是H.264 Annex B, 还一种就是普通的NALU
试着自己写了个解析程序,成功地转换了录像文件。
明天继续,离球门不远了 :)
找了半天发现所有的卡接口及其相似,在开发包中都是使用 RegisterStreamDirectReadCallback 注册回调函数来获取压缩后的数据流。
在它的回调函数中输出的码流不知道是啥子格式,而我需要标准的H.264码流,保存成flv并同时使用RTMP发布。如果解码后重新编码加重了CPU的负担,不符合要求。难道这就是传说中的海康码?
找啊找啊找啊找,在几乎绝望的情况下发现大华的工具里面居然有一个将 采集卡的录像文件 转换成 标准AVI 的小工具 StreamToAVI.exe。
马上一试,输出的AVI能够被MediaInfo识别,且显示AVI容器的 codec 是 AVC, Main profile. 哟西,看来还是标准的H.264码流啊。
只要能够反向这个工具就能够解析出可爱的NALU了。
打开IDA,首先盯上的就是ReadFile API调用
.text:00401CD1 push 10000h .text:00401CD6 push ecx .text:00401CD7 push ebp .text:00401CD8 call ds:ReadFile .text:00401CDE test eax, eax .text:00401CE0 jz short loc_401D0F .text:00401CE2 mov eax, [esp+10h] .text:00401CE6 cmp eax, 10000h .text:00401CEB jnb short loc_401CF5 .text:00401CED mov dword ptr [esp+14h], 1 .text:00401CF5 mov edx, [esi+60h] .text:00401CF8 push eax .text:00401CF9 push edx .text:00401CFA mov ecx, esi .text:00401CFC call sub_401E30
每次读取长度为0x10000 的文件块到内存,然后就call sub_401E30进行处理, 看来 401E30这个函数就是要反向的目标
这个函数是某个类的成员函数,成员变量是由ebp寄存器(this指针)加上偏移量进行操作,看起来真头疼啊
理清类的内存布局以及推测其中某些变量含义,花了3天时间, 虽然人是笨了点,不过好在有耐心。再结合调试跟踪,又花了一个周末的时间摸清了基本的来龙去脉。终于搞出点东西来了!
.text:00402231 mov eax, [ebp+64h] .text:00402234 cmp eax, 1FDh .text:00402239 jz short loc_40227D .text:0040223B cmp eax, 1FCh .text:00402240 jz short loc_40227D .text:00402242 cmp eax, 1FBh .text:00402247 jz short loc_40227D .text:00402249 cmp eax, 1FAh .text:0040224E jz short loc_40227D .text:00402250 cmp eax, 1F0h .text:00402255 jz short loc_40227D .text:00402257 cmp eax, 1F1h .text:0040225C jz short loc_40227D
这个1FD 1FC 1FB 1FA 1F0 应该是类型字段,标明当前的数据类型
1F0 是音频编码,略过, 不感兴趣
1FD 和 1FC 是 H.264编码 , 1FD应该是 I帧
1FB 和 1FA 不知道是什么,调试中发现, 我的录像文件从不进入这个分支执行,它应该是另一种编码类型(0x3447504D?),可能是为其它某种型号的硬件准备的。这个就略过了,反正没用。
在0x403030处发现一个重要函数
.text:00403030 mov ecx, [esp+arg_8] .text:00403034 mov eax, [esp+arg_C] .text:00403038 push ebp .text:00403039 mov ebp, [esp+4+arg_0] .text:0040303D push esi .text:0040303E push edi .text:0040303F lea edi, [ecx+eax] .text:00403042 lea eax, [ebp+1] .text:00403045 mov byte ptr [ebp+0], 0 .text:00403049 xor esi, esi .text:0040304B mov byte ptr [eax], 0 .text:0040304E inc eax .text:0040304F mov byte ptr [eax], 0 .text:00403052 inc eax .text:00403053 mov byte ptr [eax], 1 .text:00403056 mov dl, [ecx] .text:00403058 inc eax .text:00403059 mov [eax], dl .text:0040305B inc eax .text:0040305C inc ecx .text:0040305D cmp ecx, edi .text:0040305F jnb short loc_403084 .text:00403061 cmp esi, 2 .text:00403064 jnz short loc_403071 .text:00403066 cmp byte ptr [ecx], 3 .text:00403069 ja short loc_403071 .text:0040306B mov byte ptr [eax], 3 .text:0040306E inc eax .text:0040306F xor esi, esi .text:00403071 mov dl, [ecx] .text:00403073 test dl, dl .text:00403075 jnz short loc_40307A .text:00403077 inc esi .text:00403078 jmp short loc_40307C .text:0040307A xor esi, esi .text:0040307C mov [eax], dl .text:0040307E inc eax .text:0040307F inc ecx .text:00403080 cmp ecx, edi .text:00403082 jb short loc_403061 .text:00403084 mov ecx, [esp+0Ch+arg_4] .text:00403088 sub eax, ebp .text:0040308A pop edi .text:0040308B pop esi .text:0040308C mov [ecx], eax .text:0040308E pop ebp .text:0040308F retn 10h
这个函数的特征太明显了,连续设置0x00 0x00 0x00 0x01 以及 连续2个零后小于3做处理。
一眼就认出0x40303这个函数肯定是转换成H.264 Annex B format输出
围绕这个函数分析,发现卡输出的H.264分2种, 一种就是H.264 Annex B, 还一种就是普通的NALU
试着自己写了个解析程序,成功地转换了录像文件。
明天继续,离球门不远了 :)
相关文章推荐
- js将long日期格式转换为标准日期格式
- NMEA-0183 协议 ——GPS芯片输出标准格式
- double 型变量的输入输出标准格式
- JavaWeb将验证码转换为Base64格式字符串输出到前端
- [Boost]如何将UNIX风格时间转换为标准格式
- 标准格式输出
- Jsp结合XML+XSLT将输出转换为Html格式
- 【C语言】从标准输入读取字符,并把它们写到标准输出,除了 大写字母转换成小写字母之外,其他的原样输出。
- 数字字符串,转换为货币格式输出
- php将从数据库中获得的数据转换成json格式并输出
- 【转】YUV420SP的格式以及转换为RGB565的代码(Android摄像头的输出一般为YUV420P) .
- 解读:标准输入/输出格式
- Fri Sep 08 2017 17:03:02 GMT+0800 (中国标准时间)------- 格式的时间转换
- php将数组转换成csv格式文件输出的方法
- BCD转换十进制及输出格式
- C语言 时间戳和标准格式的转换
- C语言 编写一个程序从标准输入读取字符,并把他们写到标准输出。除了大写字母转换成小写字母之外,其他的原样输出。
- [Boost]如何将UNIX风格时间转换为标准格式
- apache出错提示的\\x16进制格式输出转换成可读字符方法与编码格式
- [Boost]如何将UNIX风格时间转换为标准格式