Skip to main content
Inspiring
September 21, 2012
Question

Video playback on Android 4.1.1 (Nexus 7)

  • September 21, 2012
  • 3 replies
  • 1301 views

Hi,

I've seen a few threads about video playback, but I thought this issue was a tad bit different.

I need video in a somewhat larger AIR on Android project. For video playback I'm using an altered version of Thibault Imbert's stageVideo example script from devnet (which works flawless on iOS).

(see code below)

On Android however I experience these issues:

* In the larger project loading of the video takes about 10 seconds. In a barebones project loading takes about 1, max 2 seconds.

* Trying to see what loadtimes would be without GPU rendering I stripped the class of all it's stageVideo stuff. However, on the device it still states the VideoEvent.RENDER_STATE's status is 'accelerated'. No matter what I set the app-descriptor's rendemode to. On the desktop it states 'software' as status.

Questions:

* Would it be a memory thing and how can I see what the memory usage is on the Nexus?

* How come the Nexus uses accelerated as rendermode no matter what the descriptor's rendemode is and the lack of code referring to stageVideo?

Thanks in advance

Manno

package {      import flash.display.Sprite;      import flash.display.StageAlign;      import flash.display.StageScaleMode;      import flash.media.Video;      import flash.net.NetConnection;      import flash.net.NetStream;      import flash.system.Capabilities;            public class AndroidVideoTest extends Sprite      {           private var v:Video;           public function AndroidVideoTest()           {                super();                                // support autoOrients                stage.align = StageAlign.TOP_LEFT;                stage.scaleMode = StageScaleMode.NO_SCALE;                                var vpb:VideoPlayback = new VideoPlayback( "Movie001.mp4" );                                addChild( vpb );                                vpb.playVideo();           }      } }

package {      import flash.display.Sprite;      import flash.events.Event;      import flash.events.MouseEvent;      import flash.events.NetStatusEvent;      import flash.events.VideoEvent;      import flash.geom.Rectangle;      import flash.media.Video;      import flash.net.NetConnection;      import flash.net.NetStream;      import flash.text.TextField;      import flash.text.TextFieldAutoSize;            /**       *       * @author Thibault Imbert       *       */           public class VideoPlayback extends Sprite      {           private var fileName:String = "";                      private var legend:TextField = new TextField();           private var nc:NetConnection;           private var ns:NetStream;           private var rc:Rectangle;           private var video:Video;                      private var infos:String = new String();           private var played:Boolean;                      /**            * Constructor, feed it file to play            */           public function VideoPlayback( fname:String = null )           {                     if ( fname != null )                     fileName = fname;           }                      /**            * Have it play            *            */           public function playVideo():void           {                if( stage )                     init( null );                else                     addEventListener( Event.ADDED_TO_STAGE, init, false, 0, true );           }                      /**            *            * @param event            *            */                     private function init( event:Event ):void           {                if( event )                     removeEventListener( Event.ADDED_TO_STAGE, init );                                addEventListener( Event.REMOVED_FROM_STAGE, cleanUp );                                // Debug infos                legend.autoSize = TextFieldAutoSize.LEFT;                legend.multiline = true;                legend.background = true;                legend.backgroundColor = 0xCCCCCC;                addChild(legend);                                // Connections                nc = new NetConnection();                nc.connect( null );                ns = new NetStream( nc );                ns.addEventListener( NetStatusEvent.NET_STATUS, onNetStatus, false, 0, true );                ns.client = this;                                // Screen                video = new Video();                video.smoothing = true;                                // Video Events                // 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, false, 0, true );                                playStandardVideo();           }                      /**            * Housekeeping tasks            *             * @param event            *            */                     protected function cleanUp(event:Event):void           {                removeEventListener( Event.REMOVED_FROM_STAGE, cleanUp );                                video.removeEventListener( VideoEvent.RENDER_STATE, videoStateChange );                ns.close();                ns.removeEventListener( NetStatusEvent.NET_STATUS, onNetStatus );                nc.close();           }                      /**            *            * @param event            *            */                     private function onNetStatus(event:NetStatusEvent):void           {                if ( event.info == "NetStream.Play.StreamNotFound" )                     trace( "Video file passed, not available!" );           }                      /**            * Calculate largest rect fitting the screen            * @param width            * @param height            * @return Rectangle            *            */                     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;                                var videoRect:Rectangle = new Rectangle(0, 0, 0, 0);                videoRect.x = posX;                videoRect.y = posY;                videoRect.width = videoWidth;                videoRect.height = videoHeight;                                return videoRect;           }                      /**            *            *            */                     private function resize ():void           {                     // 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;                                legend.text = infos;           }                      /**            * start video playback with 'classic' video            */                     private function playStandardVideo( ):void           {                     infos = "Starting playback\n";                                // We attach it to a Video object                video.attachNetStream(ns);                stage.addChildAt(video, 0);                                if ( !played && fileName.length )                {                     played = true;                     ns.play( fileName );                }           }                      /**            *            * @param event            *            */                     private function videoStateChange( event:VideoEvent ):void           {                     infos += "VideoEvent received\n";                infos += "Render State : " + event.status + "\n";                resize();           }                      /****************************            *            * Video eventhandlers            *            ****************************/           public function onMetaData ( evt:Object ):void{}                      public function onXMPData( info:* ):void{}      } }

This topic has been closed for replies.

3 replies

Inspiring
September 22, 2012

BTW (after rereading yesterday's post):

The class above is just the stipped version as a test to make sure no stageVideo was used and see what happend to the VideoEvent.status. Not an attempt to alter Thibaults version and still get StageVideo .

Inspiring
September 21, 2012

Q. Would it be a memory thing and how can I see what the memory usage is on the Nexus?

A. You can use top(1) and ps(1) on a Android device to get process stats but there might be a better way. You must first start a shell on the device with 'adb shell'.

Q. How come the Nexus uses accelerated as rendermode no matter what the descriptor's rendemode is and the lack of code referring to stageVideo?

A. I didn't know the class VideoEvent existed nor that you could register a listener for VideoEvent.RENDER_STATE. I don't see it documented in the reference page for the Video class.

http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/media/Video.html

In any case, the documentation for VideoEvent says this:

"Use this event for the following purposes: [...] To find out whether the video is decoded by software or the GPU. If the status property returns "accelerated", you should switch to using the StageVideo class, if possible.

Learn more"

http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/events/VideoEvent.html

This implies to me that the VideoEvent.status applies to StageVideo and not Video. That is a very odd API design IMHO.


Inspiring
September 22, 2012

Thanks.

About the memory:

I'll take a look into the shell. First week of having the device so it's kinda new ground

About the acceleration (or not)

*blush* I never bothered to look into the actual docs. Since on desktop it kindly reported "software" when on CPU and "accelerated" when in direct mode, I assumed it did what I expected. Sigh: "Never just assume...".

the 'status' of "accelerated" is more an advice to make it so, or so it seems...