Vị trí có thể cho (các) Bộ thông số trình tự / hình ảnh cho Luồng H.264


82

Tôi đang làm việc trên Bộ giải mã H.264 và tôi đang băn khoăn không biết tìm SPS và PPS ở đâu. Tài liệu tham khảo của tôi cho tôi biết rằng đó là các Đơn vị NAL được mã hóa trong H.264-Stream, nhưng khi tôi xem xét ví dụ-MP4-File với IsoViewer, nó cho biết rằng SPS và PPS nằm trong Hộp avcC.

Làm thế nào chính xác để làm việc này? Nó tìm kiếm các tệp .mkv hoặc các vùng chứa H.264 khác như thế nào?

Cảm ơn trước!

Câu trả lời:


291

Trước hết, điều quan trọng là phải hiểu rằng không có định dạng dòng bit cơ bản H.264 tiêu chuẩn duy nhất. Tài liệu đặc điểm kỹ thuật có chứa một Phụ lục, cụ thể là Phụ lục B, mô tả một định dạng khả thi, nhưng nó không phải là một yêu cầu thực tế. Tiêu chuẩn chỉ định cách video được mã hóa thành các gói riêng lẻ. Làm thế nào các gói này được lưu trữ và truyền đi là bỏ ngỏ cho bộ tích hợp.


1. Phụ lục B

Đơn vị lớp trừu tượng mạng

Các gói được gọi là Đơn vị lớp trừu tượng mạng. Thường được viết tắt NALU (hoặc đôi khi chỉ là NAL) mỗi gói tin có thể được phân tích cú pháp và xử lý riêng lẻ. Byte đầu tiên của mỗi NALU chứa kiểu NALU, cụ thể là các bit từ 3 đến 7. (bit 0 luôn tắt và các bit 1-2 cho biết liệu một NALU có được tham chiếu bởi một NALU khác hay không).

Có 19 loại NALU khác nhau được định nghĩa thành hai loại, VCL và không phải VCL:

  • Các gói VCL hoặc Lớp mã hóa video chứa thông tin trực quan thực tế.
  • Không phải VCL chứa siêu dữ liệu có thể được yêu cầu hoặc không để giải mã video.

Một NALU đơn lẻ, hoặc thậm chí một VCL NALU KHÔNG giống như một khung. Một khung có thể được 'cắt' thành nhiều NALU. Giống như bạn có thể cắt một chiếc bánh pizza. Sau đó, một hoặc nhiều lát được nhóm hầu như thành một Đơn vị truy cập (AU) chứa một khung. Cắt lát có chi phí chất lượng thấp, vì vậy nó không thường được sử dụng.

Dưới đây là bảng của tất cả các NALU được xác định.

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

Có một vài kiểu NALU mà kiến ​​thức về có thể hữu ích sau này.

  • Bộ tham số trình tự (SPS). NALU không phải VCL này chứa thông tin cần thiết để định cấu hình bộ giải mã như cấu hình, mức, độ phân giải, tốc độ khung hình.
  • Bộ thông số hình ảnh (PPS). Tương tự như SPS, không phải VCL này chứa thông tin về chế độ mã hóa entropy, nhóm lát cắt, dự đoán chuyển động và bộ lọc gỡ lỗi.
  • Làm mới bộ giải mã tức thời (IDR). VCL NALU này là một lát ảnh độc lập. Nghĩa là, một IDR có thể được giải mã và hiển thị mà không cần tham chiếu đến bất kỳ bản lưu NALU nào khác SPS và PPS.
  • Dấu phân cách đơn vị truy cập (AUD). AUD là một NALU tùy chọn có thể được sử dụng để phân tách các khung trong một luồng sơ cấp. Nó không bắt buộc (trừ khi có quy định khác bởi vùng chứa / giao thức, như TS) và thường không được bao gồm để tiết kiệm dung lượng, nhưng nó có thể hữu ích để tìm phần bắt đầu của một khung mà không cần phải phân tích cú pháp đầy đủ từng NALU.

Mã bắt đầu NALU

