• January 14, 2012
  • Jens Loeffler
  • 59

My guide to advanced video delivery with AIR for mobile resulted in a lot of interest, but also in the question how to exactly achieve 720p video quality on tablets, and the request for an encoding example with the corresponding player.

Here are two examples applications, one raw player without any framework, and a second with OSMF, both running on an iPad 1 and the Motorola Xoom.

 

Simple Video Player

package
{
	import flash.desktop.NativeApplication;
	import flash.desktop.SystemIdleMode;
	import flash.display.Sprite;
	import flash.display.StageAlign;
	import flash.display.StageScaleMode;
	import flash.events.Event;
	import flash.events.StageVideoAvailabilityEvent;
	import flash.geom.Rectangle;
	import flash.media.StageVideo;
	import flash.media.StageVideoAvailability;
	import flash.net.NetConnection;
	import flash.net.NetStream;
 
	[SWF(backgroundColor="#000000")]
	public dynamic class AIRMobileVideo_AS extends Sprite
	{
		public function AIRMobileVideo_AS()
		{
			NativeApplication.nativeApplication.systemIdleMode = SystemIdleMode.KEEP_AWAKE;
			NativeApplication.nativeApplication.addEventListener(Event.DEACTIVATE, handleDeactivate, false, 0, true)
 
			stage.align = StageAlign.TOP_LEFT;
			stage.scaleMode = StageScaleMode.NO_SCALE ;
			stage.addEventListener( StageVideoAvailabilityEvent.STAGE_VIDEO_AVAILABILITY , stageVideoState );
		}
		protected var stream:NetStream ;
 
		protected function stageVideoState( e:StageVideoAvailabilityEvent ):void
		{
			var available:Boolean = e.availability == StageVideoAvailability.AVAILABLE ;
 
			if ( available )
			{
				var nc:NetConnection = new NetConnection() ;
				nc.connect(null) ;
				stream = new NetStream(nc) ;
				stream.client = this ;
				var video:StageVideo = stage.stageVideos[0] ;
				video.viewPort = new Rectangle( 0, 0, 1280 , 720 ) ;
				video.attachNetStream( stream ) ;
				stream.play( "http://www.overdigital.com/video/Hillman_720p23.976_2400kbps.mp4") ;
			}
 
		}
 
		public function onMetaData( info:Object ):void
		{
 
		}
 
		private function handleActivate(event:Event):void
		{
			NativeApplication.nativeApplication.systemIdleMode = SystemIdleMode.KEEP_AWAKE;
		}
 
		private function handleDeactivate(event:Event):void
		{
			NativeApplication.nativeApplication.exit();
		}			
 
	}
}

Source: AIRMobileVideo_AS

 

Video Player based on OSMF

package
{
	import flash.desktop.NativeApplication;
	import flash.desktop.SystemIdleMode;
	import flash.display.Sprite;
	import flash.display.StageAlign;
	import flash.display.StageScaleMode;
	import flash.events.Event;
 
	import org.osmf.containers.MediaContainer;
	import org.osmf.elements.VideoElement;
	import org.osmf.media.MediaPlayer;
	import org.osmf.media.URLResource;
 
	[SWF(backgroundColor="#000000")]
 
	public dynamic class AIRMobileVideo_OSMF extends Sprite
 
	{
		public function AIRMobileVideo_OSMF()
		{
			stage.scaleMode = StageScaleMode.NO_SCALE;
			stage.align = StageAlign.TOP_LEFT;
 
			NativeApplication.nativeApplication.systemIdleMode = SystemIdleMode.KEEP_AWAKE;
			NativeApplication.nativeApplication.addEventListener(Event.DEACTIVATE, handleDeactivate, false, 0, true)
 
			var videoPath:String = "http://www.overdigital.com/video/Hillman_720p23.976_2400kbps.mp4";
			var resource:URLResource = new URLResource( videoPath );
			var element:VideoElement = new VideoElement( resource );
			var mediaPlayer:MediaPlayer = new MediaPlayer( element );
			var mediaContainer:MediaContainer = new MediaContainer();
			mediaContainer.addMediaElement( element );
			addChild( mediaContainer );
 
		}	
 
		private function handleActivate(event:Event):void
		{
			NativeApplication.nativeApplication.systemIdleMode = SystemIdleMode.KEEP_AWAKE;
 
		}
 
		private function handleDeactivate(event:Event):void
		{
			NativeApplication.nativeApplication.exit();
		}			
 
	}
}

