Wowza Community

Reporting IO Performance to a client that is streaming to the Wowza Server

Hello,

I’m new to Wowza, and our company currently has a trial license. We have a Wowza Server set up using EC2 and the Wowza AMI. We have mobile devices (Android and iOS) that are set up to stream to the server, and I have written some code (using Eclipse and the Wowza IDE) that lets me hook into various methods. For example, I have live-record set up in my Application.xml and I’m using onWriteComplete to publish the file that is persisted to disk to S3, and then POST to our API layer to report the S3 url. Everything in that regard is working well.

We’d like to have something that can report back to the clients (while they are streaming) some IO performance numbers (using the IOPerformanceCounter). The initial thought on this was to have the client call OPTIONS or GET_PARAMETER and set some messages or headers that will contain the information that they need. I have a class set up that implements IRTSPActionNotify so I can hook into onOptions, onGetParameter, etc. which lets me access the IOPerformanceCounter from the RTSP Session (rtspSession.getIOPerformanceCounter()).

Is this the correct/conventional way to do this? If not (or if I’ve overlooked something), what do you recommend?

Below is the current code snippet that adds messages. It seems to work, except that successive OPTIONS requests will cycle through the messages that get printed (the first OPTIONS request prints “bytes_per_second_published_to_server”, the second OPTIONS request prints “bytes_per_second_lost”, the third OPTIONS request prints a generic OPTIONS response, the fourth prints “bytes_per_second_published_to_server” again, etc.)

		@Override
		public void onOptions(RTPSession rtspSession, RTSPRequestMessage req, RTSPResponseMessages resp) {
			/*
			 * fileInBytes              =>    for vod total bytes read from file system
			 * fileInBytesRate          =>    for vod rate of bytes read per-second
			 * messagesInBytes          =>    total bytes published to the server
			 * messagesInBytesRate      =>    bytes per second published to server
			 * messagesLossBytes        =>    total bytes not sent to client due to network congestion
			 * messagesLossBytesRate    =>    byte per second loss
			 * messagesOutBytes         =>    total bytes sent to client
			 * messagesOutBytesRate     =>    byte per second sent to client
			 */
			String sessionId = req.getSessionId();
			int cSequence = req.getCSeq();
			IOPerformanceCounter performanceCounter = rtspSession.getIOPerformanceCounter();
			getLogger().info("Message count at first=" + resp.getMessageCount());  // this prints 0
			addResponseMessage(resp, cSequence, sessionId, "bytes_per_second_published_to_server", String.valueOf(performanceCounter.getMessagesInBytesRate()));
			getLogger().info("Message count after 1 added=" + resp.getMessageCount()); // this prints 1
			addResponseMessage(resp, cSequence, sessionId, "bytes_per_second_lost", String.valueOf(performanceCounter.getMessagesLossBytesRate()));
			getLogger().info("Message count after 2 added=" + resp.getMessageCount()); // this prints 2
			getLogger().info("requestMessage=" + req.toString() + ", responseMessage=" + resp.toString());
		}
                /* my attempt at adding messages to the RTSP response */
		private void addResponseMessage(RTSPResponseMessages resp, int cSequence, String sessionId, String messageMethod, String responseMessage) {
			RTSPResponseMessage rtspResponseMessage = new RTSPResponseMessage();
			rtspResponseMessage.setMethod(messageMethod);
			rtspResponseMessage.setResponseMessage(responseMessage);
			rtspResponseMessage.setResponseCode(200);
			rtspResponseMessage.setSession(sessionId);
			rtspResponseMessage.setCSeq(cSequence);
			resp.addMessage(rtspResponseMessage);
		}

Thank you in advance for any help that you can provide.

Hi,

I haven’t tried this before but from what you are saying, you would most likely have to join all of your messages together into a single string and just send one response only as there can only be one response to a request.

A JSON format would probably be the best and you could then separate them on the client side.

Roger.

Hi Roger,

Thank you very much for your reply. Joining all the messages together as a single JSON response works for us. However, we are still hung up on this “message cycling” behavior. Is it expected behavior for the client to see two messages (both have the same Cseq number), one with the message we added and one “plain” OPTIONS response? It looks something like this:

1st request from client to server:

OPTIONS rtsp://example.com:1935/live/stream-name RTSP/1.0

1st response from server (with the custom message):

RTSP/1.0 200 {“io_performance”:{“bytes_per_second_published_to_server”:0.0,“bytes_per_second_lost”:0.0}}

Cseq: 6

Server: Wowza Streaming Engine 4.0.1 build10615

2nd request from client to server:

OPTIONS rtsp://example.com:1935/live/stream-name RTSP/1.0

2nd response from server (a “standard” OPTIONS response, same Cseq #):

RTSP/1.0 200 OK

Session: 185875607;timeout=60

Supported: play.basic, con.persistent

Cseq: 6

Server: Wowza Streaming Engine 4.0.1 build10615

Public: DESCRIBE, SETUP, TEARDOWN, PLAY, PAUSE, OPTIONS, ANNOUNCE, RECORD, GET_PARAMETER

Cache-Control: no-cache

I’m only adding one RTSPResponseMessage to the RTSPResponseMessages resp object and I put a counter in the onOptions method to show that it’s only getting invoked once every two client OPTIONS requests.