2016-10-08 21 views
1

Как правильно упаковать поток байтов H264 в RTP-пакеты, чтобы я мог получать кадры с помощью FFMPEG?Как упаковать Android MediaCodec, закодированный H264 в пакеты RTP

Когда я начинаю приемник FFMPEG, он выкачивает много ошибок, как это:

Invalid UE golomb code 
[h264 @ 0xd63060] pps_id 3199971767 out of range 
[h264 @ 0xd63060] slice type 32 too large at -1 
[h264 @ 0xd63060] decode_slice_header error 
[h264 @ 0xd63060] non-existing PPS 0 referenced 
[h264 @ 0xd63060] decode_slice_header error 
[h264 @ 0xd63060] no frame! 
[h264 @ 0xd63060] decode_slice_header error 
[h264 @ 0xd63060] Unknown NAL code: 0 (0 bits) 
[h264 @ 0xd63060] no frame! 
[h264 @ 0xd63060] non-existing PPS 0 referenced 

Вот файл SDP я использую:

c=IN IP4 192.168.2.30 
t=0 0 
m=video 51372 RTP/AVP 96 
a=rtpmap:96 H264/90000 
a=recv only 

Ошибка pps_id Любопытно, его как будто он ищет следующий PPS, но не может его найти, хотя я попытался внедрить PPS в каждый NALU.

Я читал RFC 6184 и пытался его понять. Но я чувствую, что до сих пор не совсем понимаю, как взаимодействуют H264 и RTP. В настоящее время я пытаюсь кодировать пиксели из камеры и передавать кадры с разрешением 1920x1080 H264 через RTP по сети, где он затем принимается FFMPEG и декодируется. Я собираю заголовки RTP и FU-A в Java и фрагментирует NALU, когда они являются большими для MTU.

Я наблюдал поток тесно в Wireshark, вот выход моего первого пакета:

Real-Time Transport Protocol 
10.. .... = Version: RFC 1889 Version (2) 
..0. .... = Padding: False 
...0 .... = Extension: False 
.... 0000 = Contributing source identifiers count: 0 
1... .... = Marker: True 
Payload type: DynamicRTP-Type-96 (96) 
Sequence number: 0 
Timestamp: 2727179012 
Synchronization Source identifier: 0x00000000 (0) 
H.264 
NAL unit header or first byte of the payload 
    0... .... = F bit: No bit errors or other syntax violations 
    .00. .... = Nal_ref_idc (NRI): 0 
    ...0 0000 = Type: Undefined (0) 
H264 NAL Unit Payload 

Я не понимаю, почему первая полезная нагрузка имеет тип Nalu 0. Тем не менее, вот мой второй пакет:

Real-Time Transport Protocol 
10.. .... = Version: RFC 1889 Version (2) 
..0. .... = Padding: False 
...0 .... = Extension: False 
.... 0000 = Contributing source identifiers count: 0 
0... .... = Marker: False 
Payload type: DynamicRTP-Type-96 (96) 
Sequence number: 1 
Timestamp: 2727179019 
Synchronization Source identifier: 0x00000000 (0) 
H.264 
FU identifier 
    0... .... = F bit: No bit errors or other syntax violations 
    .11. .... = Nal_ref_idc (NRI): 3 
    ...1 1100 = Type: Fragmentation unit A (FU-A) (28) 
FU Header 
    1... .... = Start bit: the first packet of FU-A picture 
    .0.. .... = End bit: Not the last packet of FU-A picture 
    ..0. .... = Forbidden bit: 0 
    ...0 0101 = Nal_unit_type: Coded slice of an IDR picture (5) 
H264 NAL Unit Payload 
    0000 0000 0000 0000 0000 0000 0000 0001 0110 0101 1011 1000 0000 0100 0000 010. = first_mb_in_slice: 3000762881 
    .... ...1 = slice_type: P (P slice) (0) 
    0011 1... = pic_parameter_set_id: 6 

Итак, я думаю, что последний пакет был I-Frame? Вот фрагмент между начальными и конечными фрагментами:

Real-Time Transport Protocol 
10.. .... = Version: RFC 1889 Version (2) 
..0. .... = Padding: False 
...0 .... = Extension: False 
.... 0000 = Contributing source identifiers count: 0 
0... .... = Marker: False 
Payload type: DynamicRTP-Type-96 (96) 
Sequence number: 1 
Timestamp: 2727179019 
Synchronization Source identifier: 0x00000000 (0) 
H.264 
FU identifier 
    0... .... = F bit: No bit errors or other syntax violations 
    .11. .... = Nal_ref_idc (NRI): 3 
    ...1 1100 = Type: Fragmentation unit A (FU-A) (28) 
FU Header 
    0... .... = Start bit: Not the first packet of FU-A picture 
    .0.. .... = End bit: Not the last packet of FU-A picture 
    ..0. .... = Forbidden bit: 0 
    ...0 0101 = Nal_unit_type: Coded slice of an IDR picture (5) 

И, конечно, здесь последний пакетом предполагаемого I-Frame:

Real-Time Transport Protocol 
10.. .... = Version: RFC 1889 Version (2) 
..0. .... = Padding: False 
...0 .... = Extension: False 
.... 0000 = Contributing source identifiers count: 0 
1... .... = Marker: True 
Payload type: DynamicRTP-Type-96 (96) 
Sequence number: 1 
Timestamp: 2727179019 
Synchronization Source identifier: 0x00000000 (0) 
H.264 
FU identifier 
    0... .... = F bit: No bit errors or other syntax violations 
    .11. .... = Nal_ref_idc (NRI): 3 
    ...1 1100 = Type: Fragmentation unit A (FU-A) (28) 
