I've written the software for a digital signage product that we're developing which uses the iMX6. The screen content is configurable, and is rendered using OpenGL ES (to an SDL generated window - not using X11). It's possible to set up the screen layout such that is has video on a part of the screen, and I'm handling the video using a combination of ffmpeg's libav and a custom decoder that utilises the iMX6 VPU.
To render the video to the OpenGL ES scene, I initially create a ring buffer of 3 textures and then call glTexDirectVIV for each texture and store the pointer that's returned. Then as the video plays, I have a thread that copies the decoded video frames to the textures using the pointers that I initially received via glTexDirectVIV (I'm using NEON instructions to copy the frames as quickly as possible).
The result is quite impressive, given that it's not a zero copy solution. I'm getting about 60 fps for fairly complex OpenGL ES scenes with a video playing in the middle of it.
I'm experiencing a problem though, where after a period of time (seems fairly random - anywhere from a few seconds to a few hours) the video starts to flicker with black frames. It initially looks like every third frame is black, and then after a while every 2 out of 3 frames, and then it turns completely black - so I'm immediately thinking it's a problem with my ring buffer of 3 textures. I've been through the code trying to diagnose the issue, and the problem doesn't occur if I don't use glTexDirectVIV and just copy the frames using glTexSubImage2D, but that causes the frame rate to drop.
I now have it where I can connect a USB keyboard to the device, and when I hit a certain key it re-calls glTexDirectVIV to refresh the pointers that I have stored for the 3 textures. That's all that happens when I hit the keyboard key. Now when the video starts to flicker, when I hit this key then the flickering immediately stops.
So I've concluded that the GPU must be moving the textures in the GPU memory, thus invalidating the pointers that I have stored by my initial glTexDirectVIV call.
I originally referred to this when I wrote my code:
and with regard to glTexDirectVIV, it states "This function should be called just once in your code! (this was my mistake for a long time.....)".
My question is - should I in fact be calling glTexDirectVIV on every video frame before I copy the data, rather than assume the pointers will stay valid? That's what I'm starting to consider, but I'm a little concerned that it might cause a different problem that I'm not aware of, given the statement on that blogspot page.
If I am supposed to only call glTexDirectVIV once initially, how can I get around this problem that I'm seeing where the GPU seems to move the textures and therefore invalidates my stored pointers? Is there a way I can detect that this has happened, or prevent it happening in the first place?