/**
*
*/
package video.clientProxy;
import java.io.IOException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import org.apache.mina.core.buffer.IoBuffer;
import org.apache.mina.core.session.ExpiringSessionRecycler;
import org.apache.mina.core.session.IdleStatus;
import org.apache.mina.core.session.IoSession;
import org.apache.mina.transport.socket.nio.NioDatagramAcceptor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import video.lib.Configuration;
import video.lib.Constants;
import video.lib.OverallStatistic;
import video.lib.RtcpPacket;
import video.lib.RtpPacket;
import video.lib.ServiceInterface;
import video.lib.Statistic;
import video.transport.TransportService;
/**
* @author yuezhu
*
*/
public class RtpClientService implements ServiceInterface {
private static final Logger LOGGER = LoggerFactory.getLogger(RtpClientService.class);
private static TransportService service;
private static NioDatagramAcceptor rtpAcceptor;
private static NioDatagramAcceptor rtcpAcceptor;
private static InetSocketAddress rtpAddress = null;
private static InetSocketAddress rtcpAddress = null;
private static Thread rtpDispatcherThread;
private static Thread rtcpDispatcherThread;
private static boolean running = false;
private static Statistic overallStatistic = new OverallStatistic("client_overall");
public RtpClientService(TransportService transportService) {
service = transportService;
}
public static void setupDatagramConnector() throws IOException {
int rtpPort = Configuration.getInt("client.rtp.port", Constants.CLIENT_RTP_PORT);
int rtcpPort = Configuration.getInt("client.rtcp.port", Constants.CLIENT_RTCP_PORT);
rtpAddress = new InetSocketAddress(rtpPort);
rtpAcceptor = new NioDatagramAcceptor();
rtpAcceptor.setHandler(new ClientRtpPacketHandler());
rtpAcceptor.getSessionConfig().setIdleTime(IdleStatus.BOTH_IDLE, 0);
rtpAcceptor.setSessionRecycler(new ExpiringSessionRecycler(0));
rtpAcceptor.getSessionConfig().setReuseAddress(true);
rtpAcceptor.bind(rtpAddress);
LOGGER.info("RTP client service is listening on " + rtpPort);
rtcpAddress = new InetSocketAddress(rtcpPort);
rtcpAcceptor = new NioDatagramAcceptor();
rtcpAcceptor.setHandler(new ClientRtcpPacketHandler());
rtcpAcceptor.getSessionConfig().setIdleTime(IdleStatus.BOTH_IDLE, 0);
rtcpAcceptor.setSessionRecycler(new ExpiringSessionRecycler(0));
rtcpAcceptor.getSessionConfig().setReuseAddress(true);
rtcpAcceptor.bind(rtcpAddress);
LOGGER.info("RTCP client service is listening on " + rtcpPort);
}
private static RtpPacket recvRtpPacketFromRemote() {
byte[] bytes = null;
try {
bytes = service.getRTPTransportChannel().recv();
} catch (IOException e) {
LOGGER.error("Failed to recv RTP packer via transport service: " + e.toString());
}
return new RtpPacket(IoBuffer.wrap(bytes));
}
private static RtcpPacket recvRtcpPacketFromRemote() {
byte[] bytes = null;
try {
bytes = service.getRTCPTransportChannel().recv();
} catch (IOException e) {
LOGGER.error("Failed to recv RTCP packer via transport service: " + e.toString());
}
return new RtcpPacket(IoBuffer.wrap(bytes));
}
private static void rtpPacketDispatcher() {
RtpPacket packet = recvRtpPacketFromRemote();
overallStatistic.doStatistic(packet);
ClientTrack clientTrack = ClientTrack.getByProxySsrc(packet.getSsrc());
if (clientTrack != null) {
clientTrack.forwardRtpToClient(packet);
}
}
private static void rtcpPacketDispatcher() {
RtcpPacket packet = recvRtcpPacketFromRemote();
ClientTrack clientTrack = ClientTrack.getByProxySsrc(packet.getSsrc());
if (clientTrack != null) {
clientTrack.forwardRtcpToClient(packet);
}
}
@Override
public void start() throws IOException {
running = true;
rtpDispatcherThread = new Thread() {
@Override
public void run() {
while (running) {
rtpPacketDispatcher();
}
}
};
rtcpDispatcherThread = new Thread() {
@Override
public void run() {
while (running) {
rtcpPacketDispatcher();
}
}
};
rtpDispatcherThread.start();
rtcpDispatcherThread.start();
setupDatagramConnector();
overallStatistic.start();
}
@Override
public void stop() throws IOException {
running = false;
}
public static IoSession newRtpSession(SocketAddress remoteAddress) {
IoSession session = rtpAcceptor.newSession(remoteAddress, rtpAddress);
session.getConfig().setIdleTime(IdleStatus.BOTH_IDLE, 0);
return session;
}
public static IoSession newRtcpSession(SocketAddress remoteAddress) {
IoSession session = rtcpAcceptor.newSession(remoteAddress, rtcpAddress);
session.getConfig().setIdleTime(IdleStatus.BOTH_IDLE, 0);
return session;
}
public static InetSocketAddress getRtpAddress() {
return rtpAddress;
}
public static InetSocketAddress getRtcpAddress() {
return rtcpAddress;
}
public static InetAddress getHostAddress() {
/*
* The InetAddress (IP) is the same for both RTP and RTCP.
*/
return rtpAddress.getAddress();
}
public static int getRtpPort() {
return rtpAddress.getPort();
}
public static int getRtcpPort() {
return rtcpAddress.getPort();
}
}