3277 lines · 85.7 KB · C++
RawDownload
// 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 "mkvmuxer.hpp" #include <climits>#include <cstdio>#include <cstdlib>#include <cstring>#include <ctime>#include <new> #include "mkvmuxerutil.hpp"#include "mkvparser.hpp"#include "mkvwriter.hpp"#include "webmids.hpp" #ifdef _MSC_VER// Disable MSVC warnings that suggest making code non-portable.#pragma warning(disable : 4996)#endif namespace mkvmuxer { namespace {// Deallocate the string designated by |dst|, and then copy the |src|// string to |dst|.  The caller owns both the |src| string and the// |dst| copy (hence the caller is responsible for eventually// deallocating the strings, either directly, or indirectly via// StrCpy).  Returns true if the source string was successfully copied// to the destination.bool StrCpy(const char* src, char** dst_ptr) {  if (dst_ptr == NULL)    return false;   char*& dst = *dst_ptr;   delete[] dst;  dst = NULL;   if (src == NULL)    return true;   const size_t size = strlen(src) + 1;   dst = new (std::nothrow) char[size];  // NOLINT  if (dst == NULL)    return false;   strcpy(dst, src);  // NOLINT  return true;}}  // namespace /////////////////////////////////////////////////////////////////// IMkvWriter Class IMkvWriter::IMkvWriter() {} IMkvWriter::~IMkvWriter() {} bool WriteEbmlHeader(IMkvWriter* writer, uint64 doc_type_version) {  // Level 0  uint64 size = EbmlElementSize(kMkvEBMLVersion, 1ULL);  size += EbmlElementSize(kMkvEBMLReadVersion, 1ULL);  size += EbmlElementSize(kMkvEBMLMaxIDLength, 4ULL);  size += EbmlElementSize(kMkvEBMLMaxSizeLength, 8ULL);  size += EbmlElementSize(kMkvDocType, "webm");  size += EbmlElementSize(kMkvDocTypeVersion, doc_type_version);  size += EbmlElementSize(kMkvDocTypeReadVersion, 2ULL);   if (!WriteEbmlMasterElement(writer, kMkvEBML, size))    return false;  if (!WriteEbmlElement(writer, kMkvEBMLVersion, 1ULL))    return false;  if (!WriteEbmlElement(writer, kMkvEBMLReadVersion, 1ULL))    return false;  if (!WriteEbmlElement(writer, kMkvEBMLMaxIDLength, 4ULL))    return false;  if (!WriteEbmlElement(writer, kMkvEBMLMaxSizeLength, 8ULL))    return false;  if (!WriteEbmlElement(writer, kMkvDocType, "webm"))    return false;  if (!WriteEbmlElement(writer, kMkvDocTypeVersion, doc_type_version))    return false;  if (!WriteEbmlElement(writer, kMkvDocTypeReadVersion, 2ULL))    return false;   return true;} bool WriteEbmlHeader(IMkvWriter* writer) {  return WriteEbmlHeader(writer, mkvmuxer::Segment::kDefaultDocTypeVersion);} bool ChunkedCopy(mkvparser::IMkvReader* source, mkvmuxer::IMkvWriter* dst,                 mkvmuxer::int64 start, int64 size) {  // TODO(vigneshv): Check if this is a reasonable value.  const uint32 kBufSize = 2048;  uint8* buf = new uint8[kBufSize];  int64 offset = start;  while (size > 0) {    const int64 read_len = (size > kBufSize) ? kBufSize : size;    if (source->Read(offset, static_cast<long>(read_len), buf))      return false;    dst->Write(buf, static_cast<uint32>(read_len));    offset += read_len;    size -= read_len;  }  delete[] buf;  return true;} /////////////////////////////////////////////////////////////////// Frame Class Frame::Frame()    : add_id_(0),      additional_(NULL),      additional_length_(0),      duration_(0),      frame_(NULL),      is_key_(false),      length_(0),      track_number_(0),      timestamp_(0),      discard_padding_(0),      reference_block_timestamp_(0),      reference_block_timestamp_set_(false) {} Frame::~Frame() {  delete[] frame_;  delete[] additional_;} bool Frame::CopyFrom(const Frame& frame) {  delete[] frame_;  frame_ = NULL;  length_ = 0;  if (frame.length() > 0 && frame.frame() != NULL &&      !Init(frame.frame(), frame.length())) {    return false;  }  add_id_ = 0;  delete[] additional_;  additional_ = NULL;  additional_length_ = 0;  if (frame.additional_length() > 0 && frame.additional() != NULL &&      !AddAdditionalData(frame.additional(), frame.additional_length(),                         frame.add_id())) {    return false;  }  duration_ = frame.duration();  is_key_ = frame.is_key();  track_number_ = frame.track_number();  timestamp_ = frame.timestamp();  discard_padding_ = frame.discard_padding();  return true;} bool Frame::Init(const uint8* frame, uint64 length) {  uint8* const data =      new (std::nothrow) uint8[static_cast<size_t>(length)];  // NOLINT  if (!data)    return false;   delete[] frame_;  frame_ = data;  length_ = length;   memcpy(frame_, frame, static_cast<size_t>(length_));  return true;} bool Frame::AddAdditionalData(const uint8* additional, uint64 length,                              uint64 add_id) {  uint8* const data =      new (std::nothrow) uint8[static_cast<size_t>(length)];  // NOLINT  if (!data)    return false;   delete[] additional_;  additional_ = data;  additional_length_ = length;  add_id_ = add_id;   memcpy(additional_, additional, static_cast<size_t>(additional_length_));  return true;} bool Frame::IsValid() const {  if (length_ == 0 || !frame_) {    return false;  }  if ((additional_length_ != 0 && !additional_) ||      (additional_ != NULL && additional_length_ == 0)) {    return false;  }  if (track_number_ == 0 || track_number_ > kMaxTrackNumber) {    return false;  }  if (!CanBeSimpleBlock() && !is_key_ && !reference_block_timestamp_set_) {    return false;  }  return true;} bool Frame::CanBeSimpleBlock() const {  return additional_ == NULL && discard_padding_ == 0 && duration_ == 0;} void Frame::set_reference_block_timestamp(int64 reference_block_timestamp) {  reference_block_timestamp_ = reference_block_timestamp;  reference_block_timestamp_set_ = true;} /////////////////////////////////////////////////////////////////// CuePoint Class CuePoint::CuePoint()    : time_(0),      track_(0),      cluster_pos_(0),      block_number_(1),      output_block_number_(true) {} CuePoint::~CuePoint() {} bool CuePoint::Write(IMkvWriter* writer) const {  if (!writer || track_ < 1 || cluster_pos_ < 1)    return false;   uint64 size = EbmlElementSize(kMkvCueClusterPosition, cluster_pos_);  size += EbmlElementSize(kMkvCueTrack, track_);  if (output_block_number_ && block_number_ > 1)    size += EbmlElementSize(kMkvCueBlockNumber, block_number_);  const uint64 track_pos_size =      EbmlMasterElementSize(kMkvCueTrackPositions, size) + size;  const uint64 payload_size =      EbmlElementSize(kMkvCueTime, time_) + track_pos_size;   if (!WriteEbmlMasterElement(writer, kMkvCuePoint, payload_size))    return false;   const int64 payload_position = writer->Position();  if (payload_position < 0)    return false;   if (!WriteEbmlElement(writer, kMkvCueTime, time_))    return false;   if (!WriteEbmlMasterElement(writer, kMkvCueTrackPositions, size))    return false;  if (!WriteEbmlElement(writer, kMkvCueTrack, track_))    return false;  if (!WriteEbmlElement(writer, kMkvCueClusterPosition, cluster_pos_))    return false;  if (output_block_number_ && block_number_ > 1)    if (!WriteEbmlElement(writer, kMkvCueBlockNumber, block_number_))      return false;   const int64 stop_position = writer->Position();  if (stop_position < 0)    return false;   if (stop_position - payload_position != static_cast<int64>(payload_size))    return false;   return true;} uint64 CuePoint::PayloadSize() const {  uint64 size = EbmlElementSize(kMkvCueClusterPosition, cluster_pos_);  size += EbmlElementSize(kMkvCueTrack, track_);  if (output_block_number_ && block_number_ > 1)    size += EbmlElementSize(kMkvCueBlockNumber, block_number_);  const uint64 track_pos_size =      EbmlMasterElementSize(kMkvCueTrackPositions, size) + size;  const uint64 payload_size =      EbmlElementSize(kMkvCueTime, time_) + track_pos_size;   return payload_size;} uint64 CuePoint::Size() const {  const uint64 payload_size = PayloadSize();  return EbmlMasterElementSize(kMkvCuePoint, payload_size) + payload_size;} /////////////////////////////////////////////////////////////////// Cues Class Cues::Cues()    : cue_entries_capacity_(0),      cue_entries_size_(0),      cue_entries_(NULL),      output_block_number_(true) {} Cues::~Cues() {  if (cue_entries_) {    for (int32 i = 0; i < cue_entries_size_; ++i) {      CuePoint* const cue = cue_entries_[i];      delete cue;    }    delete[] cue_entries_;  }} bool Cues::AddCue(CuePoint* cue) {  if (!cue)    return false;   if ((cue_entries_size_ + 1) > cue_entries_capacity_) {    // Add more CuePoints.    const int32 new_capacity =        (!cue_entries_capacity_) ? 2 : cue_entries_capacity_ * 2;     if (new_capacity < 1)      return false;     CuePoint** const cues =        new (std::nothrow) CuePoint*[new_capacity];  // NOLINT    if (!cues)      return false;     for (int32 i = 0; i < cue_entries_size_; ++i) {      cues[i] = cue_entries_[i];    }     delete[] cue_entries_;     cue_entries_ = cues;    cue_entries_capacity_ = new_capacity;  }   cue->set_output_block_number(output_block_number_);  cue_entries_[cue_entries_size_++] = cue;  return true;} CuePoint* Cues::GetCueByIndex(int32 index) const {  if (cue_entries_ == NULL)    return NULL;   if (index >= cue_entries_size_)    return NULL;   return cue_entries_[index];} uint64 Cues::Size() {  uint64 size = 0;  for (int32 i = 0; i < cue_entries_size_; ++i)    size += GetCueByIndex(i)->Size();  size += EbmlMasterElementSize(kMkvCues, size);  return size;} bool Cues::Write(IMkvWriter* writer) const {  if (!writer)    return false;   uint64 size = 0;  for (int32 i = 0; i < cue_entries_size_; ++i) {    const CuePoint* const cue = GetCueByIndex(i);     if (!cue)      return false;     size += cue->Size();  }   if (!WriteEbmlMasterElement(writer, kMkvCues, size))    return false;   const int64 payload_position = writer->Position();  if (payload_position < 0)    return false;   for (int32 i = 0; i < cue_entries_size_; ++i) {    const CuePoint* const cue = GetCueByIndex(i);     if (!cue->Write(writer))      return false;  }   const int64 stop_position = writer->Position();  if (stop_position < 0)    return false;   if (stop_position - payload_position != static_cast<int64>(size))    return false;   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 ContentEncoding::ContentEncoding()    : enc_algo_(5),      enc_key_id_(NULL),      encoding_order_(0),      encoding_scope_(1),      encoding_type_(1),      enc_key_id_length_(0) {} ContentEncoding::~ContentEncoding() { delete[] enc_key_id_; } bool ContentEncoding::SetEncryptionID(const uint8* id, uint64 length) {  if (!id || length < 1)    return false;   delete[] enc_key_id_;   enc_key_id_ =      new (std::nothrow) uint8[static_cast<size_t>(length)];  // NOLINT  if (!enc_key_id_)    return false;   memcpy(enc_key_id_, id, static_cast<size_t>(length));  enc_key_id_length_ = length;   return true;} uint64 ContentEncoding::Size() const {  const uint64 encryption_size = EncryptionSize();  const uint64 encoding_size = EncodingSize(0, encryption_size);  const uint64 encodings_size =      EbmlMasterElementSize(kMkvContentEncoding, encoding_size) + encoding_size;   return encodings_size;} bool ContentEncoding::Write(IMkvWriter* writer) const {  const uint64 encryption_size = EncryptionSize();  const uint64 encoding_size = EncodingSize(0, encryption_size);  const uint64 size =      EbmlMasterElementSize(kMkvContentEncoding, encoding_size) + encoding_size;   const int64 payload_position = writer->Position();  if (payload_position < 0)    return false;   if (!WriteEbmlMasterElement(writer, kMkvContentEncoding, encoding_size))    return false;  if (!WriteEbmlElement(writer, kMkvContentEncodingOrder, encoding_order_))    return false;  if (!WriteEbmlElement(writer, kMkvContentEncodingScope, encoding_scope_))    return false;

Lines 1–500 of 3277.

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t