Публикация потока с использованием librtmp в C / C ++ - PullRequest
7 голосов
/ 24 декабря 2010

Как опубликовать поток с помощью библиотеки librtmp?Я прочитал справочную страницу librtmp и для публикации используется RTMP_Write ().

Я делаю так.

//Code
//Init RTMP code
RTMP *r;
char uri[]="rtmp://localhost:1935/live/desktop";
r= RTMP_Alloc();
RTMP_Init(r);
RTMP_SetupURL(r, (char*)uri);
RTMP_EnableWrite(r);
RTMP_Connect(r, NULL);
RTMP_ConnectStream(r,0);

Затем, чтобы ответить на ping / другие сообщения от сервера,используя поток, чтобы ответить следующим образом:

//Thread
While (ThreadIsRunning && RTMP_IsConnected(r) && RTMP_ReadPacket(r, &packet))
{
   if (RTMPPacket_IsReady(&packet))
   {
 if (!packet.m_nBodySize)
         continue;
    RTMP_ClientPacket(r, &packet); //This takes care of handling ping/other messages
    RTMPPacket_Free(&packet);
   }
}

После этого я застрял в том, как использовать RTMP_Write () для публикации файла на медиа-сервере Wowza?

Ответы [ 2 ]

6 голосов
/ 10 декабря 2012

По моему опыту, потоковая передача видеоданных на RTMP-сервер на самом деле довольно проста на стороне librtmp.Задача состоит в том, чтобы правильно упаковать видео / аудио данные и прочитать их с правильной скоростью.

Предполагается, что вы используете FLV-видеофайлы, при условии, что вы можете правильно изолировать каждый тег в файле и отправить каждый из них, используяодин RTMP_Write вызов, вам даже не нужно обрабатывать входящие пакеты.

Сложнее понять, как создаются файлы FLV.Официальная спецификация доступна здесь: http://www.adobe.com/devnet/f4v.html

Во-первых, есть заголовок, который состоит из 9 байтов.Этот заголовок не должен отправляться на сервер, а должен быть прочитан только для того, чтобы убедиться, что файл действительно FLV.

Тогда существует поток тегов.Каждый тег имеет 11-байтовый заголовок, который, помимо прочего, содержит тип тега (видео / аудио / метаданные), длину тела и метку времени тега.

Заголовок тега можно описать с помощью этой структуры:

typedef struct __flv_tag {
  uint8       type;
  uint24_be   body_length; /* in bytes, total tag size minus 11 */
  uint24_be   timestamp; /* milli-seconds */
  uint8       timestamp_extended; /* timestamp extension */
  uint24_be   stream_id; /* reserved, must be "\0\0\0" */
  /* body comes next */
} flv_tag;

Длина тела и временная метка представлены в виде 24-разрядных целых чисел с прямым порядком байтов, с дополнительным байтом для расширения временной метки, если необходимо, до 32 бит (это приблизительно в пределах отметки 4 часа).

Как только вы прочитали заголовок тега, вы можете прочитать само тело, поскольку теперь вы знаете его длину (body_length).

После этого существует 32-разрядное целое число с прямым порядком байтов, содержащее полноедлина тега (11 байт + body_length).

Вы должны записать заголовок тега + тело + предыдущий размер тега в один RTMP_Write вызов (иначе он не будет воспроизводиться).

Кроме того, будьте осторожны при отправке пакетов с номинальной частотой кадров видео, иначе воспроизведение сильно пострадает.

Я написал полный демультиплексор FLV-файла как часть моего проекта GPL FLVmeta , который вы можете использовать в качестве справочного.

0 голосов
/ 15 марта 2011

Фактически, для RTMP_Write () требуется, чтобы у вас уже был пакет RTMP, сформированный в buf. * ​​1001 *

RTMPPacket *pkt = &r->m_write;
...
pkt->m_packetType = *buf++;

Итак, вы не можете просто отправить туда данные flv - вам нужно разделить их на пакетыfirst.

Есть хорошая функция, RTMP_ReadPacket (), но она считывает данные из сетевого сокета.

У меня та же проблема, что и у вас, надеюсь скоро найти решение.

Редактировать:

В RTMP_Write () есть определенные ошибки.Я сделал патч, и теперь он работает.Я собираюсь опубликовать это.

...