Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix Theora video issues #101958

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open

Conversation

berarma
Copy link
Contributor

@berarma berarma commented Jan 23, 2025

This fixes many (if not all) of the long-standing issues when playing Theora video streams. Even though Theora is an old codec, it can still do a decent job, specially when it works 100% correctly. That's what this PR aims to do.

Videos are an essential piece for many games, and I think Godot can be a lot better by fulfilling that need in the core. Having at least a backup codec which can be used out of the box and offers compatibility with old and new hardware will make life easier for a lot of developers.

What's fixed:

  • Duplicate frames being ignored (TH_DUPFRAME). These are used when there are continuous identical frames in the stream.
  • Frames playing ahead of time, way more when frame timestamps are far from each other. The latter can happen when the encoder skips identical frames, but also when the video frame rate is lower than the screen frame rate.
  • Audio buffer running out of data when the previous situations happened and also when decoding was slow.
  • Buffering of the stream didn't work. Now it works for the decoded audio and the encoded video data.
  • The audio buffer couldn't be filled without overwriting previous audio data.
  • Frames weren't being cropped to the original picture size and offset and produced artifacts around the image for some frame sizes.

I've also removed the Theora thread streaming code since it was disabled in code and it would involve more testing. I think it's better to remove that code for now than leave it untested and focus on getting it working 100% right.

The issues fixed could be mostly worked around by setting the keyframe inverval to 1 but this would take away most compression benefits. Now videos should play correctly even at the highest keyframe interval.

And possibly other issues.

There's some code left to dynamically change post-processing levels depending on codec performance, but it doesn't really do anything as it's set to no post-processing. I think I could easily make it work but it would be good to have a setting so the user can disable post-processing or set a max level that suits the video content.

Audio delay compensation is supposed to need some work also according to code comments. I could look at it too.

Please test it. Now that I've gotten a grasp of the code, I'm determined to make it work 100%.

I think this could be easily ported to Godot 3.X.

@DeeJayLSP
Copy link
Contributor

DeeJayLSP commented Jan 23, 2025

Testing videos from #21568 and #66331, the issue seems to be gone with no regressions.

The patch in AudioRBResampler didn't seem to interfere in custom VideoStream implementations, so LGTM.

@berarma
Copy link
Contributor Author

berarma commented Jan 23, 2025

The patch in AudioRBResampler didn't seem to interfere in custom VideoStream implementations, so LGTM.

It will prevent overwriting buffered audio.

- Duplicate frames were ignored.
- Frames could be shown way before their timestamp.
- The audio buffer could run out of data.
- Buffering option was ignored in practice.
- Last frames in the stream could be ignored.
@berarma
Copy link
Contributor Author

berarma commented Jan 23, 2025

I've added a fix for #62752. Updated PR description.

@fire fire requested a review from a team January 23, 2025 23:21
@fire
Copy link
Member

fire commented Jan 23, 2025

I'm not able to review this due to time, but I believe that if the test cases work for many people this should be merged for 4.4

Copy link
Member

@Calinou Calinou left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tested locally, it causes a significant performance regression in debug builds when reading a high-bitrate 1080p60 video despite using a high-end CPU.

PC specifications
  • CPU: Intel Core i9-13900K
  • GPU: NVIDIA GeForce RTX 4090
  • RAM: 64 GB (2×32 GB DDR5-5800 C30)
  • SSD: Solidigm P44 Pro 2 TB
  • OS: Linux (Fedora 41)

See these 120 FPS videos of the running project which should showcase frame drops clearly:

Before

theora_before.mp4

After

theora_after.mp4

Source video file: https://0x0.st/8Xbm.ogv

Thankfully, this is not reproducible when using an optimized editor build (production=yes lto=full), but I worry about low-end and mobile CPUs here.

@fire
Copy link
Member

fire commented Jan 23, 2025

Note that a debug builds is not a release build of Godot Engine. So this may still be ok if we can test on a low end computer or android tablet.

@DeeJayLSP
Copy link
Contributor

Kinda off-topic, but I should warn that Theora doesn't have ARM SIMD enabled in Godot.

I made an attempt a long time ago on #68694, but it added a dependency (perl) and only worked for 32-bit ARM. I presume it's similar to libvpx's buildsystem issue.

@berarma
Copy link
Contributor Author

berarma commented Jan 24, 2025

Tested locally, it causes a significant performance regression in debug builds when reading a high-bitrate 1080p60 video despite using a high-end CPU.

I don't think this is really a performance regression. The code is doing the same work but only in a different way.

I think it's the way I choose the frames to render causing frame stuttering.

Thankfully, this is not reproducible when using an optimized editor build (production=yes lto=full), but I worry about low-end and mobile CPUs here.

I don't think it's directly related to the performance of the code but to the resulting framerate being more or less in sync with the video rate. Thus, it might happen either with low or high end machines.

Running a high-bitrate HD video at 60fps on an unoptimized codec without hardware acceleration is the worst possible scenario. Since the codec is running fully in the CPU, code optimization will be a must in most systems. Anyway, I'm glad you tried this because I think it uncovered an issue in the frame dropping/choosing logic.

I've pushed a new commit with an improved logic that worked well in my tests. I've left printf in the code so that it outputs debug information to the terminal. In case it's still not fixed I'd need that information to see what's happening on your computer. I'll remove them when we're done testing it.

@berarma berarma force-pushed the theora_fixes branch 2 times, most recently from 488f011 to 18048ea Compare January 24, 2025 12:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
5 participants