Необходимо с помощью данной библиотеки создать сервер для приема видеопотока с 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;
}