FFMPEG: 'Несоответствующий транспорт в ответе сервера' Но openRTSP работает

Купил дешевую китайскую ip камеру (бренд Yoosee). Я хочу записать его поток с помощью ffmpeg.

Мне удается заставить его работать только с использованием транспортного протокола RTSP / UDP , например:

      ffmpeg -rtsp_transport udp -i rtsp://admin:pass@192.168.0.103:554/onvif1 streamfile.mkv

pass - пароль, определенный в клиенте приложения камеры Android.

Но я очень предпочитаю транспорт RTSP / TCP, потому что при использовании UDP изображения часто повреждаются. Изображения кажутся размазанными и растрепанными. Так что я практически все протестировал и даже скомпилировал FFMPEGиз источника с использованием последнего репозитория . Но ничто не заставляет работать ffmpeg, android или windows. Я всегда получаю:

      [rtsp @ 0xxxxxxx] Nonmatching transport in server reply

Наконец обнаружил openRTSP, который использует ту же библиотеку, что и VLC. С его помощью мне удалось подключить RTSP / TCP ( после компиляции из исходников ).

      openRTSP -n -D 1 -c -B 10000000 -b 10000000 -q -Q -F cam_file \ 
-d 60 -P 30 -t -u admin pass rtsp://192.168.0.103:554/onvif1

Подробнее о openRTSPпараметры здесь .

Самая странная часть - это сравнение сообщений настройки RTSP (FFMPEG и openRTSP). Кажется очевидным, что сервер ip-камеры поддерживает RTP / AVP / TCP. RTP перемежается с существующим TCP-соединением.

И глядя на исходный код ffmpeg/libavformat/rtsp.c швы, у ffmpeg проблемы с его идентификацией?

      ...
if (reply->transports[0].lower_transport != lower_transport) {
    av_log(s, AV_LOG_ERROR, "Nonmatching transport in server reply\n");
    err = AVERROR_INVALIDDATA;
    goto fail;
}
...

1 ответ

Цитата мудрости

IP-камеры разного качества, некоторые из них, по моему опыту, ведут себя нестабильно. Работа с их потоками RTSP требует определенной отказоустойчивости.
Это, по-видимому, побочный продукт низкокачественной индустрии видеонаблюдения, которая играет быстро и свободно со стандартами, причем RTSP и ONVIF являются двумя наиболее частыми злоупотреблениями. К счастью, эти проблемы обычно можно обойти. Если ваши IP-камеры и контроллер не предназначены для совместной работы, используйте ONVIF только для однократного обнаружения и управления настройками.

FFMPEG не очень терпим в настройке RTSP

После борьбы я начал сравнивать сообщения RTSP / SETUP между и ffmpeg. по умолчанию уже выводит много подробной диагностики.

openRTSP

отправляет команды OPTIONS, а потом SETUP. Сообщения SETUP были:

      Sending request: SETUP rtsp://192.168.0.103:554/onvif1/track2 RTSP/1.0
CSeq: 6
Authorization: Digest username="admin", realm="HIipCamera", nonce="ddd21dbd0620b6fb4b1f9bcbb06340a0", uri="rtsp://192.168.0.103:554/onvif1", response="91d9c611aa004eeb1390b3fbb9373648"
User-Agent: ./openRTSP (LIVE555 Streaming Media v2021.02.11)
Transport: RTP/AVP/TCP;unicast;interleaved=2-3
Session: 3a4d2e6d

ответ камеры:

      Received a complete SETUP response:
RTSP/1.0 200 OK
CSeq: 6
Transport: RTP/AVP;unicast;destination=192.168.0.100;source=192.168.0.103;interleaved=2-3
Session: 3a4d2e6d;timeout=60

FFMPEG

За FFMPEG ты должен использовать -v 9 and -loglevel 99params, чтобы увидеть сообщения RTSP. Он только отправил DESCRIBE запрос:

      DESCRIBE rtsp://192.168.0.103:554/onvif1 RTSP/1.0
Accept: application/sdp
CSeq: 2
User-Agent: Lavf58.67.100

ответ камеры:

      Transport: RTP/AVP;unicast;destination=192.168.0.100;source=192.168.0.103;interleaved=0-1
Session: 37287775;timeout=60

Злоупотребление RTSP и решение для взлома FFMPEG

Сравнивая сообщения, становится ясно, что камера может подключаться с использованием протокола TCP с чередованием RTSP / AVP / TCP. Но по ответу камеры мы видим, что в строке «Транспорт:» он не включает «TCP» после «RTP / AVP», как это было запрошено. Нравиться:

      Transport: RTP/AVP/('TCP' missing here);....

Я проанализировал код и нашел следующую интуитивно понятную последовательность вызовов: ff_rtsp_connect, ff_rtsp_make_setup_request, ff_rtsp_send_cmd, ff_rtsp_read_reply и ff_rtsp_parse_line. Внутри этого последнего я нашел rtsp_parse_transport и следующий код:

      if (!av_strcasecmp(lower_transport, "TCP"))
    th->lower_transport = RTSP_LOWER_TRANSPORT_TCP;
else
    th->lower_transport = RTSP_LOWER_TRANSPORT_UDP;

текст анализируется после 'RTP/AVP;' в моем случае "" пустая строка символа, так как сервер камеры не включил ее.

Я вставил || !av_strcasecmp(lower_transport, "")в коде. Предполагая, что транспорт RTSP_LOWER_TRANSPORT_TCP когда lower_transportопущено. Как показано ниже:

      if (!av_strcasecmp(lower_transport, "TCP") || !av_strcasecmp(lower_transport, ""))
    th->lower_transport = RTSP_LOWER_TRANSPORT_TCP;
else
    th->lower_transport = RTSP_LOWER_TRANSPORT_UDP;

После перекомпиляции: FFMPEG работает отлично!

Я взломал FFMPEG, сделав его терпимым к злоупотреблениям RTSP, которые совершал сервер камеры. Поскольку моя версия FFMPEG будет работать только на моем неиспользуемом телевизоре Android (как сервер камеры видеонаблюдения / видеонаблюдения), других проблем не возникнет.

Лучшим решением была бы команда FFMPEG (я уже открыл билет), чтобы рассмотреть также случай отсутствия нижнего транспорта в ответе сервера rtsp. Затем сравните с запросом, отправленным клиентом, чтобы определить, был ли пропущен нижний транспорт. И попробуй соединиться с этим.

Совет

Возможно, если вы дойдете сюда, ваша дешевая камера может пострадать от злоупотребления RTSP. Я рекомендую вам попробовать использовать openRTSPсначала посмотреть, удастся ли ему подключиться. Если да, то попробуйте отладить его сообщения RTSP / setup. Возможно, существует какое-то нестандартное или взломанное решение, если вы измените (на свой страх и риск) ffmpeg/libavformat/rtsp.cкод. Или вы можете / должны использовать библиотеку live555, VLC или mplayer.

Другие вопросы по тегам