Implementation isn't perfect yet, viewer/renderer doesn't update yet when
the preference is changed so a sequence needs to be re-opened for the change to
take effect.
By using one thread per logical CPU thread, we seemed to completely saturate
the CPU which would kill the performance of the main/GUI thread (despite the
other threads being low priority). We now use half of the logical threads, which
still sees good CPU usage and minimal performance impact while allowing the
main thread to respond to user actions.
We use Qt's built in zlib compression on the fastest setting (it was found that
higher compression took 5x as long with a negligible decrease in size). This
helps keep disk cache sizes low.
A few commits ago, the render behavior was changed to only render within a
user-specified range of the playhead. This works well, but it would still
render from the start of the range (usually before the playhead) to the end,
meaning it couldn't keep up with the playhead as well as it should. This
commit prioritizes frames close to the playhead and renders outwards to
address this.
Previously we had no disk management whatsoever, so we cleared the cache on
every close just to prevent clogging up tester disk space. Now that we are
implementing disk management, there are better things to do on close regarding
disk cache. However, some users may still wish for the app to delete the cache
on close, so it's provided as an option.
This functions more or less identically to using a media out value, but the
desired speed is preserved through block length changes, even if the block's
length is reduced to zero (i.e. no rounding errors).
frames
Previously, when the video renderer received a dirty cache signal, it would
proceed to extract all frames from the range and queue them. However, this could
be extremely slow for long ranges since it had to iterate through the entire
range and calculate the individual frames it contained. Now, we use the same
range combining system as audio and automatically calculate the next frame
within the range only when necessary. Essentially the same work, but split up
over time and done only when needed leading to no discernible UI pause when
invalidating cache.
The renderer backend can now distinguish between jobs. Previously if two jobs
of the same frame were started (which is legal if the user made a change while
frames were still being rendered), an earlier job in some situations could
finish AFTER a later job, and the backend would have no way of distinguishing
between them. This meant a frame could be erroneously set to an old value
rather than the newest. This commit introduces job identification so that old
jobs are automatically discarded.
Since updating all input values per sample could be performance costly,
we now only update inputs that are either keyframing or connected to
another node
This mostly builds on the keyframing we already set up for video, but the
audio renderer will now appropriately updated keyframe inputs per sample in
accordance with keyframe values.
Since EmitCachedFrameReady() makes a copy of the texture, we can economize a lot
by re-using the same copied texture for all the times rather than making a
separate copy for each time.
The encoder was moved to its own thread and will transcode the PCM from the
audio renderer into the chosen codec while the video frames are still
received. The implementation isn't perfect and could use some cleaning up, but
it is functional at the moment.
Sending a texture directly from the texture cache is dangerous since once the
reference is relinquished, it could be picked up and used by another thread.
Copying the texture to a separate one takes a little extra time but lets the
viewer remain in control of that texture.