MPEG TS — заголовок синтаксического анализа — неверный PID — 32-битная маска Big Endian

Я думаю, что у меня здесь видение туннеля, поэтому мне нужна ваша помощь.

Я пытаюсь разобрать Файл транспортного потока MPEG и я застрял в Заголовке, в вики вы увидите, что для извлечения данных из 4-байтового заголовка предусмотрены некоторые 32-битные БЕЗ МАСКИ. Мой код учитывает порядок байтов (я думаю) и инвертирует байты, если обнаруживает, что вы работаете с прямым порядком байтов. Затем я привожу char * к int и применяю маску, все значения выглядят нормально, но PID испорчен, и я не понимаю, почему …

определение заголовка

namespace ts {

#define SYNC_BYTE_MASK 0xff000000
#define TEI_MASK 0x800000
#define PAYLOAD_START_MASK 0x400000
#define PRIORITY_MASK 0x200000
#define PID_MASK 0x1fff00
#define SCRAMBLING_CTL_MASK 0xc0
#define ADAPTATION_FIELD_MASK 0x20
#define HAS_PAYLOAD_MASK 0x10
#define COUNTER_MASK 0xf

#define HEADER_BYTES 4
#define HEADER_BITS 8 * HEADER_BYTES

class Header {

public:
std::bitset<HEADER_BITS> *full;

unsigned char _syncByte;
bool _tei;
bool _payloadStart;
bool _priority;
int16_t _pid;
std::bitset<2> *_scramblingCtl;
bool _adaptationField;
bool _hasPayload;
int _counter;

Header(const char *, size_t);
~Header();

const std::string toString();
bool isValid();

};

}

Назначение значений заголовка

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;
}

Вот пример заголовка, который должен иметь PID 33

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

Каким-то образом это снова меняется, и я не понимаю, почему …

0

Решение

Итак, проблема заключалась в том, что 13 бит PID расположены в str[1] а также str[2] что означает, что после кастинга *((int *)str) и применяя маску, все еще есть 8 завершающих 0 битов из последнего байта str[3],

Решение:

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

Благодаря @ Wimmel.

0

Другие решения


По вопросам рекламы [email protected]