FU Header 
    0... .... = Start bit: Not the first packet of FU-A picture 
    .1.. .... = End bit: the last packet of FU-A picture 
    ..0. .... = Forbidden bit: 0 
    ...0 0101 = Nal_unit_type: Coded slice of an IDR picture (5) 

Теперь вот мой пакет для последующих байт, кодер дал мне:

Real-Time Transport Protocol 
10.. .... = Version: RFC 1889 Version (2) 
..0. .... = Padding: False 
...0 .... = Extension: False 
.... 0000 = Contributing source identifiers count: 0 
0... .... = Marker: False 
Payload type: DynamicRTP-Type-96 (96) 
Sequence number: 2 
Timestamp: 2727179089 
Synchronization Source identifier: 0x00000000 (0) 
H.264 
FU identifier 
    0... .... = F bit: No bit errors or other syntax violations 
    .11. .... = Nal_ref_idc (NRI): 3 
    ...1 1100 = Type: Fragmentation unit A (FU-A) (28) 
FU Header 
    1... .... = Start bit: the first packet of FU-A picture 
    .0.. .... = End bit: Not the last packet of FU-A picture 
    ..0. .... = Forbidden bit: 0 
    ...0 0001 = Nal_unit_type: Coded slice of a non-IDR picture (1) 
H264 NAL Unit Payload 
    0000 0000 0000 0000 0000 0000 0000 0001 0110 0001 1110 0000 0010 0000 0001 100. = first_mb_in_slice: 2968522763 
    .... ...0 0111 .... = slice_type: B (B slice) (6) 
    .... 0001 110. .... = pic_parameter_set_id: 13 

Эту часть меня смущает, когда камера находится в неподвижном состоянии, кодер дает мне все меньше и меньше Nalu с неопределенными типами, и я не совсем уверен, почему, в любом случае, пакет ниже получает отправляется как один полный NALU в FFMPEG.

Real-Time Transport Protocol 
10.. .... = Version: RFC 1889 Version (2) 
..0. .... = Padding: False 
...0 .... = Extension: False 
.... 0000 = Contributing source identifiers count: 0 
1... .... = Marker: True 
Payload type: DynamicRTP-Type-96 (96) 
Sequence number: 36 
Timestamp: 2727180258 
Synchronization Source identifier: 0x00000000 (0) 
H.264 
NAL unit header or first byte of the payload 
    0... .... = F bit: No bit errors or other syntax violations 
    .00. .... = Nal_ref_idc (NRI): 0 
    ...0 0000 = Type: Undefined (0) 
H264 NAL Unit Payload 

Я использую Android MediaCodec кодировщик, а вот какой-то код, где я настроить кодировщик:

mediaCodec = MediaCodec.createByCodecName("OMX.Nvidia.h264.encoder"); 
mediaFormat = MediaFormat.createVideoFormat("video/avc", 1920, 1080); 
mediaFormat.setInteger(MediaFormat.KEY_BIT_RATE, 125000); 
mediaFormat.setInteger(MediaFormat.KEY_FRAME_RATE, 30); 
mediaFormat.setInteger(MediaFormat.KEY_COLOR_FORMAT, MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface); 
mediaFormat.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, 0); 
mediaFormat.setInteger(MediaFormat.KEY_MAX_INPUT_SIZE, 1920 * 1080); 

ли кодер дает мне целые блоки доступа или только Nalu?

Вот моя логика:

  • Если размер кадра больше, то MTU, кадр будет фрагментирован.
    • Когда я посылаю FU-A заголовок начала, я установил стартовую битый 1.
    • Когда я посылаю последние фрагментированных байты кадра, я установить биты маркеров в заголовке RTP 1, а бит конца фрагмента в заголовке FU-A до 1.
    • В заголовках FU-A между начальным и конечным фрагментами бит начала и конца установлен на 0.
    • Маркер всегда установлен в 0, за исключением последнего пакета.
  • Если NALU может поместиться в MTU, отправляется весь кадр.
  • С каждым отправленным NALU я повторяю порядковый номер для заголовка RTP.
  • С каждым отправленным NALU я получаю новую метку времени для заголовка RTP.
  • Перед тем, как фрагментировать Nalu, я сохраняю тип Nalu и вставить его в FU-A заголовке

Я чувствую, что я близко, но его явно не работает для любых приемников RTP. Я ценю любые мысли или идеи по этому вопросу.

Спасибо,

+0

'Мне, наконец, удалось это исправить' - если это решает вашу проблему, тогда вы должны опубликовать ее как ответ (да, ответы на собственные вопросы совершенно верны), чтобы другие знали, что ваша проблема решена. –

ответ

0

я, наконец, удалось решить это, мои пакеты не были настроены должным образом.

  • Я должен перебирать порядковый номер в пакете.
  • Я должен установить метку времени для NALU вместо каждого пакета.
  • Я должен разбить префикс NALU 00 00 01 **, отправив байты после индекса 4.
  • Побитовые операции в моих заголовках были неверными.

Я могу даже начать FFmpeg в середине потока, и он работает!

 Смежные вопросы

  • Нет связанных вопросов^_^