H.264 스트림에 대한 시퀀스 / 그림 매개 변수 세트의 가능한 위치


82

H.264 디코더에서 작업 중이며 SPS 및 PPS를 어디에서 찾을 수 있는지 궁금합니다. 내 참고 문헌에 따르면 H.264-Stream으로 인코딩 된 NAL 단위라고 나와 있지만 IsoViewer로 예제 MP4-File을 살펴보면 SPS와 PPS가 avcC 상자에 있다고 나와 있습니다.

정확히 어떻게 작동합니까? .mkv 파일 또는 기타 H.264 컨테이너를 어떻게 찾습니까?

미리 감사드립니다!

답변:


291

먼저, 단일 표준 H.264 기본 비트 스트림 형식이 없다는 것을 이해하는 것이 중요합니다. 사양 문서에는 한 가지 가능한 형식을 설명하는 부록, 특히 부록 B가 포함되어 있지만 실제 요구 사항은 아닙니다. 표준은 비디오가 개별 패킷으로 인코딩되는 방법을 지정합니다. 이러한 패킷이 저장되고 전송되는 방식은 통합 자에게 열려 있습니다.


1. 부록 B

네트워크 추상화 계층 단위

패킷을 네트워크 추상화 계층 단위라고합니다. 종종 축약 된 NALU (또는 때로는 NAL) 각 패킷을 개별적으로 구문 분석하고 처리 할 수 ​​있습니다. 각 NALU의 첫 번째 바이트에는 NALU 유형, 특히 비트 3 ~ 7이 포함됩니다 (비트 0은 항상 꺼져 있고 비트 1-2는 NALU가 다른 NALU에 의해 참조되는지 여부를 나타냄).

19 개의 서로 다른 NALU 유형이 VCL 및 비 VCL의 두 범주로 구분되어 정의됩니다.

  • VCL 또는 비디오 코딩 레이어 패킷에는 실제 시각적 정보가 포함됩니다.
  • 비 VCL에는 비디오 디코딩에 필요하거나 필요하지 않을 수있는 메타 데이터가 포함됩니다.

단일 NALU 또는 VCL NALU는 프레임과 동일하지 않습니다. 프레임은 여러 NALU로 '분할'될 수 있습니다. 피자를자를 수있는 것처럼 요. 그런 다음 하나 이상의 슬라이스가 하나의 프레임을 포함하는 AU (Access Unit)로 가상으로 그룹화됩니다. 슬라이싱은 약간의 품질 비용이 들기 때문에 자주 사용되지 않습니다.

아래는 정의 된 모든 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 (Sequence Parameter Set). 이 비 VCL NALU에는 프로필, 레벨, 해상도, 프레임 속도와 같은 디코더를 구성하는 데 필요한 정보가 포함되어 있습니다.
  • PPS (Picture Parameter Set). SPS와 유사하게이 비 VCL에는 엔트로피 코딩 모드, 슬라이스 그룹, 모션 예측 및 디 블로킹 필터에 대한 정보가 포함되어 있습니다.
  • 순간 디코더 새로 고침 (IDR). 이 VCL NALU는 자체 포함 된 이미지 조각입니다. 즉, 다른 NALU 저장 SPS 및 PPS를 참조하지 않고도 IDR을 디코딩하고 표시 할 수 있습니다.
  • AUD (Access Unit Delimiter). AUD는 기본 스트림에서 프레임을 구분하는 데 사용할 수있는 선택적 NALU입니다. 필요하지 않으며 (TS와 같은 컨테이너 / 프로토콜에서 달리 명시하지 않는 한) 공간을 절약하기 위해 포함되지 않는 경우가 많지만 각 NALU를 완전히 구문 분석하지 않고도 프레임의 시작 부분을 찾는 것이 유용 할 수 있습니다.

NALU 시작 코드

NALU에 포함되지 않은 것은 크기입니다. 따라서 NALU를 연결하여 스트림을 생성하는 것은 어디에서 멈추고 다음이 시작되는지 알 수 없기 때문에 작동하지 않습니다.

Annex B 사양은 각 NALU 앞에 '시작 코드'를 요구하여이를 해결합니다. 시작 코드는 2 0x00바이트 또는 3 바이트 이고 그 뒤에 0x01바이트가 있습니다. 예 : 0x000001또는 0x00000001.

4 바이트 변형은 직렬 연결을 통한 전송에 유용합니다. 31 개의 0 비트 다음에 1을 찾아 스트림을 바이트 정렬하는 것이 사소하기 때문입니다. 다음 비트가 0이면 (모든 NALU가 0 비트로 시작하기 때문에) NALU의 시작입니다. 4 바이트 변형은 일반적으로 SPS PPS AUD 및 IDR과 같은 스트림의 임의 액세스 포인트를 신호하는 데만 사용됩니다. 3 바이트 변형은 공간을 절약하기 위해 다른 모든 곳에서 사용됩니다.

