我如何从读取文件二进制的mkv中提取群集的时间

问题描述 投票:2回答:1

[当我读取二进制mkv时,群集的ID为E7字节,并且时间戳记具有无符号的int值,但是当我读取它时,id并没有给我正确的时间戳记。

double mkVSParser::get_clusters_timestamps(char *&package,unsigned long &size)
{
      uint8_t *data_to_find = new uint8_t;
      *data_to_find=0xE7;//the id
      char * buffer = new char[sizeof (uint8_t)];
      uint8_t current_data[sizeof (uint8_t)];

      for(int i=0;i<size;i++)//finde the first 0xE7 in an cluster
      {
          memcpy(&buffer[0],&package[i],sizeof (uint8_t));

          memcpy(&current_data[0],buffer,sizeof (uint8_t));

          if (memcmp(data_to_find, current_data, sizeof (uint8_t)) == 0)
          {
              unsigned int timestemp;
              std::cout<<"position of byte =="<<i<<"and id =="<<(unsigned int)package[i]<<std::endl;

              memcpy(&timestemp,&package[i+1],sizeof(unsigned int));

              std::cout<<"cluster timestemp ="<<timestemp<<std::endl;
              return 0;
          }

            }

      return 0;
}

我有什么想念的吗?

c++ memory binary mkv matroska
1个回答
0
投票

MKV二进制数据为EBML格式,并且无符号整数的大小可能可变。 Variable size int可能由可变数量的八位字节组成(字节大小可能不同)。

每个可变大小整数以VINT_WIDTH开头,后跟VINT_MARKER。 VINT_WIDTH是零个或多个值0的序列,并由VINT_MARKER终止,该值是值1的单个位。 VINT_WIDTH和VINT_MARKER的总长度(以位为单位)是可变大小整数中以八位字节为单位的总长度。

单个位1启动一个长度为八位字节的可变大小整数。位01的序列以两个八位位组的长度开始一个可变大小整数。 001以三个八位位组的长度开始一个可变长整型数,依此类推,每个额外的0位将一个八位字节加到可变长整型数的长度上。]

可变大小整数的第一个字节中第一个“ 1”位的位置表示以字节为单位的大小。如果在第一个位置

1XXXXXXX(除长度部分外,我在这里用'X'表示数字的其他位)

然后变量是一个字节长,第一个“ 1”位之后的其余位(在这种情况下为7个低位)是数字的二进制表示。 Variable size int

以开头

0000001X XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX

是七个字节,只要这里的第一个“ 1”位在第七位置。

因此,首先,您需要读取数字的第一个字节并找到第一个'1'位的位置[[N

,然后读取整数N个字节长,而忽略了第一个'1'位(好像是零位。constexpr uint8_t VarSizeIntLenMark(int length) { return 1 << (8 - length); // set single bit at length's position } int VarSizeIntLen(const uint8_t* data) { for (int i = 1; i <= 8; i++) if (VarSizeIntLenMark(i) & data[0]) return i; return 0; } uint64_t ReadVariableSizeInt(const uint8_t* data) { int length = VarSizeIntLen(data[0]); uint64_t parsedValue = data[0] & (~VarSizeIntLenMark(length)); // invert VINT_MARKER bit for (int i = 1; i < length; i++) // read other bytes parsedValue = (parsedValue << 8) + data[i]; return parsedValue; }
© www.soinside.com 2019 - 2024. All rights reserved.