`
xpp02
  • 浏览: 1010798 次
社区版块
存档分类
最新评论

开启 JM 的 trace 功能

 
阅读更多
本帖最后由 firstime 于 2009-6-15 11:16 AM 编辑

城里汉子说过:
trace文件对分析码流结构很有效。我说的是trace文件,不是一步一步跟踪,就是编解码同时生成的 trace_enc.txt 这个文件,里面对每个比特位是什么都有记录。

本论坛的帖子“H.264编解码手册”里的 H.264_MPEG-4 AVC Reference Software Manua 建议大家去看看。这个文件对编解码的所有参数做了详细介绍

trace_enc.txt 是编码的文件
trace_dec.txt 是解码的文件

运行编解码器之后才会生成相应的 trace 文件


在代码中有个参数要设置一下才行:

在defines.h文件中把

#if defined _DEBUG
#define TRACE 0 //!< 0:Trace off 1:Trace on
#else

改成
#if defined _DEBUG
#define TRACE 1 //!< 0:Trace off 1:Trace on
#else

[ 本帖最后由 firstime 于 2007-3-9 08:17 PM 编辑 ]

如何阅读 trace 文件

@0 SPS: profile_idc 01011000 ( 88)
@8 SPS: constrained_set0_flag 0 (0)
@9 SPS: constrained_set1_flag 0 (0)
@10 SPS: constrained_set2_flag 0 (0)
@11 SPS: constrained_set3_flag 0 (0)
@12 SPS: reserved_zero 0000 (0)
@16 SPS: level_idc 00011110 ( 30)

以此为例,对应码流中的 NALU 单元为:6758001E.........,其中 0X67 是 NALU 头,从 0X58 开始为 NALU 体

第一行含义:从 NALU 体第 0 个比特开始的比特串为 SPS 中的语法元素 profile_idc ,其十进制表示值为 88 。标准 7.3.2.1 小节表格中规定该语法元素编码方式为U(8),因此 88 按 U(无符号数) 方式编码的二进制值为 1011000。 因为该语法元素编码方式为 U(8),即采用 8 比特无符号数编码,因此,最终在码流中应该补足 8 位,结果为 01011000;

第二行含义:从 NALU 体第 8 个比特开始的比特串为 SPS 中的语法元素 constrained_set0_flag ,其十进制表示值为 0 。标准 7.3.2.1 小节表格中规定该语法元素编码方式为 U(1),因此 0 按 U(1) 方式编码的二进制值为 0;

第三行含义:从 NALU 体第 9 个比特开始的比特串为 SPS 中的语法元素 constrained_set1_flag ,其十进制表示值为 0 。标准 7.3.2.1 小节表格中规定该语法元素编码方式为 U(1),因此 0 按 U(1) 方式编码的二进制值为 0;

第四行含义:从 NALU 体第 10 个比特开始的比特串为 SPS 中的语法元素 constrained_set2_flag ,其十进制表示值为 0 。标准 7.3.2.1 小节表格中规定该语法元素编码方式为 U(1),因此 0 按 U(1) 方式编码的二进制值为 0;

第五行含义:从 NALU 体第 11 个比特开始的比特串为 SPS 中的语法元素 constrained_set3_flag ,其十进制表示值为 0 。标准 7.3.2.1 小节表格中规定该语法元素编码方式为 U(1),因此 0 按 U(1) 方式编码的二进制值为 0;

第六行含义:从 NALU 体第 12 个比特开始的比特串为 SPS 中的语法元素 reserved_zero,其十进制表示值为 0 。标准 7.3.2.1 小节表格中规定该语法元素编码方式为 U(4),因此 0 按 U(无符号数) 方式编码的二进制值为 0; 因为该语法元素编码方式为 U(4),即采用 4 比特无符号数编码,因此,最终在码流中应该补足 4 位,结果为 0000;

第七行含义:从 NALU 体第 16 个比特开始的比特串为 SPS 中的语法元素 level_idc,其十进制表示值为 30 。标准 7.3.2.1 小节表格中规定该语法元素编码方式为U(8),因此 30 按 U(无符号数) 方式编码的二进制值为 11110; 因为该语法元素编码方式为 U(8),即采用 8 比特无符号数编码,因此,最终在码流中应该补足 8 位,结果为 00011110;

将上述结果的二进制串连起来:
01011000 0 0 0 0 0000 00011110

按每 8 个比特划分为一段:
01011000 00000000 00011110

将其转换为 16 进制:
58001E

实际传输的码流就是上面的二进制串,而我们用 ultraedit 看到的码流正是其 16 进制表示方式

[ 本帖最后由 firstime 于 2006-12-15 11:57 AM 编辑 ]

谢谢牛人啊!

嘿嘿,这个是我很想看到的啊,十分感谢啊!!

举个例子
这个里面怎么那么多MVD?
********* Pic: 33 (I/P) MB: 51 Slice: 0 **********
@108388mb_skip_flag 0000 (1)
@108392mb_type (P_SLICE) ( 7, 4) = 1 1 (1)
@108393ref_idx_l0 = 0 (0)
@108393mvd_l0 (0) = 2(org_mv 2 pred_mv 0) 010110 (2)
@108399mvd_l0 (1) = 0(org_mv 0 pred_mv 0) (0)
@108399CBP ( 7, 4) =31 00001001111 ( 31)
@108410transform size 8x8 flag = 1 11 (1)
@108412Delta QP ( 7, 4) = 0 (0)
@108412Luma8x8 sng( 0) level = -2 run = 0 ( -2)
@108412Luma8x8 sng( 1) level =0 run = 0 00001001111 (0)
@108423Luma8x8 sng( 0) level = -3 run = 0 ( -3)
@108423Luma8x8 sng( 1) level =0 run = 1 000001001110 (0)
@108435Luma8x8 sng( 0) level = -2 run = 0 ( -2)
@108435Luma8x8 sng( 1) level =0 run = 1 1001010 (0)
@108442Luma8x8 sng( 0) level = -3 run = 0 ( -3)
@108442Luma8x8 sng( 1) level =0 run = 1 001001001 (0)
@108451DC Chroma0: level =1 run = 0 (1)
@108451DC Chroma1: level =0 run = 2 1010 (0)
@108455DC Chroma0: level = -1 run = 0 ( -1)
@108455DC Chroma1: level =0 run = 1 0101 (0)
CABAC terminating bit = 0
=======================================================================
*********** Pic: 33 (I/P) MB: 53 Slice: 0 **********
@108461mb_skip_flag (0)
CABAC terminating bit = 0
思skip的编码信息急需都没有
那应该在解码的trace里面
但是解码的trace怎么打开
怎么看skip解码的时候copy的是那一块
skip模式的 运动矢量要不要编码的?
编码的运动

1:这个里面怎么那么多MVD?
——
@108392 mb_type (P_SLICE) ( 7, 4) = 1 1 (1)

这行说明该宏块为 P_L0_L0_16x8 类型宏块(参见标准表 7-13 第 2 行)
既然宏块被分割为两个 16*8,那么当然就有两个 MV 值(上面 8 个 4*4 共用一个,下面 8 个 4*4 共用一个),当然就有两个的 MVD 值,即:
@108393mvd_l0 (0) = 2(org_mv 2 pred_mv 0) 010110 (2)
@108399mvd_l0 (1) = 0(org_mv 0 pred_mv 0) (0)

同时可见该宏块并不是 SKIP 宏块,因为该宏块 mb_type= 1


2:解码的trace怎么打开
——解码 trace 打开方式与编码相同


3:skip模式的 运动矢量要不要编码
——请你先认真学习本论坛帖子[原创] Skip、Direct宏块浅析” 。而且请你注意不要混淆概念。H.264 中的预测模式没有 skip,因此不能说“一个宏块是 skip 模式”,只能说“一个宏块是 skip 类型”。skip 类型宏块采用的是 direct 模式。


4:怎么看skip解码的时候copy的是那一块
——每个宏块都有一个参考索引。该参考索引表示了当前宏块解码的参考图像是参考列表中的哪一幅。然后解码器根据这个参考索引和计算出的 MV 确定 copy 参考图像中的哪个 “宏块”。这是由两个条件一起决定的一个计算过程。在 trace 文件中是直接看不出来的。


5:仅仅靠分析 trace 文件是不够的,也是很累的。请你用一段已压缩码流跟踪解码过程。看样子你有点急躁。急躁是解决不了问题的。另外,看样子你的这个码流采用的是 CABAC 熵编码方式。请你试验时候先采用 CAVLC 熵编码的码流。应该从易到难,先通过 CAVLC 理解了 skip 再研究 CABAC 的情况。

[ 本帖最后由 firstime 于 2007-9-16 03:38 PM 编辑 ]
非常感谢!!!!!!!!!!!!!!!!!
多谢firsttime的精辟解疑释惑!
受益 匪浅

太感谢了阿

找出skip块的copy的块 可真麻烦阿
找了好久了
跟踪编码部分
什么都没有找到
对于skip宏块 是不是运动矢量在解码端才会出现(根据相邻块的运动矢量预测出来),然后copy该运动矢量对应的macroblock

跟踪解码部分
半天了
还没有发现在哪一部分针对skip解码
wisitng(80609949)

本帖最后由 firstime 于 2009-6-15 06:47 PM 编辑

你用我加了注释的 JM 解码器代码,进 interpret_mb_mode_B 或 interpret_mb_mode_P 函数就能看见了。interpret_mb_mode_B 的第二个 if 就是 B_skip , interpret_mb_mode_P 的第一个 if 就是 P_skip。

[ 本帖最后由 firstime 于 2006-12-16 10:32 AM 编辑 ]

楼主 强 !
早就想看trace了 ,打开开关,居然不知道trace是存成文件的,害的我在cmd里面都没有看到,晕了好久!
今天终于明白了

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics