Практическая разработка упаковки встраиваемого аудио и видео формата ts.
Практическая разработка упаковки встраиваемого аудио и видео формата ts.

Введение в формат TS:

ТС: Полное название — MPEG2-TS. TS — это аббревиатура «Транспортный поток». Он отправляется пакетами, каждый пакет имеет длину 188 байт (есть также пакеты по 192 и 204 байта). Структура пакета такова, заголовок — 4 байта (первый байт — 0x47), полезная нагрузка — 184 байта. В поток TS могут быть заполнены многие типы данных, такие как видео, аудио, пользовательская информация и т. д. MPEG2-TS в основном используется для передачи программ в реальном времени, например телепрограмм в реальном времени. Особенностью формата MPEG2-TS является то, что он требует независимого декодирования любого сегмента видеопотока. Проще говоря, отрезание первой части VOB-файла на DVD (или повреждение данных) приведет к тому, что весь файл невозможно будет декодировать, а телепрограммы можно будет декодировать (просматривать) в любой момент, когда Телевизор включен.

Для анализа TS см.: 2.4 Требования к битовому потоку транспортного потока стандарта ISO/IEC 13818-1.

Конкретные ссылки следующие:

Язык кода:javascript
копировать
https://www.iso.org/obp/ui/#iso:std:iso-iec:13818:-1:ed-7:v1:en

Структура пакета TS:

Описание информации в заголовке:

Подробности следующие:

- sync_byte: фиксированное значение 0100 0111 (0x47); этот байт распознается декодером и позволяет отделить заголовок и полезную нагрузку друг от друга.

  • Transport_error_indicator: '1' указывает, что в соответствующем транспортном пакете имеется по крайней мере один бит неисправимой ошибки. Если установлено значение 1, его нельзя сбросить на 0, пока ошибка не будет исправлена.
  • payload_unit_start_indicator (индикатор начала): когда он равен 1, после первых 4 байтов будет байт корректировки, и его значение равно длине последующего поля корректировки. Поэтому начало полезной нагрузки должно быть смещено еще на 1+[длина] байт. Оказывается, полезная нагрузка исходит от
  • Transport_priority: «1» указывает, что приоритет выше, чем у других пакетов с тем же PID, но этот бит не установлен в «1».
  • PID:Инструкции хранятся с сгруппированными полезными нагрузками.данныетип。PID ценить 0x0000—0x000F бронировать. Среди них 0x0000 зарезервирован для PAT; 0x0001 зарезервирован для CAT; 0x1fff зарезервирован для группировки, которая представляет собой пустой пакет.
  • Transport_scrambling_control (управление скремблированием): указывает режим шифрования полезной нагрузки пакета потока TS. Пустые пакеты имеют значение «00». Если заголовок пакета передачи включает поле корректировки, его не следует шифровать.
  • Adaptation_field_control (управление доменом адаптации): указывает, имеет ли заголовок поле настройки или полезную нагрузку. «00» зарезервировано для будущего использования в соответствии с ISO/IEC; «01» содержит только полезную нагрузку, без поля настройки; «10» не имеет полезной нагрузки, содержит только поле настройки; «11» — это полезная нагрузка после поля настройки, и первая часть. поля настройки Один байт представляет длину поля настройки, а начало полезных данных должно быть смещено на [длину] байтов. Пустые пакеты должны иметь номер «10».
  • Continuous_counter (счетчик непрерывности): увеличивается с каждым пакетом потока TS с тем же PID.,Когда он достигает максимальной цены, он возвращается к 0. Диапазон: 0~15. Принимающая сторона может определить, есть ли потеря пакетов и ошибка последовательности передачи пакетов.

Что содержит поток TS:

Пример парсинга BAT:

TS-Пакет 1:

Эта сумка особенная. Почему ее называют первой? Потому что? continuity_counter=0 & payload_unit_start_indicator=1。

Другими словами, любой фильтр сегмента SCTION начинается с пакета TS с параметром Continuous_counter=0. В этом случае максимальный размер SECTION составляет 184X16=2944 байта.

Таким образом, размер SECTION зависит от синтаксиса SECTION, который будет анализироваться. Извлекая первые 3 байта полезной нагрузки, вы узнаете длину SCTION. Формула расчета обычно следующая:

