2012-03-08 22 views
10

Tôi có luồng H.264 thô từ Máy ảnh IP được đóng gói trong khung RTP. Tôi muốn lấy dữ liệu H.264 thô vào một tệp để tôi có thể chuyển đổi nó với ffmpeg.H.264 trên RTP - Xác định SPS và PPS Frames

Vì vậy, khi tôi muốn viết dữ liệu vào tập tin H.264 liệu của tôi, tôi phát hiện ra nó phải giống như thế này:

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] 
.... 

Vì vậy, tôi nhận được SPSPPS từ Session Description Protocol ra khỏi tôi trước thông tin liên lạc RTSP. Ngoài ra, máy ảnh sẽ gửi SPSPPS trong hai tin nhắn đơn trước khi bắt đầu với chính luồng video đó.

Vì vậy, tôi nắm bắt được các thông điệp theo thứ tự này:

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 

Sau đó đến một số Frames với Payload và tại một số điểm một khung với Marker Bit = 1 RTP. Điều này có nghĩa là (nếu tôi hiểu đúng) rằng tôi có một khung hình video hoàn chỉnh. Afer này tôi viết trình tự tiền tố (00 00 01) và NAL từ tải trọng một lần nữa và tiếp tục với thủ tục tương tự.

Bây giờ máy ảnh của tôi gửi cho tôi sau mỗi 8 Khung hình video hoàn chỉnh SPSPPS một lần nữa. (Một lần nữa trong hai khung RTP, như đã thấy trong ví dụ trên). Tôi biết rằng đặc biệt là PPS có thể thay đổi giữa phát trực tiếp nhưng đó không phải là vấn đề.

câu hỏi của tôi bây giờ là:

1. Tôi có cần phải viết SPS/PPS mỗi khung Video 8?

Nếu số SPS và số PPS của tôi không thay đổi thì đủ để viết vào đầu tệp của tôi và không có gì khác?

2. Cách phân biệt giữa SPS/PPS và Khung RTP bình thường?

Trong mã C++ của tôi phân tích dữ liệu được truyền, tôi cần tạo sự khác biệt giữa các khung RTP với Payload bình thường, một cái mang theo số SPS/PPS. Làm thế nào tôi có thể phân biệt chúng? Khung hình SPS/PPS thường nhỏ hơn, nhưng đó không phải là một cuộc gọi tiết kiệm. Bởi vì nếu tôi bỏ qua chúng tôi cần phải biết dữ liệu nào tôi có thể vứt bỏ, hoặc nếu tôi cần viết chúng tôi cần đặt Tiền tố 00 00 01 trước mặt chúng. ? Hay đó là một quy tắc cố định mà chúng xuất hiện ở mỗi Khung Video 8?

+0

Cảm ơn câu hỏi này. Tôi có cùng một câu hỏi như bạn. Tôi đọc qua mã nguồn live555 và không biết tại sao họ lưu từng gói/khung như thế. Sau khi đọc chủ đề này, mọi thứ trở nên rõ ràng với tôi. Như một gợi ý dựa trên việc thực hiện live555, bit đánh dấu chỉ được sử dụng trong các codec khác, H264 có start_bit và end_bit riêng để biểu diễn cho đầu/cuối của khung, bit đánh dấu không được sử dụng cho H264. – user534498

Trả lời

10
  1. Nếu SPS và PPS không thay đổi, bạn có thể bỏ qua chúng ngoại trừ trường hợp thứ nhất.
  2. Bạn cần phải phân tích cú pháp trường nal_unit_type của mỗi NAL, đối với SPS, nal_unit_type == 7; cho PPS, nal_unit_type == 8.

Như tôi đã nhớ, nal_unit_type là 5 bit thấp hơn của byte 1 của khung.

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

