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 <cstdint>
20 :
21 : #include <stdio.h>
22 :
23 : #include "GStreamerEMEUtils.h"
24 : #include "GStreamerUtils.h"
25 : #include "GstreamerCatLog.h"
26 : #include "RialtoGStreamerEMEProtectionMetadata.h"
27 :
28 : #define GST_CAT_DEFAULT rialtoGStreamerCat
29 16 : void getEncryptedFromProtectionMetadata(GstRialtoProtectionMetadata *protectionMeta, BufferProtectionMetadata &metadata)
30 : {
31 16 : gboolean encrypted = FALSE;
32 16 : gst_structure_get_boolean(protectionMeta->info, "encrypted", &encrypted);
33 16 : metadata.encrypted = encrypted;
34 : }
35 :
36 16 : void getMediaKeySessionIdFromProtectionMetadata(GstRialtoProtectionMetadata *protectionMeta,
37 : BufferProtectionMetadata &metadata)
38 : {
39 16 : gint mediaKeySessionId = 0;
40 16 : gst_structure_get_int(protectionMeta->info, "mks_id", &mediaKeySessionId);
41 16 : metadata.mediaKeySessionId = mediaKeySessionId;
42 : }
43 :
44 16 : void getKIDFromProtectionMetadata(GstRialtoProtectionMetadata *protectionMeta, BufferProtectionMetadata &metadata)
45 : {
46 16 : const GValue *value = gst_structure_get_value(protectionMeta->info, "kid");
47 16 : if (value)
48 : {
49 8 : GstBuffer *keyIDBuffer = gst_value_get_buffer(value);
50 8 : if (keyIDBuffer)
51 : {
52 8 : GstMappedBuffer mappedKeyID(keyIDBuffer, GST_MAP_READ);
53 8 : if (mappedKeyID)
54 : {
55 16 : metadata.kid = std::vector<uint8_t>(mappedKeyID.data(), mappedKeyID.data() + mappedKeyID.size());
56 : }
57 8 : }
58 : }
59 16 : }
60 :
61 16 : void getIVFromProtectionMetadata(GstRialtoProtectionMetadata *protectionMeta, BufferProtectionMetadata &metadata)
62 : {
63 16 : unsigned ivSize = 0;
64 16 : gst_structure_get_uint(protectionMeta->info, "iv_size", &ivSize);
65 16 : if (!ivSize && !g_strcmp0(gst_structure_get_string(protectionMeta->info, "cipher-mode"), "cbcs"))
66 : {
67 : // in case of cbcs, the same initialization vector is used to decrypt all the blocks
68 2 : gst_structure_get_uint(protectionMeta->info, "constant_iv_size", &ivSize);
69 : }
70 16 : const GValue *value = gst_structure_get_value(protectionMeta->info, "iv");
71 16 : if (value)
72 : {
73 9 : GstBuffer *ivBuffer = gst_value_get_buffer(value);
74 9 : if (ivBuffer)
75 : {
76 9 : GstMappedBuffer mappedIV(ivBuffer, GST_MAP_READ);
77 9 : if (mappedIV && (ivSize == mappedIV.size()))
78 : {
79 18 : metadata.iv = std::vector<uint8_t>(mappedIV.data(), mappedIV.data() + mappedIV.size());
80 : }
81 9 : }
82 : }
83 16 : }
84 :
85 16 : void getSubSamplesFromProtectionMetadata(GstRialtoProtectionMetadata *protectionMeta, BufferProtectionMetadata &metadata)
86 : {
87 16 : unsigned int subSampleCount = 0;
88 16 : gst_structure_get_uint(protectionMeta->info, "subsample_count", &subSampleCount);
89 :
90 16 : if (subSampleCount)
91 : {
92 1 : const GValue *value = gst_structure_get_value(protectionMeta->info, "subsamples");
93 1 : if (value)
94 : {
95 1 : GstBuffer *subSamplesBuffer = gst_value_get_buffer(value);
96 1 : if (subSamplesBuffer)
97 : {
98 1 : GstMappedBuffer mappedSubSamples(subSamplesBuffer, GST_MAP_READ);
99 1 : if (mappedSubSamples &&
100 1 : ((mappedSubSamples.size() / (sizeof(int16_t) + sizeof(int32_t))) == subSampleCount))
101 : {
102 : std::vector<uint8_t> subSamples(mappedSubSamples.data(),
103 1 : mappedSubSamples.data() + mappedSubSamples.size());
104 : //'senc' atom
105 : // unsigned int(16) subsample_count;
106 : //{
107 : // unsigned int(16) BytesOfClearData;
108 : // unsigned int(32) BytesOfEncryptedData;
109 : //}[subsample_count]
110 1 : size_t subSampleOffset = 0;
111 2 : for (unsigned int subSampleIdx = 0; subSampleIdx < subSampleCount; ++subSampleIdx)
112 : {
113 1 : uint16_t bytesOfClearData = (uint16_t)subSamples[subSampleOffset] << 8 |
114 1 : (uint16_t)subSamples[subSampleOffset + 1];
115 1 : uint32_t bytesOfEncryptedData = (uint32_t)subSamples[subSampleOffset + 2] << 24 |
116 1 : (uint32_t)subSamples[subSampleOffset + 3] << 16 |
117 1 : (uint32_t)subSamples[subSampleOffset + 4] << 8 |
118 1 : (uint32_t)subSamples[subSampleOffset + 5];
119 1 : metadata.subsamples.push_back(
120 1 : std::make_pair((uint32_t)bytesOfClearData, (uint32_t)bytesOfEncryptedData));
121 1 : subSampleOffset += sizeof(int16_t) + sizeof(int32_t);
122 : }
123 : }
124 : }
125 : }
126 : }
127 16 : }
128 :
129 16 : void getInitWithLast15FromProtectionMetadata(GstRialtoProtectionMetadata *protectionMeta,
130 : BufferProtectionMetadata &metadata)
131 : {
132 16 : guint initWithLast15 = 0;
133 16 : gst_structure_get_uint(protectionMeta->info, "init_with_last_15", &initWithLast15);
134 16 : metadata.initWithLast15 = initWithLast15;
135 : }
136 :
137 16 : void getEncryptionSchemeFromProtectionMetadata(GstRialtoProtectionMetadata *protectionMeta,
138 : BufferProtectionMetadata &metadata)
139 : {
140 16 : const char *cipherModeBuf = gst_structure_get_string(protectionMeta->info, "cipher-mode");
141 16 : GST_INFO("Retrieved encryption scheme '%s' from protection metadata.", cipherModeBuf ? cipherModeBuf : "unknown");
142 16 : if (g_strcmp0(cipherModeBuf, "cbcs") == 0)
143 : {
144 2 : metadata.cipherMode = firebolt::rialto::CipherMode::CBCS;
145 : }
146 14 : else if (g_strcmp0(cipherModeBuf, "cenc") == 0)
147 : {
148 1 : metadata.cipherMode = firebolt::rialto::CipherMode::CENC;
149 : }
150 13 : else if (g_strcmp0(cipherModeBuf, "cbc1") == 0)
151 : {
152 1 : metadata.cipherMode = firebolt::rialto::CipherMode::CBC1;
153 : }
154 12 : else if (g_strcmp0(cipherModeBuf, "cens") == 0)
155 : {
156 1 : metadata.cipherMode = firebolt::rialto::CipherMode::CENS;
157 : }
158 : else
159 : {
160 11 : if (cipherModeBuf)
161 : {
162 1 : GST_ERROR("Unknown encryption scheme '%s'!", cipherModeBuf);
163 : }
164 : else
165 : {
166 10 : GST_ERROR("Missing encryption scheme!");
167 : }
168 11 : metadata.cipherMode = firebolt::rialto::CipherMode::UNKNOWN;
169 : }
170 16 : }
171 :
172 16 : void getEncryptionPatternFromProtectionMetadata(GstRialtoProtectionMetadata *protectionMeta,
173 : BufferProtectionMetadata &metadata)
174 : {
175 16 : if (gst_structure_get_uint(protectionMeta->info, "crypt_byte_block", &metadata.cryptBlocks) == false)
176 : {
177 7 : GST_INFO("Failed to get crypt_byte_block value!");
178 7 : return;
179 : }
180 9 : if (gst_structure_get_uint(protectionMeta->info, "skip_byte_block", &metadata.skipBlocks) == false)
181 : {
182 1 : GST_INFO("Failed to get skip_byte_block value!");
183 1 : return;
184 : }
185 :
186 8 : GST_INFO("Successful retrieval of 'crypt_byte_block' and 'skip_byte_block'.");
187 8 : metadata.encryptionPatternSet = true;
188 : }
189 :
190 19 : void ProcessProtectionMetadata(GstBuffer *buffer, BufferProtectionMetadata &metadata)
191 : {
192 19 : if (buffer == nullptr)
193 1 : return;
194 :
195 : GstRialtoProtectionMetadata *protectionMeta = reinterpret_cast<GstRialtoProtectionMetadata *>(
196 18 : gst_buffer_get_meta(buffer, GST_RIALTO_PROTECTION_METADATA_GET_TYPE));
197 18 : if (protectionMeta)
198 : {
199 16 : getEncryptedFromProtectionMetadata(protectionMeta, metadata);
200 16 : if (metadata.encrypted)
201 : {
202 16 : getMediaKeySessionIdFromProtectionMetadata(protectionMeta, metadata);
203 16 : getKIDFromProtectionMetadata(protectionMeta, metadata);
204 16 : getIVFromProtectionMetadata(protectionMeta, metadata);
205 16 : getSubSamplesFromProtectionMetadata(protectionMeta, metadata);
206 16 : getInitWithLast15FromProtectionMetadata(protectionMeta, metadata);
207 16 : getEncryptionSchemeFromProtectionMetadata(protectionMeta, metadata);
208 16 : getEncryptionPatternFromProtectionMetadata(protectionMeta, metadata);
209 : }
210 : }
211 : }
|