#include #include #include #include #include #include #include "resampler.h" #define MICROSECOND 1000000 static inline uint64_t div_uint64_ceil(uint64_t num, uint64_t den) { return (num / den) + (num % den != 0); } static int resampler_init (struct Resampler *resampler, const AVChannelLayout *out_chlayout, enum AVSampleFormat out_sample_fmt, int64_t out_sample_rate, uint64_t out_frame_size) { /* Let me tell you something; you --don't want-- CAN'T configure a * SwrContext manually, GOOD ****ING LUCK DOING THAT. The documentation is * so bad on that matter, it only referes to "tHe PaRaMeTeRs" or show off a * list of deprecated attribute which looks nothing like what's actually * used in their API. I tried to copy what's being done in their a API but * whatever I do would either not work or be liable to change since it's not * documented for shit (even the documented stuff doesn't appears stable, so * wtf am I saying anyway). A ****ing joke, I tell you that. * * Pardon my french. * * Anywho, instead of configuring the input parameter directly, we shove * them in resampler so we can recall them before calling ffmpeg's SWR * allocator. */ resampler->out_chlayout = out_chlayout; resampler->out_sample_fmt = out_sample_fmt; resampler->out_sample_rate = out_sample_rate; resampler->out_frame_size = out_frame_size; resampler->swr = NULL; return 0; } static int resampler_conf (struct Resampler *resampler, const AVChannelLayout *in_chlayout, enum AVSampleFormat in_sample_fmt, int64_t in_sample_rate) { int err; err = swr_alloc_set_opts2( &resampler->swr, resampler->out_chlayout, resampler->out_sample_fmt, resampler->out_sample_rate, in_chlayout, in_sample_fmt, in_sample_rate, 0, 0); if (err) return err; if (!swr_is_initialized(resampler->swr)) if ((err = swr_init(resampler->swr))) return err; resampler->in_sample_rate = in_sample_rate; resampler->needed = div_uint64_ceil(resampler->out_frame_size * in_sample_rate, resampler->out_sample_rate); return 0; } int resampler_send_frame (struct Resampler *resampler, AVFrame *in) { int err; if ((err = swr_convert(resampler->swr, NULL, 0, (const uint8_t **)in->extended_data, in->nb_samples)) < 0) return err; resampler->stored += in->nb_samples; return 0; } int resampler_send_empty (struct Resampler *resampler, unsigned int microsecond) { // TODO: Check for downcasting int nb_samples; nb_samples = div_uint64_ceil(microsecond * resampler->in_sample_rate, 1000); return swr_inject_silence(resampler->swr, nb_samples); } int resampler_convert (struct Resampler *resampler, AVFrame *out) { int err; assert(out != NULL); assert(resampler->swr != NULL); if (resampler->stored < resampler->needed) { return AVERROR(EAGAIN); /* err = swr_inject_silence(resampler->swr, resampler->needed - resampler->stored); if (err < 0) return err; */ } err = swr_convert(resampler->swr, out->extended_data, out->nb_samples, NULL, 0); if (err < 0) return err; resampler->stored = 0; return 0; } void resampler_free (struct Resampler *resampler) { if (resampler == NULL) return; swr_free(&resampler->swr); } int resampler_init_for_encoder (struct Resampler *resampler, const struct Encoder *encoder) { AVCodecContext *avctx = encoder->avctx; return resampler_init(resampler, &avctx->ch_layout, avctx->sample_fmt, avctx->sample_rate, avctx->frame_size); } int resampler_conf_for_decoder (struct Resampler *resampler, const struct Decoder *decoder) { AVCodecContext *avctx = decoder->avctx; return resampler_conf(resampler, &avctx->ch_layout, avctx->sample_fmt, avctx->sample_rate); }