FFmpeg FFI
| (require (file "../ffmpeg-ffi.rkt")) | package: base |
This module provides the low-level Racket FFI binding for the native FFmpeg audio shim. The native shim exposes an opaque FFmpeg instance and keeps all decoder state inside that instance.
The output format of the native shim is signed 32-bit interleaved PCM. The buffer returned by the native layer is copied into Racket-managed memory before it is passed to higher layers.
procedure
(fmpg-ffi-decoder-handler) → procedure?
The returned procedure manages one native FFmpeg instance. Commands are sent as a symbol followed by command-specific arguments.
'new creates the native FFmpeg instance and returns #t.
'delete frees the native FFmpeg instance and returns #t.
'init opens a file and fetches stream and metadata information.
'close closes the currently opened file.
'format calls a format callback with the current stream format.
'info writes stream information to the sound logger.
'read decodes the next audio block.
'seek seeks to an absolute PCM sample position.
'tell returns the current PCM sample position.
'file returns the currently opened filename.
'metadata returns a hash with file metadata.
1 Command Interface
The command handler is used as follows:
(define h (fmpg-ffi-decoder-handler)) (h 'new) (h 'init filename) (h 'read audio-callback format-callback) (h 'close) (h 'delete)
The 'new command must be called before 'init. A handler owns at most one native FFmpeg instance. Calling 'new twice without 'delete raises an error.
2 Format Callback
The 'format command and the first 'read call report the stream format by calling the supplied callback as follows:
(format-callback pcm-pos sample-rate channels bits-per-sample bytes-per-sample pcm-length)
The pcm-pos argument is the current PCM sample position. The pcm-length argument is the total number of PCM samples, or -1 when this is not known.
3 Reading Audio
The 'read command decodes one audio block. It expects an audio callback and a format callback:
(h 'read audio-callback format-callback)
On the first read, the format callback is called before audio data is returned. If decoding produces data, the audio callback is called as:
(audio-callback 'data pcm-pos buffer size)
The pcm-pos argument is the absolute sample position of the first sample frame in the buffer. The buffer argument points to a copied PCM buffer, and size is the buffer size in bytes.
When the stream ends, the callback is called as:
(audio-callback 'done -1 #f 0)
The command returns #t.
4 Seeking
The 'seek command takes an absolute PCM sample position:
(h 'seek pcm-pos)
The sample position is converted to milliseconds using the current sample rate and is then passed to the native FFmpeg shim. After seeking, the current PCM position is updated from the native decoder.
5 Metadata
The 'metadata command returns a mutable hash with the following keys:
'title
'author
'album
'genre
'comment
'copyright
'year
'track
'bitrate
'duration-ms
'audio-streams
Missing string fields are returned as empty strings. Missing numeric fields are returned as -1.
6 Native Library
The module loads a shared library named "ffmpeg_audio" or "libffmpeg_audio" using get-lib.
The native layer is expected to provide an instance-only FFmpeg API. The relevant C-side properties are:
decoder state is stored in an opaque fmpg_instance;
output is signed 32-bit interleaved PCM;
the native buffer remains valid only until the next decode, seek, close or free call;
Racket copies the buffer before passing it upward.
7 Errors
Native failures are reported as Racket errors. Examples include failure to allocate the native instance, failure to open a file and failure to seek to a requested sample position.
Unknown commands also raise an error.