#ifndef FFMPEG_AUDIO_H #define FFMPEG_AUDIO_H #include #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 const char *fmpg_ffmpeg_version(); FFMPEG_EXTERN const char *fmpg_int_version2string(int ver); FFMPEG_EXTERN int fmpg_compatible_ffmpeg(); #ifdef __cplusplus } #endif #endif