mamedev / mame

MAME
https://www.mamedev.org/
Other
8.41k stars 2.04k forks source link

aviwrite will not write a file with odd-numbered dimensions, always rescales #12775

Open chungy opened 2 months ago

chungy commented 2 months ago

MAME version

mame0269-234-g233a5e82799

System information

Arch Linux, x86-64, 64GB system RAM

INI configuration details

#
# CORE CONFIGURATION OPTIONS
#
readconfig                1
writeconfig               0

#
# CORE SEARCH PATH OPTIONS
#
homepath                  .
rompath                   $HOME/.mame/roms;$HOME/.mame/sw-roms;$HOME/.mame/sw-chds
hashpath                  $HOME/.mame/hash;/usr/lib/mame/hash
samplepath                $HOME/.mame/samples
artpath                   $HOME/.mame/artwork;/usr/lib/mame/artwork
ctrlrpath                 $HOME/.mame/ctrlr;/usr/lib/mame/ctrlr
inipath                   $HOME/.mame/ini
fontpath                  .
cheatpath                 cheat
crosshairpath             crosshair
pluginspath               /usr/lib/mame/plugins
languagepath              $HOME/.mame/language;/usr/lib/mame/language
swpath                    software

#
# CORE OUTPUT DIRECTORY OPTIONS
#
cfg_directory             $HOME/.mame/cfg
nvram_directory           $HOME/.mame/nvram
input_directory           $HOME/.mame/inp
state_directory           $HOME/.mame/sta
snapshot_directory        $HOME/.mame/snap
diff_directory            $HOME/.mame/diff
comment_directory         $HOME/.mame/comments
share_directory           share

#
# CORE STATE/PLAYBACK OPTIONS
#
state                     
autosave                  0
rewind                    0
rewind_capacity           100
playback                  
record                    
exit_after_playback       0
mngwrite                  
aviwrite                  
wavwrite                  
snapname                  %g/%i
snapsize                  auto
snapview                  auto
snapbilinear              1
statename                 %g
burnin                    0

#
# CORE PERFORMANCE OPTIONS
#
autoframeskip             0
frameskip                 0
seconds_to_run            0
throttle                  1
sleep                     1
speed                     1
refreshspeed              0
lowlatency                1

#
# CORE RENDER OPTIONS
#
keepaspect                1
unevenstretch             1
unevenstretchx            0
unevenstretchy            0
autostretchxy             0
intoverscan               0
intscalex                 0
intscaley                 0

#
# CORE ROTATION OPTIONS
#
rotate                    1
ror                       0
rol                       0
autoror                   0
autorol                   0
flipx                     0
flipy                     0

#
# CORE ARTWORK OPTIONS
#
artwork_crop              0
fallback_artwork          
override_artwork          

#
# CORE SCREEN OPTIONS
#
brightness                1.0
contrast                  1.0
gamma                     1.0
pause_brightness          0.65
effect                    none

#
# CORE VECTOR OPTIONS
#
beam_width_min            1.0
beam_width_max            1.0
beam_dot_size             1.0
beam_intensity_weight     0
flicker                   0

#
# CORE SOUND OPTIONS
#
samplerate                48000
samples                   1
volume                    0
compressor                1
speaker_report            0

#
# CORE INPUT OPTIONS
#
coin_lockout              1
ctrlr                     
mouse                     0
joystick                  1
lightgun                  0
multikeyboard             0
multimouse                0
steadykey                 0
ui_active                 0
offscreen_reload          0
joystick_map              auto
joystick_deadzone         0.3
joystick_saturation       0.85
joystick_threshold        0.3
natural                   0
joystick_contradictory    0
coin_impulse              0

#
# CORE INPUT AUTOMATIC ENABLE OPTIONS
#
paddle_device             keyboard
adstick_device            keyboard
pedal_device              keyboard
dial_device               keyboard
trackball_device          mouse
lightgun_device           mouse
positional_device         keyboard
mouse_device              mouse

#
# CORE DEBUGGING OPTIONS
#
verbose                   0
log                       0
oslog                     0
debug                     0
update_in_pause           0
debugscript               
debuglog                  0

