EMMA Coverage Report (generated Tue Dec 18 20:38:46 CET 2007)
[all classes][cz.vutbr.feec.session.rtprtcp.internal]

COVERAGE SUMMARY FOR SOURCE FILE [RTPThreadHandler.java]

nameclass, %method, %block, %line, %
RTPThreadHandler.java0%   (0/1)0%   (0/6)0%   (0/388)0%   (0/85)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class RTPThreadHandler0%   (0/1)0%   (0/6)0%   (0/388)0%   (0/85)
<static initializer> 0%   (0/1)0%   (0/5)0%   (0/3)
RTPThreadHandler (Session3550, Socket, int): void 0%   (0/1)0%   (0/31)0%   (0/9)
run (): void 0%   (0/1)0%   (0/162)0%   (0/39)
sendPacket (byte [], int): int 0%   (0/1)0%   (0/8)0%   (0/2)
sendPacket (byte [], int, boolean): int 0%   (0/1)0%   (0/107)0%   (0/21)
validateRTPPacketHeader (byte []): boolean 0%   (0/1)0%   (0/75)0%   (0/11)

1package cz.vutbr.feec.session.rtprtcp.internal;
2 
3import java.net.InetAddress;
4import java.net.UnknownHostException;
5import java.util.Random;
6 
7import org.apache.log4j.Logger;
8 
9import cz.vutbr.feec.packets.PacketGenerateException;
10import cz.vutbr.feec.packets.PacketParseException;
11import cz.vutbr.feec.packets.rtp.RTPPacket;
12import cz.vutbr.feec.session.SessionThread;
13 
14import net.java.dev.jssm.Socket;
15 
16/**
17 * This class encapsulates the functionality to construct and send out RTP
18 * Packets and also to receive RTP Packets. It provides a seperate thread to
19 * receive and send out RTP Packets.
20 */
21 
22public class RTPThreadHandler extends SessionThread {
23        /** The logger. */
24        private static Logger logger = Logger.getLogger(RTPThreadHandler.class
25                        .getName());
26 
27        /** Multicast Socket for sending RTP. */
28        protected Socket socket;
29 
30        /** The destination port. */
31        protected int destPort;
32 
33        /**
34         * Constructs a datagram, assembles it into an RTP packet and sends it out.
35         * @param marker the marker
36         * @param length the length
37         * @param data Payload to be sent out as part of the RTP Packet.
38         * @return  the int
39         */
40        private byte[] sendBuffer = new byte[1500];
41 
42        /** The sequence number of rtp packet. */
43        private long sequence_number; // 16 bits
44 
45        /** The RTP session. */
46        private Session3550 session;
47 
48        /**
49         * Constructor for the class. Takes in a TCP/IP Address and a port number.
50         * It initializes a a new multicast socket according to the multicast
51         * address and the port number given
52         * 
53         * @param rtpPort
54         *            the rtp port
55         * @param multicastSocket
56         *            the multicast socket
57         * @param rtpSession
58         *            the rtp session
59         */
60        public RTPThreadHandler(Session3550 rtpSession, Socket multicastSocket,
61                        int rtpPort) {
62                this.setName("RTP-in/out (R) or (S)");
63                this.session = rtpSession;
64                this.socket = multicastSocket;
65 
66                this.destPort = rtpPort;
67                // socket.setDestinationPort(rtpPort);
68 
69                Random rnd = new Random(); // Use time as default seed
70 
71                // Start with a random sequence number
72                sequence_number = (long) (Math.abs(rnd.nextInt()) & 0x000000FF);
73 
74                // Session3550.outprintln("RTP Session SSRC: "
75                // + Long.toHexString(session.getOwnSource().getSSRC()));
76                // Session3550.outprintln(" Starting Seq: " + sequence_number);
77        }
78 
79        /**
80         * Send packet.
81         * 
82         * @param length
83         *            the length
84         * @param data
85         *            the data
86         * 
87         * @return the int
88         * @throws PacketGenerateException 
89         */
90        public int sendPacket(byte[] data, int length) throws PacketGenerateException {
91                boolean marker = false;
92                return sendPacket(data, length, marker);
93        }
94 
95        public int sendPacket(byte[] data, int length, boolean marker) throws PacketGenerateException {
96                RTPPacket packet = new RTPPacket();
97                packet.setVersion(RTCPConstants.VERSION);
98                packet.setPadding(RTCPConstants.PADDING);
99                packet.setExtension(RTCPConstants.EXTENSION);
100                int m  = marker ? 1 : 0;
101                packet.setMarker(m);
102                packet.setPayloadtype(session.getPayloadType());
103                packet.setSeqNum(sequence_number);
104                packet.setTimeStamp(System.currentTimeMillis());
105                packet.setSSRC(session.getOwnSource().getSSRC());
106                packet.setData(data, 0, data.length);
107                int pktLen = packet.generate(sendBuffer, 0);
108                
109                // invoke event for listeners
110                session.onRTPSent(packet);
111 
112                sequence_number++;
113                session.packetCount++;
114                session.octetCount += data.length;
115                session.getOwnSource().timeOfLastRTPSent = System.currentTimeMillis();
116 
117                logger.debug(" RTP_PKT_LEN:" + pktLen + " RTP_HEADER_LEN:" 
118                                + " PAYLOAD_LEN:"+length);
119                socket.sendTo(sendBuffer, pktLen , destPort);
120 
121                return pktLen;
122        }
123 
124        /**
125         * Starts the RTP Receiver. This method instantiates a multicast socket on
126         * the multicast address and port specified and listens for packets on that
127         * multicast group. When it receives a packet, it parses the packet out and
128         * updates several session and source level statistics. It also posts an
129         * event to the Application about the reception of an RTP Packet
130         */
131 
132        public void run() {
133                byte buf[] = new byte[1024];
134                // DatagramPacket packet = new DatagramPacket(buf, buf.length);
135                int packetLen;
136                long lastTime = System.currentTimeMillis();
137 
138                while (!isStopped()) {
139                        packetLen = socket.receiveFrom(buf);
140                        if (packetLen == -1) {
141                                continue; // repeat - only timeout
142                        }
143 
144                        lastTime = System.currentTimeMillis();
145 
146                        if (validateRTPPacketHeader(buf)) {
147                                
148                                RTPPacket rtppkt = new RTPPacket();
149                                try {
150                                        rtppkt.parse(buf, 0, packetLen);
151                                } catch (PacketParseException e) {
152                                        logger.warn("Packet parsing failed");
153                                        continue;
154                                }
155 
156                                final int RTP_PACKET_HEADER_LENGTH = 12;
157                                final int RTP_PACKET_CSRC_LENGTH = 4 * rtppkt.getCSRCcount();
158                                
159                                // the payload is after the fixed 12 byte header
160                                
161                                // TODO: Neefektivni kod - zlepsit naroky na pamet
162                                byte payload[] = new byte[packetLen - RTP_PACKET_HEADER_LENGTH
163                                                - RTP_PACKET_CSRC_LENGTH];
164 
165                                for (int i = 0; i < payload.length; i++) {
166                                        payload[i] = buf[i + RTP_PACKET_HEADER_LENGTH
167                                                        + RTP_PACKET_CSRC_LENGTH];
168                                        // System.out.print(" "+payload[i]);
169                                }
170 
171                                rtppkt.setData(payload, 0, payload.length);
172 
173                                // Get the source corresponding to this SSRC
174                                Source src = session.getMemberOrCreateMember(rtppkt.getSSRC());
175 
176                                if (rtppkt.getSSRC() != session.getOwnSource().ssrc) { // not me
177 
178                                        long curTime = System.currentTimeMillis();
179 
180                                        // store last received packet
181                                        session.lastRTPPktReceived = rtppkt;
182                                        src.timeOfLastRTPArrival = curTime;
183 
184                                        // actualize max timestamp seen
185                                        if (src.update_seq(rtppkt.getSeqNum(), rtppkt.getTimeStamp())) {
186 
187                                                // if this is the first RTP Packet Received from
188                                                // this source
189                                                // then store the seq no. as its base
190 
191                                                session.onRTPReceive(rtppkt);
192                                                // Source of RTP packet is not yet sender
193                                                if (!src.isSender()) {
194                                                        src.setSender(true);
195                                                        // add saneder to Senders Table
196                                                        session.addSender(rtppkt.getSSRC(), rtppkt.getSeqNum());
197                                                        // call nottifier
198                                                        session.onNewSender(src);
199                                                }
200 
201                                                // AudioPlayer2 player =
202                                                // GuiFactory.getAudioPlayer();
203                                                // player.play(payload, payload.length);
204                                        }
205                                        // else {
206                                        // System.out.println("!!!!!!!!!!!!!!!!! NOT YET
207                                        // VALIDATED"+src.ssrc);
208                                        // }
209                                }
210                        } else {
211                                InetAddress from;
212                                try {
213                                        from = InetAddress.getByAddress(socket.getRemoteAddress());
214                                        logger.warn("Bad RTP Packet received From:" + from + " LEN:"
215                                                        + packetLen);
216//                                        from = InetAddressFactory.newInetAddress(
217//                                                        socket.getRemoteAddress()).toString();
218                                } catch (UnknownHostException e) {
219                                        // ok
220                                }
221                        }
222                        logger.debug("TIME FOR PROCESSING RTP PACKET: "
223                                        + (System.currentTimeMillis() - lastTime));
224                }
225        }
226 
227        /**
228         * Validates RTP Packet. Returns true or false corresponding to the test
229         * results.
230         * 
231         * @param packet
232         *            the packet
233         * 
234         * @return True if validation was successful, False otherwise.
235         */
236 
237        private boolean validateRTPPacketHeader(byte packet[]) {
238                // +-+-+-+-+-+-+-+-+
239                // |V=2|P|X| CC |
240                // +-+-+-+-+-+-+-+-+
241 
242                if (packet.length <= 0) {
243                        logger.warn("packet.length <= 0: " + packet.length);
244                        return false;
245                }
246 
247                // Version MUST be 2
248                if (((packet[0] & 0xC0) >> 6) != 2) {
249                        // VersionValid = false;
250                        logger.warn("RTP version != 2: " + ((packet[0] & 0xC0) >> 6));
251                        return false;
252                }
253 
254                // +-+-+-+-+-+-+-+-+
255                // |M| PT |
256                // +-+-+-+-+-+-+-+-+
257                // 0 1 0 1 1 0 0 0
258 
259                // Payload Type must be the same as the session's
260                if ((packet[1] & 0x7F) != session.getPayloadType()) {
261                        logger.warn("PAYLOAD TYPE != " + session.getPayloadType() + "("
262                                        + (packet[1] & 0x7F) + ")");
263 
264                        return false;
265                }
266                return true;
267        }
268}

[all classes][cz.vutbr.feec.session.rtprtcp.internal]
EMMA 2.0.5312 EclEmma Fix 1 (C) Vladimir Roubtsov