我如何从读取二进制文件的 mkv 中提取集群的 timstemp
How do i extract timstemp of a cluster from mkv reading the file binary
当我读取二进制 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(¤t_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(×temp,&package[i+1],sizeof(unsigned int));
std::cout<<"cluster timestemp ="<<timestemp<<std::endl;
return 0;
}
}
return 0;
}
有什么我遗漏的吗?
MKV 二进制数据采用 EBML 格式,无符号整数的大小可能是可变的。 可变大小的 int 可能包含可变数量的八位字节(可能具有不同的字节大小)。
Each Variable Size Integer starts with a VINT_WIDTH followed by a VINT_MARKER. VINT_WIDTH is a sequence of zero or more bits of value 0
, and is terminated by the VINT_MARKER, which is a single bit of value 1
. The total length in bits of both VINT_WIDTH and VINT_MARKER is the total length in octets in of the Variable Size Integer.
The single bit 1
starts a Variable Size Integer with a length of one octet. The sequence of bits 01
starts a Variable Size Integer with a length of two octets. 001
starts a Variable Size Integer with a length of three octets, and so on, with each additional 0-bit adding one octet to the length of the Variable Size Integer.
可变大小整数的第一个字节中第一个“1”位的位置表示以字节为单位的大小。如果在第一位
1XXXXXXX (I use 'X' for other bits of the number here, besides the length part)
然后变量是一个字节长,第一个“1”位之后的其余位(在这种情况下为低 7 位)是数字的二进制表示。 以
开头的可变大小整数
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;
}
当我读取二进制 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(¤t_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(×temp,&package[i+1],sizeof(unsigned int));
std::cout<<"cluster timestemp ="<<timestemp<<std::endl;
return 0;
}
}
return 0;
}
有什么我遗漏的吗?
MKV 二进制数据采用 EBML 格式,无符号整数的大小可能是可变的。 可变大小的 int 可能包含可变数量的八位字节(可能具有不同的字节大小)。
Each Variable Size Integer starts with a VINT_WIDTH followed by a VINT_MARKER. VINT_WIDTH is a sequence of zero or more bits of value
0
, and is terminated by the VINT_MARKER, which is a single bit of value1
. The total length in bits of both VINT_WIDTH and VINT_MARKER is the total length in octets in of the Variable Size Integer.The single bit
1
starts a Variable Size Integer with a length of one octet. The sequence of bits01
starts a Variable Size Integer with a length of two octets.001
starts a Variable Size Integer with a length of three octets, and so on, with each additional 0-bit adding one octet to the length of the Variable Size Integer.
可变大小整数的第一个字节中第一个“1”位的位置表示以字节为单位的大小。如果在第一位
1XXXXXXX (I use 'X' for other bits of the number here, besides the length part)
然后变量是一个字节长,第一个“1”位之后的其余位(在这种情况下为低 7 位)是数字的二进制表示。 以
开头的可变大小整数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;
}