По-перше, важливо зрозуміти, що не існує єдиного стандартного формату елементарного потоку бітів H.264. Технічний документ містить додаток, зокрема Додаток B, який описує один із можливих форматів, але це не є фактичною вимогою. Стандарт визначає спосіб кодування відео в окремі пакети. Те, як ці пакети зберігаються та передаються, залишається відкритим для інтегратора.
1. Додаток В
Одиниці рівня мережевої абстракції
Пакети називаються мережевими одиницями рівня абстракції. Часто скорочений NALU (або іноді просто NAL) кожен пакет може бути проаналізований та оброблений окремо. Перший байт кожного NALU містить тип NALU, зокрема біти від 3 до 7. (біт 0 завжди вимкнений, а біти 1-2 вказують, чи посилається на NALU інший NALU).
Визначено 19 різних типів NALU, розділених на дві категорії, VCL та non-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 для створення потоку не буде працювати, оскільки ви не будете знати, де зупиняється, а починається наступний.
Специфікація Додатка В вирішує це, вимагаючи, щоб перед кожним 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, часто в документації зручніше вважати, що вони вже були видалені. Представлення без байтів запобігання емуляції називається Raw Byte Sequence Payload (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
Це повний АС, що містить 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). Цей метод легше аналізувати, але ви втрачаєте функції вирівнювання байтів у Додатку В. Просто для того, щоб ускладнити ситуацію, довжина може кодуватися за допомогою 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.