Możliwe lokalizacje zestawów parametrów sekwencji / obrazu dla strumienia H.264

84

Pracuję nad dekoderem H.264 i zastanawiam się, gdzie znaleźć SPS i PPS. W mojej literaturze referencyjnej jest mi powiedziane, że są to jednostki NAL zakodowane w strumieniu H.264, ale kiedy patrzę na przykładowy plik MP4 z IsoViewer, mówi, że SPS i PPS są w skrzynce avcC.

Jak dokładnie to działa? Jak to wygląda w przypadku plików .mkv lub innych kontenerów H.264?

Z góry dziękuję!

bananenbär
źródło

Odpowiedzi:

299

Po pierwsze, ważne jest, aby zrozumieć, że nie ma jednego standardowego podstawowego formatu strumienia bitów H.264. Dokument specyfikacji zawiera załącznik, w szczególności załącznik B, który opisuje jeden możliwy format, ale nie jest to faktyczny wymóg. Standard określa sposób kodowania wideo w pojedynczych pakietach. Sposób przechowywania i przesyłania tych pakietów pozostaje otwarty dla integratora.


1. Załącznik B

Jednostki warstwy abstrakcji sieci

Pakiety nazywane są jednostkami warstwy abstrakcji sieci. Często w skrócie NALU (lub czasami po prostu NAL) każdy pakiet może być indywidualnie analizowany i przetwarzany. Pierwszy bajt każdej NALU zawiera typ NALU, a konkretnie bity od 3 do 7. (bit 0 jest zawsze wyłączony, a bity 1-2 wskazują, czy do NALU odwołuje się inny NALU).

Istnieje 19 różnych typów NALU, podzielonych na dwie kategorie, VCL i non-VCL:

  • Pakiety VCL lub Video Coding Layer zawierają rzeczywiste informacje wizualne.
  • Pliki inne niż VCL zawierają metadane, które mogą, ale nie muszą, być wymagane do dekodowania wideo.

Pojedynczy NALU lub nawet VCL NALU to NIE to samo, co rama. Ramkę można „pociąć” na kilka jednostek NALU. Tak jak możesz pokroić pizzę. Jeden lub więcej wycinków jest następnie wirtualnie grupowanych w jednostki dostępu (AU), które zawierają jedną ramkę. Krojenie ma niewielki koszt jakościowy, więc nie jest często używane.

Poniżej znajduje się tabela wszystkich zdefiniowanych jednostek 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

Istnieje kilka typów NALU, których znajomość może być później przydatna.

  • Zestaw parametrów sekwencji (SPS). Ten NALU inny niż VCL zawiera informacje wymagane do skonfigurowania dekodera, takie jak profil, poziom, rozdzielczość, liczba klatek na sekundę.
  • Zestaw parametrów obrazu (PPS). Podobnie jak SPS, ten nie-VCL zawiera informacje o trybie kodowania entropijnego, grupach wycinków, przewidywaniu ruchu i filtrach odblokowujących.
  • Chwilowe odświeżanie dekodera (IDR).Ten VCL NALU jest samodzielnym wycinkiem obrazu. Oznacza to, że IDR może być dekodowany i wyświetlany bez odwoływania się do innych NALU poza SPS i PPS.
  • Ogranicznik jednostki dostępu (AUD). AUD jest opcjonalnym NALU, którego można używać do oddzielania ramek w strumieniu elementarnym. Nie jest to wymagane (chyba że kontener / protokół stanowi inaczej, np. TS) i często nie jest dołączane w celu zaoszczędzenia miejsca, ale może być przydatne znalezienie początku ramki bez konieczności pełnego analizowania każdego NALU.

Kody startowe NALU

NALU nie zawiera jego rozmiaru. Dlatego zwykłe połączenie jednostek NALU w celu utworzenia strumienia nie zadziała, ponieważ nie będziesz wiedział, gdzie jeden się zatrzymuje, a następny zaczyna.

Specyfikacja Aneksu B rozwiązuje ten problem, wymagając, aby „Kody startowe” poprzedzały każdy NALU. Kod startowy składa się z 2 lub 3 0x00bajtów, po których następuje 0x01bajt. np. 0x000001lub0x00000001 . .

Odmiana 4-bajtowa jest przydatna do transmisji przez połączenie szeregowe, ponieważ wyrównanie strumienia poprzez wyszukiwanie 31 bitów zerowych, po których następuje jeden, jest trywialne. Jeśli następny bit ma wartość 0 (ponieważ każdy NALU zaczyna się od bitu 0), jest to początek NALU. Odmiana 4-bajtowa jest zwykle używana tylko do sygnalizowania punktów dostępu swobodnego w strumieniu, takich jak SPS PPS AUD i IDR, przy czym zmiana 3-bajtowa jest używana wszędzie w celu zaoszczędzenia miejsca.

Bajty zapobiegania emulacji

Zacząć działać, ponieważ kody czterech sekwencji bajtów 0x000000, 0x000001, 0x000002i 0x000003są nielegalne w nieprzekraczalnym RBSP Nalu. Dlatego podczas tworzenia NALU zwraca się uwagę na uniknięcie tych wartości, które w przeciwnym razie mogłyby zostać pomylone z kodem startowym. Osiąga się to poprzez wstawienie bajtu „Zapobieganie emulacji” 0x03, tak więc 0x000001staje się0x00000301 .