secLen = ((uint16_t)(buf[1] & 0xf)) << 8 | buf[2])  buf — начальная позиция полезной нагрузки. Подробности смотрите в синтаксической структуре таблицы BAT.

Обзор следующий:

  • 1. Инкремент пакета равен 0, что означает начало первого SCTION. Пакет TS с инкрементом пакета, равным 0, имеет payload_unit_start_indicator=1. В других случаях payload_unit_start_indicator=0.
  • 2. Конкретное положение полезной нагрузки зависит от жатки 4 + длины дополнительной площадки + исходного положения грузовой единицы.
  • 3. Длина каждого SCTION включается в первые 3 байта полезной нагрузки.
  • Payload_unit_start_indicator=1 обычно используется в демультиплексоре для определения начала нового пакета.

47 40 11 10 означает, что поле настройки отсутствует и имеется флаг начала единицы загрузки. Тогда начальная позиция полезной нагрузки находится после data[5], длина полезной нагрузки равна 183, а первые 3 байта полезной нагрузки — 4a f2 ed. . Текущая длина SCTION равна secLen=749 байт.

TS-Пакет 2:

47 00 11 11 означает, что нет поля настройки и нет флага начала единицы загрузки, тогда начальная позиция полезной нагрузки находится после data[4], а длина полезной нагрузки равна 184.

TS-Пакет 3:

47 00 11 12 означает отсутствие поля настройки и отсутствие флага начала единицы нагрузки, тогда начальная позиция полезной нагрузки находится после data[4], а длина полезной нагрузки равна 184.

TS-пакет 4:

47 00 11 13 означает отсутствие поля настройки и отсутствие флага начала единицы нагрузки, тогда начальная позиция полезной нагрузки находится после data[4], а длина полезной нагрузки равна 184.

TS-пакет 5:

47 00 11 14 означает отсутствие поля настройки и отсутствие флага начала единицы нагрузки, тогда начальная позиция полезной нагрузки находится после data[4], а длина полезной нагрузки равна 17.

Это последний пакет TS текущего SCTION, как определить, последний ли это пакет?

Во-первых, когда мы разобрали первый пакет TS, мы получили secLen=749. По мере увеличения инкремента пакетов мы последовательно получили полезную нагрузку 749-183-184-184-184=17, поэтому при анализе пятого пакета TS When, полезная нагрузка составляет 17 байт, BAT завершает работу по сбору данных, синтаксический анализ BAT выглядит следующим образом:

Поток TS должен содержать пакеты PAT, пакеты PMT, несколько аудиопакетов, несколько видеопакетов, несколько пакетов PCR и другие информационные пакеты.

Процесс анализа данных потока TS: найти пакет с PID 0x0, проанализировать PAT, program_map_PID в пакете PAT представляет PID поиска PMT, элементарный_PID в пакете PMT представляет PID аудио и; видеопакет и пакет PMT PCR_PID представляет собой PID PCR. Иногда PID PCR совпадает с PID аудио или видео, что означает, что PCR будет интегрирован в пакет аудио и видео. Иногда обратите внимание на анализ. PCR — это отдельный пакет CAT, NIT, SDT, а PID EIT: 0x01, 0x10, 0x11, 0x12.

Давайте проанализируем это ниже. В стандарте ISO/IEC 13818-1 указано, что значение PID BAT равно 0x11, а идентификатор пакета TS (т. е. sync_byte) — 0x47, чтобы гарантировать достоверность данных в этом пакете TS. , сначала ищем 47 40 11 Эти три группы шестнадцатеричных чисел, почему они такие? Конкретный секрет заключается в структуре пакета TS. Как упоминалось ранее, sync_byte имеет фиксированное значение 0x47. Теперь посмотрите на четыре элемента Transport_error_indicator, payload_unit_start_indicator, Transport_priority и PID. PID равен 0x11, что является идентификацией BAT. Transport_error_indicator равен 0, а Transport_priority равен 0. Думайте о них как о двух наборах восьмизначных шестнадцатеричных чисел: 40 11. Теперь посмотрим на наш пример фрагмента потока TS. Кажется, он начинается с 47 40 11. Заголовок потока TS занимает 4 байта. Содержимое оставшейся части нагрузки определяется PID. Примером является таблица BAT. Здесь есть кое-что, на что следует обратить внимание: когда payload_unit_start_indicator равен 1, после первых 4 байтов будет байт корректировки, и его значение определяет конкретную начальную позицию содержимого полезной нагрузки. Теперь посмотрим на данные в примере 47 40 11 10 00. Пятый байт — 00, а это значит, что сразу после 00 идет конкретное содержимое загрузки, то есть за 4a f2 ed следует загрузка.

