Возможные местоположения для набора (ей) параметров последовательности / изображения для потока H.264

Я работаю над декодером H.264, и мне интересно, где найти SPS и PPS. Моя справочная литература говорит мне, что это NAL-единицы, закодированные в H.264-Stream, но когда я смотрю на файл-пример MP4 с IsoViewer, он говорит, что SPS и PPS находятся в блоке avcC.

Как именно это работает? Как это выглядит для файлов.mkv или других контейнеров H.264?

Заранее спасибо!

2 ответа

Решение

Во-первых, важно понимать, что не существует единого стандартного элементарного формата битового потока H.264. Документ спецификации содержит Приложение, в частности Приложение B, в котором описывается один возможный формат, но это не является фактическим требованием. Стандарт определяет, как видео кодируется в отдельные пакеты. Как эти пакеты хранятся и передаются, остается открытым для интегратора.


1. Приложение Б

Сетевые единицы уровня абстракции

Пакеты называются Единицами Уровня Абстракции Сети. Часто сокращенно NALU (или иногда просто NAL) каждый пакет может быть индивидуально проанализирован и обработан. Первый байт каждого NALU содержит тип NALU, в частности, биты с 3 по 7. (бит 0 всегда выключен, а биты 1-2 указывают, ссылается ли NALU на другой NALU).

Существует 19 различных типов NALU, разделенных на две категории: VCL и не VCL:

  • Пакеты VCL или Video Coding Layer содержат фактическую визуальную информацию.
  • Номера для VCL содержат метаданные, которые могут или не могут потребоваться для декодирования видео.

Один NALU или даже VCL NALU - это НЕ то же самое, что кадр. Кадр может быть "разрезан" на несколько блоков NALU. Также как вы можете нарезать пиццу. Один или несколько слайсов затем виртуально группируются в блоки доступа (AU), которые содержат один кадр. Нарезка имеет небольшую стоимость, поэтому ее не часто используют.

Ниже приведена таблица всех определенных NALU.

0      Unspecified                                                    non-VCL
1      Coded slice of a non-IDR picture                               VCL
2      Coded slice data partition A                                   VCL
3      Coded slice data partition B                                   VCL
4      Coded slice data partition C                                   VCL
5      Coded slice of an IDR picture                                  VCL
6      Supplemental enhancement information (SEI)                     non-VCL
7      Sequence parameter set                                         non-VCL
8      Picture parameter set                                          non-VCL
9      Access unit delimiter                                          non-VCL
10     End of sequence                                                non-VCL
11     End of stream                                                  non-VCL
12     Filler data                                                    non-VCL
13     Sequence parameter set extension                               non-VCL
14     Prefix NAL unit                                                non-VCL
15     Subset sequence parameter set                                  non-VCL
16     Depth parameter set                                            non-VCL
17..18 Reserved                                                       non-VCL
19     Coded slice of an auxiliary coded picture without partitioning non-VCL
20     Coded slice extension                                          non-VCL
21     Coded slice extension for depth view components                non-VCL
22..23 Reserved                                                       non-VCL
24..31 Unspecified                                                    non-VCL

Есть пара типов NALU, где знание может быть полезно позже.

  • Набор параметров последовательности (SPS). Это не VCL NALU содержит информацию, необходимую для настройки декодера, такую ​​как профиль, уровень, разрешение, частота кадров.
  • Набор параметров изображения (PPS). Подобно SPS, этот не-VCL содержит информацию о режиме энтропийного кодирования, группах слайсов, фильтрах предсказания движения и деблокирования.
  • Мгновенное обновление декодера (IDR). Этот VCL NALU является автономным фрагментом изображения. Таким образом, IDR может быть декодирован и отображен без ссылки на любой другой NALU, кроме SPS и PPS.
  • Разделитель доступа (AUD). AUD - это необязательный NALU, который можно использовать для разделения кадров в элементарном потоке. Это не требуется (если иное не указано контейнером / протоколом, таким как TS), и часто не включается для экономии места, но может быть полезно найти начало кадра без необходимости полного разбора каждого NALU.

Стартовые коды NALU

NALU не содержит его размер. Поэтому простая конкатенация NALU для создания потока не будет работать, потому что вы не будете знать, где останавливается один и начинается следующий.

Спецификация Приложения B решает эту проблему, требуя, чтобы "Начальные коды" предшествовали каждому NALU. Стартовый код 2 или 3 0x00 байты следуют с 0x01 байт. например 0x000001 или же 0x00000001,

