Dpdo external decoder library API (v1)

Dpdo ships no third-party decoder and links none. You provide a dynamic library (.so / .dll), select it in the player, and Dpdo calls it through the ABI below — you get back standard interleaved float32 PCM.

Why it works this way

Licensing and patent responsibility for third-party decoders (ffmpeg and friends) belongs to whoever supplies the library. Dpdo only provides the mechanism: load, verify, dispatch by capability. The library is yours, placed by you, and only used when you turn it on — the same approach VLC and similar players take.

Two kinds of library, one entry point

FormWhat it isHow Dpdo uses it
Plugin library (recommended)Exports the seven dpdo_ext_* functions below; the library does its own container parsing and decodingCalled strictly through the ABI
Bare ffmpegAn ordinary ffmpeg build (exports avformat_open_input, avcodec_open2, …) with no dpdo_ext_*Detected automatically, driven through ffmpeg's older API; whatever decoders it carries are what you can play

Loading tries the plugin ABI first, then bare ffmpeg. When both fail the log reports both reasons, for example:

player_cli: not a DPDO decoder plugin [ABI version mismatch: library reports 99, this build expects 1];
	            not a usable raw ffmpeg [missing symbol 'avformat_open_input']
	

How to load it

WhereHow
Command line (Linux / Windows)DpdoPlayerEngine -ext-decoder /path/to/lib.so
Turn off an already loaded libraryDpdoPlayerEngine -no-ext-decoder
Desktop GUISettings → Enable external decoder library → choose the file (the GUI passes the same argument)
Android / HarmonyOSSettings → Enable external decoder library → choose the file (the app copies it into its private directory)

The load result is reported honestly as one of three states: ok (plugin ABI) / okraw (bare ffmpeg) / fail: reason.

The seven ABI functions

The header is the single authority: public/dpdo_ext_decoder.h. C linkage, no name mangling (wrap in extern "C" from C++).

int          dpdo_ext_abi_version(void);                                  /* 1. version */
	const char  *dpdo_ext_codecs(void);                                       /* 2. capabilities */
	void        *dpdo_ext_open(const char *path, int *channels,
	                           int *sample_rate, int *bits_per_sample,
	                           long long *total_frames);                      /* 3. open */
	long long    dpdo_ext_read(void *handle, float *out, long long frames);   /* 4. read */
	int          dpdo_ext_seek(void *handle, long long frame);                /* 5. seek */
	void         dpdo_ext_close(void *handle);                                /* 6. close */
	const char  *dpdo_ext_last_error(void *handle);                           /* 7. last error */
	
#MeaningHard requirement
1Return DPDO_EXT_DECODER_ABI_V1 (currently 1)A mismatch makes the engine dlclose immediately and report it — no call is ever dispatched to that library
2Comma-separated lowercase capability names, e.g. "dts,ape,alac"The string is owned by the library and must stay valid for the process lifetime; an empty string is treated as a failure
3Return a handle on success; write all four out-parametersReturn NULL on failure and set the reason for #7
4Read up to frames frames into out (interleaved float32); return the number of frames read0 = end of stream; negative = error; the engine never asks for more than total_frames
5Seek to frame frame (0-based)Return 0 on success; approximate seeking is allowed, but subsequent reads must continue from that point without channel mix-up
6Release the handleEach successful open gets exactly one close
7Human-readable error string (owned by the library, do not free); "" when there is no errorWhen open fails the engine has no handle and calls this with NULL — support library-level errors and return the reason anyway

Output contract

  • Interleaved float32, range −1.0 … +1.0; one frame = one sample per channel.
  • Integer PCM normalisation is the library's job (matching Dpdo's internal float pipeline).
  • Do not resample or change the sample rate: the engine uses the sample_rate you report.

Limits of the bare-ffmpeg path

  • The engine does not declare ffmpeg structs; it reads them at measured offsets (ffmpeg 3.x era). If the layout does not match it refuses instead of guessing.
  • Only the decoders your .so actually contains are usable. The UI therefore never promises a fixed format list.
  • Seeking reopens the container and skips frames exactly, rather than trusting the demuxer's av_seek_frame.
  • When the container header disagrees with the content, the content wins (classic case: a DTS-CD .wav whose RIFF header claims 16-bit PCM).

Platforms

PlatformLibrary fileNotes
Linux.soGive an absolute path
Windows.dllSibling dependency DLLs are found automatically (LOAD_WITH_ALTERED_SEARCH_PATH)
Android.soThe app copies the selected library into its private directory files/decoders/; to change libraries, select the file again in Settings
HarmonyOS.soSame as Android
iOS—The OS forbids loading external dynamic libraries; this path is not available

Verify your library yourself

  1. Load it: run DpdoPlayerEngine -ext-decoder <path> -i <a file> once and read the first lines. Success prints external decoder library loaded: … (codecs: …) or raw ffmpeg loaded: …; failure prints both reasons (which symbol is missing / ABI version mismatch).
  2. Confirm it is really in use: the session arguments must contain -ext-decoder <path> — that is the hard evidence.
  3. Check the PCM: compare against a reference implementation (e.g. ffmpeg -i x.wv -f f32le -) sample by sample; the expected difference is zero.
  4. Negative case: a truncated file must fail clearly — never silently pad and present it as complete audio.

Licensing and responsibility

  • Dpdo does not bundle or redistribute any third-party decoder library; the installer contains none of their files.
  • Licensing (including GPL and patent obligations) and compliance are the responsibility of whoever supplies the library. Make sure you are allowed to use and distribute it.
  • We do not provide, recommend, or download any specific third-party library for you.

Change log

ABI versionChange
v1First release: seven symbols; three-state load result; last_error(NULL) semantics made explicit