Source: AIRMobileVideo_OSMF

 

The OSMF version on both tablets.

 

Considerations

  • Ensure videos are mobile optimized, since mobile HW decoders likely don’t support all levels or profiles of H.264. Follow the encoding cookbook, and the mobile encoding guidelines.
  • Make sure to use the StageVideo API if you use an AS only approach, or the latest OSMF version which has build-in StageVideo support. Define <renderMode>direct</renderMode> in the Adobe AIR application xml file to enable StageVideo.
  • Consider adaptive streaming to adjust to less consistent mobile networks, as example HTTP Dynamic Streaming on Android, or HLS streaming on iOS.

Update 01/27/12: If you use the captive runtime approach, please update Flash Builder/Flash to the latest AIR version for 720p Android playback (AIR 3.1.0.5560 or higher)

Jens Loeffler

Author of Overdigital.net. The views/posts are my personal opinion.

http://www.overdigital.net

59 comments on “Source Code – 720p Video on iPad and Android Tablets with Adobe AIR

  1. Hi, I’m trying to use this in a flex mobile application (flex 4.6).
    it work when I test on desktop iPad simulator but not on the devise. I even used your mp4 in order to avoid encoder problem.
    I’m non able to make iOS play mp4 video. And can’t get any information on how to do this.
    It would be great if you could post a sample code of how to do this with a flex project.
     
    Thanks

    1.  @PaoloBernardin1 Does it work on the actual device? The simular could cause some issues, since it’s a simulator, and not a real emulator. With Flex you also need to hide the background (set it 0 alpha) when using StageVideo.

      1.  @Jens Loeffler 
        What if you’re buildiing an as3 mobile project, how do you set the background alpha to 0?

  2. I have been able to get the OSMF sample to work with a progressive download, but not with an HLS stream (sourced from my Wowza streaming server). The same HLS url will play on the iPod Touch / iPad 2 directly in QT player (using browser to load it).
     
    I did alter the OSMF sample to use a media factory to create the media element, but no dice.

    1.  @JimInspired Hi Jim. I assume this is on iOS. Did you set renderMode to direct? In addition, does your HLS URL end with .m3u8? Please also make sure you don’t use autoPlay, there is currently an issue. 

    2.  @JimInspired FYI, I can get HLS stream to play in the non-OSMF sample. I’ve done a bunch of research and from what I can tell, OSMF does not support HLS streams.

  3. I’m using iPad iOS 5.1 with Flash builder 4.6. I’m trying building an iPad app holding a list and videos in its itemrenderer components.
     
    The code that I’m using to use the StageVideo is working pretty well when using outside the List/itemRenderer component, that means in the same View class. The video is coming as expectedly and playing on iPad. But whenever I’m trying to call the same code inside an itemrenderer object, the app crash.
     
    The code snippets as you described:
     
                   var available:Boolean = e.availability == StageVideoAvailability.AVAILABLE ;
     
                                            if ( available )
                                            {
                                                      var nc:NetConnection = new NetConnection() ;
                                                      nc.connect(null) ;
                                                      stream = new NetStream(nc) ;
                                                      stream.client = this;
                                                      var video:StageVideo = stage.stageVideos[0] ;
                                                      video.viewPort = new Rectangle( 0, 0, 622 , 480 ) ;
                                                      video.attachNetStream( stream ) ;
                                                      stream.play( new File(new File(“app:/elements/video/FoxTraveller_NIB.mp4”).nativePath).url ) ;
     
                                            }
     
    I’ve noticed that available field coming as ‘available’ but it instantly crash.
     
    Any help would be highly appreciated! Please.
     
    Thanks & Kind Regards.

      1. @Jens Loeffler Hi, thanks! Actually it was my fault, a few associated methods with the stream.client which generally ‘not’ requires to explicitly code while in View component but in a ItemRenderer component (here the stream client bind with the ItemRenderer). In my case those methods weren’t present so it was actually crashing while running in device, I found it after debug mode. Now since the methods are not present in the ItemRenderer component, it works as expected. Thanks.

  4. Hey, 
     
    Thanks for this great article.
    I would like to know if I have to use the stageVideo API or if it could work without it. Basically, I would like user could slide video by touching the screen. Thanks !
     

    1.  @starchicken  Yes, you have to use StageVideo, otherwise the performance won’t be good. You can move the video object around though by modifying the StageVideo view area – there is an example in this article. http://www.overdigital.com/2012/01/09/the-ultimate-guide-to-understanding-advanced-video-delivery-with-air-for-mobile/

  5. Hi jens, thanks for the article.
     
     I tested the version based on OSMF. In my Ipad runs perfectly. I do not have an Android tablet and failing I used Samsung GT-I9000 Galaxy, the video load but soon after the application quits playing. I do not know if this device is suitable for such applications. Can you say something about it? 
     
    Greetings
     
    PD. Sorry for my bad English

    1.  @tonilopez It should work – what is the video you are testing with? You could also try to use AIR 3.3 from Adobe Labs – http://labs.adobe.com/technologies/flashplatformruntimes/air3-3/

  6. I’m still not able to make it work in a flash builder project, I get not error, but i can’t see the video play on the device.
    would you mind posting a flash builder project sample?

    1.  @PaoloBernardin1 You should be able to import the examples into Flash Builder (it was created with Flash Builder). Do you hear audio? Make sure to set renderMode to direct on Android (or direct/gpu on iOS), and if you use the Flex framework, set the background alpha of the application to 0. 

      1.  @Jens Loeffler Actually I was able to make it work by updating to air 3.2 and to the latest release of osmf.swc.
        But the video (i’m using your mp4 as a test) doesn’t run very smooth.
        Plus are there any controls available for the mediaplayer or we have to implement it ourselves?
        Thanks for you help

        1.  @PaoloBernardin1 What device are you testing on? The 720p video only runs smoothly on tablets and ICS, for Android 2.x smartphones you have to follow the Android encoding guidelines (http://www.adobe.com/devnet/devices/articles/encoding-guidelines-android.html) – the smartphone (Android 2.x) rule is basically not higher than 640×360, and no excessive bitrates. Strobe Media Playback has a mobile touch skin, more information here: http://sourceforge.net/apps/mediawiki/osmf.adobe/index.php?title=HTML5_%26_JavaScript_support_for_SMP. Also on Android tablets + ICS, you have to use renderMode direct in the application.xml, otherwise 720p won’t work.
           
           

        2.  @PaoloBernardin1 That’s indeed odd, on iPad2 with H.264 the video is just passed to the native player. Maybe it stutters because of insufficient bandwidth? 

  7. Thanks for this post.I tried this with rtmp url for playing the live stream.It plays well.But the video doesnot display in full screen rather it display only in corner of the screen..After changing output size in encoder the video enlarges and it doesnot fit in sceen but out of screen..How to make the video display within screen in exact fit to the screen size for any encoder video size?

      1.  @Jens Loeffler 
                     I am using FMLE encoder. Format is H.264,Frame rate15.00,Total bandwidth required to stream 248kbps.
                  I couldn’t display the full video source within the screen but a part of the video only within the screen .

        1. Thank you Jens Loeffler,
           After setting width and height of mediaContainer to the fullscreenwidth and fullscreenheight the video displayed in fullscreen..

  8. I imported the sample code into Flash Builder 4.7 beta and deployed it to an iPad2 (iOS 5.1.1) and a ASUS Transformer (Android 4.0.3). I left the mp4 URL as is. It doesn’t work on either device. On the iPad I observe a NetStream NetStatusEvent “NetStream.Play.Failed”. On the ASUS Transformer, I hear audio but see no video.
     
    I also tried playing the mp4 in the default browser on both devices. It plays on the Transformer but not on the iPad.
     
    By the way, on the Transformer, the app exits immediately. I worked around it by commenting out “NativeApplication.nativeApplication.exit()” in handleDeactivate().
     
    This follows right along with a string of problems I have seen with StageVideo which I summarized on the Adobe AIR mobile development forum.
     
    http://forums.adobe.com/thread/1069285

      1.  @Jens Loeffler Yes, renderMode is set to direct in AIRMobileVideo_AS-app.xml:
         
        <renderMode>direct</renderMode>
         
        Yes, I am using the AIR 3.4 SDK:
         
        <application xmlns=”http://ns.adobe.com/air/application/3.4″>
         

  9. @Jens Loeffler  @PaoloBernardin1 I have set the background alpha to 0 in the main application window, but still no luck. Can you please explain where the background should be set to 0

    1. @kolexinfos  @PaoloBernardin1 Background alpha 0 is for Flex applications. StageVideo is always at the bottom layer, if you have a colored background, it will overlay the video and you won’t see it (audio only). Do you hear audio at all?

    2. @Jens Loeffler  @PaoloBernardin1 I have actually been able to view the video. The challenge as actually that the video element was not been properly be added to the display list which i was able to fix, thanks.

  10. Hi Jens,
     
    Having played around with the StageVideo API a bit now, I have one quick question for you. Is there a way to set the viewport of the classic video object, that AIR has changed into a StageVideo? If yes, I can set it to a 0 width, height rectangle. 
     
    I tried setting viewport of stage.stageVideos[0] but no avail. 
     
    Thanks,
    Pulkit

  11. Hi,

    Thank you for your tutorial.
    I have tested this “Simple Video Player”,
    But I hearing in my Ipad only sound, video is not visible. Ipad Screen is black

    Testing with Flash CS6 and Air 3.7

    What can I do?

    Thanks

  12. Hi Jens,
    How do I add controls to the video player based on OSMF? I know I should be able to do this with the Strobe Media Player, but how? Do you have any examples?

    Thanks in advance for your help.

    1. @pc Are you looking for a skining language, or can you write your own UI? Strobe has more abstract skinning capabilities. There is also a chrome player, i believe in the OSMF repository somewhere which has a skinning approach.
      OSMF is really designed for you to write your own UI code.

      1. Jens Loeffler Thanks for the prompt reply, I can write my own code if I need to I was just looking for an easy example of how to do this.
        I found this link http://www.adobe.com/devnet/flash/articles/mastering-osmf-pt2.html and thought it would help. The problem is it seems to be using an older version of the API or something, when I try to include the classes like ControlBG etc it doesn’t work. So I cannot create the control bar UI in the way they describe. Do you know of an examples that use the latest API? I really only need basic functionality play/pause/showing elapsed time etc.
        Thanks again.

        1. @pc Jens Loeffler Yes, the API changed a lot since the first version this article was written for. Maybe there is something useful in the example app section? http://sourceforge.net/adobe/osmf/svn/2081/tree/osmf/trunk/apps/samples/framework/

  13. Hi,
    Thanks for the tutorial. I have a demo set up based on your OSMF version of the video player. It works on the simulator and on an iPad. My problem is that seeking does not work on the iPad. In the simulator I can skip to various points in the video as long as it is fully buffered, i.e. the whole movie is buffered. When I test the code on an iPad it doesn’t seem to buffer the video, it just starts playing, and I can’t seek to other points. The only point I can seek back to is 0, therefore starting the video again.
    Any thoughts on this?
    Thank you.

      1. Jens Loeffler Hi Jens, I tried the simple video player. I couldn’t get it to work in the simulator because e.availability == unavailable when I tested the code on my desktop. I’m not sure why this should be, I’m using a new iMac. I ran the code on an iPad and it worked fine but this is not so good for testing.

        The OSMF version I created has a sprite to track the buffering. It grows as more of the video is buffered. When the video is fully buffered the scaleX property is 1. In the simulator this works fine, the sprite grows to full width. When I test the code on an iPad the sprite does not grow, so buffering is not happening. I’ve checked the MediaPlayer canBuffer property when running on an iPad and it is true, the canSeek property is also true. Any thoughts on why buffering would not be happening on an iPad? I’m testing on the latest iPad.

        1. @biter Jens Loeffler Some events are not available on AIR for iOS, which is related to how H.264 video playback is implemented on iOS. Under the hood, AIR use the native video framework on IOS, with all it’s features and limitations (e.g. only MP4/MOV or m3u8 playback, not RTMP or HDS). It’s because it was the only way to enable it on iOS, given the API.
          When you are testing it on the desktop, it works with the regular model, meaning all events are available.
          Here is more official information on this: http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/net/NetStream.html -> Unsupported properties

  14. Hi,

    Thanks for the tutorial. I am using Flash Builder 4.7 and Adobe AIR 3.9, will i be able to use your code to play video on my iPad?

    Thank you.

  15. Hi, thank for this example it’s was so helpful, but when I test it using HLS and HDS links its not work, there are any solution for OSMF to make it work in such links.
    Thanks.

  16. on android: true into tag -> now it works perfectly with basic as3 classes without flex or StageVideo or OSMF, just AIRSDK 18.0

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.

banner
Follow

Get every new post delivered to your Inbox

Join other followers: