Add support to output sub-sample encryption information.
See http://wiki.webmproject.org/encryption/webm-subsample-encryption for the format. Change-Id: Ia5d6f3566b92c46911704108d3e86cd0fac9ee34
This commit is contained in:
parent
26f434423f
commit
c97e3e7d60
@ -12,6 +12,29 @@
|
||||
|
||||
namespace {
|
||||
|
||||
// Swaps unsigned 32 bit values to big endian if needed. Returns |value|
|
||||
// unmodified if architecture is big endian. Returns swapped bytes of |value|
|
||||
// if architecture is little endian. Returns 0 otherwise.
|
||||
uint32_t swap32_check_little_endian(uint32_t value) {
|
||||
// Check endianness.
|
||||
union {
|
||||
uint32_t val32;
|
||||
uint8_t c[4];
|
||||
} check;
|
||||
check.val32 = 0x01234567U;
|
||||
|
||||
// Check for big endian.
|
||||
if (check.c[3] == 0x67)
|
||||
return value;
|
||||
|
||||
// Check for not little endian.
|
||||
if (check.c[0] != 0x67)
|
||||
return 0;
|
||||
|
||||
return value << 24 | ((value << 8) & 0x0000FF00U) |
|
||||
((value >> 8) & 0x00FF0000U) | value >> 24;
|
||||
}
|
||||
|
||||
// Swaps unsigned 64 bit values to big endian if needed. Returns |value|
|
||||
// unmodified if architecture is big endian. Returns swapped bytes of |value|
|
||||
// if architecture is little endian. Returns 0 otherwise.
|
||||
@ -43,6 +66,14 @@ uint64_t swap64_check_little_endian(uint64_t value) {
|
||||
|
||||
namespace libwebm {
|
||||
|
||||
uint32_t host_to_bigendian(uint32_t value) {
|
||||
return swap32_check_little_endian(value);
|
||||
}
|
||||
|
||||
uint32_t bigendian_to_host(uint32_t value) {
|
||||
return swap32_check_little_endian(value);
|
||||
}
|
||||
|
||||
uint64_t host_to_bigendian(uint64_t value) {
|
||||
return swap64_check_little_endian(value);
|
||||
}
|
||||
@ -51,4 +82,4 @@ uint64_t bigendian_to_host(uint64_t value) {
|
||||
return swap64_check_little_endian(value);
|
||||
}
|
||||
|
||||
} // namespace libwebm
|
||||
} // namespace libwebm
|
||||
|
@ -13,9 +13,19 @@
|
||||
|
||||
namespace libwebm {
|
||||
|
||||
// Swaps unsigned 64 bit values to big endian if needed. Returns |value| if
|
||||
// Swaps unsigned 32 bit values to big endian if needed. Returns |value| if
|
||||
// architecture is big endian. Returns big endian value if architecture is
|
||||
// little endian. Returns 0 otherwise.
|
||||
uint32_t host_to_bigendian(uint32_t value);
|
||||
|
||||
// Swaps unsigned 32 bit values to little endian if needed. Returns |value| if
|
||||
// architecture is big endian. Returns little endian value if architecture is
|
||||
// little endian. Returns 0 otherwise.
|
||||
uint32_t bigendian_to_host(uint32_t value);
|
||||
|
||||
// Swaps unsigned 64 bit values to big endian if needed. Returns |value| if
|
||||
// architecture is big endian. Returns big endian value if architecture is
|
||||
// little endian. Returns 0 otherwise.
|
||||
uint64_t host_to_bigendian(uint64_t value);
|
||||
|
||||
// Swaps unsigned 64 bit values to little endian if needed. Returns |value| if
|
||||
|
57
webm_info.cc
57
webm_info.cc
@ -788,6 +788,39 @@ void PrintVP8Info(const uint8_t* data, int size, FILE* o) {
|
||||
altref_frame, partition_length);
|
||||
}
|
||||
|
||||
// Prints the partition offsets of the sub-sample encryption. |data| must point
|
||||
// to an encrypted frame just after the signal byte. Returns the number of
|
||||
// bytes read from the sub-sample partition information.
|
||||
int PrintSubSampleEncryption(const uint8_t* data, int size, FILE* o) {
|
||||
int read_end = sizeof(uint64_t);
|
||||
|
||||
// Skip past IV.
|
||||
if (size < read_end)
|
||||
return 0;
|
||||
data += sizeof(uint64_t);
|
||||
|
||||
// Read number of partitions.
|
||||
read_end += sizeof(uint8_t);
|
||||
if (size < read_end)
|
||||
return 0;
|
||||
const int num_partitions = data[0];
|
||||
data += sizeof(uint8_t);
|
||||
|
||||
// Read partitions.
|
||||
for (int i = 0; i < num_partitions; ++i) {
|
||||
read_end += sizeof(uint32_t);
|
||||
if (size < read_end)
|
||||
return 0;
|
||||
uint32_t partition_offset;
|
||||
memcpy(&partition_offset, data, sizeof(partition_offset));
|
||||
partition_offset = libwebm::bigendian_to_host(partition_offset);
|
||||
fprintf(o, " off[%d]:%u", i, partition_offset);
|
||||
data += sizeof(uint32_t);
|
||||
}
|
||||
|
||||
return read_end;
|
||||
}
|
||||
|
||||
bool OutputCluster(const mkvparser::Cluster& cluster,
|
||||
const mkvparser::Tracks& tracks, const Options& options,
|
||||
FILE* o, mkvparser::MkvReader* reader, Indent* indent,
|
||||
@ -883,6 +916,7 @@ bool OutputCluster(const mkvparser::Cluster& cluster,
|
||||
fprintf(o, " size_payload: %lld", block->m_size);
|
||||
|
||||
const uint8_t KEncryptedBit = 0x1;
|
||||
const uint8_t kSubSampleBit = 0x2;
|
||||
const int kSignalByteSize = 1;
|
||||
bool encrypted_stream = false;
|
||||
if (options.output_encrypted_info) {
|
||||
@ -917,8 +951,10 @@ bool OutputCluster(const mkvparser::Cluster& cluster,
|
||||
return false;
|
||||
}
|
||||
|
||||
const bool encrypted_frame = (data[0] & KEncryptedBit) ? 1 : 0;
|
||||
const bool encrypted_frame = !!(data[0] & KEncryptedBit);
|
||||
const bool sub_sample_encrypt = !!(data[0] & kSubSampleBit);
|
||||
fprintf(o, " enc: %d", encrypted_frame ? 1 : 0);
|
||||
fprintf(o, " sub: %d", sub_sample_encrypt ? 1 : 0);
|
||||
|
||||
if (encrypted_frame) {
|
||||
uint64_t iv;
|
||||
@ -953,24 +989,35 @@ bool OutputCluster(const mkvparser::Cluster& cluster,
|
||||
fprintf(o, "\n%sVP8 data :", indent->indent_str().c_str());
|
||||
|
||||
bool encrypted_frame = false;
|
||||
bool sub_sample_encrypt = false;
|
||||
int frame_size = static_cast<int>(frame.len);
|
||||
|
||||
int frame_offset = 0;
|
||||
if (encrypted_stream) {
|
||||
if (data[0] & KEncryptedBit) {
|
||||
encrypted_frame = true;
|
||||
if (data[0] & kSubSampleBit) {
|
||||
sub_sample_encrypt = true;
|
||||
data += kSignalByteSize;
|
||||
frame_size -= kSignalByteSize;
|
||||
frame_offset =
|
||||
PrintSubSampleEncryption(data, frame_size, o);
|
||||
}
|
||||
} else {
|
||||
frame_offset = kSignalByteSize;
|
||||
}
|
||||
}
|
||||
|
||||
if (!encrypted_frame) {
|
||||
if (!encrypted_frame || sub_sample_encrypt) {
|
||||
data += frame_offset;
|
||||
frame_size -= frame_offset;
|
||||
|
||||
const string codec_id = track->GetCodecId();
|
||||
if (codec_id == "V_VP8") {
|
||||
PrintVP8Info(data, static_cast<int>(frame.len), o);
|
||||
PrintVP8Info(data, frame_size, o);
|
||||
} else if (codec_id == "V_VP9") {
|
||||
PrintVP9Info(data, static_cast<int>(frame.len), o, time_ns,
|
||||
stats, parser, level_stats);
|
||||
PrintVP9Info(data, frame_size, o, time_ns, stats, parser,
|
||||
level_stats);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user