Line data Source code
1 : /*
2 : * Copyright (C) 2022 Sky UK
3 : *
4 : * This library is free software; you can redistribute it and/or
5 : * modify it under the terms of the GNU Lesser General Public
6 : * License as published by the Free Software Foundation;
7 : * version 2.1 of the License.
8 : *
9 : * This library is distributed in the hope that it will be useful,
10 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 : * Lesser General Public License for more details.
13 : *
14 : * You should have received a copy of the GNU Lesser General Public
15 : * License along with this library; if not, write to the Free Software
16 : * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17 : */
18 :
19 : #include "GStreamerMSEUtils.h"
20 : #include "GStreamerUtils.h"
21 : #include "GstreamerCatLog.h"
22 :
23 : #include <cstdint>
24 : #include <cstring>
25 : #include <unordered_map>
26 : #include <unordered_set>
27 :
28 : #define GST_CAT_DEFAULT rialtoGStreamerCat
29 :
30 3 : void rialto_mse_sink_setup_supported_caps(GstElementClass *elementClass,
31 : const std::vector<std::string> &supportedMimeTypes)
32 : {
33 : static const std::unordered_map<std::string, std::vector<std::string>> kMimeToCaps =
34 : {{"audio/mp4", {"audio/mpeg, mpegversion=1", "audio/mpeg, mpegversion=2", "audio/mpeg, mpegversion=4"}},
35 : {"audio/mp3", {"audio/mpeg, mpegversion=1", "audio/mpeg, mpegversion=2"}},
36 : {"audio/aac", {"audio/mpeg, mpegversion=2", "audio/mpeg, mpegversion=4"}},
37 : {"audio/x-eac3", {"audio/x-ac3", "audio/x-eac3"}},
38 : {"audio/x-opus", {"audio/x-opus"}},
39 : {"audio/b-wav", {"audio/b-wav"}},
40 : {"audio/x-flac", {"audio/x-flac"}},
41 : #ifdef RIALTO_ENABLE_X_RAW
42 : {"audio/x-raw", {"audio/x-raw"}},
43 : #endif
44 : {"video/h264", {"video/x-h264"}},
45 : {"video/h265", {"video/x-h265"}},
46 : {"video/x-av1", {"video/x-av1"}},
47 : {"video/x-vp9", {"video/x-vp9"}},
48 : {"text/vtt", {"text/vtt", "application/x-subtitle-vtt"}},
49 19 : {"text/ttml", {"application/ttml+xml"}}};
50 :
51 3 : std::unordered_set<std::string> addedCaps; // keep track what caps were added to avoid duplicates
52 3 : GstCaps *caps = gst_caps_new_empty();
53 18 : for (const std::string &mime : supportedMimeTypes)
54 : {
55 15 : auto mimeToCapsIt = kMimeToCaps.find(mime);
56 15 : if (mimeToCapsIt != kMimeToCaps.end())
57 : {
58 34 : for (const std::string &capsStr : mimeToCapsIt->second)
59 : {
60 20 : if (addedCaps.find(capsStr) == addedCaps.end())
61 : {
62 16 : GST_INFO("Caps '%s' is supported", capsStr.c_str());
63 16 : GstCaps *newCaps = gst_caps_from_string(capsStr.c_str());
64 16 : gst_caps_append(caps, newCaps);
65 16 : addedCaps.insert(capsStr);
66 : }
67 : }
68 : }
69 : else
70 : {
71 1 : GST_WARNING("Mime '%s' is not supported", mime.c_str());
72 : }
73 : }
74 :
75 3 : GstPadTemplate *sinktempl = gst_pad_template_new("sink", GST_PAD_SINK, GST_PAD_ALWAYS, caps);
76 3 : gst_element_class_add_pad_template(elementClass, sinktempl);
77 3 : gst_caps_unref(caps);
78 7 : }
79 :
80 5 : std::optional<firebolt::rialto::Layout> rialto_mse_sink_convert_layout(const gchar *layoutStr)
81 : {
82 5 : if (g_strcmp0(layoutStr, "interleaved") == 0)
83 : {
84 2 : return firebolt::rialto::Layout::INTERLEAVED;
85 : }
86 3 : if (g_strcmp0(layoutStr, "non-interleaved") == 0)
87 : {
88 2 : return firebolt::rialto::Layout::NON_INTERLEAVED;
89 : }
90 1 : return std::nullopt;
91 : }
92 :
93 33 : std::optional<firebolt::rialto::Format> rialto_mse_sink_convert_format(const gchar *formatStr)
94 : {
95 : static const std::unordered_map<std::string, firebolt::rialto::Format>
96 0 : kStringToFormat{{"S8", firebolt::rialto::Format::S8},
97 0 : {"U8", firebolt::rialto::Format::U8},
98 0 : {"S16LE", firebolt::rialto::Format::S16LE},
99 0 : {"S16BE", firebolt::rialto::Format::S16BE},
100 0 : {"U16LE", firebolt::rialto::Format::U16LE},
101 0 : {"U16BE", firebolt::rialto::Format::U16BE},
102 0 : {"S24_32LE", firebolt::rialto::Format::S24_32LE},
103 0 : {"S24_32BE", firebolt::rialto::Format::S24_32BE},
104 0 : {"U24_32LE", firebolt::rialto::Format::U24_32LE},
105 0 : {"U24_32BE", firebolt::rialto::Format::U24_32BE},
106 0 : {"S32LE", firebolt::rialto::Format::S32LE},
107 0 : {"S32BE", firebolt::rialto::Format::S32BE},
108 0 : {"U32LE", firebolt::rialto::Format::U32LE},
109 0 : {"U32BE", firebolt::rialto::Format::U32BE},
110 0 : {"S24LE", firebolt::rialto::Format::S24LE},
111 0 : {"S24BE", firebolt::rialto::Format::S24BE},
112 0 : {"U24LE", firebolt::rialto::Format::U24LE},
113 0 : {"U24BE", firebolt::rialto::Format::U24BE},
114 0 : {"S20LE", firebolt::rialto::Format::S20LE},
115 0 : {"S20BE", firebolt::rialto::Format::S20BE},
116 0 : {"U20LE", firebolt::rialto::Format::U20LE},
117 0 : {"U20BE", firebolt::rialto::Format::U20BE},
118 0 : {"S18LE", firebolt::rialto::Format::S18LE},
119 0 : {"S18BE", firebolt::rialto::Format::S18BE},
120 0 : {"U18LE", firebolt::rialto::Format::U18LE},
121 0 : {"U18BE", firebolt::rialto::Format::U18BE},
122 0 : {"F32LE", firebolt::rialto::Format::F32LE},
123 0 : {"F32BE", firebolt::rialto::Format::F32BE},
124 0 : {"F64LE", firebolt::rialto::Format::F64LE},
125 65 : {"F64BE", firebolt::rialto::Format::F64BE}};
126 33 : const auto it = kStringToFormat.find(formatStr);
127 33 : if (it != kStringToFormat.end())
128 : {
129 32 : return it->second;
130 : }
131 1 : return std::nullopt;
132 : }
133 :
134 127 : std::shared_ptr<firebolt::rialto::CodecData> get_codec_data(const GstStructure *structure)
135 : {
136 127 : const GValue *codec_data = gst_structure_get_value(structure, "codec_data");
137 127 : if (codec_data)
138 : {
139 2 : GstBuffer *buf = gst_value_get_buffer(codec_data);
140 2 : if (buf)
141 : {
142 1 : GstMappedBuffer mappedBuf(buf, GST_MAP_READ);
143 1 : if (mappedBuf)
144 : {
145 1 : auto codecData = std::make_shared<firebolt::rialto::CodecData>();
146 1 : codecData->data = std::vector<std::uint8_t>(mappedBuf.data(), mappedBuf.data() + mappedBuf.size());
147 1 : codecData->type = firebolt::rialto::CodecDataType::BUFFER;
148 1 : return codecData;
149 : }
150 : else
151 : {
152 0 : GST_ERROR("Failed to read codec_data");
153 0 : return nullptr;
154 : }
155 1 : }
156 1 : const gchar *str = g_value_get_string(codec_data);
157 1 : if (str)
158 : {
159 1 : auto codecData = std::make_shared<firebolt::rialto::CodecData>();
160 1 : codecData->data = std::vector<std::uint8_t>(str, str + std::strlen(str));
161 1 : codecData->type = firebolt::rialto::CodecDataType::STRING;
162 1 : return codecData;
163 : }
164 : }
165 :
166 125 : return nullptr;
167 : }
168 :
169 127 : firebolt::rialto::SegmentAlignment get_segment_alignment(const GstStructure *s)
170 : {
171 127 : const gchar *alignment = gst_structure_get_string(s, "alignment");
172 127 : if (alignment)
173 : {
174 3 : GST_DEBUG("Alignment found %s", alignment);
175 3 : if (strcmp(alignment, "au") == 0)
176 : {
177 1 : return firebolt::rialto::SegmentAlignment::AU;
178 : }
179 2 : else if (strcmp(alignment, "nal") == 0)
180 : {
181 1 : return firebolt::rialto::SegmentAlignment::NAL;
182 : }
183 : }
184 :
185 125 : return firebolt::rialto::SegmentAlignment::UNDEFINED;
186 : }
187 :
188 4 : bool get_dv_profile(const GstStructure *s, uint32_t &dvProfile)
189 : {
190 4 : gboolean isDolbyVisionEnabled = false;
191 4 : if (gst_structure_get_boolean(s, "dovi-stream", &isDolbyVisionEnabled) && isDolbyVisionEnabled)
192 : {
193 1 : if (gst_structure_get_uint(s, "dv_profile", &dvProfile))
194 : {
195 1 : return true;
196 : }
197 : }
198 3 : return false;
199 : }
200 :
201 127 : firebolt::rialto::StreamFormat get_stream_format(const GstStructure *structure)
202 : {
203 127 : const gchar *streamFormat = gst_structure_get_string(structure, "stream-format");
204 127 : firebolt::rialto::StreamFormat format = firebolt::rialto::StreamFormat::UNDEFINED;
205 127 : if (streamFormat)
206 : {
207 : static const std::unordered_map<std::string, firebolt::rialto::StreamFormat> stringToStreamFormatMap =
208 0 : {{"raw", firebolt::rialto::StreamFormat::RAW},
209 0 : {"avc", firebolt::rialto::StreamFormat::AVC},
210 0 : {"byte-stream", firebolt::rialto::StreamFormat::BYTE_STREAM},
211 0 : {"hvc1", firebolt::rialto::StreamFormat::HVC1},
212 12 : {"hev1", firebolt::rialto::StreamFormat::HEV1}};
213 :
214 5 : auto strToStreamFormatIt = stringToStreamFormatMap.find(streamFormat);
215 5 : if (strToStreamFormatIt != stringToStreamFormatMap.end())
216 : {
217 5 : format = strToStreamFormatIt->second;
218 : }
219 : }
220 :
221 127 : return format;
222 1 : }
|