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 : {"audio/x-raw", {"audio/x-raw"}},
42 : {"video/h264", {"video/x-h264"}},
43 : {"video/h265", {"video/x-h265"}},
44 : {"video/x-av1", {"video/x-av1"}},
45 : {"video/x-vp9", {"video/x-vp9"}},
46 : {"text/vtt", {"text/vtt", "application/x-subtitle-vtt"}},
47 : {"text/ttml", {"application/ttml+xml"}},
48 : {"text/cc",
49 : {"closedcaption/x-cea-608", "closedcaption/x-cea-708", "application/x-cea-608", "application/x-cea-708",
50 20 : "application/x-subtitle-cc"}}};
51 :
52 3 : std::unordered_set<std::string> addedCaps; // keep track what caps were added to avoid duplicates
53 3 : GstCaps *caps = gst_caps_new_empty();
54 19 : for (const std::string &mime : supportedMimeTypes)
55 : {
56 16 : auto mimeToCapsIt = kMimeToCaps.find(mime);
57 16 : if (mimeToCapsIt != kMimeToCaps.end())
58 : {
59 40 : for (const std::string &capsStr : mimeToCapsIt->second)
60 : {
61 25 : if (addedCaps.find(capsStr) == addedCaps.end())
62 : {
63 21 : GST_INFO("Caps '%s' is supported", capsStr.c_str());
64 21 : GstCaps *newCaps = gst_caps_from_string(capsStr.c_str());
65 21 : gst_caps_append(caps, newCaps);
66 21 : addedCaps.insert(capsStr);
67 : }
68 : }
69 : }
70 : else
71 : {
72 1 : GST_WARNING("Mime '%s' is not supported", mime.c_str());
73 : }
74 : }
75 :
76 3 : GstPadTemplate *sinktempl = gst_pad_template_new("sink", GST_PAD_SINK, GST_PAD_ALWAYS, caps);
77 3 : gst_element_class_add_pad_template(elementClass, sinktempl);
78 3 : gst_caps_unref(caps);
79 7 : }
80 :
81 5 : std::optional<firebolt::rialto::Layout> rialto_mse_sink_convert_layout(const gchar *layoutStr)
82 : {
83 5 : if (g_strcmp0(layoutStr, "interleaved") == 0)
84 : {
85 2 : return firebolt::rialto::Layout::INTERLEAVED;
86 : }
87 3 : if (g_strcmp0(layoutStr, "non-interleaved") == 0)
88 : {
89 2 : return firebolt::rialto::Layout::NON_INTERLEAVED;
90 : }
91 1 : return std::nullopt;
92 : }
93 :
94 33 : std::optional<firebolt::rialto::Format> rialto_mse_sink_convert_format(const gchar *formatStr)
95 : {
96 : static const std::unordered_map<std::string, firebolt::rialto::Format>
97 0 : kStringToFormat{{"S8", firebolt::rialto::Format::S8},
98 0 : {"U8", firebolt::rialto::Format::U8},
99 0 : {"S16LE", firebolt::rialto::Format::S16LE},
100 0 : {"S16BE", firebolt::rialto::Format::S16BE},
101 0 : {"U16LE", firebolt::rialto::Format::U16LE},
102 0 : {"U16BE", firebolt::rialto::Format::U16BE},
103 0 : {"S24_32LE", firebolt::rialto::Format::S24_32LE},
104 0 : {"S24_32BE", firebolt::rialto::Format::S24_32BE},
105 0 : {"U24_32LE", firebolt::rialto::Format::U24_32LE},
106 0 : {"U24_32BE", firebolt::rialto::Format::U24_32BE},
107 0 : {"S32LE", firebolt::rialto::Format::S32LE},
108 0 : {"S32BE", firebolt::rialto::Format::S32BE},
109 0 : {"U32LE", firebolt::rialto::Format::U32LE},
110 0 : {"U32BE", firebolt::rialto::Format::U32BE},
111 0 : {"S24LE", firebolt::rialto::Format::S24LE},
112 0 : {"S24BE", firebolt::rialto::Format::S24BE},
113 0 : {"U24LE", firebolt::rialto::Format::U24LE},
114 0 : {"U24BE", firebolt::rialto::Format::U24BE},
115 0 : {"S20LE", firebolt::rialto::Format::S20LE},
116 0 : {"S20BE", firebolt::rialto::Format::S20BE},
117 0 : {"U20LE", firebolt::rialto::Format::U20LE},
118 0 : {"U20BE", firebolt::rialto::Format::U20BE},
119 0 : {"S18LE", firebolt::rialto::Format::S18LE},
120 0 : {"S18BE", firebolt::rialto::Format::S18BE},
121 0 : {"U18LE", firebolt::rialto::Format::U18LE},
122 0 : {"U18BE", firebolt::rialto::Format::U18BE},
123 0 : {"F32LE", firebolt::rialto::Format::F32LE},
124 0 : {"F32BE", firebolt::rialto::Format::F32BE},
125 0 : {"F64LE", firebolt::rialto::Format::F64LE},
126 65 : {"F64BE", firebolt::rialto::Format::F64BE}};
127 33 : const auto it = kStringToFormat.find(formatStr);
128 33 : if (it != kStringToFormat.end())
129 : {
130 32 : return it->second;
131 : }
132 1 : return std::nullopt;
133 : }
134 :
135 133 : std::shared_ptr<firebolt::rialto::CodecData> get_codec_data(const GstStructure *structure)
136 : {
137 133 : const GValue *codec_data = gst_structure_get_value(structure, "codec_data");
138 133 : if (codec_data)
139 : {
140 2 : GstBuffer *buf = gst_value_get_buffer(codec_data);
141 2 : if (buf)
142 : {
143 1 : GstMappedBuffer mappedBuf(buf, GST_MAP_READ);
144 1 : if (mappedBuf)
145 : {
146 1 : auto codecData = std::make_shared<firebolt::rialto::CodecData>();
147 1 : codecData->data = std::vector<std::uint8_t>(mappedBuf.data(), mappedBuf.data() + mappedBuf.size());
148 1 : codecData->type = firebolt::rialto::CodecDataType::BUFFER;
149 1 : return codecData;
150 : }
151 : else
152 : {
153 0 : GST_ERROR("Failed to read codec_data");
154 0 : return nullptr;
155 : }
156 1 : }
157 1 : const gchar *str = g_value_get_string(codec_data);
158 1 : if (str)
159 : {
160 1 : auto codecData = std::make_shared<firebolt::rialto::CodecData>();
161 1 : codecData->data = std::vector<std::uint8_t>(str, str + std::strlen(str));
162 1 : codecData->type = firebolt::rialto::CodecDataType::STRING;
163 1 : return codecData;
164 : }
165 : }
166 :
167 131 : return nullptr;
168 : }
169 :
170 133 : firebolt::rialto::SegmentAlignment get_segment_alignment(const GstStructure *s)
171 : {
172 133 : const gchar *alignment = gst_structure_get_string(s, "alignment");
173 133 : if (alignment)
174 : {
175 3 : GST_DEBUG("Alignment found %s", alignment);
176 3 : if (strcmp(alignment, "au") == 0)
177 : {
178 1 : return firebolt::rialto::SegmentAlignment::AU;
179 : }
180 2 : else if (strcmp(alignment, "nal") == 0)
181 : {
182 1 : return firebolt::rialto::SegmentAlignment::NAL;
183 : }
184 : }
185 :
186 131 : return firebolt::rialto::SegmentAlignment::UNDEFINED;
187 : }
188 :
189 4 : bool get_dv_profile(const GstStructure *s, uint32_t &dvProfile)
190 : {
191 4 : gboolean isDolbyVisionEnabled = false;
192 4 : if (gst_structure_get_boolean(s, "dovi-stream", &isDolbyVisionEnabled) && isDolbyVisionEnabled)
193 : {
194 1 : if (gst_structure_get_uint(s, "dv_profile", &dvProfile))
195 : {
196 1 : return true;
197 : }
198 : }
199 3 : return false;
200 : }
201 :
202 133 : firebolt::rialto::StreamFormat get_stream_format(const GstStructure *structure)
203 : {
204 133 : const gchar *streamFormat = gst_structure_get_string(structure, "stream-format");
205 133 : firebolt::rialto::StreamFormat format = firebolt::rialto::StreamFormat::UNDEFINED;
206 133 : if (streamFormat)
207 : {
208 : static const std::unordered_map<std::string, firebolt::rialto::StreamFormat> stringToStreamFormatMap =
209 0 : {{"raw", firebolt::rialto::StreamFormat::RAW},
210 0 : {"avc", firebolt::rialto::StreamFormat::AVC},
211 0 : {"byte-stream", firebolt::rialto::StreamFormat::BYTE_STREAM},
212 0 : {"hvc1", firebolt::rialto::StreamFormat::HVC1},
213 12 : {"hev1", firebolt::rialto::StreamFormat::HEV1}};
214 :
215 5 : auto strToStreamFormatIt = stringToStreamFormatMap.find(streamFormat);
216 5 : if (strToStreamFormatIt != stringToStreamFormatMap.end())
217 : {
218 5 : format = strToStreamFormatIt->second;
219 : }
220 : }
221 :
222 133 : return format;
223 1 : }
|