org.red5.server.net.rtmp.message.Header Java Examples
The following examples show how to use
org.red5.server.net.rtmp.message.Header.
You can vote up the ones you like or vote down the ones you don't like,
and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: RTMPTClientTest.java From red5-client with Apache License 2.0 | 6 votes |
@SuppressWarnings("unchecked") protected void onCommand(RTMPConnection conn, Channel channel, Header header, Notify notify) { super.onCommand(conn, channel, header, notify); System.out.println("onInvoke, header = " + header.toString()); System.out.println("onInvoke, notify = " + notify.toString()); Object obj = notify.getCall().getArguments().length > 0 ? notify.getCall().getArguments()[0] : null; if (obj instanceof Map) { Map<String, String> map = (Map<String, String>) obj; String code = map.get("code"); if (StatusCodes.NS_PLAY_STOP.equals(code)) { synchronized (RTMPTClientTest.class) { finished = true; RTMPTClientTest.class.notifyAll(); } disconnect(); System.out.println("Disconnected"); } } }
Example #2
Source File: RTMPTSClientTest.java From red5-client with Apache License 2.0 | 6 votes |
@SuppressWarnings("unchecked") protected void onCommand(RTMPConnection conn, Channel channel, Header header, Notify notify) { super.onCommand(conn, channel, header, notify); System.out.println("onInvoke, header = " + header.toString()); System.out.println("onInvoke, notify = " + notify.toString()); Object obj = notify.getCall().getArguments().length > 0 ? notify.getCall().getArguments()[0] : null; if (obj instanceof Map) { Map<String, String> map = (Map<String, String>) obj; String code = map.get("code"); if (StatusCodes.NS_PLAY_STOP.equals(code)) { synchronized (RTMPTSClientTest.class) { finished = true; RTMPTSClientTest.class.notifyAll(); } disconnect(); System.out.println("Disconnected"); } } }
Example #3
Source File: BaseRTMPClientHandler.java From red5-client with Apache License 2.0 | 6 votes |
/** {@inheritDoc} */ @Override protected void onSharedObject(RTMPConnection conn, Channel channel, Header source, SharedObjectMessage object) { log.trace("onSharedObject"); ClientSharedObject so = sharedObjects.get(object.getName()); if (so != null) { if (so.isPersistent() == object.isPersistent()) { log.debug("Received SO request: {}", object); so.dispatchEvent(object); } else { log.error("Ignoring request for wrong-persistent SO: {}", object); } } else { log.error("Ignoring request for non-existend SO: {}", object); } }
Example #4
Source File: Channel.java From red5-server-common with Apache License 2.0 | 6 votes |
/** * Writes packet from event data to RTMP connection and stream id. * * @param event * Event data * @param streamId * Stream id */ private void write(IRTMPEvent event, Number streamId) { log.trace("write to stream id: {} channel: {}", streamId, id); final Header header = new Header(); final Packet packet = new Packet(header, event); // set the channel id header.setChannelId(id); int ts = event.getTimestamp(); if (ts != 0) { header.setTimer(event.getTimestamp()); } header.setStreamId(streamId); header.setDataType(event.getDataType()); // should use RTMPConnection specific method.. //log.trace("Connection type for write: {}", connection.getClass().getName()); connection.write(packet); }
Example #5
Source File: RTMPProtocolEncoder.java From red5-server-common with Apache License 2.0 | 6 votes |
/** * Determine type of header to use. * * @param header RTMP message header * @param lastHeader Previous header * @return Header type to use */ private byte getHeaderType(final Header header, final Header lastHeader) { //int lastFullTs = ((RTMPConnection) Red5.getConnectionLocal()).getState().getLastFullTimestampWritten(header.getChannelId()); if (lastHeader == null || header.getStreamId() != lastHeader.getStreamId() || header.getTimer() < lastHeader.getTimer()) { // new header mark if header for another stream return HEADER_NEW; } else if (header.getSize() != lastHeader.getSize() || header.getDataType() != lastHeader.getDataType()) { // same source header if last header data type or size differ return HEADER_SAME_SOURCE; } else if (header.getTimer() != lastHeader.getTimer()) { // timer change marker if there's time gap between header time stamps return HEADER_TIMER_CHANGE; } // continue encoding return HEADER_CONTINUE; }
Example #6
Source File: AxisTest.java From red5-rtsp-restreamer with Apache License 2.0 | 5 votes |
public IRTMPEvent getAVCDecoderConfig() { IoBuffer buffV = IoBuffer.allocate(_pCodecSetup.length); buffV.setAutoExpand(true); for (int p = 0; p < _pCodecSetup.length; p++) buffV.put((byte) _pCodecSetup[p]); buffV.flip(); buffV.position(0); IRTMPEvent video = new VideoData(buffV); video.setHeader(new Header()); return video; }
Example #7
Source File: ClientBroadcastStream.java From red5-server-common with Apache License 2.0 | 5 votes |
/** * Notifies handler on stream broadcast start */ private void notifyBroadcastStart() { IStreamAwareScopeHandler handler = getStreamAwareHandler(); if (handler != null) { try { handler.streamBroadcastStart(this); } catch (Throwable t) { log.error("Error in notifyBroadcastStart", t); } } // send metadata for creation and start dates IoBuffer buf = IoBuffer.allocate(256); buf.setAutoExpand(true); Output out = new Output(buf); out.writeString("onMetaData"); Map<Object, Object> params = new HashMap<>(); Calendar cal = GregorianCalendar.getInstance(); cal.setTimeInMillis(creationTime); params.put("creationdate", ZonedDateTime.ofInstant(cal.toInstant(), ZoneId.of("UTC")).format(DateTimeFormatter.ISO_INSTANT)); cal.setTimeInMillis(startTime); params.put("startdate", ZonedDateTime.ofInstant(cal.toInstant(), ZoneId.of("UTC")).format(DateTimeFormatter.ISO_INSTANT)); if (log.isDebugEnabled()) { log.debug("Params: {}", params); } out.writeMap(params); buf.flip(); Notify notify = new Notify(buf); notify.setAction("onMetaData"); notify.setHeader(new Header()); notify.getHeader().setDataType(Notify.TYPE_STREAM_METADATA); notify.getHeader().setStreamId(0); notify.setTimestamp(0); dispatchEvent(notify); }
Example #8
Source File: RTMPHandler.java From red5-server-common with Apache License 2.0 | 5 votes |
/** {@inheritDoc} */ @Override protected void onChunkSize(RTMPConnection conn, Channel channel, Header source, ChunkSize chunkSize) { int requestedChunkSize = chunkSize.getSize(); log.debug("Chunk size: {}", requestedChunkSize); // set chunk size on the connection RTMP state = conn.getState(); // set only the read chunk size since it came from the client state.setReadChunkSize(requestedChunkSize); //state.setWriteChunkSize(requestedChunkSize); // set on each of the streams for (IClientStream stream : conn.getStreams()) { if (stream instanceof IClientBroadcastStream) { IClientBroadcastStream bs = (IClientBroadcastStream) stream; IBroadcastScope scope = bs.getScope().getBroadcastScope(bs.getPublishedName()); if (scope == null) { continue; } OOBControlMessage setChunkSize = new OOBControlMessage(); setChunkSize.setTarget("ClientBroadcastStream"); setChunkSize.setServiceName("chunkSize"); if (setChunkSize.getServiceParamMap() == null) { setChunkSize.setServiceParamMap(new HashMap<String, Object>()); } setChunkSize.getServiceParamMap().put("chunkSize", requestedChunkSize); scope.sendOOBControlMessage((IConsumer) null, setChunkSize); log.debug("Sending chunksize {} to {}", chunkSize, bs.getProvider()); } } }
Example #9
Source File: RTMPHandler.java From red5-server-common with Apache License 2.0 | 5 votes |
/** {@inheritDoc} */ @Override protected void onPing(RTMPConnection conn, Channel channel, Header source, Ping ping) { switch (ping.getEventType()) { case Ping.CLIENT_BUFFER: SetBuffer setBuffer = (SetBuffer) ping; // get the stream id int streamId = setBuffer.getStreamId(); // get requested buffer size in milliseconds int buffer = setBuffer.getBufferLength(); log.debug("Client sent a buffer size: {} ms for stream id: {}", buffer, streamId); IClientStream stream = null; if (streamId != 0) { // The client wants to set the buffer time stream = conn.getStreamById(streamId); if (stream != null) { stream.setClientBufferDuration(buffer); log.trace("Stream type: {}", stream.getClass().getName()); } } //catch-all to make sure buffer size is set if (stream == null) { // Remember buffer time until stream is created conn.rememberStreamBufferDuration(streamId, buffer); log.debug("Remembering client buffer on stream: {}", buffer); } break; case Ping.PONG_SERVER: // This is the response to an IConnection.ping request conn.pingReceived(ping); break; default: log.warn("Unhandled ping: {}", ping); } }
Example #10
Source File: RTMPProtocolEncoder.java From red5-server-common with Apache License 2.0 | 5 votes |
/** * Calculate number of bytes necessary to encode the header. * * @param header * RTMP message header * @param lastHeader * Previous header * @return Calculated size */ private int calculateHeaderSize(final Header header, final Header lastHeader) { final byte headerType = getHeaderType(header, lastHeader); int channelIdAdd = 0; int channelId = header.getChannelId(); if (channelId > 320) { channelIdAdd = 2; } else if (channelId > 63) { channelIdAdd = 1; } return RTMPUtils.getHeaderLength(headerType) + channelIdAdd; }
Example #11
Source File: BaseRTMPClientHandler.java From red5-client with Apache License 2.0 | 5 votes |
/** {@inheritDoc} */ @Override protected void onChunkSize(RTMPConnection conn, Channel channel, Header source, ChunkSize chunkSize) { log.debug("onChunkSize"); // set read and write chunk sizes RTMP state = conn.getState(); state.setReadChunkSize(chunkSize.getSize()); state.setWriteChunkSize(chunkSize.getSize()); log.info("ChunkSize is not fully implemented: {}", chunkSize); }
Example #12
Source File: ClientTest.java From red5-client with Apache License 2.0 | 5 votes |
@SuppressWarnings("unchecked") protected void onCommand(RTMPConnection conn, Channel channel, Header header, Notify notify) { super.onCommand(conn, channel, header, notify); System.out.println("onInvoke - header: " + header.toString() + " notify: " + notify.toString()); Object obj = notify.getCall().getArguments().length > 0 ? notify.getCall().getArguments()[0] : null; if (obj instanceof Map) { Map<String, String> map = (Map<String, String>) obj; String code = map.get("code"); if (StatusCodes.NS_PLAY_STOP.equals(code)) { finished = true; disconnect(); System.out.println("Disconnected"); } } }
Example #13
Source File: RTMP.java From red5-server-common with Apache License 2.0 | 4 votes |
/** * @return the writeHeader */ public Header getWriteHeader() { return writeHeader; }
Example #14
Source File: TestRTMPProtocolDecoder.java From red5-server-common with Apache License 2.0 | 4 votes |
@Test public void testDecodeBufferCreateDelete() { log.debug("\ntestDecodeBufferCreateDelete"); RTMPProtocolDecoder dec = new RTMPProtocolDecoder(); List<Object> objs; RTMPConnection conn = new RTMPMinaConnection(); conn.getState().setState(RTMP.STATE_CONNECTED); conn.setHandler(this); for (int i = 0; i < 13; ++i) { conn.getState().setLastReadHeader(i, new Header()); //TODO hardcoded, so test will not fail } int idx = 0; for (IoBuffer p : new IoBuffer[] { // packet #0 // connect // 320 IoBuffer.wrap(IOUtils.hexStringToByteArray("030000000001321400000000020007636f6e6e656374003ff00000000000000300036170700200086f666c614" + "4656d6f0008666c61736856657202000e4c4e582032302c302c302c333036000673776655726c020029687474703a2f2f6c6f63616c686f73743a35303" + "8302f64656d6f732f6f666c615f64656d6f2e7377660005746355726c02001972746dc3703a2f2f6c6f63616c686f73742f6f666c6144656d6f0004667" + "061640100000c6361706162696c697469657300406de00000000000000b617564696f436f646563730040abee0000000000000b766964656f436f64656" + "37300406f800000000000000d766964656f46756e6374696f6e003ff000000000000000077061676555c3726c02002a687474703a2f2f6c6f63616c686" + "f73743a353038302f64656d6f732f6f666c615f64656d6f2e68746d6c000009")) // packet #1 // 16 , IoBuffer.wrap(IOUtils.hexStringToByteArray("02db5565000004050000000000989680")) // packet #2 // 59 , IoBuffer.wrap(IOUtils.hexStringToByteArray("0300017c00002f140000000002002264656d6f536572766963652e6765744c6973744f66417661696c61626" + "c65464c567300400000000000000005")) // packet #3 // 14 , IoBuffer.wrap(IOUtils.hexStringToByteArray("42000000000006040007ce4c5f73")) // packet #4 // 7 , IoBuffer.wrap(IOUtils.hexStringToByteArray("c20007ce4c6743")) // packet #5 // 7 , IoBuffer.wrap(IOUtils.hexStringToByteArray("c20007ce4c6f13")) // packet #6 // 33 , IoBuffer.wrap(IOUtils.hexStringToByteArray("43001e610000191402000c63726561746553747265616d00400800000000000005")) // packet #7 // 18 , IoBuffer.wrap(IOUtils.hexStringToByteArray("4200000000000a0400030000000000001388")) // packet #8 // 52 , IoBuffer.wrap(IOUtils.hexStringToByteArray("08001fdd00001d1401000000020004706c61790000000000000000000502000973706565782e666c76c200030000000100001388")) // packet #9 // huge connect from OpenMeetings , IoBuffer.wrap(IOUtils.hexStringToByteArray("030000000001b71400000000020007636f6e6e656374003ff000000000000003000361707002000e6f70656" + "e6d656574696e67732f350008666c61736856657202000e4c4e582032302c302c302c323836000673776655726c020082687474703a2f2f6c6f63616c6" + "86f73743a353038302f6f70656e6d656574696e67732f7075626c69632f6d61696e6465c36275672e73776631312e7377663f7769636b65747369643d3" + "563333562613330396634393030346139303366323264623663323564393330266c616e67756167653d31267769636b6574726f6f6d69643d350005746" + "355726c02002472746d703a2f2f6c6f63616c686f73743a313933352f6f70656e6d656574696e67732f35c30004667061640100000c6361706162696c6" + "97469657300406de00000000000000b617564696f436f646563730040abee0000000000000b766964656f436f6465637300406f800000000000000d766" + "964656f46756e6374696f6e003ff000000000000000077061676555726c02002a687474703a2f2f6c6f63616c686f73743ac3353038302f6f70656e6d6" + "56574696e67732f23726f6f6d2f35000e6f626a656374456e636f64696e670040080000000000000000090100")), IoBuffer.wrap(IOUtils.hexStringToByteArray("4300120c0000191402000c63726561746553747265616d00400800000000000005")), IoBuffer.wrap(IOUtils.hexStringToByteArray("4200000000000a0400030000000000001388830014d302000c63726561746553747265616d0040100000000" + "0000005430000000000221402000c64656c65746553747265616d00000000000000000005003ff0000000000000")), IoBuffer.wrap(IOUtils.hexStringToByteArray("04007dc400010108010000006a42a5b3b597d08decc518618c31c688880821841022226eaaaaaaaaaafeff" + "ffffffffffffffffffe17384c5790bb1ae48f4812ff082e31ce7381ccecffdfdff7f16a61525c7586c145624279c6d15b8ca145c5b11a396dc1ea405aa" + "eb584a82022a4aab5c0d3ccf732381d8568f05399f98b47eb22b1a714aa116482deab090420000000000040100000101c4e3d6aed29dc420b24cd22897" + "948f0d68c12e16b640bc736918d278b5956c2d44e358010e8ff699b91bd73716ecd70b891b3791263b9d380554dccec61646ad51dd5e9ed429a3a4a2b0" + "51066394111179fbe53f6562f3f461cd49fb1b6b662e79535391f32d29668e3494a211ff442e2de649475ba8e480f6de4ef5b73dff6d3356")), IoBuffer.wrap(IOUtils.hexStringToByteArray("8400002e6a5f2bd5e6b81389f5bcd79c93cf8dc82fcde9abd1af033d756343a53488344bd53c15f9202ac59" + "299268794caa179534a2132b68a1da926f5da1ad3566d43223d99437a65ba4f829395c95c94f11838650cb6169785929758aded8b6da3ac86ba422805e" + "cf6ebfc0ecfa8d37a2fde5f7feaa919b154c9136251a8a4aa09753616608175d6aa9b6995a1b89a8472118833d8a6eab81572fdde05ed5f21364cd97a6" + "a7abc24c6fcef545e2d2553b3152384afd567957b749125404821853a388400a2597955cb538137a5b79eab101599c9e71ad7c5d6db1039a1274771d2c" + "eb2cd95eb8ac9befed41d2a79c34b630afc146979b549eaf9d50d952895f63b56ba504600008e0005010932000084074202becac8c293f8c2c3b658622" + "5827a0342932209024ad6308162a489b0c0336fe9de14fe139c3630dcd66b622a6e0892b6c9673ce3a23ce9f3e7db683bcd42b304e2bc951c296bad8b8" + "2f8d0e8abc3d8d271005414b939d278939dd98396c2906fffc41e6cede4d1138362cc1708f4247c30771f80acc29423a3214f3e478350dd11a6353fd95" + "ae16f4157ed26c0f412c29e347a7e9f6ba6a6a994b262cd7535d3cf13e7f4f4cea6ce4e276c1878257c4ae1567630569ee959f17be28cf26064404905e" + "a16a9db4a4c1633da1cb4d1fa03443cf1d3a9c1b8810a784e74ed3d189363379ec459a1cd27059851e8065a48359a23fd911974c8902087c674e893e90" + "b24977641c286330b314b360d50b3a7c559d70af3a18359d17b413b79d17c7857f80ad25141621a9d3ac946706625e367789865cd02dd9abda5ad36c0b" + "02bed04e90e56d4d5c456f72f43f49c870f05f8094f17f4e8859e40889d7c056030ffc9de4024ca472461a14af4621d3408e702b6b3307214f6215d102" + "b35b38784f982b063a06bb5334c201c8ac5e0ddbf89fc6868d831e02f59a8b23de824852e4b9185d74d0838c9cdde42ce360c740e191a853d9180373fe" + "a5905ca943bd662110c561b31c0c0e0ab380da7fc2a6c262d18a104def5a489af528a9e14f60380c3d9fe48a00adbc48a25db7122e4689071098101861" + "0a318649d6bbb4089c64214068e853d1da031095162e115e167286848c5229a0529675108471b5de14f2b71c3ac92fa0eee340c740b29ab460982b74f0" + "d81907fc3209224c42c3220712ad9594ed3a08b5bd1b96f5a17085be34229640bb4a5c046b69aeaec8124a3510b0e148e61e01c0b890a732a6ade87c78" + "4fa30f1721063ffc5d8573a9f1b1c8984d84b296365952241988f045702b8d226c43582a6f943867bd5d869a7254fc8902e0a7f74f66a509f172ae9684" + "a0c83f9b85291b88915150ac29e1c62288cd0e34725a889f288488d0369ff91a0fec4fbc5ae74682e0a17cc4408c186874d82446f596b66b170118e233" + "614f1069ec2160d9625312cdda23a602790a22152f301c64fa45ccc60c27c04d1ba240543511d2b6df077dc85a88640dd80850fa2c0a18dcd6c0cacd4d" + "88fcd3da04c15fc19b61a0238d443c98a04314c0dc06b2878dacd2c23cea36c02042c15c35480c940f4eb189c3cc4dc1a27ac254fd69a2db187853f899" + "3afca21a7321e09c15a59a95938de276b4840b21e831d02c994e81195f48c29edf4ca764190ff328aae09c21f6825318ce242b061608ff160636046414" + "bb02fb8ce836effd2b1c60ce6d5ef53b1c56d830c05c27c9d606414f0b0ac119e1787220d25b3195dbd68a38d778b1e1d6b5ab022854142db0685f9822" + "6b68da2663538884a300a7a146b1c6162af268051846e8c2b06280832d6be1c8653476048c618582fde872329ee8d029f352ea4e44a1422292a6342ff2" + "b641840306960cffd32c3da0436394c9ad0d8300a796a6ab0b574c6160ddda03c49ff015490d9d0a7f3bbc01fcc304d46e31ffba0c27ea86e8191beac9" + "8dc16053ce26b418e7f150a744602650ea227ab7b15b6052d1760bc29e8da4637c4b0f60dd191e8343050186fe0699fae01dc480d2c27563014f27659e" + "b5630154ad06e19286dff5fa22034c052f18d3214f593616c467b06c2d95a44fc11c088bc14f962903b9d6fb0a1819e1442bc220a7b1437780d061c085" + "b01488dde8dd4ea0b55fbd89076673ba16853fa38601907f7a20f4f45c1a3fe06b7f96a9623efbdd44f06360948c4")) }) { objs = dec.decodeBuffer(conn, p); log.debug("Objects #02: {}", objs); assertFalse("Objects should not be empty", objs.isEmpty()); assertEquals("Buffer should be empty [idx = " + idx++ + "]", p.capacity(), p.remaining()); } }
Example #15
Source File: RTMPHandler.java From red5-server-common with Apache License 2.0 | 4 votes |
/** {@inheritDoc} */ @Override protected void onSharedObject(RTMPConnection conn, Channel channel, Header source, SharedObjectMessage message) { if (log.isDebugEnabled()) { log.debug("onSharedObject - conn: {} channel: {} so message: {}", new Object[] { conn.getSessionId(), channel.getId(), message }); } final IScope scope = conn.getScope(); if (scope != null) { // so name String name = message.getName(); // whether or not the incoming so is persistent boolean persistent = message.isPersistent(); // shared object service ISharedObjectService sharedObjectService = (ISharedObjectService) ScopeUtils.getScopeService(scope, ISharedObjectService.class, SharedObjectService.class, false); if (!sharedObjectService.hasSharedObject(scope, name)) { log.debug("Shared object service doesnt have requested object, creation will be attempted"); ISharedObjectSecurityService security = (ISharedObjectSecurityService) ScopeUtils.getScopeService(scope, ISharedObjectSecurityService.class); if (security != null) { // Check handlers to see if creation is allowed for (ISharedObjectSecurity handler : security.getSharedObjectSecurity()) { if (!handler.isCreationAllowed(scope, name, persistent)) { log.debug("Shared object create failed, creation is not allowed"); sendSOCreationFailed(conn, message); return; } } } if (!sharedObjectService.createSharedObject(scope, name, persistent)) { log.debug("Shared object create failed"); sendSOCreationFailed(conn, message); return; } } ISharedObject so = sharedObjectService.getSharedObject(scope, name); if (so != null) { if (so.isPersistent() == persistent) { log.debug("Dispatch persistent shared object"); so.dispatchEvent(message); } else { log.warn("Shared object persistence mismatch - current: {} incoming: {}", so.isPersistent(), persistent); // reset the object so we can re-use it message.reset(); // add the error event message.addEvent(new SharedObjectEvent(ISharedObjectEvent.Type.CLIENT_STATUS, "error", SO_PERSISTENCE_MISMATCH)); conn.getChannel(3).write(message); } } else { log.warn("Shared object lookup returned null for {} in {}", name, scope.getName()); // reset the object so we can re-use it message.reset(); // add the error event message.addEvent(new SharedObjectEvent(ISharedObjectEvent.Type.CLIENT_STATUS, "error", NC_CALL_FAILED)); conn.getChannel(3).write(message); } } else { // The scope already has been deleted log.debug("Shared object scope was not found"); sendSOCreationFailed(conn, message); } }
Example #16
Source File: AxisTest.java From red5-rtsp-restreamer with Apache License 2.0 | 4 votes |
private void sendAVCDecoderConfig(int timecode) { IoBuffer buffV = IoBuffer.allocate(_pCodecSetup.length); buffV.setAutoExpand(true); for (int p = 0; p < _pCodecSetup.length; p++) buffV.put((byte) _pCodecSetup[p]); buffV.flip(); buffV.position(0); IRTMPEvent video = new VideoData(buffV); video.setTimestamp(timecode); video.setHeader(new Header()); if (output != null) output.dispatchEvent(video); }
Example #17
Source File: BaseRTMPClientHandler.java From red5-client with Apache License 2.0 | 4 votes |
/** {@inheritDoc} */ @Override protected void onPing(RTMPConnection conn, Channel channel, Header source, Ping ping) { log.trace("onPing"); switch (ping.getEventType()) { case Ping.PING_CLIENT: case Ping.STREAM_BEGIN: case Ping.RECORDED_STREAM: case Ping.STREAM_PLAYBUFFER_CLEAR: // the server wants to measure the RTT Ping pong = new Ping(); pong.setEventType(Ping.PONG_SERVER); pong.setValue2((int) (System.currentTimeMillis() & 0xffffffff)); conn.ping(pong); break; case Ping.STREAM_DRY: log.debug("Stream indicates there is no data available"); break; case Ping.CLIENT_BUFFER: // set the client buffer IClientStream stream = null; // get the stream id Number streamId = ping.getValue2(); // get requested buffer size in milliseconds int buffer = ping.getValue3(); log.debug("Client sent a buffer size: {} ms for stream id: {}", buffer, streamId); // the client wants to set the buffer time stream = conn.getStreamById(streamId); if (stream != null) { stream.setClientBufferDuration(buffer); log.info("Setting client buffer on stream: {}", buffer); } // catch-all to make sure buffer size is set if (stream == null) { // remember buffer time until stream is created conn.rememberStreamBufferDuration(streamId.intValue(), buffer); log.info("Remembering client buffer on stream: {}", buffer); } break; case Ping.PING_SWF_VERIFY: log.debug("SWF verification ping"); // TODO get the swf verification bytes from the handshake SWFResponse swfPong = new SWFResponse(new byte[42]); conn.ping(swfPong); break; case Ping.BUFFER_EMPTY: log.debug("Buffer empty ping"); break; case Ping.BUFFER_FULL: log.debug("Buffer full ping"); break; default: log.warn("Unhandled ping: {}", ping); } }
Example #18
Source File: BaseRTMPHandler.java From red5-server-common with Apache License 2.0 | 4 votes |
/** {@inheritDoc} */ public void messageReceived(RTMPConnection conn, Packet packet) throws Exception { log.trace("messageReceived connection: {}", conn.getSessionId()); if (conn != null) { IRTMPEvent message = null; try { message = packet.getMessage(); final Header header = packet.getHeader(); final Number streamId = header.getStreamId(); final Channel channel = conn.getChannel(header.getChannelId()); final IClientStream stream = conn.getStreamById(streamId); if (log.isTraceEnabled()) { log.trace("Message received - header: {}", header); } // set stream id on the connection conn.setStreamId(streamId); // increase number of received messages conn.messageReceived(); // set the source of the message message.setSource(conn); // process based on data type final byte headerDataType = header.getDataType(); if (log.isTraceEnabled()) { log.trace("Header / message data type: {}", headerDataType); } switch (headerDataType) { case TYPE_AGGREGATE: log.debug("Aggregate type data - header timer: {} size: {}", header.getTimer(), header.getSize()); case TYPE_AUDIO_DATA: case TYPE_VIDEO_DATA: // mark the event as from a live source // log.trace("Marking message as originating from a Live source"); message.setSourceType(Constants.SOURCE_TYPE_LIVE); // NOTE: If we respond to "publish" with "NetStream.Publish.BadName", // the client sends a few stream packets before stopping. We need to ignore them if (stream != null) { ((IEventDispatcher) stream).dispatchEvent(message); } break; case TYPE_FLEX_SHARED_OBJECT: case TYPE_SHARED_OBJECT: onSharedObject(conn, channel, header, (SharedObjectMessage) message); break; case TYPE_INVOKE: case TYPE_FLEX_MESSAGE: onCommand(conn, channel, header, (Invoke) message); IPendingServiceCall call = ((Invoke) message).getCall(); if (message.getHeader().getStreamId().intValue() != 0 && call.getServiceName() == null && StreamAction.PUBLISH.equals(call.getServiceMethodName())) { if (stream != null) { // Only dispatch if stream really was created ((IEventDispatcher) stream).dispatchEvent(message); } } break; case TYPE_NOTIFY: // like an invoke, but does not return anything and has a invoke / transaction id of 0 case TYPE_FLEX_STREAM_SEND: if (((Notify) message).getData() != null && stream != null) { // Stream metadata ((IEventDispatcher) stream).dispatchEvent(message); } else { onCommand(conn, channel, header, (Notify) message); } break; case TYPE_PING: onPing(conn, channel, header, (Ping) message); break; case TYPE_BYTES_READ: onStreamBytesRead(conn, channel, header, (BytesRead) message); break; case TYPE_CHUNK_SIZE: onChunkSize(conn, channel, header, (ChunkSize) message); break; case Constants.TYPE_CLIENT_BANDWIDTH: // onBWDone / peer bw log.debug("Client bandwidth: {}", message); onClientBandwidth(conn, channel, (ClientBW) message); break; case Constants.TYPE_SERVER_BANDWIDTH: // window ack size log.debug("Server bandwidth: {}", message); onServerBandwidth(conn, channel, (ServerBW) message); break; default: log.debug("Unknown type: {}", header.getDataType()); } if (message instanceof Unknown) { log.info("Message type unknown: {}", message); } } catch (Throwable t) { log.error("Exception", t); } // XXX this may be causing 'missing' data if previous methods are not making copies before buffering etc.. if (message != null) { message.release(); } } }
Example #19
Source File: RTMP.java From red5-server-common with Apache License 2.0 | 4 votes |
/** * @return the readPacketHeader */ public Header getReadPacketHeader() { return readPacketHeader; }
Example #20
Source File: RTMP.java From red5-server-common with Apache License 2.0 | 4 votes |
/** * @return the readHeader */ public Header getReadHeader() { return readHeader; }
Example #21
Source File: RTMPConnection.java From red5-server-common with Apache License 2.0 | 4 votes |
private String getMessageType(Packet packet) { final Header header = packet.getHeader(); final byte headerDataType = header.getDataType(); return messageTypeToName(headerDataType); }
Example #22
Source File: Aggregate.java From red5-server-common with Apache License 2.0 | 4 votes |
/** * Breaks-up the aggregate into its individual parts and returns them as a list. The parts are returned based on the ordering of the aggregate itself. * * @return list of IRTMPEvent objects */ public LinkedList<IRTMPEvent> getParts() { LinkedList<IRTMPEvent> parts = new LinkedList<IRTMPEvent>(); log.trace("Aggregate data length: {}", data.limit()); int position = data.position(); do { try { // read the header //log.trace("Hex: {}", data.getHexDump()); byte subType = data.get(); // when we run into subtype 0 break out of here if (subType == 0) { log.debug("Subtype 0 encountered within this aggregate, processing with exit"); break; } int size = IOUtils.readUnsignedMediumInt(data); log.debug("Data subtype: {} size: {}", subType, size); // TODO ensure the data contains all the bytes to support the specified size int timestamp = IOUtils.readExtendedMediumInt(data); /* timestamp = ntohap((GETIBPOINTER(buffer) + 4)); 0x12345678 == 34 56 78 12 */ int streamId = IOUtils.readUnsignedMediumInt(data); log.debug("Data timestamp: {} stream id: {}", timestamp, streamId); Header partHeader = new Header(); partHeader.setChannelId(header.getChannelId()); partHeader.setDataType(subType); partHeader.setSize(size); // use the stream id from the aggregate's header partHeader.setStreamId(header.getStreamId()); partHeader.setTimer(timestamp); // timer delta == time stamp - timer base // the back pointer may be used to verify the size of the individual part // it will be equal to the data size + header size int backPointer = 0; switch (subType) { case TYPE_AUDIO_DATA: AudioData audio = new AudioData(data.getSlice(size)); audio.setTimestamp(timestamp); audio.setHeader(partHeader); log.debug("Audio header: {}", audio.getHeader()); parts.add(audio); //log.trace("Hex: {}", data.getHexDump()); // ensure 4 bytes left to read an int if (data.position() < data.limit() - 4) { backPointer = data.getInt(); //log.trace("Back pointer: {}", backPointer); if (backPointer != (size + 11)) { log.debug("Data size ({}) and back pointer ({}) did not match", size, backPointer); } } break; case TYPE_VIDEO_DATA: VideoData video = new VideoData(data.getSlice(size)); video.setTimestamp(timestamp); video.setHeader(partHeader); log.debug("Video header: {}", video.getHeader()); parts.add(video); //log.trace("Hex: {}", data.getHexDump()); // ensure 4 bytes left to read an int if (data.position() < data.limit() - 4) { backPointer = data.getInt(); //log.trace("Back pointer: {}", backPointer); if (backPointer != (size + 11)) { log.debug("Data size ({}) and back pointer ({}) did not match", size, backPointer); } } break; default: log.debug("Non-A/V subtype: {}", subType); Unknown unk = new Unknown(subType, data.getSlice(size)); unk.setTimestamp(timestamp); unk.setHeader(partHeader); parts.add(unk); // ensure 4 bytes left to read an int if (data.position() < data.limit() - 4) { backPointer = data.getInt(); } } position = data.position(); } catch (Exception e) { log.error("Exception decoding aggregate parts", e); break; } log.trace("Data position: {}", position); } while (position < data.limit()); log.trace("Aggregate processing complete, {} parts extracted", parts.size()); return parts; }
Example #23
Source File: BaseEvent.java From red5-server-common with Apache License 2.0 | 4 votes |
/** {@inheritDoc} */ public Header getHeader() { return header; }
Example #24
Source File: BaseEvent.java From red5-server-common with Apache License 2.0 | 4 votes |
/** {@inheritDoc} */ public void setHeader(Header header) { this.header = header; }
Example #25
Source File: RTMPProtocolEncoder.java From red5-server-common with Apache License 2.0 | 4 votes |
/** * Encode packet. * * @param packet * RTMP packet * @return Encoded data */ public IoBuffer encodePacket(Packet packet) { IoBuffer out = null; Header header = packet.getHeader(); int channelId = header.getChannelId(); //log.trace("Channel id: {}", channelId); IRTMPEvent message = packet.getMessage(); if (message instanceof ChunkSize) { ChunkSize chunkSizeMsg = (ChunkSize) message; ((RTMPConnection) Red5.getConnectionLocal()).getState().setWriteChunkSize(chunkSizeMsg.getSize()); } // normally the message is expected not to be dropped if (!dropMessage(channelId, message)) { //log.trace("Header time: {} message timestamp: {}", header.getTimer(), message.getTimestamp()); IoBuffer data = encodeMessage(header, message); if (data != null) { RTMP rtmp = ((RTMPConnection) Red5.getConnectionLocal()).getState(); // set last write packet rtmp.setLastWritePacket(channelId, packet); // ensure we're at the beginning if (data.position() != 0) { data.flip(); } else { data.rewind(); } // length of the data to be chunked int dataLen = data.limit(); header.setSize(dataLen); //if (log.isTraceEnabled()) { //log.trace("Message: {}", data); //} // chunk size for writing int chunkSize = rtmp.getWriteChunkSize(); // number of chunks to write int numChunks = (int) Math.ceil(dataLen / (float) chunkSize); // get last header Header lastHeader = rtmp.getLastWriteHeader(channelId); if (log.isTraceEnabled()) { log.trace("Channel id: {} chunkSize: {}", channelId, chunkSize); } // attempt to properly guess the size of the buffer we'll need int bufSize = dataLen + 18 + (numChunks * 2); //log.trace("Allocated buffer size: {}", bufSize); out = IoBuffer.allocate(bufSize, false); out.setAutoExpand(true); do { // encode the header encodeHeader(header, lastHeader, out); // write a chunk byte[] buf = new byte[Math.min(chunkSize, data.remaining())]; data.get(buf); //log.trace("Buffer: {}", Hex.encodeHexString(buf)); out.put(buf); // move header over to last header lastHeader = header.clone(); } while (data.hasRemaining()); // collapse the time stamps on the last header after decode is complete lastHeader.setTimerBase(lastHeader.getTimer()); // clear the delta lastHeader.setTimerDelta(0); // set last write header rtmp.setLastWriteHeader(channelId, lastHeader); data.free(); out.flip(); data = null; } } message.release(); return out; }
Example #26
Source File: RTMPProtocolEncoder.java From red5-server-common with Apache License 2.0 | 4 votes |
/** * Encode RTMP header into given IoBuffer. * * @param header RTMP message header * @param lastHeader Previous header * @param buf Buffer for writing encoded header into */ public void encodeHeader(Header header, Header lastHeader, IoBuffer buf) { byte headerType = getHeaderType(header, lastHeader); RTMPUtils.encodeHeaderByte(buf, headerType, header.getChannelId()); if (log.isTraceEnabled()) { log.trace("{} lastHeader: {}", Header.HeaderType.values()[headerType], lastHeader); } /* * Timestamps in RTMP are given as an integer number of milliseconds relative to an unspecified epoch. Typically, each stream will start with a timestamp of 0, but this is not * required, as long as the two endpoints agree on the epoch. Note that this means that any synchronization across multiple streams (especially from separate hosts) requires some * additional mechanism outside of RTMP. Because timestamps are 32 bits long, they roll over every 49 days, 17 hours, 2 minutes and 47.296 seconds. Because streams are allowed to * run continuously, potentially for years on end, an RTMP application SHOULD use serial number arithmetic [RFC1982] when processing timestamps, and SHOULD be capable of handling * wraparound. For example, an application assumes that all adjacent timestamps are within 2^31 - 1 milliseconds of each other, so 10000 comes after 4000000000, and 3000000000 * comes before 4000000000. Timestamp deltas are also specified as an unsigned integer number of milliseconds, relative to the previous timestamp. Timestamp deltas may be either 24 * or 32 bits long. */ int timeBase = 0, timeDelta = 0; int headerSize = header.getSize(); // encode the message header section switch (headerType) { case HEADER_NEW: // type 0 - 11 bytes timeBase = header.getTimerBase(); // absolute time - unsigned 24-bit (3 bytes) (chop at max 24bit time) RTMPUtils.writeMediumInt(buf, Math.min(timeBase, MEDIUM_INT_MAX)); // header size 24-bit (3 bytes) RTMPUtils.writeMediumInt(buf, headerSize); // 1 byte buf.put(header.getDataType()); // little endian 4 bytes RTMPUtils.writeReverseInt(buf, header.getStreamId().intValue()); header.setTimerDelta(timeDelta); // write the extended timestamp if we are indicated to do so if (timeBase >= MEDIUM_INT_MAX) { buf.putInt(timeBase); header.setExtended(true); } RTMPConnection conn = (RTMPConnection) Red5.getConnectionLocal(); if (conn != null) { conn.getState().setLastFullTimestampWritten(header.getChannelId(), timeBase); } break; case HEADER_SAME_SOURCE: // type 1 - 7 bytes // delta type timeDelta = (int) RTMPUtils.diffTimestamps(header.getTimer(), lastHeader.getTimer()); header.setTimerDelta(timeDelta); // write the time delta 24-bit 3 bytes RTMPUtils.writeMediumInt(buf, Math.min(timeDelta, MEDIUM_INT_MAX)); // write header size RTMPUtils.writeMediumInt(buf, headerSize); buf.put(header.getDataType()); // write the extended timestamp if we are indicated to do so if (timeDelta >= MEDIUM_INT_MAX) { buf.putInt(timeDelta); header.setExtended(true); } // time base is from last header minus delta timeBase = header.getTimerBase() - timeDelta; header.setTimerBase(timeBase); break; case HEADER_TIMER_CHANGE: // type 2 - 3 bytes // delta type timeDelta = (int) RTMPUtils.diffTimestamps(header.getTimer(), lastHeader.getTimer()); header.setTimerDelta(timeDelta); // write the time delta 24-bit 3 bytes RTMPUtils.writeMediumInt(buf, Math.min(timeDelta, MEDIUM_INT_MAX)); // write the extended timestamp if we are indicated to do so if (timeDelta >= MEDIUM_INT_MAX) { buf.putInt(timeDelta); header.setExtended(true); } // time base is from last header minus delta timeBase = header.getTimerBase() - timeDelta; header.setTimerBase(timeBase); break; case HEADER_CONTINUE: // type 3 - 0 bytes // time base from the most recent header timeBase = header.getTimerBase() - timeDelta; // write the extended timestamp if we are indicated to do so if (lastHeader.isExtended()) { buf.putInt(timeBase); } break; default: break; } log.trace("Encoded chunk {} {}", Header.HeaderType.values()[headerType], header); }
Example #27
Source File: RTMPProtocolEncoder.java From red5-server-common with Apache License 2.0 | 4 votes |
/** * Encode message. * * @param header * RTMP message header * @param message * RTMP message (event) * @return Encoded message data */ public IoBuffer encodeMessage(Header header, IRTMPEvent message) { IServiceCall call = null; switch (header.getDataType()) { case TYPE_CHUNK_SIZE: return encodeChunkSize((ChunkSize) message); case TYPE_INVOKE: log.trace("Invoke {}", message); call = ((Invoke) message).getCall(); if (call != null) { log.debug("{}", call.toString()); Object[] args = call.getArguments(); if (args != null && args.length > 0) { Object a0 = args[0]; if (a0 instanceof Status) { Status status = (Status) a0; //code: NetStream.Seek.Notify if (StatusCodes.NS_SEEK_NOTIFY.equals(status.getCode())) { //desc: Seeking 25000 (stream ID: 1). int seekTime = Integer.valueOf(status.getDescription().split(" ")[1]); log.trace("Seek to time: {}", seekTime); // TODO make sure this works on stream ids > 1 //audio and video channels int[] channels = new int[] { 5, 6 }; //if its a seek notification, reset the "mapping" for audio (5) and video (6) RTMP rtmp = ((RTMPConnection) Red5.getConnectionLocal()).getState(); for (int channelId : channels) { LiveTimestampMapping mapping = rtmp.getLastTimestampMapping(channelId); if (mapping != null) { long timestamp = mapping.getClockStartTime() + (seekTime & 0xFFFFFFFFL); log.trace("Setting last stream time to: {}", timestamp); mapping.setLastStreamTime(timestamp); } else { log.trace("No ts mapping for channel id: {}", channelId); } } } } } } return encodeInvoke((Invoke) message); case TYPE_NOTIFY: log.trace("Notify {}", message); call = ((Notify) message).getCall(); if (call == null) { return encodeStreamMetadata((Notify) message); } else { return encodeNotify((Notify) message); } case TYPE_PING: if (message instanceof SetBuffer) { return encodePing((SetBuffer) message); } else if (message instanceof SWFResponse) { return encodePing((SWFResponse) message); } else { return encodePing((Ping) message); } case TYPE_BYTES_READ: return encodeBytesRead((BytesRead) message); case TYPE_AGGREGATE: log.trace("Encode aggregate message"); return encodeAggregate((Aggregate) message); case TYPE_AUDIO_DATA: log.trace("Encode audio message"); return encodeAudioData((AudioData) message); case TYPE_VIDEO_DATA: log.trace("Encode video message"); return encodeVideoData((VideoData) message); case TYPE_FLEX_SHARED_OBJECT: return encodeFlexSharedObject((ISharedObjectMessage) message); case TYPE_SHARED_OBJECT: return encodeSharedObject((ISharedObjectMessage) message); case TYPE_SERVER_BANDWIDTH: return encodeServerBW((ServerBW) message); case TYPE_CLIENT_BANDWIDTH: return encodeClientBW((ClientBW) message); case TYPE_FLEX_MESSAGE: return encodeFlexMessage((FlexMessage) message); case TYPE_FLEX_STREAM_SEND: return encodeFlexStreamSend((FlexStreamSend) message); default: log.warn("Unknown object type: {}", header.getDataType()); } return null; }
Example #28
Source File: RTMPProtocolDecoder.java From red5-server-common with Apache License 2.0 | 4 votes |
/** * Decodes RTMP message event. * * @param conn * RTMP connection * @param header * RTMP header * @param in * Input IoBuffer * @return RTMP event */ public IRTMPEvent decodeMessage(RTMPConnection conn, Header header, IoBuffer in) { IRTMPEvent message; byte dataType = header.getDataType(); switch (dataType) { case TYPE_AUDIO_DATA: message = decodeAudioData(in); message.setSourceType(Constants.SOURCE_TYPE_LIVE); break; case TYPE_VIDEO_DATA: message = decodeVideoData(in); message.setSourceType(Constants.SOURCE_TYPE_LIVE); break; case TYPE_AGGREGATE: message = decodeAggregate(in); break; case TYPE_FLEX_SHARED_OBJECT: // represents an SO in an AMF3 container message = decodeFlexSharedObject(in); break; case TYPE_SHARED_OBJECT: message = decodeSharedObject(in); break; case TYPE_FLEX_MESSAGE: message = decodeFlexMessage(in); break; case TYPE_INVOKE: message = decodeAction(conn.getEncoding(), in, header); break; case TYPE_FLEX_STREAM_SEND: if (log.isTraceEnabled()) { log.trace("Decoding flex stream send on stream id: {}", header.getStreamId()); } // skip first byte in.get(); // decode stream data; slice from the current position message = decodeStreamData(in.slice()); break; case TYPE_NOTIFY: if (log.isTraceEnabled()) { log.trace("Decoding notify on stream id: {}", header.getStreamId()); } if (header.getStreamId().doubleValue() != 0.0d) { message = decodeStreamData(in); } else { message = decodeAction(conn.getEncoding(), in, header); } break; case TYPE_PING: message = decodePing(in); break; case TYPE_BYTES_READ: message = decodeBytesRead(in); break; case TYPE_CHUNK_SIZE: message = decodeChunkSize(in); break; case TYPE_SERVER_BANDWIDTH: message = decodeServerBW(in); break; case TYPE_CLIENT_BANDWIDTH: message = decodeClientBW(in); break; case TYPE_ABORT: message = decodeAbort(in); break; default: log.warn("Unknown object type: {}", dataType); message = decodeUnknown(dataType, in); break; } // add the header to the message message.setHeader(header); return message; }
Example #29
Source File: RTMPProtocolDecoder.java From red5-server-common with Apache License 2.0 | 4 votes |
/** * Decode the 'action' for a supplied an Invoke. * * @param encoding * AMF encoding * @param in * buffer * @param header * data header * @return notify */ private Invoke decodeAction(Encoding encoding, IoBuffer in, Header header) { // for response, the action string and invokeId is always encoded as AMF0 we use the first byte to decide which encoding to use in.mark(); byte tmp = in.get(); in.reset(); Input input; if (encoding == Encoding.AMF3 && tmp == AMF.TYPE_AMF3_OBJECT) { input = new org.red5.io.amf3.Input(in); ((org.red5.io.amf3.Input) input).enforceAMF3(); } else { input = new org.red5.io.amf.Input(in); } // get the action String action = Deserializer.deserialize(input, String.class); if (action == null) { throw new RuntimeException("Action was null"); } if (log.isTraceEnabled()) { log.trace("Action: {}", action); } // instance the invoke Invoke invoke = new Invoke(); // set the transaction id invoke.setTransactionId(readTransactionId(input)); // reset and decode parameters input.reset(); // get / set the parameters if there any Object[] params = in.hasRemaining() ? handleParameters(in, invoke, input) : new Object[0]; // determine service information final int dotIndex = action.lastIndexOf('.'); String serviceName = (dotIndex == -1) ? null : action.substring(0, dotIndex); // pull off the prefixes since java doesn't allow this on a method name if (serviceName != null && (serviceName.startsWith("@") || serviceName.startsWith("|"))) { serviceName = serviceName.substring(1); } String serviceMethod = (dotIndex == -1) ? action : action.substring(dotIndex + 1, action.length()); // pull off the prefixes since java doesnt allow this on a method name if (serviceMethod.startsWith("@") || serviceMethod.startsWith("|")) { serviceMethod = serviceMethod.substring(1); } // create the pending call for invoke PendingCall call = new PendingCall(serviceName, serviceMethod, params); invoke.setCall(call); return invoke; }
Example #30
Source File: RTMP.java From red5-server-common with Apache License 2.0 | 2 votes |
/** * Setter for last read header. * * @param channelId * Channel id * @param header * Header */ public void setLastReadHeader(int channelId, Header header) { getChannelInfo(channelId).setReadHeader(header); }