7 #include "packager/media/formats/mp4/encrypting_fragmenter.h"
9 #include "packager/media/base/aes_encryptor.h"
10 #include "packager/media/base/buffer_reader.h"
11 #include "packager/media/base/key_source.h"
12 #include "packager/media/base/media_sample.h"
13 #include "packager/media/filters/vp8_parser.h"
14 #include "packager/media/filters/vp9_parser.h"
15 #include "packager/media/formats/mp4/box_definitions.h"
19 const size_t kDefaultIvSize = 8u;
20 const size_t kCencBlockSize = 16u;
23 namespace edash_packager {
29 scoped_ptr<EncryptionKey> encryption_key,
31 VideoCodec video_codec,
32 uint8_t nalu_length_size)
34 encryption_key_(encryption_key.Pass()),
35 video_codec_(video_codec),
36 nalu_length_size_(nalu_length_size),
37 clear_time_(clear_time) {
38 DCHECK(encryption_key_);
39 if (video_codec == kCodecVP8) {
41 }
else if (video_codec == kCodecVP9) {
46 EncryptingFragmenter::~EncryptingFragmenter() {}
50 if (!fragment_initialized()) {
56 Status status = EncryptSample(sample);
68 traf()->auxiliary_size.sample_info_sizes.clear();
69 traf()->auxiliary_offset.offsets.clear();
70 if (IsSubsampleEncryptionRequired()) {
71 traf()->sample_encryption.flags |=
72 SampleEncryption::kUseSubsampleEncryption;
74 traf()->sample_encryption.sample_encryption_entries.clear();
76 const bool enable_encryption = clear_time_ <= 0;
77 if (!enable_encryption) {
81 const uint32_t kClearSampleDescriptionIndex = 2;
83 traf()->header.flags |=
84 TrackFragmentHeader::kSampleDescriptionIndexPresentMask;
85 traf()->header.sample_description_index = kClearSampleDescriptionIndex;
92 DCHECK_LE(clear_time_, 0);
95 DCHECK_GT(clear_time_, 0);
96 clear_time_ -= fragment_duration();
102 bool enable_encryption) {
103 return (!enable_encryption || encryptor_) ? Status::OK :
CreateEncryptor();
108 traf()->auxiliary_offset.offsets.push_back(0);
112 saiz.sample_count = traf()->runs[0].sample_sizes.size();
113 if (!saiz.sample_info_sizes.empty()) {
115 &saiz.default_sample_info_size)) {
116 saiz.default_sample_info_size = 0;
121 DCHECK(!IsSubsampleEncryptionRequired());
122 saiz.default_sample_info_size = encryptor_->iv().size();
124 traf()->sample_encryption.iv_size = encryptor_->iv().size();
128 DCHECK(encryption_key_);
131 const bool initialized = encryption_key_->iv.empty()
132 ? encryptor->InitializeWithRandomIv(
133 encryption_key_->key, kDefaultIvSize)
134 : encryptor->InitializeWithIv(
135 encryption_key_->key, encryption_key_->iv);
137 return Status(error::MUXER_FAILURE,
"Failed to create the encryptor.");
138 encryptor_ = encryptor.Pass();
142 void EncryptingFragmenter::EncryptBytes(uint8_t* data, uint32_t size) {
144 CHECK(encryptor_->Encrypt(data, size, data));
147 Status EncryptingFragmenter::EncryptSample(scoped_refptr<MediaSample> sample) {
150 SampleEncryptionEntry sample_encryption_entry;
151 sample_encryption_entry.initialization_vector = encryptor_->iv();
152 uint8_t* data = sample->writable_data();
153 if (IsSubsampleEncryptionRequired()) {
155 std::vector<VPxFrameInfo> vpx_frames;
156 if (!vpx_parser_->Parse(sample->data(), sample->data_size(),
158 return Status(error::MUXER_FAILURE,
"Failed to parse vpx frame.");
161 const bool is_superframe = vpx_frames.size() > 1;
162 for (
const VPxFrameInfo& frame : vpx_frames) {
163 SubsampleEntry subsample;
164 subsample.clear_bytes = frame.uncompressed_header_size;
165 subsample.cipher_bytes =
166 frame.frame_size - frame.uncompressed_header_size;
173 uint16_t misalign_bytes = subsample.cipher_bytes % kCencBlockSize;
174 subsample.clear_bytes += misalign_bytes;
175 subsample.cipher_bytes -= misalign_bytes;
178 sample_encryption_entry.subsamples.push_back(subsample);
179 if (subsample.cipher_bytes > 0)
180 EncryptBytes(data + subsample.clear_bytes, subsample.cipher_bytes);
181 data += frame.frame_size;
184 BufferReader reader(data, sample->data_size());
185 while (reader.HasBytes(1)) {
186 uint64_t nalu_length;
187 if (!reader.ReadNBytesInto8(&nalu_length, nalu_length_size_))
188 return Status(error::MUXER_FAILURE,
"Fail to read nalu_length.");
190 if (!reader.SkipBytes(nalu_length)) {
191 return Status(error::MUXER_FAILURE,
192 "Sample size does not match nalu_length.");
195 SubsampleEntry subsample;
196 subsample.clear_bytes = nalu_length_size_ + 1;
197 subsample.cipher_bytes = nalu_length - 1;
198 sample_encryption_entry.subsamples.push_back(subsample);
200 EncryptBytes(data + subsample.clear_bytes, subsample.cipher_bytes);
201 data += nalu_length_size_ + nalu_length;
206 traf()->auxiliary_size.sample_info_sizes.push_back(
207 sample_encryption_entry.ComputeSize());
209 EncryptBytes(data, sample->data_size());
212 traf()->sample_encryption.sample_encryption_entries.push_back(
213 sample_encryption_entry);
214 encryptor_->UpdateIv();