Chapter 4. Audio and Video Enhancements

Since the YouTube video revolution of 2006, Flash has been the premiere method of video delivery through web browsers, avoiding the fragmentation that otherwise persisted as a result of warring codecs and players. The VP6 Flash Video (FLV) format standardized most video playback over the Web in alignment with Flash Player. Over the years, different container formats and codecs have been added to the Flash Player to keep up with industry trends, including H.264 decoding with Flash Player 9. With Flash Player 11, we have a set of new enhancements to take advantage of.

H.264/AVC Software Encoding for Cameras

With Flash Player 11, developers now have the ability to encode H.264 video streams within the Flash Player itself. Prior versions of the runtime were able to decode H.264 and with the additional encoding functionality, a whole other set of applications can be built to record and broadcast in this industry standard format.

Warning

H.264/AVC software encoding is only available on the desktop. Mobile devices cannot utilize this feature due to the amount of CPU it takes to encode the streams.

To compile and run the examples included below effectively, it is recommended that you install Flash Media Server.

Note

Note that if you do not have access to a commercial license for Flash Media Server, Adobe does offer a free developer edition with which you can test this and other examples. When doing any serious work through FMS, it is encouraged that you begin with a local development instance such as this.

Flash Media Server developer edition can be acquired from Adobe via http://www.adobe.com/products/flashmediaserver/

Warning

Flash Media Server is available for either Windows or Linux.

Encoding H.264 within Flash Player 11

To encode a video stream using H.264 within Flash Player 11, we must employ the new H264VideoStreamSettings class and associated objects. When constructing a H264VideoStreamSettings instance for use in our project, we can set the particular profile and level of the encoding. This is useful for targeting certain specific devices which may only support something like baseline encoding. Once we have configured our H264VideoStreamSettings instance, we assign it to the videoStreamSettings property of a NetStream instance and then process the stream as normal.

package {
    import flash.display.Sprite;
    import flash.events.NetStatusEvent;
    import flash.media.Camera;
    import flash.media.H264Level;
    import flash.media.H264Profile;
    import flash.media.H264VideoStreamSettings;
    import flash.media.Video;
    import flash.net.NetConnection;
    import flash.net.NetStream;
    import flash.text.TextField;
    import flash.text.TextFormat;

    [SWF(width="600", height="500", backgroundColor="#CCCCCC")]

    public class AVCEncode extends Sprite {

        private var traceField:TextField;
        private var video:Video;
        private var camera:Camera;
        private var connection:NetConnection;
        private var stream:NetStream;
        private var streamClient:Object;

        public function AVCEncode() {
            generateDisplayObjects();
            performOperations();
        }

        protected function generateDisplayObjects():void {
            video = new Video(stage.stageWidth, stage.stageHeight);
            addChild(video);

            var defaultFormat:TextFormat = new TextFormat();
            defaultFormat.font = "Arial";
            defaultFormat.size = 24;
            defaultFormat.color = 0xFFFFFF;

            traceField = new TextField();
            traceField.backgroundColor = 0x000000;
            traceField.alpha = 0.7;
            traceField.autoSize = "left";
            traceField.background = true;
            traceField.defaultTextFormat = defaultFormat;
            addChild(traceField);
        }

        protected function performOperations():void {
            camera = Camera.getCamera();
            camera.setMode(stage.stageWidth, stage.stageHeight, 30);
            camera.setQuality(60000, 80);
            video.attachCamera(camera);

            streamClient = new Object();
            streamClient.onBWDone = onBWDone;

            connection = new NetConnection();
            connection.client = streamClient;
            connection.addEventListener(NetStatusEvent.NET_STATUS, monitorStatus);
            connection.connect("rtmp://localhost/live");
        }

        protected function monitorStatus(e:NetStatusEvent):void {
            traceField.appendText(e.info.code + "\n");
            if(e.info.code == "NetConnection.Connect.Success"){
                beginStreaming();
            }else if(e.info.code == "NetStream.Publish.Start"){
                traceField.appendText("\n" + e.info.description + "\n");
                traceField.appendText("codec: " + stream.videoStreamSettings.codec);
            }
        }

        protected function beginStreaming():void {
            var h264Settings:H264VideoStreamSettings = new H264VideoStreamSettings();
            h264Settings.setProfileLevel(H264Profile.BASELINE, H264Level.LEVEL_2);

            stream = new NetStream(connection);
            stream.addEventListener(NetStatusEvent.NET_STATUS, monitorStatus);
            stream.videoStreamSettings = h264Settings;
            stream.attachCamera(camera);
            stream.publish("mp4:h264livestream.f4v", "live");
        }

        public function onBWDone():void {}

    }
}

