2012-03-08 22 views
10

Mam surowy H.264 strumień z kamery IP pakowane w ramkach RTP. Chcę uzyskać surowe dane H.264 w pliku, aby móc go przekonwertować na ffmpeg.H.264 nad RTP - Określenie SPS i PPS ramek

Więc kiedy chcemy zapisać dane do mojego surowego pliku H.264 I okazało się, że musi wyglądać następująco:

00 00 01 [SPS] 
00 00 01 [PPS] 
00 00 01 [NALByte] 
[PAYLOAD RTP Frame 1]  // Payload always without the first 2 Bytes -> NAL 
[PAYLOAD RTP Frame 2] 
[... until PAYLOAD Frame with Mark Bit received] // From here its a new Video Frame 
00 00 01 [NAL BYTE] 
[PAYLOAD RTP Frame 1] 
.... 

Więc uzyskać SPS i PPS z Session Description Protocol z mojego poprzedzające komunikację RTSP. Dodatkowo kamera wysyła SPS i PPS w dwóch pojedynczych wiadomościach przed rozpoczęciem samego strumienia wideo.

Więc przechwytywania komunikatów w tej kolejności:

1. Preceding RTSP Communication here (including SDP with SPS and PPS) 
2. RTP Frame with Payload: 67 42 80 28 DA 01 40 16 C4 // This is the SPS 
3. RTP Frame with Payload: 68 CE 3C 80     // This is the PPS 
4. RTP Frame with Payload: ... // Video Data 

Potem przyszedł kilka ramek z ładowność i w pewnym momencie ramce RTP z Marker Bit = 1. Oznacza to (jeśli mam rację), że mam pełną klatkę wideo. Afer to piszę Sequence prefiksu (00 00 01) i NAL z ładunkiem i znowu iść dalej z tą samą procedurą.

Teraz mój aparat przesyła mi po każdych 8 kompletnych ramkach wideo SPS i PPS ponownie. (Znowu w dwóch Ramkach RTP, jak widać w powyższym przykładzie). Wiem, że szczególnie PPS może zmieniać pomiędzy strumieniowaniem, ale to nie problem.

Moje pytania są teraz:

1. Czy muszę pisać SPS/PPS co 8 klatki wideo?

Jeśli moja SPS i mój PPS nie zmieni to powinno wystarczyć mieć napisane na samym początku mojego pliku i nic więcej?

2. Jak odróżnić SPS/PPS i normalnej RTP Frames?

W moim C++ Code, który analizuje przesyłane dane, potrzebuję zrobić różnicę między ramkami RTP z normalnym ładunkiem, a tymi niosącymi SPS/PPS. Jak mogę je odróżnić? Dobrze, że klatki SPS/PPS są zwykle dużo mniejsze, ale nie jest to połączenie, na którym można polegać. Ponieważ jeśli je zignoruję, muszę wiedzieć, które dane mogę wyrzucić, lub jeśli muszę je zapisać, muszę umieścić przed nimi prefiks 00 00 01. ? Czy jest to ustalona reguła, że ​​występują one co 8 klatek wideo?

+0

Dziękuję za to pytanie. Mam takie samo pytanie jak ty. Czytam kod źródłowy live555 i nie wiem, dlaczego zapisują każdy taki pakiet/ramkę. Po przeczytaniu tego wątku sprawy stają się dla mnie jasne. Jako sugestię opartą na implementacji live555, bit znacznikowy jest używany tylko w innych kodekach, H264 ma własne wartości początkowe i końcowe, które reprezentują początek/koniec ramki, bit znacznikowy nie jest używany dla H264. – user534498

Odpowiedz

10
  1. Jeśli SPS i PPS nie zmieniają, można je pominąć wyjątkiem 1st nich.
  2. Trzeba analizować pole nal_unit_type każdego NAL dla SPS, nal_unit_type == 7; dla PPS, nal_unit_type == 8.

Jak pamiętam, nal_unit_type to 5-bitowe bity pierwszego bajtu ramki.

nal_unit_type = frame[0] & 0x1f; 
+0

To oznaczałoby, że pierwsze 2 bajty ramki 'SPS' i' PPS' są również pewnego rodzaju "statusem NAL", podobnie jak pierwsze dwa bajty każdej innej ramki RTP? Lub innymi słowy - pole nal_unit_type, w którym oczekuję 7 lub 8 dla SPS, a PPS to to samo pole, w którym spodziewam się 28, co oznacza dane wideo? – Toby

+2

Aby uzyskać szczegółową definicję parametru nal_unit_type, możesz odwołać się do dokumentu H.264. btw, (ładunek [0] i 0x1f) == 28 oznacza, że ​​jest to fragmentacja klatki wideo, w tej sytuacji rzeczywisty typ parametru nal_unit powinien być (ładunek [1] i 0x1f). Jest to zdefiniowane w RFC3984. – ciphor

+0

Tak, po prostu to przeczytałem i otrzymałem ... ale skąd wiadomo, że nal_unit_type = 28 to fragmentacja klatki wideo? RFC 3984 odnosi się do http://www-ee.uta.edu/dip/courses/ee5356/H264systems.pdf Tabela 7.1 (strona 63) - tam kod 28 byłby pod "Nieokreślony" ..? – Toby

10
  1. Należy napisać SPS i PPS na początku strumienia, i tylko wtedy, gdy zmieni się w środku strumienia.

  2. SPS oraz PPS są zapakowane w jednostce STAP NAL (zazwyczaj STAP-A) z NAL typu 24 (STAP-A) lub 25 (STAP B) Schemat STAP opisano w RFC-3984 section 5.7.1

  3. Don polegać na bicie znacznika, używać bitów początkowych i końcowych w nagłówku NAL.

  4. pofragmentowane klatek należy regenerować jednostki NAL, stosując 3 NAL bitów jednostkowych pierwszego fragmentu (F PIB), oraz z 5 NAL bitów typu pierwszego bajtu w bloku danych (tylko dla pakietów, z bitem początkowym wartość 1) wyboru RFC-3984 section 5.8:

    NAL typu urządzenia oktet rozdrobnionym jednostki NAL nie jest zawarty w takiej postaci w urządzeniu fragmentacji ładunek, lecz informacje oktetu typem jednostki NAL z rozdrobnionym jednostki NAL jest przenoszony Pola F i NRI oktetu wskaźnika FU w polu typu Nagłówek FU.

Edycja: więcej wyjaśnienie dotyczące budowy jednostki NAL dla jednostek fragmentacji:

to pierwsze dwa bajty fu-blok danych (z prawej po nagłówku RTP):

| FU indicator | FU header | 
+---------------+---------------+ 
|0|1|2|3|4|5|6|7|0|1|2|3|4|5|6|7| 
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 
|F|NRI| Type |S|E|R| Type | 
+---------------+---------------+ 

skonstruować jednostkę NAL należy wziąć "Typ" od "FU Header" i "F" i "NRI" od "FU wskaźnik"

here to prosta implementacja

+0

Czy możesz wyjaśnić element 4? Czytałem tę sekcję specyfikacji i notowania, które cytowałeś kilka razy i nie rozumiem, co one opisują. Czy oznacza to, że wskaźnik FU powinien zostać zrekonstruowany na podstawie tych reguł, a nagłówek FU odrzucony, a pierwsze 5 bitów ładunku odrzucone, a teraz zrekonstruowany wskaźnik FU być połączony z ładunkiem (minus pierwsze 5 bitów)?Dziękuję – Joshua

+1

@Joshua: Dodałem trochę więcej wyjaśnień –

+0

Dziękuję, przykład kodu jest bardzo elegancki i doceniam twoje uproszczone wyjaśnienie. Z perspektywy czasu cytowany przez ciebie cytat jest prosty, ale twoje wyjaśnienie w punkcie 4 sugeruje użycie bitów z ładunku, stąd moje pomyłki. Teraz rozumiem, co masz na myśli. – Joshua

Powiązane problemy