7 #include "packager/media/formats/webm/encryptor.h"
9 #include "packager/media/base/buffer_writer.h"
10 #include "packager/media/base/media_sample.h"
11 #include "packager/media/formats/webm/webm_constants.h"
17 Status UpdateTrackForEncryption(
const std::vector<uint8_t>& key_id,
18 mkvmuxer::Track* track) {
19 DCHECK_EQ(track->content_encoding_entries_size(), 0u);
21 if (!track->AddContentEncoding()) {
22 return Status(error::INTERNAL_ERROR,
23 "Could not add ContentEncoding to track.");
26 mkvmuxer::ContentEncoding*
const encoding =
27 track->GetContentEncodingByIndex(0);
29 return Status(error::INTERNAL_ERROR,
30 "Could not add ContentEncoding to track.");
33 mkvmuxer::ContentEncAESSettings*
const aes = encoding->enc_aes_settings();
35 return Status(error::INTERNAL_ERROR,
36 "Error getting ContentEncAESSettings.");
38 if (aes->cipher_mode() != mkvmuxer::ContentEncAESSettings::kCTR) {
39 return Status(error::INTERNAL_ERROR,
"Cipher Mode is not CTR.");
42 if (!encoding->SetEncryptionID(key_id.data(), key_id.size())) {
43 return Status(error::INTERNAL_ERROR,
"Error setting encryption ID.");
48 void UpdateFrameForEncryption(MediaSample* sample) {
49 const size_t sample_size = sample->data_size();
50 if (sample->decrypt_config()) {
51 auto* decrypt_config = sample->decrypt_config();
52 const size_t iv_size = decrypt_config->iv().size();
53 DCHECK_EQ(iv_size, kWebMIvSize);
54 if (!decrypt_config->subsamples().empty()) {
55 auto& subsamples = decrypt_config->subsamples();
58 DCHECK_LT(subsamples.size(), kWebMMaxSubsamples);
59 const size_t num_partitions =
60 2 * subsamples.size() - 1 -
61 (subsamples.back().cipher_bytes == 0 ? 1 : 0);
62 const size_t header_size = kWebMSignalByteSize + iv_size +
63 kWebMNumPartitionsSize +
64 (kWebMPartitionOffsetSize * num_partitions);
65 sample->resize_data(header_size + sample_size);
66 uint8_t* sample_data = sample->writable_data();
67 memmove(sample_data + header_size, sample_data, sample_size);
68 sample_data[0] = kWebMEncryptedSignal | kWebMPartitionedSignal;
69 memcpy(sample_data + kWebMSignalByteSize, decrypt_config->iv().data(),
71 sample_data[kWebMSignalByteSize + kWebMIvSize] =
72 static_cast<uint8_t
>(num_partitions);
74 BufferWriter offsets_buffer;
75 uint32_t partition_offset = 0;
76 for (
size_t i = 0; i < subsamples.size() - 1; ++i) {
77 partition_offset += subsamples[i].clear_bytes;
78 offsets_buffer.AppendInt(partition_offset);
79 partition_offset += subsamples[i].cipher_bytes;
80 offsets_buffer.AppendInt(partition_offset);
84 if (subsamples.back().cipher_bytes != 0) {
85 partition_offset += subsamples.back().clear_bytes;
86 offsets_buffer.AppendInt(partition_offset);
88 DCHECK_EQ(num_partitions * kWebMPartitionOffsetSize,
89 offsets_buffer.Size());
90 memcpy(sample_data + kWebMSignalByteSize + kWebMIvSize +
91 kWebMNumPartitionsSize,
92 offsets_buffer.Buffer(), offsets_buffer.Size());
95 sample->resize_data(sample_size + iv_size + kWebMSignalByteSize);
96 uint8_t* sample_data = sample->writable_data();
100 memmove(sample_data + iv_size + kWebMSignalByteSize, sample_data,
102 sample_data[0] = kWebMEncryptedSignal;
103 memcpy(sample_data + 1, decrypt_config->iv().data(), iv_size);
107 sample->resize_data(sample_size + 1);
108 uint8_t* sample_data = sample->writable_data();
109 memmove(sample_data + 1, sample_data, sample_size);
110 sample_data[0] = 0x00;