Reputation: 41
I want to play (render to surface) two or more consecutive mp4 video sequences (each stored in a separate file on my device and maybe not present at startup) on my Android device in a smooth (no stalls, flicker, etc.) manner. So, the viewer might get the impression of watching only one continuous video. In a first step it would be sufficient to achieve this only for my Nexus 7 tablet. For displaying only one video I have been using the MediaCodec API in a similar way to http://dpsm.wordpress.com/2012/07/28/android-mediacodec-decoded/ and it works fine. By only creating (and configure) the second decoder after the first sequence has finished (decoder.stop and decoder.release of the first one was called), one can see the blending. For a smooth fade between two different video sequences I was thinking about having an init functionality where the second video is already initialized via decoder.configure(format, surface, null, 0) during the playback of the first one. Furthermore the first frame is also queued via decoder.queueInputBuffer. But doing so results to the following error:
01-13 16:20:37.182: E/BufferQueue(183): [SurfaceView] connect: already connected (cur=3, req=3)
01-13 16:20:37.182: E/MediaCodec(9148): native_window_api_connect returned an error: Invalid argument (-22)
01-13 16:20:37.182: E/Decoder Init(9148): Exception decoder.configure: java.lang.IllegalStateException
It seems to me that one surface can only be used by one decoder simultaneously. So, is there any other possibility for doing that? Maybe using OpenGL?
Best, Alex.
Upvotes: 4
Views: 1968
Reputation: 52313
What you describe with using multiple instances of MediaCodec
will work, but you can only have one "producer" connected to a Surface at a time. You'd need to tear down the first before you can proceed with the second, and I'm not sure how close you can get the timing.
What you can do instead is decode to a SurfaceTexture
, and then draw that on the SurfaceView (using, as you thought, OpenGL).
You can see an example of rendering MP4 files to a SurfaceTexture
in the ExtractMpegFramesTest example. From there you just need to render the texture to your surface (SurfaceView
? TextureView
?), using something like the STextureRender
class in CameraToMpegTest.
There's some additional examples in Grafika, though the video player there is closer to what you already have (decoder outputs to TextureView
).
Incidentally, you'll need to figure out how much of a delay to put between the last frame of movie N and the first frame of movie N+1. If the recordings were taken at fixed frame rates it's easy enough, but some sources (e.g. screenrecord
) don't record that way.
Update: If you can guarantee that your movie clips have the same characteristics (size, encoding type -- essentially everything in MediaFormat
), there's an easier way. You can flush()
the decoder when you hit end-of-stream and just start feeding in the next file. I use this to loop video in the Grafika video player (see MoviePlayer#doExtract()).
Upvotes: 1
Reputation: 32221
Crazy idea. Try margin the two videos to one. They both on your device, so it shouldn't take to long. And you can implement the fade effect by yourself.
Upvotes: 0