I'm currently trying to implement a QtQuick2.0 Video-Backend to use glTexDirectVIVMap, so that we can get to <10% (maybe <5%) for 1080p video playback.
I'm already rather far and it does look promising!
Here is the interesting part of the code:
I'm just pasting part of the code for simplicity reasons.
'bind()' is the function which is called with a active glContext and should result in a glBindTexture call.
All the other code is glue-code and not important for this question.
(If someone want the code never the less, just ask me. It will eventually be open sourced anyway so no problem in sharing the unfinished version)
I still have two mayor problems.
This question is about my struggle with glTexDirectVIVMap:
It seams that glTexDirectVIVMap is mapping the memory in the background...?
What I meaning is that it's completely async ... I think.
I seems that the time it requires to do the map is heavily depending on the chip (GC800 or GC2000, imx6solo vs. quad) and also(!) very much depending on what else is going on on the GPU.
It can very
from < 1/24 seconds (==smooth playback)
to ~ 1/4 seconds (the only way to get non-stuttering playback to reduce to playback speed to ~1/6)
This is a huge problem.
*edit - missed to describe to problem*
The problem is that the frame start to 'stutter' as soon as the delay is to high.
On the solo it's stuttering all the time.
On the quad it's only stuttering if one renders something else in the background (which results in 60fps instead of 24fps opengl-rendering)
*edit - end*
I have a couple of possible solutions in mind ... but either I don't have enough knowledge for it or it has massive drawbacks.
1. I'm doing something wrong with glTexDirectVIVMap or glTexDirectInvalidateVIV
... if someone spots an error, let me know.
... I've tried to use glTexDirectVIV as well without success, I think it's not meant for this use-case (==where memory allocation happens somewhere else)
2. queue with a specific value.
I could do a N-buffering approach
So this would mean one would:
1. take a new frame
2. map it to texture
3. push texture on a stack/FIFO
4. pop oldest texture from stack (and free memory)
During all this time the 'oldest texture' is used for rendering.
This could be configurable but at the end of the day one would need to find a reasonable value for N.
It looks like that the max. value for N could be ~6.
... this is just a guess!
If frames come along and the stack is full, one would drop them.
6 frames are 0.25 seconds (24fps/6frame).
Meaning one would need to buffer 0.25 seconds audio as well.
3. queue until map is done.
Same thing as '2.' but rather then guessing 'N', one could use (if existing) some API to get the state of the memory mapping?
GL_MAPPING_DONE flag or something like that?
Then one would pop the oldest texture as soon as the second-oldest texture is ready.