12ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian// Copyright (c) 2012 The WebM project authors. All Rights Reserved.
22ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian//
32ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian// Use of this source code is governed by a BSD-style license
42ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian// that can be found in the LICENSE file in the root of the source
52ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian// tree. An additional intellectual property rights grant can be found
62ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian// in the file PATENTS.  All contributing project authors may
72ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian// be found in the AUTHORS file in the root of the source tree.
82ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
92ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian#include "mkvmuxer.hpp"
102ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
112ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian#include <climits>
122ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian#include <cstdio>
132ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian#include <cstdlib>
142ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian#include <cstring>
152ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian#include <ctime>
162ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian#include <new>
172ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
182ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian#include "mkvmuxerutil.hpp"
192ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian#include "mkvparser.hpp"
202ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian#include "mkvwriter.hpp"
212ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian#include "webmids.hpp"
222ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
232ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian#ifdef _MSC_VER
242ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian// Disable MSVC warnings that suggest making code non-portable.
25ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#pragma warning(disable : 4996)
262ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian#endif
272ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
282ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramaniannamespace mkvmuxer {
292ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
302ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramaniannamespace {
312ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian// Deallocate the string designated by |dst|, and then copy the |src|
322ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian// string to |dst|.  The caller owns both the |src| string and the
332ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian// |dst| copy (hence the caller is responsible for eventually
342ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian// deallocating the strings, either directly, or indirectly via
352ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian// StrCpy).  Returns true if the source string was successfully copied
362ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian// to the destination.
372ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanianbool StrCpy(const char* src, char** dst_ptr) {
382ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (dst_ptr == NULL)
392ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return false;
402ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
412ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  char*& dst = *dst_ptr;
422ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
43ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  delete[] dst;
442ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  dst = NULL;
452ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
462ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (src == NULL)
472ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return true;
482ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
492ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  const size_t size = strlen(src) + 1;
502ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
512ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  dst = new (std::nothrow) char[size];  // NOLINT
522ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (dst == NULL)
532ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return false;
542ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
552ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  strcpy(dst, src);  // NOLINT
562ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  return true;
572ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian}
582ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian}  // namespace
592ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
602ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian///////////////////////////////////////////////////////////////
612ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian//
622ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian// IMkvWriter Class
632ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
64ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh VenkatasubramanianIMkvWriter::IMkvWriter() {}
652ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
66ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh VenkatasubramanianIMkvWriter::~IMkvWriter() {}
672ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
682ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanianbool WriteEbmlHeader(IMkvWriter* writer) {
692ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  // Level 0
702ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  uint64 size = EbmlElementSize(kMkvEBMLVersion, 1ULL);
712ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  size += EbmlElementSize(kMkvEBMLReadVersion, 1ULL);
722ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  size += EbmlElementSize(kMkvEBMLMaxIDLength, 4ULL);
732ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  size += EbmlElementSize(kMkvEBMLMaxSizeLength, 8ULL);
742ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  size += EbmlElementSize(kMkvDocType, "webm");
752ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  size += EbmlElementSize(kMkvDocTypeVersion, 2ULL);
762ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  size += EbmlElementSize(kMkvDocTypeReadVersion, 2ULL);
772ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
782ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (!WriteEbmlMasterElement(writer, kMkvEBML, size))
792ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return false;
802ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (!WriteEbmlElement(writer, kMkvEBMLVersion, 1ULL))
812ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return false;
822ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (!WriteEbmlElement(writer, kMkvEBMLReadVersion, 1ULL))
832ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return false;
842ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (!WriteEbmlElement(writer, kMkvEBMLMaxIDLength, 4ULL))
852ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return false;
862ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (!WriteEbmlElement(writer, kMkvEBMLMaxSizeLength, 8ULL))
872ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return false;
882ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (!WriteEbmlElement(writer, kMkvDocType, "webm"))
892ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return false;
902ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (!WriteEbmlElement(writer, kMkvDocTypeVersion, 2ULL))
912ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return false;
922ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (!WriteEbmlElement(writer, kMkvDocTypeReadVersion, 2ULL))
932ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return false;
942ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
952ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  return true;
962ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian}
972ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
98ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanianbool ChunkedCopy(mkvparser::IMkvReader* source, mkvmuxer::IMkvWriter* dst,
992ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian                 mkvmuxer::int64 start, int64 size) {
1002ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  // TODO(vigneshv): Check if this is a reasonable value.
1012ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  const uint32 kBufSize = 2048;
1022ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  uint8* buf = new uint8[kBufSize];
1032ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  int64 offset = start;
1042ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  while (size > 0) {
1052ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    const int64 read_len = (size > kBufSize) ? kBufSize : size;
1062ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    if (source->Read(offset, static_cast<long>(read_len), buf))
1072ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      return false;
1082ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    dst->Write(buf, static_cast<uint32>(read_len));
1092ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    offset += read_len;
1102ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    size -= read_len;
1112ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  }
1122ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  delete[] buf;
1132ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  return true;
1142ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian}
1152ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
1162ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian///////////////////////////////////////////////////////////////
1172ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian//
1182ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian// Frame Class
1192ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
1202ec72e65689c948e92b826ae1e867bf369e72f13Vignesh VenkatasubramanianFrame::Frame()
1212ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    : add_id_(0),
1222ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      additional_(NULL),
1232ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      additional_length_(0),
1242ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      duration_(0),
1252ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      frame_(NULL),
1262ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      is_key_(false),
1272ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      length_(0),
1282ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      track_number_(0),
1292ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      timestamp_(0),
130ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      discard_padding_(0) {}
1312ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
1322ec72e65689c948e92b826ae1e867bf369e72f13Vignesh VenkatasubramanianFrame::~Frame() {
133ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  delete[] frame_;
134ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  delete[] additional_;
1352ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian}
1362ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
1372ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanianbool Frame::Init(const uint8* frame, uint64 length) {
1382ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  uint8* const data =
1392ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      new (std::nothrow) uint8[static_cast<size_t>(length)];  // NOLINT
1402ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (!data)
1412ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return false;
1422ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
143ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  delete[] frame_;
1442ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  frame_ = data;
1452ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  length_ = length;
1462ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
1472ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  memcpy(frame_, frame, static_cast<size_t>(length_));
1482ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  return true;
1492ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian}
1502ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
1512ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanianbool Frame::AddAdditionalData(const uint8* additional, uint64 length,
1522ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian                              uint64 add_id) {
1532ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  uint8* const data =
1542ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      new (std::nothrow) uint8[static_cast<size_t>(length)];  // NOLINT
1552ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (!data)
1562ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return false;
1572ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
158ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  delete[] additional_;
1592ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  additional_ = data;
1602ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  additional_length_ = length;
1612ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  add_id_ = add_id;
1622ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
1632ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  memcpy(additional_, additional, static_cast<size_t>(additional_length_));
1642ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  return true;
1652ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian}
1662ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
1672ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian///////////////////////////////////////////////////////////////
1682ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian//
1692ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian// CuePoint Class
1702ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
1712ec72e65689c948e92b826ae1e867bf369e72f13Vignesh VenkatasubramanianCuePoint::CuePoint()
1722ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    : time_(0),
1732ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      track_(0),
1742ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      cluster_pos_(0),
1752ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      block_number_(1),
176ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      output_block_number_(true) {}
1772ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
178ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh VenkatasubramanianCuePoint::~CuePoint() {}
1792ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
1802ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanianbool CuePoint::Write(IMkvWriter* writer) const {
1812ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (!writer || track_ < 1 || cluster_pos_ < 1)
1822ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return false;
1832ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
1842ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  uint64 size = EbmlElementSize(kMkvCueClusterPosition, cluster_pos_);
1852ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  size += EbmlElementSize(kMkvCueTrack, track_);
1862ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (output_block_number_ && block_number_ > 1)
1872ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    size += EbmlElementSize(kMkvCueBlockNumber, block_number_);
188ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  const uint64 track_pos_size =
189ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      EbmlMasterElementSize(kMkvCueTrackPositions, size) + size;
190ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  const uint64 payload_size =
191ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      EbmlElementSize(kMkvCueTime, time_) + track_pos_size;
1922ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
1932ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (!WriteEbmlMasterElement(writer, kMkvCuePoint, payload_size))
1942ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return false;
1952ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
1962ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  const int64 payload_position = writer->Position();
1972ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (payload_position < 0)
1982ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return false;
1992ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
2002ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (!WriteEbmlElement(writer, kMkvCueTime, time_))
2012ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return false;
2022ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
2032ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (!WriteEbmlMasterElement(writer, kMkvCueTrackPositions, size))
2042ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return false;
2052ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (!WriteEbmlElement(writer, kMkvCueTrack, track_))
2062ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return false;
2072ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (!WriteEbmlElement(writer, kMkvCueClusterPosition, cluster_pos_))
2082ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return false;
2092ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (output_block_number_ && block_number_ > 1)
2102ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    if (!WriteEbmlElement(writer, kMkvCueBlockNumber, block_number_))
2112ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      return false;
2122ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
2132ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  const int64 stop_position = writer->Position();
2142ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (stop_position < 0)
2152ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return false;
2162ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
2172ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (stop_position - payload_position != static_cast<int64>(payload_size))
2182ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return false;
2192ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
2202ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  return true;
2212ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian}
2222ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
2232ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanianuint64 CuePoint::PayloadSize() const {
2242ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  uint64 size = EbmlElementSize(kMkvCueClusterPosition, cluster_pos_);
2252ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  size += EbmlElementSize(kMkvCueTrack, track_);
2262ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (output_block_number_ && block_number_ > 1)
2272ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    size += EbmlElementSize(kMkvCueBlockNumber, block_number_);
228ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  const uint64 track_pos_size =
229ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      EbmlMasterElementSize(kMkvCueTrackPositions, size) + size;
230ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  const uint64 payload_size =
231ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      EbmlElementSize(kMkvCueTime, time_) + track_pos_size;
2322ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
2332ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  return payload_size;
2342ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian}
2352ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
2362ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanianuint64 CuePoint::Size() const {
2372ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  const uint64 payload_size = PayloadSize();
2382ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  return EbmlMasterElementSize(kMkvCuePoint, payload_size) + payload_size;
2392ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian}
2402ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
2412ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian///////////////////////////////////////////////////////////////
2422ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian//
2432ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian// Cues Class
2442ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
2452ec72e65689c948e92b826ae1e867bf369e72f13Vignesh VenkatasubramanianCues::Cues()
2462ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    : cue_entries_capacity_(0),
2472ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      cue_entries_size_(0),
2482ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      cue_entries_(NULL),
249ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      output_block_number_(true) {}
2502ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
2512ec72e65689c948e92b826ae1e867bf369e72f13Vignesh VenkatasubramanianCues::~Cues() {
2522ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (cue_entries_) {
2532ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    for (int32 i = 0; i < cue_entries_size_; ++i) {
2542ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      CuePoint* const cue = cue_entries_[i];
2552ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      delete cue;
2562ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    }
257ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    delete[] cue_entries_;
2582ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  }
2592ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian}
2602ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
2612ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanianbool Cues::AddCue(CuePoint* cue) {
2622ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (!cue)
2632ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return false;
2642ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
2652ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if ((cue_entries_size_ + 1) > cue_entries_capacity_) {
2662ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    // Add more CuePoints.
2672ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    const int32 new_capacity =
2682ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian        (!cue_entries_capacity_) ? 2 : cue_entries_capacity_ * 2;
2692ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
2702ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    if (new_capacity < 1)
2712ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      return false;
2722ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
2732ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    CuePoint** const cues =
274ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian        new (std::nothrow) CuePoint* [new_capacity];  // NOLINT
2752ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    if (!cues)
2762ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      return false;
2772ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
2782ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    for (int32 i = 0; i < cue_entries_size_; ++i) {
2792ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      cues[i] = cue_entries_[i];
2802ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    }
2812ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
282ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    delete[] cue_entries_;
2832ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
2842ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    cue_entries_ = cues;
2852ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    cue_entries_capacity_ = new_capacity;
2862ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  }
2872ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
2882ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  cue->set_output_block_number(output_block_number_);
2892ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  cue_entries_[cue_entries_size_++] = cue;
2902ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  return true;
2912ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian}
2922ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
2932ec72e65689c948e92b826ae1e867bf369e72f13Vignesh VenkatasubramanianCuePoint* Cues::GetCueByIndex(int32 index) const {
2942ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (cue_entries_ == NULL)
2952ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return NULL;
2962ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
2972ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (index >= cue_entries_size_)
2982ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return NULL;
2992ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
3002ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  return cue_entries_[index];
3012ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian}
3022ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
3032ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanianuint64 Cues::Size() {
3042ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  uint64 size = 0;
3052ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  for (int32 i = 0; i < cue_entries_size_; ++i)
3062ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    size += GetCueByIndex(i)->Size();
3072ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  size += EbmlMasterElementSize(kMkvCues, size);
3082ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  return size;
3092ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian}
3102ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
3112ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanianbool Cues::Write(IMkvWriter* writer) const {
3122ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (!writer)
3132ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return false;
3142ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
3152ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  uint64 size = 0;
3162ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  for (int32 i = 0; i < cue_entries_size_; ++i) {
3172ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    const CuePoint* const cue = GetCueByIndex(i);
3182ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
3192ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    if (!cue)
3202ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      return false;
3212ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
3222ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    size += cue->Size();
3232ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  }
3242ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
3252ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (!WriteEbmlMasterElement(writer, kMkvCues, size))
3262ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return false;
3272ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
3282ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  const int64 payload_position = writer->Position();
3292ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (payload_position < 0)
3302ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return false;
3312ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
3322ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  for (int32 i = 0; i < cue_entries_size_; ++i) {
3332ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    const CuePoint* const cue = GetCueByIndex(i);
3342ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
3352ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    if (!cue->Write(writer))
3362ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      return false;
3372ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  }
3382ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
3392ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  const int64 stop_position = writer->Position();
3402ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (stop_position < 0)
3412ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return false;
3422ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
3432ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (stop_position - payload_position != static_cast<int64>(size))
3442ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return false;
3452ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
3462ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  return true;
3472ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian}
3482ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
3492ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian///////////////////////////////////////////////////////////////
3502ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian//
3512ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian// ContentEncAESSettings Class
3522ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
3532ec72e65689c948e92b826ae1e867bf369e72f13Vignesh VenkatasubramanianContentEncAESSettings::ContentEncAESSettings() : cipher_mode_(kCTR) {}
3542ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
3552ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanianuint64 ContentEncAESSettings::Size() const {
3562ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  const uint64 payload = PayloadSize();
3572ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  const uint64 size =
3582ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      EbmlMasterElementSize(kMkvContentEncAESSettings, payload) + payload;
3592ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  return size;
3602ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian}
3612ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
3622ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanianbool ContentEncAESSettings::Write(IMkvWriter* writer) const {
3632ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  const uint64 payload = PayloadSize();
3642ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
3652ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (!WriteEbmlMasterElement(writer, kMkvContentEncAESSettings, payload))
3662ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return false;
3672ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
3682ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  const int64 payload_position = writer->Position();
3692ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (payload_position < 0)
3702ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return false;
3712ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
3722ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (!WriteEbmlElement(writer, kMkvAESSettingsCipherMode, cipher_mode_))
3732ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return false;
3742ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
3752ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  const int64 stop_position = writer->Position();
3762ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (stop_position < 0 ||
3772ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      stop_position - payload_position != static_cast<int64>(payload))
3782ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return false;
3792ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
3802ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  return true;
3812ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian}
3822ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
3832ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanianuint64 ContentEncAESSettings::PayloadSize() const {
3842ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  uint64 size = EbmlElementSize(kMkvAESSettingsCipherMode, cipher_mode_);
3852ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  return size;
3862ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian}
3872ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
3882ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian///////////////////////////////////////////////////////////////
3892ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian//
3902ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian// ContentEncoding Class
3912ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
3922ec72e65689c948e92b826ae1e867bf369e72f13Vignesh VenkatasubramanianContentEncoding::ContentEncoding()
3932ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    : enc_algo_(5),
3942ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      enc_key_id_(NULL),
3952ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      encoding_order_(0),
3962ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      encoding_scope_(1),
3972ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      encoding_type_(1),
398ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      enc_key_id_length_(0) {}
3992ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
400ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh VenkatasubramanianContentEncoding::~ContentEncoding() { delete[] enc_key_id_; }
4012ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
4022ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanianbool ContentEncoding::SetEncryptionID(const uint8* id, uint64 length) {
4032ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (!id || length < 1)
4042ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return false;
4052ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
406ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  delete[] enc_key_id_;
4072ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
4082ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  enc_key_id_ =
4092ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      new (std::nothrow) uint8[static_cast<size_t>(length)];  // NOLINT
4102ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (!enc_key_id_)
4112ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return false;
4122ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
4132ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  memcpy(enc_key_id_, id, static_cast<size_t>(length));
4142ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  enc_key_id_length_ = length;
4152ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
4162ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  return true;
4172ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian}
4182ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
4192ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanianuint64 ContentEncoding::Size() const {
4202ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  const uint64 encryption_size = EncryptionSize();
4212ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  const uint64 encoding_size = EncodingSize(0, encryption_size);
422ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  const uint64 encodings_size =
423ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      EbmlMasterElementSize(kMkvContentEncoding, encoding_size) + encoding_size;
4242ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
4252ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  return encodings_size;
4262ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian}
4272ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
4282ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanianbool ContentEncoding::Write(IMkvWriter* writer) const {
4292ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  const uint64 encryption_size = EncryptionSize();
4302ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  const uint64 encoding_size = EncodingSize(0, encryption_size);
431ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  const uint64 size =
432ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      EbmlMasterElementSize(kMkvContentEncoding, encoding_size) + encoding_size;
4332ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
4342ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  const int64 payload_position = writer->Position();
4352ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (payload_position < 0)
4362ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return false;
4372ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
4382ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (!WriteEbmlMasterElement(writer, kMkvContentEncoding, encoding_size))
4392ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return false;
4402ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (!WriteEbmlElement(writer, kMkvContentEncodingOrder, encoding_order_))
4412ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return false;
4422ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (!WriteEbmlElement(writer, kMkvContentEncodingScope, encoding_scope_))
4432ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return false;
4442ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (!WriteEbmlElement(writer, kMkvContentEncodingType, encoding_type_))
4452ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return false;
4462ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
4472ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (!WriteEbmlMasterElement(writer, kMkvContentEncryption, encryption_size))
4482ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return false;
4492ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (!WriteEbmlElement(writer, kMkvContentEncAlgo, enc_algo_))
4502ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return false;
451ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (!WriteEbmlElement(writer, kMkvContentEncKeyID, enc_key_id_,
4522ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian                        enc_key_id_length_))
4532ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return false;
4542ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
4552ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (!enc_aes_settings_.Write(writer))
4562ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return false;
4572ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
4582ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  const int64 stop_position = writer->Position();
4592ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (stop_position < 0 ||
4602ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      stop_position - payload_position != static_cast<int64>(size))
4612ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return false;
4622ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
4632ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  return true;
4642ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian}
4652ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
4662ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanianuint64 ContentEncoding::EncodingSize(uint64 compresion_size,
4672ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian                                     uint64 encryption_size) const {
4682ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  // TODO(fgalligan): Add support for compression settings.
4692ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (compresion_size != 0)
4702ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return 0;
4712ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
4722ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  uint64 encoding_size = 0;
4732ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
4742ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (encryption_size > 0) {
475ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    encoding_size +=
476ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian        EbmlMasterElementSize(kMkvContentEncryption, encryption_size) +
477ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian        encryption_size;
4782ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  }
4792ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  encoding_size += EbmlElementSize(kMkvContentEncodingType, encoding_type_);
4802ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  encoding_size += EbmlElementSize(kMkvContentEncodingScope, encoding_scope_);
4812ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  encoding_size += EbmlElementSize(kMkvContentEncodingOrder, encoding_order_);
4822ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
4832ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  return encoding_size;
4842ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian}
4852ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
4862ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanianuint64 ContentEncoding::EncryptionSize() const {
4872ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  const uint64 aes_size = enc_aes_settings_.Size();
4882ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
489ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  uint64 encryption_size =
490ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      EbmlElementSize(kMkvContentEncKeyID, enc_key_id_, enc_key_id_length_);
4912ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  encryption_size += EbmlElementSize(kMkvContentEncAlgo, enc_algo_);
4922ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
4932ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  return encryption_size + aes_size;
4942ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian}
4952ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
4962ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian///////////////////////////////////////////////////////////////
4972ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian//
4982ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian// Track Class
4992ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
5002ec72e65689c948e92b826ae1e867bf369e72f13Vignesh VenkatasubramanianTrack::Track(unsigned int* seed)
5012ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    : codec_id_(NULL),
5022ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      codec_private_(NULL),
5032ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      language_(NULL),
5042ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      max_block_additional_id_(0),
5052ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      name_(NULL),
5062ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      number_(0),
5072ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      type_(0),
5082ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      uid_(MakeUID(seed)),
5092ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      codec_delay_(0),
5102ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      seek_pre_roll_(0),
511ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      default_duration_(0),
5122ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      codec_private_length_(0),
5132ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      content_encoding_entries_(NULL),
514ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      content_encoding_entries_size_(0) {}
5152ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
5162ec72e65689c948e92b826ae1e867bf369e72f13Vignesh VenkatasubramanianTrack::~Track() {
517ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  delete[] codec_id_;
518ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  delete[] codec_private_;
519ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  delete[] language_;
520ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  delete[] name_;
5212ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
5222ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (content_encoding_entries_) {
5232ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    for (uint32 i = 0; i < content_encoding_entries_size_; ++i) {
5242ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      ContentEncoding* const encoding = content_encoding_entries_[i];
5252ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      delete encoding;
5262ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    }
527ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    delete[] content_encoding_entries_;
5282ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  }
5292ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian}
5302ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
5312ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanianbool Track::AddContentEncoding() {
5322ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  const uint32 count = content_encoding_entries_size_ + 1;
5332ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
5342ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  ContentEncoding** const content_encoding_entries =
535ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      new (std::nothrow) ContentEncoding* [count];  // NOLINT
5362ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (!content_encoding_entries)
5372ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return false;
5382ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
5392ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  ContentEncoding* const content_encoding =
5402ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      new (std::nothrow) ContentEncoding();  // NOLINT
5412ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (!content_encoding) {
542ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    delete[] content_encoding_entries;
5432ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return false;
5442ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  }
5452ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
5462ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  for (uint32 i = 0; i < content_encoding_entries_size_; ++i) {
5472ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    content_encoding_entries[i] = content_encoding_entries_[i];
5482ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  }
5492ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
550ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  delete[] content_encoding_entries_;
5512ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
5522ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  content_encoding_entries_ = content_encoding_entries;
5532ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  content_encoding_entries_[content_encoding_entries_size_] = content_encoding;
5542ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  content_encoding_entries_size_ = count;
5552ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  return true;
5562ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian}
5572ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
5582ec72e65689c948e92b826ae1e867bf369e72f13Vignesh VenkatasubramanianContentEncoding* Track::GetContentEncodingByIndex(uint32 index) const {
5592ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (content_encoding_entries_ == NULL)
5602ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return NULL;
5612ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
5622ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (index >= content_encoding_entries_size_)
5632ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return NULL;
5642ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
5652ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  return content_encoding_entries_[index];
5662ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian}
5672ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
5682ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanianuint64 Track::PayloadSize() const {
5692ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  uint64 size = EbmlElementSize(kMkvTrackNumber, number_);
5702ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  size += EbmlElementSize(kMkvTrackUID, uid_);
5712ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  size += EbmlElementSize(kMkvTrackType, type_);
5722ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (codec_id_)
5732ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    size += EbmlElementSize(kMkvCodecID, codec_id_);
5742ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (codec_private_)
575ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    size += EbmlElementSize(kMkvCodecPrivate, codec_private_,
5762ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian                            codec_private_length_);
5772ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (language_)
5782ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    size += EbmlElementSize(kMkvLanguage, language_);
5792ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (name_)
5802ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    size += EbmlElementSize(kMkvName, name_);
5812ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (max_block_additional_id_)
5822ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    size += EbmlElementSize(kMkvMaxBlockAdditionID, max_block_additional_id_);
5832ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (codec_delay_)
5842ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    size += EbmlElementSize(kMkvCodecDelay, codec_delay_);
5852ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (seek_pre_roll_)
5862ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    size += EbmlElementSize(kMkvSeekPreRoll, seek_pre_roll_);
587ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (default_duration_)
588ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    size += EbmlElementSize(kMkvDefaultDuration, default_duration_);
5892ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
5902ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (content_encoding_entries_size_ > 0) {
5912ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    uint64 content_encodings_size = 0;
5922ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    for (uint32 i = 0; i < content_encoding_entries_size_; ++i) {
5932ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      ContentEncoding* const encoding = content_encoding_entries_[i];
5942ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      content_encodings_size += encoding->Size();
5952ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    }
5962ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
597ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    size +=
598ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian        EbmlMasterElementSize(kMkvContentEncodings, content_encodings_size) +
599ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian        content_encodings_size;
6002ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  }
6012ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
6022ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  return size;
6032ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian}
6042ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
6052ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanianuint64 Track::Size() const {
6062ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  uint64 size = PayloadSize();
6072ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  size += EbmlMasterElementSize(kMkvTrackEntry, size);
6082ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  return size;
6092ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian}
6102ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
6112ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanianbool Track::Write(IMkvWriter* writer) const {
6122ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (!writer)
6132ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return false;
6142ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
6152ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  // |size| may be bigger than what is written out in this function because
6162ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  // derived classes may write out more data in the Track element.
6172ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  const uint64 payload_size = PayloadSize();
6182ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
6192ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (!WriteEbmlMasterElement(writer, kMkvTrackEntry, payload_size))
6202ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return false;
6212ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
622ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  // |type_| has to be specified before the Track can be written.
623ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (!type_)
624ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    return false;
625ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
6262ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  uint64 size = EbmlElementSize(kMkvTrackNumber, number_);
6272ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  size += EbmlElementSize(kMkvTrackUID, uid_);
6282ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  size += EbmlElementSize(kMkvTrackType, type_);
6292ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (codec_id_)
6302ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    size += EbmlElementSize(kMkvCodecID, codec_id_);
6312ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (codec_private_)
632ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    size += EbmlElementSize(kMkvCodecPrivate, codec_private_,
6332ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian                            codec_private_length_);
6342ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (language_)
6352ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    size += EbmlElementSize(kMkvLanguage, language_);
6362ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (name_)
6372ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    size += EbmlElementSize(kMkvName, name_);
6382ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (max_block_additional_id_)
6392ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    size += EbmlElementSize(kMkvMaxBlockAdditionID, max_block_additional_id_);
6402ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (codec_delay_)
6412ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    size += EbmlElementSize(kMkvCodecDelay, codec_delay_);
6422ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (seek_pre_roll_)
6432ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    size += EbmlElementSize(kMkvSeekPreRoll, seek_pre_roll_);
644ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (default_duration_)
645ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    size += EbmlElementSize(kMkvDefaultDuration, default_duration_);
6462ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
6472ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  const int64 payload_position = writer->Position();
6482ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (payload_position < 0)
6492ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return false;
6502ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
6512ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (!WriteEbmlElement(writer, kMkvTrackNumber, number_))
6522ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return false;
6532ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (!WriteEbmlElement(writer, kMkvTrackUID, uid_))
6542ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return false;
6552ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (!WriteEbmlElement(writer, kMkvTrackType, type_))
6562ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return false;
6572ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (max_block_additional_id_) {
658ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    if (!WriteEbmlElement(writer, kMkvMaxBlockAdditionID,
6592ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian                          max_block_additional_id_)) {
6602ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      return false;
6612ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    }
6622ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  }
6632ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (codec_delay_) {
6642ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    if (!WriteEbmlElement(writer, kMkvCodecDelay, codec_delay_))
6652ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      return false;
6662ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  }
6672ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (seek_pre_roll_) {
6682ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    if (!WriteEbmlElement(writer, kMkvSeekPreRoll, seek_pre_roll_))
6692ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      return false;
6702ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  }
671ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (default_duration_) {
672ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    if (!WriteEbmlElement(writer, kMkvDefaultDuration, default_duration_))
673ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      return false;
674ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
6752ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (codec_id_) {
6762ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    if (!WriteEbmlElement(writer, kMkvCodecID, codec_id_))
6772ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      return false;
6782ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  }
6792ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (codec_private_) {
680ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    if (!WriteEbmlElement(writer, kMkvCodecPrivate, codec_private_,
6812ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian                          codec_private_length_))
6822ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      return false;
6832ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  }
6842ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (language_) {
6852ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    if (!WriteEbmlElement(writer, kMkvLanguage, language_))
6862ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      return false;
6872ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  }
6882ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (name_) {
6892ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    if (!WriteEbmlElement(writer, kMkvName, name_))
6902ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      return false;
6912ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  }
6922ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
6932ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  int64 stop_position = writer->Position();
6942ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (stop_position < 0 ||
6952ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      stop_position - payload_position != static_cast<int64>(size))
6962ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return false;
6972ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
6982ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (content_encoding_entries_size_ > 0) {
6992ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    uint64 content_encodings_size = 0;
7002ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    for (uint32 i = 0; i < content_encoding_entries_size_; ++i) {
7012ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      ContentEncoding* const encoding = content_encoding_entries_[i];
7022ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      content_encodings_size += encoding->Size();
7032ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    }
7042ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
705ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    if (!WriteEbmlMasterElement(writer, kMkvContentEncodings,
7062ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian                                content_encodings_size))
7072ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      return false;
7082ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
7092ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    for (uint32 i = 0; i < content_encoding_entries_size_; ++i) {
7102ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      ContentEncoding* const encoding = content_encoding_entries_[i];
7112ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      if (!encoding->Write(writer))
7122ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian        return false;
7132ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    }
7142ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  }
7152ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
7162ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  stop_position = writer->Position();
7172ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (stop_position < 0)
7182ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return false;
7192ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  return true;
7202ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian}
7212ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
7222ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanianbool Track::SetCodecPrivate(const uint8* codec_private, uint64 length) {
7232ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (!codec_private || length < 1)
7242ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return false;
7252ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
726ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  delete[] codec_private_;
7272ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
7282ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  codec_private_ =
7292ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      new (std::nothrow) uint8[static_cast<size_t>(length)];  // NOLINT
7302ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (!codec_private_)
7312ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return false;
7322ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
7332ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  memcpy(codec_private_, codec_private, static_cast<size_t>(length));
7342ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  codec_private_length_ = length;
7352ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
7362ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  return true;
7372ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian}
7382ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
7392ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanianvoid Track::set_codec_id(const char* codec_id) {
7402ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (codec_id) {
741ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    delete[] codec_id_;
7422ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
7432ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    const size_t length = strlen(codec_id) + 1;
7442ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    codec_id_ = new (std::nothrow) char[length];  // NOLINT
7452ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    if (codec_id_) {
7462ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian#ifdef _MSC_VER
7472ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      strcpy_s(codec_id_, length, codec_id);
7482ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian#else
7492ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      strcpy(codec_id_, codec_id);
7502ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian#endif
7512ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    }
7522ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  }
7532ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian}
7542ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
7552ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian// TODO(fgalligan): Vet the language parameter.
7562ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanianvoid Track::set_language(const char* language) {
7572ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (language) {
758ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    delete[] language_;
7592ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
7602ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    const size_t length = strlen(language) + 1;
7612ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    language_ = new (std::nothrow) char[length];  // NOLINT
7622ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    if (language_) {
7632ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian#ifdef _MSC_VER
7642ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      strcpy_s(language_, length, language);
7652ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian#else
7662ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      strcpy(language_, language);
7672ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian#endif
7682ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    }
7692ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  }
7702ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian}
7712ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
7722ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanianvoid Track::set_name(const char* name) {
7732ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (name) {
774ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    delete[] name_;
7752ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
7762ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    const size_t length = strlen(name) + 1;
7772ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    name_ = new (std::nothrow) char[length];  // NOLINT
7782ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    if (name_) {
7792ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian#ifdef _MSC_VER
7802ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      strcpy_s(name_, length, name);
7812ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian#else
7822ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      strcpy(name_, name);
7832ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian#endif
7842ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    }
7852ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  }
7862ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian}
7872ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
7882ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian///////////////////////////////////////////////////////////////
7892ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian//
7902ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian// VideoTrack Class
7912ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
7922ec72e65689c948e92b826ae1e867bf369e72f13Vignesh VenkatasubramanianVideoTrack::VideoTrack(unsigned int* seed)
7932ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    : Track(seed),
7942ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      display_height_(0),
7952ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      display_width_(0),
7962ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      frame_rate_(0.0),
7972ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      height_(0),
7982ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      stereo_mode_(0),
7992ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      alpha_mode_(0),
800ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      width_(0) {}
8012ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
802ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh VenkatasubramanianVideoTrack::~VideoTrack() {}
8032ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
8042ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanianbool VideoTrack::SetStereoMode(uint64 stereo_mode) {
805ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (stereo_mode != kMono && stereo_mode != kSideBySideLeftIsFirst &&
8062ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      stereo_mode != kTopBottomRightIsFirst &&
8072ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      stereo_mode != kTopBottomLeftIsFirst &&
8082ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      stereo_mode != kSideBySideRightIsFirst)
8092ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return false;
8102ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
8112ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  stereo_mode_ = stereo_mode;
8122ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  return true;
8132ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian}
8142ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
8152ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanianbool VideoTrack::SetAlphaMode(uint64 alpha_mode) {
816ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (alpha_mode != kNoAlpha && alpha_mode != kAlpha)
8172ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return false;
8182ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
8192ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  alpha_mode_ = alpha_mode;
8202ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  return true;
8212ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian}
8222ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
8232ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanianuint64 VideoTrack::PayloadSize() const {
8242ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  const uint64 parent_size = Track::PayloadSize();
8252ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
8262ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  uint64 size = VideoPayloadSize();
8272ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  size += EbmlMasterElementSize(kMkvVideo, size);
8282ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
8292ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  return parent_size + size;
8302ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian}
8312ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
8322ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanianbool VideoTrack::Write(IMkvWriter* writer) const {
8332ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (!Track::Write(writer))
8342ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return false;
8352ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
8362ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  const uint64 size = VideoPayloadSize();
8372ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
8382ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (!WriteEbmlMasterElement(writer, kMkvVideo, size))
8392ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return false;
8402ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
8412ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  const int64 payload_position = writer->Position();
8422ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (payload_position < 0)
8432ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return false;
8442ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
8452ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (!WriteEbmlElement(writer, kMkvPixelWidth, width_))
8462ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return false;
8472ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (!WriteEbmlElement(writer, kMkvPixelHeight, height_))
8482ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return false;
8492ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (display_width_ > 0)
8502ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    if (!WriteEbmlElement(writer, kMkvDisplayWidth, display_width_))
8512ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      return false;
8522ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (display_height_ > 0)
8532ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    if (!WriteEbmlElement(writer, kMkvDisplayHeight, display_height_))
8542ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      return false;
8552ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (stereo_mode_ > kMono)
8562ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    if (!WriteEbmlElement(writer, kMkvStereoMode, stereo_mode_))
8572ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      return false;
8582ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (alpha_mode_ > kNoAlpha)
8592ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    if (!WriteEbmlElement(writer, kMkvAlphaMode, alpha_mode_))
8602ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      return false;
8612ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (frame_rate_ > 0.0)
862ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    if (!WriteEbmlElement(writer, kMkvFrameRate,
8632ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian                          static_cast<float>(frame_rate_)))
8642ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      return false;
8652ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
8662ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  const int64 stop_position = writer->Position();
8672ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (stop_position < 0 ||
8682ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      stop_position - payload_position != static_cast<int64>(size))
8692ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return false;
8702ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
8712ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  return true;
8722ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian}
8732ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
8742ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanianuint64 VideoTrack::VideoPayloadSize() const {
8752ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  uint64 size = EbmlElementSize(kMkvPixelWidth, width_);
8762ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  size += EbmlElementSize(kMkvPixelHeight, height_);
8772ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (display_width_ > 0)
8782ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    size += EbmlElementSize(kMkvDisplayWidth, display_width_);
8792ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (display_height_ > 0)
8802ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    size += EbmlElementSize(kMkvDisplayHeight, display_height_);
8812ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (stereo_mode_ > kMono)
8822ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    size += EbmlElementSize(kMkvStereoMode, stereo_mode_);
8832ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (alpha_mode_ > kNoAlpha)
8842ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    size += EbmlElementSize(kMkvAlphaMode, alpha_mode_);
8852ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (frame_rate_ > 0.0)
8862ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    size += EbmlElementSize(kMkvFrameRate, static_cast<float>(frame_rate_));
8872ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
8882ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  return size;
8892ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian}
8902ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
8912ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian///////////////////////////////////////////////////////////////
8922ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian//
8932ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian// AudioTrack Class
8942ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
8952ec72e65689c948e92b826ae1e867bf369e72f13Vignesh VenkatasubramanianAudioTrack::AudioTrack(unsigned int* seed)
896ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    : Track(seed), bit_depth_(0), channels_(1), sample_rate_(0.0) {}
8972ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
898ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh VenkatasubramanianAudioTrack::~AudioTrack() {}
8992ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
9002ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanianuint64 AudioTrack::PayloadSize() const {
9012ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  const uint64 parent_size = Track::PayloadSize();
9022ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
903ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  uint64 size =
904ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      EbmlElementSize(kMkvSamplingFrequency, static_cast<float>(sample_rate_));
9052ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  size += EbmlElementSize(kMkvChannels, channels_);
9062ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (bit_depth_ > 0)
9072ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    size += EbmlElementSize(kMkvBitDepth, bit_depth_);
9082ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  size += EbmlMasterElementSize(kMkvAudio, size);
9092ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
9102ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  return parent_size + size;
9112ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian}
9122ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
9132ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanianbool AudioTrack::Write(IMkvWriter* writer) const {
9142ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (!Track::Write(writer))
9152ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return false;
9162ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
9172ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  // Calculate AudioSettings size.
918ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  uint64 size =
919ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      EbmlElementSize(kMkvSamplingFrequency, static_cast<float>(sample_rate_));
9202ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  size += EbmlElementSize(kMkvChannels, channels_);
9212ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (bit_depth_ > 0)
9222ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    size += EbmlElementSize(kMkvBitDepth, bit_depth_);
9232ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
9242ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (!WriteEbmlMasterElement(writer, kMkvAudio, size))
9252ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return false;
9262ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
9272ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  const int64 payload_position = writer->Position();
9282ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (payload_position < 0)
9292ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return false;
9302ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
931ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (!WriteEbmlElement(writer, kMkvSamplingFrequency,
9322ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian                        static_cast<float>(sample_rate_)))
9332ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return false;
9342ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (!WriteEbmlElement(writer, kMkvChannels, channels_))
9352ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return false;
9362ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (bit_depth_ > 0)
9372ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    if (!WriteEbmlElement(writer, kMkvBitDepth, bit_depth_))
9382ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      return false;
9392ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
9402ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  const int64 stop_position = writer->Position();
9412ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (stop_position < 0 ||
9422ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      stop_position - payload_position != static_cast<int64>(size))
9432ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return false;
9442ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
9452ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  return true;
9462ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian}
9472ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
9482ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian///////////////////////////////////////////////////////////////
9492ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian//
9502ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian// Tracks Class
9512ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
9522ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanianconst char Tracks::kOpusCodecId[] = "A_OPUS";
9532ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanianconst char Tracks::kVorbisCodecId[] = "A_VORBIS";
9542ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanianconst char Tracks::kVp8CodecId[] = "V_VP8";
9552ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanianconst char Tracks::kVp9CodecId[] = "V_VP9";
9562ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
957ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh VenkatasubramanianTracks::Tracks() : track_entries_(NULL), track_entries_size_(0) {}
9582ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
9592ec72e65689c948e92b826ae1e867bf369e72f13Vignesh VenkatasubramanianTracks::~Tracks() {
9602ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (track_entries_) {
9612ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    for (uint32 i = 0; i < track_entries_size_; ++i) {
9622ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      Track* const track = track_entries_[i];
9632ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      delete track;
9642ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    }
965ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    delete[] track_entries_;
9662ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  }
9672ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian}
9682ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
9692ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanianbool Tracks::AddTrack(Track* track, int32 number) {
9702ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (number < 0)
9712ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return false;
9722ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
9732ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  // This muxer only supports track numbers in the range [1, 126], in
9742ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  // order to be able (to use Matroska integer representation) to
9752ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  // serialize the block header (of which the track number is a part)
9762ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  // for a frame using exactly 4 bytes.
9772ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
9782ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (number > 0x7E)
9792ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return false;
9802ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
9812ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  uint32 track_num = number;
9822ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
9832ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (track_num > 0) {
9842ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    // Check to make sure a track does not already have |track_num|.
9852ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    for (uint32 i = 0; i < track_entries_size_; ++i) {
9862ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      if (track_entries_[i]->number() == track_num)
9872ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian        return false;
9882ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    }
9892ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  }
9902ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
9912ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  const uint32 count = track_entries_size_ + 1;
9922ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
993ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  Track** const track_entries = new (std::nothrow) Track* [count];  // NOLINT
9942ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (!track_entries)
9952ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return false;
9962ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
9972ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  for (uint32 i = 0; i < track_entries_size_; ++i) {
9982ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    track_entries[i] = track_entries_[i];
9992ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  }
10002ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
1001ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  delete[] track_entries_;
10022ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
10032ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  // Find the lowest availible track number > 0.
10042ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (track_num == 0) {
10052ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    track_num = count;
10062ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
10072ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    // Check to make sure a track does not already have |track_num|.
10082ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    bool exit = false;
10092ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    do {
10102ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      exit = true;
10112ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      for (uint32 i = 0; i < track_entries_size_; ++i) {
10122ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian        if (track_entries[i]->number() == track_num) {
10132ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian          track_num++;
10142ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian          exit = false;
10152ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian          break;
10162ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian        }
10172ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      }
10182ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    } while (!exit);
10192ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  }
10202ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  track->set_number(track_num);
10212ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
10222ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  track_entries_ = track_entries;
10232ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  track_entries_[track_entries_size_] = track;
10242ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  track_entries_size_ = count;
10252ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  return true;
10262ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian}
10272ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
10282ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanianconst Track* Tracks::GetTrackByIndex(uint32 index) const {
10292ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (track_entries_ == NULL)
10302ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return NULL;
10312ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
10322ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (index >= track_entries_size_)
10332ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return NULL;
10342ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
10352ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  return track_entries_[index];
10362ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian}
10372ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
10382ec72e65689c948e92b826ae1e867bf369e72f13Vignesh VenkatasubramanianTrack* Tracks::GetTrackByNumber(uint64 track_number) const {
10392ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  const int32 count = track_entries_size();
10402ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  for (int32 i = 0; i < count; ++i) {
10412ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    if (track_entries_[i]->number() == track_number)
10422ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      return track_entries_[i];
10432ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  }
10442ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
10452ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  return NULL;
10462ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian}
10472ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
10482ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanianbool Tracks::TrackIsAudio(uint64 track_number) const {
10492ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  const Track* const track = GetTrackByNumber(track_number);
10502ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
10512ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (track->type() == kAudio)
10522ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return true;
10532ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
10542ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  return false;
10552ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian}
10562ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
10572ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanianbool Tracks::TrackIsVideo(uint64 track_number) const {
10582ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  const Track* const track = GetTrackByNumber(track_number);
10592ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
10602ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (track->type() == kVideo)
10612ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return true;
10622ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
10632ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  return false;
10642ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian}
10652ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
10662ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanianbool Tracks::Write(IMkvWriter* writer) const {
10672ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  uint64 size = 0;
10682ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  const int32 count = track_entries_size();
10692ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  for (int32 i = 0; i < count; ++i) {
10702ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    const Track* const track = GetTrackByIndex(i);
10712ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
10722ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    if (!track)
10732ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      return false;
10742ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
10752ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    size += track->Size();
10762ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  }
10772ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
10782ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (!WriteEbmlMasterElement(writer, kMkvTracks, size))
10792ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return false;
10802ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
10812ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  const int64 payload_position = writer->Position();
10822ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (payload_position < 0)
10832ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return false;
10842ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
10852ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  for (int32 i = 0; i < count; ++i) {
10862ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    const Track* const track = GetTrackByIndex(i);
10872ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    if (!track->Write(writer))
10882ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      return false;
10892ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  }
10902ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
10912ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  const int64 stop_position = writer->Position();
10922ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (stop_position < 0 ||
10932ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      stop_position - payload_position != static_cast<int64>(size))
10942ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return false;
10952ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
10962ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  return true;
10972ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian}
10982ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
10992ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian///////////////////////////////////////////////////////////////
11002ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian//
11012ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian// Chapter Class
11022ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
1103ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanianbool Chapter::set_id(const char* id) { return StrCpy(id, &id_); }
11042ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
1105ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanianvoid Chapter::set_time(const Segment& segment, uint64 start_ns, uint64 end_ns) {
11062ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  const SegmentInfo* const info = segment.GetSegmentInfo();
11072ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  const uint64 timecode_scale = info->timecode_scale();
11082ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  start_timecode_ = start_ns / timecode_scale;
11092ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  end_timecode_ = end_ns / timecode_scale;
11102ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian}
11112ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
1112ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanianbool Chapter::add_string(const char* title, const char* language,
11132ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian                         const char* country) {
11142ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (!ExpandDisplaysArray())
11152ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return false;
11162ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
11172ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  Display& d = displays_[displays_count_++];
11182ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  d.Init();
11192ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
11202ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (!d.set_title(title))
11212ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return false;
11222ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
11232ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (!d.set_language(language))
11242ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return false;
11252ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
11262ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (!d.set_country(country))
11272ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return false;
11282ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
11292ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  return true;
11302ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian}
11312ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
11322ec72e65689c948e92b826ae1e867bf369e72f13Vignesh VenkatasubramanianChapter::Chapter() {
11332ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  // This ctor only constructs the object.  Proper initialization is
11342ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  // done in Init() (called in Chapters::AddChapter()).  The only
11352ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  // reason we bother implementing this ctor is because we had to
11362ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  // declare it as private (along with the dtor), in order to prevent
11372ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  // clients from creating Chapter instances (a privelege we grant
11382ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  // only to the Chapters class).  Doing no initialization here also
11392ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  // means that creating arrays of chapter objects is more efficient,
11402ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  // because we only initialize each new chapter object as it becomes
11412ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  // active on the array.
11422ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian}
11432ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
1144ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh VenkatasubramanianChapter::~Chapter() {}
11452ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
11462ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanianvoid Chapter::Init(unsigned int* seed) {
11472ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  id_ = NULL;
11482ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  displays_ = NULL;
11492ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  displays_size_ = 0;
11502ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  displays_count_ = 0;
11512ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  uid_ = MakeUID(seed);
11522ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian}
11532ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
11542ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanianvoid Chapter::ShallowCopy(Chapter* dst) const {
11552ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  dst->id_ = id_;
11562ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  dst->start_timecode_ = start_timecode_;
11572ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  dst->end_timecode_ = end_timecode_;
11582ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  dst->uid_ = uid_;
11592ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  dst->displays_ = displays_;
11602ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  dst->displays_size_ = displays_size_;
11612ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  dst->displays_count_ = displays_count_;
11622ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian}
11632ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
11642ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanianvoid Chapter::Clear() {
11652ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  StrCpy(NULL, &id_);
11662ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
11672ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  while (displays_count_ > 0) {
11682ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    Display& d = displays_[--displays_count_];
11692ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    d.Clear();
11702ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  }
11712ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
1172ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  delete[] displays_;
11732ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  displays_ = NULL;
11742ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
11752ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  displays_size_ = 0;
11762ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian}
11772ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
11782ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanianbool Chapter::ExpandDisplaysArray() {
11792ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (displays_size_ > displays_count_)
11802ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return true;  // nothing to do yet
11812ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
11822ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  const int size = (displays_size_ == 0) ? 1 : 2 * displays_size_;
11832ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
11842ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  Display* const displays = new (std::nothrow) Display[size];  // NOLINT
11852ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (displays == NULL)
11862ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return false;
11872ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
11882ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  for (int idx = 0; idx < displays_count_; ++idx) {
11892ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    displays[idx] = displays_[idx];  // shallow copy
11902ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  }
11912ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
1192ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  delete[] displays_;
11932ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
11942ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  displays_ = displays;
11952ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  displays_size_ = size;
11962ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
11972ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  return true;
11982ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian}
11992ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
12002ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanianuint64 Chapter::WriteAtom(IMkvWriter* writer) const {
1201ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  uint64 payload_size = EbmlElementSize(kMkvChapterStringUID, id_) +
1202ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                        EbmlElementSize(kMkvChapterUID, uid_) +
1203ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                        EbmlElementSize(kMkvChapterTimeStart, start_timecode_) +
1204ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                        EbmlElementSize(kMkvChapterTimeEnd, end_timecode_);
12052ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
12062ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  for (int idx = 0; idx < displays_count_; ++idx) {
12072ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    const Display& d = displays_[idx];
12082ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    payload_size += d.WriteDisplay(NULL);
12092ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  }
12102ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
12112ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  const uint64 atom_size =
1212ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      EbmlMasterElementSize(kMkvChapterAtom, payload_size) + payload_size;
12132ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
12142ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (writer == NULL)
12152ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return atom_size;
12162ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
12172ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  const int64 start = writer->Position();
12182ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
12192ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (!WriteEbmlMasterElement(writer, kMkvChapterAtom, payload_size))
12202ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return 0;
12212ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
12222ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (!WriteEbmlElement(writer, kMkvChapterStringUID, id_))
12232ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return 0;
12242ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
12252ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (!WriteEbmlElement(writer, kMkvChapterUID, uid_))
12262ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return 0;
12272ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
12282ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (!WriteEbmlElement(writer, kMkvChapterTimeStart, start_timecode_))
12292ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return 0;
12302ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
12312ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (!WriteEbmlElement(writer, kMkvChapterTimeEnd, end_timecode_))
12322ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return 0;
12332ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
12342ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  for (int idx = 0; idx < displays_count_; ++idx) {
12352ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    const Display& d = displays_[idx];
12362ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
12372ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    if (!d.WriteDisplay(writer))
12382ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      return 0;
12392ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  }
12402ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
12412ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  const int64 stop = writer->Position();
12422ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
12432ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (stop >= start && uint64(stop - start) != atom_size)
12442ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return 0;
12452ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
12462ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  return atom_size;
12472ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian}
12482ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
12492ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanianvoid Chapter::Display::Init() {
12502ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  title_ = NULL;
12512ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  language_ = NULL;
12522ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  country_ = NULL;
12532ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian}
12542ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
12552ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanianvoid Chapter::Display::Clear() {
12562ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  StrCpy(NULL, &title_);
12572ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  StrCpy(NULL, &language_);
12582ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  StrCpy(NULL, &country_);
12592ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian}
12602ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
12612ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanianbool Chapter::Display::set_title(const char* title) {
12622ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  return StrCpy(title, &title_);
12632ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian}
12642ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
12652ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanianbool Chapter::Display::set_language(const char* language) {
12662ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  return StrCpy(language, &language_);
12672ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian}
12682ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
12692ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanianbool Chapter::Display::set_country(const char* country) {
12702ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  return StrCpy(country, &country_);
12712ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian}
12722ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
12732ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanianuint64 Chapter::Display::WriteDisplay(IMkvWriter* writer) const {
12742ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  uint64 payload_size = EbmlElementSize(kMkvChapString, title_);
12752ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
12762ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (language_)
12772ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    payload_size += EbmlElementSize(kMkvChapLanguage, language_);
12782ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
12792ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (country_)
12802ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    payload_size += EbmlElementSize(kMkvChapCountry, country_);
12812ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
12822ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  const uint64 display_size =
1283ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      EbmlMasterElementSize(kMkvChapterDisplay, payload_size) + payload_size;
12842ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
12852ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (writer == NULL)
12862ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return display_size;
12872ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
12882ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  const int64 start = writer->Position();
12892ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
12902ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (!WriteEbmlMasterElement(writer, kMkvChapterDisplay, payload_size))
12912ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return 0;
12922ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
12932ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (!WriteEbmlElement(writer, kMkvChapString, title_))
12942ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return 0;
12952ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
12962ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (language_) {
12972ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    if (!WriteEbmlElement(writer, kMkvChapLanguage, language_))
12982ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      return 0;
12992ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  }
13002ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
13012ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (country_) {
13022ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    if (!WriteEbmlElement(writer, kMkvChapCountry, country_))
13032ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      return 0;
13042ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  }
13052ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
13062ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  const int64 stop = writer->Position();
13072ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
13082ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (stop >= start && uint64(stop - start) != display_size)
13092ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return 0;
13102ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
13112ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  return display_size;
13122ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian}
13132ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
13142ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian///////////////////////////////////////////////////////////////
13152ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian//
13162ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian// Chapters Class
13172ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
1318ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh VenkatasubramanianChapters::Chapters() : chapters_size_(0), chapters_count_(0), chapters_(NULL) {}
13192ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
13202ec72e65689c948e92b826ae1e867bf369e72f13Vignesh VenkatasubramanianChapters::~Chapters() {
13212ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  while (chapters_count_ > 0) {
13222ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    Chapter& chapter = chapters_[--chapters_count_];
13232ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    chapter.Clear();
13242ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  }
13252ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
1326ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  delete[] chapters_;
13272ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  chapters_ = NULL;
13282ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian}
13292ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
1330ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanianint Chapters::Count() const { return chapters_count_; }
13312ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
13322ec72e65689c948e92b826ae1e867bf369e72f13Vignesh VenkatasubramanianChapter* Chapters::AddChapter(unsigned int* seed) {
13332ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (!ExpandChaptersArray())
13342ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return NULL;
13352ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
13362ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  Chapter& chapter = chapters_[chapters_count_++];
13372ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  chapter.Init(seed);
13382ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
13392ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  return &chapter;
13402ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian}
13412ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
13422ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanianbool Chapters::Write(IMkvWriter* writer) const {
13432ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (writer == NULL)
13442ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return false;
13452ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
13462ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  const uint64 payload_size = WriteEdition(NULL);  // return size only
13472ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
13482ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (!WriteEbmlMasterElement(writer, kMkvChapters, payload_size))
13492ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return false;
13502ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
13512ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  const int64 start = writer->Position();
13522ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
13532ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (WriteEdition(writer) == 0)  // error
13542ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return false;
13552ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
13562ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  const int64 stop = writer->Position();
13572ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
13582ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (stop >= start && uint64(stop - start) != payload_size)
13592ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return false;
13602ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
13612ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  return true;
13622ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian}
13632ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
13642ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanianbool Chapters::ExpandChaptersArray() {
13652ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (chapters_size_ > chapters_count_)
13662ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return true;  // nothing to do yet
13672ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
13682ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  const int size = (chapters_size_ == 0) ? 1 : 2 * chapters_size_;
13692ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
13702ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  Chapter* const chapters = new (std::nothrow) Chapter[size];  // NOLINT
13712ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (chapters == NULL)
13722ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return false;
13732ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
13742ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  for (int idx = 0; idx < chapters_count_; ++idx) {
13752ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    const Chapter& src = chapters_[idx];
13762ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    Chapter* const dst = chapters + idx;
13772ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    src.ShallowCopy(dst);
13782ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  }
13792ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
1380ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  delete[] chapters_;
13812ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
13822ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  chapters_ = chapters;
13832ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  chapters_size_ = size;
13842ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
13852ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  return true;
13862ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian}
13872ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
13882ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanianuint64 Chapters::WriteEdition(IMkvWriter* writer) const {
13892ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  uint64 payload_size = 0;
13902ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
13912ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  for (int idx = 0; idx < chapters_count_; ++idx) {
13922ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    const Chapter& chapter = chapters_[idx];
13932ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    payload_size += chapter.WriteAtom(NULL);
13942ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  }
13952ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
13962ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  const uint64 edition_size =
1397ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      EbmlMasterElementSize(kMkvEditionEntry, payload_size) + payload_size;
13982ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
13992ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (writer == NULL)  // return size only
14002ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return edition_size;
14012ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
14022ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  const int64 start = writer->Position();
14032ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
14042ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (!WriteEbmlMasterElement(writer, kMkvEditionEntry, payload_size))
14052ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return 0;  // error
14062ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
14072ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  for (int idx = 0; idx < chapters_count_; ++idx) {
14082ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    const Chapter& chapter = chapters_[idx];
14092ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
14102ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    const uint64 chapter_size = chapter.WriteAtom(writer);
14112ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    if (chapter_size == 0)  // error
14122ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      return 0;
14132ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  }
14142ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
14152ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  const int64 stop = writer->Position();
14162ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
14172ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (stop >= start && uint64(stop - start) != edition_size)
14182ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return 0;
14192ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
14202ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  return edition_size;
14212ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian}
14222ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
14232ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian///////////////////////////////////////////////////////////////
14242ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian//
14252ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian// Cluster class
14262ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
14272ec72e65689c948e92b826ae1e867bf369e72f13Vignesh VenkatasubramanianCluster::Cluster(uint64 timecode, int64 cues_pos)
14282ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    : blocks_added_(0),
14292ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      finalized_(false),
14302ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      header_written_(false),
14312ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      payload_size_(0),
14322ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      position_for_cues_(cues_pos),
14332ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      size_position_(-1),
14342ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      timecode_(timecode),
1435ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      writer_(NULL) {}
14362ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
1437ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh VenkatasubramanianCluster::~Cluster() {}
14382ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
14392ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanianbool Cluster::Init(IMkvWriter* ptr_writer) {
14402ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (!ptr_writer) {
14412ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return false;
14422ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  }
14432ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  writer_ = ptr_writer;
14442ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  return true;
14452ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian}
14462ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
1447ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanianbool Cluster::AddFrame(const uint8* frame, uint64 length, uint64 track_number,
1448ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                       uint64 abs_timecode, bool is_key) {
1449ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  return DoWriteBlock(frame, length, track_number, abs_timecode, is_key ? 1 : 0,
14502ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian                      &WriteSimpleBlock);
14512ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian}
14522ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
1453ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanianbool Cluster::AddFrameWithAdditional(const uint8* frame, uint64 length,
14542ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian                                     const uint8* additional,
1455ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                                     uint64 additional_length, uint64 add_id,
1456ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                                     uint64 track_number, uint64 abs_timecode,
14572ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian                                     bool is_key) {
1458ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  return DoWriteBlockWithAdditional(
1459ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      frame, length, additional, additional_length, add_id, track_number,
1460ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      abs_timecode, is_key ? 1 : 0, &WriteBlockWithAdditional);
1461ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian}
1462ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
1463ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanianbool Cluster::AddFrameWithDiscardPadding(const uint8* frame, uint64 length,
14642ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian                                         int64 discard_padding,
14652ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian                                         uint64 track_number,
1466ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                                         uint64 abs_timecode, bool is_key) {
1467ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  return DoWriteBlockWithDiscardPadding(
1468ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      frame, length, discard_padding, track_number, abs_timecode,
1469ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      is_key ? 1 : 0, &WriteBlockWithDiscardPadding);
14702ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian}
14712ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
1472ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanianbool Cluster::AddMetadata(const uint8* frame, uint64 length,
1473ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                          uint64 track_number, uint64 abs_timecode,
1474ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                          uint64 duration_timecode) {
1475ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  return DoWriteBlock(frame, length, track_number, abs_timecode,
1476ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                      duration_timecode, &WriteMetadataBlock);
14772ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian}
14782ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
1479ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanianvoid Cluster::AddPayloadSize(uint64 size) { payload_size_ += size; }
1480ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
14812ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanianbool Cluster::Finalize() {
14822ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (!writer_ || finalized_ || size_position_ == -1)
14832ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return false;
14842ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
14852ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (writer_->Seekable()) {
14862ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    const int64 pos = writer_->Position();
14872ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
14882ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    if (writer_->Position(size_position_))
14892ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      return false;
14902ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
14912ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    if (WriteUIntSize(writer_, payload_size(), 8))
14922ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      return false;
14932ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
14942ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    if (writer_->Position(pos))
14952ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      return false;
14962ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  }
14972ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
14982ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  finalized_ = true;
14992ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
15002ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  return true;
15012ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian}
15022ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
15032ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanianuint64 Cluster::Size() const {
15042ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  const uint64 element_size =
1505ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      EbmlMasterElementSize(kMkvCluster, 0xFFFFFFFFFFFFFFFFULL) + payload_size_;
15062ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  return element_size;
15072ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian}
15082ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
15092ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramaniantemplate <typename Type>
15102ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanianbool Cluster::PreWriteBlock(Type* write_function) {
15112ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (write_function == NULL)
15122ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return false;
15132ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
15142ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (finalized_)
15152ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return false;
15162ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
15172ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (!header_written_) {
15182ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    if (!WriteClusterHeader())
15192ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      return false;
15202ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  }
15212ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
15222ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  return true;
15232ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian}
15242ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
15252ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanianvoid Cluster::PostWriteBlock(uint64 element_size) {
15262ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  AddPayloadSize(element_size);
15272ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  ++blocks_added_;
15282ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian}
15292ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
15302ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanianbool Cluster::IsValidTrackNumber(uint64 track_number) const {
15312ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  return (track_number > 0 && track_number <= 0x7E);
15322ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian}
15332ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
15342ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanianint64 Cluster::GetRelativeTimecode(int64 abs_timecode) const {
15352ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  const int64 cluster_timecode = this->Cluster::timecode();
15362ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  const int64 rel_timecode =
15372ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      static_cast<int64>(abs_timecode) - cluster_timecode;
15382ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
15392ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (rel_timecode < 0 || rel_timecode > kMaxBlockTimecode)
15402ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return -1;
15412ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
15422ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  return rel_timecode;
15432ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian}
15442ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
1545ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanianbool Cluster::DoWriteBlock(const uint8* frame, uint64 length,
1546ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                           uint64 track_number, uint64 abs_timecode,
1547ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                           uint64 generic_arg, WriteBlock write_block) {
15482ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (frame == NULL || length == 0)
15492ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return false;
15502ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
15512ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (!IsValidTrackNumber(track_number))
15522ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return false;
15532ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
15542ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  const int64 rel_timecode = GetRelativeTimecode(abs_timecode);
15552ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (rel_timecode < 0)
15562ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return false;
15572ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
15582ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (!PreWriteBlock(write_block))
15592ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return false;
15602ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
1561ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  const uint64 element_size = (*write_block)(
1562ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      writer_, frame, length, track_number, rel_timecode, generic_arg);
15632ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (element_size == 0)
15642ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return false;
15652ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
15662ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  PostWriteBlock(element_size);
15672ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  return true;
15682ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian}
15692ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
15702ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanianbool Cluster::DoWriteBlockWithAdditional(
1571ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    const uint8* frame, uint64 length, const uint8* additional,
1572ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    uint64 additional_length, uint64 add_id, uint64 track_number,
1573ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    uint64 abs_timecode, uint64 generic_arg, WriteBlockAdditional write_block) {
1574ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (frame == NULL || length == 0 || additional == NULL ||
1575ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      additional_length == 0)
15762ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return false;
15772ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
15782ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (!IsValidTrackNumber(track_number))
15792ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return false;
15802ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
15812ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  const int64 rel_timecode = GetRelativeTimecode(abs_timecode);
15822ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (rel_timecode < 0)
15832ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return false;
15842ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
15852ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (!PreWriteBlock(write_block))
15862ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return false;
15872ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
1588ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  const uint64 element_size =
1589ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      (*write_block)(writer_, frame, length, additional, additional_length,
1590ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                     add_id, track_number, rel_timecode, generic_arg);
15912ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (element_size == 0)
15922ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return false;
15932ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
15942ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  PostWriteBlock(element_size);
15952ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  return true;
15962ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian}
15972ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
15982ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanianbool Cluster::DoWriteBlockWithDiscardPadding(
1599ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    const uint8* frame, uint64 length, int64 discard_padding,
1600ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    uint64 track_number, uint64 abs_timecode, uint64 generic_arg,
16012ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    WriteBlockDiscardPadding write_block) {
16022ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (frame == NULL || length == 0 || discard_padding <= 0)
16032ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return false;
16042ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
16052ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (!IsValidTrackNumber(track_number))
16062ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return false;
16072ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
16082ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  const int64 rel_timecode = GetRelativeTimecode(abs_timecode);
16092ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (rel_timecode < 0)
16102ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return false;
16112ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
16122ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (!PreWriteBlock(write_block))
16132ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return false;
16142ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
1615ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  const uint64 element_size =
1616ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      (*write_block)(writer_, frame, length, discard_padding, track_number,
1617ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                     rel_timecode, generic_arg);
16182ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (element_size == 0)
16192ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return false;
16202ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
16212ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  PostWriteBlock(element_size);
16222ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  return true;
16232ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian}
16242ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
16252ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanianbool Cluster::WriteClusterHeader() {
16262ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (finalized_)
16272ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return false;
16282ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
16292ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (WriteID(writer_, kMkvCluster))
16302ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return false;
16312ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
16322ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  // Save for later.
16332ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  size_position_ = writer_->Position();
16342ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
16352ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  // Write "unknown" (EBML coded -1) as cluster size value. We need to write 8
16362ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  // bytes because we do not know how big our cluster will be.
16372ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (SerializeInt(writer_, kEbmlUnknownValue, 8))
16382ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return false;
16392ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
16402ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (!WriteEbmlElement(writer_, kMkvTimecode, timecode()))
16412ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return false;
16422ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  AddPayloadSize(EbmlElementSize(kMkvTimecode, timecode()));
16432ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  header_written_ = true;
16442ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
16452ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  return true;
16462ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian}
16472ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
16482ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian///////////////////////////////////////////////////////////////
16492ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian//
16502ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian// SeekHead Class
16512ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
16522ec72e65689c948e92b826ae1e867bf369e72f13Vignesh VenkatasubramanianSeekHead::SeekHead() : start_pos_(0ULL) {
16532ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  for (int32 i = 0; i < kSeekEntryCount; ++i) {
16542ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    seek_entry_id_[i] = 0;
16552ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    seek_entry_pos_[i] = 0;
16562ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  }
16572ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian}
16582ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
1659ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh VenkatasubramanianSeekHead::~SeekHead() {}
16602ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
16612ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanianbool SeekHead::Finalize(IMkvWriter* writer) const {
16622ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (writer->Seekable()) {
16632ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    if (start_pos_ == -1)
16642ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      return false;
16652ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
16662ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    uint64 payload_size = 0;
16672ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    uint64 entry_size[kSeekEntryCount];
16682ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
16692ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    for (int32 i = 0; i < kSeekEntryCount; ++i) {
16702ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      if (seek_entry_id_[i] != 0) {
1671ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian        entry_size[i] =
1672ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian            EbmlElementSize(kMkvSeekID, static_cast<uint64>(seek_entry_id_[i]));
16732ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian        entry_size[i] += EbmlElementSize(kMkvSeekPosition, seek_entry_pos_[i]);
16742ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
1675ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian        payload_size +=
1676ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian            EbmlMasterElementSize(kMkvSeek, entry_size[i]) + entry_size[i];
16772ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      }
16782ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    }
16792ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
16802ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    // No SeekHead elements
16812ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    if (payload_size == 0)
16822ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      return true;
16832ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
16842ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    const int64 pos = writer->Position();
16852ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    if (writer->Position(start_pos_))
16862ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      return false;
16872ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
16882ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    if (!WriteEbmlMasterElement(writer, kMkvSeekHead, payload_size))
16892ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      return false;
16902ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
16912ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    for (int32 i = 0; i < kSeekEntryCount; ++i) {
16922ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      if (seek_entry_id_[i] != 0) {
16932ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian        if (!WriteEbmlMasterElement(writer, kMkvSeek, entry_size[i]))
16942ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian          return false;
16952ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
1696ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian        if (!WriteEbmlElement(writer, kMkvSeekID,
16972ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian                              static_cast<uint64>(seek_entry_id_[i])))
16982ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian          return false;
16992ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
17002ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian        if (!WriteEbmlElement(writer, kMkvSeekPosition, seek_entry_pos_[i]))
17012ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian          return false;
17022ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      }
17032ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    }
17042ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
17052ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    const uint64 total_entry_size = kSeekEntryCount * MaxEntrySize();
17062ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    const uint64 total_size =
1707ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian        EbmlMasterElementSize(kMkvSeekHead, total_entry_size) +
1708ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian        total_entry_size;
17092ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    const int64 size_left = total_size - (writer->Position() - start_pos_);
17102ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
17112ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    const uint64 bytes_written = WriteVoidElement(writer, size_left);
17122ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    if (!bytes_written)
17132ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      return false;
17142ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
17152ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    if (writer->Position(pos))
17162ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      return false;
17172ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  }
17182ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
17192ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  return true;
17202ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian}
17212ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
17222ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanianbool SeekHead::Write(IMkvWriter* writer) {
17232ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  const uint64 entry_size = kSeekEntryCount * MaxEntrySize();
17242ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  const uint64 size = EbmlMasterElementSize(kMkvSeekHead, entry_size);
17252ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
17262ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  start_pos_ = writer->Position();
17272ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
17282ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  const uint64 bytes_written = WriteVoidElement(writer, size + entry_size);
17292ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (!bytes_written)
17302ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return false;
17312ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
17322ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  return true;
17332ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian}
17342ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
17352ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanianbool SeekHead::AddSeekEntry(uint32 id, uint64 pos) {
17362ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  for (int32 i = 0; i < kSeekEntryCount; ++i) {
17372ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    if (seek_entry_id_[i] == 0) {
17382ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      seek_entry_id_[i] = id;
17392ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      seek_entry_pos_[i] = pos;
17402ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      return true;
17412ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    }
17422ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  }
17432ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  return false;
17442ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian}
17452ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
17462ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanianuint32 SeekHead::GetId(int index) const {
17472ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (index < 0 || index >= kSeekEntryCount)
17482ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return UINT_MAX;
17492ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  return seek_entry_id_[index];
17502ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian}
17512ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
17522ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanianuint64 SeekHead::GetPosition(int index) const {
17532ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (index < 0 || index >= kSeekEntryCount)
17542ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return ULLONG_MAX;
17552ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  return seek_entry_pos_[index];
17562ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian}
17572ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
17582ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanianbool SeekHead::SetSeekEntry(int index, uint32 id, uint64 position) {
17592ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (index < 0 || index >= kSeekEntryCount)
17602ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return false;
17612ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  seek_entry_id_[index] = id;
17622ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  seek_entry_pos_[index] = position;
17632ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  return true;
17642ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian}
17652ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
17662ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanianuint64 SeekHead::MaxEntrySize() const {
17672ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  const uint64 max_entry_payload_size =
17682ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      EbmlElementSize(kMkvSeekID, 0xffffffffULL) +
17692ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      EbmlElementSize(kMkvSeekPosition, 0xffffffffffffffffULL);
17702ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  const uint64 max_entry_size =
17712ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      EbmlMasterElementSize(kMkvSeek, max_entry_payload_size) +
17722ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      max_entry_payload_size;
17732ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
17742ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  return max_entry_size;
17752ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian}
17762ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
17772ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian///////////////////////////////////////////////////////////////
17782ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian//
17792ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian// SegmentInfo Class
17802ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
17812ec72e65689c948e92b826ae1e867bf369e72f13Vignesh VenkatasubramanianSegmentInfo::SegmentInfo()
17822ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    : duration_(-1.0),
17832ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      muxing_app_(NULL),
17842ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      timecode_scale_(1000000ULL),
17852ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      writing_app_(NULL),
1786ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      date_utc_(LLONG_MIN),
1787ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      duration_pos_(-1) {}
17882ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
17892ec72e65689c948e92b826ae1e867bf369e72f13Vignesh VenkatasubramanianSegmentInfo::~SegmentInfo() {
1790ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  delete[] muxing_app_;
1791ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  delete[] writing_app_;
17922ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian}
17932ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
17942ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanianbool SegmentInfo::Init() {
17952ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  int32 major;
17962ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  int32 minor;
17972ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  int32 build;
17982ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  int32 revision;
17992ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  GetVersion(&major, &minor, &build, &revision);
18002ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  char temp[256];
18012ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian#ifdef _MSC_VER
1802ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  sprintf_s(temp, sizeof(temp) / sizeof(temp[0]), "libwebm-%d.%d.%d.%d", major,
1803ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian            minor, build, revision);
18042ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian#else
1805ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  snprintf(temp, sizeof(temp) / sizeof(temp[0]), "libwebm-%d.%d.%d.%d", major,
1806ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian           minor, build, revision);
18072ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian#endif
18082ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
18092ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  const size_t app_len = strlen(temp) + 1;
18102ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
1811ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  delete[] muxing_app_;
18122ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
18132ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  muxing_app_ = new (std::nothrow) char[app_len];  // NOLINT
18142ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (!muxing_app_)
18152ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return false;
18162ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
18172ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian#ifdef _MSC_VER
18182ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  strcpy_s(muxing_app_, app_len, temp);
18192ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian#else
18202ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  strcpy(muxing_app_, temp);
18212ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian#endif
18222ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
18232ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  set_writing_app(temp);
18242ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (!writing_app_)
18252ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return false;
18262ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  return true;
18272ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian}
18282ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
18292ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanianbool SegmentInfo::Finalize(IMkvWriter* writer) const {
18302ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (!writer)
18312ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return false;
18322ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
18332ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (duration_ > 0.0) {
18342ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    if (writer->Seekable()) {
18352ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      if (duration_pos_ == -1)
18362ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian        return false;
18372ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
18382ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      const int64 pos = writer->Position();
18392ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
18402ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      if (writer->Position(duration_pos_))
18412ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian        return false;
18422ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
1843ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      if (!WriteEbmlElement(writer, kMkvDuration,
18442ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian                            static_cast<float>(duration_)))
18452ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian        return false;
18462ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
18472ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      if (writer->Position(pos))
18482ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian        return false;
18492ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    }
18502ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  }
18512ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
18522ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  return true;
18532ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian}
18542ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
18552ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanianbool SegmentInfo::Write(IMkvWriter* writer) {
18562ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (!writer || !muxing_app_ || !writing_app_)
18572ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return false;
18582ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
18592ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  uint64 size = EbmlElementSize(kMkvTimecodeScale, timecode_scale_);
18602ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (duration_ > 0.0)
18612ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    size += EbmlElementSize(kMkvDuration, static_cast<float>(duration_));
1862ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (date_utc_ != LLONG_MIN)
1863ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    size += EbmlDateElementSize(kMkvDateUTC, date_utc_);
18642ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  size += EbmlElementSize(kMkvMuxingApp, muxing_app_);
18652ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  size += EbmlElementSize(kMkvWritingApp, writing_app_);
18662ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
18672ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (!WriteEbmlMasterElement(writer, kMkvInfo, size))
18682ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return false;
18692ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
18702ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  const int64 payload_position = writer->Position();
18712ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (payload_position < 0)
18722ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return false;
18732ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
18742ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (!WriteEbmlElement(writer, kMkvTimecodeScale, timecode_scale_))
18752ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return false;
18762ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
18772ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (duration_ > 0.0) {
18782ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    // Save for later
18792ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    duration_pos_ = writer->Position();
18802ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
18812ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    if (!WriteEbmlElement(writer, kMkvDuration, static_cast<float>(duration_)))
18822ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      return false;
18832ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  }
18842ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
1885ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (date_utc_ != LLONG_MIN)
1886ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    WriteEbmlDateElement(writer, kMkvDateUTC, date_utc_);
1887ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
18882ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (!WriteEbmlElement(writer, kMkvMuxingApp, muxing_app_))
18892ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return false;
18902ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (!WriteEbmlElement(writer, kMkvWritingApp, writing_app_))
18912ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return false;
18922ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
18932ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  const int64 stop_position = writer->Position();
18942ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (stop_position < 0 ||
18952ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      stop_position - payload_position != static_cast<int64>(size))
18962ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return false;
18972ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
18982ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  return true;
18992ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian}
19002ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
19012ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanianvoid SegmentInfo::set_muxing_app(const char* app) {
19022ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (app) {
19032ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    const size_t length = strlen(app) + 1;
19042ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    char* temp_str = new (std::nothrow) char[length];  // NOLINT
19052ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    if (!temp_str)
19062ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      return;
19072ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
19082ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian#ifdef _MSC_VER
19092ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    strcpy_s(temp_str, length, app);
19102ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian#else
19112ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    strcpy(temp_str, app);
19122ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian#endif
19132ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
1914ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    delete[] muxing_app_;
19152ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    muxing_app_ = temp_str;
19162ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  }
19172ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian}
19182ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
19192ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanianvoid SegmentInfo::set_writing_app(const char* app) {
19202ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (app) {
19212ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    const size_t length = strlen(app) + 1;
19222ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    char* temp_str = new (std::nothrow) char[length];  // NOLINT
19232ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    if (!temp_str)
19242ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      return;
19252ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
19262ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian#ifdef _MSC_VER
19272ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    strcpy_s(temp_str, length, app);
19282ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian#else
19292ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    strcpy(temp_str, app);
19302ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian#endif
19312ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
1932ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    delete[] writing_app_;
19332ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    writing_app_ = temp_str;
19342ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  }
19352ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian}
19362ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
19372ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian///////////////////////////////////////////////////////////////
19382ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian//
19392ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian// Segment Class
19402ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
19412ec72e65689c948e92b826ae1e867bf369e72f13Vignesh VenkatasubramanianSegment::Segment()
19422ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    : chunk_count_(0),
19432ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      chunk_name_(NULL),
19442ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      chunk_writer_cluster_(NULL),
19452ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      chunk_writer_cues_(NULL),
19462ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      chunk_writer_header_(NULL),
19472ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      chunking_(false),
19482ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      chunking_base_name_(NULL),
19492ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      cluster_list_(NULL),
19502ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      cluster_list_capacity_(0),
19512ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      cluster_list_size_(0),
19522ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      cues_position_(kAfterClusters),
19532ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      cues_track_(0),
19542ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      force_new_cluster_(false),
19552ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      frames_(NULL),
19562ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      frames_capacity_(0),
19572ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      frames_size_(0),
19582ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      has_video_(false),
19592ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      header_written_(false),
19602ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      last_block_duration_(0),
19612ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      last_timestamp_(0),
19622ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      max_cluster_duration_(kDefaultMaxClusterDuration),
19632ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      max_cluster_size_(0),
19642ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      mode_(kFile),
19652ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      new_cuepoint_(false),
19662ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      output_cues_(true),
19672ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      payload_pos_(0),
19682ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      size_position_(0),
19692ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      writer_cluster_(NULL),
19702ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      writer_cues_(NULL),
19712ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      writer_header_(NULL) {
19722ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  const time_t curr_time = time(NULL);
19732ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  seed_ = static_cast<unsigned int>(curr_time);
19742ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian#ifdef _WIN32
19752ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  srand(seed_);
19762ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian#endif
19772ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian}
19782ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
19792ec72e65689c948e92b826ae1e867bf369e72f13Vignesh VenkatasubramanianSegment::~Segment() {
19802ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (cluster_list_) {
19812ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    for (int32 i = 0; i < cluster_list_size_; ++i) {
19822ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      Cluster* const cluster = cluster_list_[i];
19832ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      delete cluster;
19842ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    }
1985ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    delete[] cluster_list_;
19862ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  }
19872ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
19882ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (frames_) {
19892ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    for (int32 i = 0; i < frames_size_; ++i) {
19902ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      Frame* const frame = frames_[i];
19912ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      delete frame;
19922ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    }
1993ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    delete[] frames_;
19942ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  }
19952ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
1996ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  delete[] chunk_name_;
1997ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  delete[] chunking_base_name_;
19982ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
19992ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (chunk_writer_cluster_) {
20002ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    chunk_writer_cluster_->Close();
20012ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    delete chunk_writer_cluster_;
20022ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  }
20032ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (chunk_writer_cues_) {
20042ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    chunk_writer_cues_->Close();
20052ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    delete chunk_writer_cues_;
20062ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  }
20072ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (chunk_writer_header_) {
20082ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    chunk_writer_header_->Close();
20092ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    delete chunk_writer_header_;
20102ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  }
20112ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian}
20122ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
2013ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanianvoid Segment::MoveCuesBeforeClustersHelper(uint64 diff, int32 index,
20142ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian                                           uint64* cues_size) {
20152ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  const uint64 old_cues_size = *cues_size;
20162ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  CuePoint* const cue_point = cues_.GetCueByIndex(index);
20172ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (cue_point == NULL)
20182ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return;
20192ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  const uint64 old_cue_point_size = cue_point->Size();
20202ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  const uint64 cluster_pos = cue_point->cluster_pos() + diff;
20212ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  cue_point->set_cluster_pos(cluster_pos);  // update the new cluster position
20222ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  // New size of the cue is computed as follows
20232ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  //    Let a = current size of Cues Element
20242ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  //    Let b = Difference in Cue Point's size after this pass
20252ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  //    Let c = Difference in length of Cues Element's size
20262ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  //            (This is computed as CodedSize(a + b) - CodedSize(a)
20272ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  //    Let d = a + b + c. Now d is the new size of the Cues element which is
20282ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  //                       passed on to the next recursive call.
20292ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  const uint64 cue_point_size_diff = cue_point->Size() - old_cue_point_size;
2030ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  const uint64 cue_size_diff =
2031ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      GetCodedUIntSize(*cues_size + cue_point_size_diff) -
2032ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      GetCodedUIntSize(*cues_size);
20332ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  *cues_size += cue_point_size_diff + cue_size_diff;
20342ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  diff = *cues_size - old_cues_size;
20352ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (diff > 0) {
20362ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    for (int32 i = 0; i < cues_.cue_entries_size(); ++i) {
20372ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      MoveCuesBeforeClustersHelper(diff, i, cues_size);
20382ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    }
20392ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  }
20402ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian}
20412ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
20422ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanianvoid Segment::MoveCuesBeforeClusters() {
20432ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  const uint64 current_cue_size = cues_.Size();
20442ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  uint64 cue_size = current_cue_size;
20452ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  for (int32 i = 0; i < cues_.cue_entries_size(); i++)
20462ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    MoveCuesBeforeClustersHelper(current_cue_size, i, &cue_size);
20472ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
20482ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  // Adjust the Seek Entry to reflect the change in position
20492ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  // of Cluster and Cues
20502ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  int32 cluster_index = 0;
20512ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  int32 cues_index = 0;
20522ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  for (int32 i = 0; i < SeekHead::kSeekEntryCount; ++i) {
20532ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    if (seek_head_.GetId(i) == kMkvCluster)
20542ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      cluster_index = i;
20552ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    if (seek_head_.GetId(i) == kMkvCues)
20562ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      cues_index = i;
20572ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  }
20582ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  seek_head_.SetSeekEntry(cues_index, kMkvCues,
20592ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian                          seek_head_.GetPosition(cluster_index));
20602ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  seek_head_.SetSeekEntry(cluster_index, kMkvCluster,
20612ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian                          cues_.Size() + seek_head_.GetPosition(cues_index));
20622ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian}
20632ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
20642ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanianbool Segment::Init(IMkvWriter* ptr_writer) {
20652ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (!ptr_writer) {
20662ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return false;
20672ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  }
20682ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  writer_cluster_ = ptr_writer;
20692ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  writer_cues_ = ptr_writer;
20702ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  writer_header_ = ptr_writer;
20712ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  return segment_info_.Init();
20722ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian}
20732ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
20742ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanianbool Segment::CopyAndMoveCuesBeforeClusters(mkvparser::IMkvReader* reader,
20752ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian                                            IMkvWriter* writer) {
20762ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (!writer->Seekable() || chunking_)
20772ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return false;
2078ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  const int64 cluster_offset =
2079ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      cluster_list_[0]->size_position() - GetUIntSize(kMkvCluster);
20802ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
20812ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  // Copy the headers.
20822ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (!ChunkedCopy(reader, writer, 0, cluster_offset))
20832ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return false;
20842ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
20852ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  // Recompute cue positions and seek entries.
20862ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  MoveCuesBeforeClusters();
20872ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
20882ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  // Write cues and seek entries.
20892ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  // TODO(vigneshv): As of now, it's safe to call seek_head_.Finalize() for the
20902ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  // second time with a different writer object. But the name Finalize() doesn't
20912ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  // indicate something we want to call more than once. So consider renaming it
20922ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  // to write() or some such.
20932ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (!cues_.Write(writer) || !seek_head_.Finalize(writer))
20942ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return false;
20952ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
20962ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  // Copy the Clusters.
20972ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (!ChunkedCopy(reader, writer, cluster_offset,
20982ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian                   cluster_end_offset_ - cluster_offset))
20992ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return false;
21002ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
21012ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  // Update the Segment size in case the Cues size has changed.
21022ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  const int64 pos = writer->Position();
21032ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  const int64 segment_size = writer->Position() - payload_pos_;
21042ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (writer->Position(size_position_) ||
2105ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      WriteUIntSize(writer, segment_size, 8) || writer->Position(pos))
21062ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return false;
21072ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  return true;
21082ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian}
21092ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
21102ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanianbool Segment::Finalize() {
21112ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (WriteFramesAll() < 0)
21122ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return false;
21132ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
21142ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (mode_ == kFile) {
21152ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    if (cluster_list_size_ > 0) {
21162ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      // Update last cluster's size
2117ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      Cluster* const old_cluster = cluster_list_[cluster_list_size_ - 1];
21182ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
21192ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      if (!old_cluster || !old_cluster->Finalize())
21202ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian        return false;
21212ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    }
21222ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
21232ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    if (chunking_ && chunk_writer_cluster_) {
21242ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      chunk_writer_cluster_->Close();
21252ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      chunk_count_++;
21262ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    }
21272ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
21282ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    const double duration =
21292ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian        (static_cast<double>(last_timestamp_) + last_block_duration_) /
21302ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian        segment_info_.timecode_scale();
21312ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    segment_info_.set_duration(duration);
21322ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    if (!segment_info_.Finalize(writer_header_))
21332ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      return false;
21342ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
21352ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    if (output_cues_)
21362ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      if (!seek_head_.AddSeekEntry(kMkvCues, MaxOffset()))
21372ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian        return false;
21382ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
21392ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    if (chunking_) {
21402ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      if (!chunk_writer_cues_)
21412ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian        return false;
21422ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
21432ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      char* name = NULL;
21442ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      if (!UpdateChunkName("cues", &name))
21452ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian        return false;
21462ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
21472ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      const bool cues_open = chunk_writer_cues_->Open(name);
2148ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      delete[] name;
21492ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      if (!cues_open)
21502ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian        return false;
21512ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    }
21522ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
21532ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    cluster_end_offset_ = writer_cluster_->Position();
21542ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
21552ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    // Write the seek headers and cues
21562ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    if (output_cues_)
21572ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      if (!cues_.Write(writer_cues_))
21582ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian        return false;
21592ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
21602ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    if (!seek_head_.Finalize(writer_header_))
21612ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      return false;
21622ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
21632ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    if (writer_header_->Seekable()) {
21642ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      if (size_position_ == -1)
21652ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian        return false;
21662ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
21672ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      const int64 pos = writer_header_->Position();
21682ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      const int64 segment_size = MaxOffset();
21692ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
21702ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      if (segment_size < 1)
21712ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian        return false;
21722ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
21732ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      if (writer_header_->Position(size_position_))
21742ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian        return false;
21752ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
21762ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      if (WriteUIntSize(writer_header_, segment_size, 8))
21772ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian        return false;
21782ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
21792ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      if (writer_header_->Position(pos))
21802ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian        return false;
21812ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    }
21822ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
21832ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    if (chunking_) {
21842ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      // Do not close any writers until the segment size has been written,
21852ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      // otherwise the size may be off.
21862ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      if (!chunk_writer_cues_ || !chunk_writer_header_)
21872ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian        return false;
21882ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
21892ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      chunk_writer_cues_->Close();
21902ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      chunk_writer_header_->Close();
21912ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    }
21922ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  }
21932ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
21942ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  return true;
21952ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian}
21962ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
21972ec72e65689c948e92b826ae1e867bf369e72f13Vignesh VenkatasubramanianTrack* Segment::AddTrack(int32 number) {
21982ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  Track* const track = new (std::nothrow) Track(&seed_);  // NOLINT
21992ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
22002ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (!track)
22012ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return NULL;
22022ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
22032ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (!tracks_.AddTrack(track, number)) {
22042ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    delete track;
22052ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return NULL;
22062ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  }
22072ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
22082ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  return track;
22092ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian}
22102ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
2211ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh VenkatasubramanianChapter* Segment::AddChapter() { return chapters_.AddChapter(&seed_); }
22122ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
22132ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanianuint64 Segment::AddVideoTrack(int32 width, int32 height, int32 number) {
22142ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  VideoTrack* const track = new (std::nothrow) VideoTrack(&seed_);  // NOLINT
22152ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (!track)
22162ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return 0;
22172ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
22182ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  track->set_type(Tracks::kVideo);
22192ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  track->set_codec_id(Tracks::kVp8CodecId);
22202ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  track->set_width(width);
22212ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  track->set_height(height);
22222ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
22232ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  tracks_.AddTrack(track, number);
22242ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  has_video_ = true;
22252ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
22262ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  return track->number();
22272ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian}
22282ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
22292ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanianbool Segment::AddCuePoint(uint64 timestamp, uint64 track) {
2230ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (cluster_list_size_ < 1)
22312ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return false;
22322ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
2233ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  const Cluster* const cluster = cluster_list_[cluster_list_size_ - 1];
22342ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (!cluster)
22352ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return false;
22362ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
22372ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  CuePoint* const cue = new (std::nothrow) CuePoint();  // NOLINT
22382ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (!cue)
22392ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return false;
22402ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
22412ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  cue->set_time(timestamp / segment_info_.timecode_scale());
22422ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  cue->set_block_number(cluster->blocks_added());
22432ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  cue->set_cluster_pos(cluster->position_for_cues());
22442ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  cue->set_track(track);
22452ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (!cues_.AddCue(cue))
22462ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return false;
22472ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
22482ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  new_cuepoint_ = false;
22492ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  return true;
22502ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian}
22512ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
2252ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanianuint64 Segment::AddAudioTrack(int32 sample_rate, int32 channels, int32 number) {
22532ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  AudioTrack* const track = new (std::nothrow) AudioTrack(&seed_);  // NOLINT
22542ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (!track)
22552ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return 0;
22562ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
22572ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  track->set_type(Tracks::kAudio);
22582ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  track->set_codec_id(Tracks::kVorbisCodecId);
22592ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  track->set_sample_rate(sample_rate);
22602ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  track->set_channels(channels);
22612ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
22622ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  tracks_.AddTrack(track, number);
22632ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
22642ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  return track->number();
22652ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian}
22662ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
2267ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanianbool Segment::AddFrame(const uint8* frame, uint64 length, uint64 track_number,
2268ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                       uint64 timestamp, bool is_key) {
22692ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (!frame)
22702ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return false;
22712ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
22722ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (!CheckHeaderInfo())
22732ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return false;
22742ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
22752ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  // Check for non-monotonically increasing timestamps.
22762ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (timestamp < last_timestamp_)
22772ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return false;
22782ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
22792ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  // If the segment has a video track hold onto audio frames to make sure the
22802ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  // audio that is associated with the start time of a video key-frame is
22812ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  // muxed into the same cluster.
22822ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (has_video_ && tracks_.TrackIsAudio(track_number) && !force_new_cluster_) {
22832ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    Frame* const new_frame = new (std::nothrow) Frame();
22842ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    if (new_frame == NULL || !new_frame->Init(frame, length))
22852ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      return false;
22862ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    new_frame->set_track_number(track_number);
22872ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    new_frame->set_timestamp(timestamp);
22882ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    new_frame->set_is_key(is_key);
22892ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
22902ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    if (!QueueFrame(new_frame))
22912ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      return false;
22922ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
22932ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return true;
22942ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  }
22952ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
22962ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (!DoNewClusterProcessing(track_number, timestamp, is_key))
22972ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return false;
22982ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
22992ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (cluster_list_size_ < 1)
23002ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return false;
23012ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
23022ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  Cluster* const cluster = cluster_list_[cluster_list_size_ - 1];
23032ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (!cluster)
23042ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return false;
23052ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
23062ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  const uint64 timecode_scale = segment_info_.timecode_scale();
23072ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  const uint64 abs_timecode = timestamp / timecode_scale;
23082ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
2309ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (!cluster->AddFrame(frame, length, track_number, abs_timecode, is_key))
23102ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return false;
23112ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
23122ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (new_cuepoint_ && cues_track_ == track_number) {
23132ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    if (!AddCuePoint(timestamp, cues_track_))
23142ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      return false;
23152ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  }
23162ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
23172ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (timestamp > last_timestamp_)
23182ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    last_timestamp_ = timestamp;
23192ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
23202ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  return true;
23212ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian}
23222ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
2323ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanianbool Segment::AddFrameWithAdditional(const uint8* frame, uint64 length,
23242ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian                                     const uint8* additional,
2325ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                                     uint64 additional_length, uint64 add_id,
2326ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                                     uint64 track_number, uint64 timestamp,
23272ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian                                     bool is_key) {
23282ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (frame == NULL || additional == NULL)
23292ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return false;
23302ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
23312ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (!CheckHeaderInfo())
23322ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return false;
23332ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
23342ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  // Check for non-monotonically increasing timestamps.
23352ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (timestamp < last_timestamp_)
23362ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return false;
23372ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
23382ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  // If the segment has a video track hold onto audio frames to make sure the
23392ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  // audio that is associated with the start time of a video key-frame is
23402ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  // muxed into the same cluster.
23412ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (has_video_ && tracks_.TrackIsAudio(track_number) && !force_new_cluster_) {
23422ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    Frame* const new_frame = new (std::nothrow) Frame();
23432ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    if (new_frame == NULL || !new_frame->Init(frame, length))
23442ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      return false;
23452ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    new_frame->set_track_number(track_number);
23462ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    new_frame->set_timestamp(timestamp);
23472ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    new_frame->set_is_key(is_key);
23482ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
23492ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    if (!QueueFrame(new_frame))
23502ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      return false;
23512ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
23522ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return true;
23532ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  }
23542ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
23552ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (!DoNewClusterProcessing(track_number, timestamp, is_key))
23562ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return false;
23572ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
23582ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (cluster_list_size_ < 1)
23592ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return false;
23602ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
23612ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  Cluster* const cluster = cluster_list_[cluster_list_size_ - 1];
23622ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (cluster == NULL)
23632ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return false;
23642ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
23652ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  const uint64 timecode_scale = segment_info_.timecode_scale();
23662ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  const uint64 abs_timecode = timestamp / timecode_scale;
23672ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
2368ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (!cluster->AddFrameWithAdditional(frame, length, additional,
2369ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                                       additional_length, add_id, track_number,
2370ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                                       abs_timecode, is_key))
23712ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return false;
23722ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
23732ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (new_cuepoint_ && cues_track_ == track_number) {
23742ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    if (!AddCuePoint(timestamp, cues_track_))
23752ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      return false;
23762ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  }
23772ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
23782ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (timestamp > last_timestamp_)
23792ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    last_timestamp_ = timestamp;
23802ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
23812ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  return true;
23822ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian}
23832ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
2384ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanianbool Segment::AddFrameWithDiscardPadding(const uint8* frame, uint64 length,
23852ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian                                         int64 discard_padding,
2386ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                                         uint64 track_number, uint64 timestamp,
23872ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian                                         bool is_key) {
23882ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (frame == NULL || discard_padding <= 0)
23892ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return false;
23902ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
23912ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (!CheckHeaderInfo())
23922ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return false;
23932ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
23942ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  // Check for non-monotonically increasing timestamps.
23952ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (timestamp < last_timestamp_)
23962ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return false;
23972ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
23982ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  // If the segment has a video track hold onto audio frames to make sure the
23992ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  // audio that is associated with the start time of a video key-frame is
24002ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  // muxed into the same cluster.
24012ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (has_video_ && tracks_.TrackIsAudio(track_number) && !force_new_cluster_) {
24022ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    Frame* const new_frame = new (std::nothrow) Frame();
24032ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    if (new_frame == NULL || !new_frame->Init(frame, length))
24042ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      return false;
24052ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    new_frame->set_track_number(track_number);
24062ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    new_frame->set_timestamp(timestamp);
24072ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    new_frame->set_is_key(is_key);
24082ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    new_frame->set_discard_padding(discard_padding);
24092ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
24102ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    if (!QueueFrame(new_frame))
24112ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      return false;
24122ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
24132ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return true;
24142ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  }
24152ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
24162ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (!DoNewClusterProcessing(track_number, timestamp, is_key))
24172ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return false;
24182ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
24192ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (cluster_list_size_ < 1)
24202ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return false;
24212ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
24222ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  Cluster* const cluster = cluster_list_[cluster_list_size_ - 1];
24232ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (!cluster)
24242ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return false;
24252ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
24262ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  const uint64 timecode_scale = segment_info_.timecode_scale();
24272ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  const uint64 abs_timecode = timestamp / timecode_scale;
24282ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
2429ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (!cluster->AddFrameWithDiscardPadding(
2430ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian          frame, length, discard_padding, track_number, abs_timecode, is_key)) {
24312ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return false;
24322ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  }
24332ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
24342ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (new_cuepoint_ && cues_track_ == track_number) {
24352ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    if (!AddCuePoint(timestamp, cues_track_))
24362ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      return false;
24372ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  }
24382ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
24392ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (timestamp > last_timestamp_)
24402ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    last_timestamp_ = timestamp;
24412ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
24422ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  return true;
24432ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian}
24442ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
2445ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanianbool Segment::AddMetadata(const uint8* frame, uint64 length,
2446ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                          uint64 track_number, uint64 timestamp_ns,
24472ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian                          uint64 duration_ns) {
24482ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (!frame)
24492ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return false;
24502ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
24512ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (!CheckHeaderInfo())
24522ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return false;
24532ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
24542ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  // Check for non-monotonically increasing timestamps.
24552ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (timestamp_ns < last_timestamp_)
24562ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return false;
24572ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
24582ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (!DoNewClusterProcessing(track_number, timestamp_ns, true))
24592ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return false;
24602ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
24612ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (cluster_list_size_ < 1)
24622ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return false;
24632ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
2464ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  Cluster* const cluster = cluster_list_[cluster_list_size_ - 1];
24652ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
24662ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (!cluster)
24672ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return false;
24682ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
24692ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  const uint64 timecode_scale = segment_info_.timecode_scale();
24702ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  const uint64 abs_timecode = timestamp_ns / timecode_scale;
24712ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  const uint64 duration_timecode = duration_ns / timecode_scale;
24722ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
2473ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (!cluster->AddMetadata(frame, length, track_number, abs_timecode,
24742ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian                            duration_timecode))
24752ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return false;
24762ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
24772ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (timestamp_ns > last_timestamp_)
24782ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    last_timestamp_ = timestamp_ns;
24792ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
24802ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  return true;
24812ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian}
24822ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
24832ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanianbool Segment::AddGenericFrame(const Frame* frame) {
24842ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  last_block_duration_ = frame->duration();
24852ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (!tracks_.TrackIsAudio(frame->track_number()) &&
2486ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      !tracks_.TrackIsVideo(frame->track_number()) && frame->duration() > 0) {
2487ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    return AddMetadata(frame->frame(), frame->length(), frame->track_number(),
2488ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                       frame->timestamp(), frame->duration());
24892ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  } else if (frame->additional() && frame->additional_length() > 0) {
2490ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    return AddFrameWithAdditional(
2491ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian        frame->frame(), frame->length(), frame->additional(),
2492ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian        frame->additional_length(), frame->add_id(), frame->track_number(),
2493ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian        frame->timestamp(), frame->is_key());
24942ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  } else if (frame->discard_padding() > 0) {
2495ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    return AddFrameWithDiscardPadding(
2496ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian        frame->frame(), frame->length(), frame->discard_padding(),
2497ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian        frame->track_number(), frame->timestamp(), frame->is_key());
24982ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  } else {
2499ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    return AddFrame(frame->frame(), frame->length(), frame->track_number(),
2500ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                    frame->timestamp(), frame->is_key());
25012ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  }
25022ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian}
25032ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
2504ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanianvoid Segment::OutputCues(bool output_cues) { output_cues_ = output_cues; }
25052ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
25062ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanianbool Segment::SetChunking(bool chunking, const char* filename) {
25072ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (chunk_count_ > 0)
25082ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return false;
25092ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
25102ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (chunking) {
25112ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    if (!filename)
25122ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      return false;
25132ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
25142ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    // Check if we are being set to what is already set.
25152ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    if (chunking_ && !strcmp(filename, chunking_base_name_))
25162ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      return true;
25172ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
25182ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    const size_t name_length = strlen(filename) + 1;
25192ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    char* const temp = new (std::nothrow) char[name_length];  // NOLINT
25202ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    if (!temp)
25212ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      return false;
25222ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
25232ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian#ifdef _MSC_VER
25242ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    strcpy_s(temp, name_length, filename);
25252ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian#else
25262ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    strcpy(temp, filename);
25272ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian#endif
25282ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
2529ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    delete[] chunking_base_name_;
25302ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    chunking_base_name_ = temp;
25312ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
25322ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    if (!UpdateChunkName("chk", &chunk_name_))
25332ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      return false;
25342ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
25352ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    if (!chunk_writer_cluster_) {
25362ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      chunk_writer_cluster_ = new (std::nothrow) MkvWriter();  // NOLINT
25372ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      if (!chunk_writer_cluster_)
25382ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian        return false;
25392ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    }
25402ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
25412ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    if (!chunk_writer_cues_) {
25422ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      chunk_writer_cues_ = new (std::nothrow) MkvWriter();  // NOLINT
25432ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      if (!chunk_writer_cues_)
25442ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian        return false;
25452ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    }
25462ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
25472ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    if (!chunk_writer_header_) {
25482ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      chunk_writer_header_ = new (std::nothrow) MkvWriter();  // NOLINT
25492ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      if (!chunk_writer_header_)
25502ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian        return false;
25512ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    }
25522ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
25532ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    if (!chunk_writer_cluster_->Open(chunk_name_))
25542ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      return false;
25552ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
25562ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    const size_t header_length = strlen(filename) + strlen(".hdr") + 1;
25572ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    char* const header = new (std::nothrow) char[header_length];  // NOLINT
25582ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    if (!header)
25592ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      return false;
25602ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
25612ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian#ifdef _MSC_VER
25622ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    strcpy_s(header, header_length - strlen(".hdr"), chunking_base_name_);
25632ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    strcat_s(header, header_length, ".hdr");
25642ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian#else
25652ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    strcpy(header, chunking_base_name_);
25662ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    strcat(header, ".hdr");
25672ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian#endif
25682ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    if (!chunk_writer_header_->Open(header)) {
2569ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      delete[] header;
25702ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      return false;
25712ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    }
25722ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
25732ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    writer_cluster_ = chunk_writer_cluster_;
25742ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    writer_cues_ = chunk_writer_cues_;
25752ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    writer_header_ = chunk_writer_header_;
25762ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
2577ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    delete[] header;
25782ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  }
25792ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
25802ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  chunking_ = chunking;
25812ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
25822ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  return true;
25832ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian}
25842ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
25852ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanianbool Segment::CuesTrack(uint64 track_number) {
25862ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  const Track* const track = GetTrackByNumber(track_number);
25872ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (!track)
25882ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return false;
25892ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
25902ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  cues_track_ = track_number;
25912ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  return true;
25922ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian}
25932ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
2594ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanianvoid Segment::ForceNewClusterOnNextFrame() { force_new_cluster_ = true; }
25952ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
25962ec72e65689c948e92b826ae1e867bf369e72f13Vignesh VenkatasubramanianTrack* Segment::GetTrackByNumber(uint64 track_number) const {
25972ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  return tracks_.GetTrackByNumber(track_number);
25982ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian}
25992ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
26002ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanianbool Segment::WriteSegmentHeader() {
26012ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  // TODO(fgalligan): Support more than one segment.
26022ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (!WriteEbmlHeader(writer_header_))
26032ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return false;
26042ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
26052ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  // Write "unknown" (-1) as segment size value. If mode is kFile, Segment
26062ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  // will write over duration when the file is finalized.
26072ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (WriteID(writer_header_, kMkvSegment))
26082ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return false;
26092ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
26102ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  // Save for later.
26112ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  size_position_ = writer_header_->Position();
26122ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
26132ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  // Write "unknown" (EBML coded -1) as segment size value. We need to write 8
26142ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  // bytes because if we are going to overwrite the segment size later we do
26152ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  // not know how big our segment will be.
26162ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (SerializeInt(writer_header_, kEbmlUnknownValue, 8))
26172ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return false;
26182ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
2619ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  payload_pos_ = writer_header_->Position();
26202ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
26212ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (mode_ == kFile && writer_header_->Seekable()) {
26222ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    // Set the duration > 0.0 so SegmentInfo will write out the duration. When
26232ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    // the muxer is done writing we will set the correct duration and have
26242ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    // SegmentInfo upadte it.
26252ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    segment_info_.set_duration(1.0);
26262ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
26272ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    if (!seek_head_.Write(writer_header_))
26282ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      return false;
26292ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  }
26302ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
26312ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (!seek_head_.AddSeekEntry(kMkvInfo, MaxOffset()))
26322ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return false;
26332ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (!segment_info_.Write(writer_header_))
26342ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return false;
26352ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
26362ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (!seek_head_.AddSeekEntry(kMkvTracks, MaxOffset()))
26372ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return false;
26382ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (!tracks_.Write(writer_header_))
26392ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return false;
26402ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
26412ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (chapters_.Count() > 0) {
26422ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    if (!seek_head_.AddSeekEntry(kMkvChapters, MaxOffset()))
26432ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      return false;
26442ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    if (!chapters_.Write(writer_header_))
26452ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      return false;
26462ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  }
26472ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
26482ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (chunking_ && (mode_ == kLive || !writer_header_->Seekable())) {
26492ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    if (!chunk_writer_header_)
26502ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      return false;
26512ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
26522ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    chunk_writer_header_->Close();
26532ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  }
26542ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
26552ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  header_written_ = true;
26562ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
26572ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  return true;
26582ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian}
26592ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
26602ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian// Here we are testing whether to create a new cluster, given a frame
26612ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian// having time frame_timestamp_ns.
26622ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian//
2663ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanianint Segment::TestFrame(uint64 track_number, uint64 frame_timestamp_ns,
26642ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian                       bool is_key) const {
26652ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (force_new_cluster_)
26662ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return 1;
26672ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
26682ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  // If no clusters have been created yet, then create a new cluster
26692ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  // and write this frame immediately, in the new cluster.  This path
26702ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  // should only be followed once, the first time we attempt to write
26712ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  // a frame.
26722ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
26732ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (cluster_list_size_ <= 0)
26742ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return 1;
26752ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
26762ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  // There exists at least one cluster. We must compare the frame to
26772ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  // the last cluster, in order to determine whether the frame is
26782ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  // written to the existing cluster, or that a new cluster should be
26792ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  // created.
26802ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
26812ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  const uint64 timecode_scale = segment_info_.timecode_scale();
26822ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  const uint64 frame_timecode = frame_timestamp_ns / timecode_scale;
26832ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
26842ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  const Cluster* const last_cluster = cluster_list_[cluster_list_size_ - 1];
26852ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  const uint64 last_cluster_timecode = last_cluster->timecode();
26862ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
26872ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  // For completeness we test for the case when the frame's timecode
26882ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  // is less than the cluster's timecode.  Although in principle that
26892ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  // is allowed, this muxer doesn't actually write clusters like that,
26902ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  // so this indicates a bug somewhere in our algorithm.
26912ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
26922ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (frame_timecode < last_cluster_timecode)  // should never happen
2693ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    return -1;
26942ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
26952ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  // If the frame has a timestamp significantly larger than the last
26962ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  // cluster (in Matroska, cluster-relative timestamps are serialized
26972ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  // using a 16-bit signed integer), then we cannot write this frame
26982ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  // to that cluster, and so we must create a new cluster.
26992ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
27002ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  const int64 delta_timecode = frame_timecode - last_cluster_timecode;
27012ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
27022ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (delta_timecode > kMaxBlockTimecode)
27032ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return 2;
27042ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
27052ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  // We decide to create a new cluster when we have a video keyframe.
27062ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  // This will flush queued (audio) frames, and write the keyframe
27072ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  // immediately, in the newly-created cluster.
27082ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
27092ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (is_key && tracks_.TrackIsVideo(track_number))
27102ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return 1;
27112ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
27122ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  // Create a new cluster if we have accumulated too many frames
27132ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  // already, where "too many" is defined as "the total time of frames
27142ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  // in the cluster exceeds a threshold".
27152ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
27162ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  const uint64 delta_ns = delta_timecode * timecode_scale;
27172ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
27182ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (max_cluster_duration_ > 0 && delta_ns >= max_cluster_duration_)
27192ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return 1;
27202ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
27212ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  // This is similar to the case above, with the difference that a new
27222ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  // cluster is created when the size of the current cluster exceeds a
27232ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  // threshold.
27242ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
27252ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  const uint64 cluster_size = last_cluster->payload_size();
27262ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
27272ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (max_cluster_size_ > 0 && cluster_size >= max_cluster_size_)
27282ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return 1;
27292ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
27302ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  // There's no need to create a new cluster, so emit this frame now.
27312ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
27322ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  return 0;
27332ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian}
27342ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
27352ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanianbool Segment::MakeNewCluster(uint64 frame_timestamp_ns) {
27362ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  const int32 new_size = cluster_list_size_ + 1;
27372ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
27382ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (new_size > cluster_list_capacity_) {
27392ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    // Add more clusters.
27402ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    const int32 new_capacity =
27412ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian        (cluster_list_capacity_ <= 0) ? 1 : cluster_list_capacity_ * 2;
27422ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    Cluster** const clusters =
2743ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian        new (std::nothrow) Cluster* [new_capacity];  // NOLINT
27442ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    if (!clusters)
27452ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      return false;
27462ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
27472ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    for (int32 i = 0; i < cluster_list_size_; ++i) {
27482ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      clusters[i] = cluster_list_[i];
27492ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    }
27502ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
2751ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    delete[] cluster_list_;
27522ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
27532ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    cluster_list_ = clusters;
27542ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    cluster_list_capacity_ = new_capacity;
27552ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  }
27562ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
27572ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (!WriteFramesLessThan(frame_timestamp_ns))
27582ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return false;
27592ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
27602ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (mode_ == kFile) {
27612ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    if (cluster_list_size_ > 0) {
27622ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      // Update old cluster's size
27632ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      Cluster* const old_cluster = cluster_list_[cluster_list_size_ - 1];
27642ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
27652ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      if (!old_cluster || !old_cluster->Finalize())
27662ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian        return false;
27672ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    }
27682ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
27692ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    if (output_cues_)
27702ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      new_cuepoint_ = true;
27712ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  }
27722ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
27732ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (chunking_ && cluster_list_size_ > 0) {
27742ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    chunk_writer_cluster_->Close();
27752ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    chunk_count_++;
27762ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
27772ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    if (!UpdateChunkName("chk", &chunk_name_))
27782ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      return false;
27792ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    if (!chunk_writer_cluster_->Open(chunk_name_))
27802ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      return false;
27812ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  }
27822ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
27832ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  const uint64 timecode_scale = segment_info_.timecode_scale();
27842ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  const uint64 frame_timecode = frame_timestamp_ns / timecode_scale;
27852ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
27862ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  uint64 cluster_timecode = frame_timecode;
27872ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
27882ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (frames_size_ > 0) {
27892ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    const Frame* const f = frames_[0];  // earliest queued frame
27902ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    const uint64 ns = f->timestamp();
27912ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    const uint64 tc = ns / timecode_scale;
27922ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
27932ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    if (tc < cluster_timecode)
27942ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      cluster_timecode = tc;
27952ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  }
27962ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
27972ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  Cluster*& cluster = cluster_list_[cluster_list_size_];
27982ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  const int64 offset = MaxOffset();
27992ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  cluster = new (std::nothrow) Cluster(cluster_timecode, offset);  // NOLINT
28002ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (!cluster)
28012ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return false;
28022ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
28032ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (!cluster->Init(writer_cluster_))
28042ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return false;
28052ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
28062ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  cluster_list_size_ = new_size;
28072ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  return true;
28082ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian}
28092ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
28102ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanianbool Segment::DoNewClusterProcessing(uint64 track_number,
2811ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                                     uint64 frame_timestamp_ns, bool is_key) {
28122ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  for (;;) {
28132ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    // Based on the characteristics of the current frame and current
28142ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    // cluster, decide whether to create a new cluster.
28152ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    const int result = TestFrame(track_number, frame_timestamp_ns, is_key);
28162ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    if (result < 0)  // error
28172ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      return false;
28182ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
2819ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    // Always set force_new_cluster_ to false after TestFrame.
2820ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    force_new_cluster_ = false;
28212ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
2822ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    // A non-zero result means create a new cluster.
2823ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    if (result > 0 && !MakeNewCluster(frame_timestamp_ns))
2824ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      return false;
28252ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
28262ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    // Write queued (audio) frames.
28272ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    const int frame_count = WriteFramesAll();
28282ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    if (frame_count < 0)  // error
28292ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      return false;
28302ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
28312ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    // Write the current frame to the current cluster (if TestFrame
28322ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    // returns 0) or to a newly created cluster (TestFrame returns 1).
28332ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    if (result <= 1)
28342ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      return true;
28352ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
28362ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    // TestFrame returned 2, which means there was a large time
28372ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    // difference between the cluster and the frame itself.  Do the
28382ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    // test again, comparing the frame to the new cluster.
28392ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  }
28402ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian}
28412ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
28422ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanianbool Segment::CheckHeaderInfo() {
28432ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (!header_written_) {
28442ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    if (!WriteSegmentHeader())
28452ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      return false;
28462ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
28472ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    if (!seek_head_.AddSeekEntry(kMkvCluster, MaxOffset()))
28482ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      return false;
28492ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
28502ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    if (output_cues_ && cues_track_ == 0) {
28512ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      // Check for a video track
28522ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      for (uint32 i = 0; i < tracks_.track_entries_size(); ++i) {
28532ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian        const Track* const track = tracks_.GetTrackByIndex(i);
28542ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian        if (!track)
28552ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian          return false;
28562ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
28572ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian        if (tracks_.TrackIsVideo(track->number())) {
28582ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian          cues_track_ = track->number();
28592ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian          break;
28602ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian        }
28612ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      }
28622ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
28632ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      // Set first track found
28642ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      if (cues_track_ == 0) {
28652ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian        const Track* const track = tracks_.GetTrackByIndex(0);
28662ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian        if (!track)
28672ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian          return false;
28682ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
28692ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian        cues_track_ = track->number();
28702ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      }
28712ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    }
28722ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  }
28732ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  return true;
28742ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian}
28752ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
28762ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanianbool Segment::UpdateChunkName(const char* ext, char** name) const {
28772ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (!name || !ext)
28782ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return false;
28792ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
28802ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  char ext_chk[64];
28812ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian#ifdef _MSC_VER
28822ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  sprintf_s(ext_chk, sizeof(ext_chk), "_%06d.%s", chunk_count_, ext);
28832ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian#else
28842ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  snprintf(ext_chk, sizeof(ext_chk), "_%06d.%s", chunk_count_, ext);
28852ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian#endif
28862ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
28872ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  const size_t length = strlen(chunking_base_name_) + strlen(ext_chk) + 1;
28882ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  char* const str = new (std::nothrow) char[length];  // NOLINT
28892ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (!str)
28902ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return false;
28912ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
28922ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian#ifdef _MSC_VER
2893ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  strcpy_s(str, length - strlen(ext_chk), chunking_base_name_);
28942ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  strcat_s(str, length, ext_chk);
28952ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian#else
28962ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  strcpy(str, chunking_base_name_);
28972ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  strcat(str, ext_chk);
28982ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian#endif
28992ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
2900ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  delete[] * name;
29012ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  *name = str;
29022ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
29032ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  return true;
29042ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian}
29052ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
29062ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanianint64 Segment::MaxOffset() {
29072ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (!writer_header_)
29082ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return -1;
29092ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
29102ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  int64 offset = writer_header_->Position() - payload_pos_;
29112ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
29122ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (chunking_) {
29132ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    for (int32 i = 0; i < cluster_list_size_; ++i) {
29142ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      Cluster* const cluster = cluster_list_[i];
29152ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      offset += cluster->Size();
29162ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    }
29172ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
29182ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    if (writer_cues_)
29192ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      offset += writer_cues_->Position();
29202ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  }
29212ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
29222ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  return offset;
29232ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian}
29242ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
29252ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanianbool Segment::QueueFrame(Frame* frame) {
29262ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  const int32 new_size = frames_size_ + 1;
29272ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
29282ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (new_size > frames_capacity_) {
29292ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    // Add more frames.
29302ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    const int32 new_capacity = (!frames_capacity_) ? 2 : frames_capacity_ * 2;
29312ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
29322ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    if (new_capacity < 1)
29332ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      return false;
29342ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
2935ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    Frame** const frames = new (std::nothrow) Frame* [new_capacity];  // NOLINT
29362ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    if (!frames)
29372ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      return false;
29382ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
29392ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    for (int32 i = 0; i < frames_size_; ++i) {
29402ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      frames[i] = frames_[i];
29412ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    }
29422ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
2943ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    delete[] frames_;
29442ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    frames_ = frames;
29452ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    frames_capacity_ = new_capacity;
29462ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  }
29472ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
29482ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  frames_[frames_size_++] = frame;
29492ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
29502ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  return true;
29512ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian}
29522ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
29532ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanianint Segment::WriteFramesAll() {
29542ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (frames_ == NULL)
29552ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return 0;
29562ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
29572ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (cluster_list_size_ < 1)
29582ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return -1;
29592ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
2960ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  Cluster* const cluster = cluster_list_[cluster_list_size_ - 1];
29612ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
29622ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (!cluster)
29632ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    return -1;
29642ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
29652ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  const uint64 timecode_scale = segment_info_.timecode_scale();
29662ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
29672ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  for (int32 i = 0; i < frames_size_; ++i) {
29682ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    Frame*& frame = frames_[i];
29692ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    const uint64 frame_timestamp = frame->timestamp();  // ns
29702ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    const uint64 frame_timecode = frame_timestamp / timecode_scale;
29712ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
29722ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    if (frame->discard_padding() > 0) {
2973ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      if (!cluster->AddFrameWithDiscardPadding(
2974ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian              frame->frame(), frame->length(), frame->discard_padding(),
2975ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian              frame->track_number(), frame_timecode, frame->is_key())) {
29762ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian        return -1;
29772ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      }
29782ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    } else {
2979ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      if (!cluster->AddFrame(frame->frame(), frame->length(),
2980ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                             frame->track_number(), frame_timecode,
29812ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian                             frame->is_key())) {
29822ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian        return -1;
29832ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      }
29842ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    }
29852ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
29862ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    if (new_cuepoint_ && cues_track_ == frame->track_number()) {
29872ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      if (!AddCuePoint(frame_timestamp, cues_track_))
29882ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian        return -1;
29892ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    }
29902ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
29912ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    if (frame_timestamp > last_timestamp_)
29922ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      last_timestamp_ = frame_timestamp;
29932ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
29942ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    delete frame;
29952ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    frame = NULL;
29962ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  }
29972ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
29982ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  const int result = frames_size_;
29992ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  frames_size_ = 0;
30002ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
30012ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  return result;
30022ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian}
30032ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
30042ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanianbool Segment::WriteFramesLessThan(uint64 timestamp) {
30052ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  // Check |cluster_list_size_| to see if this is the first cluster. If it is
30062ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  // the first cluster the audio frames that are less than the first video
30072ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  // timesatmp will be written in a later step.
30082ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (frames_size_ > 0 && cluster_list_size_ > 0) {
30092ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    if (!frames_)
30102ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      return false;
30112ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
3012ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    Cluster* const cluster = cluster_list_[cluster_list_size_ - 1];
30132ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    if (!cluster)
30142ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      return false;
30152ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
30162ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    const uint64 timecode_scale = segment_info_.timecode_scale();
30172ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    int32 shift_left = 0;
30182ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
30192ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    // TODO(fgalligan): Change this to use the durations of frames instead of
30202ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    // the next frame's start time if the duration is accurate.
30212ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    for (int32 i = 1; i < frames_size_; ++i) {
30222ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      const Frame* const frame_curr = frames_[i];
30232ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
30242ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      if (frame_curr->timestamp() > timestamp)
30252ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian        break;
30262ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
3027ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      const Frame* const frame_prev = frames_[i - 1];
30282ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      const uint64 frame_timestamp = frame_prev->timestamp();
30292ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      const uint64 frame_timecode = frame_timestamp / timecode_scale;
30302ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      const int64 discard_padding = frame_prev->discard_padding();
30312ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
30322ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      if (discard_padding > 0) {
3033ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian        if (!cluster->AddFrameWithDiscardPadding(
3034ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                frame_prev->frame(), frame_prev->length(), discard_padding,
3035ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                frame_prev->track_number(), frame_timecode,
3036ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                frame_prev->is_key())) {
30372ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian          return false;
30382ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian        }
30392ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      } else {
3040ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian        if (!cluster->AddFrame(frame_prev->frame(), frame_prev->length(),
3041ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                               frame_prev->track_number(), frame_timecode,
30422ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian                               frame_prev->is_key())) {
30432ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian          return false;
30442ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian        }
30452ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      }
30462ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
30472ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      if (new_cuepoint_ && cues_track_ == frame_prev->track_number()) {
30482ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian        if (!AddCuePoint(frame_timestamp, cues_track_))
30492ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian          return false;
30502ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      }
30512ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
30522ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      ++shift_left;
30532ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      if (frame_timestamp > last_timestamp_)
30542ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian        last_timestamp_ = frame_timestamp;
30552ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
30562ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      delete frame_prev;
30572ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    }
30582ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
30592ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    if (shift_left > 0) {
30602ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      if (shift_left >= frames_size_)
30612ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian        return false;
30622ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
30632ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      const int32 new_frames_size = frames_size_ - shift_left;
30642ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      for (int32 i = 0; i < new_frames_size; ++i) {
3065ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian        frames_[i] = frames_[i + shift_left];
30662ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      }
30672ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
30682ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      frames_size_ = new_frames_size;
30692ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    }
30702ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  }
30712ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
30722ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  return true;
30732ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian}
30742ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
30752ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian}  // namespace mkvmuxer
3076