Play Movie Surface Activity
Play a movie from a file on disk. Output goes to a SurfaceView.
This is very similar to PlayMovieActivity, but the output goes to a SurfaceView instead of a TextureView. There are some important differences:
- TextureViews behave like normal views. SurfaceViews don't. A SurfaceView has a transparent "hole" in the UI through which an independent Surface layer can be seen. This Surface is sent directly to the system graphics compositor.
- Because the video is being composited with the UI by the system compositor, rather than the application, it can often be done more efficiently (e.g. using a hardware composer "overlay"). This can lead to significant battery savings when playing a long movie.
- On the other hand, the TextureView contents can be freely scaled and rotated with a simple matrix. The SurfaceView output is limited to scaling, and it's more awkward to do.
- DRM-protected content can't be touched by the app (or even the system compositor). We have to point the MediaCodec decoder at a Surface that is composited by a hardware composer overlay. The only way to do the app side of this is with SurfaceView.
The MediaCodec decoder requests buffers from the Surface, passing the video dimensions in as arguments. The Surface provides buffers with a matching size, which means the video data will completely cover the Surface. As a result, there's no need to use SurfaceHolder#setFixedSize() to set the dimensions. The hardware scaler will scale the video to match the view size, so if we want to preserve the correct aspect ratio we need to adjust the View layout. We can use our custom AspectFrameLayout for this.
The actual playback of the video -- sending frames to a Surface -- is the same for TextureView and SurfaceView.