2012-07-18 42 views
13

Môi trường:H.264 chuyển đổi với FFmpeg (từ một dòng RTP)

Tôi có một camera IP, trong đó có khả năng streaming dữ liệu của nó trên RTP trong một định dạng mã hóa H.264. Dòng thô này được ghi lại từ ethernet. Với dữ liệu đó tôi phải làm việc.

Mục tiêu:

Cuối cùng tôi muốn có một file * .mp4, mà tôi có thể chơi với người chơi phương tiện phổ biến (như VLC hoặc Windows MP).

Tôi đã làm gì cho đến nay:

tôi mất rằng dòng nguyên liệu tôi có và phân tích nó. Kể từ khi dữ liệu đã được truyền qua RTP tôi cần phải chăm sóc NAL Bytes, SPS và PPS.

1. Viết một file raw

Trước tiên tôi xác định loại của mỗi khung nhận qua mạng Ethernet. Để làm như vậy, tôi phân tích cú pháp hai byte đầu tiên của mỗi RTP Payload, vì vậy tôi có thể nhận được 8 NAL Unit Bit, Fragment Type Bits và Start, Reserved và End Bit. Trong payload, họ đang sắp xếp như thế này:

Byte 1: [   3 NAL Unit Bits   | 5 Fragment Type Bits] 
Byte 2: [Start Bit | Reserved Bit | End Bit | 5 NAL Unit Bits] 

Từ đó tôi có thể xác định:

  • Start và End của một khung Video -> Bắt đầu Bit và End Bit
  • Loại Payload -> 5 Fragment loại Bits
  • NAL Đơn vị Byte

các loại Fragment đó là cần thiết trong trường hợp của tôi là:

Fragment Type 7 = SPS 
Fragment Type 8 = PPS 
Fragment Type 28 = Video Fragment 

Nte Byte được tạo bằng cách đặt các bit đơn vị NAL từ Byte 1 và 2 với nhau.

Bây giờ tùy thuộc vào loại phân mảnh Tôi làm như sau:

SPS/PPS:

  1. Viết NAL Tiền tố (0x00 0x00 0x01) và sau đó dữ liệu SPS hoặc PPS

Phân mảnh với bit bắt đầu

  1. Viết NAL Prefix
  2. Viết NAL Đơn vị Byte
  3. Viết còn lại dữ liệu thô

phân mảnh mà không Bắt đầu Bit

  1. Viết dữ liệu thô

Điều này có nghĩa tôi tập tin thô trông một cái gì đó li ke này:

[NAL Prefix][SPS][NAL Prefix][PPS][NAL Prefix][NAL Unit Byte][Raw Video Data][Raw Video Data]....[NAL Prefix][NAL Unit Byte][Raw Video Data]... 

Đối với mỗi PPS và SPS Tôi tìm thấy trong dòng dữ liệu của tôi, tôi chỉ viết một NAL Tiền tố (0x00 0x00 0x01) và sau đó là SPS/PPS chính nó.

Bây giờ tôi không thể chơi dữ liệu này với một số media player, dẫn tôi đến:

2. Chuyển đổi file

Vì tôi muốn tránh làm việc nhiều với codec Tôi chỉ đã sử dụng ứng dụng hiện có -> FFmpeg. Đây tôi kêu gọi với các tham số:

ffmpeg.exe -f h264 -i <RawInputFile> -vcodec copy -r 25 <OutPutFilename>.mp4

-f h264: Đây nên nói ffmpeg Tôi đã một h264 mã dòng

-vcodec copy: Trích dẫn từ manpage:

Force video codec to codec. Use the "copy" special value to tell that the raw codec data must be copied as is.

-r 25 : Đặt tốc độ khung hình thành 25 FPS.

Khi tôi gọi ffmpeg với các tham số đó, tôi nhận được tệp .mp4, tôi có thể phát bằng VLC và Windows MP, vì vậy nó thực sự hoạt động. Nhưng tệp bây giờ trông hơi khác so với tệp thô của tôi.

Điều này dẫn tôi đến câu hỏi của tôi:

sao tôi thực sự làm gì?

Vấn đề của tôi không phải là nó không hoạt động. Tôi chỉ muốn/cần phải biết những gì tôi đã thực sự thực hiện với gọi ffmpeg. Tôi đã có một tệp H264 thô mà tôi không thể phát.Sau khi sử dụng FFmpeg I có thể phát.

Có sự khác biệt sau đây giữa các tập tin nguyên gốc (mà tôi đã viết) và một được viết bởi FFmpeg:

  1. Tiêu đề: Các FFmpeg file có thích về 0x30 Bytes của header
  2. Footer: các FFmpeg tập tin cũng có một chân
  3. Thay đổi Prefix và 2 Bytes mới:

trong khi một khung video mới từ file Raw bắt đầu như 012.350.trong file mới nó trông như thế này:

[0x00 0x00][2 "Random" Bytes][NAL Unit Byte][Raw Video Data].....[0x00 0x00[2 other "Random" Bytes][NAL Unit Byte][Raw Video Data]... 

Tôi hiểu rằng Stream Video cần một định dạng container (đúng cho tôi nếu tôi sai nhưng tôi giả định rằng tiêu đề mới và footer chịu trách nhiệm cho điều đó). Nhưng tại sao nó thực sự thay đổi một số Byte trong dữ liệu thô? Nó không thể là một số giải mã kể từ khi dòng chính nó nên được giải mã bởi người chơi và không phải ffmpeg.

Như bạn thấy, tôi không cần một giải pháp mới cho vấn đề của mình như là một lời giải thích nhiều hơn (vì vậy tôi có thể giải thích nó một mình). Ffmpeg thực sự làm gì? Và tại sao nó thay đổi một số byte trong dữ liệu video?

+1

Bạn có thể đạt được điều này không? Nếu có, bạn có sẵn sàng chia sẻ giải pháp không? Cảm ơn! –

Trả lời

0

Có vẻ như luồng đã được đóng gói. Nhiều định dạng container phân chia bitstream thành các gói và thêm một chút thông tin như tem thời gian, độ dài của gói, v.v. Điều này cho phép bộ giải mã bỏ qua tệp mà không giải mã mọi thứ, resynching khi gói bị mất, đồng bộ hóa audio/video, kết hợp nhiều suối vv

Nhìn vào các thông tin định dạng tập tin MP4 để biết thêm thông tin:
http://en.wikipedia.org/wiki/MPEG-4_Part_14

2

Bên cạnh đó thêm container MP4, ffmpeg chuyển đổi H.264 Annex B byte luồng của mình (với Tiền tố NAL) theo định dạng có độ dài tiền tố.

Byte [0x00] [2 "ngẫu nhiên"] của bạn là số nguyên 32 bit, cho độ dài của đơn vị NAL sau theo byte.

-1

Bạn có thể đọc thêm về các thay đổi của mình ở dạng mở h264 specs. Chương Phụ lục B.

Các vấn đề liên quan