avpack is a fast C library that can pack and unpack data to/from the popular multimedia container formats.
avpack code is header-only (.h
-only) and doesn't need to be built into .a/.so/.dll
before use - you just include .h
file and that's all.
avpack is used by phiola (https://github.com/stsaz/phiola) - a fast audio player/recorder/converter. avpack is the only library for reading and writing multimedia files that is suitable for the highly efficient file I/O implemented in phiola.
Contents:
- read/write meta tags, audio track info
- read/write audio frames
- convenient for asynchronous I/O model (no I/O callback functions)
Purpose | Include Files |
---|---|
Audio file formats: | |
.aac read | aac-read.h |
.ape read | ape-read.h |
.avi read | avi-read.h |
.caf read | caf-read.h |
.flac read | flac-read.h |
.mkv/.webm read | mkv-read.h |
.mp3 read/write | mp3-read.h, mp3-write.h |
.mp4/.m4a/.mov read/write | mp4-read.h, mp4-write.h |
.mpc read | mpc-read.h |
.ogg(FLAC) read | flac-ogg-read.h |
.ogg/.opus read/write | ogg-read.h, ogg-write.h |
.ts read | ts-read.h |
.wav read/write | wav-read.h, wav-write.h |
.wv read/write | wv-read.h |
Audio streams: | |
ICY stream read | icy.h |
MPEG-1 stream read | mpeg1-read.h |
Playlists: | |
.cue read | cue.h |
.m3u read/write | m3u.h |
.pls read | pls.h |
MM Tags: | |
APETAG read | apetag.h |
ID3v1 & ID3v2 read/write | id3v1.h, id3v2.h |
Vorbis tags read/write | vorbistag.h |
Graphics: | |
.bmp read/write | bmp-read.h, bmp-write.h |
.jpg read | jpg-read.h |
.png read | png-read.h |
It doesn't contain code that reads or writes files - this is user's responsibility.
-
Clone repos:
git clone https://github.com/stsaz/ffbase git clone https://github.com/stsaz/avpack
-
Set compiler flags in your build script:
-IFFBASE_DIR -IAVPACK_DIR
where FFBASE_DIR
is your ffbase/ directory,
and AVPACK_DIR
is your avpack/ directory.
-
And then just use the necessary files, e.g.:
#include <avpack/mp4-read.h> #include <avpack/mp4-write.h>
#include <avpack/reader.h>
static const struct avpkr_if *const avpk_formats[] = {
&avpk_mp3,
...
};
struct avpk_reader_conf ac = {
.total_size = ...,
};
avpk_reader ar = {};
if (avpk_open(&ar, avpk_reader_find("mp3", avpk_formats, FF_COUNT(avpk_formats)), &ac))
goto fin;
ffstr in = {};
for (;;) {
union avpk_read_result res = {};
switch (avpk_read(&ar, &in, &res)) {
case AVPK_HEADER:
// read res.hdr
break;
case AVPK_META:
// read res.tag
break;
case AVPK_DATA:
// read res.frame
break;
case AVPK_SEEK:
// seek to res.seek_offset
// fallthrough
case AVPK_MORE:
in = ...;
break;
case AVPK_FIN:
goto fin;
case AVPK_WARNING:
// read res.error
break;
case AVPK_ERROR:
// read res.error
goto fin;
}
}
fin:
avpk_close(&ar);
#include <avpack/writer.h>
static const struct avpkw_if *const avpkw_formats[] = {
&avpkw_mp3,
...
};
avpk_writer aw = {};
struct avpk_writer_conf ac = {
.info = {
.duration = ...,
.sample_rate = ...,
.sample_bits = ...,
.channels = ...,
},
};
if (avpk_create(&aw, avpk_writer_find("mp3", avpkw_formats, FF_COUNT(avpkw_formats)), &ac))
exit(1);
avpk_tag(&aw, MMTAG_VENDOR, FFSTR_Z(""), ...);
avpk_tag(&aw, MMTAG_ARTIST, FFSTR_Z(""), ...);
avpk_tag(&aw, MMTAG_TITLE, FFSTR_Z(""), ...);
...
struct avpk_frame in = {
.len = ...,
.ptr = ...,
};
unsigned flags = 0;
for (;;) {
union avpk_write_result res = {};
int r = avpk_write(&aw, &in, flags, &res);
switch (r) {
case AVPK_DATA:
// use res.packet
break;
case AVPK_SEEK:
// seek to res.seek_offset
continue;
case AVPK_MORE:
in = ...;
flags = ...;
break;
case AVPK_FIN:
goto fin;
case AVPK_ERROR:
// read res.error.message
goto fin;
}
}
fin:
avpk_writer_close(&aw);
git clone https://github.com/stsaz/ffbase
git clone https://github.com/stsaz/avpack
cd avpack/test
make
./avpack-test all