[AvPlayer] Start a player on its own when the title registers no event callback
Reporting a loaded source as active before Start regressed Quake, which waits for its player to go inactive before starting its queued intro videos. A player left loaded but unstarted stays active forever. Only a title that registers an event callback can see the ready state and call sceAvPlayerStart itself, so a player whose title asks for autoStart or registers no callback now plays by itself once its source is ready, reaches the end of the stream and reports inactive. Titles that start playback themselves keep seeing a loaded source as active.
This commit is contained in:
parent
830eeaff53
commit
fbacc494ed
|
|
@ -541,7 +541,9 @@ public static class AvPlayerExports
|
|||
{
|
||||
Handle = handle,
|
||||
IsGen5 = IsGen5Target(ctx.TargetGeneration),
|
||||
AutoStart = TryReadByte(ctx, initDataAddress + autoStartOffset, out var autoStart) && autoStart != 0,
|
||||
AutoStart = StartsAutomatically(
|
||||
TryReadByte(ctx, initDataAddress + autoStartOffset, out var autoStart) && autoStart != 0,
|
||||
TryReadUInt64(ctx, initDataAddress + 88, out var eventCallbackForStart) ? eventCallbackForStart : 0),
|
||||
GuestBuffers = new ulong[ReadOutputVideoFrameBufferCount(
|
||||
ctx,
|
||||
initDataAddress,
|
||||
|
|
@ -615,7 +617,9 @@ public static class AvPlayerExports
|
|||
{
|
||||
Handle = handle,
|
||||
IsGen5 = IsGen5Target(ctx.TargetGeneration),
|
||||
AutoStart = TryReadByte(ctx, initDataAddress + autoStartOffset, out var autoStart) && autoStart != 0,
|
||||
AutoStart = StartsAutomatically(
|
||||
TryReadByte(ctx, initDataAddress + autoStartOffset, out var autoStart) && autoStart != 0,
|
||||
TryReadUInt64(ctx, initDataAddress + 96, out var eventCallbackForStart) ? eventCallbackForStart : 0),
|
||||
GuestBuffers = new ulong[ReadOutputVideoFrameBufferCount(
|
||||
ctx,
|
||||
initDataAddress,
|
||||
|
|
@ -2620,6 +2624,13 @@ public static class AvPlayerExports
|
|||
internal static bool IsGen5Target(Generation generation) =>
|
||||
(generation & Generation.Gen5) != 0;
|
||||
|
||||
// A player plays on its own once its source is ready when the title asks for autoStart or
|
||||
// registers no event callback: without one nothing could observe the ready state and start
|
||||
// it. Such a title never calls sceAvPlayerStart and waits for the player to go inactive at the
|
||||
// end of the stream, so leaving it unstarted kept it active forever.
|
||||
internal static bool StartsAutomatically(bool autoStartRequested, ulong eventCallback) =>
|
||||
autoStartRequested || eventCallback == 0;
|
||||
|
||||
internal static ulong GetAutoStartOffset(Generation generation, bool extended) =>
|
||||
IsGen5Target(generation)
|
||||
? extended ? 116UL : 108UL
|
||||
|
|
|
|||
|
|
@ -11,6 +11,18 @@ namespace SharpEmu.Libs.Tests.AvPlayer;
|
|||
|
||||
public sealed class AvPlayerAbiTests
|
||||
{
|
||||
[Theory]
|
||||
[InlineData(true, 0x1000UL, true)]
|
||||
[InlineData(false, 0UL, true)]
|
||||
[InlineData(true, 0UL, true)]
|
||||
[InlineData(false, 0x1000UL, false)]
|
||||
public void APlayerWithoutAnEventCallbackStartsOnItsOwn(bool autoStartRequested, ulong eventCallback, bool expected)
|
||||
{
|
||||
// Only a title that registers an event callback can see the ready state and call Start;
|
||||
// without one the player plays by itself, ends, and reports inactive.
|
||||
Assert.Equal(expected, AvPlayerExports.StartsAutomatically(autoStartRequested, eventCallback));
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(Generation.Gen4, false, 108UL)]
|
||||
[InlineData(Generation.Gen5, false, 108UL)]
|
||||
|
|
|
|||
Loading…
Reference in New Issue