test: retire Metal frontend recordings on viewport changes

Wrap the existing changing-color/audio core with an opt-in geometry change at frame 90. Require direct and threaded native frontend recording to finalize before later frames and independently decode the resulting file after playback continues.
This commit is contained in:
Codex committed 2026-10-21 21:35:23 +02:00
1 parent e69e9db6fb
commit c25df2962c
3 files changed
+36 -1

No files matched your search

@@ -176,7 +176,7 @@ jobs:
run: |
set -eu
command -v ffmpeg >/dev/null && command -v ffprobe >/dev/null || brew install ffmpeg
cc -dynamiclib -std=gnu89 -Ilibretro-common/include samples/record/nvenc_frontend/core.c -o "$RUNNER_TEMP/metal-record-core.dylib" -lm
cc -dynamiclib -std=gnu89 -Ilibretro-common/include samples/record/metal_frontend/core.c -o "$RUNNER_TEMP/metal-record-core.dylib" -lm
python3 samples/record/metal_frontend/run.py --retroarch ./retroarch --core "$RUNNER_TEMP/metal-record-core.dylib" --output-dir "$RUNNER_TEMP/metal-frontend-recordings"
- uses: actions/upload-artifact@v6
if: always()
+18
View File
@@ -0,0 +1,18 @@
/* Copyright (C) 2026 The RetroArch team. SPDX-License-Identifier: GPL-3.0-or-later */
#define retro_run metal_fixture_run
#include "../nvenc_frontend/core.c"
#undef retro_run
void retro_run(void)
{
if (frames==90 && getenv("NATIVE_RECORD_VIEWPORT_CHANGE"))
{
struct retro_game_geometry geometry;
memset(&geometry,0,sizeof(geometry));
geometry.base_width=256; geometry.base_height=HEIGHT;
geometry.max_width=WIDTH; geometry.max_height=HEIGHT;
geometry.aspect_ratio=4.0f/3.0f;
if (!environment(RETRO_ENVIRONMENT_SET_GEOMETRY,&geometry)) abort();
fprintf(stderr,"[fixture] viewport geometry changed at frame 90\n");
}
metal_fixture_run();
}
+17
View File
@@ -127,3 +127,20 @@ for control in ('early', 'exists'):
assert destination.read_bytes()==b'preserve existing output',log
assert '[Metal recording] Failed' in log,log
print(f'PASS: real frontend {control}: bounded shutdown and output preservation',flush=True)
for threaded in ('false','true'):
changed=root/f'viewport-{threaded}.mp4'
changed_config=root/f'viewport-{threaded}.cfg'
changed_config.write_text(config.read_text(encoding='utf-8').replace(
'video_threaded = "true"',f'video_threaded = "{threaded}"'),encoding='utf-8')
changed_env=dict(env,NATIVE_RECORD_VIEWPORT_CHANGE='1')
result=subprocess.run([exe,'-v','--config',str(changed_config),'-L',core,
'--record',str(changed),'--recordconfig',str(record),'--max-frames','180'],
cwd=case,env=changed_env,stdout=subprocess.PIPE,stderr=subprocess.STDOUT,timeout=60)
log=result.stdout.decode(errors='replace')
(root/f'viewport-{threaded}.log').write_text(log,encoding='utf-8')
assert result.returncode==0 and '[fixture] viewport geometry changed' in log,log[-8000:]
done=re.search(r'Finalized (\d+) GPU frames, (\d+) PCM frames',log)
assert done and 0<int(done[1])<100 and '[Metal recording] Failed' not in log,log[-8000:]
subprocess.run([ffmpeg,'-v','error','-i',str(changed),'-f','null','-'],check=True,timeout=30)
print(f'PASS: real frontend viewport change threaded={threaded}: retired playable recording',flush=True)