Podczas dekodowania ważne jest, aby szukać i ignorować bajty zapobiegające emulacji. Ponieważ bajty ochrony przed emulacją mogą występować prawie wszędzie w NALU, w dokumentacji często wygodniej jest założyć, że zostały już usunięte. Reprezentacja bez bajtów zapobiegających emulacji nosi nazwę Raw Byte Sequence Payload (RBSP).

Przykład

Spójrzmy na pełny przykład.

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

To jest kompletna jednostka AU zawierająca 3 jednostki NALU. Jak widać, zaczynamy od kodu startowego, po którym następuje SPS (SPS zaczyna się od 67). W SPS zobaczysz dwa bajty zapobiegania emulacji. Bez tych bajtów niedozwolona sekwencja 0x000000wystąpiłaby na tych pozycjach. Następnie zobaczysz kod startowy, po którym następuje PPS (PPS zaczyna się od 68) i ostatni kod startowy, po którym następuje wycinek IDR. To jest pełny strumień H.264. Jeśli wpiszesz te wartości do edytora szesnastkowego i zapiszesz plik z .264rozszerzeniem, będziesz mógł przekonwertować go na ten obraz:

Lena

Załącznik B jest powszechnie używany w formatach na żywo i strumieniowych, takich jak strumienie transportowe, transmisje radiowe i DVD. W tych formatach powszechne jest okresowe powtarzanie SPS i PPS, zwykle przed każdym IDR, tworząc w ten sposób losowy punkt dostępu dla dekodera. Umożliwia to dołączenie do trwającego już strumienia.


2. AVCC

Inną popularną metodą przechowywania strumienia H.264 jest format AVCC. W tym formacie każdy NALU jest poprzedzony jego długością (w formacie big endian). Ta metoda jest łatwiejsza do przeanalizowania, ale tracisz funkcje wyrównania bajtów z załącznika B. Aby to skomplikować, długość może być zakodowana przy użyciu 1, 2 lub 4 bajtów. Ta wartość jest przechowywana w obiekcie nagłówka. Ten nagłówek jest często nazywany „extradata” lub „sekwencją nagłówka”. Jego podstawowy format jest następujący:

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

Korzystając z tego samego przykładu powyżej, ekstradane AVCC będą wyglądać następująco:

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

Zauważysz, że SPS i PPS są teraz przechowywane poza pasmem. To znaczy oddzielone od podstawowych danych strumieniowych. Przechowywanie i przesyłanie tych danych jest zadaniem kontenera plików i wykracza poza zakres tego dokumentu. Zauważ, że chociaż nie używamy kodów startowych, bajty zapobiegające emulacji są nadal wstawiane.

Dodatkowo istnieje nowa zmienna o nazwie NALULengthSizeMinusOne. Ta myląco nazwana zmienna mówi nam, ile bajtów użyć do przechowywania długości każdego NALU. Tak więc, jeśli NALULengthSizeMinusOnejest ustawiona na 0, to każda jednostka NALU jest poprzedzona jednym bajtem określającym jej długość. Używając jednego bajtu do przechowywania rozmiaru, maksymalny rozmiar NALU to 255 bajtów. To oczywiście dość małe. Zbyt mała dla całej klatki kluczowej. Użycie 2 bajtów daje 64k na NALU. W naszym przykładzie zadziałałoby, ale nadal jest to dość niski limit. 3 bajty byłyby idealne, ale z jakiegoś powodu nie są powszechnie obsługiwane. Dlatego 4 bajty są zdecydowanie najbardziej powszechne i właśnie tego użyliśmy tutaj:

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

Zaletą tego formatu jest możliwość skonfigurowania dekodera na początku i przeskoczenia do środka strumienia. Jest to typowy przypadek użycia, w którym nośnik jest dostępny na nośniku o swobodnym dostępie, takim jak dysk twardy, i dlatego jest używany w popularnych formatach kontenerów, takich jak MP4 i MKV.

szatmary
źródło
3
Dzięki stary, ten naprawdę mi pomógł! Jednak w swoim artykule masz kilka błędów w pisaniu… Myślę;) Czasami nazywasz VCL jako „VLC”, co może być dość zagmatwane, ponieważ znam VLC jako „kodowanie o zmiennej długości”. Mimo to, twój artykuł wyjaśnił mi kilka rzeczy, dobra robota! I ... przepraszam, nie mogę cię zagłosować, jestem tu nowy, a tu jest jakiś filtr dla nowicjuszy;)
bananenbär
6
Tak, przepraszam za literówki. Jestem trochę dyslektykiem i bardzo kiepską maszynistką. Masz rację. VLC nie ma miejsca w tym tekście.
szatmary 23.07.14
2
Świetne podsumowanie! To naprawdę mi pomogło. Chociaż jest oczywiste, jeśli przyjrzeć się bliżej drugiemu (AVCC) zestawowi bajtów, myślę, że warto zauważyć, że 4-bajtowa wartość długości, która poprzedza dane NALU, jest w formacie Big-Endian. Nie mogłem zdekodować strumienia w systemie iOS, dopóki nie zdałem sobie sprawy, że wartość długości musi zostać zamieniona bajtami.
2014
1
Dzięki wielkie! Przy okazji, dekoder Windows Media Foundation h264 potrzebuje tylko próbek „Annex B”. Na szczęście konwersja między Aneksem B i AVCC jest dość prosta.
Soonts
2
Czy brakuje bajtu zerowego w pozycji 0x0022 w przykładzie ekstradanych AVCC? Opis formatu mówi, że istnieje 16-bitowe pole dla rozmiaru PPS, więc myślę, że powinno to być 0x00 0x07zamiast tylko 0x07.
rhashimoto