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