7 #include "packager/media/formats/mp4/encrypting_fragmenter.h"
11 #include "packager/media/base/aes_encryptor.h"
12 #include "packager/media/base/buffer_reader.h"
13 #include "packager/media/base/key_source.h"
14 #include "packager/media/base/media_sample.h"
15 #include "packager/media/filters/nalu_reader.h"
16 #include "packager/media/filters/vp8_parser.h"
17 #include "packager/media/filters/vp9_parser.h"
18 #include "packager/media/formats/mp4/box_definitions.h"
20 namespace edash_packager {
26 const size_t kDefaultIvSize = 8u;
27 const size_t kCencBlockSize = 16u;
31 void AddSubsamples(uint64_t clear_bytes,
32 uint64_t cipher_bytes,
33 std::vector<SubsampleEntry>* subsamples) {
34 CHECK_LT(cipher_bytes, std::numeric_limits<uint32_t>::max());
35 const uint64_t kUInt16Max = std::numeric_limits<uint16_t>::max();
36 while (clear_bytes > kUInt16Max) {
37 subsamples->push_back(SubsampleEntry(kUInt16Max, 0));
38 clear_bytes -= kUInt16Max;
41 if (clear_bytes > 0 || cipher_bytes > 0)
42 subsamples->push_back(SubsampleEntry(clear_bytes, cipher_bytes));
45 VideoCodec GetVideoCodec(
const StreamInfo& stream_info) {
46 if (stream_info.stream_type() != kStreamVideo)
47 return kUnknownVideoCodec;
48 const VideoStreamInfo& video_stream_info =
49 static_cast<const VideoStreamInfo&
>(stream_info);
50 return video_stream_info.codec();
53 uint8_t GetNaluLengthSize(
const StreamInfo& stream_info) {
54 if (stream_info.stream_type() != kStreamVideo)
57 const VideoStreamInfo& video_stream_info =
58 static_cast<const VideoStreamInfo&
>(stream_info);
59 return video_stream_info.nalu_length_size();
64 scoped_refptr<StreamInfo> info,
66 scoped_ptr<EncryptionKey> encryption_key,
68 EncryptionMode encryption_mode)
71 encryption_key_(encryption_key.Pass()),
72 nalu_length_size_(GetNaluLengthSize(*info)),
73 video_codec_(GetVideoCodec(*info)),
74 clear_time_(clear_time),
75 encryption_mode_(encryption_mode) {
76 DCHECK(encryption_key_);
77 if (video_codec_ == kCodecVP8) {
79 }
else if (video_codec_ == kCodecVP9) {
81 }
else if (video_codec_ == kCodecH264) {
87 EncryptingFragmenter::~EncryptingFragmenter() {}
91 if (!fragment_initialized()) {
97 Status status = EncryptSample(sample);
109 if (header_parser_ && !header_parser_->Initialize(info_->extra_data()))
110 return Status(error::MUXER_FAILURE,
"Fail to read SPS and PPS data.");
112 traf()->auxiliary_size.sample_info_sizes.clear();
113 traf()->auxiliary_offset.offsets.clear();
114 if (IsSubsampleEncryptionRequired()) {
115 traf()->sample_encryption.flags |=
116 SampleEncryption::kUseSubsampleEncryption;
118 traf()->sample_encryption.sample_encryption_entries.clear();
120 const bool enable_encryption = clear_time_ <= 0;
121 if (!enable_encryption) {
125 const uint32_t kClearSampleDescriptionIndex = 2;
127 traf()->header.flags |=
128 TrackFragmentHeader::kSampleDescriptionIndexPresentMask;
129 traf()->header.sample_description_index = kClearSampleDescriptionIndex;
136 DCHECK_LE(clear_time_, 0);
139 DCHECK_GT(clear_time_, 0);
140 clear_time_ -= fragment_duration();
146 bool enable_encryption) {
147 return (!enable_encryption || encryptor_) ? Status::OK :
CreateEncryptor();
152 traf()->auxiliary_offset.offsets.push_back(0);
156 saiz.sample_count = traf()->runs[0].sample_sizes.size();
157 if (!saiz.sample_info_sizes.empty()) {
159 &saiz.default_sample_info_size)) {
160 saiz.default_sample_info_size = 0;
165 DCHECK(!IsSubsampleEncryptionRequired());
166 saiz.default_sample_info_size = encryptor_->iv().size();
168 traf()->sample_encryption.iv_size = encryptor_->iv().size();
172 DCHECK(encryption_key_);
173 scoped_ptr<AesEncryptor> encryptor;
174 if (encryption_mode_ == kEncryptionModeAesCtr) {
176 }
else if (encryption_mode_ == kEncryptionModeAesCbc) {
179 return Status(error::MUXER_FAILURE,
"Unsupported encryption mode.");
181 const bool initialized = encryption_key_->iv.empty()
182 ? encryptor->InitializeWithRandomIv(
183 encryption_key_->key, kDefaultIvSize)
184 : encryptor->InitializeWithIv(
185 encryption_key_->key, encryption_key_->iv);
187 return Status(error::MUXER_FAILURE,
"Failed to create the encryptor.");
188 encryptor_ = encryptor.Pass();
192 void EncryptingFragmenter::EncryptBytes(uint8_t* data, uint32_t size) {
194 CHECK(encryptor_->EncryptData(data, size, data));
197 Status EncryptingFragmenter::EncryptSample(scoped_refptr<MediaSample> sample) {
200 SampleEncryptionEntry sample_encryption_entry;
201 sample_encryption_entry.initialization_vector = encryptor_->iv();
202 uint8_t* data = sample->writable_data();
203 if (IsSubsampleEncryptionRequired()) {
205 std::vector<VPxFrameInfo> vpx_frames;
206 if (!vpx_parser_->Parse(sample->data(), sample->data_size(),
208 return Status(error::MUXER_FAILURE,
"Failed to parse vpx frame.");
211 const bool is_superframe = vpx_frames.size() > 1;
212 for (
const VPxFrameInfo& frame : vpx_frames) {
213 SubsampleEntry subsample;
214 subsample.clear_bytes = frame.uncompressed_header_size;
215 subsample.cipher_bytes =
216 frame.frame_size - frame.uncompressed_header_size;
223 uint16_t misalign_bytes = subsample.cipher_bytes % kCencBlockSize;
224 subsample.clear_bytes += misalign_bytes;
225 subsample.cipher_bytes -= misalign_bytes;
228 sample_encryption_entry.subsamples.push_back(subsample);
229 if (subsample.cipher_bytes > 0)
230 EncryptBytes(data + subsample.clear_bytes, subsample.cipher_bytes);
231 data += frame.frame_size;
234 const NaluReader::NaluType nalu_type =
235 (video_codec_ == kCodecHVC1 || video_codec_ == kCodecHEV1)
238 NaluReader reader(nalu_type, nalu_length_size_, data,
239 sample->data_size());
243 uint64_t accumulated_clear_bytes = 0;
246 NaluReader::Result result;
247 while ((result = reader.Advance(&nalu)) == NaluReader::kOk) {
248 if (nalu.is_video_slice()) {
252 const int64_t video_slice_header_size =
253 header_parser_ ? header_parser_->GetHeaderSize(nalu) : 0;
254 if (video_slice_header_size < 0)
255 return Status(error::MUXER_FAILURE,
"Failed to read slice header.");
257 const uint64_t current_clear_bytes = nalu.header_size() +
258 video_slice_header_size;
259 const uint64_t cipher_bytes =
260 nalu.payload_size() - video_slice_header_size;
261 const uint8_t* nalu_data = nalu.data() + current_clear_bytes;
262 EncryptBytes(const_cast<uint8_t*>(nalu_data), cipher_bytes);
265 accumulated_clear_bytes + nalu_length_size_ + current_clear_bytes,
266 cipher_bytes, &sample_encryption_entry.subsamples);
267 accumulated_clear_bytes = 0;
270 accumulated_clear_bytes +=
271 nalu_length_size_ + nalu.header_size() + nalu.payload_size();
274 if (result != NaluReader::kEOStream)
275 return Status(error::MUXER_FAILURE,
"Failed to parse NAL units.");
276 AddSubsamples(accumulated_clear_bytes, 0,
277 &sample_encryption_entry.subsamples);
281 traf()->auxiliary_size.sample_info_sizes.push_back(
282 sample_encryption_entry.ComputeSize());
284 EncryptBytes(data, sample->data_size());
287 traf()->sample_encryption.sample_encryption_entries.push_back(
288 sample_encryption_entry);
289 encryptor_->UpdateIv();
293 bool EncryptingFragmenter::IsSubsampleEncryptionRequired() {
294 return vpx_parser_ || nalu_length_size_ != 0;