tlRender icon indicating copy to clipboard operation
tlRender copied to clipboard

Change or add simpler cache settings

Open ggarra13 opened this issue 1 year ago • 12 comments

While the Read Behind / Read Ahead cache settings are easy to understand and work fine for movies. When dealing with image sequences, you want to maximize the memory (ie. set a specific value in GB and forget about it).

ggarra13 avatar Jan 31 '23 11:01 ggarra13

You can do a rough conversion using the timeline information:

4 GB of cache = 4,000,000,000 bytes
Number of frames = 4,000,000,000 / (videoWidth * videoHeight * videoPixelByteCount)
Number of seconds = frames / videoSpeed

However this doesn't necessarily work for .otio files which can have multiple tracks or transitions leading to multiple images per frame.

It also seems like the cache should account for audio data so the maximum amount of memory isn't exceeded.

darbyjohnston avatar Feb 01 '23 00:02 darbyjohnston

@darbyjohnston I have two users already requesting this feature. See:

https://github.com/ggarra13/mrv2/issues/6

I think this should be made a priority.

ggarra13 avatar Mar 25 '23 12:03 ggarra13

Here's code I wrote to check the memory use/amount physical and virtual on all platforms. That may help you out.

memory.zip

ggarra13 avatar Mar 25 '23 13:03 ggarra13

Did you try my suggestion for calculating an estimate based on the video dimensions? You would need to do that each time a new file is loaded, and adjust the read ahead / read behind as necessary. It's not perfect but works OK for now until I have time to look into redesigning the cache.

darbyjohnston avatar Mar 25 '23 16:03 darbyjohnston

@darbyjohnston I just added the option now. It works for most stuff pretty well. However, even though in my new computer (yeah! I bought one :) I have 32GB of RAM, when I set it to 24GB and tried it with SolLevante, the cache line displayed that it could handle it, but there were hiccups in the playback, When I set it to default of 4.0 read ahead and 0.5 read behind it played fine all the way.

ggarra13 avatar Mar 25 '23 18:03 ggarra13

Nice, what kind of computer did you get?

Maybe try checking the system monitor and make sure it shows the memory usage you are expecting.

darbyjohnston avatar Mar 25 '23 20:03 darbyjohnston

I got a gaming machiine, as that's the best I can get here in Argentina due to imports being blocked. AMD Ryzen 7, NVidia GTX 3080, 32 GB Ram. It can play 8K webm movies with mrv2 which is good at least.

After testing out the GB parameter, I think that will work, for my users. The SolLevante issue seems to be a hard-disk issue, as the memory and read cache works fine, but the playback on the final titles stutters, for example.

ggarra13 avatar Mar 25 '23 22:03 ggarra13

Let's keep this issue open, using the video dimensions for calculating the size is just a temporary measure and a better caching system is definitely needed.

Sounds like a capable machine, what kind of hard-disk? My workstation has similar specs and seems to play back the Sol Levante movie OK. I am playing it back from a pair of SATA SSDs in RAID 0.

That's great to hear about the webms, I haven't really tested with 8K yet. Besides the movie decoding, allocating memory for the frames and uploading them to the GPU takes quite a bit of bandwidth.

darbyjohnston avatar Mar 26 '23 22:03 darbyjohnston

Sorry for closing the issue. I clicked on the wrong button.

I can play SolLevante with the default cache settings just fine. They are roughly equivalent to 4Gb of my settings. I tried it with 4Gb and 8Gb and with both it plays fine.

But when I crank the Gb setting to 16 or so, the playback of SolLevante suffers on the end credits. The scrolling of the credits becomes jittery and the audio cache goes berserk caching many seconds (the higher the mem I use the more audio it preloads).

If you cannot reproduce it with tlplay, let me know what platform you use and I can send you a link to a copy of the latest mrv2 with the Gigabytes controls.

ggarra13 avatar Mar 27 '23 14:03 ggarra13

I apologyze for the incorrect bug report. I had miscalculated the Read Ahead formula by 5 times, that's what was it over-allocating. Now I find that it under-allocated the memory. Even when I set it to 31GB, it uses about 8GB on Linux.

ggarra13 avatar Mar 29 '23 12:03 ggarra13

A user sent me a simple dummy sequence of 4K, with a pixel ratio of 2 (anamorphic).

https://1drv.ms/u/s!AlOpRG0iPvzdhKMZuZBy9KfbkZYk6w?e=6hXCI9

mrv2 plays it fine forwards, but it struggles to play it back backwards for a strange reason. I am using the default PlaybackCache() settings with the following code:


        if (Gbytes > 0)
        {
            const size_t activeCount = p.filesModel->observeActive()->getSize();

            uint64_t bytes = Gbytes * 1024 * 1024 * 1024;
            auto player = p.timelinePlayers[0];

            const auto timeline = player->timeline();
            const auto ioInfo = timeline->getIOInfo();
            double seconds = 1.F;
            if (!ioInfo.video.empty())
            {
                const auto& video = ioInfo.video[0];
                auto pixelType = video.pixelType;
                uint8_t bitDepth = imaging::getBitDepth(pixelType);
                uint64_t size = video.size.w * video.size.h * bitDepth;
                double frames = bytes / (double)size;
                seconds = frames / player->defaultSpeed();
            }
            if (ioInfo.audio.isValid())
            {
                const auto& audio = ioInfo.audio;
                size_t channelCount = audio.channelCount;
                size_t byteCount = audio::getByteCount(audio.dataType);
                size_t sampleRate = audio.sampleRate;
                uint64_t size = sampleRate * byteCount * channelCount;
                seconds -= size / 1024.0 / 1024.0;
            }

            constexpr double defaultReadAhead =
                timeline::PlayerCacheOptions().readAhead.value();
            constexpr double defaultReadBehind =
                timeline::PlayerCacheOptions().readBehind.value();
            constexpr double totalTime = defaultReadAhead + defaultReadBehind;
            constexpr double readAhead = defaultReadAhead / totalTime;
            constexpr double readBehind = defaultReadBehind / totalTime;

            options.readAhead = otime::RationalTime(
                seconds * readAhead / static_cast<double>(activeCount), 1.0);
            options.readBehind = otime::RationalTime(
                seconds * readBehind / static_cast<double>(activeCount), 1.0);
        }

ggarra13 avatar Mar 29 '23 16:03 ggarra13

Sorry, the under-allocation is probably due to YUV frames, the conversion I mentioned above is for RGB. Use the function std::size_t tl::imaging::getDataByteCount(const Info&);, it will take into account all of the different pixel formats including YUV.

darbyjohnston avatar Mar 29 '23 17:03 darbyjohnston