So long as we have Flash Media Server installed and running on our local machine, we will receive a message stating that the stream is being published and that the codec being used to encode the video is H.264, along with a preview of the camera feed. In this example, we are simply viewing the raw camera output and not the encoded stream.

H.264 Encoding within Flash Player

Figure 4-1. H.264 Encoding within Flash Player

Reading an H.264 Stream into Flash Player 11

The ability to decode H.264 has been available since Flash Player 9. To play back a stream or file encoded to H.264 with Flash Player 11 is the same procedure we would normally use. First, create a NetConnection and establish a connection to Flash Media Server. In this case, we use rtmp://localhost/live, as the server exists on the same machine. We then hook in a NetStream object and request to play the previously published stream.

package {
    import flash.display.Sprite;
    import flash.events.NetStatusEvent;
    import flash.media.Video;
    import flash.net.NetConnection;
    import flash.net.NetStream;
    import flash.text.TextField;
    import flash.text.TextFormat;

    [SWF(width="600", height="500", backgroundColor="#CCCCCC")]

    public class AVCPlayback extends Sprite {

        private var traceField:TextField;
        private var video:Video;
        private var connection:NetConnection;
        private var stream:NetStream;
        private var streamClient:Object;

        public function AVCPlayback() {
            generateDisplayObjects();
            performOperations();
        }

        protected function generateDisplayObjects():void {
            video = new Video(stage.stageWidth, stage.stageHeight);
            addChild(video);

            var defaultFormat:TextFormat = new TextFormat();
            defaultFormat.font = "Arial";
            defaultFormat.size = 24;
            defaultFormat.color = 0xFFFFFF;

            traceField = new TextField();
            traceField.backgroundColor = 0x000000;
            traceField.alpha = 0.7;
            traceField.autoSize = "left";
            traceField.background = true;
            traceField.defaultTextFormat = defaultFormat;
            addChild(traceField);
        }

        protected function performOperations():void {
            streamClient = new Object();
            streamClient.onBWDone = onBWDone;

            connection = new NetConnection();
            connection.client = streamClient;
            connection.addEventListener(NetStatusEvent.NET_STATUS, monitorStatus);
            connection.connect("rtmp://localhost/live");
        }

        protected function monitorStatus(e:NetStatusEvent):void {
            traceField.appendText(e.info.code + "\n");
            if(e.info.code == "NetConnection.Connect.Success"){
                beginStreaming();
            }
        }

        protected function beginStreaming():void {
            stream = new NetStream(connection);
            stream.addEventListener(NetStatusEvent.NET_STATUS, monitorStatus);
            stream.play("mp4:h264livestream.f4v");
            video.attachNetStream(stream);
        }

        public function onBWDone():void {}
    }
}

When this class is compiled to SWF, so long as we have the encoded stream successfully published to Flash Media Server through the previous code example, we will see the published, natively encoded H.264 stream render through a Video object similar to Figure 4-2.

Decoded H.264 from Flash Player 11 encoded stream

Figure 4-2. Decoded H.264 from Flash Player 11 encoded stream

Get What's New in Flash Player 11 now with the O’Reilly learning platform.

O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.