使用 StageVideo API

舞台视频是运行时中的一种视频呈现机制,可增强视频播放和设备性能。运行时负责创建并维护该机制;作为开发人员,您的职责是配置应用程序以利用该机制。

为了使用舞台视频,您需要实现事件处理函数框架,以检测舞台视频何时可用以及何时不可用。当接收到指示舞台视频可用的通知时,从 Stage.stageVideos 属性中检索 StageVideo 对象。运行时使用一个或多个 StageVideo 对象填充此 Vector 对象。然后,您就可以使用所提供的 StageVideo 对象替代 Video 对象来显示流式传输视频。

在 Flash Player 中,当您接收到指示舞台视频不再可用的通知时,请将视频流切换回 Video 对象。

注: 您不能创建 StageVideo 对象。

Stage.stageVideos 属性

Stage.stageVideos 属性是一个 Vector 对象,通过该对象可访问 StageVideo 实例。此矢量最多可包含 4 个 StageVideo 对象,具体取决于硬件和系统资源。移动设备可以限制为 1 个对象或无对象。

当舞台视频不可用时,该矢量不包含任何对象。为了避免运行时错误,当接收到指示舞台视频可用的最近 StageVideoAvailability 事件时,请确保仅访问该矢量的成员。

StageVideo 事件

StageVideo API 框架提供了以下事件:

StageVideoAvailabilityEvent.STAGE_VIDEO_AVAILABILITY
Stage.stageVideos 属性发生更改时发送该事件。 StageVideoAvailabilityEvent.availability 属性指示 AVAILABLE UNAVAILABLE 。使用该事件可确定 stageVideos 属性是否包含任何 StageVideo 对象,而不必直接检查 Stage.stageVideos 矢量的长度。

StageVideoEvent.RENDER_STATE
在 NetStream 或 Camera 对象已附加到 StageVideo 对象并正在播放时发送。指示当前使用的解码类型:硬件、软件或不可用(不显示任何内容)。事件目标包含 videoWidth videoHeight 属性,调整视频视口的大小时可以安全地使用这些属性。
重要说明: 从 StageVideo 目标对象获取的坐标使用舞台坐标,这是因为他们不是标准显示列表的一部分。

VideoEvent.RENDER_STATE
当正在使用 Video 对象时发送该事件。指示当前使用的是软件加速解码还是硬件加速解码。如果该事件指示硬件加速解码,则在可能的情况下,应切换到 StageVideo 对象。Video 事件目标包含 videoWidth videoHeight 属性,调整视频视口大小时可以安全地使用这些属性。

实现 StageVideo 功能的工作流程

请执行这些顶级步骤来实现 StageVideo 功能:

  1. 侦听 StageVideoAvailabilityEvent.STAGE_VIDEO_AVAILABILITY 事件以了解 Stage.stageVideos 矢量何时更改。请参阅 使用 StageVideoAvailabilityEvent.STAGE_VIDEO_AVAILABILITY 事件

  2. 如果 StageVideoAvailabilityEvent.STAGE_VIDEO_AVAILABILITY 事件报告舞台视频可用,则可以在事件处理函数中使用 Stage.stageVideos Vector 对象来访问 StageVideo 对象。

  3. 使用 StageVideo.attachNetStream() 附加一个 NetStream 对象,或使用 StageVideo.attachCamera() 附加一个 Camera 对象。

  4. 使用 NetStream.play() 播放视频。

  5. 侦听 StageVideo 对象上的 StageVideoEvent.RENDER_STATE 事件,以确定播放视频的状态。收到此事件还说明,视频的宽度和高度属性已初始化或更改。请参阅 使用 StageVideoEvent.RENDER_STATE 和 VideoEvent.RENDER_STATE 事件

  6. 侦听 Video 对象上的 VideoEvent.RENDER_STATE 事件。此事件提供与 StageVideoEvent.RENDER_STATE 相同的状态,因此您也可以使用它来确定 GPU 加速是否可用。收到此事件还说明,视频的宽度和高度属性已初始化或更改。请参阅 使用 StageVideoEvent.RENDER_STATE 和 VideoEvent.RENDER_STATE 事件

初始化 StageVideo 事件侦听器

在应用程序初始化过程中设置 StageVideoAvailabilityEvent 和 VideoEvent 侦听器。例如,可以在 flash.events.Event.ADDED_TO_STAGE 事件处理函数中初始化这些侦听器。此事件可保证您的应用程序在舞台上可见;

public class SimpleStageVideo extends Sprite 
    private var nc:NetConnection; 
    private var ns:NetStream; 
 
    public function SimpleStageVideo() 
    { 
        // Constructor for SimpleStageVideo class 
        // Make sure the app is visible and stage available 
        addEventListener(Event.ADDED_TO_STAGE, onAddedToStage); 
    } 
     
    private function onAddedToStage(event:Event):void 
    { 
        //... 
        // 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 whether 
        // StageVideo is available 
        stage.addEventListener(StageVideoAvailabilityEvent.STAGE_VIDEO_AVAILABILITY, 
            onStageVideoState); 
        // in case of fallback to Video, listen to the VideoEvent.RENDER_STATE 
        // event to handle resize properly and know about the acceleration mode running 
        video.addEventListener(VideoEvent.RENDER_STATE, videoStateChange); 
        //... 
    }

使用 StageVideoAvailabilityEvent.STAGE_VIDEO_AVAILABILITY 事件

