【问题标题】:best performance for 1080p video in flash (standalone projector)Flash 中 1080p 视频的最佳性能(独立投影仪)
【发布时间】:2012-07-24 14:28:16
【问题描述】:

我需要将一个可以播放全屏视频的小 Flash 网站转换为独立投影仪 投影仪将在 windows 7 或 xp 中运行,并且必须以 1080p 播放视频

这里有没有人有经验如何从中获得最佳性能? 硬件加速现在好像可以了?

最好的问候和感谢所有输入。

【问题讨论】:

    标签: actionscript-3 projector


    【解决方案1】:

    flash.media.StageVideo 是硬件加速播放,减少 CPU 负载:

    http://www.adobe.com/devnet/flashplayer/articles/stage_video.html

    H.264 编解码器是舞台视频的最佳搭档;使用这将确保 您可以获得从视频解码到渲染的完整 GPU 加速。和 这种方法,没有回读(将数据从 GPU 发送到 CPU) 不再需要合成显示列表中的视频帧。 YUV 4:2:0 格式的视频帧通过一个 GPU 着色器(DirectX9 或 OpenGL)并在屏幕上显示。结果,你 将看到更高的像素保真度以及 CPU 和内存的一些减少 用法。

    从上面的链接中,Thibault Imbert 有一个舞台视频的示例实现:

    package
    {
        import flash.display.Bitmap;
        import flash.display.BitmapData;
        import flash.display.DisplayObject;
        import flash.display.Loader;
        import flash.display.Shape;
        import flash.display.Sprite;
        import flash.display.StageAlign;
        import flash.display.StageDisplayState;
        import flash.display.StageScaleMode;
        import flash.events.Event;
        import flash.events.FullScreenEvent;
        import flash.events.KeyboardEvent;
        import flash.events.MouseEvent;
        import flash.events.NetStatusEvent;
        import flash.events.StageVideoAvailabilityEvent;
        import flash.events.StageVideoEvent;
        import flash.events.TimerEvent;
        import flash.events.VideoEvent;
        import flash.geom.Rectangle;
        import flash.media.SoundTransform;
        import flash.media.StageVideo;
        import flash.media.StageVideoAvailability;
        import flash.media.Video;
        import flash.net.NetConnection;
        import flash.net.NetStream;
        import flash.system.LoaderContext;
        import flash.text.TextField;
        import flash.text.TextFieldAutoSize;
        import flash.text.TextFormat;
        import flash.ui.Keyboard;
    
        /**
         * 
         * @author Thibault Imbert
         * 
         */ 
        [SWF(frameRate="1", backgroundColor="#000000")]
        public class SimpleStageVideo extends Sprite
        {
            private static const FILE_NAME:String = "video-file.mov";
            private static const INTERVAL:Number = 500;
            private static const BORDER:Number = 20;
    
            private var legend:TextField = new TextField();
            private var sv:StageVideo;
            private var nc:NetConnection;
            private var ns:NetStream;
            private var rc:Rectangle;
            private var video:Video;
            private var thumb:Shape;
            private var interactiveThumb:Sprite;
            private var totalTime:Number;
    
            private var videoWidth:int;
            private var videoHeight:int;
            private var outputBuffer:String = new String();
            private var rect:Rectangle = new Rectangle(0, 0, 0, BORDER);
            private var videoRect:Rectangle = new Rectangle(0, 0, 0, 0);
            private var gotStage:Boolean;
            private var stageVideoInUse:Boolean;
            private var classicVideoInUse:Boolean;
            private var accelerationType:String;
            private var infos:String = new String();
            private var available:Boolean;
            private var inited:Boolean;
            private var played:Boolean;
            private var container:Sprite;
    
            /**
             * 
             * 
             */     
            public function SimpleStageVideo()
            {
                // Make sure the app is visible and stage available
                addEventListener(Event.ADDED_TO_STAGE, onAddedToStage);
            }
    
            /**
             * 
             * @param event
             * 
             */     
            private function onAddedToStage(event:Event):void
            {
                // Scaling
                stage.scaleMode = StageScaleMode.NO_SCALE;
                stage.align = StageAlign.TOP_LEFT;
                legend.autoSize = TextFieldAutoSize.LEFT;
    
                // Debug infos
                legend.multiline = true;
                legend.background = true;
                legend.backgroundColor = 0xFFFFFFFF;
                addChild(legend);
    
                // Thumb seek Bar
                thumb = new Shape();
    
                interactiveThumb = new Sprite();
                interactiveThumb.addChild(thumb);
                addChild(interactiveThumb);
    
                // Connections
                nc = new NetConnection();
                nc.connect(null);
                ns = new NetStream(nc);
                ns.addEventListener(NetStatusEvent.NET_STATUS, onNetStatus);
                ns.client = this;
    
                // Screen
                video = new Video();
                video.smoothing = true;
    
                // Video Events
                // the StageVideoEvent.STAGE_VIDEO_STATE informs you if StageVideo is available or not
                stage.addEventListener(StageVideoAvailabilityEvent.STAGE_VIDEO_AVAILABILITY, onStageVideoState);
                // in case of fallback to Video, we listen to the VideoEvent.RENDER_STATE event to handle resize properly and know about the acceleration mode running
                video.addEventListener(VideoEvent.RENDER_STATE, videoStateChange);
    
                // Input Events
                stage.addEventListener(KeyboardEvent.KEY_DOWN, onKeyDown);
                stage.addEventListener(Event.RESIZE,  onResize);
                stage.addEventListener(MouseEvent.CLICK, onClick);
            }
    
            /**
             * 
             * @param event
             * 
             */     
            private function onNetStatus(event:NetStatusEvent):void
            {
                if ( event.info == "NetStream.Play.StreamNotFound" )
                    legend.text = "Video file passed, not available!";
            }
    
            /**
             * 
             * @param event
             * 
             */     
            private function onFrame(event:Event):void 
            {
                var ratio:Number = (ns.time / totalTime) * (stage.stageWidth - (BORDER << 1));
                rect.width = ratio;
                thumb.graphics.clear();
                thumb.graphics.beginFill(0xFFFFFF);
                thumb.graphics.drawRect(rect.x, rect.y, rect.width, rect.height);   
            }
    
            /**
             * 
             * @param event
             * 
             */     
            private function onClick(event:MouseEvent):void
            {
                if ( event.stageY >= interactiveThumb.y - BORDER && event.stageX <= stage.stageWidth - BORDER )
                {
                    var seekTime:Number = (stage.mouseX - BORDER) * ( totalTime / (stage.stageWidth - (BORDER << 1) ) );
                    ns.seek( seekTime );    
                }
            }
    
            /**
             * 
             * @param event
             * 
             */     
            private function onKeyDown(event:KeyboardEvent):void
            {   
                if ( event.keyCode == Keyboard.O )
                {
                    if ( available )
                        // We toggle the StageVideo on and off (fallback to Video and back to StageVideo)
                        toggleStageVideo(inited=!inited);
    
                } else if ( event.keyCode == Keyboard.F )
                {
                    stage.displayState = StageDisplayState.FULL_SCREEN;
                } else if ( event.keyCode == Keyboard.SPACE )
                {
                    ns.togglePause();
                }
            }
    
            /**
             * 
             * @param width
             * @param height
             * @return 
             * 
             */     
            private function getVideoRect(width:uint, height:uint):Rectangle
            {   
                var videoWidth:uint = width;
                var videoHeight:uint = height;
                var scaling:Number = Math.min ( stage.stageWidth / videoWidth, stage.stageHeight / videoHeight );
    
                videoWidth *= scaling, videoHeight *= scaling;
    
                var posX:uint = stage.stageWidth - videoWidth >> 1;
                var posY:uint = stage.stageHeight - videoHeight >> 1;
    
                videoRect.x = posX;
                videoRect.y = posY;
                videoRect.width = videoWidth;
                videoRect.height = videoHeight;
    
                return videoRect;
            }
    
            /**
             * 
             * 
             */     
            private function resize ():void
            {   
                if ( stageVideoInUse )
                {
                    // Get the Viewport viewable rectangle
                    rc = getVideoRect(sv.videoWidth, sv.videoHeight);
                    // set the StageVideo size using the viewPort property
                    sv.viewPort = rc;
                } else 
                {
                    // Get the Viewport viewable rectangle
                    rc = getVideoRect(video.videoWidth, video.videoHeight);
                    // Set the Video object size
                    video.width = rc.width;
                    video.height = rc.height;
                    video.x = rc.x, video.y = rc.y;
                }
    
                interactiveThumb.x = BORDER, interactiveThumb.y = stage.stageHeight - (BORDER << 1);
                legend.text = infos;
            }
    
            /**
             * 
             * @param evt
             * 
             */     
            public function onMetaData ( evt:Object ):void
            {
                totalTime = evt.duration;
                stage.addEventListener(Event.ENTER_FRAME, onFrame);
            }
    
            /**
             * 
             * @param event
             * 
             */     
            private function onStageVideoState(event:StageVideoAvailabilityEvent):void
            {   
                // Detect if StageVideo is available and decide what to do in toggleStageVideo
                toggleStageVideo(available = inited = (event.availability == StageVideoAvailability.AVAILABLE));
            }
    
            /**
             * 
             * @param on
             * 
             */     
            private function toggleStageVideo(on:Boolean):void
            {   
                infos = "StageVideo Running (Direct path) : " + on + "\n";
    
                // If we choose StageVideo we attach the NetStream to StageVideo
                if (on) 
                {
                    stageVideoInUse = true;
                    if ( sv == null )
                    {
                        sv = stage.stageVideos[0];
                        sv.addEventListener(StageVideoEvent.RENDER_STATE, stageVideoStateChange);
                    }
                    sv.attachNetStream(ns);
                    if (classicVideoInUse)
                    {
                        // If we use StageVideo, we just remove from the display list the Video object to avoid covering the StageVideo object (always in the background)
                        stage.removeChild ( video );
                        classicVideoInUse = false;
                    }
                } else 
                {
                    // Otherwise we attach it to a Video object
                    if (stageVideoInUse)
                        stageVideoInUse = false;
                    classicVideoInUse = true;
                    video.attachNetStream(ns);
                    stage.addChildAt(video, 0);
                }
    
                if ( !played ) 
                {
                    played = true;
                    ns.play(FILE_NAME);
                }
            } 
    
            /**
             * 
             * @param event
             * 
             */     
            private function onResize(event:Event):void
            {
                resize();       
            }
    
            /**
             * 
             * @param event
             * 
             */     
            private function stageVideoStateChange(event:StageVideoEvent):void
            {   
                infos += "StageVideoEvent received\n";
                infos += "Render State : " + event.status + "\n";
                resize();
            }
    
            /**
             * 
             * @param event
             * 
             */     
            private function videoStateChange(event:VideoEvent):void
            {   
                infos += "VideoEvent received\n";
                infos += "Render State : " + event.status + "\n";
                resize();
            }
        }
    }
    

    【讨论】:

      【解决方案2】:

      为了获得最佳视频,您想使用新的StageVideo 以使用硬件加速。该站点需要为 as3 并且 StageVideo 在正常的 flash 阶段下运行,因此您需要在视频播放时隐藏除控件之外的任何 flash 元素。另外我会考虑使用 AIR 而不是投影仪方法将文件打包到一个独立的应用程序中。

      【讨论】:

      • 你好,谢谢。为什么你更喜欢空气而不是投影仪?我宁愿不处理整个运行时更新和安装过程。
      • 您可以将 air 用作强制运行时:help.adobe.com/en_US/air/build/… 您现在也可以在 Flash 中的发布设置中执行此操作。我认为从 Flash CS 5.5 开始 - youtube.com/watch?v=Wpi00UAoFjE
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-03-27
      • 1970-01-01
      • 2011-08-27
      • 2023-04-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多