1/****************************************************************************
2**
3** Copyright (C) 2016 The Qt Company Ltd.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** GNU Lesser General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU Lesser
19** General Public License version 3 as published by the Free Software
20** Foundation and appearing in the file LICENSE.LGPL3 included in the
21** packaging of this file. Please review the following information to
22** ensure the GNU Lesser General Public License version 3 requirements
23** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24**
25** GNU General Public License Usage
26** Alternatively, this file may be used under the terms of the GNU
27** General Public License version 2.0 or (at your option) the GNU General
28** Public license version 3 or any later version approved by the KDE Free
29** Qt Foundation. The licenses are as published by the Free Software
30** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31** included in the packaging of this file. Please review the following
32** information to ensure the GNU General Public License requirements will
33** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34** https://www.gnu.org/licenses/gpl-3.0.html.
35**
36** $QT_END_LICENSE$
37**
38****************************************************************************/
39
40#include "qgstreameraudioencode.h"
41#include "qgstreamercapturesession.h"
42#include "qgstreamermediacontainercontrol.h"
43#include <private/qgstutils_p.h>
44
45#include <QtCore/qdebug.h>
46
47#include <math.h>
48
49QGstreamerAudioEncode::QGstreamerAudioEncode(QObject *parent)
50 :QAudioEncoderSettingsControl(parent)
51 , m_codecs(QGstCodecsInfo::AudioEncoder)
52{
53}
54
55QGstreamerAudioEncode::~QGstreamerAudioEncode()
56{
57}
58
59QStringList QGstreamerAudioEncode::supportedAudioCodecs() const
60{
61 return m_codecs.supportedCodecs();
62}
63
64QString QGstreamerAudioEncode::codecDescription(const QString &codecName) const
65{
66 return m_codecs.codecDescription(codec: codecName);
67}
68
69QStringList QGstreamerAudioEncode::supportedEncodingOptions(const QString &codec) const
70{
71 return m_codecs.codecOptions(codec);
72}
73
74QVariant QGstreamerAudioEncode::encodingOption(
75 const QString &codec, const QString &name) const
76{
77 return m_options[codec].value(akey: name);
78}
79
80void QGstreamerAudioEncode::setEncodingOption(
81 const QString &codec, const QString &name, const QVariant &value)
82{
83 m_options[codec][name] = value;
84}
85
86QList<int> QGstreamerAudioEncode::supportedSampleRates(const QAudioEncoderSettings &, bool *) const
87{
88 //TODO check element caps to find actual values
89
90 return QList<int>();
91}
92
93QAudioEncoderSettings QGstreamerAudioEncode::audioSettings() const
94{
95 return m_audioSettings;
96}
97
98void QGstreamerAudioEncode::setAudioSettings(const QAudioEncoderSettings &settings)
99{
100 m_audioSettings = settings;
101}
102
103
104GstElement *QGstreamerAudioEncode::createEncoder()
105{
106 QString codec = m_audioSettings.codec();
107 GstElement *encoderElement = gst_element_factory_make(factoryname: m_codecs.codecElement(codec).constData(), NULL);
108 if (!encoderElement)
109 return 0;
110
111 GstBin * encoderBin = GST_BIN(gst_bin_new("audio-encoder-bin"));
112
113 GstElement *sinkCapsFilter = gst_element_factory_make(factoryname: "capsfilter", NULL);
114 GstElement *srcCapsFilter = gst_element_factory_make(factoryname: "capsfilter", NULL);
115
116 gst_bin_add_many(bin: encoderBin, element_1: sinkCapsFilter, encoderElement, srcCapsFilter, NULL);
117 gst_element_link_many(element_1: sinkCapsFilter, element_2: encoderElement, srcCapsFilter, NULL);
118
119 // add ghostpads
120 GstPad *pad = gst_element_get_static_pad(element: sinkCapsFilter, name: "sink");
121 gst_element_add_pad(GST_ELEMENT(encoderBin), pad: gst_ghost_pad_new(name: "sink", target: pad));
122 gst_object_unref(GST_OBJECT(pad));
123
124 pad = gst_element_get_static_pad(element: srcCapsFilter, name: "src");
125 gst_element_add_pad(GST_ELEMENT(encoderBin), pad: gst_ghost_pad_new(name: "src", target: pad));
126 gst_object_unref(GST_OBJECT(pad));
127
128 if (m_audioSettings.sampleRate() > 0 || m_audioSettings.channelCount() > 0) {
129 GstCaps *caps = gst_caps_new_empty();
130 GstStructure *structure = qt_gst_structure_new_empty(QT_GSTREAMER_RAW_AUDIO_MIME);
131
132 if (m_audioSettings.sampleRate() > 0)
133 gst_structure_set(structure, fieldname: "rate", G_TYPE_INT, m_audioSettings.sampleRate(), NULL );
134
135 if (m_audioSettings.channelCount() > 0)
136 gst_structure_set(structure, fieldname: "channels", G_TYPE_INT, m_audioSettings.channelCount(), NULL );
137
138 gst_caps_append_structure(caps,structure);
139
140 g_object_set(G_OBJECT(sinkCapsFilter), first_property_name: "caps", caps, NULL);
141
142 gst_caps_unref(caps);
143 }
144
145 // Some encoders support several codecs. Setting a caps filter downstream with the desired
146 // codec (which is actually a string representation of the caps) will make sure we use the
147 // correct codec.
148 GstCaps *caps = gst_caps_from_string(string: codec.toUtf8().constData());
149 g_object_set(G_OBJECT(srcCapsFilter), first_property_name: "caps", caps, NULL);
150 gst_caps_unref(caps);
151
152 if (encoderElement) {
153 if (m_audioSettings.encodingMode() == QMultimedia::ConstantQualityEncoding) {
154 QMultimedia::EncodingQuality qualityValue = m_audioSettings.quality();
155
156 if (codec == QLatin1String("audio/x-vorbis")) {
157 double qualityTable[] = {
158 0.1, //VeryLow
159 0.3, //Low
160 0.5, //Normal
161 0.7, //High
162 1.0 //VeryHigh
163 };
164 g_object_set(G_OBJECT(encoderElement), first_property_name: "quality", qualityTable[qualityValue], NULL);
165 } else if (codec == QLatin1String("audio/mpeg")) {
166 g_object_set(G_OBJECT(encoderElement), first_property_name: "target", 0, NULL); //constant quality mode
167 qreal quality[] = {
168 1, //VeryLow
169 3, //Low
170 5, //Normal
171 7, //High
172 9 //VeryHigh
173 };
174 g_object_set(G_OBJECT(encoderElement), first_property_name: "quality", quality[qualityValue], NULL);
175 } else if (codec == QLatin1String("audio/x-speex")) {
176 //0-10 range with default 8
177 double qualityTable[] = {
178 2, //VeryLow
179 5, //Low
180 8, //Normal
181 9, //High
182 10 //VeryHigh
183 };
184 g_object_set(G_OBJECT(encoderElement), first_property_name: "quality", qualityTable[qualityValue], NULL);
185 } else if (codec.startsWith(s: "audio/AMR")) {
186 int band[] = {
187 0, //VeryLow
188 2, //Low
189 4, //Normal
190 6, //High
191 7 //VeryHigh
192 };
193
194 g_object_set(G_OBJECT(encoderElement), first_property_name: "band-mode", band[qualityValue], NULL);
195 }
196 } else {
197 int bitrate = m_audioSettings.bitRate();
198 if (bitrate > 0) {
199 if (codec == QLatin1String("audio/mpeg")) {
200 g_object_set(G_OBJECT(encoderElement), first_property_name: "target", 1, NULL); //constant bitrate mode
201 }
202 g_object_set(G_OBJECT(encoderElement), first_property_name: "bitrate", bitrate, NULL);
203 }
204 }
205
206 QMap<QString, QVariant> options = m_options.value(akey: codec);
207 for (auto it = options.cbegin(), end = options.cend(); it != end; ++it) {
208 const QString &option = it.key();
209 const QVariant &value = it.value();
210
211 switch (value.type()) {
212 case QVariant::Int:
213 g_object_set(G_OBJECT(encoderElement), first_property_name: option.toLatin1(), value.toInt(), NULL);
214 break;
215 case QVariant::Bool:
216 g_object_set(G_OBJECT(encoderElement), first_property_name: option.toLatin1(), value.toBool(), NULL);
217 break;
218 case QVariant::Double:
219 g_object_set(G_OBJECT(encoderElement), first_property_name: option.toLatin1(), value.toDouble(), NULL);
220 break;
221 case QVariant::String:
222 g_object_set(G_OBJECT(encoderElement), first_property_name: option.toLatin1(), value.toString().toUtf8().constData(), NULL);
223 break;
224 default:
225 qWarning() << "unsupported option type:" << option << value;
226 break;
227 }
228
229 }
230 }
231
232 return GST_ELEMENT(encoderBin);
233}
234
235
236QSet<QString> QGstreamerAudioEncode::supportedStreamTypes(const QString &codecName) const
237{
238 return m_codecs.supportedStreamTypes(codec: codecName);
239}
240

source code of qtmultimedia/src/plugins/gstreamer/mediacapture/qgstreameraudioencode.cpp