Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
Loading...
Searching...
No Matches
qffmpegresampler.cpp
Go to the documentation of this file.
1// Copyright (C) 2022 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
6#include <qloggingcategory.h>
7
8static Q_LOGGING_CATEGORY(qLcResampler, "qt.multimedia.ffmpeg.resampler")
9
11
12using namespace QFFmpeg;
13
14QFFmpegResampler::QFFmpegResampler(const QAudioFormat &inputFormat, const QAudioFormat &outputFormat) :
15 m_inputFormat(inputFormat), m_outputFormat(outputFormat)
16{
17 Q_ASSERT(inputFormat.isValid());
18 Q_ASSERT(outputFormat.isValid());
19
20 m_resampler =
21 createResampleContext(AVAudioFormat(m_inputFormat), AVAudioFormat(m_outputFormat));
22}
23
24QFFmpegResampler::QFFmpegResampler(const Codec* codec, const QAudioFormat &outputFormat)
25 : m_outputFormat(outputFormat)
26{
28
29 qCDebug(qLcResampler) << "createResampler";
30 const AVStream *audioStream = codec->stream();
31
32 if (!m_outputFormat.isValid())
33 // want the native format
34 m_outputFormat = QFFmpegMediaFormatInfo::audioFormatFromCodecParameters(audioStream->codecpar);
35
36 m_resampler = createResampleContext(AVAudioFormat(audioStream->codecpar),
37 AVAudioFormat(m_outputFormat));
38}
39
41
43{
44 if (!m_inputFormat.isValid())
45 return {};
46
47 return resample(reinterpret_cast<const uint8_t **>(&data),
48 m_inputFormat.framesForBytes(static_cast<qint32>(size)));
49}
50
52{
53 return resample(const_cast<const uint8_t **>(frame->extended_data), frame->nb_samples);
54}
55
56QAudioBuffer QFFmpegResampler::resample(const uint8_t **inputData, int inputSamplesCount)
57{
58 const int maxOutSamples = adjustMaxOutSamples(inputSamplesCount);
59
60 QByteArray samples(m_outputFormat.bytesForFrames(maxOutSamples), Qt::Uninitialized);
61 auto *out = reinterpret_cast<uint8_t *>(samples.data());
62 const int outSamples =
63 swr_convert(m_resampler.get(), &out, maxOutSamples, inputData, inputSamplesCount);
64
65 samples.resize(m_outputFormat.bytesForFrames(outSamples));
66
67 qint64 startTime = m_outputFormat.durationForFrames(m_samplesProcessed);
68 m_samplesProcessed += outSamples;
69
70 qCDebug(qLcResampler) << " new frame" << startTime << "in_samples" << inputSamplesCount
71 << outSamples << maxOutSamples;
72 return QAudioBuffer(samples, m_outputFormat, startTime);
73}
74
75int QFFmpegResampler::adjustMaxOutSamples(int inputSamplesCount)
76{
77 int maxOutSamples = swr_get_out_samples(m_resampler.get(), inputSamplesCount);
78
79 const auto remainingCompensationDistance = m_endCompensationSample - m_samplesProcessed;
80
81 if (remainingCompensationDistance > 0 && maxOutSamples > remainingCompensationDistance) {
82 // If the remaining compensation distance less than output frame,
83 // the ffmpeg resampler bufferises the rest of frames that makes
84 // unexpected delays on large frames.
85 // The hack might cause some compensation bias on large frames,
86 // however it's not significant for our logic, in fact.
87 // TODO: probably, it will need some improvements
89 maxOutSamples = swr_get_out_samples(m_resampler.get(), inputSamplesCount);
90 }
91
92 return maxOutSamples;
93}
94
96{
97 const int res = swr_set_compensation(m_resampler.get(), delta, static_cast<int>(distance));
98 if (res < 0)
99 qCWarning(qLcResampler) << "swr_set_compensation fail:" << res;
100 else {
101 m_sampleCompensationDelta = delta;
102 m_endCompensationSample = m_samplesProcessed + distance;
103 }
104}
105
107{
108 return m_samplesProcessed < m_endCompensationSample ? m_sampleCompensationDelta : 0;
109}
110
\inmodule QtMultimedia
The QAudioFormat class stores audio stream parameter information.
Q_MULTIMEDIA_EXPORT qint32 bytesForFrames(qint32 frameCount) const
Returns the number of bytes required for frameCount frames of this format.
Q_MULTIMEDIA_EXPORT qint64 durationForFrames(qint32 frameCount) const
Return the number of microseconds represented by frameCount frames in this format.
constexpr bool isValid() const noexcept
Returns true if all of the parameters are valid.
Q_MULTIMEDIA_EXPORT qint32 framesForBytes(qint32 byteCount) const
Returns the number of frames represented by byteCount in this format.
\inmodule QtCore
Definition qbytearray.h:57
static QAudioFormat audioFormatFromCodecParameters(AVCodecParameters *codecPar)
QAudioBuffer resample(const char *data, size_t size) override
~QFFmpegResampler() override
void setSampleCompensation(qint32 delta, quint32 distance)
QFFmpegResampler(const QAudioFormat &inputFormat, const QAudioFormat &outputFormat)
qint32 activeSampleCompensationDelta() const
Combined button and popup list for selecting options.
constexpr Initialization Uninitialized
qint64 startTime
QMediaFormat::AudioCodec codec
#define Q_LOGGING_CATEGORY(name,...)
#define qCWarning(category,...)
#define qCDebug(category,...)
GLsizei samples
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLsizei GLsizei GLfloat distance
GLuint res
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
unsigned int quint32
Definition qtypes.h:50
int qint32
Definition qtypes.h:49
long long qint64
Definition qtypes.h:60
QTextStream out(stdout)
[7]
QFrame frame
[0]