1233d2500723e5594f3e7c70896ffeeef32b9c950ywan// Copyright (c) 2012 The WebM project authors. All Rights Reserved.
2233d2500723e5594f3e7c70896ffeeef32b9c950ywan//
3233d2500723e5594f3e7c70896ffeeef32b9c950ywan// Use of this source code is governed by a BSD-style license
4233d2500723e5594f3e7c70896ffeeef32b9c950ywan// that can be found in the LICENSE file in the root of the source
5233d2500723e5594f3e7c70896ffeeef32b9c950ywan// tree. An additional intellectual property rights grant can be found
6233d2500723e5594f3e7c70896ffeeef32b9c950ywan// in the file PATENTS.  All contributing project authors may
7233d2500723e5594f3e7c70896ffeeef32b9c950ywan// be found in the AUTHORS file in the root of the source tree.
8233d2500723e5594f3e7c70896ffeeef32b9c950ywan
9233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include "mkvmuxer.hpp"
10233d2500723e5594f3e7c70896ffeeef32b9c950ywan
11233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include <climits>
12233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include <cstdio>
13233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include <cstdlib>
14233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include <cstring>
15233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include <ctime>
16233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include <new>
17233d2500723e5594f3e7c70896ffeeef32b9c950ywan
18233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include "mkvmuxerutil.hpp"
19233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include "mkvparser.hpp"
20233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include "mkvwriter.hpp"
21233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include "webmids.hpp"
22233d2500723e5594f3e7c70896ffeeef32b9c950ywan
23233d2500723e5594f3e7c70896ffeeef32b9c950ywan#ifdef _MSC_VER
24233d2500723e5594f3e7c70896ffeeef32b9c950ywan// Disable MSVC warnings that suggest making code non-portable.
25233d2500723e5594f3e7c70896ffeeef32b9c950ywan#pragma warning(disable:4996)
26233d2500723e5594f3e7c70896ffeeef32b9c950ywan#endif
27233d2500723e5594f3e7c70896ffeeef32b9c950ywan
28233d2500723e5594f3e7c70896ffeeef32b9c950ywannamespace mkvmuxer {
29233d2500723e5594f3e7c70896ffeeef32b9c950ywan
30233d2500723e5594f3e7c70896ffeeef32b9c950ywannamespace {
31233d2500723e5594f3e7c70896ffeeef32b9c950ywan// Deallocate the string designated by |dst|, and then copy the |src|
32233d2500723e5594f3e7c70896ffeeef32b9c950ywan// string to |dst|.  The caller owns both the |src| string and the
33233d2500723e5594f3e7c70896ffeeef32b9c950ywan// |dst| copy (hence the caller is responsible for eventually
34233d2500723e5594f3e7c70896ffeeef32b9c950ywan// deallocating the strings, either directly, or indirectly via
35233d2500723e5594f3e7c70896ffeeef32b9c950ywan// StrCpy).  Returns true if the source string was successfully copied
36233d2500723e5594f3e7c70896ffeeef32b9c950ywan// to the destination.
37233d2500723e5594f3e7c70896ffeeef32b9c950ywanbool StrCpy(const char* src, char** dst_ptr) {
38233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (dst_ptr == NULL)
39233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return false;
40233d2500723e5594f3e7c70896ffeeef32b9c950ywan
41233d2500723e5594f3e7c70896ffeeef32b9c950ywan  char*& dst = *dst_ptr;
42233d2500723e5594f3e7c70896ffeeef32b9c950ywan
43233d2500723e5594f3e7c70896ffeeef32b9c950ywan  delete [] dst;
44233d2500723e5594f3e7c70896ffeeef32b9c950ywan  dst = NULL;
45233d2500723e5594f3e7c70896ffeeef32b9c950ywan
46233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (src == NULL)
47233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return true;
48233d2500723e5594f3e7c70896ffeeef32b9c950ywan
49233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const size_t size = strlen(src) + 1;
50233d2500723e5594f3e7c70896ffeeef32b9c950ywan
51233d2500723e5594f3e7c70896ffeeef32b9c950ywan  dst = new (std::nothrow) char[size];  // NOLINT
52233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (dst == NULL)
53233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return false;
54233d2500723e5594f3e7c70896ffeeef32b9c950ywan
55233d2500723e5594f3e7c70896ffeeef32b9c950ywan  strcpy(dst, src);  // NOLINT
56233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return true;
57233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
58233d2500723e5594f3e7c70896ffeeef32b9c950ywan}  // namespace
59233d2500723e5594f3e7c70896ffeeef32b9c950ywan
60233d2500723e5594f3e7c70896ffeeef32b9c950ywan///////////////////////////////////////////////////////////////
61233d2500723e5594f3e7c70896ffeeef32b9c950ywan//
62233d2500723e5594f3e7c70896ffeeef32b9c950ywan// IMkvWriter Class
63233d2500723e5594f3e7c70896ffeeef32b9c950ywan
64233d2500723e5594f3e7c70896ffeeef32b9c950ywanIMkvWriter::IMkvWriter() {
65233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
66233d2500723e5594f3e7c70896ffeeef32b9c950ywan
67233d2500723e5594f3e7c70896ffeeef32b9c950ywanIMkvWriter::~IMkvWriter() {
68233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
69233d2500723e5594f3e7c70896ffeeef32b9c950ywan
70233d2500723e5594f3e7c70896ffeeef32b9c950ywanbool WriteEbmlHeader(IMkvWriter* writer) {
71233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // Level 0
72233d2500723e5594f3e7c70896ffeeef32b9c950ywan  uint64 size = EbmlElementSize(kMkvEBMLVersion, 1ULL);
73233d2500723e5594f3e7c70896ffeeef32b9c950ywan  size += EbmlElementSize(kMkvEBMLReadVersion, 1ULL);
74233d2500723e5594f3e7c70896ffeeef32b9c950ywan  size += EbmlElementSize(kMkvEBMLMaxIDLength, 4ULL);
75233d2500723e5594f3e7c70896ffeeef32b9c950ywan  size += EbmlElementSize(kMkvEBMLMaxSizeLength, 8ULL);
76233d2500723e5594f3e7c70896ffeeef32b9c950ywan  size += EbmlElementSize(kMkvDocType, "webm");
77233d2500723e5594f3e7c70896ffeeef32b9c950ywan  size += EbmlElementSize(kMkvDocTypeVersion, 2ULL);
78233d2500723e5594f3e7c70896ffeeef32b9c950ywan  size += EbmlElementSize(kMkvDocTypeReadVersion, 2ULL);
79233d2500723e5594f3e7c70896ffeeef32b9c950ywan
80233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (!WriteEbmlMasterElement(writer, kMkvEBML, size))
81233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return false;
82233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (!WriteEbmlElement(writer, kMkvEBMLVersion, 1ULL))
83233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return false;
84233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (!WriteEbmlElement(writer, kMkvEBMLReadVersion, 1ULL))
85233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return false;
86233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (!WriteEbmlElement(writer, kMkvEBMLMaxIDLength, 4ULL))
87233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return false;
88233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (!WriteEbmlElement(writer, kMkvEBMLMaxSizeLength, 8ULL))
89233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return false;
90233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (!WriteEbmlElement(writer, kMkvDocType, "webm"))
91233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return false;
92233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (!WriteEbmlElement(writer, kMkvDocTypeVersion, 2ULL))
93233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return false;
94233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (!WriteEbmlElement(writer, kMkvDocTypeReadVersion, 2ULL))
95233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return false;
96233d2500723e5594f3e7c70896ffeeef32b9c950ywan
97233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return true;
98233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
99233d2500723e5594f3e7c70896ffeeef32b9c950ywan
100233d2500723e5594f3e7c70896ffeeef32b9c950ywanbool ChunkedCopy(mkvparser::IMkvReader* source,
101233d2500723e5594f3e7c70896ffeeef32b9c950ywan                 mkvmuxer::IMkvWriter* dst,
102233d2500723e5594f3e7c70896ffeeef32b9c950ywan                 mkvmuxer::int64 start, int64 size) {
103233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // TODO(vigneshv): Check if this is a reasonable value.
104233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const uint32 kBufSize = 2048;
105233d2500723e5594f3e7c70896ffeeef32b9c950ywan  uint8* buf = new uint8[kBufSize];
106233d2500723e5594f3e7c70896ffeeef32b9c950ywan  int64 offset = start;
107233d2500723e5594f3e7c70896ffeeef32b9c950ywan  while (size > 0) {
108233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const int64 read_len = (size > kBufSize) ? kBufSize : size;
109233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (source->Read(offset, static_cast<long>(read_len), buf))
110233d2500723e5594f3e7c70896ffeeef32b9c950ywan      return false;
111233d2500723e5594f3e7c70896ffeeef32b9c950ywan    dst->Write(buf, static_cast<uint32>(read_len));
112233d2500723e5594f3e7c70896ffeeef32b9c950ywan    offset += read_len;
113233d2500723e5594f3e7c70896ffeeef32b9c950ywan    size -= read_len;
114233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
115233d2500723e5594f3e7c70896ffeeef32b9c950ywan  delete[] buf;
116233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return true;
117233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
118233d2500723e5594f3e7c70896ffeeef32b9c950ywan
119233d2500723e5594f3e7c70896ffeeef32b9c950ywan///////////////////////////////////////////////////////////////
120233d2500723e5594f3e7c70896ffeeef32b9c950ywan//
121233d2500723e5594f3e7c70896ffeeef32b9c950ywan// Frame Class
122233d2500723e5594f3e7c70896ffeeef32b9c950ywan
123233d2500723e5594f3e7c70896ffeeef32b9c950ywanFrame::Frame()
124233d2500723e5594f3e7c70896ffeeef32b9c950ywan    : add_id_(0),
125233d2500723e5594f3e7c70896ffeeef32b9c950ywan      additional_(NULL),
126233d2500723e5594f3e7c70896ffeeef32b9c950ywan      additional_length_(0),
127233d2500723e5594f3e7c70896ffeeef32b9c950ywan      duration_(0),
128233d2500723e5594f3e7c70896ffeeef32b9c950ywan      frame_(NULL),
129233d2500723e5594f3e7c70896ffeeef32b9c950ywan      is_key_(false),
130233d2500723e5594f3e7c70896ffeeef32b9c950ywan      length_(0),
131233d2500723e5594f3e7c70896ffeeef32b9c950ywan      track_number_(0),
132233d2500723e5594f3e7c70896ffeeef32b9c950ywan      timestamp_(0),
133233d2500723e5594f3e7c70896ffeeef32b9c950ywan      discard_padding_(0) {
134233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
135233d2500723e5594f3e7c70896ffeeef32b9c950ywan
136233d2500723e5594f3e7c70896ffeeef32b9c950ywanFrame::~Frame() {
137233d2500723e5594f3e7c70896ffeeef32b9c950ywan  delete [] frame_;
138233d2500723e5594f3e7c70896ffeeef32b9c950ywan  delete [] additional_;
139233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
140233d2500723e5594f3e7c70896ffeeef32b9c950ywan
141233d2500723e5594f3e7c70896ffeeef32b9c950ywanbool Frame::Init(const uint8* frame, uint64 length) {
142233d2500723e5594f3e7c70896ffeeef32b9c950ywan  uint8* const data =
143233d2500723e5594f3e7c70896ffeeef32b9c950ywan      new (std::nothrow) uint8[static_cast<size_t>(length)];  // NOLINT
144233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (!data)
145233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return false;
146233d2500723e5594f3e7c70896ffeeef32b9c950ywan
147233d2500723e5594f3e7c70896ffeeef32b9c950ywan  delete [] frame_;
148233d2500723e5594f3e7c70896ffeeef32b9c950ywan  frame_ = data;
149233d2500723e5594f3e7c70896ffeeef32b9c950ywan  length_ = length;
150233d2500723e5594f3e7c70896ffeeef32b9c950ywan
151233d2500723e5594f3e7c70896ffeeef32b9c950ywan  memcpy(frame_, frame, static_cast<size_t>(length_));
152233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return true;
153233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
154233d2500723e5594f3e7c70896ffeeef32b9c950ywan
155233d2500723e5594f3e7c70896ffeeef32b9c950ywanbool Frame::AddAdditionalData(const uint8* additional, uint64 length,
156233d2500723e5594f3e7c70896ffeeef32b9c950ywan                              uint64 add_id) {
157233d2500723e5594f3e7c70896ffeeef32b9c950ywan  uint8* const data =
158233d2500723e5594f3e7c70896ffeeef32b9c950ywan      new (std::nothrow) uint8[static_cast<size_t>(length)];  // NOLINT
159233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (!data)
160233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return false;
161233d2500723e5594f3e7c70896ffeeef32b9c950ywan
162233d2500723e5594f3e7c70896ffeeef32b9c950ywan  delete [] additional_;
163233d2500723e5594f3e7c70896ffeeef32b9c950ywan  additional_ = data;
164233d2500723e5594f3e7c70896ffeeef32b9c950ywan  additional_length_ = length;
165233d2500723e5594f3e7c70896ffeeef32b9c950ywan  add_id_ = add_id;
166233d2500723e5594f3e7c70896ffeeef32b9c950ywan
167233d2500723e5594f3e7c70896ffeeef32b9c950ywan  memcpy(additional_, additional, static_cast<size_t>(additional_length_));
168233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return true;
169233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
170233d2500723e5594f3e7c70896ffeeef32b9c950ywan
171233d2500723e5594f3e7c70896ffeeef32b9c950ywan///////////////////////////////////////////////////////////////
172233d2500723e5594f3e7c70896ffeeef32b9c950ywan//
173233d2500723e5594f3e7c70896ffeeef32b9c950ywan// CuePoint Class
174233d2500723e5594f3e7c70896ffeeef32b9c950ywan
175233d2500723e5594f3e7c70896ffeeef32b9c950ywanCuePoint::CuePoint()
176233d2500723e5594f3e7c70896ffeeef32b9c950ywan    : time_(0),
177233d2500723e5594f3e7c70896ffeeef32b9c950ywan      track_(0),
178233d2500723e5594f3e7c70896ffeeef32b9c950ywan      cluster_pos_(0),
179233d2500723e5594f3e7c70896ffeeef32b9c950ywan      block_number_(1),
180233d2500723e5594f3e7c70896ffeeef32b9c950ywan      output_block_number_(true) {
181233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
182233d2500723e5594f3e7c70896ffeeef32b9c950ywan
183233d2500723e5594f3e7c70896ffeeef32b9c950ywanCuePoint::~CuePoint() {
184233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
185233d2500723e5594f3e7c70896ffeeef32b9c950ywan
186233d2500723e5594f3e7c70896ffeeef32b9c950ywanbool CuePoint::Write(IMkvWriter* writer) const {
187233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (!writer || track_ < 1 || cluster_pos_ < 1)
188233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return false;
189233d2500723e5594f3e7c70896ffeeef32b9c950ywan
190233d2500723e5594f3e7c70896ffeeef32b9c950ywan  uint64 size = EbmlElementSize(kMkvCueClusterPosition, cluster_pos_);
191233d2500723e5594f3e7c70896ffeeef32b9c950ywan  size += EbmlElementSize(kMkvCueTrack, track_);
192233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (output_block_number_ && block_number_ > 1)
193233d2500723e5594f3e7c70896ffeeef32b9c950ywan    size += EbmlElementSize(kMkvCueBlockNumber, block_number_);
194233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const uint64 track_pos_size = EbmlMasterElementSize(kMkvCueTrackPositions,
195233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                                      size) + size;
196233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const uint64 payload_size = EbmlElementSize(kMkvCueTime, time_) +
197233d2500723e5594f3e7c70896ffeeef32b9c950ywan                              track_pos_size;
198233d2500723e5594f3e7c70896ffeeef32b9c950ywan
199233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (!WriteEbmlMasterElement(writer, kMkvCuePoint, payload_size))
200233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return false;
201233d2500723e5594f3e7c70896ffeeef32b9c950ywan
202233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const int64 payload_position = writer->Position();
203233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (payload_position < 0)
204233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return false;
205233d2500723e5594f3e7c70896ffeeef32b9c950ywan
206233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (!WriteEbmlElement(writer, kMkvCueTime, time_))
207233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return false;
208233d2500723e5594f3e7c70896ffeeef32b9c950ywan
209233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (!WriteEbmlMasterElement(writer, kMkvCueTrackPositions, size))
210233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return false;
211233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (!WriteEbmlElement(writer, kMkvCueTrack, track_))
212233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return false;
213233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (!WriteEbmlElement(writer, kMkvCueClusterPosition, cluster_pos_))
214233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return false;
215233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (output_block_number_ && block_number_ > 1)
216233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (!WriteEbmlElement(writer, kMkvCueBlockNumber, block_number_))
217233d2500723e5594f3e7c70896ffeeef32b9c950ywan      return false;
218233d2500723e5594f3e7c70896ffeeef32b9c950ywan
219233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const int64 stop_position = writer->Position();
220233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (stop_position < 0)
221233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return false;
222233d2500723e5594f3e7c70896ffeeef32b9c950ywan
223233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (stop_position - payload_position != static_cast<int64>(payload_size))
224233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return false;
225233d2500723e5594f3e7c70896ffeeef32b9c950ywan
226233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return true;
227233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
228233d2500723e5594f3e7c70896ffeeef32b9c950ywan
229233d2500723e5594f3e7c70896ffeeef32b9c950ywanuint64 CuePoint::PayloadSize() const {
230233d2500723e5594f3e7c70896ffeeef32b9c950ywan  uint64 size = EbmlElementSize(kMkvCueClusterPosition, cluster_pos_);
231233d2500723e5594f3e7c70896ffeeef32b9c950ywan  size += EbmlElementSize(kMkvCueTrack, track_);
232233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (output_block_number_ && block_number_ > 1)
233233d2500723e5594f3e7c70896ffeeef32b9c950ywan    size += EbmlElementSize(kMkvCueBlockNumber, block_number_);
234233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const uint64 track_pos_size = EbmlMasterElementSize(kMkvCueTrackPositions,
235233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                                      size) + size;
236233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const uint64 payload_size = EbmlElementSize(kMkvCueTime, time_) +
237233d2500723e5594f3e7c70896ffeeef32b9c950ywan                              track_pos_size;
238233d2500723e5594f3e7c70896ffeeef32b9c950ywan
239233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return payload_size;
240233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
241233d2500723e5594f3e7c70896ffeeef32b9c950ywan
242233d2500723e5594f3e7c70896ffeeef32b9c950ywanuint64 CuePoint::Size() const {
243233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const uint64 payload_size = PayloadSize();
244233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return EbmlMasterElementSize(kMkvCuePoint, payload_size) + payload_size;
245233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
246233d2500723e5594f3e7c70896ffeeef32b9c950ywan
247233d2500723e5594f3e7c70896ffeeef32b9c950ywan///////////////////////////////////////////////////////////////
248233d2500723e5594f3e7c70896ffeeef32b9c950ywan//
249233d2500723e5594f3e7c70896ffeeef32b9c950ywan// Cues Class
250233d2500723e5594f3e7c70896ffeeef32b9c950ywan
251233d2500723e5594f3e7c70896ffeeef32b9c950ywanCues::Cues()
252233d2500723e5594f3e7c70896ffeeef32b9c950ywan    : cue_entries_capacity_(0),
253233d2500723e5594f3e7c70896ffeeef32b9c950ywan      cue_entries_size_(0),
254233d2500723e5594f3e7c70896ffeeef32b9c950ywan      cue_entries_(NULL),
255233d2500723e5594f3e7c70896ffeeef32b9c950ywan      output_block_number_(true) {
256233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
257233d2500723e5594f3e7c70896ffeeef32b9c950ywan
258233d2500723e5594f3e7c70896ffeeef32b9c950ywanCues::~Cues() {
259233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (cue_entries_) {
260233d2500723e5594f3e7c70896ffeeef32b9c950ywan    for (int32 i = 0; i < cue_entries_size_; ++i) {
261233d2500723e5594f3e7c70896ffeeef32b9c950ywan      CuePoint* const cue = cue_entries_[i];
262233d2500723e5594f3e7c70896ffeeef32b9c950ywan      delete cue;
263233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
264233d2500723e5594f3e7c70896ffeeef32b9c950ywan    delete [] cue_entries_;
265233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
266233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
267233d2500723e5594f3e7c70896ffeeef32b9c950ywan
268233d2500723e5594f3e7c70896ffeeef32b9c950ywanbool Cues::AddCue(CuePoint* cue) {
269233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (!cue)
270233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return false;
271233d2500723e5594f3e7c70896ffeeef32b9c950ywan
272233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if ((cue_entries_size_ + 1) > cue_entries_capacity_) {
273233d2500723e5594f3e7c70896ffeeef32b9c950ywan    // Add more CuePoints.
274233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const int32 new_capacity =
275233d2500723e5594f3e7c70896ffeeef32b9c950ywan        (!cue_entries_capacity_) ? 2 : cue_entries_capacity_ * 2;
276233d2500723e5594f3e7c70896ffeeef32b9c950ywan
277233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (new_capacity < 1)
278233d2500723e5594f3e7c70896ffeeef32b9c950ywan      return false;
279233d2500723e5594f3e7c70896ffeeef32b9c950ywan
280233d2500723e5594f3e7c70896ffeeef32b9c950ywan    CuePoint** const cues =
281233d2500723e5594f3e7c70896ffeeef32b9c950ywan        new (std::nothrow) CuePoint*[new_capacity];  // NOLINT
282233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (!cues)
283233d2500723e5594f3e7c70896ffeeef32b9c950ywan      return false;
284233d2500723e5594f3e7c70896ffeeef32b9c950ywan
285233d2500723e5594f3e7c70896ffeeef32b9c950ywan    for (int32 i = 0; i < cue_entries_size_; ++i) {
286233d2500723e5594f3e7c70896ffeeef32b9c950ywan      cues[i] = cue_entries_[i];
287233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
288233d2500723e5594f3e7c70896ffeeef32b9c950ywan
289233d2500723e5594f3e7c70896ffeeef32b9c950ywan    delete [] cue_entries_;
290233d2500723e5594f3e7c70896ffeeef32b9c950ywan
291233d2500723e5594f3e7c70896ffeeef32b9c950ywan    cue_entries_ = cues;
292233d2500723e5594f3e7c70896ffeeef32b9c950ywan    cue_entries_capacity_ = new_capacity;
293233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
294233d2500723e5594f3e7c70896ffeeef32b9c950ywan
295233d2500723e5594f3e7c70896ffeeef32b9c950ywan  cue->set_output_block_number(output_block_number_);
296233d2500723e5594f3e7c70896ffeeef32b9c950ywan  cue_entries_[cue_entries_size_++] = cue;
297233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return true;
298233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
299233d2500723e5594f3e7c70896ffeeef32b9c950ywan
300233d2500723e5594f3e7c70896ffeeef32b9c950ywanCuePoint* Cues::GetCueByIndex(int32 index) const {
301233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (cue_entries_ == NULL)
302233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return NULL;
303233d2500723e5594f3e7c70896ffeeef32b9c950ywan
304233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (index >= cue_entries_size_)
305233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return NULL;
306233d2500723e5594f3e7c70896ffeeef32b9c950ywan
307233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return cue_entries_[index];
308233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
309233d2500723e5594f3e7c70896ffeeef32b9c950ywan
310233d2500723e5594f3e7c70896ffeeef32b9c950ywanuint64 Cues::Size() {
311233d2500723e5594f3e7c70896ffeeef32b9c950ywan  uint64 size = 0;
312233d2500723e5594f3e7c70896ffeeef32b9c950ywan  for (int32 i = 0; i < cue_entries_size_; ++i)
313233d2500723e5594f3e7c70896ffeeef32b9c950ywan    size += GetCueByIndex(i)->Size();
314233d2500723e5594f3e7c70896ffeeef32b9c950ywan  size += EbmlMasterElementSize(kMkvCues, size);
315233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return size;
316233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
317233d2500723e5594f3e7c70896ffeeef32b9c950ywan
318233d2500723e5594f3e7c70896ffeeef32b9c950ywanbool Cues::Write(IMkvWriter* writer) const {
319233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (!writer)
320233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return false;
321233d2500723e5594f3e7c70896ffeeef32b9c950ywan
322233d2500723e5594f3e7c70896ffeeef32b9c950ywan  uint64 size = 0;
323233d2500723e5594f3e7c70896ffeeef32b9c950ywan  for (int32 i = 0; i < cue_entries_size_; ++i) {
324233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const CuePoint* const cue = GetCueByIndex(i);
325233d2500723e5594f3e7c70896ffeeef32b9c950ywan
326233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (!cue)
327233d2500723e5594f3e7c70896ffeeef32b9c950ywan      return false;
328233d2500723e5594f3e7c70896ffeeef32b9c950ywan
329233d2500723e5594f3e7c70896ffeeef32b9c950ywan    size += cue->Size();
330233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
331233d2500723e5594f3e7c70896ffeeef32b9c950ywan
332233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (!WriteEbmlMasterElement(writer, kMkvCues, size))
333233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return false;
334233d2500723e5594f3e7c70896ffeeef32b9c950ywan
335233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const int64 payload_position = writer->Position();
336233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (payload_position < 0)
337233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return false;
338233d2500723e5594f3e7c70896ffeeef32b9c950ywan
339233d2500723e5594f3e7c70896ffeeef32b9c950ywan  for (int32 i = 0; i < cue_entries_size_; ++i) {
340233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const CuePoint* const cue = GetCueByIndex(i);
341233d2500723e5594f3e7c70896ffeeef32b9c950ywan
342233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (!cue->Write(writer))
343233d2500723e5594f3e7c70896ffeeef32b9c950ywan      return false;
344233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
345233d2500723e5594f3e7c70896ffeeef32b9c950ywan
346233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const int64 stop_position = writer->Position();
347233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (stop_position < 0)
348233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return false;
349233d2500723e5594f3e7c70896ffeeef32b9c950ywan
350233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (stop_position - payload_position != static_cast<int64>(size))
351233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return false;
352233d2500723e5594f3e7c70896ffeeef32b9c950ywan
353233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return true;
354233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
355233d2500723e5594f3e7c70896ffeeef32b9c950ywan
356233d2500723e5594f3e7c70896ffeeef32b9c950ywan///////////////////////////////////////////////////////////////
357233d2500723e5594f3e7c70896ffeeef32b9c950ywan//
358233d2500723e5594f3e7c70896ffeeef32b9c950ywan// ContentEncAESSettings Class
359233d2500723e5594f3e7c70896ffeeef32b9c950ywan
360233d2500723e5594f3e7c70896ffeeef32b9c950ywanContentEncAESSettings::ContentEncAESSettings() : cipher_mode_(kCTR) {}
361233d2500723e5594f3e7c70896ffeeef32b9c950ywan
362233d2500723e5594f3e7c70896ffeeef32b9c950ywanuint64 ContentEncAESSettings::Size() const {
363233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const uint64 payload = PayloadSize();
364233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const uint64 size =
365233d2500723e5594f3e7c70896ffeeef32b9c950ywan      EbmlMasterElementSize(kMkvContentEncAESSettings, payload) + payload;
366233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return size;
367233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
368233d2500723e5594f3e7c70896ffeeef32b9c950ywan
369233d2500723e5594f3e7c70896ffeeef32b9c950ywanbool ContentEncAESSettings::Write(IMkvWriter* writer) const {
370233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const uint64 payload = PayloadSize();
371233d2500723e5594f3e7c70896ffeeef32b9c950ywan
372233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (!WriteEbmlMasterElement(writer, kMkvContentEncAESSettings, payload))
373233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return false;
374233d2500723e5594f3e7c70896ffeeef32b9c950ywan
375233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const int64 payload_position = writer->Position();
376233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (payload_position < 0)
377233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return false;
378233d2500723e5594f3e7c70896ffeeef32b9c950ywan
379233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (!WriteEbmlElement(writer, kMkvAESSettingsCipherMode, cipher_mode_))
380233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return false;
381233d2500723e5594f3e7c70896ffeeef32b9c950ywan
382233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const int64 stop_position = writer->Position();
383233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (stop_position < 0 ||
384233d2500723e5594f3e7c70896ffeeef32b9c950ywan      stop_position - payload_position != static_cast<int64>(payload))
385233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return false;
386233d2500723e5594f3e7c70896ffeeef32b9c950ywan
387233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return true;
388233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
389233d2500723e5594f3e7c70896ffeeef32b9c950ywan
390233d2500723e5594f3e7c70896ffeeef32b9c950ywanuint64 ContentEncAESSettings::PayloadSize() const {
391233d2500723e5594f3e7c70896ffeeef32b9c950ywan  uint64 size = EbmlElementSize(kMkvAESSettingsCipherMode, cipher_mode_);
392233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return size;
393233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
394233d2500723e5594f3e7c70896ffeeef32b9c950ywan
395233d2500723e5594f3e7c70896ffeeef32b9c950ywan///////////////////////////////////////////////////////////////
396233d2500723e5594f3e7c70896ffeeef32b9c950ywan//
397233d2500723e5594f3e7c70896ffeeef32b9c950ywan// ContentEncoding Class
398233d2500723e5594f3e7c70896ffeeef32b9c950ywan
399233d2500723e5594f3e7c70896ffeeef32b9c950ywanContentEncoding::ContentEncoding()
400233d2500723e5594f3e7c70896ffeeef32b9c950ywan    : enc_algo_(5),
401233d2500723e5594f3e7c70896ffeeef32b9c950ywan      enc_key_id_(NULL),
402233d2500723e5594f3e7c70896ffeeef32b9c950ywan      encoding_order_(0),
403233d2500723e5594f3e7c70896ffeeef32b9c950ywan      encoding_scope_(1),
404233d2500723e5594f3e7c70896ffeeef32b9c950ywan      encoding_type_(1),
405233d2500723e5594f3e7c70896ffeeef32b9c950ywan      enc_key_id_length_(0) {
406233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
407233d2500723e5594f3e7c70896ffeeef32b9c950ywan
408233d2500723e5594f3e7c70896ffeeef32b9c950ywanContentEncoding::~ContentEncoding() {
409233d2500723e5594f3e7c70896ffeeef32b9c950ywan  delete [] enc_key_id_;
410233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
411233d2500723e5594f3e7c70896ffeeef32b9c950ywan
412233d2500723e5594f3e7c70896ffeeef32b9c950ywanbool ContentEncoding::SetEncryptionID(const uint8* id, uint64 length) {
413233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (!id || length < 1)
414233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return false;
415233d2500723e5594f3e7c70896ffeeef32b9c950ywan
416233d2500723e5594f3e7c70896ffeeef32b9c950ywan  delete [] enc_key_id_;
417233d2500723e5594f3e7c70896ffeeef32b9c950ywan
418233d2500723e5594f3e7c70896ffeeef32b9c950ywan  enc_key_id_ =
419233d2500723e5594f3e7c70896ffeeef32b9c950ywan      new (std::nothrow) uint8[static_cast<size_t>(length)];  // NOLINT
420233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (!enc_key_id_)
421233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return false;
422233d2500723e5594f3e7c70896ffeeef32b9c950ywan
423233d2500723e5594f3e7c70896ffeeef32b9c950ywan  memcpy(enc_key_id_, id, static_cast<size_t>(length));
424233d2500723e5594f3e7c70896ffeeef32b9c950ywan  enc_key_id_length_ = length;
425233d2500723e5594f3e7c70896ffeeef32b9c950ywan
426233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return true;
427233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
428233d2500723e5594f3e7c70896ffeeef32b9c950ywan
429233d2500723e5594f3e7c70896ffeeef32b9c950ywanuint64 ContentEncoding::Size() const {
430233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const uint64 encryption_size = EncryptionSize();
431233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const uint64 encoding_size = EncodingSize(0, encryption_size);
432233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const uint64 encodings_size = EbmlMasterElementSize(kMkvContentEncoding,
433233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                                      encoding_size) +
434233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                encoding_size;
435233d2500723e5594f3e7c70896ffeeef32b9c950ywan
436233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return encodings_size;
437233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
438233d2500723e5594f3e7c70896ffeeef32b9c950ywan
439233d2500723e5594f3e7c70896ffeeef32b9c950ywanbool ContentEncoding::Write(IMkvWriter* writer) const {
440233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const uint64 encryption_size = EncryptionSize();
441233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const uint64 encoding_size = EncodingSize(0, encryption_size);
442233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const uint64 size = EbmlMasterElementSize(kMkvContentEncoding,
443233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                            encoding_size) +
444233d2500723e5594f3e7c70896ffeeef32b9c950ywan                      encoding_size;
445233d2500723e5594f3e7c70896ffeeef32b9c950ywan
446233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const int64 payload_position = writer->Position();
447233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (payload_position < 0)
448233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return false;
449233d2500723e5594f3e7c70896ffeeef32b9c950ywan
450233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (!WriteEbmlMasterElement(writer, kMkvContentEncoding, encoding_size))
451233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return false;
452233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (!WriteEbmlElement(writer, kMkvContentEncodingOrder, encoding_order_))
453233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return false;
454233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (!WriteEbmlElement(writer, kMkvContentEncodingScope, encoding_scope_))
455233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return false;
456233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (!WriteEbmlElement(writer, kMkvContentEncodingType, encoding_type_))
457233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return false;
458233d2500723e5594f3e7c70896ffeeef32b9c950ywan
459233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (!WriteEbmlMasterElement(writer, kMkvContentEncryption, encryption_size))
460233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return false;
461233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (!WriteEbmlElement(writer, kMkvContentEncAlgo, enc_algo_))
462233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return false;
463233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (!WriteEbmlElement(writer,
464233d2500723e5594f3e7c70896ffeeef32b9c950ywan                        kMkvContentEncKeyID,
465233d2500723e5594f3e7c70896ffeeef32b9c950ywan                        enc_key_id_,
466233d2500723e5594f3e7c70896ffeeef32b9c950ywan                        enc_key_id_length_))
467233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return false;
468233d2500723e5594f3e7c70896ffeeef32b9c950ywan
469233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (!enc_aes_settings_.Write(writer))
470233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return false;
471233d2500723e5594f3e7c70896ffeeef32b9c950ywan
472233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const int64 stop_position = writer->Position();
473233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (stop_position < 0 ||
474233d2500723e5594f3e7c70896ffeeef32b9c950ywan      stop_position - payload_position != static_cast<int64>(size))
475233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return false;
476233d2500723e5594f3e7c70896ffeeef32b9c950ywan
477233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return true;
478233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
479233d2500723e5594f3e7c70896ffeeef32b9c950ywan
480233d2500723e5594f3e7c70896ffeeef32b9c950ywanuint64 ContentEncoding::EncodingSize(uint64 compresion_size,
481233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                     uint64 encryption_size) const {
482233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // TODO(fgalligan): Add support for compression settings.
483233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (compresion_size != 0)
484233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return 0;
485233d2500723e5594f3e7c70896ffeeef32b9c950ywan
486233d2500723e5594f3e7c70896ffeeef32b9c950ywan  uint64 encoding_size = 0;
487233d2500723e5594f3e7c70896ffeeef32b9c950ywan
488233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (encryption_size > 0) {
489233d2500723e5594f3e7c70896ffeeef32b9c950ywan    encoding_size += EbmlMasterElementSize(kMkvContentEncryption,
490233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                           encryption_size) +
491233d2500723e5594f3e7c70896ffeeef32b9c950ywan                     encryption_size;
492233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
493233d2500723e5594f3e7c70896ffeeef32b9c950ywan  encoding_size += EbmlElementSize(kMkvContentEncodingType, encoding_type_);
494233d2500723e5594f3e7c70896ffeeef32b9c950ywan  encoding_size += EbmlElementSize(kMkvContentEncodingScope, encoding_scope_);
495233d2500723e5594f3e7c70896ffeeef32b9c950ywan  encoding_size += EbmlElementSize(kMkvContentEncodingOrder, encoding_order_);
496233d2500723e5594f3e7c70896ffeeef32b9c950ywan
497233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return encoding_size;
498233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
499233d2500723e5594f3e7c70896ffeeef32b9c950ywan
500233d2500723e5594f3e7c70896ffeeef32b9c950ywanuint64 ContentEncoding::EncryptionSize() const {
501233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const uint64 aes_size = enc_aes_settings_.Size();
502233d2500723e5594f3e7c70896ffeeef32b9c950ywan
503233d2500723e5594f3e7c70896ffeeef32b9c950ywan  uint64 encryption_size = EbmlElementSize(kMkvContentEncKeyID,
504233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                           enc_key_id_,
505233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                           enc_key_id_length_);
506233d2500723e5594f3e7c70896ffeeef32b9c950ywan  encryption_size += EbmlElementSize(kMkvContentEncAlgo, enc_algo_);
507233d2500723e5594f3e7c70896ffeeef32b9c950ywan
508233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return encryption_size + aes_size;
509233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
510233d2500723e5594f3e7c70896ffeeef32b9c950ywan
511233d2500723e5594f3e7c70896ffeeef32b9c950ywan///////////////////////////////////////////////////////////////
512233d2500723e5594f3e7c70896ffeeef32b9c950ywan//
513233d2500723e5594f3e7c70896ffeeef32b9c950ywan// Track Class
514233d2500723e5594f3e7c70896ffeeef32b9c950ywan
515233d2500723e5594f3e7c70896ffeeef32b9c950ywanTrack::Track(unsigned int* seed)
516233d2500723e5594f3e7c70896ffeeef32b9c950ywan    : codec_id_(NULL),
517233d2500723e5594f3e7c70896ffeeef32b9c950ywan      codec_private_(NULL),
518233d2500723e5594f3e7c70896ffeeef32b9c950ywan      language_(NULL),
519233d2500723e5594f3e7c70896ffeeef32b9c950ywan      max_block_additional_id_(0),
520233d2500723e5594f3e7c70896ffeeef32b9c950ywan      name_(NULL),
521233d2500723e5594f3e7c70896ffeeef32b9c950ywan      number_(0),
522233d2500723e5594f3e7c70896ffeeef32b9c950ywan      type_(0),
523233d2500723e5594f3e7c70896ffeeef32b9c950ywan      uid_(MakeUID(seed)),
524233d2500723e5594f3e7c70896ffeeef32b9c950ywan      codec_delay_(0),
525233d2500723e5594f3e7c70896ffeeef32b9c950ywan      seek_pre_roll_(0),
526233d2500723e5594f3e7c70896ffeeef32b9c950ywan      codec_private_length_(0),
527233d2500723e5594f3e7c70896ffeeef32b9c950ywan      content_encoding_entries_(NULL),
528233d2500723e5594f3e7c70896ffeeef32b9c950ywan      content_encoding_entries_size_(0) {
529233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
530233d2500723e5594f3e7c70896ffeeef32b9c950ywan
531233d2500723e5594f3e7c70896ffeeef32b9c950ywanTrack::~Track() {
532233d2500723e5594f3e7c70896ffeeef32b9c950ywan  delete [] codec_id_;
533233d2500723e5594f3e7c70896ffeeef32b9c950ywan  delete [] codec_private_;
534233d2500723e5594f3e7c70896ffeeef32b9c950ywan  delete [] language_;
535233d2500723e5594f3e7c70896ffeeef32b9c950ywan  delete [] name_;
536233d2500723e5594f3e7c70896ffeeef32b9c950ywan
537233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (content_encoding_entries_) {
538233d2500723e5594f3e7c70896ffeeef32b9c950ywan    for (uint32 i = 0; i < content_encoding_entries_size_; ++i) {
539233d2500723e5594f3e7c70896ffeeef32b9c950ywan      ContentEncoding* const encoding = content_encoding_entries_[i];
540233d2500723e5594f3e7c70896ffeeef32b9c950ywan      delete encoding;
541233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
542233d2500723e5594f3e7c70896ffeeef32b9c950ywan    delete [] content_encoding_entries_;
543233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
544233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
545233d2500723e5594f3e7c70896ffeeef32b9c950ywan
546233d2500723e5594f3e7c70896ffeeef32b9c950ywanbool Track::AddContentEncoding() {
547233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const uint32 count = content_encoding_entries_size_ + 1;
548233d2500723e5594f3e7c70896ffeeef32b9c950ywan
549233d2500723e5594f3e7c70896ffeeef32b9c950ywan  ContentEncoding** const content_encoding_entries =
550233d2500723e5594f3e7c70896ffeeef32b9c950ywan      new (std::nothrow) ContentEncoding*[count];  // NOLINT
551233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (!content_encoding_entries)
552233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return false;
553233d2500723e5594f3e7c70896ffeeef32b9c950ywan
554233d2500723e5594f3e7c70896ffeeef32b9c950ywan  ContentEncoding* const content_encoding =
555233d2500723e5594f3e7c70896ffeeef32b9c950ywan      new (std::nothrow) ContentEncoding();  // NOLINT
556233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (!content_encoding) {
557233d2500723e5594f3e7c70896ffeeef32b9c950ywan    delete [] content_encoding_entries;
558233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return false;
559233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
560233d2500723e5594f3e7c70896ffeeef32b9c950ywan
561233d2500723e5594f3e7c70896ffeeef32b9c950ywan  for (uint32 i = 0; i < content_encoding_entries_size_; ++i) {
562233d2500723e5594f3e7c70896ffeeef32b9c950ywan    content_encoding_entries[i] = content_encoding_entries_[i];
563233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
564233d2500723e5594f3e7c70896ffeeef32b9c950ywan
565233d2500723e5594f3e7c70896ffeeef32b9c950ywan  delete [] content_encoding_entries_;
566233d2500723e5594f3e7c70896ffeeef32b9c950ywan
567233d2500723e5594f3e7c70896ffeeef32b9c950ywan  content_encoding_entries_ = content_encoding_entries;
568233d2500723e5594f3e7c70896ffeeef32b9c950ywan  content_encoding_entries_[content_encoding_entries_size_] = content_encoding;
569233d2500723e5594f3e7c70896ffeeef32b9c950ywan  content_encoding_entries_size_ = count;
570233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return true;
571233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
572233d2500723e5594f3e7c70896ffeeef32b9c950ywan
573233d2500723e5594f3e7c70896ffeeef32b9c950ywanContentEncoding* Track::GetContentEncodingByIndex(uint32 index) const {
574233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (content_encoding_entries_ == NULL)
575233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return NULL;
576233d2500723e5594f3e7c70896ffeeef32b9c950ywan
577233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (index >= content_encoding_entries_size_)
578233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return NULL;
579233d2500723e5594f3e7c70896ffeeef32b9c950ywan
580233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return content_encoding_entries_[index];
581233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
582233d2500723e5594f3e7c70896ffeeef32b9c950ywan
583233d2500723e5594f3e7c70896ffeeef32b9c950ywanuint64 Track::PayloadSize() const {
584233d2500723e5594f3e7c70896ffeeef32b9c950ywan  uint64 size = EbmlElementSize(kMkvTrackNumber, number_);
585233d2500723e5594f3e7c70896ffeeef32b9c950ywan  size += EbmlElementSize(kMkvTrackUID, uid_);
586233d2500723e5594f3e7c70896ffeeef32b9c950ywan  size += EbmlElementSize(kMkvTrackType, type_);
587233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (codec_id_)
588233d2500723e5594f3e7c70896ffeeef32b9c950ywan    size += EbmlElementSize(kMkvCodecID, codec_id_);
589233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (codec_private_)
590233d2500723e5594f3e7c70896ffeeef32b9c950ywan    size += EbmlElementSize(kMkvCodecPrivate,
591233d2500723e5594f3e7c70896ffeeef32b9c950ywan                            codec_private_,
592233d2500723e5594f3e7c70896ffeeef32b9c950ywan                            codec_private_length_);
593233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (language_)
594233d2500723e5594f3e7c70896ffeeef32b9c950ywan    size += EbmlElementSize(kMkvLanguage, language_);
595233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (name_)
596233d2500723e5594f3e7c70896ffeeef32b9c950ywan    size += EbmlElementSize(kMkvName, name_);
597233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (max_block_additional_id_)
598233d2500723e5594f3e7c70896ffeeef32b9c950ywan    size += EbmlElementSize(kMkvMaxBlockAdditionID, max_block_additional_id_);
599233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (codec_delay_)
600233d2500723e5594f3e7c70896ffeeef32b9c950ywan    size += EbmlElementSize(kMkvCodecDelay, codec_delay_);
601233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (seek_pre_roll_)
602233d2500723e5594f3e7c70896ffeeef32b9c950ywan    size += EbmlElementSize(kMkvSeekPreRoll, seek_pre_roll_);
603233d2500723e5594f3e7c70896ffeeef32b9c950ywan
604233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (content_encoding_entries_size_ > 0) {
605233d2500723e5594f3e7c70896ffeeef32b9c950ywan    uint64 content_encodings_size = 0;
606233d2500723e5594f3e7c70896ffeeef32b9c950ywan    for (uint32 i = 0; i < content_encoding_entries_size_; ++i) {
607233d2500723e5594f3e7c70896ffeeef32b9c950ywan      ContentEncoding* const encoding = content_encoding_entries_[i];
608233d2500723e5594f3e7c70896ffeeef32b9c950ywan      content_encodings_size += encoding->Size();
609233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
610233d2500723e5594f3e7c70896ffeeef32b9c950ywan
611233d2500723e5594f3e7c70896ffeeef32b9c950ywan    size += EbmlMasterElementSize(kMkvContentEncodings,
612233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                  content_encodings_size) +
613233d2500723e5594f3e7c70896ffeeef32b9c950ywan            content_encodings_size;
614233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
615233d2500723e5594f3e7c70896ffeeef32b9c950ywan
616233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return size;
617233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
618233d2500723e5594f3e7c70896ffeeef32b9c950ywan
619233d2500723e5594f3e7c70896ffeeef32b9c950ywanuint64 Track::Size() const {
620233d2500723e5594f3e7c70896ffeeef32b9c950ywan  uint64 size = PayloadSize();
621233d2500723e5594f3e7c70896ffeeef32b9c950ywan  size += EbmlMasterElementSize(kMkvTrackEntry, size);
622233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return size;
623233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
624233d2500723e5594f3e7c70896ffeeef32b9c950ywan
625233d2500723e5594f3e7c70896ffeeef32b9c950ywanbool Track::Write(IMkvWriter* writer) const {
626233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (!writer)
627233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return false;
628233d2500723e5594f3e7c70896ffeeef32b9c950ywan
629233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // |size| may be bigger than what is written out in this function because
630233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // derived classes may write out more data in the Track element.
631233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const uint64 payload_size = PayloadSize();
632233d2500723e5594f3e7c70896ffeeef32b9c950ywan
633233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (!WriteEbmlMasterElement(writer, kMkvTrackEntry, payload_size))
634233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return false;
635233d2500723e5594f3e7c70896ffeeef32b9c950ywan
636233d2500723e5594f3e7c70896ffeeef32b9c950ywan  uint64 size = EbmlElementSize(kMkvTrackNumber, number_);
637233d2500723e5594f3e7c70896ffeeef32b9c950ywan  size += EbmlElementSize(kMkvTrackUID, uid_);
638233d2500723e5594f3e7c70896ffeeef32b9c950ywan  size += EbmlElementSize(kMkvTrackType, type_);
639233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (codec_id_)
640233d2500723e5594f3e7c70896ffeeef32b9c950ywan    size += EbmlElementSize(kMkvCodecID, codec_id_);
641233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (codec_private_)
642233d2500723e5594f3e7c70896ffeeef32b9c950ywan    size += EbmlElementSize(kMkvCodecPrivate,
643233d2500723e5594f3e7c70896ffeeef32b9c950ywan                            codec_private_,
644233d2500723e5594f3e7c70896ffeeef32b9c950ywan                            codec_private_length_);
645233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (language_)
646233d2500723e5594f3e7c70896ffeeef32b9c950ywan    size += EbmlElementSize(kMkvLanguage, language_);
647233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (name_)
648233d2500723e5594f3e7c70896ffeeef32b9c950ywan    size += EbmlElementSize(kMkvName, name_);
649233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (max_block_additional_id_)
650233d2500723e5594f3e7c70896ffeeef32b9c950ywan    size += EbmlElementSize(kMkvMaxBlockAdditionID, max_block_additional_id_);
651233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (codec_delay_)
652233d2500723e5594f3e7c70896ffeeef32b9c950ywan    size += EbmlElementSize(kMkvCodecDelay, codec_delay_);
653233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (seek_pre_roll_)
654233d2500723e5594f3e7c70896ffeeef32b9c950ywan    size += EbmlElementSize(kMkvSeekPreRoll, seek_pre_roll_);
655233d2500723e5594f3e7c70896ffeeef32b9c950ywan
656233d2500723e5594f3e7c70896ffeeef32b9c950ywan
657233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const int64 payload_position = writer->Position();
658233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (payload_position < 0)
659233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return false;
660233d2500723e5594f3e7c70896ffeeef32b9c950ywan
661233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (!WriteEbmlElement(writer, kMkvTrackNumber, number_))
662233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return false;
663233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (!WriteEbmlElement(writer, kMkvTrackUID, uid_))
664233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return false;
665233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (!WriteEbmlElement(writer, kMkvTrackType, type_))
666233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return false;
667233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (max_block_additional_id_) {
668233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (!WriteEbmlElement(writer,
669233d2500723e5594f3e7c70896ffeeef32b9c950ywan                          kMkvMaxBlockAdditionID,
670233d2500723e5594f3e7c70896ffeeef32b9c950ywan                          max_block_additional_id_)) {
671233d2500723e5594f3e7c70896ffeeef32b9c950ywan      return false;
672233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
673233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
674233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (codec_delay_) {
675233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (!WriteEbmlElement(writer, kMkvCodecDelay, codec_delay_))
676233d2500723e5594f3e7c70896ffeeef32b9c950ywan      return false;
677233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
678233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (seek_pre_roll_) {
679233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (!WriteEbmlElement(writer, kMkvSeekPreRoll, seek_pre_roll_))
680233d2500723e5594f3e7c70896ffeeef32b9c950ywan      return false;
681233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
682233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (codec_id_) {
683233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (!WriteEbmlElement(writer, kMkvCodecID, codec_id_))
684233d2500723e5594f3e7c70896ffeeef32b9c950ywan      return false;
685233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
686233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (codec_private_) {
687233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (!WriteEbmlElement(writer,
688233d2500723e5594f3e7c70896ffeeef32b9c950ywan                          kMkvCodecPrivate,
689233d2500723e5594f3e7c70896ffeeef32b9c950ywan                          codec_private_,
690233d2500723e5594f3e7c70896ffeeef32b9c950ywan                          codec_private_length_))
691233d2500723e5594f3e7c70896ffeeef32b9c950ywan      return false;
692233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
693233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (language_) {
694233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (!WriteEbmlElement(writer, kMkvLanguage, language_))
695233d2500723e5594f3e7c70896ffeeef32b9c950ywan      return false;
696233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
697233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (name_) {
698233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (!WriteEbmlElement(writer, kMkvName, name_))
699233d2500723e5594f3e7c70896ffeeef32b9c950ywan      return false;
700233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
701233d2500723e5594f3e7c70896ffeeef32b9c950ywan
702233d2500723e5594f3e7c70896ffeeef32b9c950ywan  int64 stop_position = writer->Position();
703233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (stop_position < 0 ||
704233d2500723e5594f3e7c70896ffeeef32b9c950ywan      stop_position - payload_position != static_cast<int64>(size))
705233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return false;
706233d2500723e5594f3e7c70896ffeeef32b9c950ywan
707233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (content_encoding_entries_size_ > 0) {
708233d2500723e5594f3e7c70896ffeeef32b9c950ywan    uint64 content_encodings_size = 0;
709233d2500723e5594f3e7c70896ffeeef32b9c950ywan    for (uint32 i = 0; i < content_encoding_entries_size_; ++i) {
710233d2500723e5594f3e7c70896ffeeef32b9c950ywan      ContentEncoding* const encoding = content_encoding_entries_[i];
711233d2500723e5594f3e7c70896ffeeef32b9c950ywan      content_encodings_size += encoding->Size();
712233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
713233d2500723e5594f3e7c70896ffeeef32b9c950ywan
714233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (!WriteEbmlMasterElement(writer,
715233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                kMkvContentEncodings,
716233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                content_encodings_size))
717233d2500723e5594f3e7c70896ffeeef32b9c950ywan      return false;
718233d2500723e5594f3e7c70896ffeeef32b9c950ywan
719233d2500723e5594f3e7c70896ffeeef32b9c950ywan    for (uint32 i = 0; i < content_encoding_entries_size_; ++i) {
720233d2500723e5594f3e7c70896ffeeef32b9c950ywan      ContentEncoding* const encoding = content_encoding_entries_[i];
721233d2500723e5594f3e7c70896ffeeef32b9c950ywan      if (!encoding->Write(writer))
722233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return false;
723233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
724233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
725233d2500723e5594f3e7c70896ffeeef32b9c950ywan
726233d2500723e5594f3e7c70896ffeeef32b9c950ywan  stop_position = writer->Position();
727233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (stop_position < 0)
728233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return false;
729233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return true;
730233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
731233d2500723e5594f3e7c70896ffeeef32b9c950ywan
732233d2500723e5594f3e7c70896ffeeef32b9c950ywanbool Track::SetCodecPrivate(const uint8* codec_private, uint64 length) {
733233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (!codec_private || length < 1)
734233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return false;
735233d2500723e5594f3e7c70896ffeeef32b9c950ywan
736233d2500723e5594f3e7c70896ffeeef32b9c950ywan  delete [] codec_private_;
737233d2500723e5594f3e7c70896ffeeef32b9c950ywan
738233d2500723e5594f3e7c70896ffeeef32b9c950ywan  codec_private_ =
739233d2500723e5594f3e7c70896ffeeef32b9c950ywan      new (std::nothrow) uint8[static_cast<size_t>(length)];  // NOLINT
740233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (!codec_private_)
741233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return false;
742233d2500723e5594f3e7c70896ffeeef32b9c950ywan
743233d2500723e5594f3e7c70896ffeeef32b9c950ywan  memcpy(codec_private_, codec_private, static_cast<size_t>(length));
744233d2500723e5594f3e7c70896ffeeef32b9c950ywan  codec_private_length_ = length;
745233d2500723e5594f3e7c70896ffeeef32b9c950ywan
746233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return true;
747233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
748233d2500723e5594f3e7c70896ffeeef32b9c950ywan
749233d2500723e5594f3e7c70896ffeeef32b9c950ywanvoid Track::set_codec_id(const char* codec_id) {
750233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (codec_id) {
751233d2500723e5594f3e7c70896ffeeef32b9c950ywan    delete [] codec_id_;
752233d2500723e5594f3e7c70896ffeeef32b9c950ywan
753233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const size_t length = strlen(codec_id) + 1;
754233d2500723e5594f3e7c70896ffeeef32b9c950ywan    codec_id_ = new (std::nothrow) char[length];  // NOLINT
755233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (codec_id_) {
756233d2500723e5594f3e7c70896ffeeef32b9c950ywan#ifdef _MSC_VER
757233d2500723e5594f3e7c70896ffeeef32b9c950ywan      strcpy_s(codec_id_, length, codec_id);
758233d2500723e5594f3e7c70896ffeeef32b9c950ywan#else
759233d2500723e5594f3e7c70896ffeeef32b9c950ywan      strcpy(codec_id_, codec_id);
760233d2500723e5594f3e7c70896ffeeef32b9c950ywan#endif
761233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
762233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
763233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
764233d2500723e5594f3e7c70896ffeeef32b9c950ywan
765233d2500723e5594f3e7c70896ffeeef32b9c950ywan// TODO(fgalligan): Vet the language parameter.
766233d2500723e5594f3e7c70896ffeeef32b9c950ywanvoid Track::set_language(const char* language) {
767233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (language) {
768233d2500723e5594f3e7c70896ffeeef32b9c950ywan    delete [] language_;
769233d2500723e5594f3e7c70896ffeeef32b9c950ywan
770233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const size_t length = strlen(language) + 1;
771233d2500723e5594f3e7c70896ffeeef32b9c950ywan    language_ = new (std::nothrow) char[length];  // NOLINT
772233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (language_) {
773233d2500723e5594f3e7c70896ffeeef32b9c950ywan#ifdef _MSC_VER
774233d2500723e5594f3e7c70896ffeeef32b9c950ywan      strcpy_s(language_, length, language);
775233d2500723e5594f3e7c70896ffeeef32b9c950ywan#else
776233d2500723e5594f3e7c70896ffeeef32b9c950ywan      strcpy(language_, language);
777233d2500723e5594f3e7c70896ffeeef32b9c950ywan#endif
778233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
779233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
780233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
781233d2500723e5594f3e7c70896ffeeef32b9c950ywan
782233d2500723e5594f3e7c70896ffeeef32b9c950ywanvoid Track::set_name(const char* name) {
783233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (name) {
784233d2500723e5594f3e7c70896ffeeef32b9c950ywan    delete [] name_;
785233d2500723e5594f3e7c70896ffeeef32b9c950ywan
786233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const size_t length = strlen(name) + 1;
787233d2500723e5594f3e7c70896ffeeef32b9c950ywan    name_ = new (std::nothrow) char[length];  // NOLINT
788233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (name_) {
789233d2500723e5594f3e7c70896ffeeef32b9c950ywan#ifdef _MSC_VER
790233d2500723e5594f3e7c70896ffeeef32b9c950ywan      strcpy_s(name_, length, name);
791233d2500723e5594f3e7c70896ffeeef32b9c950ywan#else
792233d2500723e5594f3e7c70896ffeeef32b9c950ywan      strcpy(name_, name);
793233d2500723e5594f3e7c70896ffeeef32b9c950ywan#endif
794233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
795233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
796233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
797233d2500723e5594f3e7c70896ffeeef32b9c950ywan
798233d2500723e5594f3e7c70896ffeeef32b9c950ywan///////////////////////////////////////////////////////////////
799233d2500723e5594f3e7c70896ffeeef32b9c950ywan//
800233d2500723e5594f3e7c70896ffeeef32b9c950ywan// VideoTrack Class
801233d2500723e5594f3e7c70896ffeeef32b9c950ywan
802233d2500723e5594f3e7c70896ffeeef32b9c950ywanVideoTrack::VideoTrack(unsigned int* seed)
803233d2500723e5594f3e7c70896ffeeef32b9c950ywan    : Track(seed),
804233d2500723e5594f3e7c70896ffeeef32b9c950ywan      display_height_(0),
805233d2500723e5594f3e7c70896ffeeef32b9c950ywan      display_width_(0),
806233d2500723e5594f3e7c70896ffeeef32b9c950ywan      frame_rate_(0.0),
807233d2500723e5594f3e7c70896ffeeef32b9c950ywan      height_(0),
808233d2500723e5594f3e7c70896ffeeef32b9c950ywan      stereo_mode_(0),
809233d2500723e5594f3e7c70896ffeeef32b9c950ywan      alpha_mode_(0),
810233d2500723e5594f3e7c70896ffeeef32b9c950ywan      width_(0) {
811233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
812233d2500723e5594f3e7c70896ffeeef32b9c950ywan
813233d2500723e5594f3e7c70896ffeeef32b9c950ywanVideoTrack::~VideoTrack() {
814233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
815233d2500723e5594f3e7c70896ffeeef32b9c950ywan
816233d2500723e5594f3e7c70896ffeeef32b9c950ywanbool VideoTrack::SetStereoMode(uint64 stereo_mode) {
817233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (stereo_mode != kMono &&
818233d2500723e5594f3e7c70896ffeeef32b9c950ywan      stereo_mode != kSideBySideLeftIsFirst &&
819233d2500723e5594f3e7c70896ffeeef32b9c950ywan      stereo_mode != kTopBottomRightIsFirst &&
820233d2500723e5594f3e7c70896ffeeef32b9c950ywan      stereo_mode != kTopBottomLeftIsFirst &&
821233d2500723e5594f3e7c70896ffeeef32b9c950ywan      stereo_mode != kSideBySideRightIsFirst)
822233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return false;
823233d2500723e5594f3e7c70896ffeeef32b9c950ywan
824233d2500723e5594f3e7c70896ffeeef32b9c950ywan  stereo_mode_ = stereo_mode;
825233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return true;
826233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
827233d2500723e5594f3e7c70896ffeeef32b9c950ywan
828233d2500723e5594f3e7c70896ffeeef32b9c950ywanbool VideoTrack::SetAlphaMode(uint64 alpha_mode) {
829233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (alpha_mode != kNoAlpha &&
830233d2500723e5594f3e7c70896ffeeef32b9c950ywan      alpha_mode != kAlpha)
831233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return false;
832233d2500723e5594f3e7c70896ffeeef32b9c950ywan
833233d2500723e5594f3e7c70896ffeeef32b9c950ywan  alpha_mode_ = alpha_mode;
834233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return true;
835233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
836233d2500723e5594f3e7c70896ffeeef32b9c950ywan
837233d2500723e5594f3e7c70896ffeeef32b9c950ywanuint64 VideoTrack::PayloadSize() const {
838233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const uint64 parent_size = Track::PayloadSize();
839233d2500723e5594f3e7c70896ffeeef32b9c950ywan
840233d2500723e5594f3e7c70896ffeeef32b9c950ywan  uint64 size = VideoPayloadSize();
841233d2500723e5594f3e7c70896ffeeef32b9c950ywan  size += EbmlMasterElementSize(kMkvVideo, size);
842233d2500723e5594f3e7c70896ffeeef32b9c950ywan
843233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return parent_size + size;
844233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
845233d2500723e5594f3e7c70896ffeeef32b9c950ywan
846233d2500723e5594f3e7c70896ffeeef32b9c950ywanbool VideoTrack::Write(IMkvWriter* writer) const {
847233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (!Track::Write(writer))
848233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return false;
849233d2500723e5594f3e7c70896ffeeef32b9c950ywan
850233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const uint64 size = VideoPayloadSize();
851233d2500723e5594f3e7c70896ffeeef32b9c950ywan
852233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (!WriteEbmlMasterElement(writer, kMkvVideo, size))
853233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return false;
854233d2500723e5594f3e7c70896ffeeef32b9c950ywan
855233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const int64 payload_position = writer->Position();
856233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (payload_position < 0)
857233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return false;
858233d2500723e5594f3e7c70896ffeeef32b9c950ywan
859233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (!WriteEbmlElement(writer, kMkvPixelWidth, width_))
860233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return false;
861233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (!WriteEbmlElement(writer, kMkvPixelHeight, height_))
862233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return false;
863233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (display_width_ > 0)
864233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (!WriteEbmlElement(writer, kMkvDisplayWidth, display_width_))
865233d2500723e5594f3e7c70896ffeeef32b9c950ywan      return false;
866233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (display_height_ > 0)
867233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (!WriteEbmlElement(writer, kMkvDisplayHeight, display_height_))
868233d2500723e5594f3e7c70896ffeeef32b9c950ywan      return false;
869233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (stereo_mode_ > kMono)
870233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (!WriteEbmlElement(writer, kMkvStereoMode, stereo_mode_))
871233d2500723e5594f3e7c70896ffeeef32b9c950ywan      return false;
872233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (alpha_mode_ > kNoAlpha)
873233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (!WriteEbmlElement(writer, kMkvAlphaMode, alpha_mode_))
874233d2500723e5594f3e7c70896ffeeef32b9c950ywan      return false;
875233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (frame_rate_ > 0.0)
876233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (!WriteEbmlElement(writer,
877233d2500723e5594f3e7c70896ffeeef32b9c950ywan                          kMkvFrameRate,
878233d2500723e5594f3e7c70896ffeeef32b9c950ywan                          static_cast<float>(frame_rate_)))
879233d2500723e5594f3e7c70896ffeeef32b9c950ywan      return false;
880233d2500723e5594f3e7c70896ffeeef32b9c950ywan
881233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const int64 stop_position = writer->Position();
882233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (stop_position < 0 ||
883233d2500723e5594f3e7c70896ffeeef32b9c950ywan      stop_position - payload_position != static_cast<int64>(size))
884233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return false;
885233d2500723e5594f3e7c70896ffeeef32b9c950ywan
886233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return true;
887233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
888233d2500723e5594f3e7c70896ffeeef32b9c950ywan
889233d2500723e5594f3e7c70896ffeeef32b9c950ywanuint64 VideoTrack::VideoPayloadSize() const {
890233d2500723e5594f3e7c70896ffeeef32b9c950ywan  uint64 size = EbmlElementSize(kMkvPixelWidth, width_);
891233d2500723e5594f3e7c70896ffeeef32b9c950ywan  size += EbmlElementSize(kMkvPixelHeight, height_);
892233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (display_width_ > 0)
893233d2500723e5594f3e7c70896ffeeef32b9c950ywan    size += EbmlElementSize(kMkvDisplayWidth, display_width_);
894233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (display_height_ > 0)
895233d2500723e5594f3e7c70896ffeeef32b9c950ywan    size += EbmlElementSize(kMkvDisplayHeight, display_height_);
896233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (stereo_mode_ > kMono)
897233d2500723e5594f3e7c70896ffeeef32b9c950ywan    size += EbmlElementSize(kMkvStereoMode, stereo_mode_);
898233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (alpha_mode_ > kNoAlpha)
899233d2500723e5594f3e7c70896ffeeef32b9c950ywan    size += EbmlElementSize(kMkvAlphaMode, alpha_mode_);
900233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (frame_rate_ > 0.0)
901233d2500723e5594f3e7c70896ffeeef32b9c950ywan    size += EbmlElementSize(kMkvFrameRate, static_cast<float>(frame_rate_));
902233d2500723e5594f3e7c70896ffeeef32b9c950ywan
903233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return size;
904233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
905233d2500723e5594f3e7c70896ffeeef32b9c950ywan
906233d2500723e5594f3e7c70896ffeeef32b9c950ywan///////////////////////////////////////////////////////////////
907233d2500723e5594f3e7c70896ffeeef32b9c950ywan//
908233d2500723e5594f3e7c70896ffeeef32b9c950ywan// AudioTrack Class
909233d2500723e5594f3e7c70896ffeeef32b9c950ywan
910233d2500723e5594f3e7c70896ffeeef32b9c950ywanAudioTrack::AudioTrack(unsigned int* seed)
911233d2500723e5594f3e7c70896ffeeef32b9c950ywan    : Track(seed),
912233d2500723e5594f3e7c70896ffeeef32b9c950ywan      bit_depth_(0),
913233d2500723e5594f3e7c70896ffeeef32b9c950ywan      channels_(1),
914233d2500723e5594f3e7c70896ffeeef32b9c950ywan      sample_rate_(0.0) {
915233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
916233d2500723e5594f3e7c70896ffeeef32b9c950ywan
917233d2500723e5594f3e7c70896ffeeef32b9c950ywanAudioTrack::~AudioTrack() {
918233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
919233d2500723e5594f3e7c70896ffeeef32b9c950ywan
920233d2500723e5594f3e7c70896ffeeef32b9c950ywanuint64 AudioTrack::PayloadSize() const {
921233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const uint64 parent_size = Track::PayloadSize();
922233d2500723e5594f3e7c70896ffeeef32b9c950ywan
923233d2500723e5594f3e7c70896ffeeef32b9c950ywan  uint64 size = EbmlElementSize(kMkvSamplingFrequency,
924233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                static_cast<float>(sample_rate_));
925233d2500723e5594f3e7c70896ffeeef32b9c950ywan  size += EbmlElementSize(kMkvChannels, channels_);
926233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (bit_depth_ > 0)
927233d2500723e5594f3e7c70896ffeeef32b9c950ywan    size += EbmlElementSize(kMkvBitDepth, bit_depth_);
928233d2500723e5594f3e7c70896ffeeef32b9c950ywan  size += EbmlMasterElementSize(kMkvAudio, size);
929233d2500723e5594f3e7c70896ffeeef32b9c950ywan
930233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return parent_size + size;
931233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
932233d2500723e5594f3e7c70896ffeeef32b9c950ywan
933233d2500723e5594f3e7c70896ffeeef32b9c950ywanbool AudioTrack::Write(IMkvWriter* writer) const {
934233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (!Track::Write(writer))
935233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return false;
936233d2500723e5594f3e7c70896ffeeef32b9c950ywan
937233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // Calculate AudioSettings size.
938233d2500723e5594f3e7c70896ffeeef32b9c950ywan  uint64 size = EbmlElementSize(kMkvSamplingFrequency,
939233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                static_cast<float>(sample_rate_));
940233d2500723e5594f3e7c70896ffeeef32b9c950ywan  size += EbmlElementSize(kMkvChannels, channels_);
941233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (bit_depth_ > 0)
942233d2500723e5594f3e7c70896ffeeef32b9c950ywan    size += EbmlElementSize(kMkvBitDepth, bit_depth_);
943233d2500723e5594f3e7c70896ffeeef32b9c950ywan
944233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (!WriteEbmlMasterElement(writer, kMkvAudio, size))
945233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return false;
946233d2500723e5594f3e7c70896ffeeef32b9c950ywan
947233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const int64 payload_position = writer->Position();
948233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (payload_position < 0)
949233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return false;
950233d2500723e5594f3e7c70896ffeeef32b9c950ywan
951233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (!WriteEbmlElement(writer,
952233d2500723e5594f3e7c70896ffeeef32b9c950ywan                        kMkvSamplingFrequency,
953233d2500723e5594f3e7c70896ffeeef32b9c950ywan                        static_cast<float>(sample_rate_)))
954233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return false;
955233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (!WriteEbmlElement(writer, kMkvChannels, channels_))
956233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return false;
957233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (bit_depth_ > 0)
958233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (!WriteEbmlElement(writer, kMkvBitDepth, bit_depth_))
959233d2500723e5594f3e7c70896ffeeef32b9c950ywan      return false;
960233d2500723e5594f3e7c70896ffeeef32b9c950ywan
961233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const int64 stop_position = writer->Position();
962233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (stop_position < 0 ||
963233d2500723e5594f3e7c70896ffeeef32b9c950ywan      stop_position - payload_position != static_cast<int64>(size))
964233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return false;
965233d2500723e5594f3e7c70896ffeeef32b9c950ywan
966233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return true;
967233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
968233d2500723e5594f3e7c70896ffeeef32b9c950ywan
969233d2500723e5594f3e7c70896ffeeef32b9c950ywan///////////////////////////////////////////////////////////////
970233d2500723e5594f3e7c70896ffeeef32b9c950ywan//
971233d2500723e5594f3e7c70896ffeeef32b9c950ywan// Tracks Class
972233d2500723e5594f3e7c70896ffeeef32b9c950ywan
973233d2500723e5594f3e7c70896ffeeef32b9c950ywanconst char Tracks::kOpusCodecId[] = "A_OPUS";
974233d2500723e5594f3e7c70896ffeeef32b9c950ywanconst char Tracks::kVorbisCodecId[] = "A_VORBIS";
975233d2500723e5594f3e7c70896ffeeef32b9c950ywanconst char Tracks::kVp8CodecId[] = "V_VP8";
976233d2500723e5594f3e7c70896ffeeef32b9c950ywanconst char Tracks::kVp9CodecId[] = "V_VP9";
977233d2500723e5594f3e7c70896ffeeef32b9c950ywan
978233d2500723e5594f3e7c70896ffeeef32b9c950ywan
979233d2500723e5594f3e7c70896ffeeef32b9c950ywanTracks::Tracks()
980233d2500723e5594f3e7c70896ffeeef32b9c950ywan    : track_entries_(NULL),
981233d2500723e5594f3e7c70896ffeeef32b9c950ywan      track_entries_size_(0) {
982233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
983233d2500723e5594f3e7c70896ffeeef32b9c950ywan
984233d2500723e5594f3e7c70896ffeeef32b9c950ywanTracks::~Tracks() {
985233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (track_entries_) {
986233d2500723e5594f3e7c70896ffeeef32b9c950ywan    for (uint32 i = 0; i < track_entries_size_; ++i) {
987233d2500723e5594f3e7c70896ffeeef32b9c950ywan      Track* const track = track_entries_[i];
988233d2500723e5594f3e7c70896ffeeef32b9c950ywan      delete track;
989233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
990233d2500723e5594f3e7c70896ffeeef32b9c950ywan    delete [] track_entries_;
991233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
992233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
993233d2500723e5594f3e7c70896ffeeef32b9c950ywan
994233d2500723e5594f3e7c70896ffeeef32b9c950ywanbool Tracks::AddTrack(Track* track, int32 number) {
995233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (number < 0)
996233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return false;
997233d2500723e5594f3e7c70896ffeeef32b9c950ywan
998233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // This muxer only supports track numbers in the range [1, 126], in
999233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // order to be able (to use Matroska integer representation) to
1000233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // serialize the block header (of which the track number is a part)
1001233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // for a frame using exactly 4 bytes.
1002233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1003233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (number > 0x7E)
1004233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return false;
1005233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1006233d2500723e5594f3e7c70896ffeeef32b9c950ywan  uint32 track_num = number;
1007233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1008233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (track_num > 0) {
1009233d2500723e5594f3e7c70896ffeeef32b9c950ywan    // Check to make sure a track does not already have |track_num|.
1010233d2500723e5594f3e7c70896ffeeef32b9c950ywan    for (uint32 i = 0; i < track_entries_size_; ++i) {
1011233d2500723e5594f3e7c70896ffeeef32b9c950ywan      if (track_entries_[i]->number() == track_num)
1012233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return false;
1013233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
1014233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
1015233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1016233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const uint32 count = track_entries_size_ + 1;
1017233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1018233d2500723e5594f3e7c70896ffeeef32b9c950ywan  Track** const track_entries = new (std::nothrow) Track*[count];  // NOLINT
1019233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (!track_entries)
1020233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return false;
1021233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1022233d2500723e5594f3e7c70896ffeeef32b9c950ywan  for (uint32 i = 0; i < track_entries_size_; ++i) {
1023233d2500723e5594f3e7c70896ffeeef32b9c950ywan    track_entries[i] = track_entries_[i];
1024233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
1025233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1026233d2500723e5594f3e7c70896ffeeef32b9c950ywan  delete [] track_entries_;
1027233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1028233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // Find the lowest availible track number > 0.
1029233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (track_num == 0) {
1030233d2500723e5594f3e7c70896ffeeef32b9c950ywan    track_num = count;
1031233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1032233d2500723e5594f3e7c70896ffeeef32b9c950ywan    // Check to make sure a track does not already have |track_num|.
1033233d2500723e5594f3e7c70896ffeeef32b9c950ywan    bool exit = false;
1034233d2500723e5594f3e7c70896ffeeef32b9c950ywan    do {
1035233d2500723e5594f3e7c70896ffeeef32b9c950ywan      exit = true;
1036233d2500723e5594f3e7c70896ffeeef32b9c950ywan      for (uint32 i = 0; i < track_entries_size_; ++i) {
1037233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (track_entries[i]->number() == track_num) {
1038233d2500723e5594f3e7c70896ffeeef32b9c950ywan          track_num++;
1039233d2500723e5594f3e7c70896ffeeef32b9c950ywan          exit = false;
1040233d2500723e5594f3e7c70896ffeeef32b9c950ywan          break;
1041233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
1042233d2500723e5594f3e7c70896ffeeef32b9c950ywan      }
1043233d2500723e5594f3e7c70896ffeeef32b9c950ywan    } while (!exit);
1044233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
1045233d2500723e5594f3e7c70896ffeeef32b9c950ywan  track->set_number(track_num);
1046233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1047233d2500723e5594f3e7c70896ffeeef32b9c950ywan  track_entries_ = track_entries;
1048233d2500723e5594f3e7c70896ffeeef32b9c950ywan  track_entries_[track_entries_size_] = track;
1049233d2500723e5594f3e7c70896ffeeef32b9c950ywan  track_entries_size_ = count;
1050233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return true;
1051233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
1052233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1053233d2500723e5594f3e7c70896ffeeef32b9c950ywanconst Track* Tracks::GetTrackByIndex(uint32 index) const {
1054233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (track_entries_ == NULL)
1055233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return NULL;
1056233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1057233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (index >= track_entries_size_)
1058233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return NULL;
1059233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1060233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return track_entries_[index];
1061233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
1062233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1063233d2500723e5594f3e7c70896ffeeef32b9c950ywanTrack* Tracks::GetTrackByNumber(uint64 track_number) const {
1064233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const int32 count = track_entries_size();
1065233d2500723e5594f3e7c70896ffeeef32b9c950ywan  for (int32 i = 0; i < count; ++i) {
1066233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (track_entries_[i]->number() == track_number)
1067233d2500723e5594f3e7c70896ffeeef32b9c950ywan      return track_entries_[i];
1068233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
1069233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1070233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return NULL;
1071233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
1072233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1073233d2500723e5594f3e7c70896ffeeef32b9c950ywanbool Tracks::TrackIsAudio(uint64 track_number) const {
1074233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const Track* const track = GetTrackByNumber(track_number);
1075233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1076233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (track->type() == kAudio)
1077233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return true;
1078233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1079233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return false;
1080233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
1081233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1082233d2500723e5594f3e7c70896ffeeef32b9c950ywanbool Tracks::TrackIsVideo(uint64 track_number) const {
1083233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const Track* const track = GetTrackByNumber(track_number);
1084233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1085233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (track->type() == kVideo)
1086233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return true;
1087233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1088233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return false;
1089233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
1090233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1091233d2500723e5594f3e7c70896ffeeef32b9c950ywanbool Tracks::Write(IMkvWriter* writer) const {
1092233d2500723e5594f3e7c70896ffeeef32b9c950ywan  uint64 size = 0;
1093233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const int32 count = track_entries_size();
1094233d2500723e5594f3e7c70896ffeeef32b9c950ywan  for (int32 i = 0; i < count; ++i) {
1095233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const Track* const track = GetTrackByIndex(i);
1096233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1097233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (!track)
1098233d2500723e5594f3e7c70896ffeeef32b9c950ywan      return false;
1099233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1100233d2500723e5594f3e7c70896ffeeef32b9c950ywan    size += track->Size();
1101233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
1102233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1103233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (!WriteEbmlMasterElement(writer, kMkvTracks, size))
1104233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return false;
1105233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1106233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const int64 payload_position = writer->Position();
1107233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (payload_position < 0)
1108233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return false;
1109233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1110233d2500723e5594f3e7c70896ffeeef32b9c950ywan  for (int32 i = 0; i < count; ++i) {
1111233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const Track* const track = GetTrackByIndex(i);
1112233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (!track->Write(writer))
1113233d2500723e5594f3e7c70896ffeeef32b9c950ywan      return false;
1114233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
1115233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1116233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const int64 stop_position = writer->Position();
1117233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (stop_position < 0 ||
1118233d2500723e5594f3e7c70896ffeeef32b9c950ywan      stop_position - payload_position != static_cast<int64>(size))
1119233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return false;
1120233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1121233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return true;
1122233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
1123233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1124233d2500723e5594f3e7c70896ffeeef32b9c950ywan///////////////////////////////////////////////////////////////
1125233d2500723e5594f3e7c70896ffeeef32b9c950ywan//
1126233d2500723e5594f3e7c70896ffeeef32b9c950ywan// Chapter Class
1127233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1128233d2500723e5594f3e7c70896ffeeef32b9c950ywanbool Chapter::set_id(const char* id) {
1129233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return StrCpy(id, &id_);
1130233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
1131233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1132233d2500723e5594f3e7c70896ffeeef32b9c950ywanvoid Chapter::set_time(const Segment& segment,
1133233d2500723e5594f3e7c70896ffeeef32b9c950ywan                       uint64 start_ns,
1134233d2500723e5594f3e7c70896ffeeef32b9c950ywan                       uint64 end_ns) {
1135233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const SegmentInfo* const info = segment.GetSegmentInfo();
1136233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const uint64 timecode_scale = info->timecode_scale();
1137233d2500723e5594f3e7c70896ffeeef32b9c950ywan  start_timecode_ = start_ns / timecode_scale;
1138233d2500723e5594f3e7c70896ffeeef32b9c950ywan  end_timecode_ = end_ns / timecode_scale;
1139233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
1140233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1141233d2500723e5594f3e7c70896ffeeef32b9c950ywanbool Chapter::add_string(const char* title,
1142233d2500723e5594f3e7c70896ffeeef32b9c950ywan                         const char* language,
1143233d2500723e5594f3e7c70896ffeeef32b9c950ywan                         const char* country) {
1144233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (!ExpandDisplaysArray())
1145233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return false;
1146233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1147233d2500723e5594f3e7c70896ffeeef32b9c950ywan  Display& d = displays_[displays_count_++];
1148233d2500723e5594f3e7c70896ffeeef32b9c950ywan  d.Init();
1149233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1150233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (!d.set_title(title))
1151233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return false;
1152233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1153233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (!d.set_language(language))
1154233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return false;
1155233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1156233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (!d.set_country(country))
1157233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return false;
1158233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1159233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return true;
1160233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
1161233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1162233d2500723e5594f3e7c70896ffeeef32b9c950ywanChapter::Chapter() {
1163233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // This ctor only constructs the object.  Proper initialization is
1164233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // done in Init() (called in Chapters::AddChapter()).  The only
1165233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // reason we bother implementing this ctor is because we had to
1166233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // declare it as private (along with the dtor), in order to prevent
1167233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // clients from creating Chapter instances (a privelege we grant
1168233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // only to the Chapters class).  Doing no initialization here also
1169233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // means that creating arrays of chapter objects is more efficient,
1170233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // because we only initialize each new chapter object as it becomes
1171233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // active on the array.
1172233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
1173233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1174233d2500723e5594f3e7c70896ffeeef32b9c950ywanChapter::~Chapter() {
1175233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
1176233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1177233d2500723e5594f3e7c70896ffeeef32b9c950ywanvoid Chapter::Init(unsigned int* seed) {
1178233d2500723e5594f3e7c70896ffeeef32b9c950ywan  id_ = NULL;
1179233d2500723e5594f3e7c70896ffeeef32b9c950ywan  displays_ = NULL;
1180233d2500723e5594f3e7c70896ffeeef32b9c950ywan  displays_size_ = 0;
1181233d2500723e5594f3e7c70896ffeeef32b9c950ywan  displays_count_ = 0;
1182233d2500723e5594f3e7c70896ffeeef32b9c950ywan  uid_ = MakeUID(seed);
1183233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
1184233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1185233d2500723e5594f3e7c70896ffeeef32b9c950ywanvoid Chapter::ShallowCopy(Chapter* dst) const {
1186233d2500723e5594f3e7c70896ffeeef32b9c950ywan  dst->id_ = id_;
1187233d2500723e5594f3e7c70896ffeeef32b9c950ywan  dst->start_timecode_ = start_timecode_;
1188233d2500723e5594f3e7c70896ffeeef32b9c950ywan  dst->end_timecode_ = end_timecode_;
1189233d2500723e5594f3e7c70896ffeeef32b9c950ywan  dst->uid_ = uid_;
1190233d2500723e5594f3e7c70896ffeeef32b9c950ywan  dst->displays_ = displays_;
1191233d2500723e5594f3e7c70896ffeeef32b9c950ywan  dst->displays_size_ = displays_size_;
1192233d2500723e5594f3e7c70896ffeeef32b9c950ywan  dst->displays_count_ = displays_count_;
1193233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
1194233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1195233d2500723e5594f3e7c70896ffeeef32b9c950ywanvoid Chapter::Clear() {
1196233d2500723e5594f3e7c70896ffeeef32b9c950ywan  StrCpy(NULL, &id_);
1197233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1198233d2500723e5594f3e7c70896ffeeef32b9c950ywan  while (displays_count_ > 0) {
1199233d2500723e5594f3e7c70896ffeeef32b9c950ywan    Display& d = displays_[--displays_count_];
1200233d2500723e5594f3e7c70896ffeeef32b9c950ywan    d.Clear();
1201233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
1202233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1203233d2500723e5594f3e7c70896ffeeef32b9c950ywan  delete [] displays_;
1204233d2500723e5594f3e7c70896ffeeef32b9c950ywan  displays_ = NULL;
1205233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1206233d2500723e5594f3e7c70896ffeeef32b9c950ywan  displays_size_ = 0;
1207233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
1208233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1209233d2500723e5594f3e7c70896ffeeef32b9c950ywanbool Chapter::ExpandDisplaysArray() {
1210233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (displays_size_ > displays_count_)
1211233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return true;  // nothing to do yet
1212233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1213233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const int size = (displays_size_ == 0) ? 1 : 2 * displays_size_;
1214233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1215233d2500723e5594f3e7c70896ffeeef32b9c950ywan  Display* const displays = new (std::nothrow) Display[size];  // NOLINT
1216233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (displays == NULL)
1217233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return false;
1218233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1219233d2500723e5594f3e7c70896ffeeef32b9c950ywan  for (int idx = 0; idx < displays_count_; ++idx) {
1220233d2500723e5594f3e7c70896ffeeef32b9c950ywan    displays[idx] = displays_[idx];  // shallow copy
1221233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
1222233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1223233d2500723e5594f3e7c70896ffeeef32b9c950ywan  delete [] displays_;
1224233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1225233d2500723e5594f3e7c70896ffeeef32b9c950ywan  displays_ = displays;
1226233d2500723e5594f3e7c70896ffeeef32b9c950ywan  displays_size_ = size;
1227233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1228233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return true;
1229233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
1230233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1231233d2500723e5594f3e7c70896ffeeef32b9c950ywanuint64 Chapter::WriteAtom(IMkvWriter* writer) const {
1232233d2500723e5594f3e7c70896ffeeef32b9c950ywan  uint64 payload_size =
1233233d2500723e5594f3e7c70896ffeeef32b9c950ywan      EbmlElementSize(kMkvChapterStringUID, id_) +
1234233d2500723e5594f3e7c70896ffeeef32b9c950ywan      EbmlElementSize(kMkvChapterUID, uid_) +
1235233d2500723e5594f3e7c70896ffeeef32b9c950ywan      EbmlElementSize(kMkvChapterTimeStart, start_timecode_) +
1236233d2500723e5594f3e7c70896ffeeef32b9c950ywan      EbmlElementSize(kMkvChapterTimeEnd, end_timecode_);
1237233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1238233d2500723e5594f3e7c70896ffeeef32b9c950ywan  for (int idx = 0; idx < displays_count_; ++idx) {
1239233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const Display& d = displays_[idx];
1240233d2500723e5594f3e7c70896ffeeef32b9c950ywan    payload_size += d.WriteDisplay(NULL);
1241233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
1242233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1243233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const uint64 atom_size =
1244233d2500723e5594f3e7c70896ffeeef32b9c950ywan      EbmlMasterElementSize(kMkvChapterAtom, payload_size) +
1245233d2500723e5594f3e7c70896ffeeef32b9c950ywan      payload_size;
1246233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1247233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (writer == NULL)
1248233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return atom_size;
1249233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1250233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const int64 start = writer->Position();
1251233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1252233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (!WriteEbmlMasterElement(writer, kMkvChapterAtom, payload_size))
1253233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return 0;
1254233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1255233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (!WriteEbmlElement(writer, kMkvChapterStringUID, id_))
1256233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return 0;
1257233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1258233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (!WriteEbmlElement(writer, kMkvChapterUID, uid_))
1259233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return 0;
1260233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1261233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (!WriteEbmlElement(writer, kMkvChapterTimeStart, start_timecode_))
1262233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return 0;
1263233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1264233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (!WriteEbmlElement(writer, kMkvChapterTimeEnd, end_timecode_))
1265233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return 0;
1266233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1267233d2500723e5594f3e7c70896ffeeef32b9c950ywan  for (int idx = 0; idx < displays_count_; ++idx) {
1268233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const Display& d = displays_[idx];
1269233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1270233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (!d.WriteDisplay(writer))
1271233d2500723e5594f3e7c70896ffeeef32b9c950ywan      return 0;
1272233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
1273233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1274233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const int64 stop = writer->Position();
1275233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1276233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (stop >= start && uint64(stop - start) != atom_size)
1277233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return 0;
1278233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1279233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return atom_size;
1280233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
1281233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1282233d2500723e5594f3e7c70896ffeeef32b9c950ywanvoid Chapter::Display::Init() {
1283233d2500723e5594f3e7c70896ffeeef32b9c950ywan  title_ = NULL;
1284233d2500723e5594f3e7c70896ffeeef32b9c950ywan  language_ = NULL;
1285233d2500723e5594f3e7c70896ffeeef32b9c950ywan  country_ = NULL;
1286233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
1287233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1288233d2500723e5594f3e7c70896ffeeef32b9c950ywanvoid Chapter::Display::Clear() {
1289233d2500723e5594f3e7c70896ffeeef32b9c950ywan  StrCpy(NULL, &title_);
1290233d2500723e5594f3e7c70896ffeeef32b9c950ywan  StrCpy(NULL, &language_);
1291233d2500723e5594f3e7c70896ffeeef32b9c950ywan  StrCpy(NULL, &country_);
1292233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
1293233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1294233d2500723e5594f3e7c70896ffeeef32b9c950ywanbool Chapter::Display::set_title(const char* title) {
1295233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return StrCpy(title, &title_);
1296233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
1297233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1298233d2500723e5594f3e7c70896ffeeef32b9c950ywanbool Chapter::Display::set_language(const char* language) {
1299233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return StrCpy(language, &language_);
1300233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
1301233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1302233d2500723e5594f3e7c70896ffeeef32b9c950ywanbool Chapter::Display::set_country(const char* country) {
1303233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return StrCpy(country, &country_);
1304233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
1305233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1306233d2500723e5594f3e7c70896ffeeef32b9c950ywanuint64 Chapter::Display::WriteDisplay(IMkvWriter* writer) const {
1307233d2500723e5594f3e7c70896ffeeef32b9c950ywan  uint64 payload_size = EbmlElementSize(kMkvChapString, title_);
1308233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1309233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (language_)
1310233d2500723e5594f3e7c70896ffeeef32b9c950ywan    payload_size += EbmlElementSize(kMkvChapLanguage, language_);
1311233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1312233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (country_)
1313233d2500723e5594f3e7c70896ffeeef32b9c950ywan    payload_size += EbmlElementSize(kMkvChapCountry, country_);
1314233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1315233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const uint64 display_size =
1316233d2500723e5594f3e7c70896ffeeef32b9c950ywan      EbmlMasterElementSize(kMkvChapterDisplay, payload_size) +
1317233d2500723e5594f3e7c70896ffeeef32b9c950ywan      payload_size;
1318233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1319233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (writer == NULL)
1320233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return display_size;
1321233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1322233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const int64 start = writer->Position();
1323233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1324233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (!WriteEbmlMasterElement(writer, kMkvChapterDisplay, payload_size))
1325233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return 0;
1326233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1327233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (!WriteEbmlElement(writer, kMkvChapString, title_))
1328233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return 0;
1329233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1330233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (language_) {
1331233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (!WriteEbmlElement(writer, kMkvChapLanguage, language_))
1332233d2500723e5594f3e7c70896ffeeef32b9c950ywan      return 0;
1333233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
1334233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1335233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (country_) {
1336233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (!WriteEbmlElement(writer, kMkvChapCountry, country_))
1337233d2500723e5594f3e7c70896ffeeef32b9c950ywan      return 0;
1338233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
1339233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1340233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const int64 stop = writer->Position();
1341233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1342233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (stop >= start && uint64(stop - start) != display_size)
1343233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return 0;
1344233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1345233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return display_size;
1346233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
1347233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1348233d2500723e5594f3e7c70896ffeeef32b9c950ywan///////////////////////////////////////////////////////////////
1349233d2500723e5594f3e7c70896ffeeef32b9c950ywan//
1350233d2500723e5594f3e7c70896ffeeef32b9c950ywan// Chapters Class
1351233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1352233d2500723e5594f3e7c70896ffeeef32b9c950ywanChapters::Chapters()
1353233d2500723e5594f3e7c70896ffeeef32b9c950ywan    : chapters_size_(0),
1354233d2500723e5594f3e7c70896ffeeef32b9c950ywan      chapters_count_(0),
1355233d2500723e5594f3e7c70896ffeeef32b9c950ywan      chapters_(NULL) {
1356233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
1357233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1358233d2500723e5594f3e7c70896ffeeef32b9c950ywanChapters::~Chapters() {
1359233d2500723e5594f3e7c70896ffeeef32b9c950ywan  while (chapters_count_ > 0) {
1360233d2500723e5594f3e7c70896ffeeef32b9c950ywan    Chapter& chapter = chapters_[--chapters_count_];
1361233d2500723e5594f3e7c70896ffeeef32b9c950ywan    chapter.Clear();
1362233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
1363233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1364233d2500723e5594f3e7c70896ffeeef32b9c950ywan  delete [] chapters_;
1365233d2500723e5594f3e7c70896ffeeef32b9c950ywan  chapters_ = NULL;
1366233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
1367233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1368233d2500723e5594f3e7c70896ffeeef32b9c950ywanint Chapters::Count() const {
1369233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return chapters_count_;
1370233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
1371233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1372233d2500723e5594f3e7c70896ffeeef32b9c950ywanChapter* Chapters::AddChapter(unsigned int* seed) {
1373233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (!ExpandChaptersArray())
1374233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return NULL;
1375233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1376233d2500723e5594f3e7c70896ffeeef32b9c950ywan  Chapter& chapter = chapters_[chapters_count_++];
1377233d2500723e5594f3e7c70896ffeeef32b9c950ywan  chapter.Init(seed);
1378233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1379233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return &chapter;
1380233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
1381233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1382233d2500723e5594f3e7c70896ffeeef32b9c950ywanbool Chapters::Write(IMkvWriter* writer) const {
1383233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (writer == NULL)
1384233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return false;
1385233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1386233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const uint64 payload_size = WriteEdition(NULL);  // return size only
1387233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1388233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (!WriteEbmlMasterElement(writer, kMkvChapters, payload_size))
1389233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return false;
1390233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1391233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const int64 start = writer->Position();
1392233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1393233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (WriteEdition(writer) == 0)  // error
1394233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return false;
1395233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1396233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const int64 stop = writer->Position();
1397233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1398233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (stop >= start && uint64(stop - start) != payload_size)
1399233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return false;
1400233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1401233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return true;
1402233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
1403233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1404233d2500723e5594f3e7c70896ffeeef32b9c950ywanbool Chapters::ExpandChaptersArray() {
1405233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (chapters_size_ > chapters_count_)
1406233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return true;  // nothing to do yet
1407233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1408233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const int size = (chapters_size_ == 0) ? 1 : 2 * chapters_size_;
1409233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1410233d2500723e5594f3e7c70896ffeeef32b9c950ywan  Chapter* const chapters = new (std::nothrow) Chapter[size];  // NOLINT
1411233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (chapters == NULL)
1412233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return false;
1413233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1414233d2500723e5594f3e7c70896ffeeef32b9c950ywan  for (int idx = 0; idx < chapters_count_; ++idx) {
1415233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const Chapter& src = chapters_[idx];
1416233d2500723e5594f3e7c70896ffeeef32b9c950ywan    Chapter* const dst = chapters + idx;
1417233d2500723e5594f3e7c70896ffeeef32b9c950ywan    src.ShallowCopy(dst);
1418233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
1419233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1420233d2500723e5594f3e7c70896ffeeef32b9c950ywan  delete [] chapters_;
1421233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1422233d2500723e5594f3e7c70896ffeeef32b9c950ywan  chapters_ = chapters;
1423233d2500723e5594f3e7c70896ffeeef32b9c950ywan  chapters_size_ = size;
1424233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1425233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return true;
1426233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
1427233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1428233d2500723e5594f3e7c70896ffeeef32b9c950ywanuint64 Chapters::WriteEdition(IMkvWriter* writer) const {
1429233d2500723e5594f3e7c70896ffeeef32b9c950ywan  uint64 payload_size = 0;
1430233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1431233d2500723e5594f3e7c70896ffeeef32b9c950ywan  for (int idx = 0; idx < chapters_count_; ++idx) {
1432233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const Chapter& chapter = chapters_[idx];
1433233d2500723e5594f3e7c70896ffeeef32b9c950ywan    payload_size += chapter.WriteAtom(NULL);
1434233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
1435233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1436233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const uint64 edition_size =
1437233d2500723e5594f3e7c70896ffeeef32b9c950ywan      EbmlMasterElementSize(kMkvEditionEntry, payload_size) +
1438233d2500723e5594f3e7c70896ffeeef32b9c950ywan      payload_size;
1439233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1440233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (writer == NULL)  // return size only
1441233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return edition_size;
1442233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1443233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const int64 start = writer->Position();
1444233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1445233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (!WriteEbmlMasterElement(writer, kMkvEditionEntry, payload_size))
1446233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return 0;  // error
1447233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1448233d2500723e5594f3e7c70896ffeeef32b9c950ywan  for (int idx = 0; idx < chapters_count_; ++idx) {
1449233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const Chapter& chapter = chapters_[idx];
1450233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1451233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const uint64 chapter_size = chapter.WriteAtom(writer);
1452233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (chapter_size == 0)  // error
1453233d2500723e5594f3e7c70896ffeeef32b9c950ywan      return 0;
1454233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
1455233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1456233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const int64 stop = writer->Position();
1457233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1458233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (stop >= start && uint64(stop - start) != edition_size)
1459233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return 0;
1460233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1461233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return edition_size;
1462233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
1463233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1464233d2500723e5594f3e7c70896ffeeef32b9c950ywan///////////////////////////////////////////////////////////////
1465233d2500723e5594f3e7c70896ffeeef32b9c950ywan//
1466233d2500723e5594f3e7c70896ffeeef32b9c950ywan// Cluster class
1467233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1468233d2500723e5594f3e7c70896ffeeef32b9c950ywanCluster::Cluster(uint64 timecode, int64 cues_pos)
1469233d2500723e5594f3e7c70896ffeeef32b9c950ywan    : blocks_added_(0),
1470233d2500723e5594f3e7c70896ffeeef32b9c950ywan      finalized_(false),
1471233d2500723e5594f3e7c70896ffeeef32b9c950ywan      header_written_(false),
1472233d2500723e5594f3e7c70896ffeeef32b9c950ywan      payload_size_(0),
1473233d2500723e5594f3e7c70896ffeeef32b9c950ywan      position_for_cues_(cues_pos),
1474233d2500723e5594f3e7c70896ffeeef32b9c950ywan      size_position_(-1),
1475233d2500723e5594f3e7c70896ffeeef32b9c950ywan      timecode_(timecode),
1476233d2500723e5594f3e7c70896ffeeef32b9c950ywan      writer_(NULL) {
1477233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
1478233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1479233d2500723e5594f3e7c70896ffeeef32b9c950ywanCluster::~Cluster() {
1480233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
1481233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1482233d2500723e5594f3e7c70896ffeeef32b9c950ywanbool Cluster::Init(IMkvWriter* ptr_writer) {
1483233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (!ptr_writer) {
1484233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return false;
1485233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
1486233d2500723e5594f3e7c70896ffeeef32b9c950ywan  writer_ = ptr_writer;
1487233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return true;
1488233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
1489233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1490233d2500723e5594f3e7c70896ffeeef32b9c950ywanbool Cluster::AddFrame(const uint8* frame,
1491233d2500723e5594f3e7c70896ffeeef32b9c950ywan                       uint64 length,
1492233d2500723e5594f3e7c70896ffeeef32b9c950ywan                       uint64 track_number,
1493233d2500723e5594f3e7c70896ffeeef32b9c950ywan                       uint64 abs_timecode,
1494233d2500723e5594f3e7c70896ffeeef32b9c950ywan                       bool is_key) {
1495233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return DoWriteBlock(frame,
1496233d2500723e5594f3e7c70896ffeeef32b9c950ywan                      length,
1497233d2500723e5594f3e7c70896ffeeef32b9c950ywan                      track_number,
1498233d2500723e5594f3e7c70896ffeeef32b9c950ywan                      abs_timecode,
1499233d2500723e5594f3e7c70896ffeeef32b9c950ywan                      is_key ? 1 : 0,
1500233d2500723e5594f3e7c70896ffeeef32b9c950ywan                      &WriteSimpleBlock);
1501233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
1502233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1503233d2500723e5594f3e7c70896ffeeef32b9c950ywanbool Cluster::AddFrameWithAdditional(const uint8* frame,
1504233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                     uint64 length,
1505233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                     const uint8* additional,
1506233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                     uint64 additional_length,
1507233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                     uint64 add_id,
1508233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                     uint64 track_number,
1509233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                     uint64 abs_timecode,
1510233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                     bool is_key) {
1511233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return DoWriteBlockWithAdditional(frame,
1512233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                    length,
1513233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                    additional,
1514233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                    additional_length,
1515233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                    add_id,
1516233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                    track_number,
1517233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                    abs_timecode,
1518233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                    is_key ? 1 : 0,
1519233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                    &WriteBlockWithAdditional);
1520233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
1521233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1522233d2500723e5594f3e7c70896ffeeef32b9c950ywanbool Cluster::AddFrameWithDiscardPadding(const uint8* frame,
1523233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                         uint64 length,
1524233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                         int64 discard_padding,
1525233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                         uint64 track_number,
1526233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                         uint64 abs_timecode,
1527233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                         bool is_key) {
1528233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return DoWriteBlockWithDiscardPadding(frame,
1529233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                        length,
1530233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                        discard_padding,
1531233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                        track_number,
1532233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                        abs_timecode,
1533233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                        is_key ? 1 : 0,
1534233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                        &WriteBlockWithDiscardPadding);
1535233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
1536233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1537233d2500723e5594f3e7c70896ffeeef32b9c950ywanbool Cluster::AddMetadata(const uint8* frame,
1538233d2500723e5594f3e7c70896ffeeef32b9c950ywan                          uint64 length,
1539233d2500723e5594f3e7c70896ffeeef32b9c950ywan                          uint64 track_number,
1540233d2500723e5594f3e7c70896ffeeef32b9c950ywan                          uint64 abs_timecode,
1541233d2500723e5594f3e7c70896ffeeef32b9c950ywan                          uint64 duration_timecode) {
1542233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return DoWriteBlock(frame,
1543233d2500723e5594f3e7c70896ffeeef32b9c950ywan                      length,
1544233d2500723e5594f3e7c70896ffeeef32b9c950ywan                      track_number,
1545233d2500723e5594f3e7c70896ffeeef32b9c950ywan                      abs_timecode,
1546233d2500723e5594f3e7c70896ffeeef32b9c950ywan                      duration_timecode,
1547233d2500723e5594f3e7c70896ffeeef32b9c950ywan                      &WriteMetadataBlock);
1548233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
1549233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1550233d2500723e5594f3e7c70896ffeeef32b9c950ywanvoid Cluster::AddPayloadSize(uint64 size) {
1551233d2500723e5594f3e7c70896ffeeef32b9c950ywan  payload_size_ += size;
1552233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
1553233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1554233d2500723e5594f3e7c70896ffeeef32b9c950ywanbool Cluster::Finalize() {
1555233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (!writer_ || finalized_ || size_position_ == -1)
1556233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return false;
1557233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1558233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (writer_->Seekable()) {
1559233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const int64 pos = writer_->Position();
1560233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1561233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (writer_->Position(size_position_))
1562233d2500723e5594f3e7c70896ffeeef32b9c950ywan      return false;
1563233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1564233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (WriteUIntSize(writer_, payload_size(), 8))
1565233d2500723e5594f3e7c70896ffeeef32b9c950ywan      return false;
1566233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1567233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (writer_->Position(pos))
1568233d2500723e5594f3e7c70896ffeeef32b9c950ywan      return false;
1569233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
1570233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1571233d2500723e5594f3e7c70896ffeeef32b9c950ywan  finalized_ = true;
1572233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1573233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return true;
1574233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
1575233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1576233d2500723e5594f3e7c70896ffeeef32b9c950ywanuint64 Cluster::Size() const {
1577233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const uint64 element_size =
1578233d2500723e5594f3e7c70896ffeeef32b9c950ywan      EbmlMasterElementSize(kMkvCluster,
1579233d2500723e5594f3e7c70896ffeeef32b9c950ywan                            0xFFFFFFFFFFFFFFFFULL) + payload_size_;
1580233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return element_size;
1581233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
1582233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1583233d2500723e5594f3e7c70896ffeeef32b9c950ywantemplate <typename Type>
1584233d2500723e5594f3e7c70896ffeeef32b9c950ywanbool Cluster::PreWriteBlock(Type* write_function) {
1585233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (write_function == NULL)
1586233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return false;
1587233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1588233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (finalized_)
1589233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return false;
1590233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1591233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (!header_written_) {
1592233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (!WriteClusterHeader())
1593233d2500723e5594f3e7c70896ffeeef32b9c950ywan      return false;
1594233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
1595233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1596233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return true;
1597233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
1598233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1599233d2500723e5594f3e7c70896ffeeef32b9c950ywanvoid Cluster::PostWriteBlock(uint64 element_size) {
1600233d2500723e5594f3e7c70896ffeeef32b9c950ywan  AddPayloadSize(element_size);
1601233d2500723e5594f3e7c70896ffeeef32b9c950ywan  ++blocks_added_;
1602233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
1603233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1604233d2500723e5594f3e7c70896ffeeef32b9c950ywanbool Cluster::IsValidTrackNumber(uint64 track_number) const {
1605233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return (track_number > 0 && track_number <= 0x7E);
1606233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
1607233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1608233d2500723e5594f3e7c70896ffeeef32b9c950ywanint64 Cluster::GetRelativeTimecode(int64 abs_timecode) const {
1609233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const int64 cluster_timecode = this->Cluster::timecode();
1610233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const int64 rel_timecode =
1611233d2500723e5594f3e7c70896ffeeef32b9c950ywan      static_cast<int64>(abs_timecode) - cluster_timecode;
1612233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1613233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (rel_timecode < 0 || rel_timecode > kMaxBlockTimecode)
1614233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return -1;
1615233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1616233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return rel_timecode;
1617233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
1618233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1619233d2500723e5594f3e7c70896ffeeef32b9c950ywanbool Cluster::DoWriteBlock(
1620233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const uint8* frame,
1621233d2500723e5594f3e7c70896ffeeef32b9c950ywan    uint64 length,
1622233d2500723e5594f3e7c70896ffeeef32b9c950ywan    uint64 track_number,
1623233d2500723e5594f3e7c70896ffeeef32b9c950ywan    uint64 abs_timecode,
1624233d2500723e5594f3e7c70896ffeeef32b9c950ywan    uint64 generic_arg,
1625233d2500723e5594f3e7c70896ffeeef32b9c950ywan    WriteBlock write_block) {
1626233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (frame == NULL || length == 0)
1627233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return false;
1628233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1629233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (!IsValidTrackNumber(track_number))
1630233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return false;
1631233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1632233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const int64 rel_timecode = GetRelativeTimecode(abs_timecode);
1633233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (rel_timecode < 0)
1634233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return false;
1635233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1636233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (!PreWriteBlock(write_block))
1637233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return false;
1638233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1639233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const uint64 element_size = (*write_block)(writer_,
1640233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                             frame,
1641233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                             length,
1642233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                             track_number,
1643233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                             rel_timecode,
1644233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                             generic_arg);
1645233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (element_size == 0)
1646233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return false;
1647233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1648233d2500723e5594f3e7c70896ffeeef32b9c950ywan  PostWriteBlock(element_size);
1649233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return true;
1650233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
1651233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1652233d2500723e5594f3e7c70896ffeeef32b9c950ywanbool Cluster::DoWriteBlockWithAdditional(
1653233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const uint8* frame,
1654233d2500723e5594f3e7c70896ffeeef32b9c950ywan    uint64 length,
1655233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const uint8* additional,
1656233d2500723e5594f3e7c70896ffeeef32b9c950ywan    uint64 additional_length,
1657233d2500723e5594f3e7c70896ffeeef32b9c950ywan    uint64 add_id,
1658233d2500723e5594f3e7c70896ffeeef32b9c950ywan    uint64 track_number,
1659233d2500723e5594f3e7c70896ffeeef32b9c950ywan    uint64 abs_timecode,
1660233d2500723e5594f3e7c70896ffeeef32b9c950ywan    uint64 generic_arg,
1661233d2500723e5594f3e7c70896ffeeef32b9c950ywan    WriteBlockAdditional write_block) {
1662233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (frame == NULL || length == 0 ||
1663233d2500723e5594f3e7c70896ffeeef32b9c950ywan      additional == NULL || additional_length == 0)
1664233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return false;
1665233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1666233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (!IsValidTrackNumber(track_number))
1667233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return false;
1668233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1669233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const int64 rel_timecode = GetRelativeTimecode(abs_timecode);
1670233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (rel_timecode < 0)
1671233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return false;
1672233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1673233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (!PreWriteBlock(write_block))
1674233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return false;
1675233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1676233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const uint64 element_size = (*write_block)(writer_,
1677233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                             frame,
1678233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                             length,
1679233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                             additional,
1680233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                             additional_length,
1681233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                             add_id,
1682233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                             track_number,
1683233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                             rel_timecode,
1684233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                             generic_arg);
1685233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (element_size == 0)
1686233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return false;
1687233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1688233d2500723e5594f3e7c70896ffeeef32b9c950ywan  PostWriteBlock(element_size);
1689233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return true;
1690233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
1691233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1692233d2500723e5594f3e7c70896ffeeef32b9c950ywanbool Cluster::DoWriteBlockWithDiscardPadding(
1693233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const uint8* frame,
1694233d2500723e5594f3e7c70896ffeeef32b9c950ywan    uint64 length,
1695233d2500723e5594f3e7c70896ffeeef32b9c950ywan    int64 discard_padding,
1696233d2500723e5594f3e7c70896ffeeef32b9c950ywan    uint64 track_number,
1697233d2500723e5594f3e7c70896ffeeef32b9c950ywan    uint64 abs_timecode,
1698233d2500723e5594f3e7c70896ffeeef32b9c950ywan    uint64 generic_arg,
1699233d2500723e5594f3e7c70896ffeeef32b9c950ywan    WriteBlockDiscardPadding write_block) {
1700233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (frame == NULL || length == 0 || discard_padding <= 0)
1701233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return false;
1702233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1703233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (!IsValidTrackNumber(track_number))
1704233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return false;
1705233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1706233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const int64 rel_timecode = GetRelativeTimecode(abs_timecode);
1707233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (rel_timecode < 0)
1708233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return false;
1709233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1710233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (!PreWriteBlock(write_block))
1711233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return false;
1712233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1713233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const uint64 element_size = (*write_block)(writer_,
1714233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                             frame,
1715233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                             length,
1716233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                             discard_padding,
1717233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                             track_number,
1718233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                             rel_timecode,
1719233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                             generic_arg);
1720233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (element_size == 0)
1721233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return false;
1722233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1723233d2500723e5594f3e7c70896ffeeef32b9c950ywan  PostWriteBlock(element_size);
1724233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return true;
1725233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
1726233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1727233d2500723e5594f3e7c70896ffeeef32b9c950ywanbool Cluster::WriteClusterHeader() {
1728233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (finalized_)
1729233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return false;
1730233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1731233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (WriteID(writer_, kMkvCluster))
1732233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return false;
1733233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1734233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // Save for later.
1735233d2500723e5594f3e7c70896ffeeef32b9c950ywan  size_position_ = writer_->Position();
1736233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1737233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // Write "unknown" (EBML coded -1) as cluster size value. We need to write 8
1738233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // bytes because we do not know how big our cluster will be.
1739233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (SerializeInt(writer_, kEbmlUnknownValue, 8))
1740233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return false;
1741233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1742233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (!WriteEbmlElement(writer_, kMkvTimecode, timecode()))
1743233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return false;
1744233d2500723e5594f3e7c70896ffeeef32b9c950ywan  AddPayloadSize(EbmlElementSize(kMkvTimecode, timecode()));
1745233d2500723e5594f3e7c70896ffeeef32b9c950ywan  header_written_ = true;
1746233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1747233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return true;
1748233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
1749233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1750233d2500723e5594f3e7c70896ffeeef32b9c950ywan///////////////////////////////////////////////////////////////
1751233d2500723e5594f3e7c70896ffeeef32b9c950ywan//
1752233d2500723e5594f3e7c70896ffeeef32b9c950ywan// SeekHead Class
1753233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1754233d2500723e5594f3e7c70896ffeeef32b9c950ywanSeekHead::SeekHead() : start_pos_(0ULL) {
1755233d2500723e5594f3e7c70896ffeeef32b9c950ywan  for (int32 i = 0; i < kSeekEntryCount; ++i) {
1756233d2500723e5594f3e7c70896ffeeef32b9c950ywan    seek_entry_id_[i] = 0;
1757233d2500723e5594f3e7c70896ffeeef32b9c950ywan    seek_entry_pos_[i] = 0;
1758233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
1759233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
1760233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1761233d2500723e5594f3e7c70896ffeeef32b9c950ywanSeekHead::~SeekHead() {
1762233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
1763233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1764233d2500723e5594f3e7c70896ffeeef32b9c950ywanbool SeekHead::Finalize(IMkvWriter* writer) const {
1765233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (writer->Seekable()) {
1766233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (start_pos_ == -1)
1767233d2500723e5594f3e7c70896ffeeef32b9c950ywan      return false;
1768233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1769233d2500723e5594f3e7c70896ffeeef32b9c950ywan    uint64 payload_size = 0;
1770233d2500723e5594f3e7c70896ffeeef32b9c950ywan    uint64 entry_size[kSeekEntryCount];
1771233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1772233d2500723e5594f3e7c70896ffeeef32b9c950ywan    for (int32 i = 0; i < kSeekEntryCount; ++i) {
1773233d2500723e5594f3e7c70896ffeeef32b9c950ywan      if (seek_entry_id_[i] != 0) {
1774233d2500723e5594f3e7c70896ffeeef32b9c950ywan        entry_size[i] = EbmlElementSize(
1775233d2500723e5594f3e7c70896ffeeef32b9c950ywan            kMkvSeekID,
1776233d2500723e5594f3e7c70896ffeeef32b9c950ywan            static_cast<uint64>(seek_entry_id_[i]));
1777233d2500723e5594f3e7c70896ffeeef32b9c950ywan        entry_size[i] += EbmlElementSize(kMkvSeekPosition, seek_entry_pos_[i]);
1778233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1779233d2500723e5594f3e7c70896ffeeef32b9c950ywan        payload_size += EbmlMasterElementSize(kMkvSeek, entry_size[i]) +
1780233d2500723e5594f3e7c70896ffeeef32b9c950ywan                        entry_size[i];
1781233d2500723e5594f3e7c70896ffeeef32b9c950ywan      }
1782233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
1783233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1784233d2500723e5594f3e7c70896ffeeef32b9c950ywan    // No SeekHead elements
1785233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (payload_size == 0)
1786233d2500723e5594f3e7c70896ffeeef32b9c950ywan      return true;
1787233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1788233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const int64 pos = writer->Position();
1789233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (writer->Position(start_pos_))
1790233d2500723e5594f3e7c70896ffeeef32b9c950ywan      return false;
1791233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1792233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (!WriteEbmlMasterElement(writer, kMkvSeekHead, payload_size))
1793233d2500723e5594f3e7c70896ffeeef32b9c950ywan      return false;
1794233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1795233d2500723e5594f3e7c70896ffeeef32b9c950ywan    for (int32 i = 0; i < kSeekEntryCount; ++i) {
1796233d2500723e5594f3e7c70896ffeeef32b9c950ywan      if (seek_entry_id_[i] != 0) {
1797233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (!WriteEbmlMasterElement(writer, kMkvSeek, entry_size[i]))
1798233d2500723e5594f3e7c70896ffeeef32b9c950ywan          return false;
1799233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1800233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (!WriteEbmlElement(writer,
1801233d2500723e5594f3e7c70896ffeeef32b9c950ywan                              kMkvSeekID,
1802233d2500723e5594f3e7c70896ffeeef32b9c950ywan                              static_cast<uint64>(seek_entry_id_[i])))
1803233d2500723e5594f3e7c70896ffeeef32b9c950ywan          return false;
1804233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1805233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (!WriteEbmlElement(writer, kMkvSeekPosition, seek_entry_pos_[i]))
1806233d2500723e5594f3e7c70896ffeeef32b9c950ywan          return false;
1807233d2500723e5594f3e7c70896ffeeef32b9c950ywan      }
1808233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
1809233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1810233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const uint64 total_entry_size = kSeekEntryCount * MaxEntrySize();
1811233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const uint64 total_size =
1812233d2500723e5594f3e7c70896ffeeef32b9c950ywan        EbmlMasterElementSize(kMkvSeekHead,
1813233d2500723e5594f3e7c70896ffeeef32b9c950ywan                              total_entry_size) + total_entry_size;
1814233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const int64 size_left = total_size - (writer->Position() - start_pos_);
1815233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1816233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const uint64 bytes_written = WriteVoidElement(writer, size_left);
1817233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (!bytes_written)
1818233d2500723e5594f3e7c70896ffeeef32b9c950ywan      return false;
1819233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1820233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (writer->Position(pos))
1821233d2500723e5594f3e7c70896ffeeef32b9c950ywan      return false;
1822233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
1823233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1824233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return true;
1825233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
1826233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1827233d2500723e5594f3e7c70896ffeeef32b9c950ywanbool SeekHead::Write(IMkvWriter* writer) {
1828233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const uint64 entry_size = kSeekEntryCount * MaxEntrySize();
1829233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const uint64 size = EbmlMasterElementSize(kMkvSeekHead, entry_size);
1830233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1831233d2500723e5594f3e7c70896ffeeef32b9c950ywan  start_pos_ = writer->Position();
1832233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1833233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const uint64 bytes_written = WriteVoidElement(writer, size + entry_size);
1834233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (!bytes_written)
1835233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return false;
1836233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1837233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return true;
1838233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
1839233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1840233d2500723e5594f3e7c70896ffeeef32b9c950ywanbool SeekHead::AddSeekEntry(uint32 id, uint64 pos) {
1841233d2500723e5594f3e7c70896ffeeef32b9c950ywan  for (int32 i = 0; i < kSeekEntryCount; ++i) {
1842233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (seek_entry_id_[i] == 0) {
1843233d2500723e5594f3e7c70896ffeeef32b9c950ywan      seek_entry_id_[i] = id;
1844233d2500723e5594f3e7c70896ffeeef32b9c950ywan      seek_entry_pos_[i] = pos;
1845233d2500723e5594f3e7c70896ffeeef32b9c950ywan      return true;
1846233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
1847233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
1848233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return false;
1849233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
1850233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1851233d2500723e5594f3e7c70896ffeeef32b9c950ywanuint32 SeekHead::GetId(int index) const {
1852233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (index < 0 || index >= kSeekEntryCount)
1853233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return UINT_MAX;
1854233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return seek_entry_id_[index];
1855233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
1856233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1857233d2500723e5594f3e7c70896ffeeef32b9c950ywanuint64 SeekHead::GetPosition(int index) const {
1858233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (index < 0 || index >= kSeekEntryCount)
1859233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return ULLONG_MAX;
1860233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return seek_entry_pos_[index];
1861233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
1862233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1863233d2500723e5594f3e7c70896ffeeef32b9c950ywanbool SeekHead::SetSeekEntry(int index, uint32 id, uint64 position) {
1864233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (index < 0 || index >= kSeekEntryCount)
1865233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return false;
1866233d2500723e5594f3e7c70896ffeeef32b9c950ywan  seek_entry_id_[index] = id;
1867233d2500723e5594f3e7c70896ffeeef32b9c950ywan  seek_entry_pos_[index] = position;
1868233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return true;
1869233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
1870233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1871233d2500723e5594f3e7c70896ffeeef32b9c950ywanuint64 SeekHead::MaxEntrySize() const {
1872233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const uint64 max_entry_payload_size =
1873233d2500723e5594f3e7c70896ffeeef32b9c950ywan      EbmlElementSize(kMkvSeekID, 0xffffffffULL) +
1874233d2500723e5594f3e7c70896ffeeef32b9c950ywan      EbmlElementSize(kMkvSeekPosition, 0xffffffffffffffffULL);
1875233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const uint64 max_entry_size =
1876233d2500723e5594f3e7c70896ffeeef32b9c950ywan      EbmlMasterElementSize(kMkvSeek, max_entry_payload_size) +
1877233d2500723e5594f3e7c70896ffeeef32b9c950ywan      max_entry_payload_size;
1878233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1879233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return max_entry_size;
1880233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
1881233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1882233d2500723e5594f3e7c70896ffeeef32b9c950ywan///////////////////////////////////////////////////////////////
1883233d2500723e5594f3e7c70896ffeeef32b9c950ywan//
1884233d2500723e5594f3e7c70896ffeeef32b9c950ywan// SegmentInfo Class
1885233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1886233d2500723e5594f3e7c70896ffeeef32b9c950ywanSegmentInfo::SegmentInfo()
1887233d2500723e5594f3e7c70896ffeeef32b9c950ywan    : duration_(-1.0),
1888233d2500723e5594f3e7c70896ffeeef32b9c950ywan      muxing_app_(NULL),
1889233d2500723e5594f3e7c70896ffeeef32b9c950ywan      timecode_scale_(1000000ULL),
1890233d2500723e5594f3e7c70896ffeeef32b9c950ywan      writing_app_(NULL),
1891233d2500723e5594f3e7c70896ffeeef32b9c950ywan      duration_pos_(-1) {
1892233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
1893233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1894233d2500723e5594f3e7c70896ffeeef32b9c950ywanSegmentInfo::~SegmentInfo() {
1895233d2500723e5594f3e7c70896ffeeef32b9c950ywan  delete [] muxing_app_;
1896233d2500723e5594f3e7c70896ffeeef32b9c950ywan  delete [] writing_app_;
1897233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
1898233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1899233d2500723e5594f3e7c70896ffeeef32b9c950ywanbool SegmentInfo::Init() {
1900233d2500723e5594f3e7c70896ffeeef32b9c950ywan  int32 major;
1901233d2500723e5594f3e7c70896ffeeef32b9c950ywan  int32 minor;
1902233d2500723e5594f3e7c70896ffeeef32b9c950ywan  int32 build;
1903233d2500723e5594f3e7c70896ffeeef32b9c950ywan  int32 revision;
1904233d2500723e5594f3e7c70896ffeeef32b9c950ywan  GetVersion(&major, &minor, &build, &revision);
1905233d2500723e5594f3e7c70896ffeeef32b9c950ywan  char temp[256];
1906233d2500723e5594f3e7c70896ffeeef32b9c950ywan#ifdef _MSC_VER
1907233d2500723e5594f3e7c70896ffeeef32b9c950ywan  sprintf_s(temp,
1908233d2500723e5594f3e7c70896ffeeef32b9c950ywan            sizeof(temp)/sizeof(temp[0]),
1909233d2500723e5594f3e7c70896ffeeef32b9c950ywan            "libwebm-%d.%d.%d.%d",
1910233d2500723e5594f3e7c70896ffeeef32b9c950ywan            major,
1911233d2500723e5594f3e7c70896ffeeef32b9c950ywan            minor,
1912233d2500723e5594f3e7c70896ffeeef32b9c950ywan            build,
1913233d2500723e5594f3e7c70896ffeeef32b9c950ywan            revision);
1914233d2500723e5594f3e7c70896ffeeef32b9c950ywan#else
1915233d2500723e5594f3e7c70896ffeeef32b9c950ywan  snprintf(temp,
1916233d2500723e5594f3e7c70896ffeeef32b9c950ywan           sizeof(temp)/sizeof(temp[0]),
1917233d2500723e5594f3e7c70896ffeeef32b9c950ywan           "libwebm-%d.%d.%d.%d",
1918233d2500723e5594f3e7c70896ffeeef32b9c950ywan           major,
1919233d2500723e5594f3e7c70896ffeeef32b9c950ywan           minor,
1920233d2500723e5594f3e7c70896ffeeef32b9c950ywan           build,
1921233d2500723e5594f3e7c70896ffeeef32b9c950ywan           revision);
1922233d2500723e5594f3e7c70896ffeeef32b9c950ywan#endif
1923233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1924233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const size_t app_len = strlen(temp) + 1;
1925233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1926233d2500723e5594f3e7c70896ffeeef32b9c950ywan  delete [] muxing_app_;
1927233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1928233d2500723e5594f3e7c70896ffeeef32b9c950ywan  muxing_app_ = new (std::nothrow) char[app_len];  // NOLINT
1929233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (!muxing_app_)
1930233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return false;
1931233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1932233d2500723e5594f3e7c70896ffeeef32b9c950ywan#ifdef _MSC_VER
1933233d2500723e5594f3e7c70896ffeeef32b9c950ywan  strcpy_s(muxing_app_, app_len, temp);
1934233d2500723e5594f3e7c70896ffeeef32b9c950ywan#else
1935233d2500723e5594f3e7c70896ffeeef32b9c950ywan  strcpy(muxing_app_, temp);
1936233d2500723e5594f3e7c70896ffeeef32b9c950ywan#endif
1937233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1938233d2500723e5594f3e7c70896ffeeef32b9c950ywan  set_writing_app(temp);
1939233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (!writing_app_)
1940233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return false;
1941233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return true;
1942233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
1943233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1944233d2500723e5594f3e7c70896ffeeef32b9c950ywanbool SegmentInfo::Finalize(IMkvWriter* writer) const {
1945233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (!writer)
1946233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return false;
1947233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1948233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (duration_ > 0.0) {
1949233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (writer->Seekable()) {
1950233d2500723e5594f3e7c70896ffeeef32b9c950ywan      if (duration_pos_ == -1)
1951233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return false;
1952233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1953233d2500723e5594f3e7c70896ffeeef32b9c950ywan      const int64 pos = writer->Position();
1954233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1955233d2500723e5594f3e7c70896ffeeef32b9c950ywan      if (writer->Position(duration_pos_))
1956233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return false;
1957233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1958233d2500723e5594f3e7c70896ffeeef32b9c950ywan      if (!WriteEbmlElement(writer,
1959233d2500723e5594f3e7c70896ffeeef32b9c950ywan                            kMkvDuration,
1960233d2500723e5594f3e7c70896ffeeef32b9c950ywan                            static_cast<float>(duration_)))
1961233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return false;
1962233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1963233d2500723e5594f3e7c70896ffeeef32b9c950ywan      if (writer->Position(pos))
1964233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return false;
1965233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
1966233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
1967233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1968233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return true;
1969233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
1970233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1971233d2500723e5594f3e7c70896ffeeef32b9c950ywanbool SegmentInfo::Write(IMkvWriter* writer) {
1972233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (!writer || !muxing_app_ || !writing_app_)
1973233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return false;
1974233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1975233d2500723e5594f3e7c70896ffeeef32b9c950ywan  uint64 size = EbmlElementSize(kMkvTimecodeScale, timecode_scale_);
1976233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (duration_ > 0.0)
1977233d2500723e5594f3e7c70896ffeeef32b9c950ywan    size += EbmlElementSize(kMkvDuration, static_cast<float>(duration_));
1978233d2500723e5594f3e7c70896ffeeef32b9c950ywan  size += EbmlElementSize(kMkvMuxingApp, muxing_app_);
1979233d2500723e5594f3e7c70896ffeeef32b9c950ywan  size += EbmlElementSize(kMkvWritingApp, writing_app_);
1980233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1981233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (!WriteEbmlMasterElement(writer, kMkvInfo, size))
1982233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return false;
1983233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1984233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const int64 payload_position = writer->Position();
1985233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (payload_position < 0)
1986233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return false;
1987233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1988233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (!WriteEbmlElement(writer, kMkvTimecodeScale, timecode_scale_))
1989233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return false;
1990233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1991233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (duration_ > 0.0) {
1992233d2500723e5594f3e7c70896ffeeef32b9c950ywan    // Save for later
1993233d2500723e5594f3e7c70896ffeeef32b9c950ywan    duration_pos_ = writer->Position();
1994233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1995233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (!WriteEbmlElement(writer, kMkvDuration, static_cast<float>(duration_)))
1996233d2500723e5594f3e7c70896ffeeef32b9c950ywan      return false;
1997233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
1998233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1999233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (!WriteEbmlElement(writer, kMkvMuxingApp, muxing_app_))
2000233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return false;
2001233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (!WriteEbmlElement(writer, kMkvWritingApp, writing_app_))
2002233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return false;
2003233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2004233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const int64 stop_position = writer->Position();
2005233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (stop_position < 0 ||
2006233d2500723e5594f3e7c70896ffeeef32b9c950ywan      stop_position - payload_position != static_cast<int64>(size))
2007233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return false;
2008233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2009233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return true;
2010233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
2011233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2012233d2500723e5594f3e7c70896ffeeef32b9c950ywanvoid SegmentInfo::set_muxing_app(const char* app) {
2013233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (app) {
2014233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const size_t length = strlen(app) + 1;
2015233d2500723e5594f3e7c70896ffeeef32b9c950ywan    char* temp_str = new (std::nothrow) char[length];  // NOLINT
2016233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (!temp_str)
2017233d2500723e5594f3e7c70896ffeeef32b9c950ywan      return;
2018233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2019233d2500723e5594f3e7c70896ffeeef32b9c950ywan#ifdef _MSC_VER
2020233d2500723e5594f3e7c70896ffeeef32b9c950ywan    strcpy_s(temp_str, length, app);
2021233d2500723e5594f3e7c70896ffeeef32b9c950ywan#else
2022233d2500723e5594f3e7c70896ffeeef32b9c950ywan    strcpy(temp_str, app);
2023233d2500723e5594f3e7c70896ffeeef32b9c950ywan#endif
2024233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2025233d2500723e5594f3e7c70896ffeeef32b9c950ywan    delete [] muxing_app_;
2026233d2500723e5594f3e7c70896ffeeef32b9c950ywan    muxing_app_ = temp_str;
2027233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
2028233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
2029233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2030233d2500723e5594f3e7c70896ffeeef32b9c950ywanvoid SegmentInfo::set_writing_app(const char* app) {
2031233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (app) {
2032233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const size_t length = strlen(app) + 1;
2033233d2500723e5594f3e7c70896ffeeef32b9c950ywan    char* temp_str = new (std::nothrow) char[length];  // NOLINT
2034233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (!temp_str)
2035233d2500723e5594f3e7c70896ffeeef32b9c950ywan      return;
2036233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2037233d2500723e5594f3e7c70896ffeeef32b9c950ywan#ifdef _MSC_VER
2038233d2500723e5594f3e7c70896ffeeef32b9c950ywan    strcpy_s(temp_str, length, app);
2039233d2500723e5594f3e7c70896ffeeef32b9c950ywan#else
2040233d2500723e5594f3e7c70896ffeeef32b9c950ywan    strcpy(temp_str, app);
2041233d2500723e5594f3e7c70896ffeeef32b9c950ywan#endif
2042233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2043233d2500723e5594f3e7c70896ffeeef32b9c950ywan    delete [] writing_app_;
2044233d2500723e5594f3e7c70896ffeeef32b9c950ywan    writing_app_ = temp_str;
2045233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
2046233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
2047233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2048233d2500723e5594f3e7c70896ffeeef32b9c950ywan///////////////////////////////////////////////////////////////
2049233d2500723e5594f3e7c70896ffeeef32b9c950ywan//
2050233d2500723e5594f3e7c70896ffeeef32b9c950ywan// Segment Class
2051233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2052233d2500723e5594f3e7c70896ffeeef32b9c950ywanSegment::Segment()
2053233d2500723e5594f3e7c70896ffeeef32b9c950ywan    : chunk_count_(0),
2054233d2500723e5594f3e7c70896ffeeef32b9c950ywan      chunk_name_(NULL),
2055233d2500723e5594f3e7c70896ffeeef32b9c950ywan      chunk_writer_cluster_(NULL),
2056233d2500723e5594f3e7c70896ffeeef32b9c950ywan      chunk_writer_cues_(NULL),
2057233d2500723e5594f3e7c70896ffeeef32b9c950ywan      chunk_writer_header_(NULL),
2058233d2500723e5594f3e7c70896ffeeef32b9c950ywan      chunking_(false),
2059233d2500723e5594f3e7c70896ffeeef32b9c950ywan      chunking_base_name_(NULL),
2060233d2500723e5594f3e7c70896ffeeef32b9c950ywan      cluster_list_(NULL),
2061233d2500723e5594f3e7c70896ffeeef32b9c950ywan      cluster_list_capacity_(0),
2062233d2500723e5594f3e7c70896ffeeef32b9c950ywan      cluster_list_size_(0),
2063233d2500723e5594f3e7c70896ffeeef32b9c950ywan      cues_position_(kAfterClusters),
2064233d2500723e5594f3e7c70896ffeeef32b9c950ywan      cues_track_(0),
2065233d2500723e5594f3e7c70896ffeeef32b9c950ywan      force_new_cluster_(false),
2066233d2500723e5594f3e7c70896ffeeef32b9c950ywan      frames_(NULL),
2067233d2500723e5594f3e7c70896ffeeef32b9c950ywan      frames_capacity_(0),
2068233d2500723e5594f3e7c70896ffeeef32b9c950ywan      frames_size_(0),
2069233d2500723e5594f3e7c70896ffeeef32b9c950ywan      has_video_(false),
2070233d2500723e5594f3e7c70896ffeeef32b9c950ywan      header_written_(false),
2071233d2500723e5594f3e7c70896ffeeef32b9c950ywan      last_block_duration_(0),
2072233d2500723e5594f3e7c70896ffeeef32b9c950ywan      last_timestamp_(0),
2073233d2500723e5594f3e7c70896ffeeef32b9c950ywan      max_cluster_duration_(kDefaultMaxClusterDuration),
2074233d2500723e5594f3e7c70896ffeeef32b9c950ywan      max_cluster_size_(0),
2075233d2500723e5594f3e7c70896ffeeef32b9c950ywan      mode_(kFile),
2076233d2500723e5594f3e7c70896ffeeef32b9c950ywan      new_cuepoint_(false),
2077233d2500723e5594f3e7c70896ffeeef32b9c950ywan      output_cues_(true),
2078233d2500723e5594f3e7c70896ffeeef32b9c950ywan      payload_pos_(0),
2079233d2500723e5594f3e7c70896ffeeef32b9c950ywan      size_position_(0),
2080233d2500723e5594f3e7c70896ffeeef32b9c950ywan      writer_cluster_(NULL),
2081233d2500723e5594f3e7c70896ffeeef32b9c950ywan      writer_cues_(NULL),
2082233d2500723e5594f3e7c70896ffeeef32b9c950ywan      writer_header_(NULL) {
2083233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const time_t curr_time = time(NULL);
2084233d2500723e5594f3e7c70896ffeeef32b9c950ywan  seed_ = static_cast<unsigned int>(curr_time);
2085233d2500723e5594f3e7c70896ffeeef32b9c950ywan#ifdef _WIN32
2086233d2500723e5594f3e7c70896ffeeef32b9c950ywan  srand(seed_);
2087233d2500723e5594f3e7c70896ffeeef32b9c950ywan#endif
2088233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
2089233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2090233d2500723e5594f3e7c70896ffeeef32b9c950ywanSegment::~Segment() {
2091233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (cluster_list_) {
2092233d2500723e5594f3e7c70896ffeeef32b9c950ywan    for (int32 i = 0; i < cluster_list_size_; ++i) {
2093233d2500723e5594f3e7c70896ffeeef32b9c950ywan      Cluster* const cluster = cluster_list_[i];
2094233d2500723e5594f3e7c70896ffeeef32b9c950ywan      delete cluster;
2095233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
2096233d2500723e5594f3e7c70896ffeeef32b9c950ywan    delete [] cluster_list_;
2097233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
2098233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2099233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (frames_) {
2100233d2500723e5594f3e7c70896ffeeef32b9c950ywan    for (int32 i = 0; i < frames_size_; ++i) {
2101233d2500723e5594f3e7c70896ffeeef32b9c950ywan      Frame* const frame = frames_[i];
2102233d2500723e5594f3e7c70896ffeeef32b9c950ywan      delete frame;
2103233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
2104233d2500723e5594f3e7c70896ffeeef32b9c950ywan    delete [] frames_;
2105233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
2106233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2107233d2500723e5594f3e7c70896ffeeef32b9c950ywan  delete [] chunk_name_;
2108233d2500723e5594f3e7c70896ffeeef32b9c950ywan  delete [] chunking_base_name_;
2109233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2110233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (chunk_writer_cluster_) {
2111233d2500723e5594f3e7c70896ffeeef32b9c950ywan    chunk_writer_cluster_->Close();
2112233d2500723e5594f3e7c70896ffeeef32b9c950ywan    delete chunk_writer_cluster_;
2113233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
2114233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (chunk_writer_cues_) {
2115233d2500723e5594f3e7c70896ffeeef32b9c950ywan    chunk_writer_cues_->Close();
2116233d2500723e5594f3e7c70896ffeeef32b9c950ywan    delete chunk_writer_cues_;
2117233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
2118233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (chunk_writer_header_) {
2119233d2500723e5594f3e7c70896ffeeef32b9c950ywan    chunk_writer_header_->Close();
2120233d2500723e5594f3e7c70896ffeeef32b9c950ywan    delete chunk_writer_header_;
2121233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
2122233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
2123233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2124233d2500723e5594f3e7c70896ffeeef32b9c950ywanvoid Segment::MoveCuesBeforeClustersHelper(uint64 diff,
2125233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                           int32 index,
2126233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                           uint64* cues_size) {
2127233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const uint64 old_cues_size = *cues_size;
2128233d2500723e5594f3e7c70896ffeeef32b9c950ywan  CuePoint* const cue_point = cues_.GetCueByIndex(index);
2129233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (cue_point == NULL)
2130233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return;
2131233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const uint64 old_cue_point_size = cue_point->Size();
2132233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const uint64 cluster_pos = cue_point->cluster_pos() + diff;
2133233d2500723e5594f3e7c70896ffeeef32b9c950ywan  cue_point->set_cluster_pos(cluster_pos);  // update the new cluster position
2134233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // New size of the cue is computed as follows
2135233d2500723e5594f3e7c70896ffeeef32b9c950ywan  //    Let a = current size of Cues Element
2136233d2500723e5594f3e7c70896ffeeef32b9c950ywan  //    Let b = Difference in Cue Point's size after this pass
2137233d2500723e5594f3e7c70896ffeeef32b9c950ywan  //    Let c = Difference in length of Cues Element's size
2138233d2500723e5594f3e7c70896ffeeef32b9c950ywan  //            (This is computed as CodedSize(a + b) - CodedSize(a)
2139233d2500723e5594f3e7c70896ffeeef32b9c950ywan  //    Let d = a + b + c. Now d is the new size of the Cues element which is
2140233d2500723e5594f3e7c70896ffeeef32b9c950ywan  //                       passed on to the next recursive call.
2141233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const uint64 cue_point_size_diff = cue_point->Size() - old_cue_point_size;
2142233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const uint64 cue_size_diff = GetCodedUIntSize(*cues_size +
2143233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                                cue_point_size_diff) -
2144233d2500723e5594f3e7c70896ffeeef32b9c950ywan                               GetCodedUIntSize(*cues_size);
2145233d2500723e5594f3e7c70896ffeeef32b9c950ywan  *cues_size += cue_point_size_diff + cue_size_diff;
2146233d2500723e5594f3e7c70896ffeeef32b9c950ywan  diff = *cues_size - old_cues_size;
2147233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (diff > 0) {
2148233d2500723e5594f3e7c70896ffeeef32b9c950ywan    for (int32 i = 0; i < cues_.cue_entries_size(); ++i) {
2149233d2500723e5594f3e7c70896ffeeef32b9c950ywan      MoveCuesBeforeClustersHelper(diff, i, cues_size);
2150233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
2151233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
2152233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
2153233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2154233d2500723e5594f3e7c70896ffeeef32b9c950ywanvoid Segment::MoveCuesBeforeClusters() {
2155233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const uint64 current_cue_size = cues_.Size();
2156233d2500723e5594f3e7c70896ffeeef32b9c950ywan  uint64 cue_size = current_cue_size;
2157233d2500723e5594f3e7c70896ffeeef32b9c950ywan  for (int32 i = 0; i < cues_.cue_entries_size(); i++)
2158233d2500723e5594f3e7c70896ffeeef32b9c950ywan    MoveCuesBeforeClustersHelper(current_cue_size, i, &cue_size);
2159233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2160233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // Adjust the Seek Entry to reflect the change in position
2161233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // of Cluster and Cues
2162233d2500723e5594f3e7c70896ffeeef32b9c950ywan  int32 cluster_index = 0;
2163233d2500723e5594f3e7c70896ffeeef32b9c950ywan  int32 cues_index = 0;
2164233d2500723e5594f3e7c70896ffeeef32b9c950ywan  for (int32 i = 0; i < SeekHead::kSeekEntryCount; ++i) {
2165233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (seek_head_.GetId(i) == kMkvCluster)
2166233d2500723e5594f3e7c70896ffeeef32b9c950ywan      cluster_index = i;
2167233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (seek_head_.GetId(i) == kMkvCues)
2168233d2500723e5594f3e7c70896ffeeef32b9c950ywan      cues_index = i;
2169233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
2170233d2500723e5594f3e7c70896ffeeef32b9c950ywan  seek_head_.SetSeekEntry(cues_index, kMkvCues,
2171233d2500723e5594f3e7c70896ffeeef32b9c950ywan                          seek_head_.GetPosition(cluster_index));
2172233d2500723e5594f3e7c70896ffeeef32b9c950ywan  seek_head_.SetSeekEntry(cluster_index, kMkvCluster,
2173233d2500723e5594f3e7c70896ffeeef32b9c950ywan                          cues_.Size() + seek_head_.GetPosition(cues_index));
2174233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
2175233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2176233d2500723e5594f3e7c70896ffeeef32b9c950ywanbool Segment::Init(IMkvWriter* ptr_writer) {
2177233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (!ptr_writer) {
2178233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return false;
2179233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
2180233d2500723e5594f3e7c70896ffeeef32b9c950ywan  writer_cluster_ = ptr_writer;
2181233d2500723e5594f3e7c70896ffeeef32b9c950ywan  writer_cues_ = ptr_writer;
2182233d2500723e5594f3e7c70896ffeeef32b9c950ywan  writer_header_ = ptr_writer;
2183233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return segment_info_.Init();
2184233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
2185233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2186233d2500723e5594f3e7c70896ffeeef32b9c950ywanbool Segment::CopyAndMoveCuesBeforeClusters(mkvparser::IMkvReader* reader,
2187233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                            IMkvWriter* writer) {
2188233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (!writer->Seekable() || chunking_)
2189233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return false;
2190233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const int64 cluster_offset = cluster_list_[0]->size_position() -
2191233d2500723e5594f3e7c70896ffeeef32b9c950ywan                               GetUIntSize(kMkvCluster);
2192233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2193233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // Copy the headers.
2194233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (!ChunkedCopy(reader, writer, 0, cluster_offset))
2195233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return false;
2196233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2197233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // Recompute cue positions and seek entries.
2198233d2500723e5594f3e7c70896ffeeef32b9c950ywan  MoveCuesBeforeClusters();
2199233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2200233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // Write cues and seek entries.
2201233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // TODO(vigneshv): As of now, it's safe to call seek_head_.Finalize() for the
2202233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // second time with a different writer object. But the name Finalize() doesn't
2203233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // indicate something we want to call more than once. So consider renaming it
2204233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // to write() or some such.
2205233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (!cues_.Write(writer) || !seek_head_.Finalize(writer))
2206233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return false;
2207233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2208233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // Copy the Clusters.
2209233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (!ChunkedCopy(reader, writer, cluster_offset,
2210233d2500723e5594f3e7c70896ffeeef32b9c950ywan                   cluster_end_offset_ - cluster_offset))
2211233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return false;
2212233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2213233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // Update the Segment size in case the Cues size has changed.
2214233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const int64 pos = writer->Position();
2215233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const int64 segment_size = writer->Position() - payload_pos_;
2216233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (writer->Position(size_position_) ||
2217233d2500723e5594f3e7c70896ffeeef32b9c950ywan      WriteUIntSize(writer, segment_size, 8) ||
2218233d2500723e5594f3e7c70896ffeeef32b9c950ywan      writer->Position(pos))
2219233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return false;
2220233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return true;
2221233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
2222233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2223233d2500723e5594f3e7c70896ffeeef32b9c950ywanbool Segment::Finalize() {
2224233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (WriteFramesAll() < 0)
2225233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return false;
2226233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2227233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (mode_ == kFile) {
2228233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (cluster_list_size_ > 0) {
2229233d2500723e5594f3e7c70896ffeeef32b9c950ywan      // Update last cluster's size
2230233d2500723e5594f3e7c70896ffeeef32b9c950ywan      Cluster* const old_cluster = cluster_list_[cluster_list_size_-1];
2231233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2232233d2500723e5594f3e7c70896ffeeef32b9c950ywan      if (!old_cluster || !old_cluster->Finalize())
2233233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return false;
2234233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
2235233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2236233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (chunking_ && chunk_writer_cluster_) {
2237233d2500723e5594f3e7c70896ffeeef32b9c950ywan      chunk_writer_cluster_->Close();
2238233d2500723e5594f3e7c70896ffeeef32b9c950ywan      chunk_count_++;
2239233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
2240233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2241233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const double duration =
2242233d2500723e5594f3e7c70896ffeeef32b9c950ywan        (static_cast<double>(last_timestamp_) + last_block_duration_) /
2243233d2500723e5594f3e7c70896ffeeef32b9c950ywan        segment_info_.timecode_scale();
2244233d2500723e5594f3e7c70896ffeeef32b9c950ywan    segment_info_.set_duration(duration);
2245233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (!segment_info_.Finalize(writer_header_))
2246233d2500723e5594f3e7c70896ffeeef32b9c950ywan      return false;
2247233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2248233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (output_cues_)
2249233d2500723e5594f3e7c70896ffeeef32b9c950ywan      if (!seek_head_.AddSeekEntry(kMkvCues, MaxOffset()))
2250233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return false;
2251233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2252233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (chunking_) {
2253233d2500723e5594f3e7c70896ffeeef32b9c950ywan      if (!chunk_writer_cues_)
2254233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return false;
2255233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2256233d2500723e5594f3e7c70896ffeeef32b9c950ywan      char* name = NULL;
2257233d2500723e5594f3e7c70896ffeeef32b9c950ywan      if (!UpdateChunkName("cues", &name))
2258233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return false;
2259233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2260233d2500723e5594f3e7c70896ffeeef32b9c950ywan      const bool cues_open = chunk_writer_cues_->Open(name);
2261233d2500723e5594f3e7c70896ffeeef32b9c950ywan      delete [] name;
2262233d2500723e5594f3e7c70896ffeeef32b9c950ywan      if (!cues_open)
2263233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return false;
2264233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
2265233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2266233d2500723e5594f3e7c70896ffeeef32b9c950ywan    cluster_end_offset_ = writer_cluster_->Position();
2267233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2268233d2500723e5594f3e7c70896ffeeef32b9c950ywan    // Write the seek headers and cues
2269233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (output_cues_)
2270233d2500723e5594f3e7c70896ffeeef32b9c950ywan      if (!cues_.Write(writer_cues_))
2271233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return false;
2272233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2273233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (!seek_head_.Finalize(writer_header_))
2274233d2500723e5594f3e7c70896ffeeef32b9c950ywan      return false;
2275233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2276233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (writer_header_->Seekable()) {
2277233d2500723e5594f3e7c70896ffeeef32b9c950ywan      if (size_position_ == -1)
2278233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return false;
2279233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2280233d2500723e5594f3e7c70896ffeeef32b9c950ywan      const int64 pos = writer_header_->Position();
2281233d2500723e5594f3e7c70896ffeeef32b9c950ywan      const int64 segment_size = MaxOffset();
2282233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2283233d2500723e5594f3e7c70896ffeeef32b9c950ywan      if (segment_size < 1)
2284233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return false;
2285233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2286233d2500723e5594f3e7c70896ffeeef32b9c950ywan      if (writer_header_->Position(size_position_))
2287233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return false;
2288233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2289233d2500723e5594f3e7c70896ffeeef32b9c950ywan      if (WriteUIntSize(writer_header_, segment_size, 8))
2290233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return false;
2291233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2292233d2500723e5594f3e7c70896ffeeef32b9c950ywan      if (writer_header_->Position(pos))
2293233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return false;
2294233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
2295233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2296233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (chunking_) {
2297233d2500723e5594f3e7c70896ffeeef32b9c950ywan      // Do not close any writers until the segment size has been written,
2298233d2500723e5594f3e7c70896ffeeef32b9c950ywan      // otherwise the size may be off.
2299233d2500723e5594f3e7c70896ffeeef32b9c950ywan      if (!chunk_writer_cues_ || !chunk_writer_header_)
2300233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return false;
2301233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2302233d2500723e5594f3e7c70896ffeeef32b9c950ywan      chunk_writer_cues_->Close();
2303233d2500723e5594f3e7c70896ffeeef32b9c950ywan      chunk_writer_header_->Close();
2304233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
2305233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
2306233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2307233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return true;
2308233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
2309233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2310233d2500723e5594f3e7c70896ffeeef32b9c950ywanTrack* Segment::AddTrack(int32 number) {
2311233d2500723e5594f3e7c70896ffeeef32b9c950ywan  Track* const track = new (std::nothrow) Track(&seed_);  // NOLINT
2312233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2313233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (!track)
2314233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return NULL;
2315233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2316233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (!tracks_.AddTrack(track, number)) {
2317233d2500723e5594f3e7c70896ffeeef32b9c950ywan    delete track;
2318233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return NULL;
2319233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
2320233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2321233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return track;
2322233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
2323233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2324233d2500723e5594f3e7c70896ffeeef32b9c950ywanChapter* Segment::AddChapter() {
2325233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return chapters_.AddChapter(&seed_);
2326233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
2327233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2328233d2500723e5594f3e7c70896ffeeef32b9c950ywanuint64 Segment::AddVideoTrack(int32 width, int32 height, int32 number) {
2329233d2500723e5594f3e7c70896ffeeef32b9c950ywan  VideoTrack* const track = new (std::nothrow) VideoTrack(&seed_);  // NOLINT
2330233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (!track)
2331233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return 0;
2332233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2333233d2500723e5594f3e7c70896ffeeef32b9c950ywan  track->set_type(Tracks::kVideo);
2334233d2500723e5594f3e7c70896ffeeef32b9c950ywan  track->set_codec_id(Tracks::kVp8CodecId);
2335233d2500723e5594f3e7c70896ffeeef32b9c950ywan  track->set_width(width);
2336233d2500723e5594f3e7c70896ffeeef32b9c950ywan  track->set_height(height);
2337233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2338233d2500723e5594f3e7c70896ffeeef32b9c950ywan  tracks_.AddTrack(track, number);
2339233d2500723e5594f3e7c70896ffeeef32b9c950ywan  has_video_ = true;
2340233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2341233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return track->number();
2342233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
2343233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2344233d2500723e5594f3e7c70896ffeeef32b9c950ywanbool Segment::AddCuePoint(uint64 timestamp, uint64 track) {
2345233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (cluster_list_size_  < 1)
2346233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return false;
2347233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2348233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const Cluster* const cluster = cluster_list_[cluster_list_size_-1];
2349233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (!cluster)
2350233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return false;
2351233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2352233d2500723e5594f3e7c70896ffeeef32b9c950ywan  CuePoint* const cue = new (std::nothrow) CuePoint();  // NOLINT
2353233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (!cue)
2354233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return false;
2355233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2356233d2500723e5594f3e7c70896ffeeef32b9c950ywan  cue->set_time(timestamp / segment_info_.timecode_scale());
2357233d2500723e5594f3e7c70896ffeeef32b9c950ywan  cue->set_block_number(cluster->blocks_added());
2358233d2500723e5594f3e7c70896ffeeef32b9c950ywan  cue->set_cluster_pos(cluster->position_for_cues());
2359233d2500723e5594f3e7c70896ffeeef32b9c950ywan  cue->set_track(track);
2360233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (!cues_.AddCue(cue))
2361233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return false;
2362233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2363233d2500723e5594f3e7c70896ffeeef32b9c950ywan  new_cuepoint_ = false;
2364233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return true;
2365233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
2366233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2367233d2500723e5594f3e7c70896ffeeef32b9c950ywanuint64 Segment::AddAudioTrack(int32 sample_rate,
2368233d2500723e5594f3e7c70896ffeeef32b9c950ywan                              int32 channels,
2369233d2500723e5594f3e7c70896ffeeef32b9c950ywan                              int32 number) {
2370233d2500723e5594f3e7c70896ffeeef32b9c950ywan  AudioTrack* const track = new (std::nothrow) AudioTrack(&seed_);  // NOLINT
2371233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (!track)
2372233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return 0;
2373233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2374233d2500723e5594f3e7c70896ffeeef32b9c950ywan  track->set_type(Tracks::kAudio);
2375233d2500723e5594f3e7c70896ffeeef32b9c950ywan  track->set_codec_id(Tracks::kVorbisCodecId);
2376233d2500723e5594f3e7c70896ffeeef32b9c950ywan  track->set_sample_rate(sample_rate);
2377233d2500723e5594f3e7c70896ffeeef32b9c950ywan  track->set_channels(channels);
2378233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2379233d2500723e5594f3e7c70896ffeeef32b9c950ywan  tracks_.AddTrack(track, number);
2380233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2381233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return track->number();
2382233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
2383233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2384233d2500723e5594f3e7c70896ffeeef32b9c950ywanbool Segment::AddFrame(const uint8* frame,
2385233d2500723e5594f3e7c70896ffeeef32b9c950ywan                       uint64 length,
2386233d2500723e5594f3e7c70896ffeeef32b9c950ywan                       uint64 track_number,
2387233d2500723e5594f3e7c70896ffeeef32b9c950ywan                       uint64 timestamp,
2388233d2500723e5594f3e7c70896ffeeef32b9c950ywan                       bool is_key) {
2389233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (!frame)
2390233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return false;
2391233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2392233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (!CheckHeaderInfo())
2393233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return false;
2394233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2395233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // Check for non-monotonically increasing timestamps.
2396233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (timestamp < last_timestamp_)
2397233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return false;
2398233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2399233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // If the segment has a video track hold onto audio frames to make sure the
2400233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // audio that is associated with the start time of a video key-frame is
2401233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // muxed into the same cluster.
2402233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (has_video_ && tracks_.TrackIsAudio(track_number) && !force_new_cluster_) {
2403233d2500723e5594f3e7c70896ffeeef32b9c950ywan    Frame* const new_frame = new (std::nothrow) Frame();
2404233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (new_frame == NULL || !new_frame->Init(frame, length))
2405233d2500723e5594f3e7c70896ffeeef32b9c950ywan      return false;
2406233d2500723e5594f3e7c70896ffeeef32b9c950ywan    new_frame->set_track_number(track_number);
2407233d2500723e5594f3e7c70896ffeeef32b9c950ywan    new_frame->set_timestamp(timestamp);
2408233d2500723e5594f3e7c70896ffeeef32b9c950ywan    new_frame->set_is_key(is_key);
2409233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2410233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (!QueueFrame(new_frame))
2411233d2500723e5594f3e7c70896ffeeef32b9c950ywan      return false;
2412233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2413233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return true;
2414233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
2415233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2416233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (!DoNewClusterProcessing(track_number, timestamp, is_key))
2417233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return false;
2418233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2419233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (cluster_list_size_ < 1)
2420233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return false;
2421233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2422233d2500723e5594f3e7c70896ffeeef32b9c950ywan  Cluster* const cluster = cluster_list_[cluster_list_size_ - 1];
2423233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (!cluster)
2424233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return false;
2425233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2426233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const uint64 timecode_scale = segment_info_.timecode_scale();
2427233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const uint64 abs_timecode = timestamp / timecode_scale;
2428233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2429233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (!cluster->AddFrame(frame,
2430233d2500723e5594f3e7c70896ffeeef32b9c950ywan                         length,
2431233d2500723e5594f3e7c70896ffeeef32b9c950ywan                         track_number,
2432233d2500723e5594f3e7c70896ffeeef32b9c950ywan                         abs_timecode,
2433233d2500723e5594f3e7c70896ffeeef32b9c950ywan                         is_key))
2434233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return false;
2435233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2436233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (new_cuepoint_ && cues_track_ == track_number) {
2437233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (!AddCuePoint(timestamp, cues_track_))
2438233d2500723e5594f3e7c70896ffeeef32b9c950ywan      return false;
2439233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
2440233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2441233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (timestamp > last_timestamp_)
2442233d2500723e5594f3e7c70896ffeeef32b9c950ywan    last_timestamp_ = timestamp;
2443233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2444233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return true;
2445233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
2446233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2447233d2500723e5594f3e7c70896ffeeef32b9c950ywanbool Segment::AddFrameWithAdditional(const uint8* frame,
2448233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                     uint64 length,
2449233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                     const uint8* additional,
2450233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                     uint64 additional_length,
2451233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                     uint64 add_id,
2452233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                     uint64 track_number,
2453233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                     uint64 timestamp,
2454233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                     bool is_key) {
2455233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (frame == NULL || additional == NULL)
2456233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return false;
2457233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2458233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (!CheckHeaderInfo())
2459233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return false;
2460233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2461233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // Check for non-monotonically increasing timestamps.
2462233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (timestamp < last_timestamp_)
2463233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return false;
2464233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2465233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // If the segment has a video track hold onto audio frames to make sure the
2466233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // audio that is associated with the start time of a video key-frame is
2467233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // muxed into the same cluster.
2468233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (has_video_ && tracks_.TrackIsAudio(track_number) && !force_new_cluster_) {
2469233d2500723e5594f3e7c70896ffeeef32b9c950ywan    Frame* const new_frame = new (std::nothrow) Frame();
2470233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (new_frame == NULL || !new_frame->Init(frame, length))
2471233d2500723e5594f3e7c70896ffeeef32b9c950ywan      return false;
2472233d2500723e5594f3e7c70896ffeeef32b9c950ywan    new_frame->set_track_number(track_number);
2473233d2500723e5594f3e7c70896ffeeef32b9c950ywan    new_frame->set_timestamp(timestamp);
2474233d2500723e5594f3e7c70896ffeeef32b9c950ywan    new_frame->set_is_key(is_key);
2475233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2476233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (!QueueFrame(new_frame))
2477233d2500723e5594f3e7c70896ffeeef32b9c950ywan      return false;
2478233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2479233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return true;
2480233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
2481233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2482233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (!DoNewClusterProcessing(track_number, timestamp, is_key))
2483233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return false;
2484233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2485233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (cluster_list_size_ < 1)
2486233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return false;
2487233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2488233d2500723e5594f3e7c70896ffeeef32b9c950ywan  Cluster* const cluster = cluster_list_[cluster_list_size_ - 1];
2489233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (cluster == NULL)
2490233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return false;
2491233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2492233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const uint64 timecode_scale = segment_info_.timecode_scale();
2493233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const uint64 abs_timecode = timestamp / timecode_scale;
2494233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2495233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (!cluster->AddFrameWithAdditional(frame,
2496233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                       length,
2497233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                       additional,
2498233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                       additional_length,
2499233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                       add_id,
2500233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                       track_number,
2501233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                       abs_timecode,
2502233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                       is_key))
2503233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return false;
2504233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2505233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (new_cuepoint_ && cues_track_ == track_number) {
2506233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (!AddCuePoint(timestamp, cues_track_))
2507233d2500723e5594f3e7c70896ffeeef32b9c950ywan      return false;
2508233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
2509233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2510233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (timestamp > last_timestamp_)
2511233d2500723e5594f3e7c70896ffeeef32b9c950ywan    last_timestamp_ = timestamp;
2512233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2513233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return true;
2514233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
2515233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2516233d2500723e5594f3e7c70896ffeeef32b9c950ywanbool Segment::AddFrameWithDiscardPadding(const uint8* frame,
2517233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                         uint64 length,
2518233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                         int64 discard_padding,
2519233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                         uint64 track_number,
2520233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                         uint64 timestamp,
2521233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                         bool is_key) {
2522233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (frame == NULL || discard_padding <= 0)
2523233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return false;
2524233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2525233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (!CheckHeaderInfo())
2526233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return false;
2527233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2528233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // Check for non-monotonically increasing timestamps.
2529233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (timestamp < last_timestamp_)
2530233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return false;
2531233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2532233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // If the segment has a video track hold onto audio frames to make sure the
2533233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // audio that is associated with the start time of a video key-frame is
2534233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // muxed into the same cluster.
2535233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (has_video_ && tracks_.TrackIsAudio(track_number) && !force_new_cluster_) {
2536233d2500723e5594f3e7c70896ffeeef32b9c950ywan    Frame* const new_frame = new (std::nothrow) Frame();
2537233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (new_frame == NULL || !new_frame->Init(frame, length))
2538233d2500723e5594f3e7c70896ffeeef32b9c950ywan      return false;
2539233d2500723e5594f3e7c70896ffeeef32b9c950ywan    new_frame->set_track_number(track_number);
2540233d2500723e5594f3e7c70896ffeeef32b9c950ywan    new_frame->set_timestamp(timestamp);
2541233d2500723e5594f3e7c70896ffeeef32b9c950ywan    new_frame->set_is_key(is_key);
2542233d2500723e5594f3e7c70896ffeeef32b9c950ywan    new_frame->set_discard_padding(discard_padding);
2543233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2544233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (!QueueFrame(new_frame))
2545233d2500723e5594f3e7c70896ffeeef32b9c950ywan      return false;
2546233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2547233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return true;
2548233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
2549233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2550233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (!DoNewClusterProcessing(track_number, timestamp, is_key))
2551233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return false;
2552233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2553233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (cluster_list_size_ < 1)
2554233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return false;
2555233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2556233d2500723e5594f3e7c70896ffeeef32b9c950ywan  Cluster* const cluster = cluster_list_[cluster_list_size_ - 1];
2557233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (!cluster)
2558233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return false;
2559233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2560233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const uint64 timecode_scale = segment_info_.timecode_scale();
2561233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const uint64 abs_timecode = timestamp / timecode_scale;
2562233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2563233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (!cluster->AddFrameWithDiscardPadding(frame, length,
2564233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                           discard_padding,
2565233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                           track_number,
2566233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                           abs_timecode,
2567233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                           is_key)) {
2568233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return false;
2569233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
2570233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2571233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (new_cuepoint_ && cues_track_ == track_number) {
2572233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (!AddCuePoint(timestamp, cues_track_))
2573233d2500723e5594f3e7c70896ffeeef32b9c950ywan      return false;
2574233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
2575233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2576233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (timestamp > last_timestamp_)
2577233d2500723e5594f3e7c70896ffeeef32b9c950ywan    last_timestamp_ = timestamp;
2578233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2579233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return true;
2580233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
2581233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2582233d2500723e5594f3e7c70896ffeeef32b9c950ywanbool Segment::AddMetadata(const uint8* frame,
2583233d2500723e5594f3e7c70896ffeeef32b9c950ywan                          uint64 length,
2584233d2500723e5594f3e7c70896ffeeef32b9c950ywan                          uint64 track_number,
2585233d2500723e5594f3e7c70896ffeeef32b9c950ywan                          uint64 timestamp_ns,
2586233d2500723e5594f3e7c70896ffeeef32b9c950ywan                          uint64 duration_ns) {
2587233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (!frame)
2588233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return false;
2589233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2590233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (!CheckHeaderInfo())
2591233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return false;
2592233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2593233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // Check for non-monotonically increasing timestamps.
2594233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (timestamp_ns < last_timestamp_)
2595233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return false;
2596233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2597233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (!DoNewClusterProcessing(track_number, timestamp_ns, true))
2598233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return false;
2599233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2600233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (cluster_list_size_ < 1)
2601233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return false;
2602233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2603233d2500723e5594f3e7c70896ffeeef32b9c950ywan  Cluster* const cluster = cluster_list_[cluster_list_size_-1];
2604233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2605233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (!cluster)
2606233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return false;
2607233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2608233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const uint64 timecode_scale = segment_info_.timecode_scale();
2609233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const uint64 abs_timecode = timestamp_ns / timecode_scale;
2610233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const uint64 duration_timecode = duration_ns / timecode_scale;
2611233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2612233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (!cluster->AddMetadata(frame,
2613233d2500723e5594f3e7c70896ffeeef32b9c950ywan                            length,
2614233d2500723e5594f3e7c70896ffeeef32b9c950ywan                            track_number,
2615233d2500723e5594f3e7c70896ffeeef32b9c950ywan                            abs_timecode,
2616233d2500723e5594f3e7c70896ffeeef32b9c950ywan                            duration_timecode))
2617233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return false;
2618233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2619233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (timestamp_ns > last_timestamp_)
2620233d2500723e5594f3e7c70896ffeeef32b9c950ywan    last_timestamp_ = timestamp_ns;
2621233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2622233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return true;
2623233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
2624233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2625233d2500723e5594f3e7c70896ffeeef32b9c950ywanbool Segment::AddGenericFrame(const Frame* frame) {
2626233d2500723e5594f3e7c70896ffeeef32b9c950ywan  last_block_duration_ = frame->duration();
2627233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (!tracks_.TrackIsAudio(frame->track_number()) &&
2628233d2500723e5594f3e7c70896ffeeef32b9c950ywan      !tracks_.TrackIsVideo(frame->track_number()) &&
2629233d2500723e5594f3e7c70896ffeeef32b9c950ywan      frame->duration() > 0) {
2630233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return AddMetadata(frame->frame(),
2631233d2500723e5594f3e7c70896ffeeef32b9c950ywan                       frame->length(),
2632233d2500723e5594f3e7c70896ffeeef32b9c950ywan                       frame->track_number(),
2633233d2500723e5594f3e7c70896ffeeef32b9c950ywan                       frame->timestamp(),
2634233d2500723e5594f3e7c70896ffeeef32b9c950ywan                       frame->duration());
2635233d2500723e5594f3e7c70896ffeeef32b9c950ywan  } else if (frame->additional() && frame->additional_length() > 0) {
2636233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return AddFrameWithAdditional(frame->frame(),
2637233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                  frame->length(),
2638233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                  frame->additional(),
2639233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                  frame->additional_length(),
2640233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                  frame->add_id(),
2641233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                  frame->track_number(),
2642233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                  frame->timestamp(),
2643233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                  frame->is_key());
2644233d2500723e5594f3e7c70896ffeeef32b9c950ywan  } else if (frame->discard_padding() > 0) {
2645233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return AddFrameWithDiscardPadding(frame->frame(), frame->length(),
2646233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                      frame->discard_padding(),
2647233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                      frame->track_number(),
2648233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                      frame->timestamp(),
2649233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                      frame->is_key());
2650233d2500723e5594f3e7c70896ffeeef32b9c950ywan  } else {
2651233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return AddFrame(frame->frame(),
2652233d2500723e5594f3e7c70896ffeeef32b9c950ywan                    frame->length(),
2653233d2500723e5594f3e7c70896ffeeef32b9c950ywan                    frame->track_number(),
2654233d2500723e5594f3e7c70896ffeeef32b9c950ywan                    frame->timestamp(),
2655233d2500723e5594f3e7c70896ffeeef32b9c950ywan                    frame->is_key());
2656233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
2657233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
2658233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2659233d2500723e5594f3e7c70896ffeeef32b9c950ywanvoid Segment::OutputCues(bool output_cues) {
2660233d2500723e5594f3e7c70896ffeeef32b9c950ywan  output_cues_ = output_cues;
2661233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
2662233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2663233d2500723e5594f3e7c70896ffeeef32b9c950ywanbool Segment::SetChunking(bool chunking, const char* filename) {
2664233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (chunk_count_ > 0)
2665233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return false;
2666233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2667233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (chunking) {
2668233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (!filename)
2669233d2500723e5594f3e7c70896ffeeef32b9c950ywan      return false;
2670233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2671233d2500723e5594f3e7c70896ffeeef32b9c950ywan    // Check if we are being set to what is already set.
2672233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (chunking_ && !strcmp(filename, chunking_base_name_))
2673233d2500723e5594f3e7c70896ffeeef32b9c950ywan      return true;
2674233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2675233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const size_t name_length = strlen(filename) + 1;
2676233d2500723e5594f3e7c70896ffeeef32b9c950ywan    char* const temp = new (std::nothrow) char[name_length];  // NOLINT
2677233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (!temp)
2678233d2500723e5594f3e7c70896ffeeef32b9c950ywan      return false;
2679233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2680233d2500723e5594f3e7c70896ffeeef32b9c950ywan#ifdef _MSC_VER
2681233d2500723e5594f3e7c70896ffeeef32b9c950ywan    strcpy_s(temp, name_length, filename);
2682233d2500723e5594f3e7c70896ffeeef32b9c950ywan#else
2683233d2500723e5594f3e7c70896ffeeef32b9c950ywan    strcpy(temp, filename);
2684233d2500723e5594f3e7c70896ffeeef32b9c950ywan#endif
2685233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2686233d2500723e5594f3e7c70896ffeeef32b9c950ywan    delete [] chunking_base_name_;
2687233d2500723e5594f3e7c70896ffeeef32b9c950ywan    chunking_base_name_ = temp;
2688233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2689233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (!UpdateChunkName("chk", &chunk_name_))
2690233d2500723e5594f3e7c70896ffeeef32b9c950ywan      return false;
2691233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2692233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (!chunk_writer_cluster_) {
2693233d2500723e5594f3e7c70896ffeeef32b9c950ywan      chunk_writer_cluster_ = new (std::nothrow) MkvWriter();  // NOLINT
2694233d2500723e5594f3e7c70896ffeeef32b9c950ywan      if (!chunk_writer_cluster_)
2695233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return false;
2696233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
2697233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2698233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (!chunk_writer_cues_) {
2699233d2500723e5594f3e7c70896ffeeef32b9c950ywan      chunk_writer_cues_ = new (std::nothrow) MkvWriter();  // NOLINT
2700233d2500723e5594f3e7c70896ffeeef32b9c950ywan      if (!chunk_writer_cues_)
2701233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return false;
2702233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
2703233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2704233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (!chunk_writer_header_) {
2705233d2500723e5594f3e7c70896ffeeef32b9c950ywan      chunk_writer_header_ = new (std::nothrow) MkvWriter();  // NOLINT
2706233d2500723e5594f3e7c70896ffeeef32b9c950ywan      if (!chunk_writer_header_)
2707233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return false;
2708233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
2709233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2710233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (!chunk_writer_cluster_->Open(chunk_name_))
2711233d2500723e5594f3e7c70896ffeeef32b9c950ywan      return false;
2712233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2713233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const size_t header_length = strlen(filename) + strlen(".hdr") + 1;
2714233d2500723e5594f3e7c70896ffeeef32b9c950ywan    char* const header = new (std::nothrow) char[header_length];  // NOLINT
2715233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (!header)
2716233d2500723e5594f3e7c70896ffeeef32b9c950ywan      return false;
2717233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2718233d2500723e5594f3e7c70896ffeeef32b9c950ywan#ifdef _MSC_VER
2719233d2500723e5594f3e7c70896ffeeef32b9c950ywan    strcpy_s(header, header_length - strlen(".hdr"), chunking_base_name_);
2720233d2500723e5594f3e7c70896ffeeef32b9c950ywan    strcat_s(header, header_length, ".hdr");
2721233d2500723e5594f3e7c70896ffeeef32b9c950ywan#else
2722233d2500723e5594f3e7c70896ffeeef32b9c950ywan    strcpy(header, chunking_base_name_);
2723233d2500723e5594f3e7c70896ffeeef32b9c950ywan    strcat(header, ".hdr");
2724233d2500723e5594f3e7c70896ffeeef32b9c950ywan#endif
2725233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (!chunk_writer_header_->Open(header)) {
2726233d2500723e5594f3e7c70896ffeeef32b9c950ywan      delete [] header;
2727233d2500723e5594f3e7c70896ffeeef32b9c950ywan      return false;
2728233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
2729233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2730233d2500723e5594f3e7c70896ffeeef32b9c950ywan    writer_cluster_ = chunk_writer_cluster_;
2731233d2500723e5594f3e7c70896ffeeef32b9c950ywan    writer_cues_ = chunk_writer_cues_;
2732233d2500723e5594f3e7c70896ffeeef32b9c950ywan    writer_header_ = chunk_writer_header_;
2733233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2734233d2500723e5594f3e7c70896ffeeef32b9c950ywan    delete [] header;
2735233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
2736233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2737233d2500723e5594f3e7c70896ffeeef32b9c950ywan  chunking_ = chunking;
2738233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2739233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return true;
2740233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
2741233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2742233d2500723e5594f3e7c70896ffeeef32b9c950ywanbool Segment::CuesTrack(uint64 track_number) {
2743233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const Track* const track = GetTrackByNumber(track_number);
2744233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (!track)
2745233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return false;
2746233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2747233d2500723e5594f3e7c70896ffeeef32b9c950ywan  cues_track_ = track_number;
2748233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return true;
2749233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
2750233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2751233d2500723e5594f3e7c70896ffeeef32b9c950ywanvoid Segment::ForceNewClusterOnNextFrame() {
2752233d2500723e5594f3e7c70896ffeeef32b9c950ywan  force_new_cluster_ = true;
2753233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
2754233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2755233d2500723e5594f3e7c70896ffeeef32b9c950ywanTrack* Segment::GetTrackByNumber(uint64 track_number) const {
2756233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return tracks_.GetTrackByNumber(track_number);
2757233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
2758233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2759233d2500723e5594f3e7c70896ffeeef32b9c950ywanbool Segment::WriteSegmentHeader() {
2760233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // TODO(fgalligan): Support more than one segment.
2761233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (!WriteEbmlHeader(writer_header_))
2762233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return false;
2763233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2764233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // Write "unknown" (-1) as segment size value. If mode is kFile, Segment
2765233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // will write over duration when the file is finalized.
2766233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (WriteID(writer_header_, kMkvSegment))
2767233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return false;
2768233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2769233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // Save for later.
2770233d2500723e5594f3e7c70896ffeeef32b9c950ywan  size_position_ = writer_header_->Position();
2771233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2772233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // Write "unknown" (EBML coded -1) as segment size value. We need to write 8
2773233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // bytes because if we are going to overwrite the segment size later we do
2774233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // not know how big our segment will be.
2775233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (SerializeInt(writer_header_, kEbmlUnknownValue, 8))
2776233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return false;
2777233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2778233d2500723e5594f3e7c70896ffeeef32b9c950ywan  payload_pos_ =  writer_header_->Position();
2779233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2780233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (mode_ == kFile && writer_header_->Seekable()) {
2781233d2500723e5594f3e7c70896ffeeef32b9c950ywan    // Set the duration > 0.0 so SegmentInfo will write out the duration. When
2782233d2500723e5594f3e7c70896ffeeef32b9c950ywan    // the muxer is done writing we will set the correct duration and have
2783233d2500723e5594f3e7c70896ffeeef32b9c950ywan    // SegmentInfo upadte it.
2784233d2500723e5594f3e7c70896ffeeef32b9c950ywan    segment_info_.set_duration(1.0);
2785233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2786233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (!seek_head_.Write(writer_header_))
2787233d2500723e5594f3e7c70896ffeeef32b9c950ywan      return false;
2788233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
2789233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2790233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (!seek_head_.AddSeekEntry(kMkvInfo, MaxOffset()))
2791233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return false;
2792233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (!segment_info_.Write(writer_header_))
2793233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return false;
2794233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2795233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (!seek_head_.AddSeekEntry(kMkvTracks, MaxOffset()))
2796233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return false;
2797233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (!tracks_.Write(writer_header_))
2798233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return false;
2799233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2800233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (chapters_.Count() > 0) {
2801233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (!seek_head_.AddSeekEntry(kMkvChapters, MaxOffset()))
2802233d2500723e5594f3e7c70896ffeeef32b9c950ywan      return false;
2803233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (!chapters_.Write(writer_header_))
2804233d2500723e5594f3e7c70896ffeeef32b9c950ywan      return false;
2805233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
2806233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2807233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (chunking_ && (mode_ == kLive || !writer_header_->Seekable())) {
2808233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (!chunk_writer_header_)
2809233d2500723e5594f3e7c70896ffeeef32b9c950ywan      return false;
2810233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2811233d2500723e5594f3e7c70896ffeeef32b9c950ywan    chunk_writer_header_->Close();
2812233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
2813233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2814233d2500723e5594f3e7c70896ffeeef32b9c950ywan  header_written_ = true;
2815233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2816233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return true;
2817233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
2818233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2819233d2500723e5594f3e7c70896ffeeef32b9c950ywan// Here we are testing whether to create a new cluster, given a frame
2820233d2500723e5594f3e7c70896ffeeef32b9c950ywan// having time frame_timestamp_ns.
2821233d2500723e5594f3e7c70896ffeeef32b9c950ywan//
2822233d2500723e5594f3e7c70896ffeeef32b9c950ywanint Segment::TestFrame(uint64 track_number,
2823233d2500723e5594f3e7c70896ffeeef32b9c950ywan                       uint64 frame_timestamp_ns,
2824233d2500723e5594f3e7c70896ffeeef32b9c950ywan                       bool is_key) const {
2825233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (force_new_cluster_)
2826233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return 1;
2827233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2828233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // If no clusters have been created yet, then create a new cluster
2829233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // and write this frame immediately, in the new cluster.  This path
2830233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // should only be followed once, the first time we attempt to write
2831233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // a frame.
2832233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2833233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (cluster_list_size_ <= 0)
2834233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return 1;
2835233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2836233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // There exists at least one cluster. We must compare the frame to
2837233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // the last cluster, in order to determine whether the frame is
2838233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // written to the existing cluster, or that a new cluster should be
2839233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // created.
2840233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2841233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const uint64 timecode_scale = segment_info_.timecode_scale();
2842233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const uint64 frame_timecode = frame_timestamp_ns / timecode_scale;
2843233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2844233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const Cluster* const last_cluster = cluster_list_[cluster_list_size_ - 1];
2845233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const uint64 last_cluster_timecode = last_cluster->timecode();
2846233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2847233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // For completeness we test for the case when the frame's timecode
2848233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // is less than the cluster's timecode.  Although in principle that
2849233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // is allowed, this muxer doesn't actually write clusters like that,
2850233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // so this indicates a bug somewhere in our algorithm.
2851233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2852233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (frame_timecode < last_cluster_timecode)  // should never happen
2853233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return -1;  // error
2854233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2855233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // If the frame has a timestamp significantly larger than the last
2856233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // cluster (in Matroska, cluster-relative timestamps are serialized
2857233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // using a 16-bit signed integer), then we cannot write this frame
2858233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // to that cluster, and so we must create a new cluster.
2859233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2860233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const int64 delta_timecode = frame_timecode - last_cluster_timecode;
2861233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2862233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (delta_timecode > kMaxBlockTimecode)
2863233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return 2;
2864233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2865233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // We decide to create a new cluster when we have a video keyframe.
2866233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // This will flush queued (audio) frames, and write the keyframe
2867233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // immediately, in the newly-created cluster.
2868233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2869233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (is_key && tracks_.TrackIsVideo(track_number))
2870233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return 1;
2871233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2872233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // Create a new cluster if we have accumulated too many frames
2873233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // already, where "too many" is defined as "the total time of frames
2874233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // in the cluster exceeds a threshold".
2875233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2876233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const uint64 delta_ns = delta_timecode * timecode_scale;
2877233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2878233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (max_cluster_duration_ > 0 && delta_ns >= max_cluster_duration_)
2879233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return 1;
2880233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2881233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // This is similar to the case above, with the difference that a new
2882233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // cluster is created when the size of the current cluster exceeds a
2883233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // threshold.
2884233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2885233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const uint64 cluster_size = last_cluster->payload_size();
2886233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2887233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (max_cluster_size_ > 0 && cluster_size >= max_cluster_size_)
2888233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return 1;
2889233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2890233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // There's no need to create a new cluster, so emit this frame now.
2891233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2892233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return 0;
2893233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
2894233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2895233d2500723e5594f3e7c70896ffeeef32b9c950ywanbool Segment::MakeNewCluster(uint64 frame_timestamp_ns) {
2896233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const int32 new_size = cluster_list_size_ + 1;
2897233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2898233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (new_size > cluster_list_capacity_) {
2899233d2500723e5594f3e7c70896ffeeef32b9c950ywan    // Add more clusters.
2900233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const int32 new_capacity =
2901233d2500723e5594f3e7c70896ffeeef32b9c950ywan        (cluster_list_capacity_ <= 0) ? 1 : cluster_list_capacity_ * 2;
2902233d2500723e5594f3e7c70896ffeeef32b9c950ywan    Cluster** const clusters =
2903233d2500723e5594f3e7c70896ffeeef32b9c950ywan        new (std::nothrow) Cluster*[new_capacity];  // NOLINT
2904233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (!clusters)
2905233d2500723e5594f3e7c70896ffeeef32b9c950ywan      return false;
2906233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2907233d2500723e5594f3e7c70896ffeeef32b9c950ywan    for (int32 i = 0; i < cluster_list_size_; ++i) {
2908233d2500723e5594f3e7c70896ffeeef32b9c950ywan      clusters[i] = cluster_list_[i];
2909233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
2910233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2911233d2500723e5594f3e7c70896ffeeef32b9c950ywan    delete [] cluster_list_;
2912233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2913233d2500723e5594f3e7c70896ffeeef32b9c950ywan    cluster_list_ = clusters;
2914233d2500723e5594f3e7c70896ffeeef32b9c950ywan    cluster_list_capacity_ = new_capacity;
2915233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
2916233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2917233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (!WriteFramesLessThan(frame_timestamp_ns))
2918233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return false;
2919233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2920233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (mode_ == kFile) {
2921233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (cluster_list_size_ > 0) {
2922233d2500723e5594f3e7c70896ffeeef32b9c950ywan      // Update old cluster's size
2923233d2500723e5594f3e7c70896ffeeef32b9c950ywan      Cluster* const old_cluster = cluster_list_[cluster_list_size_ - 1];
2924233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2925233d2500723e5594f3e7c70896ffeeef32b9c950ywan      if (!old_cluster || !old_cluster->Finalize())
2926233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return false;
2927233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
2928233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2929233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (output_cues_)
2930233d2500723e5594f3e7c70896ffeeef32b9c950ywan      new_cuepoint_ = true;
2931233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
2932233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2933233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (chunking_ && cluster_list_size_ > 0) {
2934233d2500723e5594f3e7c70896ffeeef32b9c950ywan    chunk_writer_cluster_->Close();
2935233d2500723e5594f3e7c70896ffeeef32b9c950ywan    chunk_count_++;
2936233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2937233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (!UpdateChunkName("chk", &chunk_name_))
2938233d2500723e5594f3e7c70896ffeeef32b9c950ywan      return false;
2939233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (!chunk_writer_cluster_->Open(chunk_name_))
2940233d2500723e5594f3e7c70896ffeeef32b9c950ywan      return false;
2941233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
2942233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2943233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const uint64 timecode_scale = segment_info_.timecode_scale();
2944233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const uint64 frame_timecode = frame_timestamp_ns / timecode_scale;
2945233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2946233d2500723e5594f3e7c70896ffeeef32b9c950ywan  uint64 cluster_timecode = frame_timecode;
2947233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2948233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (frames_size_ > 0) {
2949233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const Frame* const f = frames_[0];  // earliest queued frame
2950233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const uint64 ns = f->timestamp();
2951233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const uint64 tc = ns / timecode_scale;
2952233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2953233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (tc < cluster_timecode)
2954233d2500723e5594f3e7c70896ffeeef32b9c950ywan      cluster_timecode = tc;
2955233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
2956233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2957233d2500723e5594f3e7c70896ffeeef32b9c950ywan  Cluster*& cluster = cluster_list_[cluster_list_size_];
2958233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const int64 offset = MaxOffset();
2959233d2500723e5594f3e7c70896ffeeef32b9c950ywan  cluster = new (std::nothrow) Cluster(cluster_timecode, offset);  // NOLINT
2960233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (!cluster)
2961233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return false;
2962233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2963233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (!cluster->Init(writer_cluster_))
2964233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return false;
2965233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2966233d2500723e5594f3e7c70896ffeeef32b9c950ywan  cluster_list_size_ = new_size;
2967233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return true;
2968233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
2969233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2970233d2500723e5594f3e7c70896ffeeef32b9c950ywanbool Segment::DoNewClusterProcessing(uint64 track_number,
2971233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                     uint64 frame_timestamp_ns,
2972233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                     bool is_key) {
2973233d2500723e5594f3e7c70896ffeeef32b9c950ywan  for (;;) {
2974233d2500723e5594f3e7c70896ffeeef32b9c950ywan    // Based on the characteristics of the current frame and current
2975233d2500723e5594f3e7c70896ffeeef32b9c950ywan    // cluster, decide whether to create a new cluster.
2976233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const int result = TestFrame(track_number, frame_timestamp_ns, is_key);
2977233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (result < 0)  // error
2978233d2500723e5594f3e7c70896ffeeef32b9c950ywan      return false;
2979233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2980233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // Always set force_new_cluster_ to false after TestFrame.
2981233d2500723e5594f3e7c70896ffeeef32b9c950ywan  force_new_cluster_ = false;
2982233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2983233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // A non-zero result means create a new cluster.
2984233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (result > 0 && !MakeNewCluster(frame_timestamp_ns))
2985233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return false;
2986233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2987233d2500723e5594f3e7c70896ffeeef32b9c950ywan    // Write queued (audio) frames.
2988233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const int frame_count = WriteFramesAll();
2989233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (frame_count < 0)  // error
2990233d2500723e5594f3e7c70896ffeeef32b9c950ywan      return false;
2991233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2992233d2500723e5594f3e7c70896ffeeef32b9c950ywan    // Write the current frame to the current cluster (if TestFrame
2993233d2500723e5594f3e7c70896ffeeef32b9c950ywan    // returns 0) or to a newly created cluster (TestFrame returns 1).
2994233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (result <= 1)
2995233d2500723e5594f3e7c70896ffeeef32b9c950ywan      return true;
2996233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2997233d2500723e5594f3e7c70896ffeeef32b9c950ywan    // TestFrame returned 2, which means there was a large time
2998233d2500723e5594f3e7c70896ffeeef32b9c950ywan    // difference between the cluster and the frame itself.  Do the
2999233d2500723e5594f3e7c70896ffeeef32b9c950ywan    // test again, comparing the frame to the new cluster.
3000233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
3001233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
3002233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3003233d2500723e5594f3e7c70896ffeeef32b9c950ywanbool Segment::CheckHeaderInfo() {
3004233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (!header_written_) {
3005233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (!WriteSegmentHeader())
3006233d2500723e5594f3e7c70896ffeeef32b9c950ywan      return false;
3007233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3008233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (!seek_head_.AddSeekEntry(kMkvCluster, MaxOffset()))
3009233d2500723e5594f3e7c70896ffeeef32b9c950ywan      return false;
3010233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3011233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (output_cues_ && cues_track_ == 0) {
3012233d2500723e5594f3e7c70896ffeeef32b9c950ywan      // Check for a video track
3013233d2500723e5594f3e7c70896ffeeef32b9c950ywan      for (uint32 i = 0; i < tracks_.track_entries_size(); ++i) {
3014233d2500723e5594f3e7c70896ffeeef32b9c950ywan        const Track* const track = tracks_.GetTrackByIndex(i);
3015233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (!track)
3016233d2500723e5594f3e7c70896ffeeef32b9c950ywan          return false;
3017233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3018233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (tracks_.TrackIsVideo(track->number())) {
3019233d2500723e5594f3e7c70896ffeeef32b9c950ywan          cues_track_ = track->number();
3020233d2500723e5594f3e7c70896ffeeef32b9c950ywan          break;
3021233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
3022233d2500723e5594f3e7c70896ffeeef32b9c950ywan      }
3023233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3024233d2500723e5594f3e7c70896ffeeef32b9c950ywan      // Set first track found
3025233d2500723e5594f3e7c70896ffeeef32b9c950ywan      if (cues_track_ == 0) {
3026233d2500723e5594f3e7c70896ffeeef32b9c950ywan        const Track* const track = tracks_.GetTrackByIndex(0);
3027233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (!track)
3028233d2500723e5594f3e7c70896ffeeef32b9c950ywan          return false;
3029233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3030233d2500723e5594f3e7c70896ffeeef32b9c950ywan        cues_track_ = track->number();
3031233d2500723e5594f3e7c70896ffeeef32b9c950ywan      }
3032233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
3033233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
3034233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return true;
3035233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
3036233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3037233d2500723e5594f3e7c70896ffeeef32b9c950ywanbool Segment::UpdateChunkName(const char* ext, char** name) const {
3038233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (!name || !ext)
3039233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return false;
3040233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3041233d2500723e5594f3e7c70896ffeeef32b9c950ywan  char ext_chk[64];
3042233d2500723e5594f3e7c70896ffeeef32b9c950ywan#ifdef _MSC_VER
3043233d2500723e5594f3e7c70896ffeeef32b9c950ywan  sprintf_s(ext_chk, sizeof(ext_chk), "_%06d.%s", chunk_count_, ext);
3044233d2500723e5594f3e7c70896ffeeef32b9c950ywan#else
3045233d2500723e5594f3e7c70896ffeeef32b9c950ywan  snprintf(ext_chk, sizeof(ext_chk), "_%06d.%s", chunk_count_, ext);
3046233d2500723e5594f3e7c70896ffeeef32b9c950ywan#endif
3047233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3048233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const size_t length = strlen(chunking_base_name_) + strlen(ext_chk) + 1;
3049233d2500723e5594f3e7c70896ffeeef32b9c950ywan  char* const str = new (std::nothrow) char[length];  // NOLINT
3050233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (!str)
3051233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return false;
3052233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3053233d2500723e5594f3e7c70896ffeeef32b9c950ywan#ifdef _MSC_VER
3054233d2500723e5594f3e7c70896ffeeef32b9c950ywan  strcpy_s(str, length-strlen(ext_chk), chunking_base_name_);
3055233d2500723e5594f3e7c70896ffeeef32b9c950ywan  strcat_s(str, length, ext_chk);
3056233d2500723e5594f3e7c70896ffeeef32b9c950ywan#else
3057233d2500723e5594f3e7c70896ffeeef32b9c950ywan  strcpy(str, chunking_base_name_);
3058233d2500723e5594f3e7c70896ffeeef32b9c950ywan  strcat(str, ext_chk);
3059233d2500723e5594f3e7c70896ffeeef32b9c950ywan#endif
3060233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3061233d2500723e5594f3e7c70896ffeeef32b9c950ywan  delete [] *name;
3062233d2500723e5594f3e7c70896ffeeef32b9c950ywan  *name = str;
3063233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3064233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return true;
3065233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
3066233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3067233d2500723e5594f3e7c70896ffeeef32b9c950ywanint64 Segment::MaxOffset() {
3068233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (!writer_header_)
3069233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return -1;
3070233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3071233d2500723e5594f3e7c70896ffeeef32b9c950ywan  int64 offset = writer_header_->Position() - payload_pos_;
3072233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3073233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (chunking_) {
3074233d2500723e5594f3e7c70896ffeeef32b9c950ywan    for (int32 i = 0; i < cluster_list_size_; ++i) {
3075233d2500723e5594f3e7c70896ffeeef32b9c950ywan      Cluster* const cluster = cluster_list_[i];
3076233d2500723e5594f3e7c70896ffeeef32b9c950ywan      offset += cluster->Size();
3077233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
3078233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3079233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (writer_cues_)
3080233d2500723e5594f3e7c70896ffeeef32b9c950ywan      offset += writer_cues_->Position();
3081233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
3082233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3083233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return offset;
3084233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
3085233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3086233d2500723e5594f3e7c70896ffeeef32b9c950ywanbool Segment::QueueFrame(Frame* frame) {
3087233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const int32 new_size = frames_size_ + 1;
3088233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3089233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (new_size > frames_capacity_) {
3090233d2500723e5594f3e7c70896ffeeef32b9c950ywan    // Add more frames.
3091233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const int32 new_capacity = (!frames_capacity_) ? 2 : frames_capacity_ * 2;
3092233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3093233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (new_capacity < 1)
3094233d2500723e5594f3e7c70896ffeeef32b9c950ywan      return false;
3095233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3096233d2500723e5594f3e7c70896ffeeef32b9c950ywan    Frame** const frames = new (std::nothrow) Frame*[new_capacity];  // NOLINT
3097233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (!frames)
3098233d2500723e5594f3e7c70896ffeeef32b9c950ywan      return false;
3099233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3100233d2500723e5594f3e7c70896ffeeef32b9c950ywan    for (int32 i = 0; i < frames_size_; ++i) {
3101233d2500723e5594f3e7c70896ffeeef32b9c950ywan      frames[i] = frames_[i];
3102233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
3103233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3104233d2500723e5594f3e7c70896ffeeef32b9c950ywan    delete [] frames_;
3105233d2500723e5594f3e7c70896ffeeef32b9c950ywan    frames_ = frames;
3106233d2500723e5594f3e7c70896ffeeef32b9c950ywan    frames_capacity_ = new_capacity;
3107233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
3108233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3109233d2500723e5594f3e7c70896ffeeef32b9c950ywan  frames_[frames_size_++] = frame;
3110233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3111233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return true;
3112233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
3113233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3114233d2500723e5594f3e7c70896ffeeef32b9c950ywanint Segment::WriteFramesAll() {
3115233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (frames_ == NULL)
3116233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return 0;
3117233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3118233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (cluster_list_size_ < 1)
3119233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return -1;
3120233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3121233d2500723e5594f3e7c70896ffeeef32b9c950ywan  Cluster* const cluster = cluster_list_[cluster_list_size_-1];
3122233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3123233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (!cluster)
3124233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return -1;
3125233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3126233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const uint64 timecode_scale = segment_info_.timecode_scale();
3127233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3128233d2500723e5594f3e7c70896ffeeef32b9c950ywan  for (int32 i = 0; i < frames_size_; ++i) {
3129233d2500723e5594f3e7c70896ffeeef32b9c950ywan    Frame*& frame = frames_[i];
3130233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const uint64 frame_timestamp = frame->timestamp();  // ns
3131233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const uint64 frame_timecode = frame_timestamp / timecode_scale;
3132233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3133233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (frame->discard_padding() > 0) {
3134233d2500723e5594f3e7c70896ffeeef32b9c950ywan      if (!cluster->AddFrameWithDiscardPadding(frame->frame(),
3135233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                               frame->length(),
3136233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                               frame->discard_padding(),
3137233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                               frame->track_number(),
3138233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                               frame_timecode,
3139233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                               frame->is_key())) {
3140233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return -1;
3141233d2500723e5594f3e7c70896ffeeef32b9c950ywan      }
3142233d2500723e5594f3e7c70896ffeeef32b9c950ywan    } else {
3143233d2500723e5594f3e7c70896ffeeef32b9c950ywan      if (!cluster->AddFrame(frame->frame(),
3144233d2500723e5594f3e7c70896ffeeef32b9c950ywan                             frame->length(),
3145233d2500723e5594f3e7c70896ffeeef32b9c950ywan                             frame->track_number(),
3146233d2500723e5594f3e7c70896ffeeef32b9c950ywan                             frame_timecode,
3147233d2500723e5594f3e7c70896ffeeef32b9c950ywan                             frame->is_key())) {
3148233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return -1;
3149233d2500723e5594f3e7c70896ffeeef32b9c950ywan      }
3150233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
3151233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3152233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (new_cuepoint_ && cues_track_ == frame->track_number()) {
3153233d2500723e5594f3e7c70896ffeeef32b9c950ywan      if (!AddCuePoint(frame_timestamp, cues_track_))
3154233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return -1;
3155233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
3156233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3157233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (frame_timestamp > last_timestamp_)
3158233d2500723e5594f3e7c70896ffeeef32b9c950ywan      last_timestamp_ = frame_timestamp;
3159233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3160233d2500723e5594f3e7c70896ffeeef32b9c950ywan    delete frame;
3161233d2500723e5594f3e7c70896ffeeef32b9c950ywan    frame = NULL;
3162233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
3163233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3164233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const int result = frames_size_;
3165233d2500723e5594f3e7c70896ffeeef32b9c950ywan  frames_size_ = 0;
3166233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3167233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return result;
3168233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
3169233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3170233d2500723e5594f3e7c70896ffeeef32b9c950ywanbool Segment::WriteFramesLessThan(uint64 timestamp) {
3171233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // Check |cluster_list_size_| to see if this is the first cluster. If it is
3172233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // the first cluster the audio frames that are less than the first video
3173233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // timesatmp will be written in a later step.
3174233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (frames_size_ > 0 && cluster_list_size_ > 0) {
3175233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (!frames_)
3176233d2500723e5594f3e7c70896ffeeef32b9c950ywan      return false;
3177233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3178233d2500723e5594f3e7c70896ffeeef32b9c950ywan    Cluster* const cluster = cluster_list_[cluster_list_size_-1];
3179233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (!cluster)
3180233d2500723e5594f3e7c70896ffeeef32b9c950ywan      return false;
3181233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3182233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const uint64 timecode_scale = segment_info_.timecode_scale();
3183233d2500723e5594f3e7c70896ffeeef32b9c950ywan    int32 shift_left = 0;
3184233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3185233d2500723e5594f3e7c70896ffeeef32b9c950ywan    // TODO(fgalligan): Change this to use the durations of frames instead of
3186233d2500723e5594f3e7c70896ffeeef32b9c950ywan    // the next frame's start time if the duration is accurate.
3187233d2500723e5594f3e7c70896ffeeef32b9c950ywan    for (int32 i = 1; i < frames_size_; ++i) {
3188233d2500723e5594f3e7c70896ffeeef32b9c950ywan      const Frame* const frame_curr = frames_[i];
3189233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3190233d2500723e5594f3e7c70896ffeeef32b9c950ywan      if (frame_curr->timestamp() > timestamp)
3191233d2500723e5594f3e7c70896ffeeef32b9c950ywan        break;
3192233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3193233d2500723e5594f3e7c70896ffeeef32b9c950ywan      const Frame* const frame_prev = frames_[i-1];
3194233d2500723e5594f3e7c70896ffeeef32b9c950ywan      const uint64 frame_timestamp = frame_prev->timestamp();
3195233d2500723e5594f3e7c70896ffeeef32b9c950ywan      const uint64 frame_timecode = frame_timestamp / timecode_scale;
3196233d2500723e5594f3e7c70896ffeeef32b9c950ywan      const int64 discard_padding = frame_prev->discard_padding();
3197233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3198233d2500723e5594f3e7c70896ffeeef32b9c950ywan      if (discard_padding > 0) {
3199233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (!cluster->AddFrameWithDiscardPadding(frame_prev->frame(),
3200233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                                 frame_prev->length(),
3201233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                                 discard_padding,
3202233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                                 frame_prev->track_number(),
3203233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                                 frame_timecode,
3204233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                                 frame_prev->is_key())) {
3205233d2500723e5594f3e7c70896ffeeef32b9c950ywan          return false;
3206233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
3207233d2500723e5594f3e7c70896ffeeef32b9c950ywan      } else {
3208233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (!cluster->AddFrame(frame_prev->frame(),
3209233d2500723e5594f3e7c70896ffeeef32b9c950ywan                               frame_prev->length(),
3210233d2500723e5594f3e7c70896ffeeef32b9c950ywan                               frame_prev->track_number(),
3211233d2500723e5594f3e7c70896ffeeef32b9c950ywan                               frame_timecode,
3212233d2500723e5594f3e7c70896ffeeef32b9c950ywan                               frame_prev->is_key())) {
3213233d2500723e5594f3e7c70896ffeeef32b9c950ywan          return false;
3214233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
3215233d2500723e5594f3e7c70896ffeeef32b9c950ywan      }
3216233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3217233d2500723e5594f3e7c70896ffeeef32b9c950ywan      if (new_cuepoint_ && cues_track_ == frame_prev->track_number()) {
3218233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (!AddCuePoint(frame_timestamp, cues_track_))
3219233d2500723e5594f3e7c70896ffeeef32b9c950ywan          return false;
3220233d2500723e5594f3e7c70896ffeeef32b9c950ywan      }
3221233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3222233d2500723e5594f3e7c70896ffeeef32b9c950ywan      ++shift_left;
3223233d2500723e5594f3e7c70896ffeeef32b9c950ywan      if (frame_timestamp > last_timestamp_)
3224233d2500723e5594f3e7c70896ffeeef32b9c950ywan        last_timestamp_ = frame_timestamp;
3225233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3226233d2500723e5594f3e7c70896ffeeef32b9c950ywan      delete frame_prev;
3227233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
3228233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3229233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (shift_left > 0) {
3230233d2500723e5594f3e7c70896ffeeef32b9c950ywan      if (shift_left >= frames_size_)
3231233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return false;
3232233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3233233d2500723e5594f3e7c70896ffeeef32b9c950ywan      const int32 new_frames_size = frames_size_ - shift_left;
3234233d2500723e5594f3e7c70896ffeeef32b9c950ywan      for (int32 i = 0; i < new_frames_size; ++i) {
3235233d2500723e5594f3e7c70896ffeeef32b9c950ywan        frames_[i] = frames_[i+shift_left];
3236233d2500723e5594f3e7c70896ffeeef32b9c950ywan      }
3237233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3238233d2500723e5594f3e7c70896ffeeef32b9c950ywan      frames_size_ = new_frames_size;
3239233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
3240233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
3241233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3242233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return true;
3243233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
3244233d2500723e5594f3e7c70896ffeeef32b9c950ywan
3245233d2500723e5594f3e7c70896ffeeef32b9c950ywan}  // namespace mkvmuxer
3246