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