google / ExoPlayer

This project is deprecated and stale. The latest ExoPlayer code is available in https://github.com/androidx/media
https://developer.android.com/media/media3/exoplayer
Apache License 2.0
21.74k stars 6.03k forks source link

Play video in reverse #2191

Closed rafiip closed 7 years ago

rafiip commented 7 years ago

Hi, As much as the title says , in the future , will it be possible to play a video backwards ? or is it something that can be achievable now ? if it is , i will appreciate if you point me to the right direction . regards.

andrewlewis commented 7 years ago

ExoPlayer doesn't support this I'm afraid. Generally, it is not feasible to play compressed videos backwards in real time, due to the way they are represented.

The encoded representation of each video frame generally depends on one or more reference frames, except for key-frames which can be decoded independently. To decode a given frame you first need decode its reference frames, and to decode those you need to decode their reference frames, and so on (until you reach a key-frame). A common case is for each frame to depend on its preceding neighbor. So it can be much more expensive to decode an arbitrary frame compared to the cost of decoding a key-frame. The same cost contributes to the buffering pause you might see when doing a frame-exact seek.

Common workarounds for this problem are (1) (re-)encoding the source video with only key-frames so any frame can be decoded for about the same cost, at the expense of decreased coding efficiency, (2) decoding and storing whole groups of pictures in advance of playing them, which can use a lot of storage (unless you re-compress the decoded frames independently) or (3) playing only those frames which can be decoded efficiently (normally just key-frames) which means that playback won't be smooth. Various other tricks/tradeoffs are possible.

WeiChungChang commented 7 years ago

Dear mehraf:

I guess your request is to playback all frames smoothly as andrewlewis's suggestion (2)

(2) decoding and storing whole groups of pictures in advance of playing them, which can use a lot of storage (unless you re-compress the decoded frames independently)

According to my previous experience it is possible to achieve it. Previously I made this function by mediacodec: https://developer.android.com/reference/android/media/MediaCodec.html

You could check the result at the link below: original movie: https://www.youtube.com/watch?v=gGaXMwQAEK8

The new feature created based on MeidaCodec (play baseball in reverse direction is actually very funny!): https://www.youtube.com/watch?v=BKZdIb8H3CU

You could compare & check the effect by these two movies.

I attach my original design document as the link below: https://drive.google.com/file/d/0B7H5vJR3qWj0WFRnMG9fQmV0bE0/view?usp=sharing

Here are some important tips to achieve it.

  1. DispMaxqueue means the max storage you have for your codec (as andrewlewis suggested)

... which can use a lot of storage...

for me, I ported a software H264 decoder, control the max internal buffer to be about 10~20 MB. You should carefully set it according to your case.

  1. A check should be made to see if the movie to be playback satisfies the limit of storage or not. As my experience, for MP4, we could easily (for most cases) detect the max GOP. However, for MPEG2-TS it is not the case. So we only support MP4 previously.

  2. Most of the devices with HW codec, as my HTC X9, could keep ~ more than 1 seconds frames within the codec. Hence a reorder if the max GOP is less than 1 second may be possible. I think if you do NOT care the movies which are compressed by strange settings (as those with irregular huge GOP size), you could complete it (as I know, some cameras ex, from SONY(but about 3 years ago), make the rule by compressed in regular GOP size = 1 second (or 0.5 second); for this case it is nice to complete the reverse playback functionality).

In short, technically it is NOT hard to do but the only problem is the irregular source movies.