{"id":1249,"date":"2011-01-17T17:24:44","date_gmt":"2011-01-17T14:24:44","guid":{"rendered":"http:\/\/blog.denivip.ru\/?p=1249"},"modified":"2013-08-05T14:12:12","modified_gmt":"2013-08-05T10:12:12","slug":"enabling-quality-of-service-for-online-video","status":"publish","type":"post","link":"http:\/\/blog.denivip.ru\/index.php\/2011\/01\/enabling-quality-of-service-for-online-video\/?lang=en","title":{"rendered":"Enabling Quality of Service for Online Video"},"content":{"rendered":"<p style=\"text-align: center;\"><a href=\"http:\/\/blog.denivip.ru\/wp-content\/uploads\/2010\/12\/online_video_advertising_4.jpg\"><img loading=\"lazy\" decoding=\"async\" class=\"size-full wp-image-840  aligncenter\" title=\"online_video_advertising_4\" src=\"http:\/\/blog.denivip.ru\/wp-content\/uploads\/2010\/12\/online_video_advertising_4.jpg\" alt=\"QoS \u0434\u043b\u044f \u043e\u043d\u043b\u0430\u0439\u043d \u0432\u0438\u0434\u0435\u043e\" width=\"338\" height=\"179\" srcset=\"http:\/\/blog.denivip.ru\/wp-content\/uploads\/2010\/12\/online_video_advertising_4.jpg 338w, http:\/\/blog.denivip.ru\/wp-content\/uploads\/2010\/12\/online_video_advertising_4-300x158.jpg 300w\" sizes=\"(max-width: 338px) 100vw, 338px\" \/><\/a><\/p>\n<p>To enhance the quality of video broadcast online, stream status statistics should be analyzed. To collect statistics, two classes can be used: NetStreamInfo and NetStreamMulticastInfo (for P2P connections).In this article, we will overview these classes and the ways to access them via the OSMF framework, which is all but intuitive. We will cover open source ActionScript 3 lib for sending statistics to Google Analytics with QoS metrics.<!--more--><\/p>\n<p><strong>NetStreamInfo Class<\/strong><br \/>\nThe NetStreamInfo class gives access to Quality of Service (QOS) statistics. The data is fetched from the NetStream object and the audio, video and data streaming buffer used. The NetStreamInfo object is returned on accessing NetStream.info property, making a snapshot of the current QOS status and providing QOS statistics in terms of NetStreamInfo properties.<\/p>\n<p>The NetStreamInfo class has the following statistical properties. They are all read-only and have the Number type:<\/p>\n<ul>\n<li>audioBufferByteLength &#8212; the length of the NetStream audio buffer (in bytes).<\/li>\n<li>audioBufferLength &#8212; the length of the NetStream audio buffer (in seconds).<\/li>\n<li>audioByteCount &#8212; the total count of audio bytes enqueued, whether played back or cleaned data.<\/li>\n<li>audioBytesPerSecond &#8212; the NetStream audio buffer fill rate (bytes per second).<\/li>\n<li>audioLossRate &#8212; sets the level of audio loss for the NetStream session.<\/li>\n<li>byteCount &#8212; the total count of bytes enqueued, whether played back or cleaned.<\/li>\n<li>currentBytesPerSecond &#8212; the NetStream buffer fill rate (bytes per second).<\/li>\n<li>dataBufferByteLength &#8212; the NetStream data buffer length (bytes).<\/li>\n<li>dataBufferLength &#8212; the NetStream data buffer length (seconds).<\/li>\n<li>dataByteCount &#8212; the total count of data message bytes enqueued, whether played back or cleaned.<\/li>\n<li>dataBytesPerSecond \u2013 the NetStream data buffer fill rate (bytes per second).<\/li>\n<li>droppedFrames &#8212; the number of video frames lost in the current NetStream playback session.<\/li>\n<li>maxBytesPerSecond \u2013 the maximum NetStream buffer fill rate (bytes per second).<\/li>\n<li>playbackBytesPerSecond \u2013 the stream playback rate (bytes per second).<\/li>\n<li>SRTT \u2013 Smoothed Round Trip Time for the NetStream session, in milliseconds. This property is valid only for the RTMFP streams. For RTMP streams, it returns 0.<\/li>\n<li>videoBufferByteLength &#8212; the NetStream video buffer length  (bytes).<\/li>\n<li>videoBufferLength &#8212; the NetStream data buffer length (seconds).<\/li>\n<li>videoByteCount &#8212; the total count of video bytes enqueued, whether played back or cleaned.<\/li>\n<li>videoBytesPerSecond &#8212; the NetStream video buffer fill rate (bytes per second).<\/li>\n<li>videoLossRate &#8212; the percentage of video data loss through the NetStream object (percentage of lost messages in the total number of messages).<\/li>\n<\/ul>\n<p><strong>NetStreamMulticastInfo Class<\/strong><br \/>\nNetStreamMulticastInfo class presents rich statistics on the quality of service (QoS), related to basic streaming using RTMFP peering and NetStream IP multicast. The NetStreamMulticastInfo object is returned by the NetStream.multicastInfo property.<br \/>\nThe numeric properties are total amounts calculated from the start of multicast. Such properties include the number of media bytes sent or the number of media fragment messages received. The rate properties represent the current rate snapshot averaged over a few seconds. They specify the rate at which the local node receives the data.<\/p>\n<p>NetStreamMulticastInfo class has the following statistical properties. They are all read-only and have the Number type:<\/p>\n<ul>\n<li>bytesPushedFromPeers &#8212; the number of bytes of media content proactively pushed by peers and received by the local node.<\/li>\n<li>bytesPushedToPeers &#8212; the number of media bytes proactively pushed by the local node to peers.<\/li>\n<li>bytesReceivedFromIPMulticast &#8212; the number media bytes received by the local node from IP multicast.<\/li>\n<li>bytesReceivedFromServer &#8212; the number of media bytes received by the local node from the server.<\/li>\n<li>bytesRequestedByPeers &#8212; the number of media bytes sent by the local node to peers in response to their request of certain fragments.<\/li>\n<li>bytesRequestedFromPeers &#8212; the number of media bytes that the local node requested and received from peers.<\/li>\n<li>fragmentsPushedFromPeers &#8212; the number of media fragment messages proactively pushed from peers and received by the local node.<\/li>\n<li>fragmentsPushedToPeers &#8212; the number of media fragment messages proactively pushed by the local node to peers.<\/li>\n<li>fragmentsReceivedFromIPMulticast &#8212; the number of media fragment messages received by the local node from IP Multicast.<\/li>\n<li>fragmentsReceivedFromServer &#8212; the number of media fragment messages received by the local node from the server.<\/li>\n<li>fragmentsRequestedByPeers &#8212; the number of media fragment messages that the local node has sent to peers in response to their requests for specific fragments.<\/li>\n<li>fragmentsRequestedFromPeers &#8212; the number of media fragment messages that the local node requested and received from peers.<\/li>\n<li>receiveControlBytesPerSecond &#8212; the rate (bytes per second) at which the local node is receiving control overhead messages from peers.<\/li>\n<li>receiveDataBytesPerSecond &#8212; the rate (bytes per second) at which the local node is receiving media data from peers, from the server, and IP Multicast.<\/li>\n<li>receiveDataBytesPerSecondFromIPMulticast &#8212; the rate (bytes per second) at which the local node receives data from IP Multicast.<\/li>\n<li>receiveDataBytesPerSecondFromServer &#8212; the rate (bytes per second) at which the local node receives media content from the server.<\/li>\n<li>sendControlBytesPerSecond &#8212; the rate (bytes per second) at which the local node sends control overhead messages to peers and the server.<\/li>\n<li>sendControlBytesPerSecondToServer &#8212; the rate (bytes per second) at which the local node sends control overhead messages to the server.<\/li>\n<li>sendDataBytesPerSecond &#8212; the rate (bytes per second) at which the media content is sent by the local node to peers.<\/li>\n<\/ul>\n<p>To directly access the NetStream class and its info and multicastInfo properties returning the instances of NetStreamInfo and NetStreamMulticastInfo classes respectively, from OSMF, you&#8217;ll need to override the createNetStream  method of the org.osmf.net.NetLoader class, or of a class inherited from NetLoader. Also, you\u2019ll need to introduce a get method for NetStream, returning the NetStream class when called by the parent class.<\/p>\n<p>The below example shows access to the NetStream class and its info property using the OSMF framework and org.osmf.net.MulticastNetLoader.<\/p>\n<div class=\"codecolorer-container text default\" style=\"overflow:auto;white-space:nowrap;width:540px;\"><table cellspacing=\"0\" cellpadding=\"0\"><tbody><tr><td class=\"line-numbers\"><div>1<br \/>2<br \/>3<br \/>4<br \/>5<br \/>6<br \/>7<br \/>8<br \/>9<br \/>10<br \/>11<br \/>12<br \/>13<br \/>14<br \/>15<br \/>16<br \/>17<br \/>18<br \/>19<br \/>20<br \/>21<br \/>22<br \/>23<br \/>24<br \/>25<br \/>26<br \/>27<br \/><\/div><\/td><td><div class=\"text codecolorer\">\/\/ Create a custom loader class CustomMulticastNetLoader based on MulticastNetLoader<br \/>\n\/\/ and override the createNetStream method <br \/>\npackage<br \/>\n{<br \/>\nimport org.osmf.net.MulticastNetLoader;<br \/>\nimport org.osmf.net.MulticastResource;<br \/>\nimport org.osmf.media.URLResource;<br \/>\nimport flash.net.NetStream;<br \/>\nimport flash.net.NetConnection;<br \/>\npublic class CustomMulticastNetLoader extends MulticastNetLoader<br \/>\n{<br \/>\npublic function CustomMulticastNetLoader (factory: NetConnectionFactoryBase = null)<br \/>\n{<br \/>\nsuper (factory);<br \/>\n}<br \/>\npublic function getNetStream (): NetStream {<br \/>\nreturn _netStream;<br \/>\n}<br \/>\nprivate var _netStream: NetStream;<br \/>\noverride protected function createNetStream (connection: NetConnection, resource: URLResource): NetStream<br \/>\n{<br \/>\nvar rs: MulticastResource = resource as MulticastResource;<br \/>\n_netStream = new NetStream (connection, rs.groupspec);<br \/>\nreturn _netStream;<br \/>\n}<br \/>\n}<br \/>\n}<\/div><\/td><\/tr><\/tbody><\/table><\/div>\n<p>Then create a test p2p player, using CustomMulticastNetLoader class as loader.<\/p>\n<div class=\"codecolorer-container text default\" style=\"overflow:auto;white-space:nowrap;width:540px;\"><table cellspacing=\"0\" cellpadding=\"0\"><tbody><tr><td class=\"line-numbers\"><div>1<br \/>2<br \/>3<br \/>4<br \/>5<br \/>6<br \/>7<br \/>8<br \/>9<br \/>10<br \/>11<br \/>12<br \/>13<br \/>14<br \/>15<br \/>16<br \/>17<br \/>18<br \/>19<br \/>20<br \/>21<br \/>22<br \/>23<br \/>24<br \/>25<br \/>26<br \/>27<br \/>28<br \/>29<br \/>30<br \/>31<br \/>32<br \/>33<br \/>34<br \/>35<br \/>36<br \/>37<br \/>38<br \/>39<br \/>40<br \/>41<br \/>42<br \/>43<br \/>44<br \/>45<br \/>46<br \/>47<br \/>48<br \/>49<br \/>50<br \/>51<br \/>52<br \/>53<br \/>54<br \/>55<br \/>56<br \/>57<br \/>58<br \/>59<br \/>60<br \/>61<br \/><\/div><\/td><td><div class=\"text codecolorer\">package<br \/>\n{<br \/>\nimport flash.display.Sprite;<br \/>\nimport flash.utils.Timer;<br \/>\nimport flash.events.TimerEvent;<br \/>\nimport flash.net.NetStream;<br \/>\nimport flash.net.NetStreamInfo;<br \/>\nimport flash.net.NetStreamMulticastInfo;<br \/>\nimport org.osmf.media.MediaPlayer;<br \/>\nimport org.osmf.containers.MediaContainer;<br \/>\nimport org.osmf.elements.VideoElement;<br \/>\nimport org.osmf.net.MulticastResource;<br \/>\nimport CustomMulticastNetLoader;<br \/>\npublic class TestPlayer extends Sprite<br \/>\n{<br \/>\npublic function TestPlayer ()<br \/>\n{<br \/>\ninitPlayer ();<br \/>\ninitMainTimer ();<br \/>\n}<br \/>\nprivate var loader: CustomMulticastNetLoader;<br \/>\nprivate function initPlayer (): void<br \/>\n{<br \/>\nvar resource: MulticastResource = new MulticastResource (&quot;your application URI&quot;, &quot;your stream name&quot;);<br \/>\nresource.groupspec = &quot;your descriptor&quot;;<br \/>\nresource.streamName = &quot;your stream name&quot;;<br \/>\nloader = new CustomMulticastNetLoader ();<br \/>\nvar videoElement = new VideoElement (resource, loader);<br \/>\nvar mediaPlayer: MediaPlayer = new MediaPlayer ();<br \/>\nmediaPlayer.media = videoElement;<br \/>\nmediaPlayer.volume = 0.5;<br \/>\nvar container: MediaContainer = new MediaContainer ();<br \/>\ncontainer.width = 800;<br \/>\ncontainer.height = 450;<br \/>\ncontainer.addMediaElement (videoElement);<br \/>\naddChild (container);<br \/>\n}<br \/>\nprivate function initMainTimer (): void<br \/>\n{<br \/>\nvar mainTimer: Timer = new Timer (1000, 0);<br \/>\nmainTimer.addEventListener (TimerEvent.TIMER, onMainTimerTickHandler);<br \/>\nmainTimer.start ();<br \/>\n}<br \/>\nprivate function onMainTimerTickHandler (evt: TimerEvent): void<br \/>\n{<br \/>\nvar netStream: NetStream = loader.getNetStream ();<br \/>\nvar netStreamInfo: NetStreamInfo = netStream.info;<br \/>\nvar netStreamMulticastInfo: NetStreamMulticastInfo = netStream.multicastInfo;<br \/>\n\/ \/ Display NetStreamInfo statistics <br \/>\ntrace (&quot;Video buffer length in byte:&quot; + netStreamInfo.videoBufferByteLength);<br \/>\ntrace (&quot;Video buffer length in seconds:&quot; + netStreamInfo.videoBufferLength);<br \/>\ntrace (&quot;Video byte \/ sec:&quot; + netStreamInfo.videoBytesPerSecond);<br \/>\ntrace (&quot;Video loss rate:&quot; + netStreamInfo.videoLossRate);<br \/>\n\/ \/ Display NetStreamMulticastInfo statistics <br \/>\ntrace (&quot;Bytes pushed FROM peers:&quot; + netStreamMulticastInfo.bytesPushedFromPeers);<br \/>\ntrace (&quot;Bytes pushed TO peers:&quot; + netStreamMulticastInfo.bytesPushedToPeers);<br \/>\ntrace (&quot;Receive data bytes \/ second:&quot; + netStreamMulticastInfo.receiveDataBytesPerSecond);<br \/>\ntrace (&quot;Send data bytes \/ second:&quot; + netStreamMulticastInfo.sendDataBytesPerSecond);<br \/>\n}<br \/>\n}<br \/>\n}<\/div><\/td><\/tr><\/tbody><\/table><\/div>\n<p>After compiling a test player, the debug console every second outputs a statistical slice of the following parameters (metrics): videoBufferByteLength, videoBufferLength, videoBytesPerSecond, videoLossRate, as well as the parameters of the P2P: bytesPushedFromPeers, bytesPushedToPeers, receiveDataBytesPerSecond, sendDataBytesPerSecond.<\/p>\n<p>This method of access to the NetStream class can be applied to all OSMF loader classes (HTTPStreamingNetLoader, RTMPDynamicStreamingNetLoader, DVRCastNetLoader and NetLoader).<\/p>\n<p><a href=\"http:\/\/labs.denivip.ru\/projects\/tivista\" onclick=\"_gaq.push(['_trackEvent', 'Engagement', 'Redirect', 'labs']);\" target=\"_blank\">TiViSta<\/a> &#8212; this is our open source service to send statistics to Google Analytics, which could be really useful for automated QoS tracking, reporting and analysis.<\/p>\n<p>Have a good QoS for all you visitors!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>To enhance the quality of video broadcast online, stream status statistics should be analyzed. To collect statistics, two classes can be used: NetStreamInfo and NetStreamMulticastInfo (for P2P connections).In this article, we will overview these classes and the ways to access them via the OSMF framework, which is all but intuitive. We will cover open source [&hellip;]<\/p>\n","protected":false},"author":4,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[20,12],"tags":[],"_links":{"self":[{"href":"http:\/\/blog.denivip.ru\/index.php\/wp-json\/wp\/v2\/posts\/1249"}],"collection":[{"href":"http:\/\/blog.denivip.ru\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/blog.denivip.ru\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/blog.denivip.ru\/index.php\/wp-json\/wp\/v2\/users\/4"}],"replies":[{"embeddable":true,"href":"http:\/\/blog.denivip.ru\/index.php\/wp-json\/wp\/v2\/comments?post=1249"}],"version-history":[{"count":6,"href":"http:\/\/blog.denivip.ru\/index.php\/wp-json\/wp\/v2\/posts\/1249\/revisions"}],"predecessor-version":[{"id":4871,"href":"http:\/\/blog.denivip.ru\/index.php\/wp-json\/wp\/v2\/posts\/1249\/revisions\/4871"}],"wp:attachment":[{"href":"http:\/\/blog.denivip.ru\/index.php\/wp-json\/wp\/v2\/media?parent=1249"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/blog.denivip.ru\/index.php\/wp-json\/wp\/v2\/categories?post=1249"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/blog.denivip.ru\/index.php\/wp-json\/wp\/v2\/tags?post=1249"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}