Một NALU không chứa là kích thước của nó. Do đó, chỉ cần nối các NALU để tạo một luồng sẽ không hoạt động vì bạn sẽ không biết điểm dừng và điểm tiếp theo bắt đầu.

Đặc điểm kỹ thuật của Phụ lục B giải quyết vấn đề này bằng cách yêu cầu 'Mã khởi động' đứng trước mỗi NALU. Mã bắt đầu là 2 hoặc 3 0x00byte theo sau là một 0x01byte. ví dụ 0x000001hoặc 0x00000001.

Biến thể 4 byte rất hữu ích cho việc truyền qua kết nối nối tiếp vì việc căn chỉnh luồng bằng cách tìm kiếm 31 bit 0 theo sau là một điều tầm thường. Nếu bit tiếp theo là 0 (vì mọi NALU đều bắt đầu bằng bit 0), nó là phần bắt đầu của NALU. Biến thể 4 byte thường chỉ được sử dụng để báo hiệu các điểm truy cập ngẫu nhiên trong luồng như SPS PPS AUD và IDR Trong đó biến thể 3 byte được sử dụng ở mọi nơi khác để tiết kiệm dung lượng.

Byte ngăn chặn mô phỏng

Bắt đầu mã làm việc vì bốn chuỗi byte 0x000000, 0x000001, 0x0000020x000003là bất hợp pháp trong phạm vi một tổ chức phi RBSP Nalu. Vì vậy, khi tạo NALU, hãy cẩn thận để thoát các giá trị này có thể bị nhầm lẫn với mã bắt đầu. Điều này được thực hiện bằng cách chèn một byte 'Ngăn chặn mô phỏng' 0x03, để điều đó 0x000001trở thành 0x00000301.

Khi giải mã, điều quan trọng là phải tìm và bỏ qua các byte ngăn chặn giả lập. Bởi vì các byte ngăn chặn mô phỏng có thể xảy ra hầu như ở bất kỳ đâu trong NALU, nên trong tài liệu thường thuận tiện hơn nếu cho rằng chúng đã bị xóa. Một biểu diễn không có byte ngăn mô phỏng được gọi là Tải trọng trình tự theo trình tự thô (RBSP).

Thí dụ

Hãy xem một ví dụ hoàn chỉnh.

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

Đây là một AU hoàn chỉnh chứa 3 NALU. Như bạn có thể thấy, chúng ta bắt đầu bằng mã Bắt đầu theo sau là SPS (SPS bắt đầu bằng 67). Trong SPS, bạn sẽ thấy hai byte Ngăn chặn Giả lập. Nếu không có các byte này, chuỗi bất hợp pháp 0x000000sẽ xảy ra tại các vị trí này. Tiếp theo, bạn sẽ thấy mã bắt đầu theo sau là PPS (PPS bắt đầu bằng 68) và một mã bắt đầu cuối cùng theo sau là lát IDR. Đây là một luồng H.264 hoàn chỉnh. Nếu bạn nhập các giá trị này vào trình chỉnh sửa hex và lưu tệp với .264phần mở rộng, bạn sẽ có thể chuyển đổi nó thành hình ảnh sau:

Lena

Phụ lục B thường được sử dụng trong các định dạng phát trực tiếp và phát trực tuyến như luồng truyền tải, chương trình phát sóng qua mạng và DVD. Trong các định dạng này, thông thường lặp lại SPS và PPS theo định kỳ, thường là trước mỗi IDR, do đó tạo ra một điểm truy cập ngẫu nhiên cho bộ giải mã. Điều này cho phép khả năng tham gia luồng đang diễn ra.


2. AVCC

Phương pháp lưu trữ luồng H.264 phổ biến khác là định dạng AVCC. Trong định dạng này, mỗi NALU được đặt trước với độ dài của nó (ở định dạng endian lớn). Phương pháp này dễ phân tích cú pháp hơn, nhưng bạn làm mất các tính năng căn chỉnh byte của Phụ lục B. Chỉ làm phức tạp mọi thứ, độ dài có thể được mã hóa bằng 1, 2 hoặc 4 byte. Giá trị này được lưu trữ trong một đối tượng tiêu đề. Tiêu đề này thường được gọi là 'dữ liệu bổ sung' hoặc 'tiêu đề trình tự'. Định dạng cơ bản của nó như sau:

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