#
# CORE COMM OPTIONS
#
comm_localhost            0.0.0.0
comm_localport            15112
comm_remotehost           127.0.0.1
comm_remoteport           15112
comm_framesync            0

#
# CORE MISC OPTIONS
#
drc                       1
drc_use_c                 0
drc_log_uml               0
drc_log_native            0
bios                      
cheat                     0
skip_gameinfo             1
uifont                    default
ui                        cabinet
ramsize                   
confirm_quit              0
ui_mouse                  1
language                  English
nvram_save                1

#
# SCRIPTING OPTIONS
#
autoboot_command          
autoboot_delay            0
autoboot_script           
console                   0
plugins                   1
plugin                    
noplugin                  

#
# HTTP SERVER OPTIONS
#
http                      0
http_port                 8080
http_root                 web

#
# OSD INPUT MAPPING OPTIONS
#
uimodekey                 SCRLOCK
controller_map            none
background_input          0

#
# OSD FONT OPTIONS
#
uifontprovider            auto

#
# OSD OUTPUT OPTIONS
#
output                    auto

#
# OSD INPUT OPTIONS
#
keyboardprovider          auto
mouseprovider             auto
lightgunprovider          auto
joystickprovider          auto

#
# OSD DEBUGGING OPTIONS
#
debugger                  auto
debugger_port             23946
debugger_font             auto
debugger_font_size        0
watchdog                  0

#
# OSD PERFORMANCE OPTIONS
#
numprocessors             auto
bench                     0

#
# OSD VIDEO OPTIONS
#
video                     opengl
numscreens                1
window                    0
maximize                  1
waitvsync                 0
syncrefresh               0
monitorprovider           auto

#
# OSD PER-WINDOW VIDEO OPTIONS
#
screen                    auto
aspect                    auto
resolution                auto
view                      auto
screen0                   auto
aspect0                   auto
resolution0               auto
view0                     auto
screen1                   auto
aspect1                   auto
resolution1               auto
view1                     auto
screen2                   auto
aspect2                   auto
resolution2               auto
view2                     auto
screen3                   auto
aspect3                   auto
resolution3               auto
view3                     auto

#
# OSD FULL SCREEN OPTIONS
#
switchres                 0

#
# OSD ACCELERATED VIDEO OPTIONS
#
filter                    0
prescale                  1

#
# OpenGL-SPECIFIC OPTIONS
#
gl_forcepow2texture       0
gl_notexturerect          0
gl_vbo                    1
gl_pbo                    1
gl_glsl                   0
gl_glsl_filter            1
glsl_shader_mame0         none
glsl_shader_mame1         none
glsl_shader_mame2         none
glsl_shader_mame3         none
glsl_shader_mame4         none
glsl_shader_mame5         none
glsl_shader_mame6         none
glsl_shader_mame7         none
glsl_shader_mame8         none
glsl_shader_mame9         none
glsl_shader_screen0       none
glsl_shader_screen1       none
glsl_shader_screen2       none
glsl_shader_screen3       none
glsl_shader_screen4       none
glsl_shader_screen5       none
glsl_shader_screen6       none
glsl_shader_screen7       none
glsl_shader_screen8       none
glsl_shader_screen9       none

#
# OSD SOUND OPTIONS
#
sound                     auto
audio_latency             2

#
# PORTAUDIO OPTIONS
#
pa_api                    none
pa_device                 none
pa_latency                0

#
# OSD MIDI OPTIONS
#
midiprovider              auto

#
# OSD EMULATED NETWORKING OPTIONS
#
networkprovider           auto

#
# BGFX POST-PROCESSING OPTIONS
#
bgfx_path                 $HOME/.mame/bgfx;/usr/lib/mame/bgfx
bgfx_backend              auto
bgfx_debug                0
bgfx_screen_chains        default
bgfx_shadow_mask          slot-mask.png
bgfx_lut                  
bgfx_avi_name             auto

#
# SDL PERFORMANCE OPTIONS
#
sdlvideofps               0

