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 void WriteEncryptedFrameHeader(
const DecryptConfig* decrypt_config,
18 BufferWriter* header_buffer) {
20 const size_t iv_size = decrypt_config->iv().size();
21 DCHECK_EQ(iv_size, kWebMIvSize);
22 if (!decrypt_config->subsamples().empty()) {
23 const auto& subsamples = decrypt_config->subsamples();
26 DCHECK_LT(subsamples.size(), kWebMMaxSubsamples);
27 const size_t num_partitions =
28 2 * subsamples.size() - 1 -
29 (subsamples.back().cipher_bytes == 0 ? 1 : 0);
30 const size_t header_size = kWebMSignalByteSize + iv_size +
31 kWebMNumPartitionsSize +
32 (kWebMPartitionOffsetSize * num_partitions);
34 const uint8_t signal_byte = kWebMEncryptedSignal | kWebMPartitionedSignal;
35 header_buffer->AppendInt(signal_byte);
36 header_buffer->AppendVector(decrypt_config->iv());
37 header_buffer->AppendInt(static_cast<uint8_t>(num_partitions));
39 uint32_t partition_offset = 0;
40 for (
size_t i = 0; i < subsamples.size() - 1; ++i) {
41 partition_offset += subsamples[i].clear_bytes;
42 header_buffer->AppendInt(partition_offset);
43 partition_offset += subsamples[i].cipher_bytes;
44 header_buffer->AppendInt(partition_offset);
48 if (subsamples.back().cipher_bytes != 0) {
49 partition_offset += subsamples.back().clear_bytes;
50 header_buffer->AppendInt(partition_offset);
53 DCHECK_EQ(header_size, header_buffer->Size());
56 const uint8_t signal_byte = kWebMEncryptedSignal;
57 header_buffer->AppendInt(signal_byte);
58 header_buffer->AppendVector(decrypt_config->iv());
62 const uint8_t signal_byte = 0x00;
63 header_buffer->AppendInt(signal_byte);
68 Status UpdateTrackForEncryption(
const std::vector<uint8_t>& key_id,
69 mkvmuxer::Track* track) {
70 DCHECK_EQ(track->content_encoding_entries_size(), 0u);
72 if (!track->AddContentEncoding()) {
73 return Status(error::INTERNAL_ERROR,
74 "Could not add ContentEncoding to track.");
77 mkvmuxer::ContentEncoding*
const encoding =
78 track->GetContentEncodingByIndex(0);
80 return Status(error::INTERNAL_ERROR,
81 "Could not add ContentEncoding to track.");
84 mkvmuxer::ContentEncAESSettings*
const aes = encoding->enc_aes_settings();
86 return Status(error::INTERNAL_ERROR,
87 "Error getting ContentEncAESSettings.");
89 if (aes->cipher_mode() != mkvmuxer::ContentEncAESSettings::kCTR) {
90 return Status(error::INTERNAL_ERROR,
"Cipher Mode is not CTR.");
93 if (!encoding->SetEncryptionID(key_id.data(), key_id.size())) {
94 return Status(error::INTERNAL_ERROR,
"Error setting encryption ID.");
99 void UpdateFrameForEncryption(MediaSample* sample) {
101 BufferWriter header_buffer;
102 WriteEncryptedFrameHeader(sample->decrypt_config(), &header_buffer);
104 const size_t sample_size = header_buffer.Size() + sample->data_size();
105 std::shared_ptr<uint8_t> new_sample_data(
new uint8_t[sample_size],
106 std::default_delete<uint8_t[]>());
107 memcpy(new_sample_data.get(), header_buffer.Buffer(), header_buffer.Size());
108 memcpy(&new_sample_data.get()[header_buffer.Size()], sample->data(),
109 sample->data_size());
110 sample->TransferData(std::move(new_sample_data), sample_size);
All the methods that are virtual are virtual for mocking.