ADC推荐:实现适用于电视上的Flash Platform的视频和内容
Adobe Flash Platform是在Web上实现视频和富交互式内容的领先平台。现在Adobe正与Google和三星等公司合作,将Adobe Flash Player 10.1和Adobe AIR 2.5引入到电视机中,使消费者可以在他们的起居室内观赏同样的视频内容。本文提供调整您的内容以在电视上最优地执行的建议。 要确保您的视频内容最优地执行,应该执行以下操作:
- 使用新的StageVideo API
- 确认您的视频流采用了适合电视的格式进行编码
- 同时针对新内容和传统内容优化您的视频播放器和应用程序的性能
- 确保您应用程序的用户界面适合电视
- 理解适合视频的内容保护选项
- 向您的网站添加条件逻辑,以便根据目标设备自定义您的视频流和视频播放器
要求
需要的产品
- Flash Professional CS5(下载试用版)
示例文件
预备知识
应该牢固掌握使用Flash实现视频的知识,包括用于视频传送和回放的ActionScript API。了解HTTP、视频传送网络协议和视频编码标准的基本知识也有所帮助。
舞台视频简介
迄今为止,Flash Player中的视频都是使用ActionScript 3中的Video对象渲染的。Video对象与舞台上的任何其他对象相同,为开发人员提供了前所未有的创造性控件数量。例如,视频可以在旋转立方体的每个面上显示,或者多个视频可以混合为一个新的视频。
要支持这种创造性控制水平,Flash运行时必须对每个视频帧进行大量处理。取决于底层设备的功率,增加的处理工作可能降低视频的帧率,或者可能提升Flash施加在CPU上的负载。
为了解决此问题,Adobe引入了一种新的视频渲染方式。这种新方法称为"舞台视频",它最充分地利用了底层的视频硬件。将CPU上低得多的负载转换为了较低功耗设备上的更高帧率以及更少的内存使用。 舞台视频的性能优势对电视和机顶盒尤其有用。这些设备没有像桌面计算机那样强大的CPU,但它们拥有非常强大的视频解码器,能够使用极少的CPU资源渲染高品质的视频内容。
使用这种新的舞台视频方法,视频会渲染到StageVideo对象上,而不是渲染到Video对象上。StageVideo对象始终显示在一个与窗口对齐的矩形屏幕区域中。尽管其他图形可能位于StageVideo对象之上的图层中,但您不能将对象放在视频之后的图层上。而且,在使用StageVideo对象时以下功能将不可用:
- StageVideo对象不能旋转。
- StageVideo对象可能不能应用colorTransform或3D变换。它可能也没有用于扭曲视频的矩阵变换。
- StageVideo对象不能应用alpha通道、滤镜、蒙板或scale9Grid。
- 视频数据不能复制到BitmapData对象中。
- 视频数据不能嵌入到SWF文件中。舞台视频只能用于来自NetStream对象的视频。
- 取决于底层硬件,一些色彩空间可能不受支持。在这些情况下,Flash运行时将选择一种替代的色彩空间。新的StageVideo ActionScript API提供了一种查询所使用的色彩空间的方式。
- 为了确保计算机桌面上的和电视设备上的Flash Player之间的兼容性,需要使用wmode=direct。
- 避免wmode=transparent SWF文件彼此重叠。Google TV等平台不支持wmode=transparent。这意味着wmode=window中支持所有Flash实例,无论使用何种嵌入标记参数。
在实际中,上述所有限制都不会影响到最常见的使用场景,也就是视频播放器应用程序。在这些限制可接受的情况下,强烈建议开发人员使用StageVideo对象。
Google TV*平台、所有AIR for TV平台上都支持舞台视频,所有支持Flash Player的平台上很快也会支持它。
Flash Player包含一个名为StageVideo的新类,它表示硬件视频平面上的一个视频显示实例。StageVideo对象是由Flash运行时创建的,不能自行实例化。可以使用以下命令从Stage对象访问StageVideo对象:
var v:Vector.<StageVideo> = stage.stageVideos; var stageVideo:StageVideo; if ( v.length >= 1 ) { stageVideo = v[0]; }
在访问stageVideos属性时,Stage.stageVideos矢量的长度将因平台和硬件可用性不同而异。该矢量的长度有时将为0。开发人员必须检查此条件,如果不满足,内容必定会中断。如果StageVideo对象不可用,那么应使用Video对象代替。获得了StageVideo对象后,可以移动和调整它的大小。坐标始终在Stage坐标空间中,因为StageVideo对象实质上是Stage的子对象,而未包含在标准显示列表中。示例代码:
stageVideo.viewPort = new Rectangle(10,10,320,240);
在显示视频流之前,开发人员应该为StageVideoEvent.RENDER_STATE事件添加一个侦听器。下面是一个事件处理函数的框架:
function onStageVideoEvent(event:StageVideoEvent) { if ( event.status == StageVideoEvent.RENDER_STATUS_UNAVAILABLE ) { // The video hardware stopped showing video. On the desktop you // would want to fall back to use a normal Video object // to continue rendering video at a cost of performance. } if ( event.status == StageVideoEvent.RENDER_STATUS_SOFTWARE) { // The video is decoded using a software video decoder. } if ( event.status == StageVideoEvent.RENDER_STATUS_ACCELERATED ) { // The video is decoded using a hardware based video decoder. } } stageVideo.addEventListener(StageVideoEvent.RENDER_STATE, onStageVideoEvent);
要在StageVideo中显示视频流,可以使用attachNetStream方法,它类似于Video.attachNetStream方法:
stageVideo.attachNetStream(myNetStream);
在使用上述任何API之前,StageVideo API提供了多种方法来跟踪功能。例如,我们可以查询StageVideo对象可以显示哪些视频色彩空间。该API返回一个字符串矢量,其中通常包含"BT.601"和"BT.709"。
var colorSpaces:Vector.<String> = stageVideo.colorSpaces;
下面是一个使用新StageVideo API的应用程序片段:
{ public var netStream:NetSteam; public function SamplePlayer() { netConnection.connect(null); video.attachNetStream(netStream); // might be overridden later // Set up normal display list properties video.x = 100; video.y = 100; video.width = 320; video.height = 240; addChild(video); // Try to render as stage video var v:Vector.<StageVideo> = stage.stageVideos; if ( v.length >= 1 ) { var stageVideo:StageVideo = v[0]; stageVideo.viewPort = stageVideo.addEventListener( StageVideoEvent.RENDER_STATE,renderStateEventHandler); stageVideo.attachNetStream(netStream); } netStream.play("MyVideo.f4v"); } public function renderStateEventHandler(event:StageVideoEvent):void { // If video is not rendered properly let the // video object in the display list try to render it. if ( event.status == StageVideoEvent.RENDER_STATUS_UNAVAILABLE ) { video.attachNetStream(netStream); } } }
要获得利用StageVideo API的完整的视频播放器示例,请查看本文附带的示例文件(TestStageVideo.as)。
视频编码指南
当将视频传输到电视设备时,Adobe建议遵守以下编码准则:
- 视频编解码器:H.264,主流或高级配置文件,递增式编码
- 分辨率:720i、720p、1080i或1080p
- 帧率:每秒24或30帧
- 音频编解码器:AAC-LC或AC3,44.1 kHz,立体声
- 组合比特率:最高2Mbps(或更高,取决于可用带宽)
- 音频比特率:最高192 kbps
- 像素高宽比:1 x 1
Flash Player还支持使用Sorenson Spark或On2 VP6编解码器编码的视频。但是,这些编解码器没有受到视频硬件的全面支持,所以它们播放的帧率要低得多。因此,应该尽可能使用H.264。
这些视频编码准则不适用于某些支持Flash Player的其他设备,比如智能电话。因此您网站上应该包含某种条件逻辑,向不同的目标设备提供不同的视频流。本文后面将介绍更多细节。
要阅读关于使用Flash Player优化视频的更多信息,请立即查阅文档Delivering video for Flash Player 10.1 on mobile devices。从移动视频编码准则到视频播放器优化,该文档涵盖了任何处理视频的Flash开发人员都在关注的一般优化方法。
视频传送指南
考虑到您用户家里接入的网络连接的质量大多不稳定,您的视频传送系统需要采取某种类型的自适应比特率策略,无论使用何种设备类型。出于不同的原因,这适用于像在移动电话上一样向起居室传送的视频。在前一种情况中,随着其他用户开始使用相同的网络连接,网络阻塞会加剧;在后一种情况中,随着用户不断移动,信号的质量会不断变化。在两种情况中,可用的带宽都会在播放视频过程中不断变化。
Adobe Flash Media Server 4等具有自适应比特率功能的技术,以及在网络断开期间恢复的功能,能够在回放期间网络容量不断变化的情况下实现高品质的用户体验。Flash Player on Google TV和Samsung设备上的AIR中的功能支持这种自适应比特率回放。为了充分利用各种技术,以及利用已经完成的广泛测试,Adobe强烈建议使用开源媒体框架*(Open Source Media Framework,OSMF)作为任何视频播放器应用于嵌入式设备的基础。Adobe免费*提供了OSMF,支持迅速实现视频播放器来利用所有Flash Platform功能,包括自适应比特率和我们的内容保护解决方案。
对于内容的传送,Flash Platform中提供了各种协议来为您在网络上传送视频提供支持:
- HTTP Dynamic Streaming(F4F格式)
- RTMP/e Streaming
- HTTP Progressive Download
- RTMFP Peer-to-Peer
- RTMFP Multicast
上面的选择使您能够灵活地使用现有传送基础设施向目标电视设备传送视频。
在GOOGLE TV上支持传统内容
在未来,Flash Player将同时支持Video对象和StageVideo对象。如果一部分内容在屏幕上一个与窗口对齐的矩形区域中显示视频,那么您应该使用StageVideo对象,如果一部分内容在视频上执行复杂的变换,那么应该使用较慢的Video对象。
因为StageVideo对象是新的,网络上的所有现有内容都是用的是Video对象。当该内容在使用低功耗CPU的高分辨率设备上显示时,结果有时不太理想。
为了解决此问题,Adobe已决定进行短期的妥协。在Google TV和AIR for TV平台上,将使用与StageVideo对象所用代码路径相同的路径渲染Video对象。因此,Video对象将具有与StageVideo对象相同的性能,但它仍然受到同样的限制。如果将任何不受支持的功能(本文"舞台视频简介"一节中已列出)应用到Video对象,这些功能将被忽略。例如,如果Video对象的alpha对象设置为0.5,那么会像alpha属性被设置为1一样渲染视频。
如果您尝试同时在多个Video对象中播放多个视频,那么只有一个或两个视频会同时播放。每次调用NetStream.play()都会导致一个新视频开始播放,而其他视频将停止。
在未来的版本中,Adobe将会恢复Video对象原始的期望行为。当Video对象的原始行为恢复之后,它的渲染速度将更慢。另一方面,StageVideo将始终最大化所有平台上的性能、最大化质量并最小化能耗。因此,应该将StageVideo对象应用于任何不依赖于复杂变换或渲染效果的视频内容。
FLASH PLATFORM的一般优化
本文介绍了适用于针对Flash Player on Google TV或Adobe AIR on TV进行开发的开发人员的具体优化方法。请注意,另一篇名为Optimizing performance for the Adobe Flash Platform*(PDF,3.8 MB)的文章介绍了许多适用于任何嵌入式系统环境的一般优化方法。不要错过,该文章介绍了多种先进技术,涵盖从对象池到手动位图缓存等内容。这些技术将改进在Flash Player中查看您的内容时的性能。
Google TV或Samsung联网电视等设备上的Flash Player和AIR支持对H.264视频进行硬件加速。作为针对GPU加速设备进行开发的ActionScript开发人员,要获得最佳的性能,您应该了解一些需要避免的事项。文章Flash Player 10.1 hardware acceleration for video and graphics*介绍了Flash运行时中的硬件加速功能的技术细节。
您可以在许多资源中了解如何改进ActionScript的性能。Adobe建议在嵌入式平台上使用ActionScript 3,因为Flash可以充分利用ActionScript 3所实现的改进的性能特征:
随着Flash Player和AIR在各种屏幕和各种类型的设备上普及,Flash内容需要意识到它将在任何类型的屏幕(任何尺寸)上运行。AIR应用程序可以设计来在移动电话、桌面计算机、电视或平板计算机上运行。访问您网站的人可能来自Android电话、Google TV或桌面计算机。认识到所有这些设备之间的区别,并利用Flash Platform平台,您能够构建多屏幕应用程序。这些应用程序不断尊重设备,而且允许作为内容开发人员的您共享您的许多代码,以便降低针对该设备进行优化的成本,或者在理想情况下什么都不用做。
考虑一个电视屏幕。电视仅提供了较少的屏幕分辨率供内容支持,包括960 × 540、1280 × 720(720p)或1920 × 1080(1080p)。甚至使用3种基本的电视屏幕分辨率,您的内容也需要解决许多输入方法(鼠标、遥控器、自由运动的操作杆、混合键盘等)和CPU/GPU性能特征之间的差异,才能供用户访问。
要确保您用于Flash的视频内容能够适当处理不同的屏幕尺寸和调整常见行为,请确保您阅读了文章为多个屏幕大小创作移动 Flash 内容,它介绍了基本的知识。
视频播放器和渲染优化
除了恰当地编码您的视频流,优化您的视频播放器和相关内容也非常重要。如果您的视频播放器使用了太多CPU周期,那么它可能影响视频回放的帧率,或者可能导致用户界面不流畅。
低效的视频播放器通常是由执行过量脚本和过量渲染导致的。以下各节介绍一些视频播放器优化方法,它们可能对显著提升电视性能有所帮助。
简化渲染复杂性
尽可能减少Stage上的对象数量。例如,使用简单的填充样式(比如简单的矩形实色形状,而不是渐变色或多条细线)简化基本按钮的形状。尤其谨慎使用耗资源的渲染功能,比如滤镜。如果播放头(playhead)等形状会不断改变形状或位置,那么应该尽可能少地更新它们——每秒不超过一两次。
不要将wmode设置为"transparent"
这个参数适用于您的目标是Google TV或任何其他在电视类设备中嵌入了Flash Player的平台。在这种情况下,视频播放器SWF文件使用object和embed标记组合嵌入在HTML页面中。如果这些标记包含wmode参数,那么确保该参数的值设置为了"direct"。一些平台上可能支持其他wmode值,但对它们的支持不一致。重叠的SWF文件彼此不会正确叠放,也不会与其他HTML元素正确叠放。
限制使用计时器函数并检查重复
这里的目的是最小化ActionScript处理间隔:enterFrame处理函数、向NetStream注册的回调函数、鼠标事件处理函数和其他此类函数。当注册计时器函数时,将尽可能频繁地调用它,直到达到请求的速率;Flash Player最终可能将其所有时间用于执行脚本,而不是绘制视频帧。对于更新UI组件的计时器函数尤其如此,它们会触发重新绘制,这是非常消耗资源的操作。
不要渲染当前不可见的内容
如果如果一个对象在Stage上隐藏或位于另一个对象之后,那么Flash渲染器仍将浪费时间来渲染隐藏的对象(例如计算它的边框)。如果您希望使一个对象不可见,不要将隐藏在另一个对象背后,将它移离Stage,将它的alpha属性设置为0,或者将它的可视属性设置为false。相反,应调用removeChild()从显示列表中完整地删除该对象。另外,确保停止了任何隐藏对象的时间轴。
当视频完成时关闭NetStream
如果与一个NetStream对象关联的视频已完成播放,则调用NetStream.close()方法。这使Flash运行时能够更好地管理视频资源。
最小化频繁变化的对象的位图缓存
在频繁更新的对象上避免位图缓存(通过cacheAsBitmap属性)。当启用了位图缓存时,每次更新对象都需要重新缓存位图(一个非常耗资源的操作)。例如,频繁更新的文本字段不应该启用位图缓存,因为这会影响视频回放速度。
避免透明效果
尽可能避免透明或将透明对象限制在较小的区域。例如,将透明的覆盖广告转换为播放前或播放后的广告可能更适合。
避免绘图API
绘图API调用特别占用资源,因为它们通常在渲染滚动栏等对象前通过栅格化工具在Stage上动态创建它们。而且,这些对象在每次执行ActionScript时都会销毁并重新创建。如果可能,在创作时在Stage上静态创建这些对象,它们位于不同时间轴的内存中。
提升ActionScript效率
计算机科学编码优化适用于ActionScript,示例包括避免大循环,减少函数调用深度以及简化面向对象类的设计。Adobe提供了一些提升ActionScript性能的最佳实践。由于许多视频播放器的行为,它们可能在视频回放期间执行大量脚本。如果CPU完全用于执行ActionScript,那么执行ActionScript所消耗的时间可能导致视频回放问题。
避免以非常短的时间间隔(比如短语一次帧更新)使用ActionScript计时器,或者在任何处理函数中花费大量时间。对于Flash Player,从ActionScript到JavaScript的调用可能非常耗资源,不应该在视频回放期间定期执行。而且还需要避免过于频繁地清除LocalObject。只有在一个页面上的SWF文件之间通信时才需要这么做。如果您的目标是在一个页面上的SWF文件之间通信,LocalConnection是一个性能更高的选择。
用户界面指南
考虑典型的家用电器。电视位于房间的中央,并与各种设备相连。起居室里可能有一个或许多人,一些人在看电视,其他人在参加其他活动,但也在起居室里。您的应用程序处于一种非常独特的环境中,与运行Flash的任何其他类型的平台都不同。电视是各种人和家庭成员共享的唯一的消费电子设备。与移动电话、台式计算机或笔记本计算机不同,电视不需要有"所有者",打开它的任何可能不是关闭它的人。
因此,您的应用程序和视频播放器的用户界面应该针对电视机和起居室环境而优化。如果您正在创建一款游戏,一个人可以从另一个人离开的位置接着玩,或者如果您正在构建一个视频播放器,播放/暂停状态可能在用户之间转换,那么会发生什么?
您的用户可能坐在离屏幕10-15英尺的位置,而且手中的设备可能不是鼠标和QWERTY键盘,可能是一个遥控器。它甚至可能是一个混合型遥控器,或者可能是一部移动电话。房间里可能是黑的,所以画面需要简单明了,字体和颜色需要清晰可辨。字体大小需要在10英尺外可读,通常某个人会看一眼就迅速按了遥控器上的按钮,调出该应用程序。
对于大部分UI,一种常见做法是在200毫秒内迅速响应按钮单击,这样就必须预先缓存用户工作流程中可能包含的项,以为用户提供最优的体验。很容易将电视想象为另一台PC类设备,但同样重要的是,考虑电视的发展历史和数十年来成年人和孩子是如何被告知电视应有的行为和操作的。人们期望电视是一台娱乐设备,无论是用于靠在沙发上观看视频还是坐在前面玩游戏。例如,要求遣散人们的通知会影响人们以娱乐为导向的期望,因为消费者只是希望他们的电视能够工作。考虑尽可能少地使用模态对话框和简化用户体验,以突出娱乐重点。在设计您的应用程序和任何用户界面时应考虑到所有这些因素。
内容保护指南
Google TV设备和AIR for TV设备支持对付费视频内容进行Flash Platform内容保护。
从Flash Media Server(FMS)安全地传输视频可以使用RTMPE(Real Time Media Protocol Encrypted,加密的实时媒体协议)和SWF Verification来实现,目前已有许多领先的付费视频提供商使用它们来提供无缝的观看体验。FMS中的内容保护功能受众多主流内容传送网络(CDN)支持,实现了轻松的内容工作流程和大范围的地理区域覆盖。
Adobe推出了一款内容保护解决方案Adobe Flash Access 2,它可以提供更高级别的保护、更高的灵活性和新的内容商业化机会。Flash Access同时适用于下载和传输,拥有来自Adobe的FMS或新的HTTP Dynamic Streaming协议。Flash Access可用于启用了AIR for TV的设备,将包含在即将面世的Google TV版本中。
作为开发人员,您可能在开发端到端解决方案,后者仅仅是用户体验设计和实现。对于有着,实现对RTMPE和Flash Access的支持不需要多大功夫。Adobe Developer Connection上的白皮书Protecting online video distribution with Adobe Flash media technology*概述了使用RTMPE、SWF Verification和相关功能的典型内容保护工作流程。
Flash Access不但提供了一个服务器SDK来创建与您现有的后端(比如用户数据库和支付处理器)集成的内容保护解决方案,还提供了一个集成了Flash Player(如果可用)的客户端。白秘书Adobe Flash Access overview on protected streaming*(PDF,319 KB)介绍了在各种工作流程中使用Flash Access,而Flash Access 2.0 Help Resource Center*提供了与服务器组件相关的更多详细信息和文档。
在客户端,Flash Access引入了一些ActionScript API,可用于控制内容许可、用户身份验证(如果需要)和其他功能的获得。查看以下资源:
- flash.net.drm package classes*(API documentation)
- Rich media content: Using digital rights management*(ActionScript 3 Developer's Guide)
- flash.net.drm包类*(API文档)
- 富媒体内容:使用数字版权管理*(ActionScript 3开发人员指南)
基于目标设备自定义FLASH PLAYER
要在用户观看电视时为他们提供最优体验,您可能需要重新编码您的视频流或自定义您的视频播放器的用户界面。与此同时,您还需要在桌面计算机和智能电话上继续提供最优体验,它们可能需要不同的视频编码或不同的用户界面。
因此,您需要向您的网站添加某种条件逻辑,针对显示设备调整网页。此条件逻辑可以包含在您的Web服务器上、在您的HTML页面中运行的JavaScript中,或者在您的SWF文件中运行的ActionScript中。
在服务器上检测
当Web浏览器发出HTTP请求时,它在请求头部插入一些信息。一个插入的字段称为"user-agent"。user-agent字段描述运行该浏览器的设备。
通过向Web浏览器添加逻辑,在检测电视浏览器的user-agent字符串时,您可以提供一个电视专用的HTML页面。将浏览器重定向到服务器上的电视专用页面的一种不错方式是使用HTTP Redirect。Apache手册中包含"Redirect"指令*的更多信息,Microsoft IIS文档*中也包含关于重定向的更多信息。此外,John Boxall的移动设备检测网站*提供了一些执行设备检测的示例脚本。
请注意,user-agent的内容将因设备不同而异,在设备上的软件更新时可能更改。新设备和软件的更新非常频繁,所以您应该相应地计划更新您的服务器端逻辑。
在JavaScript中检测
第二个选项是在HTML页面中的JavaScript代码中包含相同的user-agent逻辑。根据它检测的用户代理,它可以使用document.write方法嵌入针对设备而设计的SWF文件。在这种情况下,您的网站仅包含HTML页面的一个版本,但向每
上面已经提到,依赖于user-agent字符串的代码将不适用于未来的代理字符串。此外,该代码可能运行缓慢,因为需要进行大量字符串比较。使用JavaScript方法的优势在于能够检测特定设备和操作系统,帮助您充分利用平台的具体功能。关于user-agent字符串和如何使用它们的更多信息,请查看Mozilla.org上关于浏览器检测和跨浏览器支持*的信息。
要克服在您的JavaScript中保存用户代理的静态特性,可以使用WURFL*,该服务将用户代理映射到设备功能。如果您尝试使用JavaScript检测浏览您网站的设备的特定属性,那么这样做可能很有用。
在ActionScript中检测
第三个选项是在SWF文件中的ActionScript代码中包含检测逻辑。当使用此选项时,会将单个HTML页面版本和单个SWF文件版本传送给所有服务。在SWF文件内,ActionScript代码确定目标设备的类型,请求适合该设备的视频流,并为该设备自定义视频播放器用户界面。
Flash Player提供了许多有用的ActionScript属性来收集关于目标设备的信息:
- Capabilities.cpuArchitecture
- Capabilities.os
- Capabilities.screenDPI
- Capabilities.screenResolutionX , Capabilities.screenResolutionY
- Capabilities.touchscreenType
- Mouse.supportsCursor
在Google TV上,Capabilities.os属性设置为GTV,您可以据此推断一款具有高分辨率和Capabilities.os=="GTV"的基于Intel的Android设备是一款Google TV设备。
在其他电视平台上,包括AIR for TV,Capabilities类返回的数据因底层硬件不同而异。您可以使用Capabilities类中的信息做出各种回放和渲染决定。
这项战略需要进行猜测,它并不总是支持内容识别准确的目标设备型号,但它比硬编码user-agent字符串的解决方案更适合未来的需求。
未来步骤
Flash Player现在可用于Google TV,AIR for TV很快将可用于Samsung TV和蓝光设备,所以您可以提供用户在另外的屏幕上喜爱的视频体验。尽管您将能够利用来自针对Flash Player的现有项目的许多资产,但您可能需要针对电视自定义您的视频流和视频播放器。
我们将更新本文和优化电视上的Flash Platform的技巧和方法。请定期查阅本文,查看Adobe发布的更新。
请查阅以下资源了解更多信息:
关于作者
此内容由 Adobe Systems, Inc. 编写。
ADC中文站原文地址: http://www.adobe.com/cn/devnet/devices/articles/video_content_tv.html#02

.gif)
.gif)




.gif)
发表新评论