FFmpeg FFI
fmpg-ffi-decoder-handler
1 Command Interface
2 Format Callback
3 Reading Audio
4 Seeking
5 Metadata
6 Native Library
7 Errors
9.1

FFmpeg FFI🔗ℹ

Hans Dijkema <hans@dijkewijk.nl>

 (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?

Creates a new FFmpeg decoder command handler.

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.