#
# SDL VIDEO OPTIONS
#
centerh                   1
centerv                   1
scalemode                 none

#
# SDL FULL SCREEN OPTIONS
#
useallheads               0
attach_window             

#
# SDL KEYBOARD MAPPING
#
keymap                    0
keymap_file               keymap.dat

#
# SDL JOYSTICK MAPPING
#
sixaxis                   0

#
# SDL LIGHTGUN MAPPING
#
lightgun_index1           auto
lightgun_index2           auto
lightgun_index3           auto
lightgun_index4           auto
lightgun_index5           auto
lightgun_index6           auto
lightgun_index7           auto
lightgun_index8           auto

#
# SDL LOW-LEVEL DRIVER OPTIONS
#
videodriver               auto
renderdriver              auto
audiodriver               auto
gl_lib                    auto

Emulated system/software

x1 smbsp

Incorrect behaviour

The game runs at 447x257, making it impossible to capture a clean video with all pixels intact, no more or less. The system starts up at 640x480 and as such, aviwrite will start out writing a file with these parameters, but the game display remains blurry and scaled.

Running MAME with mame x1 smbsp -snapsize 447x257 -aviwrite smbsp will cause the emulator to instead output a file with dimensions 444x256, notably the next step downwards to multiple-of-4 dimensions.

Expected behaviour

The AVI file be accurately written at 447x257. While these are unusual dimensions and most intraframe codecs (eg, H.264, AV1) require either multiple-of-2 or multiple-of-4 dimensions, MAME dumps out rawvideo in an AVI container and should not be subject to the same limitation.

ffmpeg, for example, can generate such an example file: ffmpeg -f lavfi -i testsrc=s=447x257 -t 10 -c:v rawvideo test.avi

Steps to reproduce

  1. mame x1 smbsp -aviwrite smbsp.avi -snapsize 447x257 -seconds_to_run 30 -nothrottle
  2. ffprobe ~/.mame/snap/smbsp.avi
  3. (optional) view video, notice blurriness; mpv --scale=oversample ~/.mame/snap/smbsp.avi

Additional details

No response

happppp commented 2 months ago

This is deliberate, and yes, a lot of video software refuses to process non-multiple of 4 dimensions. It's good as a default, but unfortunately no option is available to override it.

src/lib/util/aviio.cpp

/**
 * @def AVI_INTEGRAL_MULTIPLE
 *
 * @brief   Ensures the integral multiple of the video dimension, because most video players are not capable to playback a video stream with a lower multiple.
 */

static constexpr int AVI_INTEGRAL_MULTIPLE = 4;
chungy commented 2 months ago

This is deliberate, and yes, a lot of video software refuses to process non-multiple of 4 dimensions. It's good as a default, but unfortunately no option is available to override it.

I'm not sure what makes this "good as a default"; because some software is buggy? Not sure what qualifies as "a lot of video software" either. The test file generated by ffmpeg plays back in everything I've tried (but maybe related to me being on Linux, where most everything is linked to ffmpeg anyhow), and obviously ffmpeg itself handles it.

At any rate, I feel like -aviwrite is a good intermediate to get raw pixels out of a system at the proper framerate and everything. Perhaps massaging the data to fit future constraints is desirable in some use cases (eg, re-encoding it to AV1), but that's easy to handle in post-processing the video, by padding, scaling, whatever is a good idea. Sometimes I've also used aviwrite just to assist in getting screenshots, since it makes it easier to go forward and backward on a frame-by-frame basis, and MAME writing it out guarantees that every frame is as the emulated system draws it.

Anyhow, editing the source at least outputs the video at the desired dimensions, but it's still getting bilinear filtering applied and not the crispy pixels that I really want. Setting -nosnapbilinear doesn't help, it just causes uneven pixels, with some of the rows not even coming out in the output. Notably the uneven pixels even happens if I use -nosnapbilinear -snapsize $((447*4))x$((257*4)); though at least at that size, it's possible to write a program to extract the proper raw pixels and get it back to the original size. Maybe there's two bugs here.