4-байтовое изменение полезно для передачи по последовательному соединению, поскольку тривиально выравнивание потока по байту выполняется путем поиска 31 нулевого бита, за которым следует один. Если следующий бит равен 0 (потому что каждый NALU начинается с 0 бита), это начало NALU. 4-байтовое изменение обычно используется только для сигнализации точек произвольного доступа в потоке, таких как SPS PPS AUD и IDR, где 3-байтовое изменение используется повсеместно для экономии места.

Байты предотвращения эмуляции

Начальные коды работают, потому что четыре байта последовательности 0x000000, 0x000001, 0x000002 а также 0x000003 являются незаконными в пределах NALU не RBSP. Поэтому при создании NALU необходимо избегать этих значений, которые в противном случае можно было бы спутать со стартовым кодом. Это достигается путем вставки байта "Предотвращение эмуляции" 0x03, чтобы 0x000001 становится 0x00000301,

При декодировании важно искать и игнорировать байты предотвращения эмуляции. Поскольку байты предотвращения эмуляции могут возникать практически в любом месте NALU, в документации часто удобнее предположить, что они уже удалены. Представление без байтов предотвращения эмуляции называется полезной нагрузкой последовательности необработанных байтов (RBSP).

пример

Давайте посмотрим на полный пример.

0x0000 | 00 00 00 01 67 64 00 0A AC 72 84 44 26 84 00 00
0x0010 | 03 00 04 00 00 03 00 CA 3C 48 96 11 80 00 00 00
0x0020 | 01 68 E8 43 8F 13 21 30 00 00 01 65 88 81 00 05
0x0030 | 4E 7F 87 DF 61 A5 8B 95 EE A4 E9 38 B7 6A 30 6A
0x0040 | 71 B9 55 60 0B 76 2E B5 0E E4 80 59 27 B8 67 A9
0x0050 | 63 37 5E 82 20 55 FB E4 6A E9 37 35 72 E2 22 91
0x0060 | 9E 4D FF 60 86 CE 7E 42 B7 95 CE 2A E1 26 BE 87
0x0070 | 73 84 26 BA 16 36 F4 E6 9F 17 DA D8 64 75 54 B1
0x0080 | F3 45 0C 0B 3C 74 B3 9D BC EB 53 73 87 C3 0E 62
0x0090 | 47 48 62 CA 59 EB 86 3F 3A FA 86 B5 BF A8 6D 06
0x00A0 | 16 50 82 C4 CE 62 9E 4E E6 4C C7 30 3E DE A1 0B
0x00B0 | D8 83 0B B6 B8 28 BC A9 EB 77 43 FC 7A 17 94 85
0x00C0 | 21 CA 37 6B 30 95 B5 46 77 30 60 B7 12 D6 8C C5
0x00D0 | 54 85 29 D8 69 A9 6F 12 4E 71 DF E3 E2 B1 6B 6B
0x00E0 | BF 9F FB 2E 57 30 A9 69 76 C4 46 A2 DF FA 91 D9
0x00F0 | 50 74 55 1D 49 04 5A 1C D6 86 68 7C B6 61 48 6C
0x0100 | 96 E6 12 4C 27 AD BA C7 51 99 8E D0 F0 ED 8E F6
0x0110 | 65 79 79 A6 12 A1 95 DB C8 AE E3 B6 35 E6 8D BC
0x0120 | 48 A3 7F AF 4A 28 8A 53 E2 7E 68 08 9F 67 77 98
0x0130 | 52 DB 50 84 D6 5E 25 E1 4A 99 58 34 C7 11 D6 43
0x0140 | FF C4 FD 9A 44 16 D1 B2 FB 02 DB A1 89 69 34 C2
0x0150 | 32 55 98 F9 9B B2 31 3F 49 59 0C 06 8C DB A5 B2
0x0160 | 9D 7E 12 2F D0 87 94 44 E4 0A 76 EF 99 2D 91 18
0x0170 | 39 50 3B 29 3B F5 2C 97 73 48 91 83 B0 A6 F3 4B
0x0180 | 70 2F 1C 8F 3B 78 23 C6 AA 86 46 43 1D D7 2A 23
0x0190 | 5E 2C D9 48 0A F5 F5 2C D1 FB 3F F0 4B 78 37 E9
0x01A0 | 45 DD 72 CF 80 35 C3 95 07 F3 D9 06 E5 4A 58 76
0x01B0 | 03 6C 81 20 62 45 65 44 73 BC FE C1 9F 31 E5 DB
0x01C0 | 89 5C 6B 79 D8 68 90 D7 26 A8 A1 88 86 81 DC 9A
0x01D0 | 4F 40 A5 23 C7 DE BE 6F 76 AB 79 16 51 21 67 83
0x01E0 | 2E F3 D6 27 1A 42 C2 94 D1 5D 6C DB 4A 7A E2 CB
0x01F0 | 0B B0 68 0B BE 19 59 00 50 FC C0 BD 9D F5 F5 F8
0x0200 | A8 17 19 D6 B3 E9 74 BA 50 E5 2C 45 7B F9 93 EA
0x0210 | 5A F9 A9 30 B1 6F 5B 36 24 1E 8D 55 57 F4 CC 67
0x0220 | B2 65 6A A9 36 26 D0 06 B8 E2 E3 73 8B D1 C0 1C
0x0230 | 52 15 CA B5 AC 60 3E 36 42 F1 2C BD 99 77 AB A8
0x0240 | A9 A4 8E 9C 8B 84 DE 73 F0 91 29 97 AE DB AF D6
0x0250 | F8 5E 9B 86 B3 B3 03 B3 AC 75 6F A6 11 69 2F 3D
0x0260 | 3A CE FA 53 86 60 95 6C BB C5 4E F3