До сих пор была поднята проблема обнаружения полезной нагрузки TS-пакетов. При обнаружении полезной нагрузки следует обратить внимание на два момента:

  • 1. Размер адаптивной области
  • 2. "payload_unit_start_indicator" начальная область полезной нагрузки.

В качестве примера возьмем «tsBuf[]», в «tsBuf[]» хранится кадр пакета TS, tsBuf[0]=0x47, заголовок синхронизации TS, тогда tsBuf[4] — длина адаптивной области.

Язык кода:javascript
копировать
transport_packet(){
  sync_byte
    ...
  adaptation_field_control                     2               bslbf
  continuity_counter                           4               uimsbf
  if(adaptation_field_control == '10' || adaptation_field_control == '11'){
    adaptation_field()
  }
  ...
}

tsBuf[4]=adaptation_field_length

Язык кода:javascript
копировать
adaptation_field(){
  adaptation_field_length                      8               uimsbf
  if(adaptation_field_length>0){
    ...
    PCR_flag                                   1               bslbf
    ...
    if(PCR_flag == '1'){
      program_clock_reference_base             33              uimsbf
      Reserved                                 6               bslbf
      program_clock_reference_extension        9               uimsbf
      ...
    }
  }
}

Синтаксис ISO/IEC 13818-1 для адаптивных зон следующий:

Анализ заголовка TS:

Заголовок TS имеет 4 байта:

Язык кода:javascript
копировать
//Transport Stream header
typedef struct TS_header
{
         unsigned sync_byte                    :8;      //Байт синхронизации, фиксированный на 0x47 , указывая, что следующий пакет является TS. Конечно, 0x47 не появится в данных следующего пакета.
         unsigned transport_error_indicator       :1;      //Бит флага ошибки передачи. Обычно в случае ошибки передачи пакет не будет обработан.
         unsigned payload_unit_start_indicator    :1;      //Флаг начала полезной нагрузки имеет разные функции в зависимости от содержимого последующей полезной нагрузки.
         // Когда payload_unit_start_indicator равен 1, после первых 4 байтов будет байт корректировки, и его номер определяет конкретную начальную позицию содержимого полезной нагрузки.
         unsigned transport_priority              :1;      //Бит приоритета передачи, 1 указывает на высокий приоритет
         unsigned PID                          :13;     //Тип данных полезной нагрузки
         unsigned transport_scrambling_control     :2;      //Флаг шифрования, 00 означает отсутствие шифрования
         unsigned adaption_field_control          :2;      //Настройка управления полем. 01 содержит только полезную нагрузку, 10 содержит только поля настройки, а 11 содержит и поля настройки, и полезную нагрузку. Если это 00, декодер не будет его обрабатывать.
         unsigned continuity_counter              :4;      //4-битный счетчик, диапазон 0-15
} TS_header;
    //Описание специального параметра:
   //sync_byte:0x47
   //payload_unit_start_indicator: 0x01 указывает на наличие заголовка PSI или PES
   //PID: 0x0 указывает, что последующим содержимым загрузки является PAT, а разные PID указывают на разные нагрузки.
   //adaption_field_control:
        // 0x0: // reserved for future use by ISO/IEC
        // 0x1: // Никаких полей настройки, только полезная нагрузка   
        // 0x2: // Только поля настройки, без полезной нагрузки
        // 0x3: // Содержит полезную нагрузку после настройки полей
 
