Odin bindings for pl_mpeg, an
MIT-licensed single-file C library that demuxes MPEG Program Streams (.mpg)
and decodes MPEG1 video and MP2 audio.
The original pl_mpeg sources are vendored untouched in src/. This
repository only adds the Odin binding (pl_mpeg.odin) and the tooling to build
and link it.
The vendored pl_mpeg sources live in the src/ submodule. Clone it (pinned to
the tested commit) with:
git clone --depth=1 https://github.com/dssutg/odin-plmpeg
cd odin-plmpeg
git submodule update --init --recursive # pins src/ to a stable commitThe exact commit is recorded in this repository's git index (not in
.gitmodules and not tied to upstream master). So even when upstream pl_mpeg
moves on, a fresh clone always checks src/ out at a stable commit that this
binding is tested against. This is to prevent accidental breaking changes of the underlying library API.
Existing clones that skipped submodules just run the
git submodule update line above to get the same pinned checkout.
Deliberately bumping the pin once upstream has moved:
git -C src pull origin master
git add src && git commit -m "bump pl_mpeg"Never edit src/ in place; treat it as an external dependency.
- Odin
- a C compiler (
cc) and archiver (ar)
build.sh compiles the vendored C implementation into a static library that
the binding links against:
./build.sh # Linux/macOS: produces libplmpeg.a
build.bat # Windows: produces libplmpeg.a
./build.sh <path> # custom output pathOn Windows, build.bat auto-detects MSVC (cl -> .lib) vs MinGW
(gcc/ar -> .a). Set CC, AR or CFLAGS to override the compiler,
archiver or flags:
CC=clang ./build.shThe plmpeg package imports the library as system:plmpeg, so the linker
looks for libplmpeg.a in the standard search paths. Either install it there
or point the linker at its location:
odin build my_app.odin -extra-linker-flags:"-L<path> -lplmpeg"package main
import plmpeg "..."
import "core:fmt"
video_cb :: proc "c" (self: ^plmpeg.Plm, frame: ^plmpeg.Frame, user: rawptr) {
fmt.println("frame:", frame.width, "x", frame.height, "at", frame.time)
}
main :: proc() {
plm := plmpeg.create_with_filename("video.mpg")
defer plmpeg.destroy(plm)
plmpeg.set_video_decode_callback(plm, video_cb, nil)
for plmpeg.has_ended(plm) == 0 {
plmpeg.decode(plm, 1.0 / 60.0)
}
}Audio works the same way through plmpeg.set_audio_decode_callback and
plmpeg.Audio_Decode_Callback. A full usage walkthrough with build, link and
decode examples lives in the header comment of pl_mpeg.odin.
pl_mpeg only plays MPEG-1 video and MPEG-2 audio inside an MPEG Program
Stream (.mpg), so most source files need converting first.
The codec pair to target is MPEG-1 video (-c:v mpeg1video) and MPEG-1/2
Layer II audio (-c:a mp2), wrapped in an MPEG-PS container (-f mpeg):
ffmpeg -i input.mp4 -c:v mpeg1video -q:v 4 -c:a mp2 -b:a 192k -f mpeg output.mpgNotes:
-q:vsets MPEG-1 quality (2-31, lower is better; 4 is a good trade-off).-q:v 0lets ffmpeg pick the best quality.- MPEG-1 does not support modern resolutions well; rescale to a small,
normal-PAR size whose width and height are multiples of 16 (e.g.
-vf scale=256:192). SBG/PAR flags and interlacing are not supported. - Keep the audio bitrate at one of the standard MP2 rates (e.g.
32k,48k,56k,64k,128k,192k,256k,384k). - Any media (MKV, AVI, WebM, streams, etc.) can be used as input; ffmpeg
converts and muxes it into the
.mpgprogram stream.
Synthesize a quick test clip when you have no source footage:
ffmpeg -f lavfi -i testsrc=duration=2:size=160x128 -f lavfi -i \
sine=frequency=440:duration=2 -c:v mpeg1video -q:v 0 -c:a mp2 -b:a 128k \
-f mpeg clip.mpgThe package name (plmpeg) already provides a namespace, so the C plm_
prefix and _t suffix are dropped from every identifier:
| C name | Odin name |
|---|---|
plm_create_with_filename |
create_with_filename |
plm_frame_t |
Frame |
plm_buffer_t |
Buffer |
plm_samples_t |
Samples |
plm_video_decode_callback |
Video_Decode_Callback |
PLM_DEMUX_PACKET_AUDIO_1 |
Packet_Audio_1 |
pl_mpeg.odin Odin binding (package plmpeg)
pl_mpeg_odin.c C implementation translation unit for the binding
build.sh builds libplmpeg.a (Linux/macOS)
build.bat builds libplmpeg.a (Windows)
README.md this file
AGENTS.md guidance for AI agents
src/ vendored pl_mpeg sources (do not modify)
examples/
plmpeg_and_sdl2/ minimal MPEG player using this binding and SDL2
MIT. The vendored src/ preserves the upstream pl_mpeg license.