Это полный AU, содержащий 3 NALU. Как видите, мы начинаем с кода запуска, за которым следует SPS (SPS начинается с 67). Внутри SPS вы увидите два байта предотвращения эмуляции. Без этих байтов недопустимая последовательность 0x000000 будет происходить на этих позициях. Далее вы увидите стартовый код, за которым следует PPS (PPS начинается с 68) и один финальный стартовый код, за которым следует фрагмент IDR. Это полный поток H.264. Если вы введете эти значения в шестнадцатеричный редактор и сохраните файл с .264 расширение, вы сможете преобразовать его в это изображение:

Лена

Приложение B обычно используется в живом и потоковом форматах, таких как транспортные потоки, эфирное вещание и DVD-диски. В этих форматах обычно периодически повторяют SPS и PPS, обычно перед каждым IDR, создавая точку произвольного доступа для декодера. Это дает возможность присоединиться к потоку, который уже выполняется.


2. AVCC

Другим распространенным методом хранения потока H.264 является формат AVCC. В этом формате каждому NALU предшествует его длина (в формате с прямым порядком байтов). Этот метод проще анализировать, но вы теряете функции выравнивания байтов в Приложении B. Просто, чтобы усложнить ситуацию, длина может быть закодирована с использованием 1, 2 или 4 байтов. Это значение хранится в объекте заголовка. Этот заголовок часто называют "экстраданными" или "заголовком последовательности". Его основной формат выглядит следующим образом:

bits    
8   version ( always 0x01 )
8   avc profile ( sps[0][1] )
8   avc compatibility ( sps[0][2] )
8   avc level ( sps[0][3] )
6   reserved ( all bits on )
2   NALULengthSizeMinusOne
3   reserved ( all bits on )
5   number of SPS NALUs (usually 1)
repeated once per SPS:
  16     SPS size
  variable   SPS NALU data
8   number of PPS NALUs (usually 1)
repeated once per PPS
  16    PPS size
  variable PPS NALU data

Используя тот же пример выше, дополнительные данные AVCC будут выглядеть так:

0x0000 | 01 64 00 0A FF E1 00 19 67 64 00 0A AC 72 84 44
0x0010 | 26 84 00 00 03 00 04 00 00 03 00 CA 3C 48 96 11
0x0020 | 80 01 00 07 68 E8 43 8F 13 21 30

Вы заметите, что SPS и PPS теперь хранятся вне диапазона. То есть отдельно от элементарных потоков данных. Хранение и передача этих данных является задачей файлового контейнера и выходит за рамки этого документа. Обратите внимание, что, хотя мы не используем стартовые коды, байты предотвращения эмуляции по-прежнему вставляются.

Кроме того, есть новая переменная под названием NALULengthSizeMinusOne, Эта переменно-названная переменная сообщает нам, сколько байтов нужно использовать для хранения длины каждого NALU. Так что если NALULengthSizeMinusOne устанавливается в 0, тогда каждому NALU предшествует один байт, указывающий его длину. При использовании одного байта для хранения размера максимальный размер NALU составляет 255 байтов. Это, очевидно, довольно мало. Слишком маленький для целого ключевого кадра. Использование 2 байтов дает нам 64 КБ за NALU. Это будет работать в нашем примере, но все еще довольно низкий предел. 3 байта были бы идеальными, но по некоторым причинам не универсально поддерживаются. Поэтому 4 байта на сегодняшний день являются наиболее распространенными, и это то, что мы использовали здесь:

