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

84

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

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

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

Bananenbär
источник

Ответы:

299

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


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

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

Пакеты называются модулями уровня абстракции сети. Часто сокращенно 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являются незаконными в не-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 предшествует его длина (в формате big endian). Этот метод легче анализировать, но вы теряете возможности выравнивания байтов, указанные в Приложении 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.

сатмари
источник
3
Спасибо, мужик, этот мне действительно помог! Хотя в вашей статье есть некоторые опечатки ... Я думаю;) Иногда вы называете VCL «VLC», что может сбивать с толку, потому что я знаю VLC как «кодирование переменной длины». Но все же ваша статья прояснила для меня несколько вещей, хорошая работа! И ... извините, я не могу проголосовать за вас, я здесь новенький, и здесь есть какой-то фильтр newbe;)
bananenbär
6
Да, извините за опечатки. Я немного страдаю дислексией и очень плохая машинистка. Ты прав. VLC нет места в этом тексте.
szatmary
2
Отличное резюме! Это мне действительно помогло. Хотя это очевидно, если внимательно посмотреть на 2-й (AVCC) набор байтов, я думаю, стоит отметить, что значение длины в 4 байта, которое предшествует данным NALU, находится в формате Big-Endian. Я не мог заставить поток декодироваться на iOS, пока не понял, что значение длины нужно менять местами байтов.
2014,
1
Большое спасибо, чувак! Кстати, декодеру Windows Media Foundation h264 нужны только образцы «Приложения B». К счастью, преобразовать их между приложением B и AVCC довольно просто.
Soonts
2
Отсутствует ли нулевой байт по смещению 0x0022 в примере дополнительных данных AVCC? В описании формата сказано, что для размера PPS есть 16-битное поле, поэтому я думаю, что это должно быть, 0x00 0x07а не просто 0x07.
rhashimoto