67 lines
2.2 KiB
C++
67 lines
2.2 KiB
C++
#include "Resampler.h"
|
|
#include "ffcpp.h"
|
|
#include <stdexcept>
|
|
#include <memory>
|
|
#include <iostream>
|
|
|
|
extern "C" {
|
|
#include <libavutil/opt.h>
|
|
}
|
|
|
|
namespace ffcpp {
|
|
|
|
Resampler::Resampler(int inChannelLayout, int inSampleRate, AVSampleFormat inSampleFormat, int outChannelLayout,
|
|
int outSampleRate, AVSampleFormat outSampleFormat) {
|
|
_dstChannelLayout = outChannelLayout;
|
|
_dstSampleFormat = outSampleFormat;
|
|
_dstSampleRate = outSampleRate;
|
|
|
|
_swrContext = swr_alloc();
|
|
if(!_swrContext) {
|
|
throw new std::runtime_error("cannot create resampler");
|
|
}
|
|
|
|
av_opt_set_int(_swrContext, "in_channel_layout", inChannelLayout, 0);
|
|
av_opt_set_int(_swrContext, "in_sample_rate", inSampleRate, 0);
|
|
av_opt_set_sample_fmt(_swrContext, "in_sample_fmt", inSampleFormat, 0);
|
|
|
|
av_opt_set_int(_swrContext, "out_channel_layout", outChannelLayout, 0);
|
|
av_opt_set_int(_swrContext, "out_sample_rate", outSampleRate, 0);
|
|
av_opt_set_sample_fmt(_swrContext, "out_sample_fmt", outSampleFormat, 0);
|
|
|
|
int res = swr_init(_swrContext);
|
|
throwIfError(res, "cannot init resampler");
|
|
}
|
|
|
|
Resampler::Resampler(AVCodecContext *decoderCtx, AVCodecContext *encoderCtx)
|
|
: Resampler((int)decoderCtx->channel_layout, decoderCtx->sample_rate, decoderCtx->sample_fmt,
|
|
(int)encoderCtx->channel_layout, encoderCtx->sample_rate, encoderCtx->sample_fmt) {
|
|
}
|
|
|
|
Resampler::~Resampler() {
|
|
if(_swrContext) {
|
|
swr_free(&_swrContext);
|
|
}
|
|
}
|
|
|
|
Frame Resampler::resample(Frame& inFrame) {
|
|
int channelsCount = av_get_channel_layout_nb_channels(_dstChannelLayout);
|
|
AVFrame* fin = inFrame;
|
|
int outSamples = swr_get_out_samples(_swrContext, fin->nb_samples);
|
|
|
|
Frame outFrame(outSamples, channelsCount, _dstSampleFormat, _dstSampleRate);
|
|
int res = swr_convert_frame(_swrContext, outFrame, inFrame);
|
|
throwIfError(res, "cannot convert audio frame");
|
|
|
|
return outFrame;
|
|
}
|
|
|
|
bool Resampler::needResampling(AVCodecContext *decoderCtx, AVCodecContext *encoderCtx) {
|
|
return (decoderCtx->channels != encoderCtx->channels ||
|
|
decoderCtx->channel_layout != encoderCtx->channel_layout ||
|
|
decoderCtx->sample_fmt != encoderCtx->sample_fmt ||
|
|
decoderCtx->sample_rate != encoderCtx->sample_rate);
|
|
}
|
|
|
|
}
|