mirror of
https://github.com/mpromonet/v4l2rtspserver
synced 2024-11-02 03:40:13 +00:00
extract ServerMediaSubsession classes in separated files
This commit is contained in:
parent
e18f4670fc
commit
87b4d5b541
40
inc/MulticastServerMediaSubsession.h
Normal file
40
inc/MulticastServerMediaSubsession.h
Normal file
@ -0,0 +1,40 @@
|
||||
/* ---------------------------------------------------------------------------
|
||||
** This software is in the public domain, furnished "as is", without technical
|
||||
** support, and with no warranty, express or implied, as to its usefulness for
|
||||
** any purpose.
|
||||
**
|
||||
** ServerMediaSubsession.h
|
||||
**
|
||||
** -------------------------------------------------------------------------*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "ServerMediaSubsession.h"
|
||||
|
||||
// -----------------------------------------
|
||||
// ServerMediaSubsession for Multicast
|
||||
// -----------------------------------------
|
||||
class MulticastServerMediaSubsession : public PassiveServerMediaSubsession , public BaseServerMediaSubsession
|
||||
{
|
||||
public:
|
||||
static MulticastServerMediaSubsession* createNew(UsageEnvironment& env
|
||||
, struct in_addr destinationAddress
|
||||
, Port rtpPortNum, Port rtcpPortNum
|
||||
, int ttl
|
||||
, StreamReplicator* replicator
|
||||
, const std::string& format);
|
||||
|
||||
protected:
|
||||
MulticastServerMediaSubsession(StreamReplicator* replicator, RTPSink* rtpSink, RTCPInstance* rtcpInstance)
|
||||
: PassiveServerMediaSubsession(*rtpSink, rtcpInstance), BaseServerMediaSubsession(replicator), m_rtpSink(rtpSink) {};
|
||||
|
||||
virtual char const* sdpLines() ;
|
||||
virtual char const* getAuxSDPLine(RTPSink* rtpSink,FramedSource* inputSource);
|
||||
|
||||
protected:
|
||||
RTPSink* m_rtpSink;
|
||||
std::string m_SDPLines;
|
||||
};
|
||||
|
||||
|
||||
|
78
inc/SegmentServerMediaSubsession.h
Normal file
78
inc/SegmentServerMediaSubsession.h
Normal file
@ -0,0 +1,78 @@
|
||||
/* ---------------------------------------------------------------------------
|
||||
** This software is in the public domain, furnished "as is", without technical
|
||||
** support, and with no warranty, express or implied, as to its usefulness for
|
||||
** any purpose.
|
||||
**
|
||||
** ServerMediaSubsession.h
|
||||
**
|
||||
** -------------------------------------------------------------------------*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "UnicastServerMediaSubsession.h"
|
||||
|
||||
// -----------------------------------------
|
||||
// ServerMediaSubsession for HLS
|
||||
// -----------------------------------------
|
||||
class HLSServerMediaSubsession : public UnicastServerMediaSubsession
|
||||
{
|
||||
class HLSSink : public MediaSink
|
||||
{
|
||||
public:
|
||||
static HLSSink* createNew(UsageEnvironment& env, unsigned int bufferSize, unsigned int sliceDuration)
|
||||
{
|
||||
return new HLSSink(env, bufferSize, sliceDuration);
|
||||
}
|
||||
|
||||
protected:
|
||||
HLSSink(UsageEnvironment& env, unsigned bufferSize, unsigned int sliceDuration);
|
||||
virtual ~HLSSink();
|
||||
|
||||
virtual Boolean continuePlaying();
|
||||
|
||||
static void afterGettingFrame(void* clientData, unsigned frameSize,
|
||||
unsigned numTruncatedBytes,
|
||||
struct timeval presentationTime,
|
||||
unsigned durationInMicroseconds) {
|
||||
HLSSink* sink = (HLSSink*)clientData;
|
||||
sink->afterGettingFrame(frameSize, numTruncatedBytes, presentationTime);
|
||||
}
|
||||
|
||||
void afterGettingFrame(unsigned frameSize, unsigned numTruncatedBytes, struct timeval presentationTime);
|
||||
|
||||
public:
|
||||
unsigned int getHLSBufferSize(unsigned int slice);
|
||||
const char* getHLSBuffer(unsigned int slice);
|
||||
unsigned int firstTime();
|
||||
unsigned int duration();
|
||||
unsigned int getSliceDuration() { return m_sliceDuration; }
|
||||
|
||||
private:
|
||||
unsigned char * m_buffer;
|
||||
unsigned int m_bufferSize;
|
||||
std::map<unsigned int,std::string> m_outputBuffers;
|
||||
unsigned int m_refTime;
|
||||
unsigned int m_sliceDuration;
|
||||
};
|
||||
|
||||
public:
|
||||
static HLSServerMediaSubsession* createNew(UsageEnvironment& env, StreamReplicator* replicator, const std::string& format, unsigned int sliceDuration)
|
||||
{
|
||||
return new HLSServerMediaSubsession(env, replicator, format, sliceDuration);
|
||||
}
|
||||
|
||||
protected:
|
||||
HLSServerMediaSubsession(UsageEnvironment& env, StreamReplicator* replicator, const std::string& format, unsigned int sliceDuration);
|
||||
virtual ~HLSServerMediaSubsession();
|
||||
|
||||
virtual float getCurrentNPT(void* streamToken);
|
||||
virtual float duration() const ;
|
||||
virtual void seekStream(unsigned clientSessionId, void* streamToken, double& seekNPT, double streamDuration, u_int64_t& numBytes);
|
||||
virtual FramedSource* getStreamSource(void* streamToken);
|
||||
|
||||
protected:
|
||||
unsigned int m_slice;
|
||||
HLSSink * m_hlsSink;
|
||||
};
|
||||
|
||||
|
@ -7,8 +7,7 @@
|
||||
**
|
||||
** -------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef SERVER_MEDIA_SUBSESSION
|
||||
#define SERVER_MEDIA_SUBSESSION
|
||||
#pragma once
|
||||
|
||||
#include <sys/stat.h>
|
||||
|
||||
@ -16,7 +15,6 @@
|
||||
#include <iomanip>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <map>
|
||||
|
||||
// live555
|
||||
#include <liveMedia.hh>
|
||||
@ -41,234 +39,3 @@ class BaseServerMediaSubsession
|
||||
StreamReplicator* m_replicator;
|
||||
};
|
||||
|
||||
// -----------------------------------------
|
||||
// ServerMediaSubsession for Multicast
|
||||
// -----------------------------------------
|
||||
class MulticastServerMediaSubsession : public PassiveServerMediaSubsession , public BaseServerMediaSubsession
|
||||
{
|
||||
public:
|
||||
static MulticastServerMediaSubsession* createNew(UsageEnvironment& env
|
||||
, struct in_addr destinationAddress
|
||||
, Port rtpPortNum, Port rtcpPortNum
|
||||
, int ttl
|
||||
, StreamReplicator* replicator
|
||||
, const std::string& format);
|
||||
|
||||
protected:
|
||||
MulticastServerMediaSubsession(StreamReplicator* replicator, RTPSink* rtpSink, RTCPInstance* rtcpInstance)
|
||||
: PassiveServerMediaSubsession(*rtpSink, rtcpInstance), BaseServerMediaSubsession(replicator), m_rtpSink(rtpSink) {};
|
||||
|
||||
virtual char const* sdpLines() ;
|
||||
virtual char const* getAuxSDPLine(RTPSink* rtpSink,FramedSource* inputSource);
|
||||
|
||||
protected:
|
||||
RTPSink* m_rtpSink;
|
||||
std::string m_SDPLines;
|
||||
};
|
||||
|
||||
// -----------------------------------------
|
||||
// ServerMediaSubsession for Unicast
|
||||
// -----------------------------------------
|
||||
class UnicastServerMediaSubsession : public OnDemandServerMediaSubsession , public BaseServerMediaSubsession
|
||||
{
|
||||
public:
|
||||
static UnicastServerMediaSubsession* createNew(UsageEnvironment& env, StreamReplicator* replicator, const std::string& format);
|
||||
|
||||
protected:
|
||||
UnicastServerMediaSubsession(UsageEnvironment& env, StreamReplicator* replicator, const std::string& format)
|
||||
: OnDemandServerMediaSubsession(env, False), BaseServerMediaSubsession(replicator), m_format(format) {};
|
||||
|
||||
virtual FramedSource* createNewStreamSource(unsigned clientSessionId, unsigned& estBitrate);
|
||||
virtual RTPSink* createNewRTPSink(Groupsock* rtpGroupsock, unsigned char rtpPayloadTypeIfDynamic, FramedSource* inputSource);
|
||||
virtual char const* getAuxSDPLine(RTPSink* rtpSink,FramedSource* inputSource);
|
||||
|
||||
protected:
|
||||
const std::string m_format;
|
||||
};
|
||||
|
||||
// -----------------------------------------
|
||||
// ServerMediaSubsession for HLS
|
||||
// -----------------------------------------
|
||||
class HLSServerMediaSubsession : public UnicastServerMediaSubsession
|
||||
{
|
||||
class HLSSink : public MediaSink
|
||||
{
|
||||
public:
|
||||
static HLSSink* createNew(UsageEnvironment& env, unsigned int bufferSize, unsigned int sliceDuration)
|
||||
{
|
||||
return new HLSSink(env, bufferSize, sliceDuration);
|
||||
}
|
||||
|
||||
protected:
|
||||
HLSSink(UsageEnvironment& env, unsigned bufferSize, unsigned int sliceDuration) : MediaSink(env), m_bufferSize(bufferSize), m_refTime(0), m_sliceDuration(sliceDuration)
|
||||
{
|
||||
m_buffer = new unsigned char[m_bufferSize];
|
||||
}
|
||||
|
||||
virtual ~HLSSink()
|
||||
{
|
||||
delete[] m_buffer;
|
||||
}
|
||||
|
||||
|
||||
virtual Boolean continuePlaying()
|
||||
{
|
||||
Boolean ret = False;
|
||||
if (fSource != NULL)
|
||||
{
|
||||
fSource->getNextFrame(m_buffer, m_bufferSize,
|
||||
afterGettingFrame, this,
|
||||
onSourceClosure, this);
|
||||
ret = True;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void afterGettingFrame(void* clientData, unsigned frameSize,
|
||||
unsigned numTruncatedBytes,
|
||||
struct timeval presentationTime,
|
||||
unsigned durationInMicroseconds)
|
||||
{
|
||||
HLSSink* sink = (HLSSink*)clientData;
|
||||
sink->afterGettingFrame(frameSize, numTruncatedBytes, presentationTime);
|
||||
}
|
||||
|
||||
void afterGettingFrame(unsigned frameSize, unsigned numTruncatedBytes, struct timeval presentationTime)
|
||||
{
|
||||
if (numTruncatedBytes > 0)
|
||||
{
|
||||
envir() << "FileSink::afterGettingFrame(): The input frame data was too large for our buffer size \n";
|
||||
// realloc a bigger buffer
|
||||
m_bufferSize += numTruncatedBytes;
|
||||
delete[] m_buffer;
|
||||
m_buffer = new unsigned char[m_bufferSize];
|
||||
}
|
||||
else
|
||||
{
|
||||
// append buffer to slice buffer
|
||||
if (m_refTime == 0)
|
||||
{
|
||||
m_refTime = presentationTime.tv_sec;
|
||||
}
|
||||
unsigned int slice = (presentationTime.tv_sec-m_refTime)/m_sliceDuration;
|
||||
std::string& outputBuffer = m_outputBuffers[slice];
|
||||
outputBuffer.append((const char*)m_buffer, frameSize);
|
||||
|
||||
// remove old buffers
|
||||
while (m_outputBuffers.size()>5)
|
||||
{
|
||||
m_outputBuffers.erase(m_outputBuffers.begin());
|
||||
}
|
||||
}
|
||||
|
||||
continuePlaying();
|
||||
}
|
||||
|
||||
public:
|
||||
unsigned int getHLSBufferSize(unsigned int slice)
|
||||
{
|
||||
unsigned int size = 0;
|
||||
std::map<unsigned int,std::string>::iterator it = m_outputBuffers.find(slice);
|
||||
if (it != m_outputBuffers.end())
|
||||
{
|
||||
size = it->second.size();
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
const char* getHLSBuffer(unsigned int slice)
|
||||
{
|
||||
const char* content = NULL;
|
||||
std::map<unsigned int,std::string>::iterator it = m_outputBuffers.find(slice);
|
||||
if (it != m_outputBuffers.end())
|
||||
{
|
||||
content = it->second.c_str();
|
||||
}
|
||||
return content;
|
||||
}
|
||||
|
||||
unsigned int firstTime()
|
||||
{
|
||||
unsigned int firstTime = 0;
|
||||
if (m_outputBuffers.size() != 0)
|
||||
{
|
||||
firstTime = m_outputBuffers.begin()->first;
|
||||
}
|
||||
return firstTime*m_sliceDuration;
|
||||
}
|
||||
|
||||
unsigned int duration()
|
||||
{
|
||||
unsigned int duration = 0;
|
||||
if (m_outputBuffers.size() != 0)
|
||||
{
|
||||
duration = m_outputBuffers.rbegin()->first - m_outputBuffers.begin()->first;
|
||||
}
|
||||
return (duration)*m_sliceDuration;
|
||||
}
|
||||
unsigned int getSliceDuration()
|
||||
{
|
||||
return m_sliceDuration;
|
||||
}
|
||||
|
||||
private:
|
||||
unsigned char * m_buffer;
|
||||
unsigned int m_bufferSize;
|
||||
std::map<unsigned int,std::string> m_outputBuffers;
|
||||
unsigned int m_refTime;
|
||||
unsigned int m_sliceDuration;
|
||||
};
|
||||
|
||||
public:
|
||||
static HLSServerMediaSubsession* createNew(UsageEnvironment& env, StreamReplicator* replicator, const std::string& format, unsigned int sliceDuration)
|
||||
{
|
||||
return new HLSServerMediaSubsession(env, replicator, format, sliceDuration);
|
||||
}
|
||||
|
||||
protected:
|
||||
HLSServerMediaSubsession(UsageEnvironment& env, StreamReplicator* replicator, const std::string& format, unsigned int sliceDuration)
|
||||
: UnicastServerMediaSubsession(env, replicator, format), m_slice(0)
|
||||
{
|
||||
// Create a source
|
||||
FramedSource* source = replicator->createStreamReplica();
|
||||
FramedSource* videoSource = createSource(env, source, format);
|
||||
|
||||
// Start Playing the HLS Sink
|
||||
m_hlsSink = HLSSink::createNew(env, OutPacketBuffer::maxSize, sliceDuration);
|
||||
m_hlsSink->startPlaying(*videoSource, NULL, NULL);
|
||||
}
|
||||
virtual ~HLSServerMediaSubsession()
|
||||
{
|
||||
Medium::close(m_hlsSink);
|
||||
}
|
||||
|
||||
virtual float getCurrentNPT(void* streamToken)
|
||||
{
|
||||
return (m_hlsSink->firstTime());
|
||||
}
|
||||
virtual float duration() const
|
||||
{
|
||||
return (m_hlsSink->duration());
|
||||
}
|
||||
virtual void seekStream(unsigned clientSessionId, void* streamToken, double& seekNPT, double streamDuration, u_int64_t& numBytes)
|
||||
{
|
||||
m_slice = seekNPT / m_hlsSink->getSliceDuration();
|
||||
seekNPT = m_slice * m_hlsSink->getSliceDuration();
|
||||
numBytes = m_hlsSink->getHLSBufferSize(m_slice);
|
||||
std::cout << "seek seekNPT:" << seekNPT << " slice:" << m_slice << " numBytes:" << numBytes << std::endl;
|
||||
|
||||
}
|
||||
virtual FramedSource* getStreamSource(void* streamToken)
|
||||
{
|
||||
unsigned int size = m_hlsSink->getHLSBufferSize(m_slice);
|
||||
u_int8_t* content = new u_int8_t[size];
|
||||
memcpy(content, m_hlsSink->getHLSBuffer(m_slice), size);
|
||||
return ByteStreamMemoryBufferSource::createNew(envir(), content, size);
|
||||
}
|
||||
|
||||
protected:
|
||||
unsigned int m_slice;
|
||||
HLSSink * m_hlsSink;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
34
inc/UnicastServerMediaSubsession.h
Normal file
34
inc/UnicastServerMediaSubsession.h
Normal file
@ -0,0 +1,34 @@
|
||||
/* ---------------------------------------------------------------------------
|
||||
** This software is in the public domain, furnished "as is", without technical
|
||||
** support, and with no warranty, express or implied, as to its usefulness for
|
||||
** any purpose.
|
||||
**
|
||||
** ServerMediaSubsession.h
|
||||
**
|
||||
** -------------------------------------------------------------------------*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "ServerMediaSubsession.h"
|
||||
|
||||
// -----------------------------------------
|
||||
// ServerMediaSubsession for Unicast
|
||||
// -----------------------------------------
|
||||
class UnicastServerMediaSubsession : public OnDemandServerMediaSubsession , public BaseServerMediaSubsession
|
||||
{
|
||||
public:
|
||||
static UnicastServerMediaSubsession* createNew(UsageEnvironment& env, StreamReplicator* replicator, const std::string& format);
|
||||
|
||||
protected:
|
||||
UnicastServerMediaSubsession(UsageEnvironment& env, StreamReplicator* replicator, const std::string& format)
|
||||
: OnDemandServerMediaSubsession(env, False), BaseServerMediaSubsession(replicator), m_format(format) {};
|
||||
|
||||
virtual FramedSource* createNewStreamSource(unsigned clientSessionId, unsigned& estBitrate);
|
||||
virtual RTPSink* createNewRTPSink(Groupsock* rtpGroupsock, unsigned char rtpPayloadTypeIfDynamic, FramedSource* inputSource);
|
||||
virtual char const* getAuxSDPLine(RTPSink* rtpSink,FramedSource* inputSource);
|
||||
|
||||
protected:
|
||||
const std::string m_format;
|
||||
};
|
||||
|
||||
|
62
src/MulticastServerMediaSubsession.cpp
Normal file
62
src/MulticastServerMediaSubsession.cpp
Normal file
@ -0,0 +1,62 @@
|
||||
/* ---------------------------------------------------------------------------
|
||||
** This software is in the public domain, furnished "as is", without technical
|
||||
** support, and with no warranty, express or implied, as to its usefulness for
|
||||
** any purpose.
|
||||
**
|
||||
** MulticastServerMediaSubsession.cpp
|
||||
**
|
||||
** -------------------------------------------------------------------------*/
|
||||
|
||||
#include "MulticastServerMediaSubsession.h"
|
||||
#include "DeviceSource.h"
|
||||
|
||||
// -----------------------------------------
|
||||
// ServerMediaSubsession for Multicast
|
||||
// -----------------------------------------
|
||||
MulticastServerMediaSubsession* MulticastServerMediaSubsession::createNew(UsageEnvironment& env
|
||||
, struct in_addr destinationAddress
|
||||
, Port rtpPortNum, Port rtcpPortNum
|
||||
, int ttl
|
||||
, StreamReplicator* replicator
|
||||
, const std::string& format)
|
||||
{
|
||||
// Create a source
|
||||
FramedSource* source = replicator->createStreamReplica();
|
||||
FramedSource* videoSource = createSource(env, source, format);
|
||||
|
||||
// Create RTP/RTCP groupsock
|
||||
Groupsock* rtpGroupsock = new Groupsock(env, destinationAddress, rtpPortNum, ttl);
|
||||
Groupsock* rtcpGroupsock = new Groupsock(env, destinationAddress, rtcpPortNum, ttl);
|
||||
|
||||
// Create a RTP sink
|
||||
RTPSink* videoSink = createSink(env, rtpGroupsock, 96, format);
|
||||
|
||||
// Create 'RTCP instance'
|
||||
const unsigned maxCNAMElen = 100;
|
||||
unsigned char CNAME[maxCNAMElen+1];
|
||||
gethostname((char*)CNAME, maxCNAMElen);
|
||||
CNAME[maxCNAMElen] = '\0';
|
||||
RTCPInstance* rtcpInstance = RTCPInstance::createNew(env, rtcpGroupsock, 500, CNAME, videoSink, NULL);
|
||||
|
||||
// Start Playing the Sink
|
||||
videoSink->startPlaying(*videoSource, NULL, NULL);
|
||||
|
||||
return new MulticastServerMediaSubsession(replicator, videoSink, rtcpInstance);
|
||||
}
|
||||
|
||||
char const* MulticastServerMediaSubsession::sdpLines()
|
||||
{
|
||||
if (m_SDPLines.empty())
|
||||
{
|
||||
// Ugly workaround to give SPS/PPS that are get from the RTPSink
|
||||
m_SDPLines.assign(PassiveServerMediaSubsession::sdpLines());
|
||||
m_SDPLines.append(getAuxSDPLine(m_rtpSink,NULL));
|
||||
}
|
||||
return m_SDPLines.c_str();
|
||||
}
|
||||
|
||||
char const* MulticastServerMediaSubsession::getAuxSDPLine(RTPSink* rtpSink,FramedSource* inputSource)
|
||||
{
|
||||
return this->getAuxLine(dynamic_cast<V4L2DeviceSource*>(m_replicator->inputSource()), rtpSink->rtpPayloadType());
|
||||
}
|
||||
|
158
src/SegmentServerMediaSubsession.cpp
Normal file
158
src/SegmentServerMediaSubsession.cpp
Normal file
@ -0,0 +1,158 @@
|
||||
/* ---------------------------------------------------------------------------
|
||||
** This software is in the public domain, furnished "as is", without technical
|
||||
** support, and with no warranty, express or implied, as to its usefulness for
|
||||
** any purpose.
|
||||
**
|
||||
** SegmentServerMediaSubsession.cpp
|
||||
**
|
||||
** -------------------------------------------------------------------------*/
|
||||
|
||||
#include <map>
|
||||
|
||||
#include "SegmentServerMediaSubsession.h"
|
||||
|
||||
// -----------------------------------------
|
||||
// ServerMediaSubsession for HLS
|
||||
// -----------------------------------------
|
||||
HLSServerMediaSubsession::HLSSink::HLSSink(UsageEnvironment& env, unsigned bufferSize, unsigned int sliceDuration) : MediaSink(env), m_bufferSize(bufferSize), m_refTime(0), m_sliceDuration(sliceDuration)
|
||||
{
|
||||
m_buffer = new unsigned char[m_bufferSize];
|
||||
}
|
||||
|
||||
HLSServerMediaSubsession::HLSSink::~HLSSink()
|
||||
{
|
||||
delete[] m_buffer;
|
||||
}
|
||||
|
||||
|
||||
Boolean HLSServerMediaSubsession::HLSSink::continuePlaying()
|
||||
{
|
||||
Boolean ret = False;
|
||||
if (fSource != NULL)
|
||||
{
|
||||
fSource->getNextFrame(m_buffer, m_bufferSize,
|
||||
afterGettingFrame, this,
|
||||
onSourceClosure, this);
|
||||
ret = True;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
void HLSServerMediaSubsession::HLSSink::afterGettingFrame(unsigned frameSize, unsigned numTruncatedBytes, struct timeval presentationTime)
|
||||
{
|
||||
if (numTruncatedBytes > 0)
|
||||
{
|
||||
envir() << "FileSink::afterGettingFrame(): The input frame data was too large for our buffer size \n";
|
||||
// realloc a bigger buffer
|
||||
m_bufferSize += numTruncatedBytes;
|
||||
delete[] m_buffer;
|
||||
m_buffer = new unsigned char[m_bufferSize];
|
||||
}
|
||||
else
|
||||
{
|
||||
// append buffer to slice buffer
|
||||
if (m_refTime == 0)
|
||||
{
|
||||
m_refTime = presentationTime.tv_sec;
|
||||
}
|
||||
unsigned int slice = (presentationTime.tv_sec-m_refTime)/m_sliceDuration;
|
||||
std::string& outputBuffer = m_outputBuffers[slice];
|
||||
outputBuffer.append((const char*)m_buffer, frameSize);
|
||||
|
||||
// remove old buffers
|
||||
while (m_outputBuffers.size()>5)
|
||||
{
|
||||
m_outputBuffers.erase(m_outputBuffers.begin());
|
||||
}
|
||||
}
|
||||
|
||||
continuePlaying();
|
||||
}
|
||||
|
||||
unsigned int HLSServerMediaSubsession::HLSSink::getHLSBufferSize(unsigned int slice)
|
||||
{
|
||||
unsigned int size = 0;
|
||||
std::map<unsigned int,std::string>::iterator it = m_outputBuffers.find(slice);
|
||||
if (it != m_outputBuffers.end())
|
||||
{
|
||||
size = it->second.size();
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
const char* HLSServerMediaSubsession::HLSSink::getHLSBuffer(unsigned int slice)
|
||||
{
|
||||
const char* content = NULL;
|
||||
std::map<unsigned int,std::string>::iterator it = m_outputBuffers.find(slice);
|
||||
if (it != m_outputBuffers.end())
|
||||
{
|
||||
content = it->second.c_str();
|
||||
}
|
||||
return content;
|
||||
}
|
||||
|
||||
unsigned int HLSServerMediaSubsession::HLSSink::firstTime()
|
||||
{
|
||||
unsigned int firstTime = 0;
|
||||
if (m_outputBuffers.size() != 0)
|
||||
{
|
||||
firstTime = m_outputBuffers.begin()->first;
|
||||
}
|
||||
return firstTime*m_sliceDuration;
|
||||
}
|
||||
|
||||
unsigned int HLSServerMediaSubsession::HLSSink::duration()
|
||||
{
|
||||
unsigned int duration = 0;
|
||||
if (m_outputBuffers.size() != 0)
|
||||
{
|
||||
duration = m_outputBuffers.rbegin()->first - m_outputBuffers.begin()->first;
|
||||
}
|
||||
return (duration)*m_sliceDuration;
|
||||
}
|
||||
|
||||
|
||||
HLSServerMediaSubsession::HLSServerMediaSubsession(UsageEnvironment& env, StreamReplicator* replicator, const std::string& format, unsigned int sliceDuration)
|
||||
: UnicastServerMediaSubsession(env, replicator, format), m_slice(0)
|
||||
{
|
||||
// Create a source
|
||||
FramedSource* source = replicator->createStreamReplica();
|
||||
FramedSource* videoSource = createSource(env, source, format);
|
||||
|
||||
// Start Playing the HLS Sink
|
||||
m_hlsSink = HLSSink::createNew(env, OutPacketBuffer::maxSize, sliceDuration);
|
||||
m_hlsSink->startPlaying(*videoSource, NULL, NULL);
|
||||
}
|
||||
|
||||
HLSServerMediaSubsession::~HLSServerMediaSubsession()
|
||||
{
|
||||
Medium::close(m_hlsSink);
|
||||
}
|
||||
|
||||
float HLSServerMediaSubsession::getCurrentNPT(void* streamToken)
|
||||
{
|
||||
return (m_hlsSink->firstTime());
|
||||
}
|
||||
|
||||
float HLSServerMediaSubsession::duration() const
|
||||
{
|
||||
return (m_hlsSink->duration());
|
||||
}
|
||||
|
||||
void HLSServerMediaSubsession::seekStream(unsigned clientSessionId, void* streamToken, double& seekNPT, double streamDuration, u_int64_t& numBytes)
|
||||
{
|
||||
m_slice = seekNPT / m_hlsSink->getSliceDuration();
|
||||
seekNPT = m_slice * m_hlsSink->getSliceDuration();
|
||||
numBytes = m_hlsSink->getHLSBufferSize(m_slice);
|
||||
std::cout << "seek seekNPT:" << seekNPT << " slice:" << m_slice << " numBytes:" << numBytes << std::endl;
|
||||
|
||||
}
|
||||
|
||||
FramedSource* HLSServerMediaSubsession::getStreamSource(void* streamToken)
|
||||
{
|
||||
unsigned int size = m_hlsSink->getHLSBufferSize(m_slice);
|
||||
u_int8_t* content = new u_int8_t[size];
|
||||
memcpy(content, m_hlsSink->getHLSBuffer(m_slice), size);
|
||||
return ByteStreamMemoryBufferSource::createNew(envir(), content, size);
|
||||
}
|
@ -9,10 +9,6 @@
|
||||
|
||||
#include <sstream>
|
||||
|
||||
// live555
|
||||
#include <BasicUsageEnvironment.hh>
|
||||
#include <GroupsockHelper.hh>
|
||||
#include <Base64.hh>
|
||||
|
||||
// project
|
||||
#include "ServerMediaSubsession.h"
|
||||
@ -113,77 +109,3 @@ char const* BaseServerMediaSubsession::getAuxLine(V4L2DeviceSource* source,unsig
|
||||
return auxLine;
|
||||
}
|
||||
|
||||
// -----------------------------------------
|
||||
// ServerMediaSubsession for Multicast
|
||||
// -----------------------------------------
|
||||
MulticastServerMediaSubsession* MulticastServerMediaSubsession::createNew(UsageEnvironment& env
|
||||
, struct in_addr destinationAddress
|
||||
, Port rtpPortNum, Port rtcpPortNum
|
||||
, int ttl
|
||||
, StreamReplicator* replicator
|
||||
, const std::string& format)
|
||||
{
|
||||
// Create a source
|
||||
FramedSource* source = replicator->createStreamReplica();
|
||||
FramedSource* videoSource = createSource(env, source, format);
|
||||
|
||||
// Create RTP/RTCP groupsock
|
||||
Groupsock* rtpGroupsock = new Groupsock(env, destinationAddress, rtpPortNum, ttl);
|
||||
Groupsock* rtcpGroupsock = new Groupsock(env, destinationAddress, rtcpPortNum, ttl);
|
||||
|
||||
// Create a RTP sink
|
||||
RTPSink* videoSink = createSink(env, rtpGroupsock, 96, format);
|
||||
|
||||
// Create 'RTCP instance'
|
||||
const unsigned maxCNAMElen = 100;
|
||||
unsigned char CNAME[maxCNAMElen+1];
|
||||
gethostname((char*)CNAME, maxCNAMElen);
|
||||
CNAME[maxCNAMElen] = '\0';
|
||||
RTCPInstance* rtcpInstance = RTCPInstance::createNew(env, rtcpGroupsock, 500, CNAME, videoSink, NULL);
|
||||
|
||||
// Start Playing the Sink
|
||||
videoSink->startPlaying(*videoSource, NULL, NULL);
|
||||
|
||||
return new MulticastServerMediaSubsession(replicator, videoSink, rtcpInstance);
|
||||
}
|
||||
|
||||
char const* MulticastServerMediaSubsession::sdpLines()
|
||||
{
|
||||
if (m_SDPLines.empty())
|
||||
{
|
||||
// Ugly workaround to give SPS/PPS that are get from the RTPSink
|
||||
m_SDPLines.assign(PassiveServerMediaSubsession::sdpLines());
|
||||
m_SDPLines.append(getAuxSDPLine(m_rtpSink,NULL));
|
||||
}
|
||||
return m_SDPLines.c_str();
|
||||
}
|
||||
|
||||
char const* MulticastServerMediaSubsession::getAuxSDPLine(RTPSink* rtpSink,FramedSource* inputSource)
|
||||
{
|
||||
return this->getAuxLine(dynamic_cast<V4L2DeviceSource*>(m_replicator->inputSource()), rtpSink->rtpPayloadType());
|
||||
}
|
||||
|
||||
// -----------------------------------------
|
||||
// ServerMediaSubsession for Unicast
|
||||
// -----------------------------------------
|
||||
UnicastServerMediaSubsession* UnicastServerMediaSubsession::createNew(UsageEnvironment& env, StreamReplicator* replicator, const std::string& format)
|
||||
{
|
||||
return new UnicastServerMediaSubsession(env,replicator,format);
|
||||
}
|
||||
|
||||
FramedSource* UnicastServerMediaSubsession::createNewStreamSource(unsigned clientSessionId, unsigned& estBitrate)
|
||||
{
|
||||
FramedSource* source = m_replicator->createStreamReplica();
|
||||
return createSource(envir(), source, m_format);
|
||||
}
|
||||
|
||||
RTPSink* UnicastServerMediaSubsession::createNewRTPSink(Groupsock* rtpGroupsock, unsigned char rtpPayloadTypeIfDynamic, FramedSource* inputSource)
|
||||
{
|
||||
return createSink(envir(), rtpGroupsock, rtpPayloadTypeIfDynamic, m_format);
|
||||
}
|
||||
|
||||
char const* UnicastServerMediaSubsession::getAuxSDPLine(RTPSink* rtpSink,FramedSource* inputSource)
|
||||
{
|
||||
return this->getAuxLine(dynamic_cast<V4L2DeviceSource*>(m_replicator->inputSource()), rtpSink->rtpPayloadType());
|
||||
}
|
||||
|
||||
|
37
src/UnicastServerMediaSubsession.cpp
Normal file
37
src/UnicastServerMediaSubsession.cpp
Normal file
@ -0,0 +1,37 @@
|
||||
/* ---------------------------------------------------------------------------
|
||||
** This software is in the public domain, furnished "as is", without technical
|
||||
** support, and with no warranty, express or implied, as to its usefulness for
|
||||
** any purpose.
|
||||
**
|
||||
** ServerMediaSubsession.cpp
|
||||
**
|
||||
** -------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
#include "UnicastServerMediaSubsession.h"
|
||||
#include "DeviceSource.h"
|
||||
|
||||
// -----------------------------------------
|
||||
// ServerMediaSubsession for Unicast
|
||||
// -----------------------------------------
|
||||
UnicastServerMediaSubsession* UnicastServerMediaSubsession::createNew(UsageEnvironment& env, StreamReplicator* replicator, const std::string& format)
|
||||
{
|
||||
return new UnicastServerMediaSubsession(env,replicator,format);
|
||||
}
|
||||
|
||||
FramedSource* UnicastServerMediaSubsession::createNewStreamSource(unsigned clientSessionId, unsigned& estBitrate)
|
||||
{
|
||||
FramedSource* source = m_replicator->createStreamReplica();
|
||||
return createSource(envir(), source, m_format);
|
||||
}
|
||||
|
||||
RTPSink* UnicastServerMediaSubsession::createNewRTPSink(Groupsock* rtpGroupsock, unsigned char rtpPayloadTypeIfDynamic, FramedSource* inputSource)
|
||||
{
|
||||
return createSink(envir(), rtpGroupsock, rtpPayloadTypeIfDynamic, m_format);
|
||||
}
|
||||
|
||||
char const* UnicastServerMediaSubsession::getAuxSDPLine(RTPSink* rtpSink,FramedSource* inputSource)
|
||||
{
|
||||
return this->getAuxLine(dynamic_cast<V4L2DeviceSource*>(m_replicator->inputSource()), rtpSink->rtpPayloadType());
|
||||
}
|
||||
|
@ -37,6 +37,9 @@
|
||||
|
||||
#include "H264_V4l2DeviceSource.h"
|
||||
#include "ServerMediaSubsession.h"
|
||||
#include "UnicastServerMediaSubsession.h"
|
||||
#include "MulticastServerMediaSubsession.h"
|
||||
#include "SegmentServerMediaSubsession.h"
|
||||
#include "HTTPServer.h"
|
||||
|
||||
#ifdef HAVE_ALSA
|
||||
|
Loading…
Reference in New Issue
Block a user