/* ---------------------------------------------------------------------------
** 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"

// -----------------------------------------
//    ServerMediaSubsession for Multicast
// -----------------------------------------
MulticastServerMediaSubsession *MulticastServerMediaSubsession::createNew(UsageEnvironment &env, struct in_addr destinationAddress, Port rtpPortNum, Port rtcpPortNum, int ttl, StreamReplicator *replicator)
{
	return new MulticastServerMediaSubsession(env, destinationAddress, rtpPortNum, rtcpPortNum, ttl, replicator);
}

RTPSink *MulticastServerMediaSubsession::createRtpSink(UsageEnvironment &env, struct in_addr destinationAddress, Port rtpPortNum, Port rtcpPortNum, int ttl, StreamReplicator *replicator)
{
	// Create a source
	FramedSource *source = replicator->createStreamReplica();
	FramedSource *videoSource = createSource(env, source, m_format);

	// Create RTP/RTCP groupsock
#if LIVEMEDIA_LIBRARY_VERSION_INT < 1607644800
	struct in_addr groupAddress = destinationAddress;
#else
	struct sockaddr_storage groupAddress;
	groupAddress.ss_family = AF_INET;
	((struct sockaddr_in &)groupAddress).sin_addr = destinationAddress;
#endif
	Groupsock *rtpGroupsock = new Groupsock(env, groupAddress, rtpPortNum, ttl);

	// Create a RTP sink
	m_rtpSink = createSink(env, rtpGroupsock, 96, m_format, dynamic_cast<V4L2DeviceSource *>(replicator->inputSource()));

	// Create 'RTCP instance'
	const unsigned maxCNAMElen = 100;
	unsigned char CNAME[maxCNAMElen + 1];
	gethostname((char *)CNAME, maxCNAMElen);
	CNAME[maxCNAMElen] = '\0';
	Groupsock *rtcpGroupsock = new Groupsock(env, groupAddress, rtcpPortNum, ttl);
	m_rtcpInstance = RTCPInstance::createNew(env, rtcpGroupsock, 500, CNAME, m_rtpSink, NULL);

	// Start Playing the Sink
	m_rtpSink->startPlaying(*videoSource, NULL, NULL);

	return m_rtpSink;
}

#if LIVEMEDIA_LIBRARY_VERSION_INT < 1610928000
char const *MulticastServerMediaSubsession::sdpLines()
{
	int addressFamily = 0;
#else
char const *MulticastServerMediaSubsession::sdpLines(int addressFamily)
{
#endif
	if (m_SDPLines[addressFamily].empty())
	{
		// Ugly workaround to give SPS/PPS that are get from the RTPSink
#if LIVEMEDIA_LIBRARY_VERSION_INT < 1610928000
		m_SDPLines[addressFamily].assign(PassiveServerMediaSubsession::sdpLines());
#else
		m_SDPLines[addressFamily].assign(PassiveServerMediaSubsession::sdpLines(addressFamily));
#endif
		m_SDPLines[addressFamily].append(getAuxSDPLine(m_rtpSink, NULL));
	}
	return m_SDPLines[addressFamily].c_str();
}

char const *MulticastServerMediaSubsession::getAuxSDPLine(RTPSink *rtpSink, FramedSource *inputSource)
{
	return this->getAuxLine(dynamic_cast<V4L2DeviceSource *>(m_replicator->inputSource()), rtpSink);
}
