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 2024 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 "CapsBuilder.h"
21 : #include "GstMimeMapping.h"
22 : #include "RialtoServerLogging.h"
23 : #include "TypeConverters.h"
24 :
25 : namespace firebolt::rialto::server
26 : {
27 16 : MediaSourceCapsBuilder::MediaSourceCapsBuilder(std::shared_ptr<firebolt::rialto::wrappers::IGstWrapper> gstWrapper,
28 : std::shared_ptr<firebolt::rialto::wrappers::IGlibWrapper> glibWrapper,
29 16 : const firebolt::rialto::IMediaPipeline::MediaSourceAV &source)
30 16 : : m_gstWrapper(gstWrapper), m_glibWrapper(glibWrapper), m_attachedSource(source)
31 : {
32 : }
33 15 : GstCaps *MediaSourceCapsBuilder::buildCaps()
34 : {
35 15 : return buildCommonCaps();
36 : }
37 :
38 15 : GstCaps *MediaSourceCapsBuilder::buildCommonCaps()
39 : {
40 15 : GstCaps *caps = firebolt::rialto::server::createSimpleCapsFromMimeType(m_gstWrapper, m_attachedSource);
41 :
42 15 : addAlignmentToCaps(caps);
43 15 : addCodecDataToCaps(caps);
44 15 : addStreamFormatToCaps(caps);
45 :
46 15 : return caps;
47 : }
48 :
49 15 : void MediaSourceCapsBuilder::addAlignmentToCaps(GstCaps *caps) const
50 : {
51 : static const std::unordered_map<firebolt::rialto::SegmentAlignment, std::string> aligmentMap =
52 17 : {{firebolt::rialto::SegmentAlignment::AU, "au"}, {firebolt::rialto::SegmentAlignment::NAL, "nal"}};
53 :
54 15 : auto aligmentMapIt = aligmentMap.find(m_attachedSource.getSegmentAlignment());
55 15 : if (aligmentMapIt != aligmentMap.end())
56 : {
57 7 : m_gstWrapper->gstCapsSetSimple(caps, "alignment", G_TYPE_STRING, aligmentMapIt->second.c_str(), nullptr);
58 : }
59 15 : }
60 :
61 15 : void MediaSourceCapsBuilder::addCodecDataToCaps(GstCaps *caps) const
62 : {
63 15 : const std::shared_ptr<CodecData> &kCodecData = m_attachedSource.getCodecData();
64 15 : if (kCodecData && CodecDataType::BUFFER == kCodecData->type)
65 : {
66 6 : gpointer memory = m_glibWrapper->gMemdup(kCodecData->data.data(), kCodecData->data.size());
67 6 : GstBuffer *buf = m_gstWrapper->gstBufferNewWrapped(memory, kCodecData->data.size());
68 6 : m_gstWrapper->gstCapsSetSimple(caps, "codec_data", GST_TYPE_BUFFER, buf, nullptr);
69 6 : m_gstWrapper->gstBufferUnref(buf);
70 : }
71 9 : else if (kCodecData && CodecDataType::STRING == kCodecData->type)
72 : {
73 1 : std::string codecDataStr{kCodecData->data.begin(), kCodecData->data.end()};
74 1 : m_gstWrapper->gstCapsSetSimple(caps, "codec_data", G_TYPE_STRING, codecDataStr.c_str(), nullptr);
75 : }
76 15 : }
77 :
78 15 : void MediaSourceCapsBuilder::addStreamFormatToCaps(GstCaps *caps) const
79 : {
80 : static const std::unordered_map<firebolt::rialto::StreamFormat, std::string> formatMap =
81 0 : {{firebolt::rialto::StreamFormat::RAW, "raw"},
82 0 : {firebolt::rialto::StreamFormat::AVC, "avc"},
83 0 : {firebolt::rialto::StreamFormat::BYTE_STREAM, "byte-stream"},
84 0 : {firebolt::rialto::StreamFormat::HVC1, "hvc1"},
85 20 : {firebolt::rialto::StreamFormat::HEV1, "hev1"}};
86 :
87 15 : auto formatMapIt = formatMap.find(m_attachedSource.getStreamFormat());
88 15 : if (formatMapIt != formatMap.end())
89 : {
90 7 : m_gstWrapper->gstCapsSetSimple(caps, "stream-format", G_TYPE_STRING, formatMapIt->second.c_str(), nullptr);
91 : }
92 15 : }
93 :
94 9 : MediaSourceAudioCapsBuilder::MediaSourceAudioCapsBuilder(
95 : std::shared_ptr<firebolt::rialto::wrappers::IGstWrapper> gstWrapper,
96 9 : std::shared_ptr<firebolt::rialto::wrappers::IGlibWrapper> glibWrapper, const IMediaPipeline::MediaSourceAudio &source)
97 9 : : MediaSourceCapsBuilder(gstWrapper, glibWrapper, source), m_attachedAudioSource(source)
98 : {
99 : }
100 :
101 9 : GstCaps *MediaSourceAudioCapsBuilder::buildCaps()
102 : {
103 9 : std::string mimeType = m_attachedSource.getMimeType();
104 9 : if (mimeType == "audio/x-opus")
105 : {
106 1 : return createOpusCaps();
107 : }
108 :
109 8 : GstCaps *caps = MediaSourceCapsBuilder::buildCaps();
110 8 : if (mimeType == "audio/mp4" || mimeType == "audio/aac")
111 : {
112 3 : addMpegVersionToCaps(caps);
113 : }
114 5 : else if (mimeType == "audio/b-wav" || mimeType == "audio/x-raw")
115 : {
116 3 : addRawAudioData(caps);
117 : }
118 8 : addSampleRateAndChannelsToCaps(caps);
119 :
120 8 : return caps;
121 9 : }
122 :
123 1 : GstCaps *MediaSourceAudioCapsBuilder::createOpusCaps()
124 : {
125 1 : GstCaps *caps = getAudioSpecificConfiguration();
126 1 : if (!caps)
127 : {
128 0 : caps = m_gstWrapper->gstCapsNewSimple("audio/x-opus", "channel-mapping-family", G_TYPE_INT, 0, nullptr);
129 0 : addSampleRateAndChannelsToCaps(caps);
130 : }
131 :
132 1 : return caps;
133 : }
134 :
135 1 : GstCaps *MediaSourceAudioCapsBuilder::getAudioSpecificConfiguration() const
136 : {
137 1 : GstCaps *caps = nullptr;
138 1 : firebolt::rialto::AudioConfig audioConfig = m_attachedAudioSource.getAudioConfig();
139 1 : if (audioConfig.codecSpecificConfig.size())
140 : {
141 1 : gsize codec_priv_size = audioConfig.codecSpecificConfig.size();
142 1 : gconstpointer codec_priv = audioConfig.codecSpecificConfig.data();
143 :
144 1 : caps = m_gstWrapper->gstCodecUtilsOpusCreateCapsFromHeader(codec_priv, codec_priv_size);
145 1 : if (!caps)
146 : {
147 0 : RIALTO_SERVER_LOG_ERROR("Failed to parse opus header");
148 : }
149 : }
150 :
151 1 : return caps;
152 : }
153 :
154 8 : void MediaSourceAudioCapsBuilder::addSampleRateAndChannelsToCaps(GstCaps *caps) const
155 : {
156 8 : firebolt::rialto::AudioConfig audioConfig = m_attachedAudioSource.getAudioConfig();
157 :
158 8 : if (audioConfig.numberOfChannels != firebolt::rialto::kInvalidAudioChannels)
159 3 : m_gstWrapper->gstCapsSetSimple(caps, "channels", G_TYPE_INT, audioConfig.numberOfChannels, nullptr);
160 :
161 8 : if (audioConfig.sampleRate != firebolt::rialto::kInvalidAudioSampleRate)
162 3 : m_gstWrapper->gstCapsSetSimple(caps, "rate", G_TYPE_INT, audioConfig.sampleRate, nullptr);
163 8 : }
164 :
165 3 : void MediaSourceAudioCapsBuilder::addMpegVersionToCaps(GstCaps *caps) const
166 : {
167 3 : m_gstWrapper->gstCapsSetSimple(caps, "mpegversion", G_TYPE_INT, 4, nullptr);
168 : }
169 :
170 3 : void MediaSourceAudioCapsBuilder::addRawAudioData(GstCaps *caps) const
171 : {
172 3 : firebolt::rialto::AudioConfig audioConfig = m_attachedAudioSource.getAudioConfig();
173 3 : if (audioConfig.format.has_value())
174 2 : m_gstWrapper->gstCapsSetSimple(caps, "format", G_TYPE_STRING, common::convertFormat(audioConfig.format.value()),
175 : nullptr);
176 3 : if (audioConfig.layout.has_value())
177 2 : m_gstWrapper->gstCapsSetSimple(caps, "layout", G_TYPE_STRING, common::convertLayout(audioConfig.layout.value()),
178 : nullptr);
179 3 : if (audioConfig.channelMask.has_value())
180 2 : m_gstWrapper->gstCapsSetSimple(caps, "channel-mask", GST_TYPE_BITMASK, audioConfig.channelMask.value(), nullptr);
181 3 : }
182 :
183 7 : MediaSourceVideoCapsBuilder::MediaSourceVideoCapsBuilder(
184 : std::shared_ptr<firebolt::rialto::wrappers::IGstWrapper> gstWrapper,
185 7 : std::shared_ptr<firebolt::rialto::wrappers::IGlibWrapper> glibWrapper, const IMediaPipeline::MediaSourceVideo &source)
186 7 : : MediaSourceCapsBuilder(gstWrapper, glibWrapper, source), m_attachedVideoSource(source)
187 : {
188 : }
189 :
190 7 : GstCaps *MediaSourceVideoCapsBuilder::buildCaps()
191 : {
192 7 : GstCaps *caps = MediaSourceCapsBuilder::buildCaps();
193 7 : if (m_attachedVideoSource.getWidth() != firebolt::rialto::kUndefinedSize)
194 6 : m_gstWrapper->gstCapsSetSimple(caps, "width", G_TYPE_INT, m_attachedVideoSource.getWidth(), nullptr);
195 7 : if (m_attachedVideoSource.getHeight() != firebolt::rialto::kUndefinedSize)
196 6 : m_gstWrapper->gstCapsSetSimple(caps, "height", G_TYPE_INT, m_attachedVideoSource.getHeight(), nullptr);
197 :
198 7 : return caps;
199 : }
200 :
201 1 : MediaSourceVideoDolbyVisionCapsBuilder::MediaSourceVideoDolbyVisionCapsBuilder(
202 : std::shared_ptr<firebolt::rialto::wrappers::IGstWrapper> gstWrapper,
203 : std::shared_ptr<firebolt::rialto::wrappers::IGlibWrapper> glibWrapper,
204 1 : const IMediaPipeline::MediaSourceVideoDolbyVision &source)
205 1 : : MediaSourceVideoCapsBuilder(gstWrapper, glibWrapper, source), m_attachedDolbySource(source)
206 : {
207 : }
208 :
209 1 : GstCaps *MediaSourceVideoDolbyVisionCapsBuilder::buildCaps()
210 : {
211 1 : GstCaps *caps = MediaSourceVideoCapsBuilder::buildCaps();
212 1 : m_gstWrapper->gstCapsSetSimple(caps, "dovi-stream", G_TYPE_BOOLEAN, true, nullptr);
213 1 : m_gstWrapper->gstCapsSetSimple(caps, "dv_profile", G_TYPE_UINT, m_attachedDolbySource.getDolbyVisionProfile(),
214 : nullptr);
215 1 : return caps;
216 : }
217 : } // namespace firebolt::rialto::server
|