question: public RtcpPacket parseRtcpPacket ( Packet packet ) { RtcpCompoundPacket compoundPacket = new RtcpCompoundPacket ( packet ) ; Vector < RtcpPacket > subpackets = new Vector < RtcpPacket > ( ) ; DataInputStream in = new DataInputStream ( new ByteArrayInputStream ( compoundPacket . data , compoundPacket . offset , compoundPacket . length ) ) ; try { rtcpSession . updateavgrtcpsize ( compoundPacket . length ) ; int length = 0 ; for ( int offset = 0 ; offset < compoundPacket . length ; offset += length ) { int firstbyte = in . readUnsignedByte ( ) ; if ( ( firstbyte & 0xc0 ) != 128 ) { return null ; } int type = in . readUnsignedByte ( ) ; length = in . readUnsignedShort ( ) ; length = length + 1 << 2 ; int padlen = 0 ; if ( offset + length > compoundPacket . length ) { return null ; } if ( offset + length == compoundPacket . length ) { if ( ( firstbyte & 0x20 ) != 0 ) { padlen = compoundPacket . data [ compoundPacket . offset + compoundPacket . length - 1 ] & 0xff ; if ( padlen == 0 ) { return null ; } } } else if ( ( firstbyte & 0x20 ) != 0 ) { return null ; } int inlength = length - padlen ; firstbyte &= 0x1f ; RtcpPacket subpacket ; switch ( type ) { case RtcpPacket . RTCP_SR : stats . numSrPkts ++ ; if ( inlength != 28 + 24 * firstbyte ) { stats . numMalformedRtcpPkts ++ ; return null ; } RtcpSenderReportPacket srp = new RtcpSenderReportPacket ( compoundPacket ) ; subpacket = srp ; srp . ssrc = in . readInt ( ) ; srp . ntptimestampmsw = ( long ) in . readInt ( ) & 0xffffffffL ; srp . ntptimestamplsw = ( long ) in . readInt ( ) & 0xffffffffL ; srp . rtptimestamp = ( long ) in . readInt ( ) & 0xffffffffL ; srp . packetcount = ( long ) in . readInt ( ) & 0xffffffffL ; srp . octetcount = ( long ) in . readInt ( ) & 0xffffffffL ; srp . reports = new RtcpReport [ firstbyte ] ; RtpSource sourceSR = rtcpSession . getMySource ( ) ; if ( sourceSR != null ) { sourceSR . receivedSenderReport ( srp ) ; } for ( int i = 0 ; i < srp . reports . length ; i ++ ) { RtcpReport report = new RtcpReport ( ) ; srp . reports [ i ] = report ; report . ssrc = in . readInt ( ) ; long val = in . readInt ( ) ; val &= 0xffffffffL ; report . fractionlost = ( int ) ( val > > 24 ) ; report . packetslost = ( int ) ( val & 0xffffffL ) ; report . lastseq = ( long ) in . readInt ( ) & 0xffffffffL ; report . jitter = in . readInt ( ) ; report . lsr = ( long ) in . readInt ( ) & 0xffffffffL ; report . dlsr = ( long ) in . readInt ( ) & 0xffffffffL ; } notifyRtcpListeners ( new RtcpSenderReportEvent ( srp ) ) ; break ; case RtcpPacket . RTCP_RR : if ( inlength != 8 + 24 * firstbyte ) { stats . numMalformedRtcpPkts ++ ; return null ; } RtcpReceiverReportPacket rrp = new RtcpReceiverReportPacket ( compoundPacket ) ; subpacket = rrp ; rrp . ssrc = in . readInt ( ) ; rrp . reports = new RtcpReport [ firstbyte ] ; for ( int i = 0 ; i < rrp . reports . length ; i ++ ) { RtcpReport report = new RtcpReport ( ) ; rrp . reports [ i ] = report ; report . ssrc = in . readInt ( ) ; long val = in . readInt ( ) ; val &= 0xffffffffL ; report . fractionlost = ( int ) ( val > > 24 ) ; report . packetslost = ( int ) ( val & 0xffffffL ) ; report . lastseq = ( long ) in . readInt ( ) & 0xffffffffL ; report . jitter = in . readInt ( ) ; report . lsr = ( long ) in . readInt ( ) & 0xffffffffL ; report . dlsr = ( long ) in . readInt ( ) & 0xffffffffL ; } notifyRtcpListeners ( new RtcpReceiverReportEvent ( rrp ) ) ; break ; case RtcpPacket . RTCP_SDES : RtcpSdesPacket sdesp = new RtcpSdesPacket ( compoundPacket ) ; subpacket = sdesp ; sdesp . sdes = new RtcpSdesBlock [ firstbyte ] ; int sdesoff = 4 ; for ( int i = 0 ; i < sdesp . sdes . length ; i ++ ) { RtcpSdesBlock chunk = new RtcpSdesBlock ( ) ; sdesp . sdes [ i ] = chunk ; chunk . ssrc = in . readInt ( ) ; sdesoff += 5 ; Vector < RtcpSdesItem > items = new Vector < RtcpSdesItem > ( ) ; boolean gotcname = false ; int j ; while ( ( j = in . readUnsignedByte ( ) ) != 0 ) { if ( j < 1 || j > 8 ) { stats . numMalformedRtcpPkts ++ ; return null ; } if ( j == 1 ) { gotcname = true ; } RtcpSdesItem item = new RtcpSdesItem ( ) ; items . addElement ( item ) ; item . type = j ; int sdeslen = in . readUnsignedByte ( ) ; item . data = new byte [ sdeslen ] ; in . readFully ( item . data ) ; sdesoff += 2 + sdeslen ; } if ( ! gotcname ) { stats . numMalformedRtcpPkts ++ ; return null ; } chunk . items = new RtcpSdesItem [ items . size ( ) ] ; items . copyInto ( chunk . items ) ; if ( ( sdesoff & 3 ) != 0 ) { if ( in . skip ( 4 - ( sdesoff & 3 ) ) != 4 - ( sdesoff & 3 ) ) { return null ; } sdesoff = sdesoff + 3 & - 4 ; } } if ( inlength != sdesoff ) { stats . numMalformedRtcpPkts ++ ; return null ; } notifyRtcpListeners ( new RtcpSdesEvent ( sdesp ) ) ; break ; case RtcpPacket . RTCP_BYE : RtcpByePacket byep = new RtcpByePacket ( compoundPacket ) ; subpacket = byep ; byep . ssrc = new int [ firstbyte ] ; for ( int i = 0 ; i < byep . ssrc . length ; i ++ ) { byep . ssrc [ i ] = in . readInt ( ) ; } int reasonlen ; if ( inlength > 4 + 4 * firstbyte ) { reasonlen = in . readUnsignedByte ( ) ; byep . reason = new byte [ reasonlen ] ; reasonlen ++ ; } else { reasonlen = 0 ; byep . reason = new byte [ 0 ] ; } reasonlen = reasonlen + 3 & - 4 ; if ( inlength != 4 + 4 * firstbyte + reasonlen ) { stats . numMalformedRtcpPkts ++ ; return null ; } in . readFully ( byep . reason ) ; int skipBye = reasonlen - byep . reason . length ; if ( in . skip ( skipBye ) != skipBye ) { return null ; } notifyRtcpListeners ( new RtcpByeEvent ( byep ) ) ; break ; case RtcpPacket . RTCP_APP : if ( inlength < 12 ) { return null ; } RtcpAppPacket appp = new RtcpAppPacket ( compoundPacket ) ; subpacket = appp ; appp . ssrc = in . readInt ( ) ; appp . name = in . readInt ( ) ; appp . subtype = firstbyte ; appp . data = new byte [ inlength - 12 ] ; in . readFully ( appp . data ) ; int skipApp = inlength - 12 - appp . data . length ; if ( in . skip ( skipApp ) != skipApp ) { return null ; } notifyRtcpListeners ( new RtcpApplicationEvent ( appp ) ) ; break ; default : stats . numUnknownTypes ++ ; return null ; } subpacket . offset = offset ; subpacket . length = length ; subpackets . addElement ( subpacket ) ; if ( in . skipBytes ( padlen ) != padlen ) { return null ; } } } catch ( Exception e ) { return null ; } compoundPacket . packets = new RtcpPacket [ subpackets . size ( ) ] ; subpackets . copyInto ( compoundPacket . packets ) ; return compoundPacket ; }
target:  Parse the RTCP packet