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"
16 #include "packager/media/formats/mp4/cenc.h"
20 const size_t kDefaultIvSize = 8u;
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();
71 const bool enable_encryption = clear_time_ <= 0;
72 if (!enable_encryption) {
76 const uint32_t kClearSampleDescriptionIndex = 2;
78 traf()->header.flags |=
79 TrackFragmentHeader::kSampleDescriptionIndexPresentMask;
80 traf()->header.sample_description_index = kClearSampleDescriptionIndex;
87 DCHECK_LE(clear_time_, 0);
90 DCHECK_GT(clear_time_, 0);
91 clear_time_ -= fragment_duration();
97 bool enable_encryption) {
98 return (!enable_encryption || encryptor_) ? Status::OK :
CreateEncryptor();
103 traf()->auxiliary_offset.offsets.push_back(0);
107 saiz.sample_count = traf()->runs[0].sample_sizes.size();
108 if (!saiz.sample_info_sizes.empty()) {
110 &saiz.default_sample_info_size)) {
111 saiz.default_sample_info_size = 0;
116 DCHECK(!IsSubsampleEncryptionRequired());
117 saiz.default_sample_info_size = encryptor_->iv().size();
122 DCHECK(encryption_key_);
125 const bool initialized = encryption_key_->iv.empty()
126 ? encryptor->InitializeWithRandomIv(
127 encryption_key_->key, kDefaultIvSize)
128 : encryptor->InitializeWithIv(
129 encryption_key_->key, encryption_key_->iv);
131 return Status(error::MUXER_FAILURE,
"Failed to create the encryptor.");
132 encryptor_ = encryptor.Pass();
136 void EncryptingFragmenter::EncryptBytes(uint8_t* data, uint32_t size) {
138 CHECK(encryptor_->Encrypt(data, size, data));
141 Status EncryptingFragmenter::EncryptSample(scoped_refptr<MediaSample> sample) {
144 FrameCENCInfo cenc_info(encryptor_->iv());
145 uint8_t* data = sample->writable_data();
146 if (IsSubsampleEncryptionRequired()) {
148 std::vector<VPxFrameInfo> vpx_frames;
149 if (!vpx_parser_->Parse(sample->data(), sample->data_size(),
151 return Status(error::MUXER_FAILURE,
"Failed to parse vpx frame.");
153 for (
const VPxFrameInfo& frame : vpx_frames) {
154 SubsampleEntry subsample;
155 subsample.clear_bytes = frame.uncompressed_header_size;
156 subsample.cipher_bytes =
157 frame.frame_size - frame.uncompressed_header_size;
158 cenc_info.AddSubsample(subsample);
159 if (subsample.cipher_bytes > 0)
160 EncryptBytes(data + subsample.clear_bytes, subsample.cipher_bytes);
161 data += frame.frame_size;
164 BufferReader reader(data, sample->data_size());
165 while (reader.HasBytes(1)) {
166 uint64_t nalu_length;
167 if (!reader.ReadNBytesInto8(&nalu_length, nalu_length_size_))
168 return Status(error::MUXER_FAILURE,
"Fail to read nalu_length.");
170 SubsampleEntry subsample;
171 subsample.clear_bytes = nalu_length_size_ + 1;
172 subsample.cipher_bytes = nalu_length - 1;
173 if (!reader.SkipBytes(nalu_length)) {
174 return Status(error::MUXER_FAILURE,
175 "Sample size does not match nalu_length.");
178 EncryptBytes(data + subsample.clear_bytes, subsample.cipher_bytes);
179 cenc_info.AddSubsample(subsample);
180 data += nalu_length_size_ + nalu_length;
185 traf()->auxiliary_size.sample_info_sizes.push_back(cenc_info.ComputeSize());
187 EncryptBytes(data, sample->data_size());
190 cenc_info.Write(aux_data());
191 encryptor_->UpdateIv();