Перед нами стояла задача обеспечить надежную доставку и прием “live” видеопотока на Андроид для всего парка устройств с прошивкой 2.х.
Для этого совместными усилиями была предложена идея не создавать еще один медиа-плеер, который бы понимал нужный нам протокол, а написать приложение, выполняющее функции прокси-сервера на устройства. Прокси бы запускался в фоне, получал бы данные с удалённого сервера TCP-транспортом, и мог отдавать видеопоток по UDP в RTSP. Соответственно, встроенный плеер должен подсоединиться к локальному порту, на котором сидит сервер, и просто начать воспроизведение. На схеме изображён принцип работы системы.
Рисунок 1 – Схема
Реализация RTSP-общение клиента и сервера
RTSP — потоковый протокол реального времени, предназначенный для клиентского управления медиа-потоком, поступающим с сервера. Протокол не выполняет транспортных функций или функций обработки видео. Его основная и единственная цель — управление и синхронизация медиа-потоков (в случае широковещательной трансляции медиа-данных). Протокол имеет некоторое сходство с HTTP по своей структуре, однако, например, RTSP позволяет инициировать запросы как клиентом, так и сервером, в процессе их общения (конечно, сервер не может обратиться с клиенту и заставить его показывать видео).
Первым вопросом, которым мы занялись, было выяснение возможности открытия локального сокета на порте 554, который специально отведен для протокола RTSP. В результате было выяснено, что клиенту нет разницы, на каком порте открывать сокет для RTSP-обмена.
Запросы имеют формат заголовка:
названиеМетода абсолютныйАдресКонтента версияПротокола
и тела:
названиеПараметра<:><пробел>значение
Например, следующим запросом клиент просит сервер начать передачу ему медиа-потока:
PLAY rtsp://foo.com/bar.file RTSP/1.0
СSeq:3
Session: 12345678
Обычно процесс общения выглядит так:
Клиент (К): посылает запрос OPTIONS серверу (С) с указанием названия видео.
C: Если запрос устраивает сервер, то в ответе он указывает, какие методы тот поддерживает.
К: отправляет запрос DESCRIBE
С: формирует ответ, содержащий SDP-описание потока.
К: если клиента устроил ответ на предыдущий запрос, то он присылает метод SETUP, в ответ на который хочет получить описание транспорта, которым будет доставлен медиа-поток.
С: Отвечает нa SETUP.
К: Присылает метод PLAY.
С: Отвечает и начинает передачу данных.
Каждая пара сообщений (запрос-ответ) должна иметь свой номер в рамках сессии, который передаётся в виде параметра СSeq.
Реализация общения по RTSP не вызывала проблем, пока на пути не встала задача сформировать SDP-описание видео, предназначенного для передачи.
SDP (Session Description Protocol) — это формат для описания конфигурационных параметров потокового видео. Может использоваться как самостоятельно — в этом случае он представляет собой файл с разрешением sdp, так и в составе других протоколов, как в нашем случае.
Прочитав сначала бегло спецификацию RTSP, затем спецификацию SDP, захотелось сразу вставить пример со страницы RFC, быстренько его прогнать и продолжить разработку дальше. Но не тут-то было. Первые же грабли лежали в поле реализации ответа на метод DESCRIBE, который должен был содержать в своём теле sdp-сообщение, описывающее видео. То, что было приведено в качестве примера в официальной документации, мягко сказать, было слишком примерным описанием. Вот оно:
v=0
o=jdoe 2890844526 2890842807 IN IP4 127.0.0.1
s=rtsp
i=rtsp proxy
e=mymail@gmail.ru
c=IN IP4 224.2.17.12/127
t=2873397496 2873404696
a=recvonly
m=audio 49170 RTP/AVP 0
m=video 51372 RTP/AVP 99
a=rtpmap:99 h263-1998/90000
После некоторого времени, потраченного на бесполезные попытки убедить клиента в том, что отсылаемый пример описания действителен, было принято решение разобраться в спецификациях и формировать реальное описание. Остановлюсь только на некоторых наиболее интересных особенностях SDP-сообщения, которые заставили потратить на себя большое количество времени.
Так как мы будем передавать клиенту, по сути, два разных потока (аудио и видео), мы обязательно должны об этом сказать клиенту таким образом:
a=control:*
// различные параметры описания аудио
a=control:trackID=1 — этим мы говорим, что только что закончилось описание первого потока.
// различные параметры описания видео
a=control:trackID=2 — последний параметр в моём sdp говорит о том, что закончилось описание видео.
Описание аудио:
m = audio 0 RTP/AVP 96 – указывает на тип передачи и тип данных, которые будут передаваться в первом потоке. RTP-медиа данные будут “завёрнуты” в RTP пакеты, 96 – значение динамического типа аудио потока. Информацию об этом и других типах можно найти здесь :
a = rtpmap: 96 mpeg4-generic/44100/2
96 – тип потока (Правильнее сказать, тип полезной RTP-нагрузки. Что это такое, будет рассказано ниже)
mpeg4-generic – тип кодирования данных
44100 – частота
2 – количество каналов.
Это наиболее общее описание аудио-потока. Так же имеются ещё некоторые важные моменты.
Подробное описание этих параметров можно найти в следующей статье.
Описание видео:
m = video 0 RTP/AVP 97 – отличие от аудио в том, что это видео. 97 – динамический тип видео.
a = rtpmap:97 H264/90000 – этот параметр говорит клиенту о том, что видео будет закодировано с помощью h264 кодека и будет иметь битрейт равный 90000
Следующие параметры, которые необходимо указать, более просты и интуитивно понятны:
a=cliprect:0,0,height,width;
a = framesize:97 width-height;
Первый параметр – прямоугольная область видео.
Второй – размер фрейма. Здесь всё понятно.
И, наконец, мы должны указать, что у нас закончилось описание видео с помощью параметра
a = control:trackID=2
Есть ещё пара параметров, которые в угоду краткости были опущены.
Такое sdp-описание было принято сервером, и появилась возможность посылать другие команды. Следующей командой была SETUP. Если в sdp-описании было сказано, что будут присутствовать и видео, и аудио данные, то команда SETUP присылается дважды. Для аудио и видео (В той последовательности, в которой они описаны в sdp. В моём случае сначала аудио, потом видео). К обычным параметрам этого метода в ответе необходимо добавить параметр Transport.
Transport:RTP/AVP/UDP;unicast;client_port=<порты клиента>;server_port=<порты сервера>;ssrc=<источник синхронизации>));
RTP/AVP/UDP – RTP: говорим, что будет использоваться для передачи медиа данных этот протокол реального времени ; AVP – audio video profile – наши мультимедиа данные – это аудио и видео; UDP – транспортный протокол передачи данных.
<порты клиента> – обычно пара портов, на которые должны передаваться данные клиенту. Я передаю данные на первый из указанных портов.
<порты сервера> – тоже пара портов, с которых сервер будет передавать данные. Второй порт можно открывать для прослушивания отчётов о доставке в виде RTCP протокола.
<источник синхронизации> – 32-битный числовой SSRC-идентификатор, который содержится в заголовке RTP пакета и определяет уникальность потока, то есть отделяет видео поток от аудио потока в нашем случае. В случае многоканальной трансляции его значение играет более серьёзную роль.
После того как удалось отправить настроечные данные клиенту, если они его устраивают, то но присылает команду PLAY. В ответ на данную команду, помимо обязательного параметра CSeq, необходимо добавить параметры Range и RTP-Info.
Первый служит для указания временной отметки, с которой будет передаваться видео для проигрывания и его длины.
Range: 0-188;
Второй служит для описания параметров RTP-передачи.
После отправки ответа на команду PLAY можно начинать передачу видео данных на те порты и тем способом, о которых удалось договориться в ходе RTSP-общения.
Получение FLV-видеопотока с сервера
После того как удалось наладить RTSP-обмен, встал вопрос о передаче самого медиа-контента с удалённого севера. Поскольку сервер уже был настроен на отдачу данных в формате FLV, решили использовать этот контейнер.
Подробное описание структуры FLV находится в документе под названием Adobe Flash Video File Format Specification, начиная со страницы 68. Скачать можно здесь. На словах, он выглядит так:
Сначала идёт стандартный заголовок, который недвусмысленно говорит о том, что перед нами FLV файл (3 байта). За ним несколько байт несут информацию о том, какие медиа потоки содержатся в файле, то есть, есть ли в нём видео и аудио. Затем идут основные блоки данных, которые в контексте FLV описания называются тегами. Всего есть три вида тегов: SCRIPT DATA, AUDIO и VIDEO. Все они располагаются последовательно друг за другом. В общем виде, структура файла такая:
<Первые 11 байт – flv-заголовок> < 4 байта – размер предыдущего тега – всегда 0> <flv тег> <4 байта – размер предыдущего тега> <flv тег> <4 байта – размер предыдущего тега> и так до конца файла.
Каждый тег так же имеет свой заголовок (11 байт). Внутри него содержится размер полезной нагрузки, которую он несёт и много другой необходимой и полезной информации, такой как тип тега и временная метка данных. Каждый тег имеет свой идентификатор (тип), который располагается в определённом месте в заголовке тега. Для SCRIPT DATA это 18 (не забываем, что в файле будет это число в hex, то есть 12), AUDIO — 8, VIDEO — 9.
Полезная нагрузка, однако, не является “сырым” видео, а так же, в зависимости от типа тега, содержит свой определённый заголовок и тело. Рассмотрим пример с видео.
Подробное описание находится на 72 странице Adobe Flash Video File Format Specification, словами же опишу основные моменты.
Первые 4 бита определяют тип видео-фрейма, который содержится в теле тега. В данном случае нас могут интересовать только два типа фреймов – это key frame = 1 и inter frame = 2.
Следующие 4 бита содержат значение, которое определяет тип кодека, который используется для этого видео. Значение равное 7 соответствует AVC (Advanced Video Coding — одно из названий способа кодирования при помощи h264 кодека).
Следующий байт имеется только если предыдущие 4 бита содержат значение равное 7, то есть у нас имеется видео, закодированное AVC.
Байт может иметь одно из трех значений:
0 — в теле тега содержится AVC sequence header – специальный заголовок для подобного типа видео, который содержит информацию о SPS и PPS, которая в свою очередь необходима для правильного декодирования видео. Он так же имеет название AVCDecoderConfigurationRecord, под которым его можно найти в спецификации, ссылка на которую расположена ниже.
1 — содержится AVC NALU
2 — AVC end of sequence, конец последовательности.
Для получения подробной информации советую почитать спецификацию, начиная с первой страницы.
Следующие 3 байта, условие наличия которых такое же, как и у предыдущего байта, содержат в себе composition time. Это время смещения показа текущего фрейма. То есть декодируется он плеером в порядке очерёдности, но выводится на экран именно в это время. Оно может быть равно нулю, как в нашем случае, если выбрать соответствующий профайл для кодирования.
Видео и аудио данные, извлечённые из FLV-потока, связывались со своей временной меткой и ждали момента отправления. Подробнее о структуре этих данных и о том, как она влияла на воспроизведение видео, будет рассказано позднее.
Отправка RTP-пакетов по UDP клиенту
Формирование RTP-заголовка
Так как к данному моменту имелось уже всё необходимое для отправки, то пришло время изучить протокол RTP. Как уже говорилось, данный протокол предназначен для передачи медиа-траффика в реальном времени. Данные представляются в виде пакетов с фиксированным заголовком. Представляет данный пакет из себя следующее (Подробное и всеобъемлющее описание находится здесь, и по-русски здесь ):
Первые 12 байт — железно — RTP-заголовок. Заголовок может быть и больше, но для передачи данных одному клиенту, 12 байтовый заголовок — необходимый и достаточный минимум. Поясню некоторые наиболее важные моменты:
Рассмотрим первые 4 байта заголовка.
PT (payload type) — тип полезной нагрузки, которую несёт в себе пакет. Связь с тем, что было в SDP — прямая. 97 — видео, 96 — аудио.
sequence number — номер пакета в общей последовательности отправки. Так как имеется возможность того, что пакеты будут приходить клиенту не в той последовательности, что отправляет сервер, то каждый пакет и снабжён своим особым номером в последовательности. Причём, для видео и аудио данных это две разные последовательности, которые увеличиваются независимо друг от друга. Отсчёт каждая последовательность начинает с единицы.
Следующие 4 байта — это временная метка тех данных, что будут в пакете полезной нагрузкой. Эти данные мы будем брать из временного хранилища, в которое мы их поместили, после извлечения из FLV-файла. Каждая единица этих данных — это видео фрейм или аудио сэмпл (sample). Соответственно, каждая эта единица имеет своё положение в общей последовательности видео потока — это положение и задаёт временная метка.
Следующее, что необходимо указать в заголовке RTP-пакета, это 32-битное значение ssrc. Данный идентификатор позволяет клиенту из общего потока RTP-пакетов выделить отдельно аудио и видео потоки. То есть для аудио и видео данный идентификатор должен быть разным.
Сформировав таким образом битовую последовательность из 12 байт и добавив к ней полезную нагрузку — наши аудио или видео данные, можно смело начинать отправку пакетов клиенту.
Формирование полезной нагрузки для RTP-пакета
В роли полезной нагрузки в нашем случае выступает аудио и видео. Но просто взять содержимое каждого FLV-тега и представить его в виде полезной нагрузки rtp-пакета нельзя. Существует специальная спецификация, которая указывает формат полезной нагрузки RTP-пакета, причём конкретно для видео, которое закодировано с помощью h264-кодека.
Полезная нагрузка может быть представлена в виде трёх форматов:
Single NAL Unit Packet — полезная нагрузка представлена единственным NALU. NALU (в общих чертах) – это видео фрейм, кадр, представленный h264 кодеком.
Aggregation Packets — полезная нагрузка, внутри которой расположено несколько NALU. Существует несколько разновидностей подобного типа.
Fragmentation Units — когда один NALU не влезает в RTP-пакет. RTP-пакет имеет ограничение по размеру, которое выясняется в ходе RTSP-общения. Клиент присылает параметр Blocksize — максимальный размер пакета, который он готов принять.
Схема работы сервера
Перейдем теперь от описания механизмов взаимодействия компонентов к описанию их общей схемы работы.
Приложение-прокси на Android-устройстве начинает свою работу в тот момент, когда пользователь запрашивает по URL некий поток для просмотра. В это время в отдельном потоке процесса прокси происходит обращение к удалённому серверу за данными, которые запрашивает клиент. RTSP-общение между плеером и прокси происходит намного быстрее, чем общение между прокси и удаленным сервером. Поскольку описание видео клиенту уже нужно на втором RTSP-сообщении, то ему приходится ждать, пока прокси получит данные и сможет сформировать правильное SDP-описание. (Серверу для этого необходимо получить и разобрать script data). Впрочем, при скорости интернет-соединения, пригодного для просмотра видео, это ожидание не играет существенной роли. Как только завершается RTSP-обмен сообщениями, сервер уже имеет некоторый буфер видеоданных.
В процессе просмотра ролика на стороне прокси формируются RTP-заголовки, к ним добавляются видео- или аудио-данные и пакет отправляется клиенту в третьем по счету потоке данных. Всё, что необходимо — правильно обрабатывать и реагировать на RTSP-команды.
Но если бы всё было так просто. Основная работа заключалась в том, чтобы понять, какие именно видео и аудио данные должны поставляться клиенту, чтобы он смог их раскодировать и показать.
Определение формата данных, пригодного для отправки клиенту
Видео, которое прокси-сервер получал с удалённого сервера, кодировалось с помощью h264 кодека и упаковывалось в формат FLV. Формат FLV-файл мы уже рассмотрели, теперь поглядим на его содержание. В случае с видеоданными, в каждом видеотеге содержится небольшой кусок закодированного h264-кодеком видео, в случае с аудио — небольшой кусок аудио данных, закодированных с помощью ААС. Эти кусочки мы должны упаковывать в RTP-пакет и передавать клиенту. Однако при таком подходе “в лоб” клиент отказывался воспроизводить видео. Чтобы выяснить, почему, пришлось разобраться в том, что получается с видео, после того как оно проходит через кодек.
Разбор видео, закодированного h264 кодеком
Итак, видео-поток, закодированный h264-кодеком. Существует достаточное количество спецификаций, которые описывают эту прелесть и которые продаются на сайте стандартизации ISO. Зачем — не ясно, ибо в открытом доступе они находятся на соседней ссылке.
-
ITU-T Rec. H.264 (05-2003) Advanced video coding for generic audiovisual services [IT] — данная спецификация описывает то, что получается, после того как h264 видео кодек обработает видео. То есть, формат и состав видео в виде байтов. Исчерпывающая информация на английском языке, от которой поначалу бросало в дрожь (страница 61 и далее – то что нужно было мне)
-
MPEG-4 Part 10 AVC (H.264) Video Encoding [MP-AVC] — кратко описывает h264 формат и поясняет, какие профили кодирования имеются.
- ISO/IES AVC file format [ISO-AVC] — самое понятное описание содержимого видео файла, прошедшего через h264-кодек.
Декодирование видео (как и кодирование) — процесс ресурсоемкий, поэтому мобильные устройства с медленными процессорами в реальном времени могут декодировать только то видео, что закодировано не самым сложным образом.
Уровень сложности в данном случае определяется профилем кодирования (Profile). Для h264 кодека существует множество профилей кодирования. С их многообразием можно ознакомиться здесь или более подробнее в [MP-AVC] (см.выше). Мобильные устройства поддерживают далеко не все профили кодирования. Наш Android, например, может декодировать только видео Baseline профиля, но в разных вариациях.
Для кодирования видео существуют различные утилиты и приложения. Одним из популярных GNU-LGPL приложений является FFMPEG. Чтобы FFMPEG смог закодировать нужное нам видео нужным нам профилем, необходимо задать множество входных параметров и ключей. Для удобства их выносят в отдельный файл, называемый “пресет”. В сети Интернет можно найти уже подобранные пресеты для всех профилей кодирования. Однако, как показала практика, стандартный пресет для Baseline профиля воспринимается Android’ом не всегда корректно. К сожалению, тонкая оптимизация FFMPEG и его пресетов — объемный вопрос, выходящий за рамки этой статьи.
Отправка клиенту данных и поиск проблем воспроизведения
Теперь у нас есть установленное соединение с клиентом, разобранное видео, получаемое с удалённого сервера, правила формирования пакетов для отправки. Самое время начать её.
Для отправки пакетов создаётся новый поток, который используя UDP-транспорт, отправляет RTP-пакеты. Видео и аудио пакеты формируются в одном потоке в той очерёдности, в которой они были в FLV-файле.
Интересным моментом является временной интервал, с которым данные должны передаваться клиенту. Если отправлять клиенту пакеты непрерывным потоком, то он, во избежание переполнения буфера, отправляет команду PAUSE по RTSP. Можно её обрабатывать и приостанавливать поток. Но можно сделать проще. Достаточно установить интервал отправки пакетов таким, который бы соответствовал или был чуть быстрее скорости воспроизведения видео. Так как частота смена кадров, в среднем, 25-30, то чтобы не было задержек, я выбрал интервал, равный 25 миллисекундам. Для звука — 15. Если данные из внешней сети приходят вовремя, то проблем с воспроизведением не наблюдается.
Вот таким образом выглядит процесс создания сервера, транслирующего живой поток. Статья получилось очень обширная и многие интересные подробности пришлось опустить. Где-то, возможно, имеются неточности и ошибки — с радостью приму указание на них.
Очень интересная статья! А на gihub исходники выкладывать не будете? Спасибо!
Здравствуйте! Очень полезная статья! Занимаюсь разработкой программы передачи данных в соответствии с RFC5371. Там есть параметры SDP, описывающие видеопоток (описываются такие параметры как имя сессии, версия протокола, Ip-адрес приемника,отправителя,порт, а также цветовое пространство (RGB,BGR),развертка и тд.) Думал,если работали,то хотел посмотреть примеры реализации. Написал на TCP сокетах приложение передачи, теперь думаю как “прикрутить” SDP.
Может скините исходики,хотя бы там где SDP реализуется?
Всё есть в статье. У нас SDP передаётся посредством RTSP. Примеры параметров SDP так же есть, вам нужно их изменить в соответствии с форматом вашего видео.
Например, если у вас видео закодировано h264, то нужно использовать такой SDP-атрибут:
a=rtpmap:97 h264/90000
Нужно не забыть добавить описание fmtp и так далее.
А кто у вас выступает клиентом?
Клиент будет отправлять серверу изображение, а тот уже обрабатывать. Я написал простое сетевое приложение осуществляющее передачу строки серверу. А нужно все это делать используя RTP и SDP. Разбираюсь с SDP, пытаюсь реализовать. Я правильно понимаю, что нужно сделать структуру, в которой поля будут в соответствии со спецификацией? Пример (struct SDP {insigned int v; //protocol version; uint32_t unicast_address; и так далее?) А как вы поняли что если h264 то атрибут a=rtpmap:97 h264/90000, то в программе просто написать константу что-то типа #define sAtribut “rtpmap:97 h264/90000” ?? Интересно было бы посмотреть какое нибудь простое приложение использующее данные протоколы, тк не совсем ясно что куда писать. И еще вопрос, за сколько вы написали данную программу? Заранее спасибо!
a=rtpmap:97 h264/90000
97 – это такой тип динамического видео для RTP. http://en.wikipedia.org/wiki/RTP_audio_video_profile – здесь все перечислены.
h264 – это кодек видео. В вашем случае это будет jpeg2000.
90000 – это видео-битрейт.
В общем случае, это не константы. Если тип видео и кодек ещё можно таковыми сделать, то битрейт может изменяться от видео к видео.
SDP передаётся как обычный текст, поэтому в классе или в структуре вы это соберёте – не важно. Главное правильно затем перевести все атрибуты в текст и отформатировать. Каждый атрибут, например, отделяется от другого символом переноса строки.
С RFC 5371 я дела не имел, но после беглого взгляда могу сказать, вам скорее всего нужно прочесть ещё вот это: http://www.ietf.org/rfc/rfc3264.txt для того чтобы правильно передать SDP.
В нашем случае клиент передаёт “живой” поток серверу. Что у вас обрабатывает данные на сервере?
Что-то около двух месяцев ушло вместе с исследованиями.
90000 — это не видеобитрейт, а timescale, т.е. делитель для всех таймстемпов.
90 КГц тянется из mpegts, а в него из каких-то древних железок.
Мы тоже передаем видео. Расскажите плз о SDP. Вот я написал структуру. У меня есть приложение которе передает массив чаров-буфер.Я какой-нибудь функцией генерирую строку из полей структуры. Потом это все отправляется. Сервер слушает, принимает сообщение и у него есть какие-то строковые константы, определенные дефайнами. И он сравнивает их на эквивалентность и если все строки подходят, то значит он шлет обратно клиенту типа я готов принимать такое. Правилльно? Я в примерах не помню где видел там еще какой то параметр 200 Ok -что это? Еще раз спасибо.
Да, правильно. http://tools.ietf.org/html/rfc5371#section-7.2.1
Например, вы отправляете
m=video 49170 RTP/AVP 98, где 49170 – порт с которого вы будете вести передачу видео, а сервер в свою очередь должен передать порт на котором он будет ждать данные.
То же самое с a=rtpmap:98 jpeg2000/27000000
Здесь принимающая сторона может не уметь обрабатывать таймстампы с таким битрейтом. Впрочем в примере это ясно показано.
RTSP/1.0 200 OК – это ответ на команду RTSP-протокола.
RTSP управляет передачей live-видео. И если у вас именно такая передача, то вам нужно использовать именно этот протокол. И уже SDP вместе с ним. А непосредственно передавать видео-пакеты нужно с помощью RTP.
Огромное спасибо! А что за SESS_ID в полe SDP, вернее откуда его взять, там функция какая то будет, или он рандомно вычисляется? В спецификации говорится следующее is a numeric string such that the tuple of ,, ,, and forms a globally unique identifier for the session. The method of allocation is up to the creating tool, but it has been suggested that a Network Time Protocol (NTP) format timestamp be used to ensure uniqueness [13].*/
SESS_ID – это идентификатор сессии, соединения. Имеет смысл при многопотоковой трансляции(multicast), где он служит для определения каждого потока. Соответственно, должен быть уникальным. В случае вещания для одного клиента он тоже должен быть, но особой роли его значение не играет.
Что-то типа такого 1350628015 будет достаточно
Огромное спасибо! С SDP вроде разобрался-коряво но что то работает. Теперь, после того как сервер сравнит присланные параметры и отправит-да типа готов принимать, нужно отправлять по RTP\RTCP видео.Так вот, как вы реализовывали RTP? есть ли готовые реализации на СИ, как например при работе с TCP/IP мы используем готовые методы, а там как? Нашел книгу про сети,но там для Linux-но думаю разница не очень сильная, так ли? Заранее спасибо!
http://www.ietf.org/rfc/rfc3550.txt – это спецификация RTP, я реализовывал её.
Есть есть спецификация на формат полезной нагрузки для RTP пакета, это можно найти здесь(для h264 видео): http://www.ietf.org/rfc/rfc3984.txt
На github, sourceforge и других можно попытаться найти открытые реализации. Но здесь реализовывать не так много, поэтому можно просто прочитать спеку и самому сделать.
Вообще нет разницы Linux это или нет, это протокол, он должен поддерживаться везде одинаково.
Ок, спасибо.Несколько вопросов, касаемо SDP.Когда передатчик отправил серверу структуру с параметрами, сервер её проверил,он должен отправлять ту же самую структуру, или достаточно просто строки все ОК принимаю? И еще. Как вы получали параметры sess_id,и sess_version ? А также start_time и stop_time?
вы никогда не сможете реализовать _всю_ логику, которая есть в SDP, RTSP, RTP, поэтому не тратьте время и реализуйте то, что позволит вам доставить видео минимальными усилиями =)
Интернатура
Клиенты и партнеры
Орловский государственный университет имени И. С. Тургенева
Viasat
Просмотр фильмов и телеканалов
Приложения для SmartTV
Приложения для iOS и Android
КХЛ
Приложения для iOS и Android
МХЛ
Приложения для iOS и Android
Единая лига ВТБ
ОТР
Телеком Центр
ТВ Старт
CTI
CDNVideo
MSK-IX
Wifire
Binary People
Федерация гандбола России
НТВ-Плюс
СТС-Медиа
Просмотр фильмов и сериаловОнлайн-вещание
Российская Федерация Баскетбола
Федерация бадминтона
Мы
БАЗОВАЯКАФЕДРА
АСУиК
Все права защищены.
contacts@inventos.ru
+7 (4862) 599-998
Политика конфиденциальности
Наш сайт использует файлы cookies, чтобы улучшить работу и повысить эффективность сайта. Продолжая работу с сайтом, вы соглашаетесь с использованием нами cookies и политикой конфиденциальности.