How to loop video using NetStream in Data Generation Mode

WesleyJohnson picture WesleyJohnson · Aug 9, 2012 · Viewed 9k times · Source

I'm using a NetStream in Data Generation Mode to play an embeded FLV using appendBytes. When the stream is finished playing, I'd like to loop the FLV file. I'm not sure how to achieve this. Here is what I have so far (this isn't a complete example):

        public function createBorderAnimation():void
        {
            // Load the skin image
            borderAnimation = Assets.BorderAnimation;

            // Convert the animation to a byte array
            borderAnimationBytes = new borderAnimation();

            // Initialize the net connection
            border_nc = new NetConnection();
            border_nc.connect( null );

            // Initialize the net stream
            border_ns = new NetStream( border_nc );
            border_ns.client = { onMetaData:function( obj:Object ):void{ trace(obj); } }
            border_ns.addEventListener( NetStatusEvent.NET_STATUS, border_netStatusHandler );
            border_ns.play( null );
            border_ns.appendBytes( borderAnimationBytes );

            // Initialize the animation
            border_vd = new Video( 1024, 768 );
            border_vd.attachNetStream( border_ns );

            // Add the animation to the stage
            ui = new UIComponent();
            ui.addChild( DisplayObject( border_vd ) );
            grpBackground.addElement( ui );             
        }

        protected function border_netStatusHandler( event:NetStatusEvent ):void
        {
            if( event.info.code == "NetStream.Buffer.Flush" || event.info.code == "NetStream.Buffer.Empty" )
            {
                border_ns.appendBytesAction( NetStreamAppendBytesAction.RESET_BEGIN );
                border_ns.appendBytes( borderAnimationBytes );
                border_ns.appendBytesAction( NetStreamAppendBytesAction.END_SEQUENCE );
            }
        }

This will loop the animation, but it starts chewing up memory like crazy. I've tried using NetStream.seek(0) and NetStream.appendBytesAction( NetStreamAppendBytesAction.RESET_SEEK ), but then I'm not sure what to do next. If you just try to call appendBytes again after that, it doesn't work, presumably because I'm appending the full byte array which has the FLV header and stuff? I'm not very familiar with how that all works.

Any help is greatly appreciated.

Answer

Sunil D. picture Sunil D. · Aug 13, 2012

[Edit]

Initially I didn't see a memory problem with your code. However, the example app I was using (below) only listens for the NetStream.Buffer.Empty message from the NetStatusEvent. It does not listen for the NetStream.Buffer.Flush message. I just tried listening for both, as in your example, and the app goes haywire :)

The code below also shows how to use seek(0) to restart playback with appendBytes(). To make that work, you need to wait for NetStream.Seek.Notify from the NetStatusEvent, then append the bytes.

I also restarted playback without using seek(0) (the commented out line), and memory usage was fine.

I am using Mac OS X and measured memory with the top command and Activity Monitor. Activity Monitor's virtual memory stats fluctuated considerably, but nothing like a memory leak.

package
{
    import flash.display.Sprite;
    import flash.display.StageAlign;
    import flash.display.StageScaleMode;
    import flash.events.NetStatusEvent;
    import flash.media.Video;
    import flash.net.NetConnection;
    import flash.net.NetStream;
    import flash.net.NetStreamAppendBytesAction;
    import flash.utils.ByteArray;

    public class LoopEmbedFLV extends Sprite
    {

        [Embed(source="woot.flv",mimeType="application/octet-stream")]
        private var flv:Class;

        private var bytes:ByteArray;
        private var nc:NetConnection;
        private var ns:NetStream;
        private var video:Video;

        public function LoopEmbedFLV()
        {
            super();
            stage.scaleMode=StageScaleMode.NO_SCALE;
            stage.align=StageAlign.TOP_LEFT;
            bytes = new flv();
            nc=new NetConnection();
            nc.connect(null);
            ns=new NetStream(nc);
            video=new Video();
            addChild(video);
            video.attachNetStream(ns);
            ns.client = { onMetaData: function():void { } };
            ns.addEventListener(NetStatusEvent.NET_STATUS, onNetStatus);
            ns.play(null);
            ns.appendBytes(bytes);
        }

        private function onNetStatus(event:NetStatusEvent):void
        {
            var code:String=event.info.code;
            trace(code);
            switch(code)
            {
                case "NetStream.Buffer.Empty":
                    ns.seek(0);
//                  seekToBeginning();
                    break;
                case "NetStream.Seek.Notify":
                    var seekPoint:Number = event.info.seekPoint;
                    trace("seeking to: ", seekPoint);
                    seekPoint == 0 ? seekToBeginning() : seekToOffset(seekPoint);
                    break;
            }
        }

        private function seekToBeginning():void
        {
            ns.appendBytesAction(NetStreamAppendBytesAction.RESET_BEGIN);
            ns.appendBytes(bytes);
            ns.appendBytesAction(NetStreamAppendBytesAction.END_SEQUENCE);
        }
        private function seekToOffset(seekPoint:Number):void
        {
            ns.appendBytesAction(NetStreamAppendBytesAction.RESET_SEEK);
            // todo
        }
    }
}