Add CTR encryption.

- Added ContentEncAESSettings, AESSettingsCipherMode,
  AESSettingsCipherInitData elements to the parser and muxer.
- Changed ParseContentEncodingsEntry, ParseContentEncodingEntry,
  and ParseEncryptionEntry to use PasreElementHeader.
- Added ParseContentEncAESSettingsEntry function.
- PS6 removed AESSettingsCipherInitData.
- PS9 Addressed comments, Fixed some LINT issues, and converted
  mkvwriter.h/.cpp to Unix line endings.
- PS10 Addressed comments.

Change-Id: I9d96a0c194f74a6c9bf0001aa0286196e410f07e
This commit is contained in:
Frank Galligan 2012-04-18 15:32:53 -04:00
parent c4d2b27b7a
commit a320f5be63
10 changed files with 585 additions and 396 deletions

View File

@ -77,7 +77,8 @@ Frame::~Frame() {
}
bool Frame::Init(const uint8* frame, uint64 length) {
uint8* const data = new (std::nothrow) uint8[static_cast<size_t>(length)];
uint8* const data =
new (std::nothrow) uint8[static_cast<size_t>(length)]; // NOLINT
if (!data)
return false;
@ -198,7 +199,8 @@ bool Cues::AddCue(CuePoint* cue) {
if (new_capacity < 1)
return false;
CuePoint** const cues = new (std::nothrow) CuePoint*[new_capacity];
CuePoint** const cues =
new (std::nothrow) CuePoint*[new_capacity]; // NOLINT
if (!cues)
return false;
@ -265,6 +267,45 @@ bool Cues::Write(IMkvWriter* writer) const {
return true;
}
///////////////////////////////////////////////////////////////
//
// ContentEncAESSettings Class
ContentEncAESSettings::ContentEncAESSettings() : cipher_mode_(kCTR) {}
uint64 ContentEncAESSettings::Size() const {
const uint64 payload = PayloadSize();
const uint64 size =
EbmlMasterElementSize(kMkvContentEncAESSettings, payload) + payload;
return size;
}
bool ContentEncAESSettings::Write(IMkvWriter* writer) const {
const uint64 payload = PayloadSize();
if (!WriteEbmlMasterElement(writer, kMkvContentEncAESSettings, payload))
return false;
const int64 payload_position = writer->Position();
if (payload_position < 0)
return false;
if (!WriteEbmlElement(writer, kMkvAESSettingsCipherMode, cipher_mode_))
return false;
const int64 stop_position = writer->Position();
if (stop_position < 0 ||
stop_position - payload_position != static_cast<int64>(payload))
return false;
return true;
}
uint64 ContentEncAESSettings::PayloadSize() const {
uint64 size = EbmlElementSize(kMkvAESSettingsCipherMode, cipher_mode_);
return size;
}
///////////////////////////////////////////////////////////////
//
// ContentEncoding Class
@ -288,7 +329,8 @@ bool ContentEncoding::SetEncryptionID(const uint8* id, uint64 length) {
delete [] enc_key_id_;
enc_key_id_ = new (std::nothrow) uint8[static_cast<size_t>(length)];
enc_key_id_ =
new (std::nothrow) uint8[static_cast<size_t>(length)]; // NOLINT
if (!enc_key_id_)
return false;
@ -338,6 +380,9 @@ bool ContentEncoding::Write(IMkvWriter* writer) const {
enc_key_id_length_))
return false;
if (!enc_aes_settings_.Write(writer))
return false;
const int64 stop_position = writer->Position();
if (stop_position < 0 ||
stop_position - payload_position != static_cast<int64>(size))
@ -367,12 +412,14 @@ uint64 ContentEncoding::EncodingSize(uint64 compresion_size,
}
uint64 ContentEncoding::EncryptionSize() const {
const uint64 aes_size = enc_aes_settings_.Size();
uint64 encryption_size = EbmlElementSize(kMkvContentEncKeyID,
enc_key_id_,
enc_key_id_length_);
encryption_size += EbmlElementSize(kMkvContentEncAlgo, enc_algo_);
return encryption_size;
return encryption_size + aes_size;
}
///////////////////////////////////////////////////////////////
@ -411,12 +458,12 @@ bool Track::AddContentEncoding() {
const uint32 count = content_encoding_entries_size_ + 1;
ContentEncoding** const content_encoding_entries =
new (std::nothrow) ContentEncoding*[count];
new (std::nothrow) ContentEncoding*[count]; // NOLINT
if (!content_encoding_entries)
return false;
ContentEncoding* const content_encoding =
new (std::nothrow) ContentEncoding();
new (std::nothrow) ContentEncoding(); // NOLINT
if (!content_encoding) {
delete [] content_encoding_entries;
return false;
@ -572,7 +619,7 @@ bool Track::SetCodecPrivate(const uint8* codec_private, uint64 length) {
delete [] codec_private_;
codec_private_ =
new (std::nothrow) uint8[static_cast<size_t>(length)];
new (std::nothrow) uint8[static_cast<size_t>(length)]; // NOLINT
if (!codec_private_)
return false;
@ -587,7 +634,7 @@ void Track::set_codec_id(const char* codec_id) {
delete [] codec_id_;
const size_t length = strlen(codec_id) + 1;
codec_id_ = new (std::nothrow) char[length];
codec_id_ = new (std::nothrow) char[length]; // NOLINT
if (codec_id_) {
#ifdef _MSC_VER
strcpy_s(codec_id_, length, codec_id);
@ -604,7 +651,7 @@ void Track::set_language(const char* language) {
delete [] language_;
const size_t length = strlen(language) + 1;
language_ = new (std::nothrow) char[length];
language_ = new (std::nothrow) char[length]; // NOLINT
if (language_) {
#ifdef _MSC_VER
strcpy_s(language_, length, language);
@ -620,7 +667,7 @@ void Track::set_name(const char* name) {
delete [] name_;
const size_t length = strlen(name) + 1;
name_ = new (std::nothrow) char[length];
name_ = new (std::nothrow) char[length]; // NOLINT
if (name_) {
#ifdef _MSC_VER
strcpy_s(name_, length, name);
@ -842,7 +889,7 @@ bool Tracks::AddTrack(Track* track, int32 number) {
const uint32 count = track_entries_size_ + 1;
Track** const track_entries = new (std::nothrow) Track*[count];
Track** const track_entries = new (std::nothrow) Track*[count]; // NOLINT
if (!track_entries)
return false;
@ -977,7 +1024,7 @@ bool Cluster::Init(IMkvWriter* ptr_writer) {
bool Cluster::AddFrame(const uint8* frame,
uint64 length,
uint64 track_number,
short timecode,
int16 timecode,
bool is_key) {
if (finalized_)
return false;
@ -1191,7 +1238,7 @@ bool SegmentInfo::Init() {
int32 minor;
int32 build;
int32 revision;
GetVersion(major, minor, build, revision);
GetVersion(&major, &minor, &build, &revision);
char temp[256];
#ifdef _MSC_VER
sprintf_s(temp,
@ -1215,7 +1262,7 @@ bool SegmentInfo::Init() {
delete [] muxing_app_;
muxing_app_ = new (std::nothrow) char[app_len];
muxing_app_ = new (std::nothrow) char[app_len]; // NOLINT
if (!muxing_app_)
return false;
@ -1304,7 +1351,7 @@ void SegmentInfo::set_writing_app(const char* app) {
delete [] writing_app_;
const size_t length = strlen(app) + 1;
writing_app_ = new (std::nothrow) char[length];
writing_app_ = new (std::nothrow) char[length]; // NOLINT
if (writing_app_) {
#ifdef _MSC_VER
strcpy_s(writing_app_, length, app);
@ -1483,7 +1530,7 @@ uint64 Segment::AddVideoTrack(int32 width, int32 height) {
}
uint64 Segment::AddVideoTrack(int32 width, int32 height, int32 number) {
VideoTrack* const vid_track = new (std::nothrow) VideoTrack();
VideoTrack* const vid_track = new (std::nothrow) VideoTrack(); // NOLINT
if (!vid_track)
return 0;
@ -1505,7 +1552,7 @@ uint64 Segment::AddAudioTrack(int32 sample_rate, int32 channels) {
uint64 Segment::AddAudioTrack(int32 sample_rate,
int32 channels,
int32 number) {
AudioTrack* const aud_track = new (std::nothrow) AudioTrack();
AudioTrack* const aud_track = new (std::nothrow) AudioTrack(); // NOLINT
if (!aud_track)
return 0;
@ -1584,7 +1631,8 @@ bool Segment::AddFrame(const uint8* frame,
if (new_capacity < 1)
return false;
Cluster** const clusters = new (std::nothrow) Cluster*[new_capacity];
Cluster** const clusters =
new (std::nothrow) Cluster*[new_capacity]; // NOLINT
if (!clusters)
return false;
@ -1636,7 +1684,7 @@ bool Segment::AddFrame(const uint8* frame,
}
cluster_list_[cluster_list_size_] =
new (std::nothrow) Cluster(timecode, MaxOffset());
new (std::nothrow) Cluster(timecode, MaxOffset()); // NOLINT
if (!cluster_list_[cluster_list_size_])
return false;
@ -1676,7 +1724,7 @@ bool Segment::AddFrame(const uint8* frame,
if (!cluster->AddFrame(frame,
length,
track_number,
static_cast<short>(block_timecode),
static_cast<int16>(block_timecode),
is_key))
return false;
@ -1703,7 +1751,7 @@ bool Segment::SetChunking(bool chunking, const char* filename) {
return true;
const size_t name_length = strlen(filename) + 1;
char* const temp = new (std::nothrow) char[name_length];
char* const temp = new (std::nothrow) char[name_length]; // NOLINT
if (!temp)
return false;
@ -1720,19 +1768,19 @@ bool Segment::SetChunking(bool chunking, const char* filename) {
return false;
if (!chunk_writer_cluster_) {
chunk_writer_cluster_ = new (std::nothrow) MkvWriter();
chunk_writer_cluster_ = new (std::nothrow) MkvWriter(); // NOLINT
if (!chunk_writer_cluster_)
return false;
}
if (!chunk_writer_cues_) {
chunk_writer_cues_ = new (std::nothrow) MkvWriter();
chunk_writer_cues_ = new (std::nothrow) MkvWriter(); // NOLINT
if (!chunk_writer_cues_)
return false;
}
if (!chunk_writer_header_) {
chunk_writer_header_ = new (std::nothrow) MkvWriter();
chunk_writer_header_ = new (std::nothrow) MkvWriter(); // NOLINT
if (!chunk_writer_header_)
return false;
}
@ -1741,7 +1789,7 @@ bool Segment::SetChunking(bool chunking, const char* filename) {
return false;
const size_t header_length = strlen(filename) + strlen(".hdr") + 1;
char* const header = new (std::nothrow) char[header_length];
char* const header = new (std::nothrow) char[header_length]; // NOLINT
if (!header)
return false;
@ -1877,7 +1925,7 @@ bool Segment::AddCuePoint(uint64 timestamp) {
if (!cluster)
return false;
CuePoint* const cue = new (std::nothrow) CuePoint();
CuePoint* const cue = new (std::nothrow) CuePoint(); // NOLINT
if (!cue)
return false;
@ -1898,13 +1946,13 @@ bool Segment::UpdateChunkName(const char* ext, char** name) const {
char ext_chk[64];
#ifdef _MSC_VER
sprintf_s(ext_chk, 64, "_%06d.%s", chunk_count_, ext);
sprintf_s(ext_chk, sizeof(ext_chk), "_%06d.%s", chunk_count_, ext);
#else
snprintf(ext_chk, 64, "_%06d.%s", chunk_count_, ext);
snprintf(ext_chk, sizeof(ext_chk), "_%06d.%s", chunk_count_, ext);
#endif
const size_t length = strlen(chunking_base_name_) + strlen(ext_chk) + 1;
char* const str = new (std::nothrow) char[length];
char* const str = new (std::nothrow) char[length]; // NOLINT
if (!str)
return false;
@ -1951,7 +1999,7 @@ bool Segment::QueueFrame(Frame* frame) {
if (new_capacity < 1)
return false;
Frame** const frames = new (std::nothrow) Frame*[new_capacity];
Frame** const frames = new (std::nothrow) Frame*[new_capacity]; // NOLINT
if (!frames)
return false;
@ -1997,7 +2045,7 @@ bool Segment::WriteFramesAll() {
if (!cluster->AddFrame(frame->frame(),
frame->length(),
frame->track_number(),
static_cast<short>(block_timecode),
static_cast<int16>(block_timecode),
frame->is_key()))
return false;
@ -2053,7 +2101,7 @@ bool Segment::WriteFramesLessThan(uint64 timestamp) {
if (!cluster->AddFrame(frame_prev->frame(),
frame_prev->length(),
frame_prev->track_number(),
static_cast<short>(block_timecode),
static_cast<int16>(block_timecode),
frame_prev->is_key()))
return false;

View File

@ -1,4 +1,4 @@
// Copyright (c) 2011 The WebM project authors. All Rights Reserved.
// Copyright (c) 2012 The WebM project authors. All Rights Reserved.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the LICENSE file in the root of the source
@ -179,23 +179,49 @@ class Cues {
LIBWEBM_DISALLOW_COPY_AND_ASSIGN(Cues);
};
///////////////////////////////////////////////////////////////
// ContentEncAESSettings element
class ContentEncAESSettings {
public:
enum {
kCTR = 1
};
ContentEncAESSettings();
~ContentEncAESSettings() {}
// Returns the size in bytes for the ContentEncAESSettings element.
uint64 Size() const;
// Writes out the ContentEncAESSettings element to |writer|. Returns true on
// success.
bool Write(IMkvWriter* writer) const;
uint64 cipher_mode() const { return cipher_mode_; }
private:
// Returns the size in bytes for the payload of the ContentEncAESSettings
// element.
uint64 PayloadSize() const;
// Sub elements
uint64 cipher_mode_;
LIBWEBM_DISALLOW_COPY_AND_ASSIGN(ContentEncAESSettings);
};
///////////////////////////////////////////////////////////////
// ContentEncoding element
// Elements used to describe if the track data has been encrypted or
// compressed with zlib or header stripping.
// Currently only whole frames can only be encrypted once with AES. This
// dictates that ContentEncodingOrder will be 0, ContentEncodingScope will
// be 1, ContentEncodingType will be 1, and ContentEncAlgo will be 5.
// Currently only whole frames can be encrypted with AES. This dictates that
// ContentEncodingOrder will be 0, ContentEncodingScope will be 1,
// ContentEncodingType will be 1, and ContentEncAlgo will be 5.
class ContentEncoding {
public:
ContentEncoding();
~ContentEncoding();
uint64 enc_algo() const { return enc_algo_; }
uint64 encoding_order() const { return encoding_order_; }
uint64 encoding_scope() const { return encoding_scope_; }
uint64 encoding_type() const { return encoding_type_; }
// Sets the content encryption id. Copies |length| bytes from |id| to
// |enc_key_id_|. Returns true on success.
bool SetEncryptionID(const uint8* id, uint64 length);
@ -207,6 +233,12 @@ class ContentEncoding {
// success.
bool Write(IMkvWriter* writer) const;
uint64 enc_algo() const { return enc_algo_; }
uint64 encoding_order() const { return encoding_order_; }
uint64 encoding_scope() const { return encoding_scope_; }
uint64 encoding_type() const { return encoding_type_; }
ContentEncAESSettings* enc_aes_settings() { return &enc_aes_settings_; }
private:
// Returns the size in bytes for the encoding elements.
uint64 EncodingSize(uint64 compresion_size, uint64 encryption_size) const;
@ -221,6 +253,9 @@ class ContentEncoding {
uint64 encoding_scope_;
uint64 encoding_type_;
// ContentEncAESSettings element.
ContentEncAESSettings enc_aes_settings_;
// Size of the ContentEncKeyID data in bytes.
uint64 enc_key_id_length_;

View File

@ -1,4 +1,4 @@
// Copyright (c) 2011 The WebM project authors. All Rights Reserved.
// Copyright (c) 2012 The WebM project authors. All Rights Reserved.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the LICENSE file in the root of the source
@ -19,6 +19,7 @@
namespace mkvmuxer {
typedef unsigned char uint8;
typedef short int16;
typedef int int32;
typedef unsigned int uint32;
typedef long long int64;

View File

@ -1,4 +1,4 @@
// Copyright (c) 2011 The WebM project authors. All Rights Reserved.
// Copyright (c) 2012 The WebM project authors. All Rights Reserved.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the LICENSE file in the root of the source
@ -22,7 +22,6 @@
namespace mkvmuxer {
int32 GetCodedUIntSize(uint64 value) {
if (value < 0x000000000000007FULL)
return 1;
else if (value < 0x0000000000003FFFULL)
@ -41,7 +40,6 @@ int32 GetCodedUIntSize(uint64 value) {
}
int32 GetUIntSize(uint64 value) {
if (value < 0x0000000000000100ULL)
return 1;
else if (value < 0x0000000000010000ULL)
@ -309,9 +307,8 @@ uint64 WriteSimpleBlock(IMkvWriter* writer,
const uint8* data,
uint64 length,
char track_number,
short timecode,
int16 timecode,
bool is_key) {
if (!writer || !data || length < 1 || track_number < 1 || timecode < 0)
return false;
@ -329,7 +326,7 @@ uint64 WriteSimpleBlock(IMkvWriter* writer,
return 0;
uint64 flags = 0;
if(is_key)
if (is_key)
flags |= 0x80;
if (SerializeInt(writer, flags, 1))
@ -380,11 +377,11 @@ uint64 WriteVoidElement(IMkvWriter* writer, uint64 size) {
return void_size;
}
void GetVersion(int32& major, int32& minor, int32& build, int32& revision) {
major = 0;
minor = 0;
build = 1;
revision = 0;
void GetVersion(int32* major, int32* minor, int32* build, int32* revision) {
*major = 0;
*minor = 1;
*build = 0;
*revision = 0;
}
} // namespace mkvmuxer

View File

@ -75,7 +75,7 @@ uint64 WriteVoidElement(IMkvWriter* writer, uint64 size);
// Returns the version number of the muxer in |major|, |minor|, |build|,
// and |revision|.
void GetVersion(int32& major, int32& minor, int32& build, int32& revision);
void GetVersion(int32* major, int32* minor, int32* build, int32* revision);
} //end namespace mkvmuxer

View File

@ -1,4 +1,4 @@
// Copyright (c) 2010 The WebM project authors. All Rights Reserved.
// Copyright (c) 2012 The WebM project authors. All Rights Reserved.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the LICENSE file in the root of the source
@ -4478,11 +4478,147 @@ unsigned long ContentEncoding::GetEncryptionCount() const {
return static_cast<unsigned long>(count);
}
void ContentEncoding::ParseEncryptionEntry(
long ContentEncoding::ParseContentEncAESSettingsEntry(
long long start,
long long size,
IMkvReader* const pReader,
ContentEncryption* const encryption) {
IMkvReader* pReader,
ContentEncAESSettings* aes) {
assert(pReader);
assert(aes);
long long pos = start;
const long long stop = start + size;
while (pos < stop) {
long long id, size;
const long status = ParseElementHeader(pReader,
pos,
stop,
id,
size);
if (status < 0) //error
return status;
if (id == 0x7E8) {
// AESSettingsCipherMode
aes->cipher_mode = UnserializeUInt(pReader, pos, size);
if (aes->cipher_mode != 1)
return E_FILE_FORMAT_INVALID;
}
pos += size; //consume payload
assert(pos <= stop);
}
return 0;
}
long ContentEncoding::ParseContentEncodingEntry(long long start,
long long size,
IMkvReader* pReader) {
assert(pReader);
long long pos = start;
const long long stop = start + size;
// Count ContentCompression and ContentEncryption elements.
int compression_count = 0;
int encryption_count = 0;
while (pos < stop) {
long long id, size;
const long status = ParseElementHeader(pReader,
pos,
stop,
id,
size);
if (status < 0) //error
return status;
if (id == 0x1034) // ContentCompression ID
++compression_count;
if (id == 0x1035) // ContentEncryption ID
++encryption_count;
pos += size; //consume payload
assert(pos <= stop);
}
if (compression_count <= 0 && encryption_count <= 0)
return -1;
if (compression_count > 0) {
compression_entries_ =
new (std::nothrow) ContentCompression*[compression_count];
if (!compression_entries_)
return -1;
compression_entries_end_ = compression_entries_;
}
if (encryption_count > 0) {
encryption_entries_ =
new (std::nothrow) ContentEncryption*[encryption_count];
if (!encryption_entries_) {
delete [] compression_entries_;
return -1;
}
encryption_entries_end_ = encryption_entries_;
}
pos = start;
while (pos < stop) {
long long id, size;
long status = ParseElementHeader(pReader,
pos,
stop,
id,
size);
if (status < 0) //error
return status;
if (id == 0x1031) {
// ContentEncodingOrder
encoding_order_ = UnserializeUInt(pReader, pos, size);
} else if (id == 0x1032) {
// ContentEncodingScope
encoding_scope_ = UnserializeUInt(pReader, pos, size);
if (encoding_scope_ < 1)
return -1;
} else if (id == 0x1033) {
// ContentEncodingType
encoding_type_ = UnserializeUInt(pReader, pos, size);
} else if (id == 0x1034) {
// ContentCompression ID
// TODO(fgaligan): Add code to parse ContentCompression elements.
} else if (id == 0x1035) {
// ContentEncryption ID
ContentEncryption* const encryption =
new (std::nothrow) ContentEncryption();
if (!encryption)
return -1;
status = ParseEncryptionEntry(pos, size, pReader, encryption);
if (status) {
delete encryption;
return status;
}
*encryption_entries_end_++ = encryption;
}
pos += size; //consume payload
assert(pos <= stop);
}
assert(pos == stop);
return 0;
}
long ContentEncoding::ParseEncryptionEntry(
long long start,
long long size,
IMkvReader* pReader,
ContentEncryption* encryption) {
assert(pReader);
assert(encryption);
@ -4490,166 +4626,111 @@ void ContentEncoding::ParseEncryptionEntry(
const long long stop = start + size;
while (pos < stop) {
#ifdef _DEBUG
long len;
const long long id = ReadUInt(pReader, pos, len);
assert(id >= 0); //TODO: handle error case
assert((pos + len) <= stop);
#endif
long long id, size;
const long status = ParseElementHeader(pReader,
pos,
stop,
id,
size);
if (status < 0) //error
return status;
long long value;
unsigned char* buf;
size_t buf_len;
if (Match(pReader, pos, 0x7E1, value)) {
if (id == 0x7E1) {
// ContentEncAlgo
encryption->algo = value;
} else if (Match(pReader, pos, 0x7E2, buf, buf_len)) {
encryption->algo = UnserializeUInt(pReader, pos, size);
if (encryption->algo != 5)
return E_FILE_FORMAT_INVALID;
} else if (id == 0x7E2) {
// ContentEncKeyID
encryption->key_id = buf;
encryption->key_id_len = buf_len;
} else if (Match(pReader, pos, 0x7E3, buf, buf_len)) {
// ContentSignature
encryption->signature = buf;
encryption->signature_len = buf_len;
} else if (Match(pReader, pos, 0x7E4, buf, buf_len)) {
// ContentSigKeyID
encryption->sig_key_id = buf;
encryption->sig_key_id_len = buf_len;
} else if (Match(pReader, pos, 0x7E5, value)) {
// ContentSigAlgo
encoding_type_ = value;
} else if (Match(pReader, pos, 0x7E6, value)) {
// ContentSigHashAlgo
encoding_type_ = value;
} else {
long len;
const long long id = ReadUInt(pReader, pos, len);
assert(id >= 0); //TODO: handle error case
assert((pos + len) <= stop);
delete[] encryption->key_id;
encryption->key_id = NULL;
encryption->key_id_len = 0;
pos += len; //consume id
if (size <= 0)
return E_FILE_FORMAT_INVALID;
const long long size = ReadUInt(pReader, pos, len);
assert(size >= 0); //TODO: handle error case
assert((pos + len) <= stop);
const size_t buflen = static_cast<size_t>(size);
typedef unsigned char* buf_t;
const buf_t buf = new (std::nothrow) unsigned char[buflen];
if (buf == NULL)
return -1;
pos += len; //consume length of size
assert((pos + size) <= stop);
pos += size; //consume payload
assert(pos <= stop);
}
}
}
bool ContentEncoding::ParseContentEncodingEntry(long long start,
long long size,
IMkvReader* const pReader) {
assert(pReader);
long long pos = start;
const long long stop = start + size;
// Count ContentCompression and ContentEncryption elements.
long long pos1 = start;
int compression_count = 0;
int encryption_count = 0;
while (pos1 < stop) {
long len;
const long long id = ReadUInt(pReader, pos1, len);
assert(id >= 0);
assert((pos1 + len) <= stop);
pos1 += len; //consume id
const long long size = ReadUInt(pReader, pos1, len);
assert(size >= 0);
assert((pos1 + len) <= stop);
pos1 += len; //consume length of size
//pos now designates start of element
if (id == 0x1034) // ContentCompression ID
++compression_count;
if (id == 0x1035) // ContentEncryption ID
++encryption_count;
pos1 += size; //consume payload
assert(pos1 <= stop);
}
if (compression_count <= 0 && encryption_count <= 0)
return false;
if (compression_count > 0) {
compression_entries_ = new ContentCompression*[compression_count];
compression_entries_end_ = compression_entries_;
}
if (encryption_count > 0) {
encryption_entries_ = new ContentEncryption*[encryption_count];
encryption_entries_end_ = encryption_entries_;
}
while (pos < stop) {
#ifdef _DEBUG
long len;
const long long id = ReadUInt(pReader, pos, len);
assert(id >= 0); //TODO: handle error case
assert((pos + len) <= stop);
#endif
long long value;
if (Match(pReader, pos, 0x1031, value)) {
// ContentEncodingOrder
encoding_order_ = value;
} else if (Match(pReader, pos, 0x1032, value)) {
// ContentEncodingScope
encoding_scope_ = value;
assert(encoding_scope_ > 0);
} else if (Match(pReader, pos, 0x1033, value)) {
// ContentEncodingType
encoding_type_ = value;
} else {
long len;
const long long id = ReadUInt(pReader, pos, len);
assert(id >= 0); //TODO: handle error case
assert((pos + len) <= stop);
pos += len; //consume id
const long long size = ReadUInt(pReader, pos, len);
assert(size >= 0); //TODO: handle error case
assert((pos + len) <= stop);
pos += len; //consume length of size
assert((pos + size) <= stop);
//pos now designates start of payload
if (id == 0x1034) {
// ContentCompression ID
// TODO(fgaligan): Add code to parse ContentCompression elements.
} else if (id == 0x1035) {
// ContentEncryption ID
ContentEncryption* const encryption = new ContentEncryption();
ParseEncryptionEntry(pos, size, pReader, encryption);
*encryption_entries_end_ = encryption;
++encryption_entries_end_;
const int read_status = pReader->Read(pos, buflen, buf);
if (read_status) {
delete [] buf;
return status;
}
pos += size; //consume payload
assert(pos <= stop);
encryption->key_id = buf;
encryption->key_id_len = buflen;
} else if (id == 0x7E3) {
// ContentSignature
delete[] encryption->signature;
encryption->signature = NULL;
encryption->signature_len = 0;
if (size <= 0)
return E_FILE_FORMAT_INVALID;
const size_t buflen = static_cast<size_t>(size);
typedef unsigned char* buf_t;
const buf_t buf = new (std::nothrow) unsigned char[buflen];
if (buf == NULL)
return -1;
const int read_status = pReader->Read(pos, buflen, buf);
if (read_status) {
delete [] buf;
return status;
}
encryption->signature = buf;
encryption->signature_len = buflen;
} else if (id == 0x7E4) {
// ContentSigKeyID
delete[] encryption->sig_key_id;
encryption->sig_key_id = NULL;
encryption->sig_key_id_len = 0;
if (size <= 0)
return E_FILE_FORMAT_INVALID;
const size_t buflen = static_cast<size_t>(size);
typedef unsigned char* buf_t;
const buf_t buf = new (std::nothrow) unsigned char[buflen];
if (buf == NULL)
return -1;
const int read_status = pReader->Read(pos, buflen, buf);
if (read_status) {
delete [] buf;
return status;
}
encryption->sig_key_id = buf;
encryption->sig_key_id_len = buflen;
} else if (id == 0x7E5) {
// ContentSigAlgo
encryption->sig_algo = UnserializeUInt(pReader, pos, size);
} else if (id == 0x7E6) {
// ContentSigHashAlgo
encryption->sig_hash_algo = UnserializeUInt(pReader, pos, size);
} else if (id == 0x7E7) {
// ContentEncAESSettings
const long status = ParseContentEncAESSettingsEntry(
pos,
size,
pReader,
&encryption->aes_settings);
if (status)
return status;
}
pos += size; //consume payload
assert(pos <= stop);
}
assert(pos == stop);
return true;
return 0;
}
Track::Track(
@ -5038,7 +5119,7 @@ unsigned long Track::GetContentEncodingCount() const {
return static_cast<unsigned long>(count);
}
void Track::ParseContentEncodingsEntry(long long start, long long size) {
long Track::ParseContentEncodingsEntry(long long start, long long size) {
IMkvReader* const pReader = m_pSegment->m_pReader;
assert(pReader);
@ -5046,70 +5127,71 @@ void Track::ParseContentEncodingsEntry(long long start, long long size) {
const long long stop = start + size;
// Count ContentEncoding elements.
long long pos1 = start;
int count = 0;
while (pos < stop) {
long long id, size;
const long status = ParseElementHeader(pReader,
pos,
stop,
id,
size);
if (status < 0) //error
return status;
while (pos1 < stop) {
long len;
const long long id = ReadUInt(pReader, pos1, len);
assert(id >= 0);
assert((pos1 + len) <= stop);
pos1 += len; //consume id
const long long size = ReadUInt(pReader, pos1, len);
assert(size >= 0);
assert((pos1 + len) <= stop);
pos1 += len; //consume length of size
//pos now designates start of element
if (id == 0x2240) // ContentEncoding ID
++count;
pos1 += size; //consume payload
assert(pos1 <= stop);
pos += size; //consume payload
assert(pos <= stop);
}
if (count <= 0)
return;
return -1;
content_encoding_entries_ = new (std::nothrow) ContentEncoding*[count];
if (!content_encoding_entries_)
return -1;
content_encoding_entries_ = new ContentEncoding*[count];
content_encoding_entries_end_ = content_encoding_entries_;
pos = start;
while (pos < stop) {
long len;
const long long id = ReadUInt(pReader, pos, len);
assert(id >= 0);
assert((pos + len) <= stop);
pos += len; //consume id
const long long size1 = ReadUInt(pReader, pos, len);
assert(size1 >= 0);
assert((pos + len) <= stop);
pos += len; //consume length of size
long long id, size;
long status = ParseElementHeader(pReader,
pos,
stop,
id,
size);
if (status < 0) //error
return status;
//pos now designates start of element
if (id == 0x2240) { // ContentEncoding ID
ContentEncoding* const content_encoding = new ContentEncoding();
ContentEncoding* const content_encoding =
new (std::nothrow) ContentEncoding();
if (!content_encoding)
return -1;
if (!content_encoding->ParseContentEncodingEntry(pos, size1, pReader)) {
status = content_encoding->ParseContentEncodingEntry(pos,
size,
pReader);
if (status) {
delete content_encoding;
} else {
*content_encoding_entries_end_ = content_encoding;
++content_encoding_entries_end_;
return status;
}
*content_encoding_entries_end_++ = content_encoding;
}
pos += size1; //consume payload
pos += size; //consume payload
assert(pos <= stop);
}
assert(pos == stop);
return;
return 0;
}
Track::EOSBlock::EOSBlock() :

View File

@ -1,4 +1,4 @@
// Copyright (c) 2010 The WebM project authors. All Rights Reserved.
// Copyright (c) 2012 The WebM project authors. All Rights Reserved.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the LICENSE file in the root of the source
@ -203,6 +203,10 @@ private:
// compressed with zlib or header stripping.
class ContentEncoding {
public:
enum {
kCTR = 1
};
ContentEncoding();
~ContentEncoding();
@ -215,6 +219,14 @@ public:
unsigned char* settings;
};
// ContentEncAESSettings element names
struct ContentEncAESSettings {
ContentEncAESSettings() : cipher_mode(kCTR) {}
~ContentEncAESSettings() {}
unsigned long long cipher_mode;
};
// ContentEncryption element names
struct ContentEncryption {
ContentEncryption();
@ -229,6 +241,8 @@ public:
long long sig_key_id_len;
unsigned long long sig_algo;
unsigned long long sig_hash_algo;
ContentEncAESSettings aes_settings;
};
// Returns ContentCompression represented by |idx|. Returns NULL if |idx|
@ -247,21 +261,30 @@ public:
// element.
unsigned long GetEncryptionCount() const;
// Parses the ContentEncAESSettings element from |pReader|. |start| is the
// starting offset of the ContentEncAESSettings payload. |size| is the
// size in bytes of the ContentEncAESSettings payload. |encryption| is
// where the parsed values will be stored.
long ParseContentEncAESSettingsEntry(long long start,
long long size,
IMkvReader* pReader,
ContentEncAESSettings* aes);
// Parses the ContentEncoding element from |pReader|. |start| is the
// starting offset of the ContentEncoding payload. |size| is the size in
// bytes of the ContentEncoding payload. Returns true on success.
bool ParseContentEncodingEntry(long long start,
long ParseContentEncodingEntry(long long start,
long long size,
IMkvReader* const pReader);
IMkvReader* pReader);
// Parses the ContentEncryption element from |pReader|. |start| is the
// starting offset of the ContentEncryption payload. |size| is the size in
// bytes of the ContentEncryption payload. |encryption| is where the parsed
// values will be stored.
void ParseEncryptionEntry(long long start,
long ParseEncryptionEntry(long long start,
long long size,
IMkvReader* const pReader,
ContentEncryption* const encryption);
IMkvReader* pReader,
ContentEncryption* encryption);
unsigned long long encoding_order() const { return encoding_order_; }
unsigned long long encoding_scope() const { return encoding_scope_; }
@ -349,7 +372,7 @@ public:
const ContentEncoding* GetContentEncodingByIndex(unsigned long idx) const;
unsigned long GetContentEncodingCount() const;
void ParseContentEncodingsEntry(long long start, long long size);
long ParseContentEncodingsEntry(long long start, long long size);
protected:
Track(

View File

@ -1,94 +1,94 @@
// Copyright (c) 2011 The WebM project authors. All Rights Reserved.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the LICENSE file in the root of the source
// tree. An additional intellectual property rights grant can be found
// in the file PATENTS. All contributing project authors may
// be found in the AUTHORS file in the root of the source tree.
#include "mkvwriter.hpp"
#ifdef _MSC_VER
#include <share.h> // for _SH_DENYWR
#endif
#include <new>
namespace mkvmuxer {
MkvWriter::MkvWriter() : file_(NULL) {
}
MkvWriter::~MkvWriter() {
Close();
}
int32 MkvWriter::Write(const void* buffer, uint32 length) {
if (!file_)
return -1;
if (length == 0)
return 0;
if (buffer == NULL)
return -1;
const size_t bytes_written = fwrite(buffer, 1, length, file_);
return (bytes_written == length) ? 0 : -1;
}
bool MkvWriter::Open(const char* filename) {
if (filename == NULL)
return false;
if (file_)
return false;
#ifdef _MSC_VER
file_ = _fsopen(filename, "wb", _SH_DENYWR);
#else
file_ = fopen(filename, "wb");
#endif
if (file_ == NULL)
return false;
return true;
}
void MkvWriter::Close() {
if (file_) {
fclose(file_);
file_ = NULL;
}
}
int64 MkvWriter::Position() const {
if (!file_)
return 0;
#ifdef _MSC_VER
return _ftelli64(file_);
#else
return ftell(file_);
#endif
}
int32 MkvWriter::Position(int64 position) {
if (!file_)
return -1;
#ifdef _MSC_VER
return _fseeki64(file_, position, SEEK_SET);
#else
return fseek(file_, position, SEEK_SET);
#endif
}
bool MkvWriter::Seekable() const {
return true;
}
void MkvWriter::ElementStartNotify(uint64, int64) {
}
} // namespace mkvmuxer
// Copyright (c) 2012 The WebM project authors. All Rights Reserved.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the LICENSE file in the root of the source
// tree. An additional intellectual property rights grant can be found
// in the file PATENTS. All contributing project authors may
// be found in the AUTHORS file in the root of the source tree.
#include "mkvwriter.hpp"
#ifdef _MSC_VER
#include <share.h> // for _SH_DENYWR
#endif
#include <new>
namespace mkvmuxer {
MkvWriter::MkvWriter() : file_(NULL) {
}
MkvWriter::~MkvWriter() {
Close();
}
int32 MkvWriter::Write(const void* buffer, uint32 length) {
if (!file_)
return -1;
if (length == 0)
return 0;
if (buffer == NULL)
return -1;
const size_t bytes_written = fwrite(buffer, 1, length, file_);
return (bytes_written == length) ? 0 : -1;
}
bool MkvWriter::Open(const char* filename) {
if (filename == NULL)
return false;
if (file_)
return false;
#ifdef _MSC_VER
file_ = _fsopen(filename, "wb", _SH_DENYWR);
#else
file_ = fopen(filename, "wb");
#endif
if (file_ == NULL)
return false;
return true;
}
void MkvWriter::Close() {
if (file_) {
fclose(file_);
file_ = NULL;
}
}
int64 MkvWriter::Position() const {
if (!file_)
return 0;
#ifdef _MSC_VER
return _ftelli64(file_);
#else
return ftell(file_);
#endif
}
int32 MkvWriter::Position(int64 position) {
if (!file_)
return -1;
#ifdef _MSC_VER
return _fseeki64(file_, position, SEEK_SET);
#else
return fseek(file_, position, SEEK_SET);
#endif
}
bool MkvWriter::Seekable() const {
return true;
}
void MkvWriter::ElementStartNotify(uint64, int64) {
}
} // namespace mkvmuxer

View File

@ -1,49 +1,49 @@
// Copyright (c) 2012 The WebM project authors. All Rights Reserved.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the LICENSE file in the root of the source
// tree. An additional intellectual property rights grant can be found
// in the file PATENTS. All contributing project authors may
// be found in the AUTHORS file in the root of the source tree.
#ifndef MKVWRITER_HPP
#define MKVWRITER_HPP
#include <stdio.h>
#include "mkvmuxer.hpp"
#include "mkvmuxertypes.hpp"
namespace mkvmuxer {
// Default implementation of the IMkvWriter interface on Windows.
class MkvWriter : public IMkvWriter {
public:
MkvWriter();
virtual ~MkvWriter();
// IMkvWriter interface
virtual int64 Position() const;
virtual int32 Position(int64 position);
virtual bool Seekable() const;
virtual int32 Write(const void* buffer, uint32 length);
virtual void ElementStartNotify(uint64 element_id, int64 position);
// Creates and opens a file for writing. |filename| is the name of the file
// to open. This function will overwrite the contents of |filename|. Returns
// true on success.
bool Open(const char* filename);
// Closes an opened file.
void Close();
private:
// File handle to output file.
FILE* file_;
LIBWEBM_DISALLOW_COPY_AND_ASSIGN(MkvWriter);
};
} //end namespace mkvmuxer
#endif // MKVWRITER_HPP
// Copyright (c) 2012 The WebM project authors. All Rights Reserved.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the LICENSE file in the root of the source
// tree. An additional intellectual property rights grant can be found
// in the file PATENTS. All contributing project authors may
// be found in the AUTHORS file in the root of the source tree.
#ifndef MKVWRITER_HPP
#define MKVWRITER_HPP
#include <stdio.h>
#include "mkvmuxer.hpp"
#include "mkvmuxertypes.hpp"
namespace mkvmuxer {
// Default implementation of the IMkvWriter interface on Windows.
class MkvWriter : public IMkvWriter {
public:
MkvWriter();
virtual ~MkvWriter();
// IMkvWriter interface
virtual int64 Position() const;
virtual int32 Position(int64 position);
virtual bool Seekable() const;
virtual int32 Write(const void* buffer, uint32 length);
virtual void ElementStartNotify(uint64 element_id, int64 position);
// Creates and opens a file for writing. |filename| is the name of the file
// to open. This function will overwrite the contents of |filename|. Returns
// true on success.
bool Open(const char* filename);
// Closes an opened file.
void Close();
private:
// File handle to output file.
FILE* file_;
LIBWEBM_DISALLOW_COPY_AND_ASSIGN(MkvWriter);
};
} //end namespace mkvmuxer
#endif // MKVWRITER_HPP

View File

@ -1,4 +1,4 @@
// Copyright (c) 2011 The WebM project authors. All Rights Reserved.
// Copyright (c) 2012 The WebM project authors. All Rights Reserved.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the LICENSE file in the root of the source
@ -101,6 +101,9 @@ enum MkvId {
kMkvContentEncryption = 0x5035,
kMkvContentEncAlgo = 0x47E1,
kMkvContentEncKeyID = 0x47E2,
kMkvContentEncAESSettings = 0x47E7,
kMkvAESSettingsCipherMode = 0x47E8,
kMkvAESSettingsCipherInitData = 0x47E9,
//end ContentEncodings
//Cueing Data
kMkvCues = 0x1C53BB6B,