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 "playbackengine/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
30class AudioRenderer : public Renderer
31{
32 Q_OBJECT
33public:
34 AudioRenderer(const TimeController &tc, QAudioOutput *output, QAudioBufferOutput *bufferOutput);
35
36 void setOutput(QAudioOutput *output);
37
38 void setOutput(QAudioBufferOutput *bufferOutput);
39
40 ~AudioRenderer() override;
41
42protected:
43 using Microseconds = std::chrono::microseconds;
44 struct SynchronizationStamp
45 {
46 QAudio::State audioSinkState = QAudio::IdleState;
47 qsizetype audioSinkBytesFree = 0;
48 qsizetype bufferBytesWritten = 0;
49 TimePoint timePoint = TimePoint::max();
50 };
51
52 struct BufferLoadingInfo
53 {
54 enum Type { Low, Moderate, High };
55 Type type = Moderate;
56 TimePoint timePoint = TimePoint::max();
57 Microseconds delay = Microseconds(0);
58 };
59
60 struct AudioTimings
61 {
62 Microseconds actualBufferDuration = Microseconds(0);
63 Microseconds maxSoundDelay = Microseconds(0);
64 Microseconds minSoundDelay = Microseconds(0);
65 };
66
67 struct BufferedDataWithOffset
68 {
69 QAudioBuffer buffer;
70 qsizetype offset = 0;
71
72 bool isValid() const { return buffer.isValid(); }
73 qsizetype size() const { return buffer.byteCount() - offset; }
74 const char *data() const { return buffer.constData<char>() + offset; }
75 };
76
77 RenderingResult renderInternal(Frame frame) override;
78
79 RenderingResult pushFrameToOutput(const Frame &frame);
80
81 void pushFrameToBufferOutput(const Frame &frame);
82
83 void onPlaybackRateChanged() override;
84
85 int timerInterval() const override;
86
87 void onPauseChanged() override;
88
89 void freeOutput();
90
91 void updateOutputs(const Frame &frame);
92
93 void initResempler(const Frame &frame);
94
95 void onDeviceChanged();
96
97 void updateVolume();
98
99 void updateSynchronization(const SynchronizationStamp &stamp, const Frame &frame);
100
101 Microseconds bufferLoadingTime(const SynchronizationStamp &syncStamp) const;
102
103 void onAudioSinkStateChanged(QAudio::State state);
104
105 Microseconds durationForBytes(qsizetype bytes) const;
106
107private:
108 QPointer<QAudioOutput> m_output;
109 QPointer<QAudioBufferOutput> m_bufferOutput;
110 std::unique_ptr<QAudioSink> m_sink;
111 AudioTimings m_timings;
112 BufferLoadingInfo m_bufferLoadingInfo;
113 std::unique_ptr<QFFmpegResampler> m_resampler;
114 std::unique_ptr<QFFmpegResampler> m_bufferOutputResampler;
115 QAudioFormat m_sinkFormat;
116
117 BufferedDataWithOffset m_bufferedData;
118 QIODevice *m_ioDevice = nullptr;
119
120 bool m_lastFramePushDone = true;
121
122 bool m_deviceChanged = false;
123 bool m_bufferOutputChanged = false;
124 bool m_drained = false;
125 bool m_firstFrameToSink = true;
126};
127
128} // namespace QFFmpeg
129
130QT_END_NAMESPACE
131
132#endif // QFFMPEGAUDIORENDERER_P_H
133

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