0x0000 | 00 00 02 41 65 88 81 00 05 4E 7F 87 DF 61 A5 8B
0x0010 | 95 EE A4 E9 38 B7 6A 30 6A 71 B9 55 60 0B 76 2E
0x0020 | B5 0E E4 80 59 27 B8 67 A9 63 37 5E 82 20 55 FB
0x0030 | E4 6A E9 37 35 72 E2 22 91 9E 4D FF 60 86 CE 7E
0x0040 | 42 B7 95 CE 2A E1 26 BE 87 73 84 26 BA 16 36 F4
0x0050 | E6 9F 17 DA D8 64 75 54 B1 F3 45 0C 0B 3C 74 B3
0x0060 | 9D BC EB 53 73 87 C3 0E 62 47 48 62 CA 59 EB 86
0x0070 | 3F 3A FA 86 B5 BF A8 6D 06 16 50 82 C4 CE 62 9E
0x0080 | 4E E6 4C C7 30 3E DE A1 0B D8 83 0B B6 B8 28 BC
0x0090 | A9 EB 77 43 FC 7A 17 94 85 21 CA 37 6B 30 95 B5
0x00A0 | 46 77 30 60 B7 12 D6 8C C5 54 85 29 D8 69 A9 6F
0x00B0 | 12 4E 71 DF E3 E2 B1 6B 6B BF 9F FB 2E 57 30 A9
0x00C0 | 69 76 C4 46 A2 DF FA 91 D9 50 74 55 1D 49 04 5A
0x00D0 | 1C D6 86 68 7C B6 61 48 6C 96 E6 12 4C 27 AD BA
0x00E0 | C7 51 99 8E D0 F0 ED 8E F6 65 79 79 A6 12 A1 95
0x00F0 | DB C8 AE E3 B6 35 E6 8D BC 48 A3 7F AF 4A 28 8A
0x0100 | 53 E2 7E 68 08 9F 67 77 98 52 DB 50 84 D6 5E 25
0x0110 | E1 4A 99 58 34 C7 11 D6 43 FF C4 FD 9A 44 16 D1
0x0120 | B2 FB 02 DB A1 89 69 34 C2 32 55 98 F9 9B B2 31
0x0130 | 3F 49 59 0C 06 8C DB A5 B2 9D 7E 12 2F D0 87 94
0x0140 | 44 E4 0A 76 EF 99 2D 91 18 39 50 3B 29 3B F5 2C
0x0150 | 97 73 48 91 83 B0 A6 F3 4B 70 2F 1C 8F 3B 78 23
0x0160 | C6 AA 86 46 43 1D D7 2A 23 5E 2C D9 48 0A F5 F5
0x0170 | 2C D1 FB 3F F0 4B 78 37 E9 45 DD 72 CF 80 35 C3
0x0180 | 95 07 F3 D9 06 E5 4A 58 76 03 6C 81 20 62 45 65
0x0190 | 44 73 BC FE C1 9F 31 E5 DB 89 5C 6B 79 D8 68 90
0x01A0 | D7 26 A8 A1 88 86 81 DC 9A 4F 40 A5 23 C7 DE BE
0x01B0 | 6F 76 AB 79 16 51 21 67 83 2E F3 D6 27 1A 42 C2
0x01C0 | 94 D1 5D 6C DB 4A 7A E2 CB 0B B0 68 0B BE 19 59
0x01D0 | 00 50 FC C0 BD 9D F5 F5 F8 A8 17 19 D6 B3 E9 74
0x01E0 | BA 50 E5 2C 45 7B F9 93 EA 5A F9 A9 30 B1 6F 5B
0x01F0 | 36 24 1E 8D 55 57 F4 CC 67 B2 65 6A A9 36 26 D0
0x0200 | 06 B8 E2 E3 73 8B D1 C0 1C 52 15 CA B5 AC 60 3E
0x0210 | 36 42 F1 2C BD 99 77 AB A8 A9 A4 8E 9C 8B 84 DE
0x0220 | 73 F0 91 29 97 AE DB AF D6 F8 5E 9B 86 B3 B3 03
0x0230 | B3 AC 75 6F A6 11 69 2F 3D 3A CE FA 53 86 60 95
0x0240 | 6C BB C5 4E F3

Преимуществом этого формата является возможность настройки декодера в начале и перехода в середину потока. Это распространенный случай, когда носитель доступен на носителе с произвольным доступом, например на жестком диске, и поэтому используется в стандартных форматах контейнеров, таких как MP4 и MKV.

Я недавно работал над чем-то вроде этого.

Проверьте инспектора mp4. Как вы можете видеть на этом рисунке, у mp4 есть много блоков, которые нужно проанализировать, чтобы найти нужные вам данные.

введите описание изображения здесь

Здесь я пометил части коробки avcc

введите описание изображения здесь

Я только что написал много пост-блог о своей работе с h264. Я думаю, что слишком долго размещать здесь http://cagneymoreau.com/stream-video-android/

Другие вопросы по тегам