Skip to content
 
 

Latest commit

 

History

126,816 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

FFmpeg README

FFmpeg is a collection of libraries and tools to process multimedia content such as audio, video, subtitles and related metadata.

Libraries

  • libavcodec provides implementation of a wider range of codecs.
  • libavformat implements streaming protocols, container formats and basic I/O access.
  • libavutil includes hashers, decompressors and miscellaneous utility functions.
  • libavfilter provides means to alter decoded audio and video through a directed graph of connected filters.
  • libavdevice provides an abstraction to access capture and playback devices.
  • libswresample implements audio mixing and resampling routines.
  • libswscale implements color conversion and scaling routines.
Format Container Platform Encode Decode
BPK1 .bpk, .bpk1, .apd Nintendo 3DS Swapdoodle / Swapnote ✅ ✅
DPG .dpg Nintendo DS (MoonShell) ✅ ✅
Factor 5 DivX .vid GameCube (Factor 5) ✅ ✅
FastVideo DS .fv Nintendo DS ✅ ✅
Flipnote Studio .ppm Nintendo DS / DSi — ✅
Flipnote Studio 3D .kwz Nintendo 3DS — ✅
GBA FVMV .gba Game Boy Advance (Pokémon) — ✅
GBA Video (ADS) .mmstr / .gba Game Boy Advance (Majesco) ✅ ✅
GBA Video (Caimans 2.2) .gba Game Boy Advance — ✅
GBA Video (CaimansPro) .gba Game Boy Advance — ✅
GBA Video (VX++) .gba Game Boy Advance (ActImagine) — ✅
HVQM4 .h4m GameCube / Wii (Hudson Soft) ✅ ✅
Nintendo Channel .3gp Wii ✅ ✅
Nintendo 3DS Camera (2D) .avi Nintendo 3DS ✅ ✅
MO .mo Nintendo Wii ✅ ✅
MOC2 / MOC3 .mo Nintendo Wii (early MobiClip) — ✅
MODS .mods Nintendo DS ✅ ✅
MOFLEX 2D .moflex Nintendo 3DS ✅ ✅
MOFLEX 3D .moflex Nintendo 3DS ✅ ✅
Super MOFLEX .moflex Nintendo 3DS ✅ ✅
RVID .rvid RocketVideo (DS) ✅ ✅
THP .thp GameCube / Wii ✅ ✅
Wii Photo Channel .avi Wii ✅ ✅
TiVo TyStream .ty / .ty+ / .tmf TiVo (Series 1–3) ✅ ✅
VX .vx Nintendo DS ✅ ✅

Audio formats

Format Container Platform Encode Decode
AST .ast GameCube / Wii ✅ ✅
BCSTM .bcstm Nintendo 3DS ✅ ✅
BCWAV .bcwav, .cwav Nintendo 3DS ✅ ✅
BFSTM .bfstm Nintendo Wii U ✅ ✅
BFWAV .bfwav, .fwav Nintendo Wii U / Switch ✅ ✅
BNS .bns Nintendo Wii (banner sound) ✅ ✅
BRSTM .brstm Nintendo Wii ✅ ✅
BTSND .btsnd Nintendo Wii U (boot sound) ✅ ✅
DSP-ADPCM .dsp GameCube / Wii / 3DS ✅ ✅
HPS .hps GameCube (HAL Laboratory) — ✅
NUS3BANK .nus3bank, .nus3audio Nintendo Wii U / 3DS ✅ ✅
RWAV .brwav, .rwav Nintendo Wii ✅ ✅
SADL .sadl Nintendo DS (Level-5) — ✅
Wii Photo Channel AAC .m4a Wii ✅ ✅
Nintendo 3DS Sound AAC .m4a Nintendo 3DS ✅ ✅