// Parse TS header
int Parse_TS_header(unsigned char *pTSBuf, TS_header *pheader)
{
    pheader->sync_byte                                     = pTSBuf[0];
    if (pheader->sync_byte != 0x47)
        return -1;
    pheader->transport_error_indicator       = pTSBuf[1] >> 7;
    pheader->payload_unit_start_indicator    = pTSBuf[1] >> 6 & 0x01;
    pheader->transport_priority             = pTSBuf[1] >> 5 & 0x01;
    pheader->PID                         = (pTSBuf[1] & 0x1F) << 8 | pTSBuf[2];
    pheader->transport_scrambling_control   = pTSBuf[3] >> 6;
    pheader->adaption_field_control         = pTSBuf[3] >> 4 & 0x03;
    pheader->continuity_counter            = pTSBuf[3] & 0x0F;
    return 0;
}

Для анализа заголовка пакета TS см.: 2.4.3.2 Уровень пакета транспортного потока ISO/IEC 13818-1.

Анализ формата полезной нагрузки TS:

1. ПАТ-анализ:

Значение PID в заголовке TS_header равно 0x0, что указывает на то, что текущей загрузкой является PAT (таблица ассоциаций программ). Информацию данных PAT можно понимать как информацию о программе, содержащуюся во всем потоке TS.

Язык кода:javascript
копировать
// Program Association Table
typedef struct PAT_Packet_tag
{
    unsigned table_id                        : 8; //Фиксировано на 0x00 , флаг означает, что таблица является PAT
    unsigned section_syntax_indicator        : 1; //Флаг синтаксиса сегмента, фиксированный на 1
    unsigned zero                            : 1; //0
    unsigned reserved_1                      : 2; // Зарезервированный бит
    unsigned section_length                  : 12 //Указывает количество полезных байтов, следующих за этим байтом, включая CRC32;
    unsigned transport_stream_id             : 16; //Идентификатор этого транспортного потока отличается от других мультиплексированных потоков в сети.
    unsigned reserved_2                      : 2; // Зарезервированный бит
    unsigned version_number                  : 5; //Диапазон 0-31, указывающий номер версии PAT
    unsigned current_next_indicator          : 1; //Является ли отправленный PAT действительным в данный момент или действительным следующий PAT?
    unsigned section_number                  : 8; //Номер сегмента. PAT может быть разделен на несколько сегментов для передачи. Первый сегмент равен 00, а каждый последующий сегмент увеличивается на 1. Всего может быть до 256 сегментов.
    unsigned last_section_number             : 8; //Номер последнего сегмента
    // for(i=0; i<N; i++)
    // {
    unsigned program_number                  : 16;
    unsigned reserved_3                      : 3;
    unsigned network_PID                     : 16;  // Или program_map_PID
    unsigned CRC_32                          : 32;
    // }
} PAT_Packet;
 
