Zunächst ist es wichtig zu verstehen, dass es kein einzelnes Standard-H.264-Elementarbitstream-Format gibt. Das Spezifikationsdokument enthält einen Anhang, insbesondere Anhang B, der ein mögliches Format beschreibt, ist jedoch keine tatsächliche Anforderung. Der Standard legt fest, wie Videos in einzelne Pakete codiert werden. Wie diese Pakete gespeichert und übertragen werden, bleibt dem Integrator offen.
1. Anhang B.
Network Abstraction Layer Units
Die Pakete werden als Network Abstraction Layer Units bezeichnet. Oft abgekürzt NALU (oder manchmal nur NAL) kann jedes Paket einzeln analysiert und verarbeitet werden. Das erste Byte jeder NALU enthält den NALU-Typ, insbesondere die Bits 3 bis 7. (Bit 0 ist immer ausgeschaltet, und die Bits 1-2 geben an, ob eine NALU von einer anderen NALU referenziert wird).
Es sind 19 verschiedene NALU-Typen definiert, die in zwei Kategorien unterteilt sind: VCL und Nicht-VCL:
- VCL- oder Video Coding Layer-Pakete enthalten die tatsächlichen visuellen Informationen.
- Nicht-VCLs enthalten Metadaten, die möglicherweise zum Dekodieren des Videos erforderlich sind oder nicht.
Eine einzelne NALU oder sogar eine VCL-NALU ist NICHT dasselbe wie ein Frame. Ein Frame kann in mehrere NALUs unterteilt werden. Genau wie Sie eine Pizza schneiden können. Ein oder mehrere Slices werden dann virtuell zu Access Units (AU) gruppiert, die einen Frame enthalten. Das Schneiden ist mit geringen Qualitätskosten verbunden, daher wird es nicht oft verwendet.
Unten finden Sie eine Tabelle aller definierten 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
Es gibt einige NALU-Typen, bei denen Kenntnisse später hilfreich sein können.
- Sequenzparametersatz (SPS). Diese Nicht-VCL-NALU enthält Informationen, die zum Konfigurieren des Decoders erforderlich sind, z. B. Profil, Pegel, Auflösung und Bildrate.
- Bildparametersatz (PPS). Ähnlich wie die SPS enthält diese Nicht-VCL Informationen zum Entropiecodierungsmodus, zu Slice-Gruppen, zur Bewegungsvorhersage und zu Deblocking-Filtern.
- Instantaneous Decoder Refresh (IDR). Diese VCL-NALU ist eine in sich geschlossene Bildscheibe. Das heißt, ein IDR kann dekodiert und angezeigt werden, ohne auf andere NALU-Speicher-SPS und -PPS zu verweisen.
- Access Unit Delimiter (AUD). Ein AUD ist eine optionale NALU, mit der Frames in einem Elementarstrom abgegrenzt werden können. Es ist nicht erforderlich (sofern im Container / Protokoll nicht anders angegeben, wie z. B. TS) und wird häufig nicht enthalten, um Platz zu sparen. Es kann jedoch nützlich sein, den Anfang eines Frames zu finden, ohne jede NALU vollständig analysieren zu müssen.
NALU-Startcodes
Eine NALU enthält nicht ihre Größe. Daher funktioniert es nicht, die NALUs einfach zu verketten, um einen Stream zu erstellen, da Sie nicht wissen, wo einer aufhört und der nächste beginnt.
Die Spezifikation in Anhang B löst dieses Problem, indem "Startcodes" vor jeder NALU verlangt werden. Ein Startcode besteht aus 2 oder 3 0x00
Bytes, gefolgt von einem 0x01
Byte. zB 0x000001
oder 0x00000001
.
Die 4-Byte-Variante ist nützlich für die Übertragung über eine serielle Verbindung, da es trivial ist, den Stream byteweise auszurichten, indem nach 31 Null-Bits gefolgt von einer Eins gesucht wird. Wenn das nächste Bit 0 ist (weil jede NALU mit einem 0-Bit beginnt), ist dies der Beginn einer NALU. Die 4-Byte-Variante wird normalerweise nur zum Signalisieren von Direktzugriffspunkten im Stream verwendet, z. B. SPS PPS AUD und IDR. Die 3-Byte-Variante wird überall verwendet, um Platz zu sparen.
Emulationsschutzbytes
Startcodes arbeiten , weil die vier Byte - Sequenzen 0x000000
, 0x000001
, 0x000002
und 0x000003
sind illegal in einem nicht-RBSP NALU. Beim Erstellen einer NALU wird daher darauf geachtet, diese Werte zu umgehen, die andernfalls mit einem Startcode verwechselt werden könnten. Dies wird erreicht durch eine ‚Emulation Prävention‘ Byte eingefügt 0x03
, so dass 0x000001
wird 0x00000301
.
Beim Decodieren ist es wichtig, nach Emulationsschutzbytes zu suchen und diese zu ignorieren. Da Emulationsschutzbytes fast überall in einer NALU auftreten können, ist es in der Dokumentation häufig bequemer anzunehmen, dass sie bereits entfernt wurden. Eine Darstellung ohne Emulationsverhinderungsbytes wird als Raw Byte Sequence Payload (RBSP) bezeichnet.
Beispiel
Schauen wir uns ein vollständiges Beispiel an.
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
Dies ist eine vollständige AU mit 3 NALUs. Wie Sie sehen können, beginnen wir mit einem Startcode, gefolgt von einem SPS (SPS beginnt mit 67). Innerhalb der SPS werden zwei Bytes zur Verhinderung der Emulation angezeigt. Ohne diese Bytes würde die unzulässige Sequenz 0x000000
an diesen Positionen auftreten. Als nächstes sehen Sie einen Startcode, gefolgt von einem PPS (PPS beginnt mit 68) und einen endgültigen Startcode, gefolgt von einem IDR-Slice. Dies ist ein vollständiger H.264-Stream. Wenn Sie diese Werte in einen Hex-Editor eingeben und die Datei mit einer .264
Erweiterung speichern , können Sie sie in dieses Bild konvertieren:
Anhang B wird üblicherweise in Live- und Streaming-Formaten wie Transportströmen, drahtlosen Sendungen und DVDs verwendet. In diesen Formaten ist es üblich, SPS und PPS regelmäßig zu wiederholen, normalerweise vor jedem IDR, wodurch ein Direktzugriffspunkt für den Decoder erstellt wird. Dies ermöglicht die Verbindung zu einem bereits laufenden Stream.
2. AVCC
Die andere übliche Methode zum Speichern eines H.264-Streams ist das AVCC-Format. In diesem Format wird jeder NALU ihre Länge vorangestellt (im Big-Endian-Format). Diese Methode ist einfacher zu analysieren, aber Sie verlieren die Byte-Ausrichtungsfunktionen von Anhang B. Um die Sache zu verkomplizieren, kann die Länge mit 1, 2 oder 4 Bytes codiert werden. Dieser Wert wird in einem Header-Objekt gespeichert. Dieser Header wird oft als "Extradaten" oder "Sequenzheader" bezeichnet. Das Grundformat lautet wie folgt:
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
In demselben Beispiel wie oben sehen die AVCC-Extradaten folgendermaßen aus:
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
Sie werden feststellen, dass SPS und PPS jetzt außerhalb des Bandes gespeichert sind. Das heißt, getrennt von den Elementarstromdaten. Die Speicherung und Übertragung dieser Daten ist Aufgabe des Dateicontainers und geht über den Rahmen dieses Dokuments hinaus. Beachten Sie, dass Emulationsschutzbytes immer noch eingefügt werden, obwohl wir keine Startcodes verwenden.
Zusätzlich gibt es eine neue Variable namens NALULengthSizeMinusOne
. Diese verwirrend benannte Variable gibt an, wie viele Bytes zum Speichern der Länge jeder NALU verwendet werden sollen. Wenn NALULengthSizeMinusOne
also 0 gesetzt ist, wird jeder NALU ein einzelnes Byte vorangestellt, das ihre Länge angibt. Bei Verwendung eines einzelnen Bytes zum Speichern der Größe beträgt die maximale Größe einer NALU 255 Byte. Das ist offensichtlich ziemlich klein. Viel zu klein für einen ganzen Schlüsselrahmen. Die Verwendung von 2 Bytes ergibt 64 KB pro NALU. In unserem Beispiel würde es funktionieren, aber es ist immer noch eine ziemlich niedrige Grenze. 3 Bytes wären perfekt, werden aber aus irgendeinem Grund nicht allgemein unterstützt. Daher sind 4 Bytes bei weitem am häufigsten und werden hier verwendet:
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
Ein Vorteil dieses Formats ist die Möglichkeit, den Decoder zu Beginn zu konfigurieren und in die Mitte eines Streams zu springen. Dies ist ein häufiger Anwendungsfall, bei dem das Medium auf einem Direktzugriffsmedium wie einer Festplatte verfügbar ist und daher in gängigen Containerformaten wie MP4 und MKV verwendet wird.
0x00 0x07
statt nur sein0x07
.