The DSP-ADPCM encoder derives its predictor coefficients over the whole stream, the same autocorrelation and Levinson refinement Nintendo's own DSPADPCM tool uses, so these land around 80 dB SDR. AST's ADPCM is AFC, a variant with a predictor table fixed by the format rather than derived, and lands around 65 dB; AST can also be written as uncompressed PCM, as can BRSTM, BFSTM and BCSTM. BTSND is always 48 kHz stereo big-endian PCM, because its player on the console reads no format fields at all.

BNS files are usually LZ10-compressed, wrapped in an IMD5 header, or both. Decoding unwraps whichever combination it finds; -compress 1 writes the compressed form.

RWAV, FWAV and CWAV are the same single-sample wave container across three console generations — Wii .brwav, Wii U / Switch .bfwav, 3DS .bcwav — and share one demuxer and one muxer here. All three carry DSP-ADPCM (adpcm_thp, or adpcm_thp_le when the BOM says little-endian), planar PCM16 or planar PCM8, and all three store their channels as separate blocks referenced from the INFO chunk rather than interleaved. The byte order is read from the 0xFEFF / 0xFFFE BOM at offset 4, not assumed from the magic, so a little-endian .brwav and a big-endian .bcwav both decode. These are the individual samples that RWAR / FWAR / CWAR wave archives and the RBNK / BRSAR instrument banks reference; the sibling wiimms-szs-tools-plus unpacks those archives into the loose wave files this reads and writes.

ffmpeg -i input.wav -c:a adpcm_thp out.brwav
ffmpeg -i input.wav -c:a adpcm_thp out.bfwav
ffmpeg -i input.wav -c:a pcm_s16le_planar out.bcwav
ffmpeg -i sound.bcwav out.wav

They are FFmpeg-level formats only: encode.py and the GUI do not list them among their audio targets yet, so use ffmpeg directly.

MOC2 and MOC3 are the two MobiClip container generations that predate the .mo layout the mo demuxer reads, and use the same .mo extension. The moc3 demuxer covers the fla2, gvi3 and vid2 payload tags; vid2 carries MOC5-style chunk headers, while fla2 and gvi3 are a raw bitstream whose frame boundaries are recovered by scanning. It is decode-only — new files are written in the mo layout — and vid2 seeking is not implemented. Its header size is not fixed (64 bytes on MOC2, 240/284/288/292 on MOC3), so it is read from the header rather than assumed.

Decode-only inputs (the FVMV, Caimans, and VX++ GBA Video cartridge families and both Flipnote formats) can be transcoded into any of the encodable formats above, or previewed with encode.py decode <file>. Series-3 TiVo TyStreams (and MFS VideoClip resources) are handled through an internal port of the s3tots tool, which losslessly rewraps them to MPEG-2 TS before FFmpeg reads them.

TiVo .ty encoding (the ty muxer, mpeg2video + mp2/ac3) is ported from the "tyffmpeg" encoding library and targets the common Series 2 (Stand-Alone) container layout; it requires --enable-gpl and does not write .ty+'s trailing XML metadata block or Series 1/3-specific PES framing.

