10#include <libavcodec/avcodec.h>
11#include <libavformat/avformat.h>
12#include <libavutil/opt.h>
13#include <libswresample/swresample.h>
16#if defined(_WIN32) && defined(_MSVC_LANG)
17#pragma comment(lib, "ffmpeg/lib/windows/avcodec.lib")
18#pragma comment(lib, "ffmpeg/lib/windows/avformat.lib")
19#pragma comment(lib, "ffmpeg/lib/windows/avutil.lib")
20#pragma comment(lib, "ffmpeg/lib/windows/swresample.lib")
24#if LIBAVFORMAT_VERSION_MAJOR < 60
25#error unsupported libavformat version.
28#if LIBAVCODEC_VERSION_MAJOR < 60
29#error unsupported libavcodec version.
32#if LIBAVUTIL_VERSION_MAJOR < 58
33#error unsupported libavutil version.
36#if LIBSWRESAMPLE_VERSION_MAJOR < 4
37#error unsupported libswresample version.
42#if !defined(HEPHAUDIO_INTERNAL_SAMPLE_FMT)
46 inline std::string FFmpegGetErrorMessage(
int errorCode)
48 char errorMessage[AV_ERROR_MAX_STRING_SIZE]{ };
49 if (av_strerror(errorCode, errorMessage, AV_ERROR_MAX_STRING_SIZE) < 0)
51 return "error message not found.";
56 inline AVCodecID CodecIdFromAudioFormatInfo(
const AudioFormatInfo& audioFormatInfo)
58 switch (audioFormatInfo.formatTag)
61 case HEPHAUDIO_FORMAT_TAG_PCM:
63 if (audioFormatInfo.endian == Heph::Endian::Little)
65 switch (audioFormatInfo.bitsPerSample)
68 return AV_CODEC_ID_PCM_U8;
70 return AV_CODEC_ID_PCM_S16LE;
72 return AV_CODEC_ID_PCM_S24LE;
74 return AV_CODEC_ID_PCM_S32LE;
76 return AV_CODEC_ID_PCM_S64LE;
78 return AV_CODEC_ID_NONE;
83 switch (audioFormatInfo.bitsPerSample)
86 return AV_CODEC_ID_PCM_U8;
88 return AV_CODEC_ID_PCM_S16BE;
90 return AV_CODEC_ID_PCM_S24BE;
92 return AV_CODEC_ID_PCM_S32BE;
94 return AV_CODEC_ID_PCM_S64BE;
96 return AV_CODEC_ID_NONE;
101 case HEPHAUDIO_FORMAT_TAG_IEEE_FLOAT:
103 if (audioFormatInfo.endian == Heph::Endian::Little)
105 return audioFormatInfo.bitsPerSample ==
sizeof(double) ? AV_CODEC_ID_PCM_F64LE : AV_CODEC_ID_PCM_F32LE;
107 return audioFormatInfo.bitsPerSample ==
sizeof(double) ? AV_CODEC_ID_PCM_F64BE : AV_CODEC_ID_PCM_F32BE;
110 case HEPHAUDIO_FORMAT_TAG_ALAW:
111 return AV_CODEC_ID_PCM_ALAW;
113 case HEPHAUDIO_FORMAT_TAG_MULAW:
114 return AV_CODEC_ID_PCM_MULAW;
116 case HEPHAUDIO_FORMAT_TAG_WMA:
117 return AV_CODEC_ID_WMAV2;
119 case HEPHAUDIO_FORMAT_TAG_WMAUDIO_LOSSLESS:
120 return AV_CODEC_ID_WMALOSSLESS;
122 case HEPHAUDIO_FORMAT_TAG_WMAVOICE:
123 return AV_CODEC_ID_WMAVOICE;
125 case HEPHAUDIO_FORMAT_TAG_MPEG:
126 return AV_CODEC_ID_MP2;
128 case HEPHAUDIO_FORMAT_TAG_MP3:
129 return AV_CODEC_ID_MP3;
131 case HEPHAUDIO_FORMAT_TAG_AAC:
132 return AV_CODEC_ID_AAC;
134 case HEPHAUDIO_FORMAT_TAG_ALAC:
135 return AV_CODEC_ID_ALAC;
137 case HEPHAUDIO_FORMAT_TAG_FLAC:
138 return AV_CODEC_ID_FLAC;
140 case HEPHAUDIO_FORMAT_TAG_OPUS:
141 return AV_CODEC_ID_OPUS;
143 case HEPHAUDIO_FORMAT_TAG_VORBIS:
144 return AV_CODEC_ID_VORBIS;
147 return AV_CODEC_ID_NONE;
151 inline AVSampleFormat ToAVSampleFormat(
const AVCodec* avCodec,
const AudioFormatInfo& formatInfo)
153 if (avCodec ==
nullptr || avCodec->sample_fmts ==
nullptr)
155 return AV_SAMPLE_FMT_NONE;
158 auto getFirstSupportedSampleFormat = [avCodec](std::vector<AVSampleFormat> possibleFormats) -> AVSampleFormat
160 for (
size_t i = 0; i < possibleFormats.size(); ++i)
162 for (
size_t j = 0; avCodec->sample_fmts[j] != AV_SAMPLE_FMT_NONE; ++j)
164 if (possibleFormats[i] == avCodec->sample_fmts[j])
166 return possibleFormats[i];
170 return AV_SAMPLE_FMT_NONE;
173 if (formatInfo.formatTag == HEPHAUDIO_FORMAT_TAG_IEEE_FLOAT)
175 if (formatInfo.bitsPerSample ==
sizeof(
double))
177 return getFirstSupportedSampleFormat(
179 AV_SAMPLE_FMT_DBL, AV_SAMPLE_FMT_DBLP,
180 AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_FLTP,
181 AV_SAMPLE_FMT_S64, AV_SAMPLE_FMT_S64P,
182 AV_SAMPLE_FMT_S32, AV_SAMPLE_FMT_S32P,
183 AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_S16P
186 return getFirstSupportedSampleFormat(
188 AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_FLTP,
189 AV_SAMPLE_FMT_DBL, AV_SAMPLE_FMT_DBLP,
190 AV_SAMPLE_FMT_S64, AV_SAMPLE_FMT_S64P,
191 AV_SAMPLE_FMT_S32, AV_SAMPLE_FMT_S32P,
192 AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_S16P
196 switch (formatInfo.bitsPerSample)
199 return getFirstSupportedSampleFormat(
201 AV_SAMPLE_FMT_U8, AV_SAMPLE_FMT_U8P,
202 AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_S16P,
203 AV_SAMPLE_FMT_S32, AV_SAMPLE_FMT_S32P,
204 AV_SAMPLE_FMT_S64, AV_SAMPLE_FMT_S64P,
205 AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_FLTP,
206 AV_SAMPLE_FMT_DBL, AV_SAMPLE_FMT_DBLP
209 return getFirstSupportedSampleFormat(
211 AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_S16P,
212 AV_SAMPLE_FMT_S32, AV_SAMPLE_FMT_S32P,
213 AV_SAMPLE_FMT_S64, AV_SAMPLE_FMT_S64P,
214 AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_FLTP,
215 AV_SAMPLE_FMT_DBL, AV_SAMPLE_FMT_DBLP,
216 AV_SAMPLE_FMT_U8, AV_SAMPLE_FMT_U8P
220 return getFirstSupportedSampleFormat(
222 AV_SAMPLE_FMT_S32, AV_SAMPLE_FMT_S32P,
223 AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_FLTP,
224 AV_SAMPLE_FMT_S64, AV_SAMPLE_FMT_S64P,
225 AV_SAMPLE_FMT_DBL, AV_SAMPLE_FMT_DBLP,
226 AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_S16P,
227 AV_SAMPLE_FMT_U8, AV_SAMPLE_FMT_U8P
230 return getFirstSupportedSampleFormat(
232 AV_SAMPLE_FMT_S64, AV_SAMPLE_FMT_S64P,
233 AV_SAMPLE_FMT_S32, AV_SAMPLE_FMT_S32P,
234 AV_SAMPLE_FMT_DBL, AV_SAMPLE_FMT_DBLP,
235 AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_FLTP,
236 AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_S16P,
237 AV_SAMPLE_FMT_U8, AV_SAMPLE_FMT_U8P
240 return getFirstSupportedSampleFormat(
242 AV_SAMPLE_FMT_DBL, AV_SAMPLE_FMT_DBLP,
243 AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_FLTP,
244 AV_SAMPLE_FMT_S64, AV_SAMPLE_FMT_S64P,
245 AV_SAMPLE_FMT_S32, AV_SAMPLE_FMT_S32P,
246 AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_S16P,
247 AV_SAMPLE_FMT_U8, AV_SAMPLE_FMT_U8P
252 inline AVSampleFormat ToAVSampleFormat(
const AudioFormatInfo& formatInfo)
254 const AVCodecID codecID = HephAudio::CodecIdFromAudioFormatInfo(formatInfo);
255 const AVCodec* avCodec = avcodec_find_encoder(codecID);
256 return HephAudio::ToAVSampleFormat(avCodec, formatInfo);
259 inline AVChannelLayout ToAVChannelLayout(
const AudioChannelLayout& audioChannelLayout)
261 AVChannelLayout avChannelLayout{};
262 avChannelLayout.order = AV_CHANNEL_ORDER_NATIVE;
263 avChannelLayout.nb_channels = audioChannelLayout.count;
264 avChannelLayout.u.mask = (uint64_t)audioChannelLayout.mask;
265 return avChannelLayout;
268 inline AudioChannelLayout FromAVChannelLayout(
const AVChannelLayout& avChannelLayout)
270 AudioChannelLayout audioChannelLayout;
272 audioChannelLayout.
count = avChannelLayout.nb_channels;
274 uint32_t avChMask = (uint32_t)avChannelLayout.u.mask;
278 if (audioChannelLayout.mask == AudioChannelMask::Unknown)
280 switch (audioChannelLayout.count)
283 audioChannelLayout.mask = HEPHAUDIO_CH_MASK_MONO;
286 audioChannelLayout.mask = HEPHAUDIO_CH_MASK_STEREO;
293 return audioChannelLayout;
296 inline uint32_t GetClosestSupportedSampleRate(
const AVCodec* avCodec, uint32_t targetSampleRate)
298 if (avCodec->supported_samplerates !=
nullptr)
300 int32_t closestSampleRate = avCodec->supported_samplerates[0];
301 int32_t closestAbsDeltaSampleRate = abs((
int)targetSampleRate - avCodec->supported_samplerates[0]);
302 for (
size_t i = 1; avCodec->supported_samplerates[i] != 0; i++)
304 if (avCodec->supported_samplerates[i] == targetSampleRate)
306 return targetSampleRate;
309 const int32_t currentAbsDeltaSampleRate = abs((
int)targetSampleRate - avCodec->supported_samplerates[i]);
310 if (currentAbsDeltaSampleRate < closestAbsDeltaSampleRate)
312 closestAbsDeltaSampleRate = currentAbsDeltaSampleRate;
313 closestSampleRate = avCodec->supported_samplerates[i];
315 else if (currentAbsDeltaSampleRate == closestAbsDeltaSampleRate && avCodec->supported_samplerates[i] > closestSampleRate)
317 closestSampleRate = avCodec->supported_samplerates[i];
320 return closestSampleRate;
323 return targetSampleRate;
326 inline uint32_t GetClosestSupportedSampleRate(
const AudioFormatInfo& formatInfo)
328 const AVCodecID codecID = HephAudio::CodecIdFromAudioFormatInfo(formatInfo);
329 const AVCodec* avCodec = avcodec_find_encoder(codecID);
330 return HephAudio::GetClosestSupportedSampleRate(avCodec, formatInfo.sampleRate);
334#define HEPHAUDIO_FFMPEG_GET_ERROR_MESSAGE(errorCode) HephAudio::FFmpegGetErrorMessage(errorCode)
337#if defined(HEPH_AUDIO_SAMPLE_TYPE_DBL)
338#define HEPHAUDIO_FFMPEG_INTERNAL_SAMPLE_FMT AV_SAMPLE_FMT_DBL
339#elif defined(HEPH_AUDIO_SAMPLE_TYPE_FLT)
340#define HEPHAUDIO_FFMPEG_INTERNAL_SAMPLE_FMT AV_SAMPLE_FMT_FLT
341#elif defined(HEPH_AUDIO_SAMPLE_TYPE_S64)
342#define HEPHAUDIO_FFMPEG_INTERNAL_SAMPLE_FMT AV_SAMPLE_FMT_S64
343#elif defined(HEPH_AUDIO_SAMPLE_TYPE_S32)
344#define HEPHAUDIO_FFMPEG_INTERNAL_SAMPLE_FMT AV_SAMPLE_FMT_S32
345#elif defined(HEPH_AUDIO_SAMPLE_TYPE_S16)
346#define HEPHAUDIO_FFMPEG_INTERNAL_SAMPLE_FMT AV_SAMPLE_FMT_S16
348#define HEPHAUDIO_FFMPEG_INTERNAL_SAMPLE_FMT AV_SAMPLE_FMT_FLT
AudioChannelMask
Definition AudioChannelLayout.h:70
uint16_t count
Definition AudioChannelLayout.h:141