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

ZVISION: Experimental sound support for the high-resolution ZGI movies (DVD version) #1356

Merged
merged 20 commits into from Nov 4, 2018

Conversation

eriktorbjorn
Copy link
Member

This has been sitting on my hard drive for quite some time now...

Back before clone2727 left the ScummVM project, he and I were trying to get the sound working in the high-resolution ZGI movies. When he left, there was still major problems with the audio/video sync and the project fell by the wayside. When GOG released the DVD version, this became a lot more relevant so I made an effort to update the code and received permission from clone2727 to release it.

There are some caveats:

  • It uses liba52 for sound support. I hope this is portable enough for our purposes.
  • I've only actually tested the three opening movies (i.e. up to and including the "Propaganda on Parade" movie.)
  • The movies use higher resolution than the game itself, but the window remains the same size so movies may be downscaled. This is far from ideal, and it wasn't the case when work began on this.
  • It only uses the video timestamps for sync, not the audio ones. This is hopefully good enough. I had a hell of a time getting it to work at all, and ended up having to buffer packets so that they could be handled out of order. Otherwise, it would get out of sync no matter what I did.

There may be other things to consider, but the truth is that I don't have the time nor the knowledge to get it any better than it is now. Hopefully someone else will be able to work out the last kinks. I hope I rebased the code properly. Git is an intelligence test that I keep failing...

Torbjörn Andersson added 17 commits October 17, 2018 17:13
This is for an experiment aiming to decode audio for the hi-res
videos in Zork: Grand Inquisitor. I don't know if we want to add
a dependency on liba52, but the license should allow us to include
the code verbatim, if that's preferrable.
At the moment, this produces nothing but misery in the form of
Valgrind warnings and horrible noise.
This collects the whole frame before trying to decode it. It's
still now working right, but it's way better than it was before.
This is used for some logo animations at the start of the game. I
don't know if it's used for anything else, but probably not.
Like most things that make this branch actually work, this comes
from clone2727.
This code comes from clone2727's now defunct (?) ac3 branch.
This code comes from clone2727's now defunct (?) ac3 branch, with
some minor compile fixes. This represents the latest version of
the stalled AC-3 decoder work for Zork: Grand Inquisitor. Note,
however, that I have not yet asked for clone2727's permission to
use this. I'm just experimenting.
From what I understand, this has something to do with the image
being either made up from two or three parts. When it's made from
three parts, the frame should be displayed for half again as long
as normal.

This makes the speed of the Zork: Grand Inquisitor video look
about right to me. It's still out of sync, but it doesn't seem to
get *more* out of sync as the video progresses.
This is another attempts at improving the audio/video sync in the
MPEG-PS decoder. Unfortunately, the audio probably also needs to
be synced to its pts timestamps...
I think it makes things easier to read, and I have some ideas
that I want to try which should be easier this way...
We weren't doing anything with it anyway. And I'm not sure it's
even available in the ZGI videos.
Sometimes (only at the very start of a movie?) there will be a
video packet that has a PTS but no frame to display. Save that PTS
and use it for the next frame. This doesn't actually improve
anything, as far as I can tell, but feels right.
In all my attempts to get the audio and video to sync up in the
ZGI videos, there have always been 9-10 frames of video before the
audio even starts, even though the audio is timestamped to start
before. This attempts to fix that by prioritizing sending audio
packets to the decoder in a timely fashion.

I do not know if this is the correct way of doing this, and there
are still some things that need to be fixed. But pragmatically, it
does procude significantly better sync, so...
@eriktorbjorn
Copy link
Member Author

One thing I forgot to mention is that there seems to be some sort of interlacing going on in some parts of the "Propaganda on Parade" intro video. It doesn't really have anything to do with this pull request, but since I don't see it if I play the video in a media player it's something that should be looked into, I guess.

I had hoped Wikipedia's articles on "Telecine" or "Three-two pull down" would give me ideas, but nope. No clue what to do about it.

@bluegr
Copy link
Member

bluegr commented Oct 21, 2018

Nice work from everyone involved!
liba52 looks to be portable (they even say so on their website)

Out of curiosity, why can't we change the screen resolution when a video is played, and we resort to downscaling?

@angstsmurf
Copy link
Contributor

Wouldn't the best solution be to always run in the highest resolution needed and upscale the non-video parts?

@eriktorbjorn
Copy link
Member Author

Out of curiosity, why can't we change the screen resolution when a video is played, and we resort to downscaling?

As I said (though perhaps not clearly enough), when work started on this the backend would change the window size when the videos were playing. But at some point, probably related to that you can now resize the game window at will, even with the SDL renderer and not just the OpenGL renderer, this was changed. There's this comment in backends/graphics/sdl/sdl-graphics.cpp:

