This is a tutorial for creating 3DO “stream” files which are compatible with the PlayMovie app found in some games (such as Doom) or NuPlayer found in the streaming examples. Substituting movietostream with movietostream_shuttle will create a stream compatible with ShuttlePlayer. See the Streaming examples for more details.
Like other platforms at the time the 3DO's typical video codec was Cinepak. Audio generally is 8 or 16bit signed big endian PCM which can be compressed (AIFF or AIFC).
The 3DO SDK provides a number of tools to enable converting to Cinepak, compress audio, and then mux into the “stream” format used by the standard data streaming library. You can, and should, check out the original docs for more details.
You will need a MacOS 3DO development environment. You can find a system PPC QEMU image here.
This guide expects 3DO Toolkit 1.5, 3DO Portfolio 2.5, MPW, and Quicktime Pro 6.0.3 (+ MPEG4/Divx codecs) installed.
The file we'll be processing is myvideo.mkv
and within MacOS exists on a drive labeled scratch
as in the QEMU image linked above.
We first need to take our source video and convert it into something Quicktime will be able to process. Given the age of Quicktime 6.0.3 used in MacOS9 the best and most recent codec available to us is MPEG-4 Part 2 (Divx). This will give the smallest and best quality to later convert to Cinepak. Alternatively we could use qtrle which is lossless but the file will be huge there doesn't appear to be a significance difference in encode time or quality between them. The overall compression is very slightly better when using a qtrle source but visually appears the same.
While FFMPEG does have a Cinepak encoder it is 1) extremely slow. 2) Causes the 3DO tool movietostream to crash.
The vaguedenoiser and fps filters can be removed but the denoiser can help compression and clarity when encoding to Cinepak and the framerate change may be necessary to work around the fps issue mentioned above. The scaler will maximize the resolution depending on the aspect ratio. The max being 320×240. If you are targeting a CRT then 304×228 or 288×216 are recommended resolutions given the overscan.
$ ffmpeg \ -i "myvideo.mkv" \ -vf "vaguedenoiser,scale='if(gt(a,320/240),320,-1)':'if(gt(a,320/240),-1,240)':force_original_aspect_ratio=decrease,fps=30000/1001" \ -c:v mpeg4 \ -qscale:v 0 \ -an \ -sn \ -y \ "file:myvideo.mov"
For audio we can convert directly to AIFF which could be used without further encoding but most likely you'll want to compress it to save space. That special compressed format, AIFC, is not supported by FFMPEG so we'll handle that in the next step.
From the docs: tktfldr/dsgfldr/2dsgc.html
Sample audio at 44 kHz and convert it to lower sample rates as appropriate. Deciding on the optimal compression may require some experimentation. Here's some information to help you decide on compression rate:
CD quality stereo requires 176 KB/s.
The lowest quality sound currently offered(22 K Mono 4:1) is acceptable for voice in most cases.
Most music can use 22 K 16-bit stereo 2:1 compressed (44KB/s data rate). High frequencies are attenuated, but not usually too much.
Most audio sounds better at 2:1 compression than at 4:1. 22 KB 2:1 sounds better than 44 KB 4:1-and they have the same data rate.
$ ffmpeg \ -i myvideo.mkv \ -vn \ -c:a pcm_s16be \ -ar 22050 \ -ac 2 \ -sn \ "file:myvideo.aiff"
$ ffmpeg \ -i myvideo.mkv \ -vn \ -c:a pcm_s16be \ -ar 22050 \ -ac 1 \ -sn \ "file:myvideo.aiff"
Transfer myvideo.mov
and myvideo.aiff
to the MacOS system. There are a number of ways to do this but an easy way is to use an FTP or HTTP server on the host system and use NetFiller or Classzilla to copy the files to the scratch
drive.
scratch:myvideo.mov
in Quicktimescratch:myvideo.cvid
)MovieCompress is a tool provided with the 3DO SDK. It's not clear if the tool is buggy generally or not toally compatible with OS9 but the output seems to crash movietostream. More testing is needed.
If you've already selected the sample rate, channels, etc. when using FFMPEG skip to 5.
scratch:myvideo.aiff
in Quicktimescratch:myvideo.aiff
scratch:myvideo.aifc
)Run these commands within MPW Shell. The keypad enter key is required to execute command or click on the MPW Shell button in the top left of the MPW Shell window.
movietostream -b 65536 -o scratch:myvideo.film scratch:myvideo.avi
sftostream -o scratch:myvideo.saudio -i scratch:myvideo.aifc
Annoyingly the Weave program requires a separate file to work rather than using command line arguments. Here is a generic script that should work for exclusive video/audio streaming (where an app isn't also doing other things). Open SimpleText or similar text editor and create a plain text file with the content below.
You can read more about Weave script commands at: tktfldr/dsrfldr/dsr4frst.html
weaver.script
writestreamheader writemarkertable streamblocksize 98304 mediablocksize 2048 streambuffers 6 streamerdeltapri 6 dataacqdeltapri 8 preloadinstrument SA_22K_16B_S_SDX2 audioclockchan 0 enableaudiomask 0x3 subscriber FILM 10 subscriber SNDS 7 subscriber CTRL 11 streamstarttime 0 file scratch:myvideo.saudio 0 0 file scratch:myvideo.film 1 0
Notes:
enableaudiomask
: stereo = 0x3 and mono = 0x1file
: The last value is a start time offset in audio ticks. There are 240 audio ticks per second. You can set an offset to help with desync but it will still de-sync over time.preloadinstrument
: change to SA_22K_16B_M_SDX2 for mono or just leave it out and let the system handle it.
Once the script is saved (let's call it weaver.script
) we can now “weave” the stream files (myvideo.film and myvideo.saudio) together.
weaver -o scratch:myvideo.stream <scratch:weaver.script
Coming
Will be creating a simple project that enables building 3DO ISOs dedicated to playing video clips.