Sử dụng cùng một ví dụ ở trên, ngoại dữ liệu AVCC sẽ giống như sau:

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

Bạn sẽ nhận thấy SPS và PPS hiện được lưu trữ ngoài băng tần. Đó là, tách biệt với dữ liệu luồng sơ cấp. Lưu trữ và truyền dữ liệu này là công việc của vùng chứa tệp và ngoài phạm vi của tài liệu này. Lưu ý rằng mặc dù chúng tôi không sử dụng mã bắt đầu, các byte ngăn mô phỏng vẫn được chèn.

Ngoài ra, có một biến mới được gọi là NALULengthSizeMinusOne. Biến có tên khó hiểu này cho chúng ta biết có bao nhiêu byte cần sử dụng để lưu trữ độ dài của mỗi NALU. Vì vậy, nếu NALULengthSizeMinusOneđược đặt thành 0, thì mỗi NALU được đặt trước một byte duy nhất cho biết độ dài của nó. Sử dụng một byte duy nhất để lưu trữ kích thước, kích thước tối đa của NALU là 255 byte. Đó rõ ràng là khá nhỏ. Quá nhỏ cho toàn bộ khung hình chính. Sử dụng 2 byte mang lại cho chúng tôi 64k mỗi NALU. Nó sẽ hoạt động trong ví dụ của chúng tôi, nhưng vẫn là một giới hạn khá thấp. 3 byte sẽ là hoàn hảo, nhưng vì một số lý do không được hỗ trợ phổ biến. Do đó, 4 byte cho đến nay là phổ biến nhất và nó là những gì chúng tôi đã sử dụng ở đây:

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

Một lợi thế của định dạng này là khả năng định cấu hình bộ giải mã khi bắt đầu và chuyển vào giữa luồng. Đây là một trường hợp sử dụng phổ biến trong đó phương tiện có sẵn trên phương tiện truy cập ngẫu nhiên như ổ cứng, và do đó được sử dụng ở các định dạng vùng chứa phổ biến như MP4 và MKV.


2
Cảm ơn anh bạn, người đó đã thực sự giúp tôi! Tuy nhiên, bạn có một số lỗi đánh máy trong bài viết của mình ... Tôi nghĩ vậy;) Đôi khi bạn gọi VCL là 'VLC', điều này có thể khá khó hiểu vì tôi biết VLC là 'mã hóa độ dài thay đổi'. Nhưng vẫn còn, bài viết của bạn đã làm sáng tỏ một vài điều cho tôi, làm tốt lắm! Và ... xin lỗi tôi không thể upvote bạn, tôi mới ở đây và có một số loại lọc newbe đây;)
bananenbär

5
Vâng, xin lỗi về lỗi chính tả. Tôi hơi khó đọc và là một người đánh máy kém. Bạn nói đúng. VLC không có vị trí trong văn bản này.
szatmary

2
Tóm tắt tuyệt vời! Điều này thực sự đã giúp tôi. Mặc dù rõ ràng là nếu người ta nhìn kỹ vào bộ byte thứ 2 (AVCC), tôi nghĩ rằng điều đáng để chỉ ra rằng giá trị độ dài 4 byte đứng trước dữ liệu NALU ở định dạng Big-Endian. Tôi không thể giải mã luồng trên iOS cho đến khi tôi nhận ra rằng giá trị độ dài phải được hoán đổi byte.
giờ trưa

1
Cám ơn nhiều, ông bạn! BTW, bộ giải mã h264 của Windows Media Foundation chỉ muốn các mẫu "Phụ lục B". May mắn thay, nó khá đơn giản để chuyển đổi chúng giữa Phụ lục B và AVCC.
Soonts

2
Có thiếu byte 0 ở độ lệch 0x0022 của ví dụ về ngoại dữ liệu AVCC không? Mô tả định dạng cho biết có một trường 16 bit cho kích thước PPS, vì vậy tôi nghĩ điều này nên được 0x00 0x07thay vì chỉ 0x07.
rhashimoto
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.