에뮬레이션 방지 바이트

시작 코드가 작동 네 개의 바이트 시퀀스 때문에 0x000000, 0x000001, 0x0000020x000003비 RBSP NALU 내에서 불법입니다. 따라서 NALU를 생성 할 때 시작 코드와 혼동 될 수있는 이러한 값을 이스케이프하도록주의해야합니다. 이것은 '에뮬레이션 방지'바이트를 삽입함으로써 달성된다 0x03즉 있도록 0x000001된다 0x00000301.

디코딩 할 때 에뮬레이션 방지 바이트를 찾아 무시하는 것이 중요합니다. 에뮬레이션 방지 바이트는 NALU 내의 거의 모든 곳에서 발생할 수 있으므로 문서에서 이미 제거되었다고 가정하는 것이 더 편리합니다. 에뮬레이션 방지 바이트가없는 표현을 RBSP (Raw Byte Sequence Payload)라고합니다.

완전한 예를 살펴 보겠습니다.

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를 포함하는 완전한 AU입니다. 보시다시피 시작 코드와 SPS (SPS는 67로 시작)로 시작합니다. SPS 내에 두 개의 에뮬레이션 방지 바이트가 표시됩니다. 이러한 바이트가 없으면 이러한 0x000000위치에서 잘못된 시퀀스 가 발생합니다. 다음으로 시작 코드와 PPS (PPS는 68로 시작), 마지막 시작 코드와 IDR 슬라이스가 차례로 표시됩니다. 이것은 완전한 H.264 스트림입니다. 이러한 값을 16 진 편집기에 입력하고 .264확장자로 파일을 저장하면 다음 이미지로 변환 할 수 있습니다.

레나

Annex B는 일반적으로 전송 스트림, 무선 방송 및 DVD와 같은 라이브 및 스트리밍 형식으로 사용됩니다. 이러한 형식에서는 SPS와 PPS를 정기적으로 반복하여 일반적으로 모든 IDR보다 먼저 반복하여 디코더에 대한 임의 액세스 포인트를 생성하는 것이 일반적입니다. 이를 통해 이미 진행중인 스트림에 참여할 수 있습니다.


2. AVCC

H.264 스트림을 저장하는 또 다른 일반적인 방법은 AVCC 형식입니다. 이 형식에서 각 NALU는 길이 (빅 엔디안 형식)가 앞에옵니다. 이 방법은 파싱하기가 더 쉽지만 Annex B의 바이트 정렬 기능을 잃어 버립니다. 복잡하게하기 위해 길이는 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 바이트를 사용하면 NALU 당 64k가됩니다. 이 예제에서는 작동하지만 여전히 매우 낮은 한계입니다. 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와 같은 일반적인 컨테이너 형식으로 사용됩니다.


2
고마워요, 그 사람이 정말 나를 도왔습니다! 기사에 약간의 입력 오류가 있습니다 ... 제 생각에는;) 때때로 VCL을 'VLC'라고 부르는데, 제가 VLC를 '가변 길이 코딩'으로 알고 있기 때문에 꽤 혼란 스러울 수 있습니다. 그러나 여전히 귀하의 기사는 나를 위해 몇 가지 사항을 정리했습니다. 그리고 ... 투표 할 수 없어서 죄송합니다. 저는 여기 새로 왔고 여기에 일종의 newbe 필터가 있습니다;)
bananenbär

5
예, 오타에 대해 죄송합니다. 나는 약간 난독증이고 매우 가난한 타이피스트입니다. 당신이 올바른지. 이 텍스트에는 VLC가 없습니다.
szatmary

2
대단한 요약! 이것은 정말 나를 도왔습니다. 두 번째 (AVCC) 바이트 집합을 자세히 살펴보면 분명하지만 NALU 데이터 앞에 오는 4 바이트 길이 값이 Big-Endian 형식이라는 점을 지적 할 가치가 있다고 생각합니다. 길이 값이 바이트 스왑되어야한다는 것을 깨달을 때까지 iOS에서 스트림을 디코딩 할 수 없었습니다.
12on

1
고마워요! BTW, Windows Media Foundation h264 디코더는 "Annex B"샘플 만 필요합니다. 다행히도 Annex B와 AVCC간에 변환하는 것은 매우 간단합니다.

2
AVCC extradata 예제의 오프셋 0x0022에 누락 된 0 바이트가 있습니까? 형식 설명 내가이 있어야한다고 생각합니다 그래서 PPS 크기에 대한 16 비트 필드가 말한다 0x00 0x07대신의 0x07.
rhashimoto
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.