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:
parent
c4d2b27b7a
commit
a320f5be63
112
mkvmuxer.cpp
112
mkvmuxer.cpp
@ -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;
|
||||
|
||||
|
53
mkvmuxer.hpp
53
mkvmuxer.hpp
@ -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_;
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
464
mkvparser.cpp
464
mkvparser.cpp
@ -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() :
|
||||
|
@ -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(
|
||||
|
188
mkvwriter.cpp
188
mkvwriter.cpp
@ -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
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
Loading…
x
Reference in New Issue
Block a user