// We only update the actual window when flags change (which usually means
// fullscreen mode is entered/exited), when updates are forced so that we
// do not reset the window size whenever a game makes a call to change the
// size or pixel format of the internal game surface (since a user may have
// resized the game window), or when the launcher is visible (since a user
// may change the scaler, which should reset the window size)
if (!_window->getSDLWindow() || _lastFlags != flags || _overlayVisible || _allowWindowSizeReset) {

So it probably has something to do with _allowWindowSizeReset, but I'm not familiar with the inner workings on the backend.

@criezy
Copy link
Member

criezy commented Oct 22, 2018

It should indeed run at the highest resolution and upscaled some parts rather than downscale others. I am guessing the zvision engine does not call initGraphicsModes when it starts with the list of resolutions it uses. Doing so should allow the backend to choose the best window size.

@eriktorbjorn
Copy link
Member Author

Wouldn't the best solution be to always run in the highest resolution
needed and upscale the non-video parts?

Maybe, but I thought the game graphics looked ugly when I resized the window to 800x600 pixels. And you'd still have the problem where subtitles would look smaller during cutscenes, wouldn't you? So personally I would prefer the window to change size as needed during gameplay like it used to, at least as long as the window hasn't been manually resized. But there's probably no one-size-fits-all solution here...

@criezy
Copy link
Member

criezy commented Oct 22, 2018

The engines that can change resolution during game play should now call initGraphicsModes when starting to indicate all the resolutions that it will use. It is then up to the backend to decide what to do with this information. The SDL backends sets the window size to the highest of the provided resolutions and keeps it at this size all the while the game is running. You can see a discussion in PR #1007 that added the feature. They is indeed no magical behaviour that fits all the cases and all the tastes and we had to settle for what we though was best.

Also at the time the change was made this indeed meant that the parts in lower resolution would be upscaled to fit the bigger window. Since then a stretch mode has been added however, which means that while the window will remain at the higher resolution we can instruct the SDL backend to not scale the display and instead use black borders for the parts at a lower resolution (by select the Center stretch mode in the options).

@eriktorbjorn
Copy link
Member Author

Ok, so if I understand correctly commit 9fb8e87 is the correct way of handling the different resolutions. And commit a945825 is hopefully the right way of allowing me to set the stretch mode per game, even when using the launcher dialog.

@@ -210,6 +210,9 @@ void initCommonGFX() {

if (gameDomain->contains("filtering"))
g_system->setFeatureState(OSystem::kFeatureFilteringMode, ConfMan.getBool("filtering"));

if (gameDomain->contains("stretch_mode"))
g_system->setStretchMode(ConfMan.get("stretch_mode").c_str());
Copy link
Member

Choose a reason for hiding this comment

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

It would be good if this could be merged seperately from the rest of this pull request, since it is a good fix anyway and I think this may be the fix for a problem reported on the forum a few days back:
http://forums.scummvm.org/viewtopic.php?t=14732

Copy link
Member

Choose a reason for hiding this comment

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

Oops! This is an oversight from myself when I added the feature. But it is indeed unrelated to this PR. I will commit that change this evening when I am back home (unless somebody does it before me).

Copy link
Member

Choose a reason for hiding this comment

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

@criezy : Happy for you to commit it later. Though @eriktorbjorn will have to rebase the PR at that point to remove this commit...

@criezy
Copy link
Member

criezy commented Oct 22, 2018

Commit 9fb8e87 is actually not the correct way to handle the game having multiple resolutions, although it probably works with the SDL backend.

The idea is to do something like this when starting the engine (before the first call to initGraphics):

Graphics::ModeList modes;
modes.push_back(Graphics::Mode(WINDOW_WIDTH, WINDOW_HEIGHT));
if (getGameId() == GID_GRANDINQUISITOR && (getFeatures() & GF_DVD))
	modes.push_back(Graphics::Mode(HIRES_WINDOW_WIDTH, HIRES_WINDOW_HEIGHT));
initGraphicsModes(modes);

Note: since initScreen() is called not only from ZVision::initialize() but also after playing the video in ActionStreamVideo::execute(), it is probably best to call initGraphicsModes() from ZVision::initialize() before the call to initScreen() rather than to do it in initScreen() itself.

@criezy
Copy link
Member

criezy commented Oct 22, 2018

Good work on this feature!
I finally installed my copy of ZGI from GoG and it was nice to see those high resolution videos with sound :-)

Before merging this you will need to drop the last commit (because I have already pushed it to trunk) and amend the previous one as per my previous comment (to use initGraphicsModes() before calling initScreen() in ZVision::initialize()). Actually I would suggest to also check if we are using the high-res videos or not, so the code would be:

Graphics::ModeList modes;
modes.push_back(Graphics::Mode(WINDOW_WIDTH, WINDOW_HEIGHT));
if (getGameId() == GID_GRANDINQUISITOR && (getFeatures() & GF_DVD) && (!ConfMan.hasKey("mpegmovies") || ConfMan.getBool("mpegmovies")))
        modes.push_back(Graphics::Mode(HIRES_WINDOW_WIDTH, HIRES_WINDOW_HEIGHT));
initGraphicsModes(modes);

I have made the changes locally to test this PR, and I can force push if you want.

@eriktorbjorn
Copy link
Member Author

I have made the changes locally to test this PR, and I can force push if you want.

If you can do that, that'd be great because I'm short on time right now. There's also a typo ("procude" instead of "produce") in the commit message for commit b326ff6, if that can be fixed.

By the way, if the hi-res graphics mode is only specified if "mpegmovies" is set, what happens if you enable it after the game has begun?

@criezy
Copy link
Member

criezy commented Oct 23, 2018

You can enable the high-res movies while the game is running? I missed that. If you do that then the window would remain at its small size (unless resized by the user of playing in fullscreen) and the high-res videos would be downscaled. Then indeed it might be better to not check if they are enabled or not when starting the engine and always add the high-res size to the used graphics modes.

@eriktorbjorn
Copy link
Member Author

You can enable the high-res movies while the game is running? I missed that.

I think so. I can't check at this very moment, but can't you enable/disable them from the game's own options dialog?

@bluegr
Copy link
Member

bluegr commented Oct 23, 2018

You can enable the high-res movies while the game is running? I missed that.

I think so. I can't check at this very moment, but can't you enable/disable them from the game's own options dialog?

I've just checked and no, you can't toggle the hi-res movies while the game is running. You can toggle if movie upscaling will occur via line skipping, or via doubling pixels.

@eriktorbjorn
Copy link
Member Author

I've just checked and no, you can't toggle the hi-res movies while the game is running. You can
toggle if movie upscaling will occur via line skipping, or via doubling pixels.

My copy of the game has a switch labelled "MPEG" in the lower right corner of the options dialog that switches between the hi-res and lo-res movies.

This allows the backend to show the hi-res videos at full
resolution, rather than scaling them down.
Copy link
Member

@criezy criezy left a comment

Choose a reason for hiding this comment

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

I also checked and I can confirm what @eriktorbjorn wrote. At least with the version from GoG there is the possibility to toggle on/off the use of the high-res videos in the in-game Preferences dialog. I have thus reverted to the code that always adds the high-res size to the graphics modes for the DVD version.

I have forced pushed the commit to properly handle the multiple resolutions. I am now happy with this PR and I think it can be merged. I will leave a few more days for review and if there is no objection I will merge the PR this weekend.

@bluegr
Copy link
Member

bluegr commented Oct 24, 2018

Ah it has been awhile. I remember now: this option needs to be set in the script manager, otherwise it is disabled and not shown in the preferences dialog. I specifically added code to hide it when libmpeg2 has not been included in the build, and it wasn't included in my local build, which is why I didn't see the option :)

