5 #include <packager/media/formats/webm/webm_crypto_helpers.h>
7 #include <absl/base/internal/endian.h>
8 #include <absl/log/log.h>
10 #include <packager/macros/logging.h>
11 #include <packager/media/base/buffer_reader.h>
12 #include <packager/media/formats/webm/webm_constants.h>
22 std::vector<uint8_t> GenerateWebMCounterBlock(
const uint8_t* iv,
int iv_size) {
23 std::vector<uint8_t> counter_block(iv, iv + iv_size);
24 counter_block.insert(counter_block.end(),
32 bool WebMCreateDecryptConfig(
const uint8_t* data,
34 const uint8_t* key_id,
36 std::unique_ptr<DecryptConfig>* decrypt_config,
38 int header_size = kWebMSignalByteSize;
39 if (data_size < header_size) {
40 DVLOG(1) <<
"Empty WebM sample.";
43 uint8_t signal_byte = data[0];
45 if (signal_byte & kWebMEncryptedSignal) {
47 header_size += kWebMIvSize;
48 if (data_size < header_size) {
49 DVLOG(1) <<
"Encrypted WebM sample too small to hold IV: " << data_size;
52 std::vector<SubsampleEntry> subsamples;
53 if (signal_byte & kWebMPartitionedSignal) {
55 header_size += kWebMNumPartitionsSize;
56 if (data_size < header_size) {
58 <<
"Encrypted WebM sample too small to hold number of partitions: "
62 uint8_t num_partitions = data[kWebMSignalByteSize + kWebMIvSize];
63 BufferReader offsets_buffer(data + header_size, data_size - header_size);
64 header_size += num_partitions * kWebMPartitionOffsetSize;
65 uint32_t subsample_offset = 0;
66 bool encrypted_subsample =
false;
67 uint16_t clear_size = 0;
68 uint32_t encrypted_size = 0;
69 for (uint8_t partition_idx = 0; partition_idx < num_partitions;
71 uint32_t partition_offset;
72 if (!offsets_buffer.Read4(&partition_offset)) {
74 <<
"Encrypted WebM sample too small to hold partition offsets: "
78 if (partition_offset < subsample_offset) {
79 DVLOG(1) <<
"Partition offsets out of order.";
82 if (encrypted_subsample) {
83 encrypted_size = partition_offset - subsample_offset;
84 subsamples.push_back(SubsampleEntry(clear_size, encrypted_size));
86 clear_size = partition_offset - subsample_offset;
87 if (partition_idx == (num_partitions - 1)) {
88 encrypted_size = data_size - header_size - subsample_offset - clear_size;
89 subsamples.push_back(SubsampleEntry(clear_size, encrypted_size));
92 subsample_offset = partition_offset;
93 encrypted_subsample = !encrypted_subsample;
95 if (!(num_partitions % 2)) {
97 clear_size = data_size - header_size - subsample_offset;
99 subsamples.push_back(SubsampleEntry(clear_size, encrypted_size));
102 decrypt_config->reset(
new DecryptConfig(
103 std::vector<uint8_t>(key_id, key_id + key_id_size),
104 GenerateWebMCounterBlock(data + kWebMSignalByteSize, kWebMIvSize),
108 decrypt_config->reset();
111 *data_offset = header_size;
All the methods that are virtual are virtual for mocking.