Ретранслятор на основе Live555
От: cheloveky  
Дата: 13.09.11 09:08
Оценка:
Необходимо с помощью данной библиотеки создать сервер для приема видеопотока с IP-камер по RTSP/RTP протоколу и передачи этих же данных по этому же протоколу клиентам.
Прием с камеры реализован, передача из файла клиентам тоже реализована. Возникли проблемы при получении адреса (или сокета) клиента который подключился к серверу.

Часть кода начала воспроизведения потока полученного с камеры клиенту
// source подставляем в sink и запускаем воспроизведение
void StartStream(Groupsock *gs)
{
        *g_env << "= Session: " << g_cameraSession << " [main]\n";
        MediaSubsessionIterator iter(*g_cameraSession);
        while ((g_cameraSubsession = iter.next()) != NULL) {

            if (g_cameraSubsession->readSource() == NULL) continue; // was not initiated


            RTPSink* rtpSink;

            // Normal case:
            unsigned const maxPacketSize = 65536; // allow for large UDP packets
            
            // Для создания sink конструктор взят из примера testRelay.cpp (перенаправляет RTP поток)
            rtpSink = (RTPSink*)BasicUDPSink::createNew(*g_env, gs, maxPacketSize);

            g_cameraSubsession->sink = rtpSink;
            if (g_cameraSubsession->sink == NULL) {
                *g_env << "Failed to create RTPSink for \"" << g_cameraStreamURL
                     << "\": " << g_env->getResultMsg() << "\n";
            } else {

                *g_env << "Created output file: \"" << g_cameraStreamURL << "\"\n";

                g_cameraSubsession->sink->startPlaying(*(g_cameraSubsession->readSource()),
                                               subsessionAfterPlaying,
                                               g_cameraSubsession);


                // Also set a handler to be called if a RTCP "BYE" arrives
                // for this subsession:
                if (g_cameraSubsession->rtcpInstance() != NULL) {
                    g_cameraSubsession->rtcpInstance()->setByeHandler(subsessionByeHandler, g_cameraSubsession);
                }
                madeProgress = True;
            }
        }
        if (!madeProgress) shutdown();

        ....

        startPlayingSession(g_cameraSession, g_initialSeekTime, g_endTime, g_scale, continueAfterPLAY);
}

void startPlayingSession(MediaSession* session, double start, double end, float scale, RTSPClient::responseHandler* afterFunc) {
  g_ourRTSPClient->sendPlayCommand(*session, afterFunc, start, end, scale, g_ourAuthenticator);
}

// Часть кода который обрабатывает подключение клиента
ServerMediaSession* VideoRTSPServer::lookupServerMediaSession(char const* streamName)
{
    ServerMediaSession* sms = RTSPServer::lookupServerMediaSession(streamName);
    Boolean smsExists = sms != NULL;

    if (!smsExists) {
        sms = createNewSMS(envir(), streamName);
        addServerMediaSession(sms);
    }    
    return sms;
}

// Так реализовано создание сессии для трансляции потока из файла, а необходимо транслировать с IP-камеры через сервер
static ServerMediaSession* createNewSMS(UsageEnvironment& env,
                    char const* fileName, FILE* /*fid*/) {
  // Use the file name extension to determine the type of "ServerMediaSession":
  char const* extension = strrchr(fileName, '.');
  if (extension == NULL) return NULL;

  ServerMediaSession* sms = NULL;
  Boolean const reuseSource = False;
  if (strcmp(extension, ".264") == 0) {
    // Assumed to be a H.264 Video Elementary Stream file:
    NEW_SMS("H.264 Video");
    OutPacketBuffer::maxSize = 100000; // allow for some possibly large H.264 frames
    sms->addSubsession(H264VideoFileServerMediaSubsession::createNew(env, fileName, reuseSource));
  }
  return sms;
}
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.