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 2022 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 "DataReaderV2.h"
21 : #include "RialtoServerLogging.h"
22 : #include "ShmCommon.h"
23 : #include "TypeConverters.h"
24 : #include "metadata.pb.h"
25 :
26 : namespace
27 : {
28 : firebolt::rialto::SegmentAlignment
29 2 : convertSegmentAlignment(const firebolt::rialto::MediaSegmentMetadata_SegmentAlignment &segmentAlignment)
30 : {
31 2 : switch (segmentAlignment)
32 : {
33 0 : case firebolt::rialto::MediaSegmentMetadata_SegmentAlignment_ALIGNMENT_UNDEFINED:
34 : {
35 0 : return firebolt::rialto::SegmentAlignment::UNDEFINED;
36 : }
37 0 : case firebolt::rialto::MediaSegmentMetadata_SegmentAlignment_ALIGNMENT_NAL:
38 : {
39 0 : return firebolt::rialto::SegmentAlignment::NAL;
40 : }
41 2 : case firebolt::rialto::MediaSegmentMetadata_SegmentAlignment_ALIGNMENT_AU:
42 : {
43 2 : return firebolt::rialto::SegmentAlignment::AU;
44 : }
45 : }
46 0 : return firebolt::rialto::SegmentAlignment::UNDEFINED;
47 : }
48 :
49 4 : firebolt::rialto::CipherMode convertCipherMode(const firebolt::rialto::MediaSegmentMetadata_CipherMode &cipherMode)
50 : {
51 4 : switch (cipherMode)
52 : {
53 0 : case firebolt::rialto::MediaSegmentMetadata_CipherMode_UNKNOWN:
54 : {
55 0 : return firebolt::rialto::CipherMode::UNKNOWN;
56 : }
57 1 : case firebolt::rialto::MediaSegmentMetadata_CipherMode_CENC:
58 : {
59 1 : return firebolt::rialto::CipherMode::CENC;
60 : }
61 1 : case firebolt::rialto::MediaSegmentMetadata_CipherMode_CBC1:
62 : {
63 1 : return firebolt::rialto::CipherMode::CBC1;
64 : }
65 1 : case firebolt::rialto::MediaSegmentMetadata_CipherMode_CENS:
66 : {
67 1 : return firebolt::rialto::CipherMode::CENS;
68 : }
69 1 : case firebolt::rialto::MediaSegmentMetadata_CipherMode_CBCS:
70 : {
71 1 : return firebolt::rialto::CipherMode::CBCS;
72 : }
73 : }
74 0 : return firebolt::rialto::CipherMode::UNKNOWN;
75 : }
76 :
77 2 : firebolt::rialto::CodecDataType convertCodecDataType(const firebolt::rialto::MediaSegmentMetadata_CodecData_Type &type)
78 : {
79 2 : if (firebolt::rialto::MediaSegmentMetadata_CodecData_Type_STRING == type)
80 : {
81 0 : return firebolt::rialto::CodecDataType::STRING;
82 : }
83 2 : return firebolt::rialto::CodecDataType::BUFFER;
84 : }
85 :
86 : std::unique_ptr<firebolt::rialto::IMediaPipeline::MediaSegment>
87 11 : createSegment(const firebolt::rialto::MediaSegmentMetadata &metadata, const firebolt::rialto::MediaSourceType &type)
88 : {
89 : // Create segment
90 11 : std::unique_ptr<firebolt::rialto::IMediaPipeline::MediaSegment> segment;
91 11 : if (type == firebolt::rialto::MediaSourceType::AUDIO)
92 : {
93 5 : if (!metadata.has_sample_rate() || !metadata.has_channels_num())
94 : {
95 1 : RIALTO_SERVER_LOG_ERROR("SampleRate/ChannelsNum not present in audio metadata");
96 1 : return nullptr;
97 : }
98 8 : segment = std::make_unique<firebolt::rialto::IMediaPipeline::MediaSegmentAudio>(metadata.stream_id(),
99 4 : metadata.time_position(),
100 4 : metadata.sample_duration(),
101 4 : metadata.sample_rate(),
102 4 : metadata.channels_num(),
103 4 : metadata.clipping_start(),
104 12 : metadata.clipping_end());
105 : }
106 6 : else if (type == firebolt::rialto::MediaSourceType::VIDEO)
107 : {
108 5 : if (!metadata.has_width() || !metadata.has_height())
109 : {
110 1 : RIALTO_SERVER_LOG_ERROR("Width/height not present in video metadata");
111 1 : return nullptr;
112 : }
113 :
114 4 : firebolt::rialto::Fraction frameRate{firebolt::rialto::kUndefinedSize, firebolt::rialto::kUndefinedSize};
115 4 : if (metadata.has_frame_rate())
116 : {
117 4 : frameRate = {metadata.frame_rate().numerator(), metadata.frame_rate().denominator()};
118 : }
119 8 : segment = std::make_unique<firebolt::rialto::IMediaPipeline::MediaSegmentVideo>(metadata.stream_id(),
120 4 : metadata.time_position(),
121 4 : metadata.sample_duration(),
122 4 : metadata.width(),
123 12 : metadata.height(), frameRate);
124 : }
125 1 : else if (type == firebolt::rialto::MediaSourceType::SUBTITLE)
126 : {
127 : segment =
128 2 : std::make_unique<firebolt::rialto::IMediaPipeline::MediaSegment>(metadata.stream_id(),
129 0 : firebolt::rialto::MediaSourceType::SUBTITLE,
130 1 : metadata.time_position(),
131 3 : metadata.sample_duration());
132 : }
133 : else
134 : {
135 0 : RIALTO_SERVER_LOG_ERROR("Unknown segment type");
136 0 : return nullptr;
137 : }
138 :
139 : // Read optional data
140 9 : if (metadata.has_segment_alignment())
141 : {
142 2 : segment->setSegmentAlignment(convertSegmentAlignment(metadata.segment_alignment()));
143 : }
144 9 : if (metadata.has_extra_data())
145 : {
146 2 : segment->setExtraData(std::vector<uint8_t>(metadata.extra_data().begin(), metadata.extra_data().end()));
147 : }
148 9 : if (metadata.has_codec_data())
149 : {
150 2 : auto codecData = std::make_shared<firebolt::rialto::CodecData>();
151 2 : codecData->type = convertCodecDataType(metadata.codec_data().type());
152 2 : codecData->data = std::vector<uint8_t>(metadata.codec_data().data().begin(), metadata.codec_data().data().end());
153 2 : segment->setCodecData(codecData);
154 : }
155 :
156 : // Read encryption data
157 14 : if (metadata.has_media_key_session_id() || metadata.has_key_id() || metadata.has_init_vector() ||
158 5 : metadata.has_init_with_last_15())
159 : {
160 4 : segment->setEncrypted(true);
161 : }
162 : else
163 : {
164 5 : segment->setEncrypted(false);
165 : }
166 9 : if (metadata.has_media_key_session_id())
167 : {
168 4 : segment->setMediaKeySessionId(metadata.media_key_session_id());
169 : }
170 9 : if (metadata.has_key_id())
171 : {
172 4 : segment->setKeyId(std::vector<uint8_t>(metadata.key_id().begin(), metadata.key_id().end()));
173 : }
174 9 : if (metadata.has_init_vector())
175 : {
176 4 : segment->setInitVector(std::vector<uint8_t>(metadata.init_vector().begin(), metadata.init_vector().end()));
177 : }
178 9 : if (metadata.has_init_with_last_15())
179 : {
180 4 : segment->setInitWithLast15(metadata.init_with_last_15());
181 : }
182 9 : if (metadata.has_cipher_mode())
183 : {
184 4 : segment->setCipherMode(convertCipherMode(metadata.cipher_mode()));
185 : }
186 9 : if (metadata.has_crypt() && metadata.has_skip())
187 : {
188 2 : segment->setEncryptionPattern(metadata.crypt(), metadata.skip());
189 : }
190 :
191 13 : for (const auto &info : metadata.sub_sample_info())
192 : {
193 4 : segment->addSubSample(info.num_clear_bytes(), info.num_encrypted_bytes());
194 : }
195 9 : return segment;
196 11 : }
197 : } // namespace
198 :
199 : namespace firebolt::rialto::server
200 : {
201 13 : DataReaderV2::DataReaderV2(const MediaSourceType &mediaSourceType, std::uint8_t *buffer, std::uint32_t dataOffset,
202 13 : std::uint32_t numFrames)
203 13 : : m_mediaSourceType{mediaSourceType}, m_buffer{buffer}, m_dataOffset{dataOffset}, m_numFrames{numFrames}
204 : {
205 13 : RIALTO_SERVER_LOG_DEBUG("Detected Metadata in Version 2. Media source type: %s",
206 : common::convertMediaSourceType(m_mediaSourceType));
207 : }
208 :
209 12 : IMediaPipeline::MediaSegmentVector DataReaderV2::readData() const
210 : {
211 12 : IMediaPipeline::MediaSegmentVector mediaSegments;
212 12 : uint8_t *currentReadPosition{m_buffer + m_dataOffset};
213 21 : for (auto i = 0U; i < m_numFrames; ++i)
214 : {
215 12 : std::uint32_t *metadataSize{reinterpret_cast<uint32_t *>(currentReadPosition)};
216 12 : currentReadPosition += sizeof(uint32_t);
217 12 : MediaSegmentMetadata metadata;
218 12 : if (!metadata.ParseFromArray(currentReadPosition, *metadataSize))
219 : {
220 1 : RIALTO_SERVER_LOG_ERROR("Metadata parsing failed!");
221 1 : return IMediaPipeline::MediaSegmentVector{};
222 : }
223 11 : auto newSegment{createSegment(metadata, m_mediaSourceType)};
224 11 : if (!newSegment)
225 : {
226 2 : RIALTO_SERVER_LOG_ERROR("Segment parsing failed!");
227 2 : return IMediaPipeline::MediaSegmentVector{};
228 : }
229 9 : currentReadPosition += *metadataSize;
230 9 : newSegment->setData(metadata.length(), currentReadPosition);
231 9 : currentReadPosition += metadata.length();
232 9 : mediaSegments.emplace_back(std::move(newSegment));
233 14 : }
234 9 : return mediaSegments;
235 12 : }
236 : } // namespace firebolt::rialto::server
|