StageVideoAvailabilityEvent.STAGE_VIDEO_AVAILABILITY 处理函数中,根据 StageVideo 的可用性确定是使用 Video 对象还是使用 StageVideo 对象。如果 StageVideoAvailabilityEvent.availability 属性设置为 StageVideoAvailability.AVAILABLE ,则使用 StageVideo。在这种情况下,可依赖于 Stage.stageVideos 矢量来包含一个或多个 StageVideo 对象。从 Stage.stageVideos 属性获取 StageVideo 对象,并将 NetStream 对象附加到它。由于 StageVideo 对象始终显示在背景中,因此需删除所有现有的 Video 对象(始终位于前景中)。还可以使用此事件处理函数添加 StageVideoEvent.RENDER_STATE 事件的侦听器。

如果 StageVideoAvailabilityEvent.availability 属性设置为 StageVideoAvailability.UNAVAILABLE ,请勿使用 StageVideo 或访问 Stage.stageVideos 矢量。在这种情况下,请将 NetStream 对象附加到 Video 对象。最后,请将 StageVideo 或 Video 对象添加到舞台,并调用 NetStream.play()

下面的代码显示如何处理 StageVideoAvailabilityEvent.STAGE_VIDEO_AVAILABILITY 事件:

private var sv:StageVideo; 
private var video:Video; 
 
private function onStageVideoState(event:StageVideoAvailabilityEvent):void 
{     
    // Detect if StageVideo is available and decide what to do in toggleStageVideo 
    toggleStageVideo(event.availability == StageVideoAvailability.AVAILABLE); 
} 
 
private function toggleStageVideo(on:Boolean):void 
{     
    // To choose StageVideo 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 you use StageVideo, remove from the display list the 
            // Video object to avoid covering the StageVideo object 
            // (which is always in the background) 
            stage.removeChild ( video ); 
            classicVideoInUse = false; 
        } 
    } else 
    { 
        // Otherwise 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); 
    } 
} 
重要说明: 当应用程序第一次在 Stage.stageVideos[0] 访问 vector 元素时,默认矩形设置为 0,0,0,0, 并使用默认值平移和缩放属性。请始终将这些值设置您首选的设置。您可以使用 StageVideoEvent.RENDER_STATE VideoEvent.RENDER_STATE 事件的 videoWidth videoHeight 属性来计算视频视口尺寸。

可从 舞台视频快速入门 下载本示例应用程序的完整源代码。

使用 StageVideoEvent.RENDER_STATE 和 VideoEvent.RENDER_STATE 事件

当显示环境变化时,StageVideo 和 Video 对象会发送事件以通知应用程序。这些事件为 StageVideoEvent.RENDER_STATE VideoEvent.RENDER_STATE

当 NetStream 对象已附加并开始播放时,StageVideo 或 Video 对象会调度一个呈现状态事件。当显示环境变化时,它还会发送此事件;例如,当视频视口的大小调整时。请使用这些通知将视口重新设置为事件目标对象的当前 videoHeight videoWidth 值。

已报告的呈现状态包括:

  • RENDER_STATUS_UNAVAILABLE

  • RENDER_STATUS_SOFTWARE

  • RENDER_STATUS_ACCELERATED

不论当前播放视频的是哪个类,使用硬件加速解码时,均会指示呈现状态。请查看 StageVideoEvent.status 属性了解必要的解码是否可用。如果此属性设置为“unavailable”,则 StageVideo 对象不能播放此视频。此状态要求您立即将 NetStream 对象重新附加到 Video 对象。其他状态会将当前的呈现情况通知您的应用程序。

下表说明了 Flash Player 中 StageVideoEvent 和 VideoEvent 对象的所有呈现状态值的影响。

VideoStatus.ACCELERATED

VideoStatus.SOFTWARE

VideoStatus.UNAVAILABLE

StageVideoEvent

解码和呈现均发生在硬件中。(最佳性能。)

通过硬件呈现,使用软件解码。(可接受的性能。)

没有可用的 GPU 资源来处理视频,不显示任何内容。 回退到 Video 对象。

VideoEvent

使用软件呈现,通过硬件解码。(仅在现代桌面系统中可达到可接受的性能。全屏性能会下降。)

使用软件呈现,使用软件解码。(最差的性能表现。全屏性能会下降。)

(不适用)

色彩空间

舞台视频使用基础硬件功能提供色彩空间支持。SWF 内容可提供指示其首选色彩空间的元数据。但是,设备图形硬件决定是否可使用该色彩空间。某一台设备可能会支持多种色彩空间,而另一台设备却不支持任何色彩空间。如果硬件不支持所请求的色彩空间,则 Flash Player 将尝试在所支持的色彩空间中查找匹配度最高的色彩空间。

若要查询硬件支持的色彩空间,请使用 StageVideo.colorSpaces 属性。此属性以 String 矢量的形式返回所支持的色彩空间列表:

var colorSpace:Vector.<String> = stageVideo.colorSpaces();

若要了解当前播放的视频所使用的色彩空间,请检查 StageVideoEvent.colorSpace 属性。在 StageVideoEvent.RENDER_STATE 事件的事件处理函数中检查此属性:

var currColorSpace:String; 
 
//StageVideoEvent.RENDER_STATE event handler 
private function stageVideoRenderState(event:Object):void 
{ 
    //... 
    currColorSpace = (event as StageVideoEvent).colorSpace; 
    //... 
}

如果 Flash Player 无法为不支持的色彩空间找到替代色彩空间,舞台视频将使用默认的 BT.601 色彩空间。例如,采用 H.264 编码的视频流通常使用 BT.709 色彩空间。如果设备硬件不支持 BT.709,则 colorSpace 属性将返回 "BT601" 。如果 StageVideoEvent.colorSpace 的值为 "unknown" ,则指示硬件未提供色彩空间查询方法。

如果您的应用程序认为当前色彩空间不可接受,可选择从 StageVideo 对象切换到 Video 对象。Video 类通过软件合成支持所有色彩空间。