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 2022 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 "Utils.h"
21 : #include "CapsBuilder.h"
22 : #include "GstMimeMapping.h"
23 : #include "IGlibWrapper.h"
24 : #include "IGstWrapper.h"
25 : #include "RialtoServerLogging.h"
26 : #include <algorithm>
27 : #include <string.h>
28 :
29 : namespace
30 : {
31 : const char *underflowSignals[]{"buffer-underflow-callback", "vidsink-underflow-callback", "underrun-callback"};
32 : const char *firstFrameSignals[]{"first-video-frame-callback"};
33 :
34 207 : bool isType(const firebolt::rialto::wrappers::IGstWrapper &gstWrapper, GstElement *element, GstElementFactoryListType type)
35 : {
36 207 : if (!element)
37 : {
38 0 : return false;
39 : }
40 :
41 207 : GstElementFactory *factory{gstWrapper.gstElementGetFactory(element)};
42 207 : if (!factory)
43 : {
44 0 : return false;
45 : }
46 207 : return gstWrapper.gstElementFactoryListIsType(factory, type);
47 : }
48 : } // namespace
49 :
50 : namespace firebolt::rialto::server
51 : {
52 :
53 3 : bool isVideoDecoder(const firebolt::rialto::wrappers::IGstWrapper &gstWrapper, GstElement *element)
54 : {
55 3 : return isType(gstWrapper, element, GST_ELEMENT_FACTORY_TYPE_DECODER | GST_ELEMENT_FACTORY_TYPE_MEDIA_VIDEO);
56 : }
57 :
58 26 : bool isAudioDecoder(const firebolt::rialto::wrappers::IGstWrapper &gstWrapper, GstElement *element)
59 : {
60 26 : return isType(gstWrapper, element, GST_ELEMENT_FACTORY_TYPE_DECODER | GST_ELEMENT_FACTORY_TYPE_MEDIA_AUDIO);
61 : }
62 :
63 8 : bool isVideoParser(const firebolt::rialto::wrappers::IGstWrapper &gstWrapper, GstElement *element)
64 : {
65 8 : return isType(gstWrapper, element, GST_ELEMENT_FACTORY_TYPE_PARSER | GST_ELEMENT_FACTORY_TYPE_MEDIA_VIDEO);
66 : }
67 :
68 3 : bool isAudioParser(const firebolt::rialto::wrappers::IGstWrapper &gstWrapper, GstElement *element)
69 : {
70 3 : return isType(gstWrapper, element, GST_ELEMENT_FACTORY_TYPE_PARSER | GST_ELEMENT_FACTORY_TYPE_MEDIA_AUDIO);
71 : }
72 :
73 34 : bool isVideoSink(const firebolt::rialto::wrappers::IGstWrapper &gstWrapper, GstElement *element)
74 : {
75 34 : return isType(gstWrapper, element, GST_ELEMENT_FACTORY_TYPE_SINK | GST_ELEMENT_FACTORY_TYPE_MEDIA_VIDEO);
76 : }
77 :
78 22 : bool isAudioSink(const firebolt::rialto::wrappers::IGstWrapper &gstWrapper, GstElement *element)
79 : {
80 22 : return isType(gstWrapper, element, GST_ELEMENT_FACTORY_TYPE_SINK | GST_ELEMENT_FACTORY_TYPE_MEDIA_AUDIO);
81 : }
82 :
83 27 : bool isSink(const firebolt::rialto::wrappers::IGstWrapper &gstWrapper, GstElement *element)
84 : {
85 27 : return isType(gstWrapper, element, GST_ELEMENT_FACTORY_TYPE_SINK);
86 : }
87 :
88 34 : bool isDecoder(const firebolt::rialto::wrappers::IGstWrapper &gstWrapper, GstElement *element)
89 : {
90 34 : return isType(gstWrapper, element, GST_ELEMENT_FACTORY_TYPE_DECODER);
91 : }
92 :
93 32 : bool isAudio(const firebolt::rialto::wrappers::IGstWrapper &gstWrapper, GstElement *element)
94 : {
95 32 : return isType(gstWrapper, element, GST_ELEMENT_FACTORY_TYPE_MEDIA_AUDIO);
96 : }
97 :
98 18 : bool isVideo(const firebolt::rialto::wrappers::IGstWrapper &gstWrapper, GstElement *element)
99 : {
100 18 : return isType(gstWrapper, element, GST_ELEMENT_FACTORY_TYPE_MEDIA_VIDEO);
101 : }
102 :
103 28 : std::optional<std::string> getUnderflowSignalName(const firebolt::rialto::wrappers::IGlibWrapper &glibWrapper,
104 : GstElement *element)
105 : {
106 28 : GType type = glibWrapper.gObjectType(element);
107 28 : guint nsignals{0};
108 28 : guint *signals = glibWrapper.gSignalListIds(type, &nsignals);
109 :
110 28 : for (guint i = 0; i < nsignals; i++)
111 : {
112 : GSignalQuery query;
113 28 : glibWrapper.gSignalQuery(signals[i], &query);
114 84 : const auto signalNameIt = std::find_if(std::begin(underflowSignals), std::end(underflowSignals),
115 28 : [&](const auto *signalName)
116 28 : { return strcmp(signalName, query.signal_name) == 0; });
117 :
118 28 : if (std::end(underflowSignals) != signalNameIt)
119 : {
120 28 : glibWrapper.gFree(signals);
121 56 : return std::string(*signalNameIt);
122 : }
123 : }
124 0 : glibWrapper.gFree(signals);
125 :
126 0 : return std::nullopt;
127 : }
128 :
129 28 : std::optional<std::string> getFirstFrameSignalName(const firebolt::rialto::wrappers::IGlibWrapper &glibWrapper,
130 : GstElement *element)
131 : {
132 28 : GType type = glibWrapper.gObjectType(element);
133 28 : guint nsignals{0};
134 28 : guint *signals = glibWrapper.gSignalListIds(type, &nsignals);
135 :
136 55 : for (guint i = 0; i < nsignals; i++)
137 : {
138 : GSignalQuery query;
139 28 : glibWrapper.gSignalQuery(signals[i], &query);
140 84 : const auto signalNameIt = std::find_if(std::begin(firstFrameSignals), std::end(firstFrameSignals),
141 28 : [&](const auto *signalName)
142 28 : { return strcmp(signalName, query.signal_name) == 0; });
143 :
144 28 : if (std::end(firstFrameSignals) != signalNameIt)
145 : {
146 1 : glibWrapper.gFree(signals);
147 2 : return std::string(*signalNameIt);
148 : }
149 : }
150 27 : glibWrapper.gFree(signals);
151 :
152 27 : return std::nullopt;
153 : }
154 :
155 24 : GstCaps *createCapsFromMediaSource(const std::shared_ptr<firebolt::rialto::wrappers::IGstWrapper> &gstWrapper,
156 : const std::shared_ptr<firebolt::rialto::wrappers::IGlibWrapper> &glibWrapper,
157 : const std::unique_ptr<IMediaPipeline::MediaSource> &source)
158 : {
159 24 : std::unique_ptr<MediaSourceCapsBuilder> capsBuilder;
160 :
161 24 : firebolt::rialto::SourceConfigType configType = source->getConfigType();
162 24 : if (configType == firebolt::rialto::SourceConfigType::AUDIO)
163 : {
164 14 : const IMediaPipeline::MediaSourceAudio *kSource = dynamic_cast<IMediaPipeline::MediaSourceAudio *>(source.get());
165 14 : if (kSource)
166 : {
167 13 : capsBuilder = std::make_unique<MediaSourceAudioCapsBuilder>(gstWrapper, glibWrapper, *kSource);
168 : }
169 : else
170 : {
171 1 : RIALTO_SERVER_LOG_ERROR("Failed to cast to audio source");
172 1 : return nullptr;
173 : }
174 : }
175 10 : else if (configType == firebolt::rialto::SourceConfigType::VIDEO)
176 : {
177 7 : const IMediaPipeline::MediaSourceVideo *kSource = dynamic_cast<IMediaPipeline::MediaSourceVideo *>(source.get());
178 7 : if (kSource)
179 : {
180 6 : capsBuilder = std::make_unique<MediaSourceVideoCapsBuilder>(gstWrapper, glibWrapper, *kSource);
181 : }
182 : else
183 : {
184 1 : RIALTO_SERVER_LOG_ERROR("Failed to cast to video source");
185 1 : return nullptr;
186 : }
187 : }
188 3 : else if (configType == firebolt::rialto::SourceConfigType::VIDEO_DOLBY_VISION)
189 : {
190 : const IMediaPipeline::MediaSourceVideoDolbyVision *kSource =
191 2 : dynamic_cast<IMediaPipeline::MediaSourceVideoDolbyVision *>(source.get());
192 2 : if (kSource)
193 : {
194 1 : capsBuilder = std::make_unique<MediaSourceVideoDolbyVisionCapsBuilder>(gstWrapper, glibWrapper, *kSource);
195 : }
196 : else
197 : {
198 1 : RIALTO_SERVER_LOG_ERROR("Failed to cast to dolby vision source!");
199 1 : return nullptr;
200 : }
201 : }
202 1 : else if (configType == firebolt::rialto::SourceConfigType::SUBTITLE)
203 : {
204 : // subtitle caps is just a simple type, without any extra parameters
205 1 : return firebolt::rialto::server::createSimpleCapsFromMimeType(gstWrapper, *source.get());
206 : }
207 : else
208 : {
209 0 : RIALTO_SERVER_LOG_ERROR("Invalid config type %u", static_cast<uint32_t>(configType));
210 0 : return nullptr;
211 : }
212 :
213 20 : return capsBuilder->buildCaps();
214 24 : }
215 : } // namespace firebolt::rialto::server
|