C++ C++;-MPEG TS-解析标头-PID混乱-大端32位掩码

C++ C++;-MPEG TS-解析标头-PID混乱-大端32位掩码,c++,parsing,video-streaming,binary-data,mpeg2-ts,C++,Parsing,Video Streaming,Binary Data,Mpeg2 Ts,我想我在这里有一个隧道视野,所以我需要你的帮助 我试图解析一个,但我被困在了标题上,在wiki上,你会看到提供了一些32位的BE掩码,以便从4字节的标题中提取数据。我的代码考虑了endianess(我想),如果它检测到您在一个小endian上运行,就会反转字节。然后我将char*转换为int并应用掩码,所有的值看起来都很好,但是PID搞乱了,我不明白为什么 标题定义 不知怎的,它又被反转了,我不明白为什么…好吧,问题是PID的13位位于str[1]和str[2],这意味着在抛出*((int*)s

我想我在这里有一个隧道视野,所以我需要你的帮助

我试图解析一个,但我被困在了标题上,在wiki上,你会看到提供了一些32位的BE掩码,以便从4字节的标题中提取数据。我的代码考虑了endianess(我想),如果它检测到您在一个小endian上运行,就会反转字节。然后我将char*转换为int并应用掩码,所有的值看起来都很好,但是PID搞乱了,我不明白为什么

标题定义


不知怎的,它又被反转了,我不明白为什么…

好吧,问题是PID的13位位于
str[1]
str[2]
,这意味着在抛出
*((int*)str
并应用掩码之后,最后一个字节
str[3]
仍然有8个尾随的0位

解决方案:

this->_pid = bytes & PID_MASK; 
this->_pid >>= 8;

感谢@Wimmel.

您不需要反转字节,因为您读取的不是整数,而是4个字节。它们的顺序总是正确的。但是使用位集输出它们可能会有问题。我反转是因为我需要在int上应用掩码(be),而我的机器是LE,所以如果我在施法之前不反转,它就乱套了,对吗?当我保持原样时,布尔值没有正确设置,PID也没有正确设置:(我明白了,你确实使用整数。但是如果你和使用
0x1ff00
,你应该将结果移位8位(末尾的零)。因此你的例子有PID 33。啊!很好,我必须解释第4个字节……如果你关心代表点,请给出答案:)。谢谢
ts::Header::Header(const char *header, size_t n) {
    uint32_t bytes = reverseLE(header, n);

    // just for display
    char t[4];
    memcpy(t, header, 4);
    std::cout << "Original: " << std::bitset<32>(*((uint32_t *)t)) << std::endl;
    this->full = new std::bitset<HEADER_BITS>(bytes);

    uint32_t tmp = bytes & SYNC_BYTE_MASK;
    this->_syncByte = ((char *)&tmp)[n - 1];

    this->_tei = bytes & TEI_MASK;
    this->_payloadStart = bytes & PAYLOAD_START_MASK;
    this->_priority = bytes & PRIORITY_MASK;
    this->_pid = bytes & PID_MASK; // THIS ONE IS MESSED UP !!
    this->_scramblingCtl = new std::bitset<2>(bytes & SCRAMBLING_CTL_MASK);
    this->_adaptationField = bytes & ADAPTATION_FIELD_MASK;
    this->_hasPayload = bytes & HAS_PAYLOAD_MASK;
    this->_counter = bytes & COUNTER_MASK;
}
   #include "utils.h"

int is_big_endian(void)
{
    union {
        uint32_t i;
        char c[4];
    } e = { 0x01000000 };

    return e.c[0];
}

void swap(char *s, int a, int b) {
    char tmp;

    tmp = s[a];
    s[a] = s[b];
    s[b] = tmp;
}

// Converts string to int taking endianess into account
uint32_t reverseLE(const char *bits, size_t n) {
    uint32_t ret = 0;
    char *cp = (char *)malloc(n * sizeof(char));

    memcpy(cp, bits, n);
    if ( ! is_big_endian() ) {
        for (int i = 0; i < n / 2; i++)
            swap(cp, i, n - 1 - i);
    }

    ret = *((uint32_t *)cp);
    free(cp);
    return ret;
}
Original: 00010010001000010000000001000111
Binary: 01000111000000000010000100010010
Sync byte: G
TEI: 0
Payload start: 0
Priority: 0
PID: 8448 0010000100000000
Scrambling Ctl: 00
Adaptation field: 0
Has Payload: 1
Counter: 2
this->_pid = bytes & PID_MASK; 
this->_pid >>= 8;