Мир торта!
1.Получить данные
Как я вижу, вы уже знаете, как это сделать (запустить сеанс RTSP, НАСТРОЙКА транспорта RTP/AVP/UDP;unicast;
и получить дейтаграммы пользователя) ... но если у вас есть сомнения, ask.
Независимо от транспорта (UDP или TCP) формат данных в основном одинаков:
- Данные RTP:
[RTP Header - 12bytes][Video data]
- UDP:
[RTP Data]
- TCP:
[$ - 1byte][Transport Channel - 1byte][RTP data length - 2bytes][RTP
data]
Таким образом, чтобы получить данные из UDP, вам нужно только удалить первые 12 байтов, которые представляют заголовок RTP.Но будьте осторожны, вам это нужно для получения информации о синхронизации видео, а для MPEG4 - информации о пакетировании!
Для TCP вам нужно прочитать первый байт, пока не получите байт $
.Затем прочитайте следующий байт, который будет транспортным каналом, которому принадлежат следующие данные (когда сервер отвечает на запрос SETUP, он говорит: Transport: RTP/AVP/TCP;unicast;interleaved=0-1
это означает, что VIDEO DATA будет иметь TRANSPORT_CHANNEL = 0, а VIDEO RTCP DATA будет иметь TRANSPORT_CHANNEL = 1).Вы хотите получить ВИДЕО ДАННЫЕ, поэтому мы ожидаем 0 ... затем прочитаем один короткий (2 байта), который представляет длину следующих данных RTP, поэтому прочитайте столько байтов, и теперь сделайте то же самое, что и для UDP.
2.Данные распаковки
Данные H264 и MPEG4 обычно пакетируются (в SDP есть параметр packetization-mode
, который может иметь значения 0, 1 и 2, что означает каждое из них, и как его распаковать, вы можетесм. ЗДЕСЬ ), поскольку существует определенный сетевой предел, который одна конечная точка может отправлять через TCP или UDP, который называется MTU.Обычно это 1500 байт или меньше.Таким образом, если видеокадр больше этого (и обычно это так), он должен быть фрагментирован (пакетирован) на фрагменты размера MTU.Это может быть сделано с помощью кодировщика / стримера на транспорте TCP и UDP, или вы можете ретранслировать по IP для фрагментации и повторной сборки видеокадра на другой стороне ... первое гораздо лучше, если вы хотите иметь плавное видео с высокой вероятностью ошибок по UDPи TCP.
H264: Чтобы проверить, содержат ли данные RTP (поступившие по UDP или перемеженные по TCP) фрагмент одного большего видеокадра H264, вы должны знать, как выглядит фрагменткогда он упакован:
H264 FRAGMENT
First byte: [ 3 NAL UNIT BITS | 5 FRAGMENT TYPE BITS]
Second byte: [ START BIT | END BIT | RESERVED BIT | 5 NAL UNIT BITS]
Other bytes: [... VIDEO FRAGMENT DATA...]
Теперь получите первые ВИДЕО ДАННЫЕ в байтовом массиве с именем Data
и получите следующую информацию:
int fragment_type = Data[0] & 0x1F;
int nal_type = Data[1] & 0x1F;
int start_bit = Data[1] & 0x80;
int end_bit = Data[1] & 0x40;
Если fragment_type == 28
, то видеоданные, следующие за ним, представляют фрагмент видеокадра.Следующая проверка start_bit
установлена, если это так, то этот фрагмент является первым в последовательности.Вы используете его для восстановления NAL-байта IDR, взяв первые 3 бита из первого байта полезной нагрузки (3 NAL UNIT BITS
) и объединив их с последними 5 битами из второго байта полезной нагрузки (5 NAL UNIT BITS
), чтобы вы получили такой байт, как этот [3 NAL UNIT BITS | 5 NAL UNIT BITS]
,Затем запишите этот байт NAL сначала в чистый буфер с VIDEO FRAGMENT DATA
из этого фрагмента.
Если start_bit
и end_bit
равны 0, просто запишите VIDEO FRAGMENT DATA
(пропуская первые два байта полезной нагрузки, которые идентифицируют фрагмент) в буфер.
Если start_bit
равно 0и end_bit
равно 1, это означает, что это последний фрагмент, и вы просто записываете его VIDEO FRAGMENT DATA
(пропуская первые два байта, которые идентифицируют фрагмент) в буфер, и теперь вы восстанавливаете свой видеокадр!
Имейте в виду, что данные RTP содержат заголовок RTP в первых 12 байтах и что, если кадр фрагментирован, вы никогда не записываете первые два байта в буфер дефрагментации, и что вам нужно восстановить байт NAL и записать его первым,Если вы что-то напутаете, картинка будет частичной (половина будет серой или черной, или вы увидите артефакты).
MPEG4: Это очень просто.Вам нужно проверить MARKER_BIT в заголовке RTP.Этот байт устанавливается (1
), если видеоданные представляют весь видеокадр, а 0
видеоданных представляет собой один фрагмент видеокадра.Итак, чтобы разобраться в этом, вам нужно посмотреть, что такое MARKER_BIT.Если это 1
, просто прочитайте байты видеоданных.
ВЕСЬ КАДР:
[MARKER = 1]
ПАКЕТИРОВАННАЯ РАМА:
[MARKER = 0], [MARKER = 0], [MARKER = 0], [MARKER = 1]
Первый пакет, который имеет MARKER_BIT=0
, является первым фрагментом видеокадра, все остальные последующие, включая первый с MARKER_BIT=1
, являются фрагментами одного и того же видеокадра.Итак, что вам нужно сделать, это:
- До
MARKER_BIT=0
поместить ВИДЕО ДАННЫЕ в буфер депакетизации - Поместить следующие ВИДЕО ДАННЫЕ где
MARKER_BIT=1
в тот же буфер - Буфер распаковки теперь содержит один целый кадр MPEG4
3.Обработка данных для декодера (поток байтов NAL)
Когда вы распаковали видеокадры, вам необходимо создать поток байтов NAL.Он имеет следующий формат:
- H264:
0x000001[SPS], 0x000001[PPS], 0x000001[VIDEO FRAME], 0x000001...
- MPEG4:
0x000001[Visual Object Sequence Start], 0x000001[VIDEO FRAME]
ПРАВИЛА:
- Каждый кадр ДОЛЖЕН начинаться с
0x000001
3-байтового кода независимо от кодека - Каждый поток ДОЛЖЕН начинаться с ИНФОРМАЦИИ О КОНФИГУРАЦИИ, для H264, которые являются кадрами SPS и PPS в этом порядке (
sprop-parameter-sets
в SDP), а для MPEG4 фрейм VOS (config
параметр в SDP)
Поэтому необходимо создать буфер конфигурации для H264 и MPEG4 с добавлением 3 байтов 0x000001
, отправитьсначала, а затем добавьте к каждому депакетированному видеокадру те же 3 байта и отправьте его в декодер.
Если вам нужны какие-либо разъяснения, просто прокомментируйте ...:)