Line data Source code
1 : /*
2 : * If not stated otherwise in this file or this component's LICENSE file the
3 : * following copyright and licenses apply:
4 : *
5 : * Copyright 2023 Sky UK
6 : *
7 : * Licensed under the Apache License, Version 2.0 (the "License");
8 : * you may not use this file except in compliance with the License.
9 : * You may obtain a copy of the License at
10 : *
11 : * http://www.apache.org/licenses/LICENSE-2.0
12 : *
13 : * Unless required by applicable law or agreed to in writing, software
14 : * distributed under the License is distributed on an "AS IS" BASIS,
15 : * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 : * See the License for the specific language governing permissions and
17 : * limitations under the License.
18 : */
19 :
20 : #include "tasks/webAudio/SetCaps.h"
21 : #include "IGlibWrapper.h"
22 : #include "IGstWrapper.h"
23 : #include "RialtoServerLogging.h"
24 :
25 : #include <gst/audio/gstaudiobasesink.h>
26 : #include <limits.h>
27 : #include <stdexcept>
28 :
29 : namespace firebolt::rialto::server::tasks::webaudio
30 : {
31 : namespace
32 : {
33 : class WebAudioCapsBuilder
34 : {
35 : public:
36 5 : WebAudioCapsBuilder(std::shared_ptr<firebolt::rialto::wrappers::IGstWrapper> gstWrapper,
37 : std::shared_ptr<firebolt::rialto::wrappers::IGlibWrapper> glibWrapper)
38 5 : : m_gstWrapper(gstWrapper), m_glibWrapper(glibWrapper)
39 : {
40 : }
41 5 : virtual ~WebAudioCapsBuilder() = default;
42 : virtual GstCaps *buildCaps() = 0;
43 :
44 : protected:
45 : std::shared_ptr<firebolt::rialto::wrappers::IGstWrapper> m_gstWrapper;
46 : std::shared_ptr<firebolt::rialto::wrappers::IGlibWrapper> m_glibWrapper;
47 : };
48 :
49 : class WebAudioPcmCapsBuilder : public WebAudioCapsBuilder
50 : {
51 : public:
52 5 : WebAudioPcmCapsBuilder(std::shared_ptr<firebolt::rialto::wrappers::IGstWrapper> gstWrapper,
53 : std::shared_ptr<firebolt::rialto::wrappers::IGlibWrapper> glibWrapper,
54 : const WebAudioPcmConfig &pcmConfig)
55 5 : : WebAudioCapsBuilder(gstWrapper, glibWrapper), m_pcmConfig(pcmConfig)
56 : {
57 : }
58 10 : ~WebAudioPcmCapsBuilder() override = default;
59 :
60 5 : GstCaps *buildCaps() override
61 : {
62 5 : GstCaps *caps = m_gstWrapper->gstCapsNewEmptySimple("audio/x-raw");
63 5 : addFormat(caps);
64 5 : m_gstWrapper->gstCapsSetSimple(caps, "channels", G_TYPE_INT, m_pcmConfig.channels, "layout", G_TYPE_STRING,
65 5 : "interleaved", "rate", G_TYPE_INT, m_pcmConfig.rate, "channel-mask",
66 : GST_TYPE_BITMASK,
67 5 : m_gstWrapper->gstAudioChannelGetFallbackMask(m_pcmConfig.channels), nullptr);
68 :
69 5 : return caps;
70 : }
71 :
72 : protected:
73 5 : void addFormat(GstCaps *caps)
74 : {
75 5 : std::string format;
76 :
77 5 : if (m_pcmConfig.isFloat)
78 : {
79 1 : format += "F";
80 : }
81 4 : else if (m_pcmConfig.isSigned)
82 : {
83 1 : format += "S";
84 : }
85 : else
86 : {
87 3 : format += "U";
88 : }
89 :
90 5 : format += std::to_string(m_pcmConfig.sampleSize);
91 :
92 5 : if (m_pcmConfig.isBigEndian)
93 : {
94 1 : format += "BE";
95 : }
96 : else
97 : {
98 4 : format += "LE";
99 : }
100 :
101 5 : m_gstWrapper->gstCapsSetSimple(caps, "format", G_TYPE_STRING, format.c_str(), nullptr);
102 : }
103 :
104 : const WebAudioPcmConfig &m_pcmConfig;
105 : };
106 : }; // namespace
107 :
108 7 : SetCaps::SetCaps(WebAudioPlayerContext &context, std::shared_ptr<firebolt::rialto::wrappers::IGstWrapper> gstWrapper,
109 : std::shared_ptr<firebolt::rialto::wrappers::IGlibWrapper> glibWrapper,
110 7 : const std::string &audioMimeType, std::weak_ptr<const WebAudioConfig> webAudioConfig)
111 7 : : m_context{context}, m_gstWrapper{gstWrapper}, m_glibWrapper{glibWrapper}, m_audioMimeType{audioMimeType}
112 : {
113 7 : RIALTO_SERVER_LOG_DEBUG("Constructing SetCaps");
114 :
115 7 : if (m_audioMimeType == "audio/x-raw")
116 : {
117 6 : std::shared_ptr<const WebAudioConfig> kConfig = webAudioConfig.lock();
118 6 : if (kConfig == nullptr)
119 : {
120 0 : throw std::runtime_error("Config is null for 'audio/x-raw'");
121 : }
122 6 : m_config.pcm = kConfig->pcm;
123 : }
124 7 : }
125 :
126 15 : SetCaps::~SetCaps()
127 : {
128 7 : RIALTO_SERVER_LOG_DEBUG("SetCaps finished");
129 8 : }
130 :
131 6 : void SetCaps::execute() const
132 : {
133 6 : RIALTO_SERVER_LOG_DEBUG("Executing SetCaps");
134 :
135 6 : GstCaps *caps = createCapsFromMimeType();
136 6 : if (caps)
137 : {
138 5 : gchar *capsStr = m_gstWrapper->gstCapsToString(caps);
139 5 : std::string strCaps = capsStr;
140 5 : m_glibWrapper->gFree(capsStr);
141 :
142 5 : RIALTO_SERVER_LOG_DEBUG("caps str: '%s'", strCaps.c_str());
143 :
144 5 : GstCaps *appsrcCaps = m_gstWrapper->gstAppSrcGetCaps(GST_APP_SRC(m_context.source));
145 5 : if ((!appsrcCaps) || (!m_gstWrapper->gstCapsIsEqual(appsrcCaps, caps)))
146 : {
147 4 : RIALTO_SERVER_LOG_INFO("Updating web audio appsrc caps to '%s'", strCaps.c_str());
148 4 : m_gstWrapper->gstAppSrcSetCaps(GST_APP_SRC(m_context.source), caps);
149 : }
150 :
151 5 : if (appsrcCaps)
152 4 : m_gstWrapper->gstCapsUnref(appsrcCaps);
153 5 : if (caps)
154 5 : m_gstWrapper->gstCapsUnref(caps);
155 :
156 5 : setBytesPerSample();
157 : }
158 6 : }
159 :
160 6 : GstCaps *SetCaps::createCapsFromMimeType() const
161 : {
162 6 : std::unique_ptr<WebAudioCapsBuilder> capsBuilder;
163 :
164 6 : if (m_audioMimeType == "audio/x-raw")
165 : {
166 5 : capsBuilder = std::make_unique<WebAudioPcmCapsBuilder>(m_gstWrapper, m_glibWrapper, m_config.pcm);
167 : }
168 : else
169 : {
170 1 : RIALTO_SERVER_LOG_ERROR("Invalid audio mime type %s", m_audioMimeType.c_str());
171 1 : return nullptr;
172 : }
173 :
174 5 : return capsBuilder->buildCaps();
175 6 : }
176 :
177 5 : void SetCaps::setBytesPerSample() const
178 : {
179 5 : if (m_audioMimeType == "audio/x-raw")
180 : {
181 5 : m_context.bytesPerSample = m_config.pcm.channels * (m_config.pcm.sampleSize / CHAR_BIT);
182 : }
183 : else
184 : {
185 0 : RIALTO_SERVER_LOG_ERROR("Cannot set bytes per sample, invalid audio mime type %s", m_audioMimeType.c_str());
186 : }
187 5 : }
188 :
189 : } // namespace firebolt::rialto::server::tasks::webaudio
|