Điều này có nghĩa là 2 Bytes đầu tiên của khung 'SPS' và' PPS' cũng là một dạng "Trạng thái NAL" giống như hai byte đầu tiên của mỗi Khung RTP khác? Hay nói cách khác - trường nal_unit_type mà tôi mong đợi 7 hoặc 8 cho SPS và PPS là cùng một trường mà tôi mong đợi 28 có nghĩa là dữ liệu video của nó? – Toby

+2

Để biết định nghĩa chi tiết về nal_unit_type, bạn có thể tham khảo tài liệu H.264. btw, (tải trọng [0] & 0x1f) == 28 có nghĩa đây là một khung video phân mảnh, trong trường hợp này, nal_unit_type thực tế phải là (trọng tải [1] & 0x1f). Điều này được định nghĩa trong RFC3984. – ciphor

+0

Vâng, tôi chỉ đọc nó và hiểu ... nhưng làm thế nào để bạn biết rằng nal_unit_type = 28 là khung video phân mảnh? RFC 3984 đề cập đến http://www-ee.uta.edu/dip/courses/ee5356/H264systems.pdf Bảng 7.1 (Trang 63) - có mã số 28 sẽ nằm trong "Không xác định" ..? – Toby

10
  1. Bạn nên viết SPS và PPS vào đầu dòng, và chỉ khi họ thay đổi ở giữa suối.

  2. SPS và PPS khung được đóng gói trong một đơn vị STAP NAL (thường STAP-A) với NAL loại 24 (STAP-A) hoặc 25 định dạng STAP (STAP-B) được mô tả trong RFC-3984 section 5.7.1

  3. Don 't dựa vào bit đánh dấu, sử dụng bit bắt đầu và bit kết thúc trong tiêu đề NAL.

  4. Đối với khung video phân mảnh, bạn nên tạo lại đơn vị NAL sử dụng 3 bit đơn vị NAL của đoạn đầu tiên (F, NRI) kết hợp với 5 bit loại NAL của byte đầu tiên trong tải trọng (chỉ dành cho gói có bit bắt đầu được đặt thành 1) RFC-3984 section 5.8:

    các NAL loại đơn vị octet của đơn vị NAL phân mảnh không được bao gồm như vậy trong các đơn vị phân mảnh tải trọng, nhưng thay vì các thông tin của NAL unit loại octet của đơn vị NAL phân mảnh được chuyển tải trong Các trường F và NRI của chỉ số octet FU của đơn vị phân mảnh và trong trường loại tiêu đề FU.

EDIT: hơn giải thích về xây dựng đơn vị NAL cho các đơn vị phân mảnh:

đây là hai byte đầu tiên của một FU-A tải trọng (ngay sau khi tiêu đề 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 | 
+---------------+---------------+ 

để xây dựng đơn vị NAL, bạn nên thực hiện "Loại" từ "FU Header" và "F" và "NRI" từ "FU indicator"

here là triển khai đơn giản

+0

Bạn có thể giải thích mục 4 không? Tôi đã đọc phần đó của spec và blurb bạn trích dẫn nhiều lần và tôi không hiểu những gì nó được mô tả. Điều đó có nghĩa là chỉ báo FU nên được xây dựng lại dựa trên các quy tắc này, và tiêu đề FU bị loại bỏ, và 5 bit đầu tiên của tải trọng bị loại bỏ, và chỉ báo FU được xây dựng lại được nối với trọng tải (ít hơn 5 bit đầu tiên)?Cảm ơn bạn – Joshua

+1

@Joshua: Tôi đã thêm một số giải thích thêm –

+0

Cảm ơn bạn, ví dụ mã rất thanh lịch và tôi đánh giá cao sự giải thích đơn giản của bạn. Trong hindsight blurb bạn trích dẫn là đơn giản, nhưng lời giải thích của bạn trong mục 4 cho thấy sử dụng bit từ tải trọng, do đó sự nhầm lẫn của tôi. Bây giờ tôi hiểu ý của bạn là gì. – Joshua