HVQM4 encoding (the hvqm4 codec + muxer) is a from-scratch implementation: per-block DC prediction, greedy nest-basis matching pursuit for the AC/texture residual (in place of the original's VQ codebook), literal-block escape, and P-pictures with per-8x8 integer-pixel motion search plus intra fallback. It is built directly against the bundled decoder rather than any original Hudson Soft encoder. Half-pixel search, predictive AOT residuals, and B-pictures are not implemented yet. Set FFmpeg's -g option to control the I-picture interval (-g 1 produces an all-intra stream).

Encoding ADS-era GBA Video

The ads_gba encoder and mmstr muxer write the in-house codec Majesco used before the GCC-era carts moved to ActImagine VX. Frames are all-intra and carry no prediction at all: a frame is nothing but 8-bit indices into a 256-entry codebook, which is built by k-means over every block in a chunk.

ffmpeg -i input.mp4 -s 240x160 -pix_fmt rgb24 -c:v ads_gba movie.mmstr

The bundled front ends expose both compressor generations directly:

python3 encode.py gba_ads none input.mp4       # LZMA / Dragon Ball GT lineage
python3 encode.py gba_hydrogen none input.mp4  # Inflate / Hydrogen lineage

They also appear as separate GBA Video choices in the GUI. Both outputs are .mmstr resources for insertion into a compatible cartridge image; they are not bootable .gba ROMs.

-chunk_frames sets how many frames share one codebook, trading size against sharpness — 30 frames of testsrc2 span 37.9 KB at 1 and 10.9 KB at 32, for about 31 dB either way, because what actually compresses here is consecutive frames reusing the same entries. -mode picks the block geometry: the even modes keep one chroma sample for a whole block, the odd ones one per block row. Mode 5 is refused rather than encoded, because it declares two chroma samples for a three-row block and the decoder reads the third off the end of the entry into its neighbour — a ROM quirk the decoder reproduces faithfully and that nothing can sensibly target. Modes 2, 3 and 4 have three-pixel-tall blocks, so they need a height divisible by three and cannot cover the GBA's 160 lines.

Blobs go through one of two compressors, picked with -compression:

  • 0 (default) — the LZMA the ADS-era / Dragon Ball GT lineage runs (adslzmaenc.c), stock LZMA with lc=0, lp=0, pb=2 and no end marker, the exact inverse of the bundled decoder. Every probability-coded decision mirrors the decoder's bit-read one for one, which is what lets two independently-run range coders track one adaptive model without either side ever transmitting it. The match finder is a plain greedy hash-chain search with repeated-distance and short-rep preference, not a multi-pass optimal parse — that costs ratio, not correctness.
  • 1 — the Hydrogen-era compressor (majescoenc.c) that Dora the Explorer and the rest of that lineage use instead: DEFLATE-shaped, but bits run most significant first out of little-endian halfwords, a block header is a bare 2-bit type with no BFINAL, and the uncompressed size in each blob's prefix is the only thing that ends the stream. Stored, fixed-Huffman and dynamic-Huffman encodings are all built and the cheapest kept, which bounds the incompressible case.

Both write the same 8-byte [uint32 uncompressed_size][uint32 params] prefix, and reading a bare .mmstr infers which compressor was used from the first blob rather than needing to be told.

One caveat: this writes .mmstr resource files, not cartridges — nothing here rebuilds a ROM. Audio is decode-only, since the cart's ADPCM has no encoder yet.

Wii Photo Channel and Nintendo Channel

wii_photo writes an ordinary Motion-JPEG AVI for the Wii Photo Channel. It defaults to 640x480 (the Channel accepts up to 848x480), with 32 kHz PCM audio when audio is selected. Nintendo only guarantees the video component, so use none if playback of an AVI's sound track is unreliable on a particular Wii.

python3 encode.py wii_photo pcm input.mp4

wii_photo_m4a writes AAC-LC M4A for Photo Channel 1.1. 3ds_sound writes the same broadly compatible 44.1 kHz / 128 kb/s stereo AAC-LC profile; it is within Nintendo 3DS Sound's 16-320 kb/s and 32-48 kHz limits.

python3 encode.py wii_photo_m4a aac input.wav
python3 encode.py 3ds_sound aac input.wav

nintendo_channel reproduces the delivery profile found in the UK Nintendo Channel 2009 archive: 3gp6, H.264 constrained-baseline level 2.1 at 378x284 and 25 fps, and stereo AAC-LC at 32 kHz. It requires the same --enable-libx264 build configuration as MobiClip video encoding.

python3 encode.py nintendo_channel aac input.mp4

3ds_camera writes a 2D-compatible Camera AVI: 480x240, 20 fps, Motion JPEG, and 16 kHz mono IMA ADPCM. 3ds_camera3d takes left and right input files and writes the Camera's native two-track stereoscopic MJPEG layout (left eye first). Copy either file to a DCIM camera folder and name it in the Camera's HNI_####.AVI style.

python3 encode.py 3ds_camera adpcm input.mp4
python3 encode.py 3ds_camera3d adpcm left.mp4 right.mp4

Splitting stereoscopic MOFLEX video

The MOFLEX demuxer exports the VideoWithLayout descriptor as standard stereoscopic side data. Nintendo 3DS layout 0/1 video stores the left and right eyes as alternating decoded frames, so both eyes must be decoded before they are separated. This example duplicates the audio into two ordinary MP4 files:

ffmpeg -i input.moflex \
  -filter_complex "[0:v]split=2[vl][vr];[vl]stereo3d=al:ml,sidedata=delete:type=STEREO3D[left];[vr]stereo3d=al:mr,sidedata=delete:type=STEREO3D[right]" \
  -map "[left]"  -map 0:a? -c:v h264_videotoolbox -c:a aac left.mp4 \
  -map "[right]" -map 0:a? -c:v h264_videotoolbox -c:a aac right.mp4

For layout 1 (right-first), exchange al for ar. Layouts 2/3 and 4/5 are top/bottom and side-by-side respectively and can be separated with the corresponding stereo3d input mode.

encode.py decode does this automatically — it reads the layout from the side data and writes name_left.mp4 / name_right.mp4, or just one eye with --eyes left|right, or the untouched stream with --eyes packed.

Playback

encode.py play <file> opens any supported input in a window without writing anything to disk, which is the quickest way to check a file:

python3 encode.py play movie.mods                   # DS clip, in a window
python3 encode.py play movie.moflex                 # 3D: both eyes side by side
python3 encode.py play movie.moflex --eyes left     # 3D: one eye, full window

Playback uses the bundled ffplay, which links the same decoders as ffmpeg, so nothing is written to disk and no external player is involved. ffplay is only built when the tree is configured with SDL2 (--enable-sdl2, the default when SDL2 is installed); without it, play says so rather than falling back to a system player that cannot read these formats.

Tools

  • ffmpeg is a command line toolbox to manipulate, convert and stream multimedia content.
  • ffplay is a minimalistic multimedia player.
  • ffprobe is a simple analysis tool to inspect multimedia content.
  • Additional small tools such as aviocat, ismindex and qt-faststart.
Audio Codec MOFLEX (3DS) MODS (DS) MO (Wii)
ADPCM ✅ ✅ ✅
FastAudio ✅ ✅ ✅
PCM ✅ ✅ ✅
Vorbis ➖ ➖ ✅
Codebook (SX) ➖ ✅ ➖

Building

Mobiclip video encoding (-c:v mobiclip, and therefore every .mo / .moflex / .mods output) is implemented as a fork of x264, so it is only compiled in when FFmpeg is configured with --enable-libx264. Configure without it and the mobiclip encoder is simply absent — decoding and the non-Mobiclip formats still work, which makes the omission easy to miss.

The fork is required; stock x264 does not implement the Mobiclip bitstream:

git clone https://github.com/quatric/x264 && cd x264
./configure --prefix="$PWD/../x264-install" --enable-static --enable-pic --disable-cli
make -j && make install
cd .. && PKG_CONFIG_PATH="$PWD/x264-install/lib/pkgconfig" \
  ./configure --enable-gpl --enable-libx264 && make -j

Confirm with ffmpeg -encoders | grep mobiclip.

Documentation

For full technical documentation of the MobiClip formats (video/audio codecs, container layouts, and platform requirements across the DS/3DS/Wii), see The Mobiclip Formats.

The offline documentation is available in the doc/ directory.

The online documentation is available in the main website and in the wiki.

Examples

Coding examples are available in the doc/examples directory.

License

FFmpeg codebase is mainly LGPL-licensed with optional components licensed under GPL. Please refer to the LICENSE file for detailed information.

Copyright (c) 2026 quatric

About

World's first OSS video encoder for Wii, 3DS, and DS Mobiclip Video

Resources

Contributing

Stars

32 stars

Watchers

3 watching

Forks

Releases

Packages

Contributors

Languages