H.264码流分析入门(以第一帧为例)

       编码foreman_part_qcif.yuv的第一帧,分析生成的码流,为了便于分析,我们需要打开JM8.6编码器中的trace_enc.txt文件记录功能,怎么开启呢?在JM8.6 encoder的define.h文件中有这样的代码:

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

     

      只需要把代码改为下面的形式就可以开启trace_enc.txt文件的功能:

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


      trace_enc.txt文件对码流分析具有很大的作用,运行一下程序,看看trace_enc.txt中的内容就知道了. 我们知道,码流在test.264文件中,如果要看的话,需要用UltrlEdit来看其中二进制比特对应的十六进制,而且不能复制,这样就不太方便了. 为了便于分析码流,便于观看,本人把码流写成对应的字符形式,直观,而且可以复制. 具体在代码中的操作为:

void printDataIntoFile(FILE *fp, int i)
{
	char str[20];
	int r = 2;
	int length;
	int j;
	assert(i >= 0 && i <= 255);

	itoa(i, str, r); // 重要函数(转成二进制)

	if(i <= 15)
		fprintf(fp, "0%X: ", i);
	else
		fprintf(fp, "%X: ", i);

	length = strlen(str);
	for(j = length; j < 8; j++)
		fprintf(fp, "0"); // 前面补0

	fprintf(fp, "%s <---", str);

	fprintf(fp, "(%3d)\n", i);
}

/*!
 ********************************************************************************************
 * \brief 
 *    Writes a NALU to the Annex B Byte Stream
 *
 * \return
 *    number of bits written
 *
 ********************************************************************************************
*/
int WriteAnnexbNALU (NALU_t *n)
{
  int BitsWritten = 0;
  int i;

  assert (n != NULL);
  assert (n->forbidden_bit == 0);
  assert (f != NULL);
  assert (n->startcodeprefix_len == 3 || n->startcodeprefix_len == 4);

// printf ("WriteAnnexbNALU: writing %d bytes w/ startcode_len %d\n", n->len+1, n->startcodeprefix_len); 
  if (n->startcodeprefix_len > 3)
  {
    putc (0, f);
    BitsWritten =+ 8;

	printDataIntoFile(fp, 0);
  }
  putc (0, f);
  printDataIntoFile(fp, 0); // 写到myData.txt中

  putc (0, f);
  printDataIntoFile(fp, 0); // 写到myData.txt中

  putc (1, f);
  printDataIntoFile(fp, 1); // 写到myData.txt中

  BitsWritten += 24;

  n->buf[0] =
    n->forbidden_bit << 7      |
    n->nal_reference_idc << 5  |
    n->nal_unit_type;

// printf ("First Byte %x, nal_ref_idc %x, nal_unit_type %d\n", n->buf[0], n->nal_reference_idc, n->nal_unit_type);

  if (n->len != fwrite (n->buf, 1, n->len, f))
  {
    printf ("Fatal: cannot write %d bytes to bitstream file, exit (-1)\n", n->len);
    exit (-1);
  }

  BitsWritten += n->len * 8;

  for(i = 0; i < n->len; i++ )
  {
	 // 写到myData.txt中
	 printDataIntoFile(fp, n->buf[i]);
  }

  fflush (f);
#if TRACE
  fprintf (p_trace, "\n\nAnnex B NALU w/ %s startcode, len %d, forbidden_bit %d, nal_reference_idc %d, nal_unit_type %d\n\n",
    n->startcodeprefix_len == 4?"long":"short", n->len, n->forbidden_bit, n->nal_reference_idc, n->nal_unit_type);
  fflush (p_trace);
#endif
  return BitsWritten;
}


       在myData.txt中的部分内容为:

00: 00000000 <---(  0)
00: 00000000 <---(  0)
00: 00000000 <---(  0)
01: 00000001 <---(  1)
67: 01100111 <---(103)
42: 01000010 <---( 66)
00: 00000000 <---(  0)
1E: 00011110 <---( 30)
............

      而trace_enc.txt中的部分内容为:

@0     SPS: profile_idc                                       01000010 ( 66)
@8     SPS: constrained_set0_flag                                    0 (  0)
@9     SPS: constrained_set1_flag                                    0 (  0)
@10    SPS: constrained_set2_flag                                    0 (  0)
@11    SPS: reserved_zero                                        00000 (  0)
@16    SPS: level_idc                                         00011110 ( 30)
............

       经本人严格对比后发现:myData.txt中的内容和trace_enc.txt中的内容实际上是高度一致的. 下面参照trace_enc.txt的内容来解析码流. (由于博客的篇幅限制,故只作简要解析)

00000000

00000000

00000000

00000001       这些表示接下来的比特流是一个NALU(SPS对应的NALU)

0                     forbidden_zero = 0--->0

11                   nal_ref_idc = 11--->3

00111             nal_unit_type = 00111--->7 

       对照trace_enc.txt, 继续分析:

01000010          @0    SPS: profile_idc                                       01000010 ( 66)

0                        @8     SPS: constrained_set0_flag                                    0 (  0)

0                        @9     SPS: constrained_set1_flag                                    0 (  0)

0                        @10    SPS: constrained_set2_flag                                    0 (  0)

00000                @11   SPS: reserved_zero                                        00000 (  0)

00011110          @16   SPS: level_idc                                         00011110 ( 30)

111100010110000101100010011000

10                      补齐  (SODBtoRBSP)          第一帧共有3处补齐,从代码中可以看到SODBtoRBSP函数刚好被调用3次

 

00000000000000000000000000000001011010001100100010100001010000111000   PPS

1000                  补齐  (SODBtoRBSP) 

 

00000000000000000000000000000001011001011000100010000100000000100        SliceHeader

 

*********** Pic: 0 (I/P) MB: 0 Slice: 0 **********

1100011011000010111110000000000000111010110111011111100000000000111001111100000110000010111011100110000111100100001010000111011011001011010010001001001011101010011111000010110000001101001100000000111111111111001111100101111100101100000000010101001101010010111010011100110011011100000100101010101000110100000010110010001011001011100100001001010110011100010000001001111110000000100001000001011001001001100011010101100001001001111000001110000000010010000011101001000110111111001000100011101101010011111010100001010011011110100001110101101011111100110010100110010011110001011000000111001001000001100000000101110100011011010010011111001011100111000000100000101000111010100001000101000111001011111111

 

*********** Pic: 0 (I/P) MB: 98 Slice: 0 **********

110011101110111010010111011111111001000010101110011011011100110111010001101010000011101001001101010010110000100011010010011100011011111101110010011100101100001001000001100101010000110011011010010001110011010111110101100000111000111100000100110011111110101001010000010100000011001101000001100110011111101011101000101100111010110000000101100000101010011010000101001111010101110100111000000110101101000110010110001110000110000011111110111000110110011000001110011101

100                  补齐  (SODBtoRBSP)

 

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值