1// Copyright (C) 2021 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
3#ifndef QFFMPEGAUDIORENDERER_P_H
4#define QFFMPEGAUDIORENDERER_P_H
5
6//
7// W A R N I N G
8// -------------
9//
10// This file is not part of the Qt API. It exists purely as an
11// implementation detail. This header file may change from version to
12// version without notice, or even be removed.
13//
14// We mean it.
15//
16
17#include <QtFFmpegMediaPluginImpl/private/qffmpegrenderer_p.h>
18
19#include "qaudiobuffer.h"
20
21QT_BEGIN_NAMESPACE
22
23class QAudioOutput;
24class QAudioBufferOutput;
25class QAudioSink;
26class QFFmpegResampler;
27
28namespace QFFmpeg {
29
30struct AbstractAudioFrameConverter;
31
32class AudioRenderer : public Renderer
33{
34 Q_OBJECT
35public:
36 AudioRenderer(const TimeController &tc, QAudioOutput *output, QAudioBufferOutput *bufferOutput,
37 bool pitchCompensation);
38
39 void setOutput(QAudioOutput *output);
40
41 void setOutput(QAudioBufferOutput *bufferOutput);
42
43 void setPitchCompensation(bool enabled);
44
45 ~AudioRenderer() override;
46
47protected:
48 using Microseconds = std::chrono::microseconds;
49 struct SynchronizationStamp
50 {
51 QAudio::State audioSinkState = QAudio::IdleState;
52 qsizetype audioSinkBytesFree = 0;
53 qsizetype bufferBytesWritten = 0;
54 TimePoint timePoint = TimePoint::max();
55 };
56
57 struct BufferLoadingInfo
58 {
59 enum Type { Low, Moderate, High };
60 Type type = Moderate;
61 TimePoint timePoint = TimePoint::max();
62 Microseconds delay = Microseconds(0);
63 };
64
65 struct AudioTimings
66 {
67 Microseconds actualBufferDuration = Microseconds(0);
68 Microseconds maxSoundDelay = Microseconds(0);
69 Microseconds minSoundDelay = Microseconds(0);
70 };
71
72 struct BufferedDataWithOffset
73 {
74 QAudioBuffer buffer;
75 qsizetype offset = 0;
76
77 bool isValid() const { return buffer.isValid(); }
78 qsizetype size() const { return buffer.byteCount() - offset; }
79 const char *data() const { return buffer.constData<char>() + offset; }
80 };
81
82 RenderingResult renderInternal(Frame frame) override;
83
84 RenderingResult pushFrameToOutput(const Frame &frame);
85
86 void pushFrameToBufferOutput(const Frame &frame);
87
88 void onPlaybackRateChanged() override;
89
90 std::chrono::milliseconds timerInterval() const override;
91
92 void onPauseChanged() override;
93
94 void freeOutput();
95
96 void updateOutputs(const Frame &frame);
97
98 void initAudioFrameConverter(const Frame &frame);
99
100 void onDeviceChanged();
101
102 void updateVolume();
103
104 void updateSynchronization(const SynchronizationStamp &stamp, const Frame &frame);
105
106 Microseconds bufferLoadingTime(const SynchronizationStamp &syncStamp) const;
107
108 void onAudioSinkStateChanged(QAudio::State state);
109
110 Microseconds durationForBytes(qsizetype bytes) const;
111
112private:
113 QPointer<QAudioOutput> m_output;
114 QPointer<QAudioBufferOutput> m_bufferOutput;
115 std::unique_ptr<QAudioSink> m_sink;
116 AudioTimings m_timings;
117 BufferLoadingInfo m_bufferLoadingInfo;
118 std::unique_ptr<QFFmpegResampler> m_bufferOutputResampler;
119 QAudioFormat m_sinkFormat;
120
121 BufferedDataWithOffset m_bufferedData;
122 QPointer<QIODevice> m_ioDevice;
123
124 bool m_lastFramePushDone = true;
125
126 bool m_deviceChanged = false;
127 bool m_bufferOutputChanged = false;
128 bool m_drained = false;
129 bool m_firstFrameToSink = true;
130
131 // pitch compensation
132 bool m_pitchCompensation = false;
133 std::unique_ptr<AbstractAudioFrameConverter> m_audioFrameConverter;
134};
135
136} // namespace QFFmpeg
137
138QT_END_NAMESPACE
139
140#endif // QFFMPEGAUDIORENDERER_P_H
141

source code of qtmultimedia/src/plugins/multimedia/ffmpeg/playbackengine/qffmpegaudiorenderer_p.h