// Parse PAT
int Parse_PAT(unsigned char *pTSBuf, PAT_Packet *packet)
{
    TS_header TSheader;
    if (Parse_TS_packet_header(pTSBuf, &TSheader) != 0)
        return -1;
    if (TSheader.payload_unit_start_indicator == 0x01) // Указывает, что он содержит заголовок PSI или PES.
    {
        if (TSheader.PID == 0x0)  // означает ПАТ
        {
             int iBeginlen = 4;
             int adaptation_field_length = pTSBuf[4];
             switch(TSheader.adaption_field_control)
             {
             case 0x0:                                    // reserved for future use by ISO/IEC
                  return -1;
             case 0x1:                                    // Никаких полей настройки, только полезная нагрузка       
                  iBeginlen += pTSBuf[iBeginlen] + 1;  // + pointer_field
                  break;
             case 0x2:                                     // Только поля настройки, без полезной нагрузки
                  return -1;
             case 0x3: // Содержит полезную нагрузку после настройки полей
                 if (adaptation_field_length > 0) 
                 {
                      iBeginlen += 1;                   // адаптация_field_length занимает 8 бит
                      iBeginlen += adaptation_field_length; // + adaptation_field_length
                 }
                 else
                 {
                      iBeginlen += 1;                       // адаптация_field_length занимает 8 бит
                 }
                 iBeginlen += pTSBuf[iBeginlen] + 1;           // + pointer_field
                 break;
            default:
                 break;
            }
            unsigned char *pPAT = pTSBuf + iBeginlen;
            packet->table_id                    = pTSBuf[0];
            packet->section_syntax_indicator    = pTSBuf[1] >> 7;
            packet->zero                        = pTSBuf[1] >> 6 & 0x1;
            packet->reserved_1                  = pTSBuf[1] >> 4 & 0x3;
            packet->section_length              = (pTSBuf[1] & 0x0F) << 8 | pTSBuf[2];
            packet->transport_stream_id         = pTSBuf[3] << 8 | pTSBuf[4];
            packet->reserved_2                  = pTSBuf[5] >> 6;
            packet->version_number              = pTSBuf[5] >> 1 &  0x1F;
            packet->current_next_indicator      = (pTSBuf[5] << 7) >> 7;
            packet->section_number              = pTSBuf[6];
            packet->last_section_number         = pTSBuf[7];
            int len = 0;
            len = 3 + packet->section_length;
            packet->CRC_32                      = (pTSBuf[len-4] & 0x000000FF) << 24
                                                | (pTSBuf[len-3] & 0x000000FF) << 16
                                                | (pTSBuf[len-2] & 0x000000FF) << 8
                                                | (pTSBuf[len-1] & 0x000000FF);
 
            int n = 0;
            for ( n = 0; n < (packet->section_length - 12); n += 4 )
            {
                 packet->program_number = pTSBuf[8 + n ] << 8 | pTSBuf[9 + n ]; 
                 packet->reserved_3                = pTSBuf[10 + n ] >> 5;
                 if ( packet->program_number == 0x00)
                 { 
                     packet->network_PID = (pTSBuf[10 + n ] & 0x1F) << 8 | pTSBuf[11 + n ];
                 }
                 else
                 {
                     // Действительный PID PMT, а затем используйте этот PIDценить, чтобы найти пакет PMT.
                     program_map_PID = (pTSBuf[10 + n] & 0x1F) << 8 | pTSBuf[11 + n];
                 }
            }
            return 0;
         }
    }
    return -1;
}

Для анализа данных PAT см.: 2.4.4.3 Таблица ассоциаций программ ISO/IEC 13818-1.

2. Анализ ПМТ:

PID PMT (таблицы сопоставления программ) можно определить из program_map_PID в пакете PAT. Информацию данных PMT можно понимать как аудио- и видеоинформацию, содержащуюся в этой программе.

Язык кода:javascript
копировать
// Program Map Table
typedef struct PMT_Packet_tag
{
     unsigned table_id                        : 8;
     unsigned section_syntax_indicator        : 1;
     unsigned zero                            : 1;
     unsigned reserved_1                      : 2;
     unsigned section_length                  : 12;
     unsigned program_number                  : 16;
     unsigned reserved_2                      : 2;
     unsigned version_number                  : 5;
     unsigned current_next_indicator          : 1;
     unsigned section_number                  : 8;
     unsigned last_section_number             : 8;
     unsigned reserved_3                      : 3;
     unsigned PCR_PID                         : 13;
     unsigned reserved_4                      : 4;
     unsigned program_info_length             : 12;
     // for(i=0; i<N; i++)
     // {
     unsigned stream_type                     : 8;
     unsigned reserved_5                      : 3;
     unsigned elementary_PID                  : 13;
     unsigned reserved_6                      : 4;
     unsigned ES_info_length                  : 12;
     // }
     unsigned CRC_32                          : 32;
} PMT_Packet;
   // Parse PMT
int Parse_PMT(unsigned char *pTSBuf, PMT_Packet *packet)
{
    // Просто обратитесь к Parse_PAT(), чтобы сделать это.
    // ...
     
    return 0;
}

Для анализа данных PMT см.: 2.4.4.8 Таблица карты программы ISO/IEC 13818-1.

3. PES-анализ:

Согласно документу, обратитесь к процессу анализа PAT и PMT, чтобы завершить анализ PES.

Что необходимо отметить, так это анализ PTS в PES. Вообще говоря, при 90 к Гц значение PTS/9000 находится в секундах.

Язык кода:javascript
копировать
unsigned long long Parse_PTS(unsigned *pBuf)
{
     unsigned long long llpts = (((unsigned long long)(pBuf[0] & 0x0E)) << 29)
         | (unsigned long long)(pBuf[1] << 22)
         | (((unsigned long long)(pBuf[2] & 0xFE)) << 14)
         | (unsigned long long)(pBuf[3] << 7)
         | (unsigned long long)(pBuf[4] >> 1);
     return llpts;
}

