0

I'm writing an app which displays cutscenes. Currently, the way it works is that (because surface views / video views can't typically be placed on top of each other) I remove the VideoView from the layout the instant the app runs. Then, when I want to display a cutscene, I add the VideoView back into the layout and, once the animation is ready to play, remove the SurfaceView (if done right, there is no "black flash" prior to the video starting. This works successfully.) However, when the video ends, I can do one of two things:

  • Remove VideoView, followed by adding the SurfaceView back to the layout. This causes a black flash on the screen while the SurfaceView is being added back.
  • Add the SurfaceView back, followed by removing the VideoView once the SurfaceView is prepared to render.

Likewise, I chose the second option to eliminate the black flash on screen. However, this causes a different issue. For some reason, After a VideoView has begun a playback, if a SurfaceView is added on top of that whose canvas is then drawn on, there are dark vertical stripes which run down the screen from top to bottom.

Once the VideoView is removed, the stripes disappear. However, there is, understandably, about a quarter of a second or so of lag time between the SurfaceView being added back and the VideoView being removed from the layout. During this period, the stripes are clearly visible.

Is there any way around this?

Note that I am using Vitamio to render AVI videos.

Alexander Guyer
  • 2,063
  • 1
  • 14
  • 20

2 Answers2

0

I have found the solution after a bit of thought and some trial and error.

It seems to be either an android or Vitamio bug.

If a SurfaceView's canvas is drawn on while a VideoView is also present in the current layout, and that VideoView's start() method has been called without a following call to stopPlayback() there will often be graphical malformations.

Even if the VideoView has reached the end of its playback, stopPlayback() still must be called to avoid this graphical malformation.

EDIT: Note that this may occur even with calls to setZOrderMediaOverlay() or setZOrderOnTop(). However, as stated, calling stopPlayback() seems to do the trick.

Alexander Guyer
  • 2,063
  • 1
  • 14
  • 20
0

As noted in the docs, VideoView is a subclass of SurfaceView. If you try to have two SurfaceViews occupying the same space at the same time, the results are somewhat unpredictable. (Well, I predict they will be bad.)

If you want them to overlap, you need to put them at different Z depths. For example, you can use setZOrderMediaOverlay() on the SurfaceView with the Canvas to place it above the VideoView, but still below the View UI layer.

You do need to ensure that the Canvas-based SurfaceView is generally transparent. See Grafika's "multi-surface test" for an example with three overlapping SurfaceViews. drawCircleSurface() uses Canvas rendering.

Additional details can be found in the graphics architecture document.

fadden
  • 51,356
  • 5
  • 116
  • 166
  • Even with setZOrderMediaOverlay(), the vertical stripes were present. Also tried setZOrderOnTop(true). Neither of these prevailed. As I said, it may just be a Vitamio bug of some sort. The only solution I found was to stop the playback, which immediately removed the stripes. However, when both of these methods are used, it works flawlessly. Thank you. – Alexander Guyer Jul 27 '15 at 19:44
  • It's difficult to fathom how this would be possible, as separate Surfaces have zero interaction with one another. They're combined by SurfaceFlinger, the system compositor, not the app; there is no reason why they should be aware of each other or have any ability to interfere with one another (barring device-specific driver bugs). Note that the Z-order calls must be made in `onCreate()`; they will have no effect once the Surface has been created. – fadden Jul 27 '15 at 20:07
  • 1
    If it were a device-specific hardware composer bug, one way to probe the problem would be to use the `screenrecord` command to capture video while it's glitching. If the glitches don't appear in the recorded video, there's a good chance this is a device driver issue. (You could also just temporarily disable HWC with the adb command from this answer: http://stackoverflow.com/questions/30328373/adb-screencap-output-is-different-than-on-the-device/30330318#30330318 ) I don't know how interested you are in pursuing this further, as you seem to have a work-around. – fadden Jul 27 '15 at 20:15