The code in question is in zvision.cpp:222:

#ifndef USE_MPEG2
	// libmpeg2 not loaded, disable the MPEG2 movies option
	_scriptManager->setStateValue(StateKey_MPEGMovies, 2);
#endif

@eriktorbjorn
Copy link
Member Author

The code in question is in zvision.cpp:222:

#ifndef USE_MPEG2
	// libmpeg2 not loaded, disable the MPEG2 movies option
	_scriptManager->setStateValue(StateKey_MPEGMovies, 2);
#endif

Ah, so I guess this should be "if !defined(USE_MPEG2) || !defined(USE_A52)" now? (I'm not sure if there's any such condition for having the option in ScummVM's engine options though.)

@eriktorbjorn
Copy link
Member Author

And perhaps the hi-resolution mode should only be set if ScummVM is compiled with the necessary libraries to play the hi-resolution movies.

@bluegr
Copy link
Member

bluegr commented Oct 28, 2018

@eriktorbjorn: yes, and yes to both of your questions :P

@eriktorbjorn
Copy link
Member Author

eriktorbjorn commented Oct 29, 2018

@eriktorbjorn: yes, and yes to both of your questions :P

Hmm... Well, unfortunately I'm still short on time and probably will be for the rest of the week. I'm uncertain how the aforementioned force push criezy made affects things if I commit to my branch, so I won't do anything at this moment. I see there are a couple of other places where it only checked for USE_MPEG that should probably include USE_A52 as well.

I don't like having such a minor thing hold this up, so if anyone else can fix it I'd be grateful. Again. :-)

@criezy
Copy link
Member

criezy commented Oct 31, 2018

I have pushed a commit to check on USE_A52 everywhere where it was checking USE_MPEG and also added that change when initializing the graphics mode.

This seems to work well. The only place where the option is still visible when either libmpeg2 or liba52 is not used is in the engine options. This one is more problematic as the flag is set in the config file when adding the game to ScummVM.

@criezy
Copy link
Member

criezy commented Oct 31, 2018

I forgot the engine options in the config are updated when starting the engine. So this is not as bad as I though and I have added a commit to remove the mpeg engine option from the detection table when libmpeg2 or liba52 is not used.

This is not perfect as we now get the following behaviour:

  1. Add game with version of ScummVM that does not support playing the mpeg movies
    The option is not visible in the game edit dialog.
  2. Now upgrade to a ScummVM version that supports playing the mpeg movies
    The option is still not visible in the game edit dialog.
  3. Start the game, then return to launcher.
    The option is now visible in the game edit dialog.

But I think this is better than always having the option visible.

@criezy criezy merged commit e4ff192 into scummvm:master Nov 4, 2018
@eriktorbjorn eriktorbjorn deleted the ac3 branch February 8, 2022 09:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
5 participants