4#include "playbackengine/qffmpegcodeccontext_p.h"
6#include <qloggingcategory.h>
13using namespace QFFmpeg;
17 : m_inputFormat(inputFormat), m_outputFormat(outputFormat), m_startTime(startTime)
22 const auto inputAvFormat = AVAudioFormat(m_inputFormat);
23 const auto outputAvFormat = AVAudioFormat(m_outputFormat);
25 m_resampler = createResampleContext(inputAvFormat, outputAvFormat);
27 qCDebug(qLcResampler) <<
"Created QFFmpegResampler with offset" << m_startTime
28 <<
"us. Converting from" << inputAvFormat <<
"to" << outputAvFormat;
34 : m_outputFormat(outputFormat), m_startTime(startTime)
36 Q_ASSERT(codecContext);
38 const AVStream *audioStream = codecContext->stream();
40 if (!m_outputFormat.isValid())
42 m_outputFormat = QFFmpegMediaFormatInfo::audioFormatFromCodecParameters(*audioStream->codecpar);
44 const auto inputAvFormat = AVAudioFormat(codecContext->context());
45 const auto outputAvFormat = AVAudioFormat(m_outputFormat);
47 m_resampler = createResampleContext(inputAvFormat, outputAvFormat);
49 qCDebug(qLcResampler).nospace() <<
"Created QFFmpegResampler. Offset: " << m_startTime
50 <<
"us. From: " << inputAvFormat <<
" to: " << outputAvFormat;
53template <
typename... Args>
56 std::unique_ptr<QFFmpegResampler> resampler{
57 new QFFmpegResampler(std::forward<Args>(args)...),
59 if (resampler->isInitialized())
64std::unique_ptr<QFFmpegResampler>
68 return createImpl(inputFormat, outputFormat, startTime);
71std::unique_ptr<QFFmpegResampler>
75 return createImpl(codecContext, outputFormat, startTime);
80 return m_resampler !=
nullptr;
87 if (!m_inputFormat.isValid())
90 return resample(
reinterpret_cast<
const uint8_t **>(&data),
91 m_inputFormat.framesForBytes(
static_cast<qint32>(size)));
96 return resample(
const_cast<
const uint8_t **>(frame->extended_data), frame->nb_samples);
99QAudioBuffer
QFFmpegResampler::resample(
const uint8_t **inputData,
int inputSamplesCount)
101 const int maxOutSamples = adjustMaxOutSamples(inputSamplesCount);
103 QByteArray samples(m_outputFormat.bytesForFrames(maxOutSamples), Qt::Uninitialized);
104 auto *out =
reinterpret_cast<uint8_t *>(samples.data());
105 const int outSamples =
106 swr_convert(m_resampler.get(), &out, maxOutSamples, inputData, inputSamplesCount);
108 samples.resize(m_outputFormat.bytesForFrames(outSamples));
110 const qint64 startTime = m_outputFormat.durationForFrames(m_samplesProcessed) + m_startTime;
111 m_samplesProcessed += outSamples;
113 qCDebug(qLcResamplerTrace).nospace()
114 <<
"Created output buffer. Time stamp: " << startTime
115 <<
"us. Samples in: " << inputSamplesCount
116 <<
", Samples out: " << outSamples <<
", Max samples: " << maxOutSamples;
117 return QAudioBuffer(samples, m_outputFormat, startTime);
122 int maxOutSamples = swr_get_out_samples(m_resampler.get(), inputSamplesCount);
124 const auto remainingCompensationDistance = m_endCompensationSample - m_samplesProcessed;
126 if (remainingCompensationDistance > 0 && maxOutSamples > remainingCompensationDistance) {
133 setSampleCompensation(0, 0);
134 maxOutSamples = swr_get_out_samples(m_resampler.get(), inputSamplesCount);
137 return maxOutSamples;
142 const int res = swr_set_compensation(m_resampler.get(), delta,
static_cast<
int>(distance));
144 qCWarning(qLcResampler) <<
"swr_set_compensation fail:" << res;
146 m_sampleCompensationDelta = delta;
147 m_endCompensationSample = m_samplesProcessed + distance;
153 return m_samplesProcessed < m_endCompensationSample ? m_sampleCompensationDelta : 0;
QAudioBuffer resample(const char *data, size_t size) override
~QFFmpegResampler() override
void setSampleCompensation(qint32 delta, quint32 distance)
QAudioBuffer resample(const AVFrame *frame)
bool isInitialized() const
qint32 activeSampleCompensationDelta() const
#define qCWarning(category,...)
#define qCDebug(category,...)
#define Q_STATIC_LOGGING_CATEGORY(name,...)