Для анализа данных PES требуется ссылка: 2.5.5.1 Синтаксис синтаксиса пакета PES для каталога программного потока.

Инструменты анализа потока кода:

1、Elecard Stream Analyzer:

2、EasyICE:

Ссылка на статью: https://www.cnblogs.com/jiangzhaowei/p/4344886.html.

boy illustration
Неразрушающее увеличение изображений одним щелчком мыши, чтобы сделать их более четкими артефактами искусственного интеллекта, включая руководства по установке и использованию.
boy illustration
Копикодер: этот инструмент отлично работает с Cursor, Bolt и V0! Предоставьте более качественные подсказки для разработки интерфейса (создание навигационного веб-сайта с использованием искусственного интеллекта).
boy illustration
Новый бесплатный RooCline превосходит Cline v3.1? ! Быстрее, умнее и лучше вилка Cline! (Независимое программирование AI, порог 0)
boy illustration
Разработав более 10 проектов с помощью Cursor, я собрал 10 примеров и 60 подсказок.
boy illustration
Я потратил 72 часа на изучение курсорных агентов, и вот неоспоримые факты, которыми я должен поделиться!
boy illustration
Идеальная интеграция Cursor и DeepSeek API
boy illustration
DeepSeek V3 снижает затраты на обучение больших моделей
boy illustration
Артефакт, увеличивающий количество очков: на основе улучшения характеристик препятствия малым целям Yolov8 (SEAM, MultiSEAM).
boy illustration
DeepSeek V3 раскручивался уже три дня. Сегодня я попробовал самопровозглашенную модель «ChatGPT».
boy illustration
Open Devin — инженер-программист искусственного интеллекта с открытым исходным кодом, который меньше программирует и больше создает.
boy illustration
Эксклюзивное оригинальное улучшение YOLOv8: собственная разработка SPPF | SPPF сочетается с воспринимаемой большой сверткой ядра UniRepLK, а свертка с большим ядром + без расширения улучшает восприимчивое поле
boy illustration
Популярное и подробное объяснение DeepSeek-V3: от его появления до преимуществ и сравнения с GPT-4o.
boy illustration
9 основных словесных инструкций по доработке академических работ с помощью ChatGPT, эффективных и практичных, которые стоит собрать
boy illustration
Вызовите deepseek в vscode для реализации программирования с помощью искусственного интеллекта.
boy illustration
Познакомьтесь с принципами сверточных нейронных сетей (CNN) в одной статье (суперподробно)
boy illustration
50,3 тыс. звезд! Immich: автономное решение для резервного копирования фотографий и видео, которое экономит деньги и избавляет от беспокойства.
boy illustration
Cloud Native|Практика: установка Dashbaord для K8s, графика неплохая
boy illustration
Краткий обзор статьи — использование синтетических данных при обучении больших моделей и оптимизации производительности
boy illustration
MiniPerplx: новая поисковая система искусственного интеллекта с открытым исходным кодом, спонсируемая xAI и Vercel.
boy illustration
Конструкция сервиса Synology Drive сочетает проникновение в интрасеть и синхронизацию папок заметок Obsidian в облаке.
boy illustration
Центр конфигурации————Накос
boy illustration
Начинаем с нуля при разработке в облаке Copilot: начать разработку с минимальным использованием кода стало проще
boy illustration
[Серия Docker] Docker создает мультиплатформенные образы: практика архитектуры Arm64
boy illustration
Обновление новых возможностей coze | Я использовал coze для создания апплета помощника по исправлению домашних заданий по математике
boy illustration
Советы по развертыванию Nginx: практическое создание статических веб-сайтов на облачных серверах
boy illustration
Feiniu fnos использует Docker для развертывания личного блокнота Notepad
boy illustration
Сверточная нейронная сеть VGG реализует классификацию изображений Cifar10 — практический опыт Pytorch
boy illustration
Начало работы с EdgeonePages — новым недорогим решением для хостинга веб-сайтов
boy illustration
[Зона легкого облачного игрового сервера] Управление игровыми архивами
boy illustration
Развертывание SpringCloud-проекта на базе Docker и Docker-Compose