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/nalu_reader.h"
14 #include "packager/media/filters/vp8_parser.h"
15 #include "packager/media/filters/vp9_parser.h"
16 #include "packager/media/formats/mp4/box_definitions.h"
20 const size_t kDefaultIvSize = 8u;
21 const size_t kCencBlockSize = 16u;
24 namespace edash_packager {
30 scoped_ptr<EncryptionKey> encryption_key,
32 VideoCodec video_codec,
33 uint8_t nalu_length_size)
35 encryption_key_(encryption_key.Pass()),
36 video_codec_(video_codec),
37 nalu_length_size_(nalu_length_size),
38 clear_time_(clear_time) {
39 DCHECK(encryption_key_);
40 if (video_codec == kCodecVP8) {
42 }
else if (video_codec == kCodecVP9) {
47 EncryptingFragmenter::~EncryptingFragmenter() {}
51 if (!fragment_initialized()) {
57 Status status = EncryptSample(sample);
69 traf()->auxiliary_size.sample_info_sizes.clear();
70 traf()->auxiliary_offset.offsets.clear();
71 if (IsSubsampleEncryptionRequired()) {
72 traf()->sample_encryption.flags |=
73 SampleEncryption::kUseSubsampleEncryption;
75 traf()->sample_encryption.sample_encryption_entries.clear();
77 const bool enable_encryption = clear_time_ <= 0;
78 if (!enable_encryption) {
82 const uint32_t kClearSampleDescriptionIndex = 2;
84 traf()->header.flags |=
85 TrackFragmentHeader::kSampleDescriptionIndexPresentMask;
86 traf()->header.sample_description_index = kClearSampleDescriptionIndex;
93 DCHECK_LE(clear_time_, 0);
96 DCHECK_GT(clear_time_, 0);
97 clear_time_ -= fragment_duration();
103 bool enable_encryption) {
104 return (!enable_encryption || encryptor_) ? Status::OK :
CreateEncryptor();
109 traf()->auxiliary_offset.offsets.push_back(0);
113 saiz.sample_count = traf()->runs[0].sample_sizes.size();
114 if (!saiz.sample_info_sizes.empty()) {
116 &saiz.default_sample_info_size)) {
117 saiz.default_sample_info_size = 0;
122 DCHECK(!IsSubsampleEncryptionRequired());
123 saiz.default_sample_info_size = encryptor_->iv().size();
125 traf()->sample_encryption.iv_size = encryptor_->iv().size();
129 DCHECK(encryption_key_);
132 const bool initialized = encryption_key_->iv.empty()
133 ? encryptor->InitializeWithRandomIv(
134 encryption_key_->key, kDefaultIvSize)
135 : encryptor->InitializeWithIv(
136 encryption_key_->key, encryption_key_->iv);
138 return Status(error::MUXER_FAILURE,
"Failed to create the encryptor.");
139 encryptor_ = encryptor.Pass();
143 void EncryptingFragmenter::EncryptBytes(uint8_t* data, uint32_t size) {
145 CHECK(encryptor_->Encrypt(data, size, data));
148 Status EncryptingFragmenter::EncryptSample(scoped_refptr<MediaSample> sample) {
151 SampleEncryptionEntry sample_encryption_entry;
152 sample_encryption_entry.initialization_vector = encryptor_->iv();
153 uint8_t* data = sample->writable_data();
154 if (IsSubsampleEncryptionRequired()) {
156 std::vector<VPxFrameInfo> vpx_frames;
157 if (!vpx_parser_->Parse(sample->data(), sample->data_size(),
159 return Status(error::MUXER_FAILURE,
"Failed to parse vpx frame.");
162 const bool is_superframe = vpx_frames.size() > 1;
163 for (
const VPxFrameInfo& frame : vpx_frames) {
164 SubsampleEntry subsample;
165 subsample.clear_bytes = frame.uncompressed_header_size;
166 subsample.cipher_bytes =
167 frame.frame_size - frame.uncompressed_header_size;
174 uint16_t misalign_bytes = subsample.cipher_bytes % kCencBlockSize;
175 subsample.clear_bytes += misalign_bytes;
176 subsample.cipher_bytes -= misalign_bytes;
179 sample_encryption_entry.subsamples.push_back(subsample);
180 if (subsample.cipher_bytes > 0)
181 EncryptBytes(data + subsample.clear_bytes, subsample.cipher_bytes);
182 data += frame.frame_size;
185 NaluReader reader(nalu_length_size_, data, sample->data_size());
188 NaluReader::Result result;
189 while ((result = reader.Advance(&nalu)) == NaluReader::kOk) {
190 SubsampleEntry subsample;
191 subsample.clear_bytes = nalu.header_size();
192 subsample.cipher_bytes = nalu.data_size();
193 sample_encryption_entry.subsamples.push_back(subsample);
195 EncryptBytes(const_cast<uint8_t*>(nalu.data() + nalu.header_size()),
196 subsample.cipher_bytes);
198 if (result != NaluReader::kEOStream)
199 return Status(error::MUXER_FAILURE,
"Failed to parse NAL units.");
203 traf()->auxiliary_size.sample_info_sizes.push_back(
204 sample_encryption_entry.ComputeSize());
206 EncryptBytes(data, sample->data_size());
209 traf()->sample_encryption.sample_encryption_entries.push_back(
210 sample_encryption_entry);
211 encryptor_->UpdateIv();