Возможные местоположения для набора(ов) параметров последовательности/изображения для потока H. 264
Я работаю над декодером H. 264, и мне интересно, где найти SPS и PPS. Моя справочная литература говорит мне, что это конечные единицы, закодированные в потоке H. 264, но когда я смотрю в пример-MP4-файл с IsoViewer, он говорит, что SPS и PPS находятся в поле avcC.
Как именно это работает? Как это выглядит .файлы mkv или другие контейнеры H. 264?
спасибо заранее!
2 ответа:
во-первых, важно понимать, что нет единого стандартного формата элементарного битового потока H. 264. В документе спецификации содержится приложение, в частности приложение в, в котором описывается один из возможных форматов, но это не является фактическим требованием. Стандарт определяет как видео кодируется в отдельные пакеты. Как эти пакеты хранятся и передаются на интегратор.
1. Приложение В
Уровень Абстракции Сети Единицы
пакеты называются блоками уровня сетевой абстракции. Часто сокращенный NALU (или иногда просто NAL) каждый пакет может быть индивидуально проанализирован и обработан. Первый байт каждого NALU содержит тип NALU, в частности биты с 3 по 7. (бит 0 всегда выключен, а биты 1-2 указывают, ссылается ли на NALU другой NALU).
существует 19 различных типов NALU, разделенных на две категории, VCL и non-VCL:
- VCL, или пакеты уровня кодирования видео содержат фактическую визуальную информацию.
- не-VCLs содержат метаданные, которые могут или не могут потребоваться для декодирования видео.
один NALU или даже VCL NALU-это не то же самое, что фрейм. Рамку можно "нарезать" на несколько частей. Как вы можете нарезать пиццу. Один или несколько срезов затем фактически группируются в блоки доступа (AU), которые содержат один кадр. Нарезка действительно идет по небольшой стоимости качества, поэтому это не часто используемый.
Ниже приведена таблица всех определенных NALUs.
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, этот non-VCL содержит информацию о режим энтропийного кодирования, группы срезов, предсказание движения и деблокирующие фильтры.
- мгновенное обновление декодера (IDR). этот VCL NALU является автономным фрагментом изображения. То есть IDR может быть декодирован и отображен без ссылки на любые другие NALU save SPS и PPS.
- разделитель блока доступа (AUD). AUD-это необязательный NALU, который можно использовать для разделения кадров в элементарном потоке. Не требуется (если иное не предусмотрено контейнер / протокол, например TS), и часто не включается для экономии места, но может быть полезно найти начало кадра без необходимости полного разбора каждого NALU.
коды запуска NALU
NALU не содержит его размер. Поэтому простое объединение NALUs для создания потока не будет работать, потому что вы не будете знать, где заканчивается один и начинается следующий.
спецификация приложения B решает эту проблему, требуя, чтобы "коды запуска" перед каждой НАОУ. Стартовый код-2 или 3
0x00
байты следуют с0x01
байт. например,0x000001
или0x00000001
.4-байтовое изменение полезно для передачи по последовательному соединению, поскольку тривиально выровнять поток байтом, ища 31 нулевой бит, за которым следует один. Если следующий бит равен 0 (потому что каждый NALU начинается с 0 бит), это начало NALU. 4-байтовое изменение обычно используется только для сигнализации точек произвольного доступа в потоке, таких как SPS PPS AUD и IDR, где в качестве 3-байтового варианта используется везде, чтобы сэкономить место.
Байты Предотвращения Эмуляции
коды запуска работают, потому что четыре байтовые последовательности
0x000000
,0x000001
,0x000002
и0x000003
являются незаконными в рамках не-RBSP NALU. Поэтому при создании NALU необходимо позаботиться о том, чтобы избежать этих значений, которые в противном случае можно было бы спутать с начальным кодом. Это достигается путем вставки байта 'Emulation Prevention'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
это a полный АС, содержащий 3 Налу. Как вы можете видеть, мы начинаем с кода запуска, за которым следует 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 байтов. Это значение хранится в объекте заголовка. Этот заголовок часто называют ‘дополнительные данные [extradata]’ или ‘заголовок последовательности’. Его основной формат выглядит следующим образом:
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 байт дает нам 64k за 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/