back

Using the BitmapData class in ActionScript 3.0 to render video

by David Van der Voort and Tommi West

With the release of the ActionScript™ 3.0 language and Adobe Flash® Player 9 software, developers have more tools and features available to them than ever before. New classes have been included and the syntax has been improved to enable true object-oriented programming control and dynamic manipulation of graphic elements.

Video is an integral part of interactive multimedia and engaging applications. FLV files can be displayed in several ways. The fastest way is to use the FLVPlayback component to control video, and the component includes many useful display options. However, the component also consumes system resources. Another approach is writing your own code using the NetStream and Video classes to handle the loading and playback of video. In this article, we use the NetStream and Video classes to access video data — but then we take that data and make it appear in a Bitmap object.

Figure 1 shows a working example of this project. Click the video repeatedly to change the visual properties. You can also download the source files (ZIP, 4.9 MB) for this project.

AlertThis content requires Flash

Download the free Flash Player now!

Get Adobe Flash Player

Figure 1: Sample video project.

The BitmapData class

A BitmapData object is an array of pixel data that can be accessed and manipulated using the same strategies used to access any other data stored in an array. A BitmapData object is not a Display object — so to see the pixel data in the BitmapData object, you must attach it to a Bitmap object. When you attach that Bitmap object to the Stage, you can see the contents.

A unique feature of the BitmapData object is that it accepts the data of any type of Display object, including video (see Figure 2).

Figure 2: The original source video presented in a Bitmap object.

A BitmapData object has several nice pixel manipulation methods in ActionScript that are not available to a Video object. Because the BitmapData object is not a Display object, you can make changes to the bits quickly without consuming a lot of memory or affecting performance.

Creating the BitmapData object

Now that you can manipulate Video data and display it in a bitmap, what can you do with it? In this section, we explore how to use the BitmapData threshold method to manipulate the Video data before presenting it on the Stage (see Figure 3).

Figure 3: The video display affected by the pixel data of a BitmapData object.

After importing the necessary classes, assigning variables, and setting up the new NetStream and Video objects, you need to create two BitmapData objects. One object receives the Video data (vidBmpHolder) and the other is the copy where the threshold method can be applied (vidBmpDisplay):

vidBmpHolder = new BitmapData(kVIDEOW, kVIDEOH, false, 0x000000);
vidBmpDisplay = new BitmapData(kVIDEOW, kVIDEOH, false, 0x000000);

Now you can create the Bitmap Display object. Notice that it uses the data from vidBmpDisplay and not from the holder:

vidBmp = new Bitmap(vidBmpDisplay);

Controlling the video

Next, you set the stream to play the video. At this point, however, the video is not added to the Stage. Later, the bitmap will display the video data:

stream.play("palms.flv");

The onVideoLoaded function is called when the NetStream containing the video sends a message about its progress. The specific event you want to use is NetStream.Play.Start. There are several NetStream events, but you are looking for the moment the video begins playing. Once it begins, you can set up the other listener functions.

First, the flipMap function is called on ENTER_FRAME. The ENTER_FRAME event is tied to the movie's frame rate, not the video. To add some user interaction, add the function adjustProps, which is called when a user clicks the bitmap. Since the Play.Start event was triggered, you know the video is playing, and therefore the onVideoLoaded listener is no longer needed. However, in a real-world project, a best practice would include adding additional NetStatus listeners to handle errors and metadata:

private function onVideoLoaded (nsLoaded:NetStatusEvent):void
{
   // Make sure you have a Play.Start event from the stream
   if (nsLoaded.info.code == "NetStream.Play.Start")
   {   
      // Set up the listeners
      this.addEventListener(Event.ENTER_FRAME, flipMap);
      this.addEventListener(MouseEvent.CLICK, adjustProps);
   
      // Put the bitmap in the Display List
      this.addChild(this.vidBmp);
         
      this.stream.removeEventListener(NetStatusEvent.NET_STATUS, onVideoLoaded);
   }
}

Manipulating the pixel data of the BitmapData object

The flipMap function loads the current frame pixel data of the video stream and draws it directly to the BitmapData object in memory. Then the Holder data is copied to the Display BitmapData object. After the data is copied, apply the threshold method to that data. Since the Display BitmapData object is tied to the Bitmap object in the Display list, the newly transformed pixels appear on the screen:

private function flipMap(e:Event):void
{
   this.vidBmpHolder.draw(video);
         
   // Copy the pixels from the Holder BitmapData object 
   // To the BitmapData object where the data can be manipulated
   this.vidBmpDisplay.copyPixels(vidBmpHolder, vidBmpRect, vidBmpPoint);
   _color = (_color / 128) * 0xffffff;
         
   // Set the initial threshold properties using variables 
   // So that you can change them on another event (a mouse click)
   this.vidBmpDisplay.threshold(vidBmpDisplay, vidBmpRect, vidBmpPoint, ">=",
    _thresh, _color, 0x0000ff, true);
         
}

The value of the threshold property is visually represented by the amount of the alpha channel that is affected in the video display (see Figure 4).

Figure 4: As the user clicks the video, the threshold property value is reset.

The last step is to create the adjustProps function that is called by the mouse event to change the display of the video when users click it in the SWF at runtime:

private function adjustProps (evt:MouseEvent):void
{
   // Visual feedback occurs upon user interaction
   this._thresh = (Math.random() * 100) * 0xffffff;

   trace (_thresh.toString(16) +" "+ _color.toString(16));

}

Conclusion

Now that you've seen what's possible, try using the sample files to create your own project. You can replace the FLV file with your own video or create buttons that enable users to change the way the video appears. Keep in mind that multiple unique bitmap instances can reference the same BitmapData. To add more Bitmap objects that display the same video data, you can create a new Bitmap object, attach vidBmpDisplay as the source, and add it to the Stage.

The improvements described in this article — and many more — make ActionScript 3.0 the most powerful version yet for object-oriented programmers and Flash developers. Here are a few more resources to get you started and provide inspiration for your next project:

 


David Van der Voort is a JavaScript developer at Sony Computer Entertainment. Before joining Sony, he worked at Crackle, Macromedia, Broderbund, Sega, and Microprose.

Tommi West is a freelance web designer and creative director at tommiland.com. Prior to starting her own business in 2004, she worked at Macromedia for six years as a technical writer, editor, and web producer. Tommi is an Adobe Community Professional.