2

我在数据生成模式下使用 NetStream 使用 appendBytes 播放嵌入的 FLV。流播放完毕后,我想循环播放 FLV 文件。我不确定如何实现这一目标。这是我到目前为止所拥有的(这不是一个完整的例子):

        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 );
            }
        }

这将循环动画,但它开始疯狂地消耗内存。我尝试过使用 NetStream.seek(0) 和 NetStream.appendBytesAction( NetStreamAppendBytesAction.RESET_SEEK ),但是我不确定下一步该做什么。如果您只是尝试在此之后再次调用 appendBytes,它就不起作用,大概是因为我正在附加具有 FLV 标头和内容的完整字节数组?我不是很熟悉这一切是如何运作的。

任何帮助是极大的赞赏。

4

2 回答 2

5

[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
        }
    }
}
于 2012-08-13T17:11:21.110 回答
1
package {

    import flash.display.MovieClip;
    import flash.events.AsyncErrorEvent;
    import flash.events.IOErrorEvent;
    import flash.events.NetStatusEvent;
    import flash.media.Video;
    import flash.net.NetConnection;
    import flash.net.NetStream;
    import flash.utils.ByteArray;


    public class VideoPlayer extends MovieClip {

        /** Проиграть массив данныx <b>byteArray</b> (flv) в видеоконтейнере <b>video</b>. Проигрывается 1 + n раз, при n >= 0 и infinity при n < 0
         * 
         * @param video - видеоконтейнер
         * @param fileArray - массив данныx (flv) 
         * @param repeat - количество повторений видеоролика (-1 - бесконечный цикл, 0 - проиграть без повторений, (n > 0) - n повторений)
         * 
         */     
        public static function playVideo(video:Video, byteArray:ByteArray, repeat:int = -1):void {
            var netConnection:NetConnection;
            var netStream:NetStream;
            var repeatCount:int = 0;

            var netStream_Status_Handler:Function = function(event:NetStatusEvent):void {
                switch(event.info.code || "") {
                    case 'NetStream.Buffer.Empty': {
                        update();
                    }
                    default: {
                        break;
                    }
                }
            }

            var netStream_IOError_Handler:Function = function(event:AsyncErrorEvent):void {

            }

            var netConnection_Status_Handler:Function = function(event:NetStatusEvent):void {
                switch(event.info.code || "") {
                    case 'NetConnection.Connect.Success': {
                        update();
                        break;
                    }

                    default: {
                        break;
                    }
                }
            }

            var update:Function = function():void {
                if(repeat > -1 && repeat < repeatCount) {
                    return;
                }

                repeatCount++;

                try {
                    if(netStream) {
                        netStream.close();
                        if(netStream.hasOwnProperty("dispose")) { // совместимость с fla|as3
                            netStream["dispose"]();
                        }
                        netStream = null;
                    }

                    netStream = new NetStream(netConnection);
                    netStream.addEventListener(NetStatusEvent.NET_STATUS, netStream_Status_Handler);
                    netStream.addEventListener(IOErrorEvent.IO_ERROR, netStream_IOError_Handler);
                    netStream.client = {};
                    netStream.play(null);
                    netStream["appendBytes"](byteArray); // совместимость с fla|as3

                    video.attachNetStream(netStream); 
                } catch(error:Error) {

                }
            }

            var netConnection_AsyncError_Handler:Function = function(event:AsyncErrorEvent):void {

            }

            var netConnection_IOError_Handler:Function = function(event:AsyncErrorEvent):void {

            }

            netConnection = new NetConnection();
            netConnection.addEventListener(NetStatusEvent.NET_STATUS , netConnection_Status_Handler);
            netConnection.addEventListener(AsyncErrorEvent.ASYNC_ERROR , netConnection_AsyncError_Handler);
            netConnection.addEventListener(IOErrorEvent.IO_ERROR , netConnection_IOError_Handler);
            netConnection.connect(null);
        }

    }
}
于 2013-07-09T13:59:36.463 回答