Files
2026-05-04 13:11:50 +02:00

163 lines
6.1 KiB
C

#ifndef FFMPEG_AUDIO_H
#define FFMPEG_AUDIO_H
#include <stdint.h>
#ifdef _WIN32
#ifdef LIB_COMPILE
#define FFMPEG_EXTERN __declspec(dllexport)
#else
#define FFMPEG_EXTERN __declspec(dllimport)
#endif
#else
#define FFMPEG_EXTERN
#endif
#ifdef __cplusplus
extern "C" {
#endif
/*
* Audio-only FFmpeg wrapper.
*
* The implementation is C++, but the exported API is plain C. The caller never
* sees FFmpeg objects, stream indices, packets, decoders, or C++ objects.
*
* Output audio format is fixed:
*
* signed 32-bit integer PCM
* interleaved / packed
* native endian
*
* A sample frame means one sample moment across all channels. For stereo S32,
* one sample frame is two int32_t values, therefore 8 bytes.
*/
typedef struct __fmpg_instance__ fmpg_instance;
/* ------------------------------------------------------------------------- */
/* Lifecycle */
/* ------------------------------------------------------------------------- */
FFMPEG_EXTERN fmpg_instance *fmpg_init(void);
FFMPEG_EXTERN void fmpg_free(fmpg_instance *instance);
/*
* Open a media file, select the best audio stream, and create the internal
* decoder/resampler for that stream.
*
* After success, metadata, duration, sample rate and channel count are
* available through the getters below.
*
* Return: 1 on success, 0 on failure.
*/
FFMPEG_EXTERN int fmpg_open_file(fmpg_instance *instance, const char *filename);
FFMPEG_EXTERN void fmpg_close(fmpg_instance *instance);
FFMPEG_EXTERN int fmpg_is_open(fmpg_instance *instance);
/* ------------------------------------------------------------------------- */
/* Audio information */
/* ------------------------------------------------------------------------- */
FFMPEG_EXTERN int fmpg_audio_stream_count(fmpg_instance *instance);
FFMPEG_EXTERN int fmpg_audio_sample_rate(fmpg_instance *instance);
FFMPEG_EXTERN int fmpg_audio_channels(fmpg_instance *instance);
FFMPEG_EXTERN int fmpg_audio_bits_per_sample(fmpg_instance *instance);
FFMPEG_EXTERN int fmpg_audio_bytes_per_sample(fmpg_instance *instance);
/* Duration in milliseconds, or -1 if unknown. */
FFMPEG_EXTERN int64_t fmpg_duration_ms(fmpg_instance *instance);
/* Duration in output sample frames, or -1 if unknown. */
FFMPEG_EXTERN int64_t fmpg_duration_samples(fmpg_instance *instance);
/* ------------------------------------------------------------------------- */
/* Metadata */
/* ------------------------------------------------------------------------- */
FFMPEG_EXTERN const char *fmpg_file_title(fmpg_instance *instance);
FFMPEG_EXTERN const char *fmpg_file_author(fmpg_instance *instance);
FFMPEG_EXTERN const char *fmpg_file_album(fmpg_instance *instance);
FFMPEG_EXTERN const char *fmpg_file_genre(fmpg_instance *instance);
FFMPEG_EXTERN const char *fmpg_file_comment(fmpg_instance *instance);
FFMPEG_EXTERN const char *fmpg_file_copyright(fmpg_instance *instance);
FFMPEG_EXTERN int fmpg_file_year(fmpg_instance *instance);
FFMPEG_EXTERN int fmpg_file_track(fmpg_instance *instance);
FFMPEG_EXTERN int fmpg_file_bitrate(fmpg_instance *instance);
/* ------------------------------------------------------------------------- */
/* Decoding */
/* ------------------------------------------------------------------------- */
/*
* Decode the next block of audio.
*
* Internally this reads compressed packets from the selected audio stream,
* feeds them to the FFmpeg decoder, receives all available decoded frames,
* converts them to signed 32-bit interleaved PCM, and concatenates them in the
* instance output buffer.
*
* Non-selected streams are skipped internally. The caller does not handle
* stream_index, packets, or decoder objects.
*
* Return:
* 1 if PCM data is available through fmpg_buffer()/fmpg_buffer_size()
* 0 at EOF or on error
*/
FFMPEG_EXTERN int fmpg_decode_next(fmpg_instance *instance);
/*
* Seek to an absolute position in milliseconds.
*
* FFmpeg may seek to a packet before the requested timestamp. This wrapper
* decodes and discards pre-roll samples until the requested output sample is
* reached, when timestamps are available. That makes the exposed sample
* position match the music position as closely as FFmpeg's timestamps allow.
*
* Return: 1 on success, 0 on failure.
*/
FFMPEG_EXTERN int fmpg_seek_ms(fmpg_instance *instance, int64_t target_pos_ms);
/* ------------------------------------------------------------------------- */
/* Output buffer and sample positions */
/* ------------------------------------------------------------------------- */
/* Pointer to the current decoded PCM buffer. Valid until next API call that
* decodes, seeks, closes, or frees the instance. */
FFMPEG_EXTERN const uint8_t *fmpg_buffer(fmpg_instance *instance);
/* Size of the current decoded PCM buffer in bytes. */
FFMPEG_EXTERN int fmpg_buffer_size(fmpg_instance *instance);
/* Number of sample frames in the current decoded PCM buffer. */
FFMPEG_EXTERN int64_t fmpg_buffer_samples(fmpg_instance *instance);
/* Absolute sample-frame index of the first sample frame in the current buffer. */
FFMPEG_EXTERN int64_t fmpg_buffer_start_sample(fmpg_instance *instance);
/* Absolute sample-frame index just after the current buffer. */
FFMPEG_EXTERN int64_t fmpg_buffer_end_sample(fmpg_instance *instance);
/*
* Current absolute sample position in the music stream.
*
* This is the same as fmpg_buffer_end_sample() after a successful
* fmpg_decode_next(): it points just after the last produced sample frame.
*/
FFMPEG_EXTERN int64_t fmpg_sample_position(fmpg_instance *instance);
/* Approximate start time of the current decoded block in seconds. */
FFMPEG_EXTERN double fmpg_timecode(fmpg_instance *instance);
FFMPEG_EXTERN int fmpg_version();
FFMPEG_EXTERN const char *fmpg_ffmpeg_version();
FFMPEG_EXTERN const char *fmpg_int_version2string(int ver);
FFMPEG_EXTERN int fmpg_compatible_ffmpeg();
#ifdef __cplusplus
}
#endif
#endif