aviwrite will not write a file with odd-numbered dimensions, always rescales
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
mame x1 smbsp -aviwrite smbsp.avi -snapsize 447x257 -seconds_to_run 30 -nothrottleffprobe ~/.mame/snap/smbsp.avi- (optional) view video, notice blurriness;
mpv --scale=oversample ~/.mame/snap/smbsp.avi
Additional details
No response
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;
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.
May I suggest to disable whatever mame does to avi output when the -snapsize option is used? That way mame keeps the default and people who need it can have their cake and eat it too, besides that is what -snapsize is supposed to do, right? Allow the user to choose the specific resolution they want.
I did a test with neogeo using -aviwrite with -snapsize 1080x1215, instead, mame generates an avi with 1080x1212. It also looks like the -nokeepaspect option doesn't bypass/disable this.
In the mame "multiple configuration files" page, it says "command line parameters take precedence over all else!" [source] Also in the -snapsize description, it says "MAME will create both snapshots and movies at the size specified".
However, it does not do so, which violates both statement.
It somewhat depends on the codec. Some codecs require the dimensions to be a multiple of 2, 4, 8 or even 16. MPEG works best with multiples of 8. There was plenty of transcoding software around that just plain refused to work on files with dimensions that aren’t a multiple of 2.
I don’t know how much the situation has changed since the circa 2010.
Codec doesn't matter in this use case. MAME is writing out a raw video in the AVI container. It's free to use any arbitrary sizes that the emulated machine outputs.
Post-processing can introduce its own limitations (due to other codecs), but I'd much rather deal with that than restrict MAME to only outputting dimensions in multiples of 4; the current system makes it almost useless for using these strange video output systems and video dumping.
The intention at the time was to not produce AVI files that popular transcoding software would refuse to process.
Is the snapsize option used for the video resolution? If it is, maybe MAME should just make it the user's responsibility to choose a size that's compatible with the codec they ultimately plan to compress it with.
I believe the current restrictions are a bad idea anyway (it violates the principle that MAME can record frame-perfect video), but a command line escape hatch would be an acceptable compromise.
I agree with @chungy, allow the user to decide the size of the recording without restrictions.
I believe the current restrictions are a bad idea anyway (it violates the principle that MAME can record frame-perfect video), but a command line escape hatch would be an acceptable compromise.
I'd like to expand on this with an additional thought I hadn't considered when I first wrote the message.
MAME allows for video recordings to be made at any point in runtime, the default keyboard bind is Ctrl-Shift-F12. This recording capability does not depend on playing back an input recording (to be fair, neither does -aviwrite), and it may be impossible to foresee the requirements beforehand, or even that you'd desire to make a video recording. I've done a fair few ad-hoc recordings of SNES games this way, myself. Combine this with the capability of many systems to resize their output, this introduces the chance an ad-hoc recording requires an unpredictable resolution, and these non-multiple-of-4 dimensions would just cause for a blurred/ugly recording, if it's even usable at all.
Limitations in video codecs in a post-processing pipeline shouldn't limit what MAME can do for itself, and especially shouldn't violate a principle of getting frame-perfect video out of MAME. These limitations can, and I think should, be addressed in the post-processing pipeline. As such, I am in favor of ditching this "feature" entirely.
Alternatives, such as a configuration or command line parameter, are unappealing but would remain better than nothing.
-aviwrite is intended as a stop gap option for capturing emulation at native speeds (i.e. Chihiro and upward) and assuming user is fine with the giant output and the possibility to break horribly in the long run (been there done that).
For any other use you either actually do a combination of -mngwrite & -wavwrite and postprocess later or just use OBS, ignoring that "pixel perfect" capturing doesn't really exist in nature.
As such, I am in favor of ditching this "feature" entirely.
"Fixing" it really means rethinking at root -> make MAME to output a virtual video/audio stream (abiding to the standards ) that the multimedia friends (i.e. GStreamer) can actually use and potentially convert instead (i.e. akin to how capturing real HW works).
This means no, it's already out of the question a deprecation here, needs a working cross platform alternative ready first to evaluate if -aviwrite deserves a removal.
We're not removing -aviwrite. And 447x257 sounds like an off-by-1 bug in the X1 CRTC emulation, but I don't know the details there.
X1 is 6845 with show_border_area(true) hack on -> showing everything including (putative) sync area.
assuming user is fine with the giant output and the possibility to break horribly in the long run (been there done that).
"giant output" is easy to deal with (I've had -aviwrite create upwards ~1.5TiB files, though fs compression made it only something like 100GiB). Never witnessed it break at all.
For any other use you either actually do a combination of
-mngwrite&-wavwriteand postprocess later
-mngwrite is already basically useless. Nothing supports it! I experimented, briefly in using it, and when I manage to cobble together old software that can dump info, it maybe outputs the right dimensions? But there's no way to get it into any actually usable codec. It's useless. :)
or just use OBS
Absolute non-starter. Best-case scenario: you can run an emulated MAME machine at full speed for the entire duration of an intended capture run and are willing to put up with scaling problems and conversion into yuv420p color space. -aviwrite is just better in every way. Can combine it with -nothrottle to make very fast video dumps of games (I've been able to dump out 2-hour Donkey Kong INPs in under a minute this way), and when an emulated machine cannot run at full speed on a host system, the AVI output is still the proper speed.
"giant output" is easy to deal with (I've had -aviwrite create upwards ~1.5TiB files, though fs compression made it only something like 100GiB). Never witnessed it break at all.
That's not exactly an efficient multimedia pipeline, believe it or not. I also feel like this issue is just concealing stuff at root anyway, Sharp X1 (and some other friends) requires a new 6845 core separate from the legacy one, and requires video capture input in the form of Telopper. If we are talking about what's a performant video capture output should be then we already have three issues here :)
About the file size, I can't read code but in aviio there are code to use HuffYUV for decompression. Is there a HuffYUV compression available?
mame sf2 -snapsize 640x480 -aviwrite sf2 -seconds_to_run 60
It creates a 3,8 GiB file.
Converting that to HuffYUV:
ffmpeg -hide_banner -i sf2.avi -c:v huffyuv -c:a copy test-huffyuv.avi
Now we have a 1,5 GiB lossless file.
That's not exactly an efficient multimedia pipeline, believe it or not.
It works well, why mess with it?
mame sf2 -snapsize 640x480 -aviwrite sf2 -seconds_to_run 60It creates a 3,8 GiB file.
Changing the -snapsize like that will create a bilinear scaled video. You might have a lossless conversion afterward, but it is not a lossless video from the onset.
Removing -snapsize and letting it run, results in a 893 MiB file, 384×224 pixel resolution. Following it with ffmpeg -i sf2.avi -c:a flac -c:v huffyuv -aspect 4:3 sf2.mkv will result in a 358 MiB file, correct aspect ratio, compressed audio, compressed video, all lossless. (FWIW, I tend to prefer magicyuv, it's faster, and the same test results in a 198 MiB file)
I don't really believe that MAME should be producing compressed streams, though. It'll have a performance impact and it's unnecessary as no matter what you do, you'll want to post-process the output anyway. Most compression codecs introduce decoding performance impacts that also makes it impractical to go backwards by single frames, in case you use -aviwrite as a pipeline for getting screenshots at "perfect" times (this is a common use for me and aviwrite).
Changing the
-snapsizelike that will create a bilinear scaled video.
Forgot to mention I use snapbilinear 0 in mame.ini, so that command is actually:
mame sf2 -snapsize 640x480 -nosnapbilinear -aviwrite sf2 -seconds_to_run 60
Nowadays, people like to use graphics (artworks), especially those who record vertical videos with artworks or some graphics that show the joystick moving, etc. In this case you'll have to set -snapsize and record everything 5x bigger, otherwise your artwork and everything else will be pixelated.
I don't really believe that MAME should be producing compressed streams
Mame can have both: -aviwrite for raw and/or maybe -aviwriteyuv for lossless compressed streams (I'm also a big fan of magicyuv instead of Huffy's). In the end this can benefit users that record long gameplays with -aviwrite.
Forgot to mention I use
snapbilinear 0in mame.ini, so that command is actually:
mame sf2 -snapsize 640x480 -nosnapbilinear -aviwrite sf2 -seconds_to_run 60
Still will have uneven pixels. :)