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 0x00
byte theo sau là một 0x01
byte. ví dụ 0x000001
hoặ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
, 0x000002
và 0x000003
là 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 đó 0x000001
trở 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 0x000000
sẽ 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 .264
phần mở rộng, bạn sẽ có thể chuyển đổi nó thành hình ảnh sau:
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.