Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(18)

Side by Side Diff: source/libvpx/third_party/libwebm/mkvmuxer.cpp

Issue 1302353004: libvpx: Pull from upstream (Closed) Base URL: https://chromium.googlesource.com/chromium/deps/libvpx.git@master
Patch Set: Created 5 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2012 The WebM project authors. All Rights Reserved. 1 // Copyright (c) 2012 The WebM project authors. All Rights Reserved.
2 // 2 //
3 // Use of this source code is governed by a BSD-style license 3 // Use of this source code is governed by a BSD-style license
4 // that can be found in the LICENSE file in the root of the source 4 // that can be found in the LICENSE file in the root of the source
5 // tree. An additional intellectual property rights grant can be found 5 // tree. An additional intellectual property rights grant can be found
6 // in the file PATENTS. All contributing project authors may 6 // in the file PATENTS. All contributing project authors may
7 // be found in the AUTHORS file in the root of the source tree. 7 // be found in the AUTHORS file in the root of the source tree.
8 8
9 #include "mkvmuxer.hpp" 9 #include "mkvmuxer.hpp"
10 10
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
58 } // namespace 58 } // namespace
59 59
60 /////////////////////////////////////////////////////////////// 60 ///////////////////////////////////////////////////////////////
61 // 61 //
62 // IMkvWriter Class 62 // IMkvWriter Class
63 63
64 IMkvWriter::IMkvWriter() {} 64 IMkvWriter::IMkvWriter() {}
65 65
66 IMkvWriter::~IMkvWriter() {} 66 IMkvWriter::~IMkvWriter() {}
67 67
68 bool WriteEbmlHeader(IMkvWriter* writer) { 68 bool WriteEbmlHeader(IMkvWriter* writer, uint64 doc_type_version) {
69 // Level 0 69 // Level 0
70 uint64 size = EbmlElementSize(kMkvEBMLVersion, 1ULL); 70 uint64 size = EbmlElementSize(kMkvEBMLVersion, 1ULL);
71 size += EbmlElementSize(kMkvEBMLReadVersion, 1ULL); 71 size += EbmlElementSize(kMkvEBMLReadVersion, 1ULL);
72 size += EbmlElementSize(kMkvEBMLMaxIDLength, 4ULL); 72 size += EbmlElementSize(kMkvEBMLMaxIDLength, 4ULL);
73 size += EbmlElementSize(kMkvEBMLMaxSizeLength, 8ULL); 73 size += EbmlElementSize(kMkvEBMLMaxSizeLength, 8ULL);
74 size += EbmlElementSize(kMkvDocType, "webm"); 74 size += EbmlElementSize(kMkvDocType, "webm");
75 size += EbmlElementSize(kMkvDocTypeVersion, 2ULL); 75 size += EbmlElementSize(kMkvDocTypeVersion, doc_type_version);
76 size += EbmlElementSize(kMkvDocTypeReadVersion, 2ULL); 76 size += EbmlElementSize(kMkvDocTypeReadVersion, 2ULL);
77 77
78 if (!WriteEbmlMasterElement(writer, kMkvEBML, size)) 78 if (!WriteEbmlMasterElement(writer, kMkvEBML, size))
79 return false; 79 return false;
80 if (!WriteEbmlElement(writer, kMkvEBMLVersion, 1ULL)) 80 if (!WriteEbmlElement(writer, kMkvEBMLVersion, 1ULL))
81 return false; 81 return false;
82 if (!WriteEbmlElement(writer, kMkvEBMLReadVersion, 1ULL)) 82 if (!WriteEbmlElement(writer, kMkvEBMLReadVersion, 1ULL))
83 return false; 83 return false;
84 if (!WriteEbmlElement(writer, kMkvEBMLMaxIDLength, 4ULL)) 84 if (!WriteEbmlElement(writer, kMkvEBMLMaxIDLength, 4ULL))
85 return false; 85 return false;
86 if (!WriteEbmlElement(writer, kMkvEBMLMaxSizeLength, 8ULL)) 86 if (!WriteEbmlElement(writer, kMkvEBMLMaxSizeLength, 8ULL))
87 return false; 87 return false;
88 if (!WriteEbmlElement(writer, kMkvDocType, "webm")) 88 if (!WriteEbmlElement(writer, kMkvDocType, "webm"))
89 return false; 89 return false;
90 if (!WriteEbmlElement(writer, kMkvDocTypeVersion, 2ULL)) 90 if (!WriteEbmlElement(writer, kMkvDocTypeVersion, doc_type_version))
91 return false; 91 return false;
92 if (!WriteEbmlElement(writer, kMkvDocTypeReadVersion, 2ULL)) 92 if (!WriteEbmlElement(writer, kMkvDocTypeReadVersion, 2ULL))
93 return false; 93 return false;
94 94
95 return true; 95 return true;
96 } 96 }
97 97
98 bool WriteEbmlHeader(IMkvWriter* writer) {
99 return WriteEbmlHeader(writer, mkvmuxer::Segment::kDefaultDocTypeVersion);
100 }
101
98 bool ChunkedCopy(mkvparser::IMkvReader* source, mkvmuxer::IMkvWriter* dst, 102 bool ChunkedCopy(mkvparser::IMkvReader* source, mkvmuxer::IMkvWriter* dst,
99 mkvmuxer::int64 start, int64 size) { 103 mkvmuxer::int64 start, int64 size) {
100 // TODO(vigneshv): Check if this is a reasonable value. 104 // TODO(vigneshv): Check if this is a reasonable value.
101 const uint32 kBufSize = 2048; 105 const uint32 kBufSize = 2048;
102 uint8* buf = new uint8[kBufSize]; 106 uint8* buf = new uint8[kBufSize];
103 int64 offset = start; 107 int64 offset = start;
104 while (size > 0) { 108 while (size > 0) {
105 const int64 read_len = (size > kBufSize) ? kBufSize : size; 109 const int64 read_len = (size > kBufSize) ? kBufSize : size;
106 if (source->Read(offset, static_cast<long>(read_len), buf)) 110 if (source->Read(offset, static_cast<long>(read_len), buf))
107 return false; 111 return false;
(...skipping 12 matching lines...) Expand all
120 Frame::Frame() 124 Frame::Frame()
121 : add_id_(0), 125 : add_id_(0),
122 additional_(NULL), 126 additional_(NULL),
123 additional_length_(0), 127 additional_length_(0),
124 duration_(0), 128 duration_(0),
125 frame_(NULL), 129 frame_(NULL),
126 is_key_(false), 130 is_key_(false),
127 length_(0), 131 length_(0),
128 track_number_(0), 132 track_number_(0),
129 timestamp_(0), 133 timestamp_(0),
130 discard_padding_(0) {} 134 discard_padding_(0),
135 reference_block_timestamp_(0),
136 reference_block_timestamp_set_(false) {}
131 137
132 Frame::~Frame() { 138 Frame::~Frame() {
133 delete[] frame_; 139 delete[] frame_;
134 delete[] additional_; 140 delete[] additional_;
135 } 141 }
136 142
143 bool Frame::CopyFrom(const Frame& frame) {
144 delete[] frame_;
145 frame_ = NULL;
146 length_ = 0;
147 if (frame.length() > 0 && frame.frame() != NULL &&
148 !Init(frame.frame(), frame.length())) {
149 return false;
150 }
151 add_id_ = 0;
152 delete[] additional_;
153 additional_ = NULL;
154 additional_length_ = 0;
155 if (frame.additional_length() > 0 && frame.additional() != NULL &&
156 !AddAdditionalData(frame.additional(), frame.additional_length(),
157 frame.add_id())) {
158 return false;
159 }
160 duration_ = frame.duration();
161 is_key_ = frame.is_key();
162 track_number_ = frame.track_number();
163 timestamp_ = frame.timestamp();
164 discard_padding_ = frame.discard_padding();
165 return true;
166 }
167
137 bool Frame::Init(const uint8* frame, uint64 length) { 168 bool Frame::Init(const uint8* frame, uint64 length) {
138 uint8* const data = 169 uint8* const data =
139 new (std::nothrow) uint8[static_cast<size_t>(length)]; // NOLINT 170 new (std::nothrow) uint8[static_cast<size_t>(length)]; // NOLINT
140 if (!data) 171 if (!data)
141 return false; 172 return false;
142 173
143 delete[] frame_; 174 delete[] frame_;
144 frame_ = data; 175 frame_ = data;
145 length_ = length; 176 length_ = length;
146 177
(...skipping 10 matching lines...) Expand all
157 188
158 delete[] additional_; 189 delete[] additional_;
159 additional_ = data; 190 additional_ = data;
160 additional_length_ = length; 191 additional_length_ = length;
161 add_id_ = add_id; 192 add_id_ = add_id;
162 193
163 memcpy(additional_, additional, static_cast<size_t>(additional_length_)); 194 memcpy(additional_, additional, static_cast<size_t>(additional_length_));
164 return true; 195 return true;
165 } 196 }
166 197
198 bool Frame::IsValid() const {
199 if (length_ == 0 || !frame_) {
200 return false;
201 }
202 if ((additional_length_ != 0 && !additional_) ||
203 (additional_ != NULL && additional_length_ == 0)) {
204 return false;
205 }
206 if (track_number_ == 0 || track_number_ > kMaxTrackNumber) {
207 return false;
208 }
209 if (!CanBeSimpleBlock() && !is_key_ && !reference_block_timestamp_set_) {
210 return false;
211 }
212 return true;
213 }
214
215 bool Frame::CanBeSimpleBlock() const {
216 return additional_ == NULL && discard_padding_ == 0 && duration_ == 0;
217 }
218
219 void Frame::set_reference_block_timestamp(int64 reference_block_timestamp) {
220 reference_block_timestamp_ = reference_block_timestamp;
221 reference_block_timestamp_set_ = true;
222 }
223
167 /////////////////////////////////////////////////////////////// 224 ///////////////////////////////////////////////////////////////
168 // 225 //
169 // CuePoint Class 226 // CuePoint Class
170 227
171 CuePoint::CuePoint() 228 CuePoint::CuePoint()
172 : time_(0), 229 : time_(0),
173 track_(0), 230 track_(0),
174 cluster_pos_(0), 231 cluster_pos_(0),
175 block_number_(1), 232 block_number_(1),
176 output_block_number_(true) {} 233 output_block_number_(true) {}
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
264 321
265 if ((cue_entries_size_ + 1) > cue_entries_capacity_) { 322 if ((cue_entries_size_ + 1) > cue_entries_capacity_) {
266 // Add more CuePoints. 323 // Add more CuePoints.
267 const int32 new_capacity = 324 const int32 new_capacity =
268 (!cue_entries_capacity_) ? 2 : cue_entries_capacity_ * 2; 325 (!cue_entries_capacity_) ? 2 : cue_entries_capacity_ * 2;
269 326
270 if (new_capacity < 1) 327 if (new_capacity < 1)
271 return false; 328 return false;
272 329
273 CuePoint** const cues = 330 CuePoint** const cues =
274 new (std::nothrow) CuePoint* [new_capacity]; // NOLINT 331 new (std::nothrow) CuePoint*[new_capacity]; // NOLINT
275 if (!cues) 332 if (!cues)
276 return false; 333 return false;
277 334
278 for (int32 i = 0; i < cue_entries_size_; ++i) { 335 for (int32 i = 0; i < cue_entries_size_; ++i) {
279 cues[i] = cue_entries_[i]; 336 cues[i] = cue_entries_[i];
280 } 337 }
281 338
282 delete[] cue_entries_; 339 delete[] cue_entries_;
283 340
284 cue_entries_ = cues; 341 cue_entries_ = cues;
(...skipping 240 matching lines...) Expand 10 before | Expand all | Expand 10 after
525 delete encoding; 582 delete encoding;
526 } 583 }
527 delete[] content_encoding_entries_; 584 delete[] content_encoding_entries_;
528 } 585 }
529 } 586 }
530 587
531 bool Track::AddContentEncoding() { 588 bool Track::AddContentEncoding() {
532 const uint32 count = content_encoding_entries_size_ + 1; 589 const uint32 count = content_encoding_entries_size_ + 1;
533 590
534 ContentEncoding** const content_encoding_entries = 591 ContentEncoding** const content_encoding_entries =
535 new (std::nothrow) ContentEncoding* [count]; // NOLINT 592 new (std::nothrow) ContentEncoding*[count]; // NOLINT
536 if (!content_encoding_entries) 593 if (!content_encoding_entries)
537 return false; 594 return false;
538 595
539 ContentEncoding* const content_encoding = 596 ContentEncoding* const content_encoding =
540 new (std::nothrow) ContentEncoding(); // NOLINT 597 new (std::nothrow) ContentEncoding(); // NOLINT
541 if (!content_encoding) { 598 if (!content_encoding) {
542 delete[] content_encoding_entries; 599 delete[] content_encoding_entries;
543 return false; 600 return false;
544 } 601 }
545 602
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
605 uint64 Track::Size() const { 662 uint64 Track::Size() const {
606 uint64 size = PayloadSize(); 663 uint64 size = PayloadSize();
607 size += EbmlMasterElementSize(kMkvTrackEntry, size); 664 size += EbmlMasterElementSize(kMkvTrackEntry, size);
608 return size; 665 return size;
609 } 666 }
610 667
611 bool Track::Write(IMkvWriter* writer) const { 668 bool Track::Write(IMkvWriter* writer) const {
612 if (!writer) 669 if (!writer)
613 return false; 670 return false;
614 671
672 // mandatory elements without a default value.
673 if (!type_ || !codec_id_)
674 return false;
675
615 // |size| may be bigger than what is written out in this function because 676 // |size| may be bigger than what is written out in this function because
616 // derived classes may write out more data in the Track element. 677 // derived classes may write out more data in the Track element.
617 const uint64 payload_size = PayloadSize(); 678 const uint64 payload_size = PayloadSize();
618 679
619 if (!WriteEbmlMasterElement(writer, kMkvTrackEntry, payload_size)) 680 if (!WriteEbmlMasterElement(writer, kMkvTrackEntry, payload_size))
620 return false; 681 return false;
621 682
622 // |type_| has to be specified before the Track can be written.
623 if (!type_)
624 return false;
625
626 uint64 size = EbmlElementSize(kMkvTrackNumber, number_); 683 uint64 size = EbmlElementSize(kMkvTrackNumber, number_);
627 size += EbmlElementSize(kMkvTrackUID, uid_); 684 size += EbmlElementSize(kMkvTrackUID, uid_);
628 size += EbmlElementSize(kMkvTrackType, type_); 685 size += EbmlElementSize(kMkvTrackType, type_);
629 if (codec_id_) 686 if (codec_id_)
630 size += EbmlElementSize(kMkvCodecID, codec_id_); 687 size += EbmlElementSize(kMkvCodecID, codec_id_);
631 if (codec_private_) 688 if (codec_private_)
632 size += EbmlElementSize(kMkvCodecPrivate, codec_private_, 689 size += EbmlElementSize(kMkvCodecPrivate, codec_private_,
633 codec_private_length_); 690 codec_private_length_);
634 if (language_) 691 if (language_)
635 size += EbmlElementSize(kMkvLanguage, language_); 692 size += EbmlElementSize(kMkvLanguage, language_);
(...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after
786 } 843 }
787 844
788 /////////////////////////////////////////////////////////////// 845 ///////////////////////////////////////////////////////////////
789 // 846 //
790 // VideoTrack Class 847 // VideoTrack Class
791 848
792 VideoTrack::VideoTrack(unsigned int* seed) 849 VideoTrack::VideoTrack(unsigned int* seed)
793 : Track(seed), 850 : Track(seed),
794 display_height_(0), 851 display_height_(0),
795 display_width_(0), 852 display_width_(0),
853 crop_left_(0),
854 crop_right_(0),
855 crop_top_(0),
856 crop_bottom_(0),
796 frame_rate_(0.0), 857 frame_rate_(0.0),
797 height_(0), 858 height_(0),
798 stereo_mode_(0), 859 stereo_mode_(0),
799 alpha_mode_(0), 860 alpha_mode_(0),
800 width_(0) {} 861 width_(0) {}
801 862
802 VideoTrack::~VideoTrack() {} 863 VideoTrack::~VideoTrack() {}
803 864
804 bool VideoTrack::SetStereoMode(uint64 stereo_mode) { 865 bool VideoTrack::SetStereoMode(uint64 stereo_mode) {
805 if (stereo_mode != kMono && stereo_mode != kSideBySideLeftIsFirst && 866 if (stereo_mode != kMono && stereo_mode != kSideBySideLeftIsFirst &&
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
839 return false; 900 return false;
840 901
841 const int64 payload_position = writer->Position(); 902 const int64 payload_position = writer->Position();
842 if (payload_position < 0) 903 if (payload_position < 0)
843 return false; 904 return false;
844 905
845 if (!WriteEbmlElement(writer, kMkvPixelWidth, width_)) 906 if (!WriteEbmlElement(writer, kMkvPixelWidth, width_))
846 return false; 907 return false;
847 if (!WriteEbmlElement(writer, kMkvPixelHeight, height_)) 908 if (!WriteEbmlElement(writer, kMkvPixelHeight, height_))
848 return false; 909 return false;
849 if (display_width_ > 0) 910 if (display_width_ > 0) {
850 if (!WriteEbmlElement(writer, kMkvDisplayWidth, display_width_)) 911 if (!WriteEbmlElement(writer, kMkvDisplayWidth, display_width_))
851 return false; 912 return false;
852 if (display_height_ > 0) 913 }
914 if (display_height_ > 0) {
853 if (!WriteEbmlElement(writer, kMkvDisplayHeight, display_height_)) 915 if (!WriteEbmlElement(writer, kMkvDisplayHeight, display_height_))
854 return false; 916 return false;
855 if (stereo_mode_ > kMono) 917 }
918 if (crop_left_ > 0) {
919 if (!WriteEbmlElement(writer, kMkvPixelCropLeft, crop_left_))
920 return false;
921 }
922 if (crop_right_ > 0) {
923 if (!WriteEbmlElement(writer, kMkvPixelCropRight, crop_right_))
924 return false;
925 }
926 if (crop_top_ > 0) {
927 if (!WriteEbmlElement(writer, kMkvPixelCropTop, crop_top_))
928 return false;
929 }
930 if (crop_bottom_ > 0) {
931 if (!WriteEbmlElement(writer, kMkvPixelCropBottom, crop_bottom_))
932 return false;
933 }
934 if (stereo_mode_ > kMono) {
856 if (!WriteEbmlElement(writer, kMkvStereoMode, stereo_mode_)) 935 if (!WriteEbmlElement(writer, kMkvStereoMode, stereo_mode_))
857 return false; 936 return false;
858 if (alpha_mode_ > kNoAlpha) 937 }
938 if (alpha_mode_ > kNoAlpha) {
859 if (!WriteEbmlElement(writer, kMkvAlphaMode, alpha_mode_)) 939 if (!WriteEbmlElement(writer, kMkvAlphaMode, alpha_mode_))
860 return false; 940 return false;
861 if (frame_rate_ > 0.0) 941 }
942 if (frame_rate_ > 0.0) {
862 if (!WriteEbmlElement(writer, kMkvFrameRate, 943 if (!WriteEbmlElement(writer, kMkvFrameRate,
863 static_cast<float>(frame_rate_))) 944 static_cast<float>(frame_rate_))) {
864 return false; 945 return false;
946 }
947 }
865 948
866 const int64 stop_position = writer->Position(); 949 const int64 stop_position = writer->Position();
867 if (stop_position < 0 || 950 if (stop_position < 0 ||
868 stop_position - payload_position != static_cast<int64>(size)) 951 stop_position - payload_position != static_cast<int64>(size)) {
869 return false; 952 return false;
953 }
870 954
871 return true; 955 return true;
872 } 956 }
873 957
874 uint64 VideoTrack::VideoPayloadSize() const { 958 uint64 VideoTrack::VideoPayloadSize() const {
875 uint64 size = EbmlElementSize(kMkvPixelWidth, width_); 959 uint64 size = EbmlElementSize(kMkvPixelWidth, width_);
876 size += EbmlElementSize(kMkvPixelHeight, height_); 960 size += EbmlElementSize(kMkvPixelHeight, height_);
877 if (display_width_ > 0) 961 if (display_width_ > 0)
878 size += EbmlElementSize(kMkvDisplayWidth, display_width_); 962 size += EbmlElementSize(kMkvDisplayWidth, display_width_);
879 if (display_height_ > 0) 963 if (display_height_ > 0)
880 size += EbmlElementSize(kMkvDisplayHeight, display_height_); 964 size += EbmlElementSize(kMkvDisplayHeight, display_height_);
965 if (crop_left_ > 0)
966 size += EbmlElementSize(kMkvPixelCropLeft, crop_left_);
967 if (crop_right_ > 0)
968 size += EbmlElementSize(kMkvPixelCropRight, crop_right_);
969 if (crop_top_ > 0)
970 size += EbmlElementSize(kMkvPixelCropTop, crop_top_);
971 if (crop_bottom_ > 0)
972 size += EbmlElementSize(kMkvPixelCropBottom, crop_bottom_);
881 if (stereo_mode_ > kMono) 973 if (stereo_mode_ > kMono)
882 size += EbmlElementSize(kMkvStereoMode, stereo_mode_); 974 size += EbmlElementSize(kMkvStereoMode, stereo_mode_);
883 if (alpha_mode_ > kNoAlpha) 975 if (alpha_mode_ > kNoAlpha)
884 size += EbmlElementSize(kMkvAlphaMode, alpha_mode_); 976 size += EbmlElementSize(kMkvAlphaMode, alpha_mode_);
885 if (frame_rate_ > 0.0) 977 if (frame_rate_ > 0.0)
886 size += EbmlElementSize(kMkvFrameRate, static_cast<float>(frame_rate_)); 978 size += EbmlElementSize(kMkvFrameRate, static_cast<float>(frame_rate_));
887 979
888 return size; 980 return size;
889 } 981 }
890 982
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
946 } 1038 }
947 1039
948 /////////////////////////////////////////////////////////////// 1040 ///////////////////////////////////////////////////////////////
949 // 1041 //
950 // Tracks Class 1042 // Tracks Class
951 1043
952 const char Tracks::kOpusCodecId[] = "A_OPUS"; 1044 const char Tracks::kOpusCodecId[] = "A_OPUS";
953 const char Tracks::kVorbisCodecId[] = "A_VORBIS"; 1045 const char Tracks::kVorbisCodecId[] = "A_VORBIS";
954 const char Tracks::kVp8CodecId[] = "V_VP8"; 1046 const char Tracks::kVp8CodecId[] = "V_VP8";
955 const char Tracks::kVp9CodecId[] = "V_VP9"; 1047 const char Tracks::kVp9CodecId[] = "V_VP9";
1048 const char Tracks::kVp10CodecId[] = "V_VP10";
956 1049
957 Tracks::Tracks() : track_entries_(NULL), track_entries_size_(0) {} 1050 Tracks::Tracks() : track_entries_(NULL), track_entries_size_(0) {}
958 1051
959 Tracks::~Tracks() { 1052 Tracks::~Tracks() {
960 if (track_entries_) { 1053 if (track_entries_) {
961 for (uint32 i = 0; i < track_entries_size_; ++i) { 1054 for (uint32 i = 0; i < track_entries_size_; ++i) {
962 Track* const track = track_entries_[i]; 1055 Track* const track = track_entries_[i];
963 delete track; 1056 delete track;
964 } 1057 }
965 delete[] track_entries_; 1058 delete[] track_entries_;
(...skipping 17 matching lines...) Expand all
983 if (track_num > 0) { 1076 if (track_num > 0) {
984 // Check to make sure a track does not already have |track_num|. 1077 // Check to make sure a track does not already have |track_num|.
985 for (uint32 i = 0; i < track_entries_size_; ++i) { 1078 for (uint32 i = 0; i < track_entries_size_; ++i) {
986 if (track_entries_[i]->number() == track_num) 1079 if (track_entries_[i]->number() == track_num)
987 return false; 1080 return false;
988 } 1081 }
989 } 1082 }
990 1083
991 const uint32 count = track_entries_size_ + 1; 1084 const uint32 count = track_entries_size_ + 1;
992 1085
993 Track** const track_entries = new (std::nothrow) Track* [count]; // NOLINT 1086 Track** const track_entries = new (std::nothrow) Track*[count]; // NOLINT
994 if (!track_entries) 1087 if (!track_entries)
995 return false; 1088 return false;
996 1089
997 for (uint32 i = 0; i < track_entries_size_; ++i) { 1090 for (uint32 i = 0; i < track_entries_size_; ++i) {
998 track_entries[i] = track_entries_[i]; 1091 track_entries[i] = track_entries_[i];
999 } 1092 }
1000 1093
1001 delete[] track_entries_; 1094 delete[] track_entries_;
1002 1095
1003 // Find the lowest availible track number > 0. 1096 // Find the lowest availible track number > 0.
(...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after
1138 // only to the Chapters class). Doing no initialization here also 1231 // only to the Chapters class). Doing no initialization here also
1139 // means that creating arrays of chapter objects is more efficient, 1232 // means that creating arrays of chapter objects is more efficient,
1140 // because we only initialize each new chapter object as it becomes 1233 // because we only initialize each new chapter object as it becomes
1141 // active on the array. 1234 // active on the array.
1142 } 1235 }
1143 1236
1144 Chapter::~Chapter() {} 1237 Chapter::~Chapter() {}
1145 1238
1146 void Chapter::Init(unsigned int* seed) { 1239 void Chapter::Init(unsigned int* seed) {
1147 id_ = NULL; 1240 id_ = NULL;
1241 start_timecode_ = 0;
1242 end_timecode_ = 0;
1148 displays_ = NULL; 1243 displays_ = NULL;
1149 displays_size_ = 0; 1244 displays_size_ = 0;
1150 displays_count_ = 0; 1245 displays_count_ = 0;
1151 uid_ = MakeUID(seed); 1246 uid_ = MakeUID(seed);
1152 } 1247 }
1153 1248
1154 void Chapter::ShallowCopy(Chapter* dst) const { 1249 void Chapter::ShallowCopy(Chapter* dst) const {
1155 dst->id_ = id_; 1250 dst->id_ = id_;
1156 dst->start_timecode_ = start_timecode_; 1251 dst->start_timecode_ = start_timecode_;
1157 dst->end_timecode_ = end_timecode_; 1252 dst->end_timecode_ = end_timecode_;
(...skipping 255 matching lines...) Expand 10 before | Expand all | Expand 10 after
1413 } 1508 }
1414 1509
1415 const int64 stop = writer->Position(); 1510 const int64 stop = writer->Position();
1416 1511
1417 if (stop >= start && uint64(stop - start) != edition_size) 1512 if (stop >= start && uint64(stop - start) != edition_size)
1418 return 0; 1513 return 0;
1419 1514
1420 return edition_size; 1515 return edition_size;
1421 } 1516 }
1422 1517
1518 // Tag Class
1519
1520 bool Tag::add_simple_tag(const char* tag_name, const char* tag_string) {
1521 if (!ExpandSimpleTagsArray())
1522 return false;
1523
1524 SimpleTag& st = simple_tags_[simple_tags_count_++];
1525 st.Init();
1526
1527 if (!st.set_tag_name(tag_name))
1528 return false;
1529
1530 if (!st.set_tag_string(tag_string))
1531 return false;
1532
1533 return true;
1534 }
1535
1536 Tag::Tag() {
1537 simple_tags_ = NULL;
1538 simple_tags_size_ = 0;
1539 simple_tags_count_ = 0;
1540 }
1541
1542 Tag::~Tag() {}
1543
1544 void Tag::ShallowCopy(Tag* dst) const {
1545 dst->simple_tags_ = simple_tags_;
1546 dst->simple_tags_size_ = simple_tags_size_;
1547 dst->simple_tags_count_ = simple_tags_count_;
1548 }
1549
1550 void Tag::Clear() {
1551 while (simple_tags_count_ > 0) {
1552 SimpleTag& st = simple_tags_[--simple_tags_count_];
1553 st.Clear();
1554 }
1555
1556 delete[] simple_tags_;
1557 simple_tags_ = NULL;
1558
1559 simple_tags_size_ = 0;
1560 }
1561
1562 bool Tag::ExpandSimpleTagsArray() {
1563 if (simple_tags_size_ > simple_tags_count_)
1564 return true; // nothing to do yet
1565
1566 const int size = (simple_tags_size_ == 0) ? 1 : 2 * simple_tags_size_;
1567
1568 SimpleTag* const simple_tags = new (std::nothrow) SimpleTag[size]; // NOLINT
1569 if (simple_tags == NULL)
1570 return false;
1571
1572 for (int idx = 0; idx < simple_tags_count_; ++idx) {
1573 simple_tags[idx] = simple_tags_[idx]; // shallow copy
1574 }
1575
1576 delete[] simple_tags_;
1577
1578 simple_tags_ = simple_tags;
1579 simple_tags_size_ = size;
1580
1581 return true;
1582 }
1583
1584 uint64 Tag::Write(IMkvWriter* writer) const {
1585 uint64 payload_size = 0;
1586
1587 for (int idx = 0; idx < simple_tags_count_; ++idx) {
1588 const SimpleTag& st = simple_tags_[idx];
1589 payload_size += st.Write(NULL);
1590 }
1591
1592 const uint64 tag_size =
1593 EbmlMasterElementSize(kMkvTag, payload_size) + payload_size;
1594
1595 if (writer == NULL)
1596 return tag_size;
1597
1598 const int64 start = writer->Position();
1599
1600 if (!WriteEbmlMasterElement(writer, kMkvTag, payload_size))
1601 return 0;
1602
1603 for (int idx = 0; idx < simple_tags_count_; ++idx) {
1604 const SimpleTag& st = simple_tags_[idx];
1605
1606 if (!st.Write(writer))
1607 return 0;
1608 }
1609
1610 const int64 stop = writer->Position();
1611
1612 if (stop >= start && uint64(stop - start) != tag_size)
1613 return 0;
1614
1615 return tag_size;
1616 }
1617
1618 // Tag::SimpleTag
1619
1620 void Tag::SimpleTag::Init() {
1621 tag_name_ = NULL;
1622 tag_string_ = NULL;
1623 }
1624
1625 void Tag::SimpleTag::Clear() {
1626 StrCpy(NULL, &tag_name_);
1627 StrCpy(NULL, &tag_string_);
1628 }
1629
1630 bool Tag::SimpleTag::set_tag_name(const char* tag_name) {
1631 return StrCpy(tag_name, &tag_name_);
1632 }
1633
1634 bool Tag::SimpleTag::set_tag_string(const char* tag_string) {
1635 return StrCpy(tag_string, &tag_string_);
1636 }
1637
1638 uint64 Tag::SimpleTag::Write(IMkvWriter* writer) const {
1639 uint64 payload_size = EbmlElementSize(kMkvTagName, tag_name_);
1640
1641 payload_size += EbmlElementSize(kMkvTagString, tag_string_);
1642
1643 const uint64 simple_tag_size =
1644 EbmlMasterElementSize(kMkvSimpleTag, payload_size) + payload_size;
1645
1646 if (writer == NULL)
1647 return simple_tag_size;
1648
1649 const int64 start = writer->Position();
1650
1651 if (!WriteEbmlMasterElement(writer, kMkvSimpleTag, payload_size))
1652 return 0;
1653
1654 if (!WriteEbmlElement(writer, kMkvTagName, tag_name_))
1655 return 0;
1656
1657 if (!WriteEbmlElement(writer, kMkvTagString, tag_string_))
1658 return 0;
1659
1660 const int64 stop = writer->Position();
1661
1662 if (stop >= start && uint64(stop - start) != simple_tag_size)
1663 return 0;
1664
1665 return simple_tag_size;
1666 }
1667
1668 // Tags Class
1669
1670 Tags::Tags() : tags_size_(0), tags_count_(0), tags_(NULL) {}
1671
1672 Tags::~Tags() {
1673 while (tags_count_ > 0) {
1674 Tag& tag = tags_[--tags_count_];
1675 tag.Clear();
1676 }
1677
1678 delete[] tags_;
1679 tags_ = NULL;
1680 }
1681
1682 int Tags::Count() const { return tags_count_; }
1683
1684 Tag* Tags::AddTag() {
1685 if (!ExpandTagsArray())
1686 return NULL;
1687
1688 Tag& tag = tags_[tags_count_++];
1689
1690 return &tag;
1691 }
1692
1693 bool Tags::Write(IMkvWriter* writer) const {
1694 if (writer == NULL)
1695 return false;
1696
1697 uint64 payload_size = 0;
1698
1699 for (int idx = 0; idx < tags_count_; ++idx) {
1700 const Tag& tag = tags_[idx];
1701 payload_size += tag.Write(NULL);
1702 }
1703
1704 if (!WriteEbmlMasterElement(writer, kMkvTags, payload_size))
1705 return false;
1706
1707 const int64 start = writer->Position();
1708
1709 for (int idx = 0; idx < tags_count_; ++idx) {
1710 const Tag& tag = tags_[idx];
1711
1712 const uint64 tag_size = tag.Write(writer);
1713 if (tag_size == 0) // error
1714 return 0;
1715 }
1716
1717 const int64 stop = writer->Position();
1718
1719 if (stop >= start && uint64(stop - start) != payload_size)
1720 return false;
1721
1722 return true;
1723 }
1724
1725 bool Tags::ExpandTagsArray() {
1726 if (tags_size_ > tags_count_)
1727 return true; // nothing to do yet
1728
1729 const int size = (tags_size_ == 0) ? 1 : 2 * tags_size_;
1730
1731 Tag* const tags = new (std::nothrow) Tag[size]; // NOLINT
1732 if (tags == NULL)
1733 return false;
1734
1735 for (int idx = 0; idx < tags_count_; ++idx) {
1736 const Tag& src = tags_[idx];
1737 Tag* const dst = tags + idx;
1738 src.ShallowCopy(dst);
1739 }
1740
1741 delete[] tags_;
1742
1743 tags_ = tags;
1744 tags_size_ = size;
1745
1746 return true;
1747 }
1748
1423 /////////////////////////////////////////////////////////////// 1749 ///////////////////////////////////////////////////////////////
1424 // 1750 //
1425 // Cluster class 1751 // Cluster class
1426 1752
1427 Cluster::Cluster(uint64 timecode, int64 cues_pos) 1753 Cluster::Cluster(uint64 timecode, int64 cues_pos, uint64 timecode_scale)
1428 : blocks_added_(0), 1754 : blocks_added_(0),
1429 finalized_(false), 1755 finalized_(false),
1430 header_written_(false), 1756 header_written_(false),
1431 payload_size_(0), 1757 payload_size_(0),
1432 position_for_cues_(cues_pos), 1758 position_for_cues_(cues_pos),
1433 size_position_(-1), 1759 size_position_(-1),
1434 timecode_(timecode), 1760 timecode_(timecode),
1761 timecode_scale_(timecode_scale),
1435 writer_(NULL) {} 1762 writer_(NULL) {}
1436 1763
1437 Cluster::~Cluster() {} 1764 Cluster::~Cluster() {}
1438 1765
1439 bool Cluster::Init(IMkvWriter* ptr_writer) { 1766 bool Cluster::Init(IMkvWriter* ptr_writer) {
1440 if (!ptr_writer) { 1767 if (!ptr_writer) {
1441 return false; 1768 return false;
1442 } 1769 }
1443 writer_ = ptr_writer; 1770 writer_ = ptr_writer;
1444 return true; 1771 return true;
1445 } 1772 }
1446 1773
1447 bool Cluster::AddFrame(const uint8* frame, uint64 length, uint64 track_number, 1774 bool Cluster::AddFrame(const Frame* const frame) { return DoWriteFrame(frame); }
1775
1776 bool Cluster::AddFrame(const uint8* data, uint64 length, uint64 track_number,
1448 uint64 abs_timecode, bool is_key) { 1777 uint64 abs_timecode, bool is_key) {
1449 return DoWriteBlock(frame, length, track_number, abs_timecode, is_key ? 1 : 0, 1778 Frame frame;
1450 &WriteSimpleBlock); 1779 if (!frame.Init(data, length))
1780 return false;
1781 frame.set_track_number(track_number);
1782 frame.set_timestamp(abs_timecode);
1783 frame.set_is_key(is_key);
1784 return DoWriteFrame(&frame);
1451 } 1785 }
1452 1786
1453 bool Cluster::AddFrameWithAdditional(const uint8* frame, uint64 length, 1787 bool Cluster::AddFrameWithAdditional(const uint8* data, uint64 length,
1454 const uint8* additional, 1788 const uint8* additional,
1455 uint64 additional_length, uint64 add_id, 1789 uint64 additional_length, uint64 add_id,
1456 uint64 track_number, uint64 abs_timecode, 1790 uint64 track_number, uint64 abs_timecode,
1457 bool is_key) { 1791 bool is_key) {
1458 return DoWriteBlockWithAdditional( 1792 if (!additional || additional_length == 0) {
1459 frame, length, additional, additional_length, add_id, track_number, 1793 return false;
1460 abs_timecode, is_key ? 1 : 0, &WriteBlockWithAdditional); 1794 }
1795 Frame frame;
1796 if (!frame.Init(data, length) ||
1797 !frame.AddAdditionalData(additional, additional_length, add_id)) {
1798 return false;
1799 }
1800 frame.set_track_number(track_number);
1801 frame.set_timestamp(abs_timecode);
1802 frame.set_is_key(is_key);
1803 return DoWriteFrame(&frame);
1461 } 1804 }
1462 1805
1463 bool Cluster::AddFrameWithDiscardPadding(const uint8* frame, uint64 length, 1806 bool Cluster::AddFrameWithDiscardPadding(const uint8* data, uint64 length,
1464 int64 discard_padding, 1807 int64 discard_padding,
1465 uint64 track_number, 1808 uint64 track_number,
1466 uint64 abs_timecode, bool is_key) { 1809 uint64 abs_timecode, bool is_key) {
1467 return DoWriteBlockWithDiscardPadding( 1810 Frame frame;
1468 frame, length, discard_padding, track_number, abs_timecode, 1811 if (!frame.Init(data, length))
1469 is_key ? 1 : 0, &WriteBlockWithDiscardPadding); 1812 return false;
1813 frame.set_discard_padding(discard_padding);
1814 frame.set_track_number(track_number);
1815 frame.set_timestamp(abs_timecode);
1816 frame.set_is_key(is_key);
1817 return DoWriteFrame(&frame);
1470 } 1818 }
1471 1819
1472 bool Cluster::AddMetadata(const uint8* frame, uint64 length, 1820 bool Cluster::AddMetadata(const uint8* data, uint64 length, uint64 track_number,
1473 uint64 track_number, uint64 abs_timecode, 1821 uint64 abs_timecode, uint64 duration_timecode) {
1474 uint64 duration_timecode) { 1822 Frame frame;
1475 return DoWriteBlock(frame, length, track_number, abs_timecode, 1823 if (!frame.Init(data, length))
1476 duration_timecode, &WriteMetadataBlock); 1824 return false;
1825 frame.set_track_number(track_number);
1826 frame.set_timestamp(abs_timecode);
1827 frame.set_duration(duration_timecode);
1828 frame.set_is_key(true); // All metadata blocks are keyframes.
1829 return DoWriteFrame(&frame);
1477 } 1830 }
1478 1831
1479 void Cluster::AddPayloadSize(uint64 size) { payload_size_ += size; } 1832 void Cluster::AddPayloadSize(uint64 size) { payload_size_ += size; }
1480 1833
1481 bool Cluster::Finalize() { 1834 bool Cluster::Finalize() {
1482 if (!writer_ || finalized_ || size_position_ == -1) 1835 if (!writer_ || finalized_ || size_position_ == -1)
1483 return false; 1836 return false;
1484 1837
1485 if (writer_->Seekable()) { 1838 if (writer_->Seekable()) {
1486 const int64 pos = writer_->Position(); 1839 const int64 pos = writer_->Position();
(...skipping 12 matching lines...) Expand all
1499 1852
1500 return true; 1853 return true;
1501 } 1854 }
1502 1855
1503 uint64 Cluster::Size() const { 1856 uint64 Cluster::Size() const {
1504 const uint64 element_size = 1857 const uint64 element_size =
1505 EbmlMasterElementSize(kMkvCluster, 0xFFFFFFFFFFFFFFFFULL) + payload_size_; 1858 EbmlMasterElementSize(kMkvCluster, 0xFFFFFFFFFFFFFFFFULL) + payload_size_;
1506 return element_size; 1859 return element_size;
1507 } 1860 }
1508 1861
1509 template <typename Type> 1862 bool Cluster::PreWriteBlock() {
1510 bool Cluster::PreWriteBlock(Type* write_function) {
1511 if (write_function == NULL)
1512 return false;
1513
1514 if (finalized_) 1863 if (finalized_)
1515 return false; 1864 return false;
1516 1865
1517 if (!header_written_) { 1866 if (!header_written_) {
1518 if (!WriteClusterHeader()) 1867 if (!WriteClusterHeader())
1519 return false; 1868 return false;
1520 } 1869 }
1521 1870
1522 return true; 1871 return true;
1523 } 1872 }
1524 1873
1525 void Cluster::PostWriteBlock(uint64 element_size) { 1874 void Cluster::PostWriteBlock(uint64 element_size) {
1526 AddPayloadSize(element_size); 1875 AddPayloadSize(element_size);
1527 ++blocks_added_; 1876 ++blocks_added_;
1528 } 1877 }
1529 1878
1530 bool Cluster::IsValidTrackNumber(uint64 track_number) const {
1531 return (track_number > 0 && track_number <= 0x7E);
1532 }
1533
1534 int64 Cluster::GetRelativeTimecode(int64 abs_timecode) const { 1879 int64 Cluster::GetRelativeTimecode(int64 abs_timecode) const {
1535 const int64 cluster_timecode = this->Cluster::timecode(); 1880 const int64 cluster_timecode = this->Cluster::timecode();
1536 const int64 rel_timecode = 1881 const int64 rel_timecode =
1537 static_cast<int64>(abs_timecode) - cluster_timecode; 1882 static_cast<int64>(abs_timecode) - cluster_timecode;
1538 1883
1539 if (rel_timecode < 0 || rel_timecode > kMaxBlockTimecode) 1884 if (rel_timecode < 0 || rel_timecode > kMaxBlockTimecode)
1540 return -1; 1885 return -1;
1541 1886
1542 return rel_timecode; 1887 return rel_timecode;
1543 } 1888 }
1544 1889
1545 bool Cluster::DoWriteBlock(const uint8* frame, uint64 length, 1890 bool Cluster::DoWriteFrame(const Frame* const frame) {
1546 uint64 track_number, uint64 abs_timecode, 1891 if (!frame || !frame->IsValid())
1547 uint64 generic_arg, WriteBlock write_block) {
1548 if (frame == NULL || length == 0)
1549 return false; 1892 return false;
1550 1893
1551 if (!IsValidTrackNumber(track_number)) 1894 if (!PreWriteBlock())
1552 return false; 1895 return false;
1553 1896
1554 const int64 rel_timecode = GetRelativeTimecode(abs_timecode); 1897 const uint64 element_size = WriteFrame(writer_, frame, this);
1555 if (rel_timecode < 0)
1556 return false;
1557
1558 if (!PreWriteBlock(write_block))
1559 return false;
1560
1561 const uint64 element_size = (*write_block)(
1562 writer_, frame, length, track_number, rel_timecode, generic_arg);
1563 if (element_size == 0) 1898 if (element_size == 0)
1564 return false; 1899 return false;
1565 1900
1566 PostWriteBlock(element_size);
1567 return true;
1568 }
1569
1570 bool Cluster::DoWriteBlockWithAdditional(
1571 const uint8* frame, uint64 length, const uint8* additional,
1572 uint64 additional_length, uint64 add_id, uint64 track_number,
1573 uint64 abs_timecode, uint64 generic_arg, WriteBlockAdditional write_block) {
1574 if (frame == NULL || length == 0 || additional == NULL ||
1575 additional_length == 0)
1576 return false;
1577
1578 if (!IsValidTrackNumber(track_number))
1579 return false;
1580
1581 const int64 rel_timecode = GetRelativeTimecode(abs_timecode);
1582 if (rel_timecode < 0)
1583 return false;
1584
1585 if (!PreWriteBlock(write_block))
1586 return false;
1587
1588 const uint64 element_size =
1589 (*write_block)(writer_, frame, length, additional, additional_length,
1590 add_id, track_number, rel_timecode, generic_arg);
1591 if (element_size == 0)
1592 return false;
1593
1594 PostWriteBlock(element_size);
1595 return true;
1596 }
1597
1598 bool Cluster::DoWriteBlockWithDiscardPadding(
1599 const uint8* frame, uint64 length, int64 discard_padding,
1600 uint64 track_number, uint64 abs_timecode, uint64 generic_arg,
1601 WriteBlockDiscardPadding write_block) {
1602 if (frame == NULL || length == 0 || discard_padding <= 0)
1603 return false;
1604
1605 if (!IsValidTrackNumber(track_number))
1606 return false;
1607
1608 const int64 rel_timecode = GetRelativeTimecode(abs_timecode);
1609 if (rel_timecode < 0)
1610 return false;
1611
1612 if (!PreWriteBlock(write_block))
1613 return false;
1614
1615 const uint64 element_size =
1616 (*write_block)(writer_, frame, length, discard_padding, track_number,
1617 rel_timecode, generic_arg);
1618 if (element_size == 0)
1619 return false;
1620
1621 PostWriteBlock(element_size); 1901 PostWriteBlock(element_size);
1622 return true; 1902 return true;
1623 } 1903 }
1624 1904
1625 bool Cluster::WriteClusterHeader() { 1905 bool Cluster::WriteClusterHeader() {
1626 if (finalized_) 1906 if (finalized_)
1627 return false; 1907 return false;
1628 1908
1629 if (WriteID(writer_, kMkvCluster)) 1909 if (WriteID(writer_, kMkvCluster))
1630 return false; 1910 return false;
(...skipping 222 matching lines...) Expand 10 before | Expand all | Expand 10 after
1853 } 2133 }
1854 2134
1855 bool SegmentInfo::Write(IMkvWriter* writer) { 2135 bool SegmentInfo::Write(IMkvWriter* writer) {
1856 if (!writer || !muxing_app_ || !writing_app_) 2136 if (!writer || !muxing_app_ || !writing_app_)
1857 return false; 2137 return false;
1858 2138
1859 uint64 size = EbmlElementSize(kMkvTimecodeScale, timecode_scale_); 2139 uint64 size = EbmlElementSize(kMkvTimecodeScale, timecode_scale_);
1860 if (duration_ > 0.0) 2140 if (duration_ > 0.0)
1861 size += EbmlElementSize(kMkvDuration, static_cast<float>(duration_)); 2141 size += EbmlElementSize(kMkvDuration, static_cast<float>(duration_));
1862 if (date_utc_ != LLONG_MIN) 2142 if (date_utc_ != LLONG_MIN)
1863 size += EbmlDateElementSize(kMkvDateUTC, date_utc_); 2143 size += EbmlDateElementSize(kMkvDateUTC);
1864 size += EbmlElementSize(kMkvMuxingApp, muxing_app_); 2144 size += EbmlElementSize(kMkvMuxingApp, muxing_app_);
1865 size += EbmlElementSize(kMkvWritingApp, writing_app_); 2145 size += EbmlElementSize(kMkvWritingApp, writing_app_);
1866 2146
1867 if (!WriteEbmlMasterElement(writer, kMkvInfo, size)) 2147 if (!WriteEbmlMasterElement(writer, kMkvInfo, size))
1868 return false; 2148 return false;
1869 2149
1870 const int64 payload_position = writer->Position(); 2150 const int64 payload_position = writer->Position();
1871 if (payload_position < 0) 2151 if (payload_position < 0)
1872 return false; 2152 return false;
1873 2153
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
1959 header_written_(false), 2239 header_written_(false),
1960 last_block_duration_(0), 2240 last_block_duration_(0),
1961 last_timestamp_(0), 2241 last_timestamp_(0),
1962 max_cluster_duration_(kDefaultMaxClusterDuration), 2242 max_cluster_duration_(kDefaultMaxClusterDuration),
1963 max_cluster_size_(0), 2243 max_cluster_size_(0),
1964 mode_(kFile), 2244 mode_(kFile),
1965 new_cuepoint_(false), 2245 new_cuepoint_(false),
1966 output_cues_(true), 2246 output_cues_(true),
1967 payload_pos_(0), 2247 payload_pos_(0),
1968 size_position_(0), 2248 size_position_(0),
2249 doc_type_version_(kDefaultDocTypeVersion),
2250 doc_type_version_written_(0),
1969 writer_cluster_(NULL), 2251 writer_cluster_(NULL),
1970 writer_cues_(NULL), 2252 writer_cues_(NULL),
1971 writer_header_(NULL) { 2253 writer_header_(NULL) {
1972 const time_t curr_time = time(NULL); 2254 const time_t curr_time = time(NULL);
1973 seed_ = static_cast<unsigned int>(curr_time); 2255 seed_ = static_cast<unsigned int>(curr_time);
1974 #ifdef _WIN32 2256 #ifdef _WIN32
1975 srand(seed_); 2257 srand(seed_);
1976 #endif 2258 #endif
1977 } 2259 }
1978 2260
(...skipping 26 matching lines...) Expand all
2005 delete chunk_writer_cues_; 2287 delete chunk_writer_cues_;
2006 } 2288 }
2007 if (chunk_writer_header_) { 2289 if (chunk_writer_header_) {
2008 chunk_writer_header_->Close(); 2290 chunk_writer_header_->Close();
2009 delete chunk_writer_header_; 2291 delete chunk_writer_header_;
2010 } 2292 }
2011 } 2293 }
2012 2294
2013 void Segment::MoveCuesBeforeClustersHelper(uint64 diff, int32 index, 2295 void Segment::MoveCuesBeforeClustersHelper(uint64 diff, int32 index,
2014 uint64* cues_size) { 2296 uint64* cues_size) {
2015 const uint64 old_cues_size = *cues_size;
2016 CuePoint* const cue_point = cues_.GetCueByIndex(index); 2297 CuePoint* const cue_point = cues_.GetCueByIndex(index);
2017 if (cue_point == NULL) 2298 if (cue_point == NULL)
2018 return; 2299 return;
2019 const uint64 old_cue_point_size = cue_point->Size(); 2300 const uint64 old_cue_point_size = cue_point->Size();
2020 const uint64 cluster_pos = cue_point->cluster_pos() + diff; 2301 const uint64 cluster_pos = cue_point->cluster_pos() + diff;
2021 cue_point->set_cluster_pos(cluster_pos); // update the new cluster position 2302 cue_point->set_cluster_pos(cluster_pos); // update the new cluster position
2022 // New size of the cue is computed as follows 2303 // New size of the cue is computed as follows
2023 // Let a = current size of Cues Element 2304 // Let a = current sum of size of all CuePoints
2024 // Let b = Difference in Cue Point's size after this pass 2305 // Let b = Increase in Cue Point's size due to this iteration
2025 // Let c = Difference in length of Cues Element's size 2306 // Let c = Increase in size of Cues Element's length due to this iteration
2026 // (This is computed as CodedSize(a + b) - CodedSize(a) 2307 // (This is computed as CodedSize(a + b) - CodedSize(a))
2027 // Let d = a + b + c. Now d is the new size of the Cues element which is 2308 // Let d = b + c. Now d is the |diff| passed to the next recursive call.
2028 // passed on to the next recursive call. 2309 // Let e = a + b. Now e is the |cues_size| passed to the next recursive
2310 // call.
2029 const uint64 cue_point_size_diff = cue_point->Size() - old_cue_point_size; 2311 const uint64 cue_point_size_diff = cue_point->Size() - old_cue_point_size;
2030 const uint64 cue_size_diff = 2312 const uint64 cue_size_diff =
2031 GetCodedUIntSize(*cues_size + cue_point_size_diff) - 2313 GetCodedUIntSize(*cues_size + cue_point_size_diff) -
2032 GetCodedUIntSize(*cues_size); 2314 GetCodedUIntSize(*cues_size);
2033 *cues_size += cue_point_size_diff + cue_size_diff; 2315 *cues_size += cue_point_size_diff;
2034 diff = *cues_size - old_cues_size; 2316 diff = cue_size_diff + cue_point_size_diff;
2035 if (diff > 0) { 2317 if (diff > 0) {
2036 for (int32 i = 0; i < cues_.cue_entries_size(); ++i) { 2318 for (int32 i = 0; i < cues_.cue_entries_size(); ++i) {
2037 MoveCuesBeforeClustersHelper(diff, i, cues_size); 2319 MoveCuesBeforeClustersHelper(diff, i, cues_size);
2038 } 2320 }
2039 } 2321 }
2040 } 2322 }
2041 2323
2042 void Segment::MoveCuesBeforeClusters() { 2324 void Segment::MoveCuesBeforeClusters() {
2043 const uint64 current_cue_size = cues_.Size(); 2325 const uint64 current_cue_size = cues_.Size();
2044 uint64 cue_size = current_cue_size; 2326 uint64 cue_size = 0;
2045 for (int32 i = 0; i < cues_.cue_entries_size(); i++) 2327 for (int32 i = 0; i < cues_.cue_entries_size(); ++i)
2328 cue_size += cues_.GetCueByIndex(i)->Size();
2329 for (int32 i = 0; i < cues_.cue_entries_size(); ++i)
2046 MoveCuesBeforeClustersHelper(current_cue_size, i, &cue_size); 2330 MoveCuesBeforeClustersHelper(current_cue_size, i, &cue_size);
2047 2331
2048 // Adjust the Seek Entry to reflect the change in position 2332 // Adjust the Seek Entry to reflect the change in position
2049 // of Cluster and Cues 2333 // of Cluster and Cues
2050 int32 cluster_index = 0; 2334 int32 cluster_index = 0;
2051 int32 cues_index = 0; 2335 int32 cues_index = 0;
2052 for (int32 i = 0; i < SeekHead::kSeekEntryCount; ++i) { 2336 for (int32 i = 0; i < SeekHead::kSeekEntryCount; ++i) {
2053 if (seek_head_.GetId(i) == kMkvCluster) 2337 if (seek_head_.GetId(i) == kMkvCluster)
2054 cluster_index = i; 2338 cluster_index = i;
2055 if (seek_head_.GetId(i) == kMkvCues) 2339 if (seek_head_.GetId(i) == kMkvCues)
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after
2157 if (!cues_.Write(writer_cues_)) 2441 if (!cues_.Write(writer_cues_))
2158 return false; 2442 return false;
2159 2443
2160 if (!seek_head_.Finalize(writer_header_)) 2444 if (!seek_head_.Finalize(writer_header_))
2161 return false; 2445 return false;
2162 2446
2163 if (writer_header_->Seekable()) { 2447 if (writer_header_->Seekable()) {
2164 if (size_position_ == -1) 2448 if (size_position_ == -1)
2165 return false; 2449 return false;
2166 2450
2167 const int64 pos = writer_header_->Position();
2168 const int64 segment_size = MaxOffset(); 2451 const int64 segment_size = MaxOffset();
2169
2170 if (segment_size < 1) 2452 if (segment_size < 1)
2171 return false; 2453 return false;
2172 2454
2455 const int64 pos = writer_header_->Position();
2456 UpdateDocTypeVersion();
2457 if (doc_type_version_ != doc_type_version_written_) {
2458 if (writer_header_->Position(0))
2459 return false;
2460
2461 if (!WriteEbmlHeader(writer_header_, doc_type_version_))
2462 return false;
2463 if (writer_header_->Position() != ebml_header_size_)
2464 return false;
2465
2466 doc_type_version_written_ = doc_type_version_;
2467 }
2468
2173 if (writer_header_->Position(size_position_)) 2469 if (writer_header_->Position(size_position_))
2174 return false; 2470 return false;
2175 2471
2176 if (WriteUIntSize(writer_header_, segment_size, 8)) 2472 if (WriteUIntSize(writer_header_, segment_size, 8))
2177 return false; 2473 return false;
2178 2474
2179 if (writer_header_->Position(pos)) 2475 if (writer_header_->Position(pos))
2180 return false; 2476 return false;
2181 } 2477 }
2182 2478
(...skipping 20 matching lines...) Expand all
2203 if (!tracks_.AddTrack(track, number)) { 2499 if (!tracks_.AddTrack(track, number)) {
2204 delete track; 2500 delete track;
2205 return NULL; 2501 return NULL;
2206 } 2502 }
2207 2503
2208 return track; 2504 return track;
2209 } 2505 }
2210 2506
2211 Chapter* Segment::AddChapter() { return chapters_.AddChapter(&seed_); } 2507 Chapter* Segment::AddChapter() { return chapters_.AddChapter(&seed_); }
2212 2508
2509 Tag* Segment::AddTag() { return tags_.AddTag(); }
2510
2213 uint64 Segment::AddVideoTrack(int32 width, int32 height, int32 number) { 2511 uint64 Segment::AddVideoTrack(int32 width, int32 height, int32 number) {
2214 VideoTrack* const track = new (std::nothrow) VideoTrack(&seed_); // NOLINT 2512 VideoTrack* const track = new (std::nothrow) VideoTrack(&seed_); // NOLINT
2215 if (!track) 2513 if (!track)
2216 return 0; 2514 return 0;
2217 2515
2218 track->set_type(Tracks::kVideo); 2516 track->set_type(Tracks::kVideo);
2219 track->set_codec_id(Tracks::kVp8CodecId); 2517 track->set_codec_id(Tracks::kVp8CodecId);
2220 track->set_width(width); 2518 track->set_width(width);
2221 track->set_height(height); 2519 track->set_height(height);
2222 2520
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
2257 track->set_type(Tracks::kAudio); 2555 track->set_type(Tracks::kAudio);
2258 track->set_codec_id(Tracks::kVorbisCodecId); 2556 track->set_codec_id(Tracks::kVorbisCodecId);
2259 track->set_sample_rate(sample_rate); 2557 track->set_sample_rate(sample_rate);
2260 track->set_channels(channels); 2558 track->set_channels(channels);
2261 2559
2262 tracks_.AddTrack(track, number); 2560 tracks_.AddTrack(track, number);
2263 2561
2264 return track->number(); 2562 return track->number();
2265 } 2563 }
2266 2564
2267 bool Segment::AddFrame(const uint8* frame, uint64 length, uint64 track_number, 2565 bool Segment::AddFrame(const uint8* data, uint64 length, uint64 track_number,
2268 uint64 timestamp, bool is_key) { 2566 uint64 timestamp, bool is_key) {
2567 if (!data)
2568 return false;
2569
2570 Frame frame;
2571 if (!frame.Init(data, length))
2572 return false;
2573 frame.set_track_number(track_number);
2574 frame.set_timestamp(timestamp);
2575 frame.set_is_key(is_key);
2576 return AddGenericFrame(&frame);
2577 }
2578
2579 bool Segment::AddFrameWithAdditional(const uint8* data, uint64 length,
2580 const uint8* additional,
2581 uint64 additional_length, uint64 add_id,
2582 uint64 track_number, uint64 timestamp,
2583 bool is_key) {
2584 if (!data || !additional)
2585 return false;
2586
2587 Frame frame;
2588 if (!frame.Init(data, length) ||
2589 !frame.AddAdditionalData(additional, additional_length, add_id)) {
2590 return false;
2591 }
2592 frame.set_track_number(track_number);
2593 frame.set_timestamp(timestamp);
2594 frame.set_is_key(is_key);
2595 return AddGenericFrame(&frame);
2596 }
2597
2598 bool Segment::AddFrameWithDiscardPadding(const uint8* data, uint64 length,
2599 int64 discard_padding,
2600 uint64 track_number, uint64 timestamp,
2601 bool is_key) {
2602 if (!data)
2603 return false;
2604
2605 Frame frame;
2606 if (!frame.Init(data, length))
2607 return false;
2608 frame.set_discard_padding(discard_padding);
2609 frame.set_track_number(track_number);
2610 frame.set_timestamp(timestamp);
2611 frame.set_is_key(is_key);
2612 return AddGenericFrame(&frame);
2613 }
2614
2615 bool Segment::AddMetadata(const uint8* data, uint64 length, uint64 track_number,
2616 uint64 timestamp_ns, uint64 duration_ns) {
2617 if (!data)
2618 return false;
2619
2620 Frame frame;
2621 if (!frame.Init(data, length))
2622 return false;
2623 frame.set_track_number(track_number);
2624 frame.set_timestamp(timestamp_ns);
2625 frame.set_duration(duration_ns);
2626 frame.set_is_key(true); // All metadata blocks are keyframes.
2627 return AddGenericFrame(&frame);
2628 }
2629
2630 bool Segment::AddGenericFrame(const Frame* frame) {
2269 if (!frame) 2631 if (!frame)
2270 return false; 2632 return false;
2271 2633
2272 if (!CheckHeaderInfo()) 2634 if (!CheckHeaderInfo())
2273 return false; 2635 return false;
2274 2636
2275 // Check for non-monotonically increasing timestamps. 2637 // Check for non-monotonically increasing timestamps.
2276 if (timestamp < last_timestamp_) 2638 if (frame->timestamp() < last_timestamp_)
2277 return false; 2639 return false;
2278 2640
2641 // Check if the track number is valid.
2642 if (!tracks_.GetTrackByNumber(frame->track_number()))
2643 return false;
2644
2645 if (frame->discard_padding() != 0)
2646 doc_type_version_ = 4;
2647
2279 // If the segment has a video track hold onto audio frames to make sure the 2648 // If the segment has a video track hold onto audio frames to make sure the
2280 // audio that is associated with the start time of a video key-frame is 2649 // audio that is associated with the start time of a video key-frame is
2281 // muxed into the same cluster. 2650 // muxed into the same cluster.
2282 if (has_video_ && tracks_.TrackIsAudio(track_number) && !force_new_cluster_) { 2651 if (has_video_ && tracks_.TrackIsAudio(frame->track_number()) &&
2652 !force_new_cluster_) {
2283 Frame* const new_frame = new (std::nothrow) Frame(); 2653 Frame* const new_frame = new (std::nothrow) Frame();
2284 if (new_frame == NULL || !new_frame->Init(frame, length)) 2654 if (!new_frame || !new_frame->CopyFrom(*frame))
2285 return false; 2655 return false;
2286 new_frame->set_track_number(track_number); 2656 return QueueFrame(new_frame);
2287 new_frame->set_timestamp(timestamp);
2288 new_frame->set_is_key(is_key);
2289
2290 if (!QueueFrame(new_frame))
2291 return false;
2292
2293 return true;
2294 } 2657 }
2295 2658
2296 if (!DoNewClusterProcessing(track_number, timestamp, is_key)) 2659 if (!DoNewClusterProcessing(frame->track_number(), frame->timestamp(),
2660 frame->is_key())) {
2297 return false; 2661 return false;
2662 }
2298 2663
2299 if (cluster_list_size_ < 1) 2664 if (cluster_list_size_ < 1)
2300 return false; 2665 return false;
2301
2302 Cluster* const cluster = cluster_list_[cluster_list_size_ - 1];
2303 if (!cluster)
2304 return false;
2305
2306 const uint64 timecode_scale = segment_info_.timecode_scale();
2307 const uint64 abs_timecode = timestamp / timecode_scale;
2308
2309 if (!cluster->AddFrame(frame, length, track_number, abs_timecode, is_key))
2310 return false;
2311
2312 if (new_cuepoint_ && cues_track_ == track_number) {
2313 if (!AddCuePoint(timestamp, cues_track_))
2314 return false;
2315 }
2316
2317 if (timestamp > last_timestamp_)
2318 last_timestamp_ = timestamp;
2319
2320 return true;
2321 }
2322
2323 bool Segment::AddFrameWithAdditional(const uint8* frame, uint64 length,
2324 const uint8* additional,
2325 uint64 additional_length, uint64 add_id,
2326 uint64 track_number, uint64 timestamp,
2327 bool is_key) {
2328 if (frame == NULL || additional == NULL)
2329 return false;
2330
2331 if (!CheckHeaderInfo())
2332 return false;
2333
2334 // Check for non-monotonically increasing timestamps.
2335 if (timestamp < last_timestamp_)
2336 return false;
2337
2338 // If the segment has a video track hold onto audio frames to make sure the
2339 // audio that is associated with the start time of a video key-frame is
2340 // muxed into the same cluster.
2341 if (has_video_ && tracks_.TrackIsAudio(track_number) && !force_new_cluster_) {
2342 Frame* const new_frame = new (std::nothrow) Frame();
2343 if (new_frame == NULL || !new_frame->Init(frame, length))
2344 return false;
2345 new_frame->set_track_number(track_number);
2346 new_frame->set_timestamp(timestamp);
2347 new_frame->set_is_key(is_key);
2348
2349 if (!QueueFrame(new_frame))
2350 return false;
2351
2352 return true;
2353 }
2354
2355 if (!DoNewClusterProcessing(track_number, timestamp, is_key))
2356 return false;
2357
2358 if (cluster_list_size_ < 1)
2359 return false;
2360
2361 Cluster* const cluster = cluster_list_[cluster_list_size_ - 1];
2362 if (cluster == NULL)
2363 return false;
2364
2365 const uint64 timecode_scale = segment_info_.timecode_scale();
2366 const uint64 abs_timecode = timestamp / timecode_scale;
2367
2368 if (!cluster->AddFrameWithAdditional(frame, length, additional,
2369 additional_length, add_id, track_number,
2370 abs_timecode, is_key))
2371 return false;
2372
2373 if (new_cuepoint_ && cues_track_ == track_number) {
2374 if (!AddCuePoint(timestamp, cues_track_))
2375 return false;
2376 }
2377
2378 if (timestamp > last_timestamp_)
2379 last_timestamp_ = timestamp;
2380
2381 return true;
2382 }
2383
2384 bool Segment::AddFrameWithDiscardPadding(const uint8* frame, uint64 length,
2385 int64 discard_padding,
2386 uint64 track_number, uint64 timestamp,
2387 bool is_key) {
2388 if (frame == NULL || discard_padding <= 0)
2389 return false;
2390
2391 if (!CheckHeaderInfo())
2392 return false;
2393
2394 // Check for non-monotonically increasing timestamps.
2395 if (timestamp < last_timestamp_)
2396 return false;
2397
2398 // If the segment has a video track hold onto audio frames to make sure the
2399 // audio that is associated with the start time of a video key-frame is
2400 // muxed into the same cluster.
2401 if (has_video_ && tracks_.TrackIsAudio(track_number) && !force_new_cluster_) {
2402 Frame* const new_frame = new (std::nothrow) Frame();
2403 if (new_frame == NULL || !new_frame->Init(frame, length))
2404 return false;
2405 new_frame->set_track_number(track_number);
2406 new_frame->set_timestamp(timestamp);
2407 new_frame->set_is_key(is_key);
2408 new_frame->set_discard_padding(discard_padding);
2409
2410 if (!QueueFrame(new_frame))
2411 return false;
2412
2413 return true;
2414 }
2415
2416 if (!DoNewClusterProcessing(track_number, timestamp, is_key))
2417 return false;
2418
2419 if (cluster_list_size_ < 1)
2420 return false;
2421 2666
2422 Cluster* const cluster = cluster_list_[cluster_list_size_ - 1]; 2667 Cluster* const cluster = cluster_list_[cluster_list_size_ - 1];
2423 if (!cluster) 2668 if (!cluster)
2424 return false; 2669 return false;
2425 2670
2426 const uint64 timecode_scale = segment_info_.timecode_scale(); 2671 // If the Frame is not a SimpleBlock, then set the reference_block_timestamp
2427 const uint64 abs_timecode = timestamp / timecode_scale; 2672 // if it is not set already.
2428 2673 bool frame_created = false;
2429 if (!cluster->AddFrameWithDiscardPadding( 2674 if (!frame->CanBeSimpleBlock() && !frame->is_key() &&
2430 frame, length, discard_padding, track_number, abs_timecode, is_key)) { 2675 !frame->reference_block_timestamp_set()) {
2431 return false; 2676 Frame* const new_frame = new (std::nothrow) Frame();
2677 if (!new_frame->CopyFrom(*frame))
2678 return false;
2679 new_frame->set_reference_block_timestamp(
2680 last_track_timestamp_[frame->track_number() - 1]);
2681 frame = new_frame;
2682 frame_created = true;
2432 } 2683 }
2433 2684
2434 if (new_cuepoint_ && cues_track_ == track_number) { 2685 if (!cluster->AddFrame(frame))
2435 if (!AddCuePoint(timestamp, cues_track_)) 2686 return false;
2687
2688 if (new_cuepoint_ && cues_track_ == frame->track_number()) {
2689 if (!AddCuePoint(frame->timestamp(), cues_track_))
2436 return false; 2690 return false;
2437 } 2691 }
2438 2692
2439 if (timestamp > last_timestamp_) 2693 last_timestamp_ = frame->timestamp();
2440 last_timestamp_ = timestamp; 2694 last_track_timestamp_[frame->track_number() - 1] = frame->timestamp();
2695 last_block_duration_ = frame->duration();
2696
2697 if (frame_created)
2698 delete frame;
2441 2699
2442 return true; 2700 return true;
2443 } 2701 }
2444 2702
2445 bool Segment::AddMetadata(const uint8* frame, uint64 length,
2446 uint64 track_number, uint64 timestamp_ns,
2447 uint64 duration_ns) {
2448 if (!frame)
2449 return false;
2450
2451 if (!CheckHeaderInfo())
2452 return false;
2453
2454 // Check for non-monotonically increasing timestamps.
2455 if (timestamp_ns < last_timestamp_)
2456 return false;
2457
2458 if (!DoNewClusterProcessing(track_number, timestamp_ns, true))
2459 return false;
2460
2461 if (cluster_list_size_ < 1)
2462 return false;
2463
2464 Cluster* const cluster = cluster_list_[cluster_list_size_ - 1];
2465
2466 if (!cluster)
2467 return false;
2468
2469 const uint64 timecode_scale = segment_info_.timecode_scale();
2470 const uint64 abs_timecode = timestamp_ns / timecode_scale;
2471 const uint64 duration_timecode = duration_ns / timecode_scale;
2472
2473 if (!cluster->AddMetadata(frame, length, track_number, abs_timecode,
2474 duration_timecode))
2475 return false;
2476
2477 if (timestamp_ns > last_timestamp_)
2478 last_timestamp_ = timestamp_ns;
2479
2480 return true;
2481 }
2482
2483 bool Segment::AddGenericFrame(const Frame* frame) {
2484 last_block_duration_ = frame->duration();
2485 if (!tracks_.TrackIsAudio(frame->track_number()) &&
2486 !tracks_.TrackIsVideo(frame->track_number()) && frame->duration() > 0) {
2487 return AddMetadata(frame->frame(), frame->length(), frame->track_number(),
2488 frame->timestamp(), frame->duration());
2489 } else if (frame->additional() && frame->additional_length() > 0) {
2490 return AddFrameWithAdditional(
2491 frame->frame(), frame->length(), frame->additional(),
2492 frame->additional_length(), frame->add_id(), frame->track_number(),
2493 frame->timestamp(), frame->is_key());
2494 } else if (frame->discard_padding() > 0) {
2495 return AddFrameWithDiscardPadding(
2496 frame->frame(), frame->length(), frame->discard_padding(),
2497 frame->track_number(), frame->timestamp(), frame->is_key());
2498 } else {
2499 return AddFrame(frame->frame(), frame->length(), frame->track_number(),
2500 frame->timestamp(), frame->is_key());
2501 }
2502 }
2503
2504 void Segment::OutputCues(bool output_cues) { output_cues_ = output_cues; } 2703 void Segment::OutputCues(bool output_cues) { output_cues_ = output_cues; }
2505 2704
2506 bool Segment::SetChunking(bool chunking, const char* filename) { 2705 bool Segment::SetChunking(bool chunking, const char* filename) {
2507 if (chunk_count_ > 0) 2706 if (chunk_count_ > 0)
2508 return false; 2707 return false;
2509 2708
2510 if (chunking) { 2709 if (chunking) {
2511 if (!filename) 2710 if (!filename)
2512 return false; 2711 return false;
2513 2712
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
2591 return true; 2790 return true;
2592 } 2791 }
2593 2792
2594 void Segment::ForceNewClusterOnNextFrame() { force_new_cluster_ = true; } 2793 void Segment::ForceNewClusterOnNextFrame() { force_new_cluster_ = true; }
2595 2794
2596 Track* Segment::GetTrackByNumber(uint64 track_number) const { 2795 Track* Segment::GetTrackByNumber(uint64 track_number) const {
2597 return tracks_.GetTrackByNumber(track_number); 2796 return tracks_.GetTrackByNumber(track_number);
2598 } 2797 }
2599 2798
2600 bool Segment::WriteSegmentHeader() { 2799 bool Segment::WriteSegmentHeader() {
2800 UpdateDocTypeVersion();
2801
2601 // TODO(fgalligan): Support more than one segment. 2802 // TODO(fgalligan): Support more than one segment.
2602 if (!WriteEbmlHeader(writer_header_)) 2803 if (!WriteEbmlHeader(writer_header_, doc_type_version_))
2603 return false; 2804 return false;
2805 doc_type_version_written_ = doc_type_version_;
2806 ebml_header_size_ = static_cast<int32>(writer_header_->Position());
2604 2807
2605 // Write "unknown" (-1) as segment size value. If mode is kFile, Segment 2808 // Write "unknown" (-1) as segment size value. If mode is kFile, Segment
2606 // will write over duration when the file is finalized. 2809 // will write over duration when the file is finalized.
2607 if (WriteID(writer_header_, kMkvSegment)) 2810 if (WriteID(writer_header_, kMkvSegment))
2608 return false; 2811 return false;
2609 2812
2610 // Save for later. 2813 // Save for later.
2611 size_position_ = writer_header_->Position(); 2814 size_position_ = writer_header_->Position();
2612 2815
2613 // Write "unknown" (EBML coded -1) as segment size value. We need to write 8 2816 // Write "unknown" (EBML coded -1) as segment size value. We need to write 8
(...skipping 24 matching lines...) Expand all
2638 if (!tracks_.Write(writer_header_)) 2841 if (!tracks_.Write(writer_header_))
2639 return false; 2842 return false;
2640 2843
2641 if (chapters_.Count() > 0) { 2844 if (chapters_.Count() > 0) {
2642 if (!seek_head_.AddSeekEntry(kMkvChapters, MaxOffset())) 2845 if (!seek_head_.AddSeekEntry(kMkvChapters, MaxOffset()))
2643 return false; 2846 return false;
2644 if (!chapters_.Write(writer_header_)) 2847 if (!chapters_.Write(writer_header_))
2645 return false; 2848 return false;
2646 } 2849 }
2647 2850
2851 if (tags_.Count() > 0) {
2852 if (!seek_head_.AddSeekEntry(kMkvTags, MaxOffset()))
2853 return false;
2854 if (!tags_.Write(writer_header_))
2855 return false;
2856 }
2857
2648 if (chunking_ && (mode_ == kLive || !writer_header_->Seekable())) { 2858 if (chunking_ && (mode_ == kLive || !writer_header_->Seekable())) {
2649 if (!chunk_writer_header_) 2859 if (!chunk_writer_header_)
2650 return false; 2860 return false;
2651 2861
2652 chunk_writer_header_->Close(); 2862 chunk_writer_header_->Close();
2653 } 2863 }
2654 2864
2655 header_written_ = true; 2865 header_written_ = true;
2656 2866
2657 return true; 2867 return true;
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
2733 } 2943 }
2734 2944
2735 bool Segment::MakeNewCluster(uint64 frame_timestamp_ns) { 2945 bool Segment::MakeNewCluster(uint64 frame_timestamp_ns) {
2736 const int32 new_size = cluster_list_size_ + 1; 2946 const int32 new_size = cluster_list_size_ + 1;
2737 2947
2738 if (new_size > cluster_list_capacity_) { 2948 if (new_size > cluster_list_capacity_) {
2739 // Add more clusters. 2949 // Add more clusters.
2740 const int32 new_capacity = 2950 const int32 new_capacity =
2741 (cluster_list_capacity_ <= 0) ? 1 : cluster_list_capacity_ * 2; 2951 (cluster_list_capacity_ <= 0) ? 1 : cluster_list_capacity_ * 2;
2742 Cluster** const clusters = 2952 Cluster** const clusters =
2743 new (std::nothrow) Cluster* [new_capacity]; // NOLINT 2953 new (std::nothrow) Cluster*[new_capacity]; // NOLINT
2744 if (!clusters) 2954 if (!clusters)
2745 return false; 2955 return false;
2746 2956
2747 for (int32 i = 0; i < cluster_list_size_; ++i) { 2957 for (int32 i = 0; i < cluster_list_size_; ++i) {
2748 clusters[i] = cluster_list_[i]; 2958 clusters[i] = cluster_list_[i];
2749 } 2959 }
2750 2960
2751 delete[] cluster_list_; 2961 delete[] cluster_list_;
2752 2962
2753 cluster_list_ = clusters; 2963 cluster_list_ = clusters;
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
2789 const Frame* const f = frames_[0]; // earliest queued frame 2999 const Frame* const f = frames_[0]; // earliest queued frame
2790 const uint64 ns = f->timestamp(); 3000 const uint64 ns = f->timestamp();
2791 const uint64 tc = ns / timecode_scale; 3001 const uint64 tc = ns / timecode_scale;
2792 3002
2793 if (tc < cluster_timecode) 3003 if (tc < cluster_timecode)
2794 cluster_timecode = tc; 3004 cluster_timecode = tc;
2795 } 3005 }
2796 3006
2797 Cluster*& cluster = cluster_list_[cluster_list_size_]; 3007 Cluster*& cluster = cluster_list_[cluster_list_size_];
2798 const int64 offset = MaxOffset(); 3008 const int64 offset = MaxOffset();
2799 cluster = new (std::nothrow) Cluster(cluster_timecode, offset); // NOLINT 3009 cluster = new (std::nothrow) Cluster(cluster_timecode, // NOLINT
3010 offset, segment_info_.timecode_scale());
2800 if (!cluster) 3011 if (!cluster)
2801 return false; 3012 return false;
2802 3013
2803 if (!cluster->Init(writer_cluster_)) 3014 if (!cluster->Init(writer_cluster_))
2804 return false; 3015 return false;
2805 3016
2806 cluster_list_size_ = new_size; 3017 cluster_list_size_ = new_size;
2807 return true; 3018 return true;
2808 } 3019 }
2809 3020
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
2866 if (!track) 3077 if (!track)
2867 return false; 3078 return false;
2868 3079
2869 cues_track_ = track->number(); 3080 cues_track_ = track->number();
2870 } 3081 }
2871 } 3082 }
2872 } 3083 }
2873 return true; 3084 return true;
2874 } 3085 }
2875 3086
3087 void Segment::UpdateDocTypeVersion() {
3088 for (uint32 index = 0; index < tracks_.track_entries_size(); ++index) {
3089 const Track* track = tracks_.GetTrackByIndex(index);
3090 if (track == NULL)
3091 break;
3092 if ((track->codec_delay() || track->seek_pre_roll()) &&
3093 doc_type_version_ < 4) {
3094 doc_type_version_ = 4;
3095 break;
3096 }
3097 }
3098 }
3099
2876 bool Segment::UpdateChunkName(const char* ext, char** name) const { 3100 bool Segment::UpdateChunkName(const char* ext, char** name) const {
2877 if (!name || !ext) 3101 if (!name || !ext)
2878 return false; 3102 return false;
2879 3103
2880 char ext_chk[64]; 3104 char ext_chk[64];
2881 #ifdef _MSC_VER 3105 #ifdef _MSC_VER
2882 sprintf_s(ext_chk, sizeof(ext_chk), "_%06d.%s", chunk_count_, ext); 3106 sprintf_s(ext_chk, sizeof(ext_chk), "_%06d.%s", chunk_count_, ext);
2883 #else 3107 #else
2884 snprintf(ext_chk, sizeof(ext_chk), "_%06d.%s", chunk_count_, ext); 3108 snprintf(ext_chk, sizeof(ext_chk), "_%06d.%s", chunk_count_, ext);
2885 #endif 3109 #endif
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
2925 bool Segment::QueueFrame(Frame* frame) { 3149 bool Segment::QueueFrame(Frame* frame) {
2926 const int32 new_size = frames_size_ + 1; 3150 const int32 new_size = frames_size_ + 1;
2927 3151
2928 if (new_size > frames_capacity_) { 3152 if (new_size > frames_capacity_) {
2929 // Add more frames. 3153 // Add more frames.
2930 const int32 new_capacity = (!frames_capacity_) ? 2 : frames_capacity_ * 2; 3154 const int32 new_capacity = (!frames_capacity_) ? 2 : frames_capacity_ * 2;
2931 3155
2932 if (new_capacity < 1) 3156 if (new_capacity < 1)
2933 return false; 3157 return false;
2934 3158
2935 Frame** const frames = new (std::nothrow) Frame* [new_capacity]; // NOLINT 3159 Frame** const frames = new (std::nothrow) Frame*[new_capacity]; // NOLINT
2936 if (!frames) 3160 if (!frames)
2937 return false; 3161 return false;
2938 3162
2939 for (int32 i = 0; i < frames_size_; ++i) { 3163 for (int32 i = 0; i < frames_size_; ++i) {
2940 frames[i] = frames_[i]; 3164 frames[i] = frames_[i];
2941 } 3165 }
2942 3166
2943 delete[] frames_; 3167 delete[] frames_;
2944 frames_ = frames; 3168 frames_ = frames;
2945 frames_capacity_ = new_capacity; 3169 frames_capacity_ = new_capacity;
2946 } 3170 }
2947 3171
2948 frames_[frames_size_++] = frame; 3172 frames_[frames_size_++] = frame;
2949 3173
2950 return true; 3174 return true;
2951 } 3175 }
2952 3176
2953 int Segment::WriteFramesAll() { 3177 int Segment::WriteFramesAll() {
2954 if (frames_ == NULL) 3178 if (frames_ == NULL)
2955 return 0; 3179 return 0;
2956 3180
2957 if (cluster_list_size_ < 1) 3181 if (cluster_list_size_ < 1)
2958 return -1; 3182 return -1;
2959 3183
2960 Cluster* const cluster = cluster_list_[cluster_list_size_ - 1]; 3184 Cluster* const cluster = cluster_list_[cluster_list_size_ - 1];
2961 3185
2962 if (!cluster) 3186 if (!cluster)
2963 return -1; 3187 return -1;
2964 3188
2965 const uint64 timecode_scale = segment_info_.timecode_scale();
2966
2967 for (int32 i = 0; i < frames_size_; ++i) { 3189 for (int32 i = 0; i < frames_size_; ++i) {
2968 Frame*& frame = frames_[i]; 3190 Frame*& frame = frames_[i];
2969 const uint64 frame_timestamp = frame->timestamp(); // ns 3191 // TODO(jzern/vigneshv): using Segment::AddGenericFrame here would limit the
2970 const uint64 frame_timecode = frame_timestamp / timecode_scale; 3192 // places where |doc_type_version_| needs to be updated.
2971 3193 if (frame->discard_padding() != 0)
2972 if (frame->discard_padding() > 0) { 3194 doc_type_version_ = 4;
2973 if (!cluster->AddFrameWithDiscardPadding( 3195 if (!cluster->AddFrame(frame))
2974 frame->frame(), frame->length(), frame->discard_padding(), 3196 return -1;
2975 frame->track_number(), frame_timecode, frame->is_key())) {
2976 return -1;
2977 }
2978 } else {
2979 if (!cluster->AddFrame(frame->frame(), frame->length(),
2980 frame->track_number(), frame_timecode,
2981 frame->is_key())) {
2982 return -1;
2983 }
2984 }
2985 3197
2986 if (new_cuepoint_ && cues_track_ == frame->track_number()) { 3198 if (new_cuepoint_ && cues_track_ == frame->track_number()) {
2987 if (!AddCuePoint(frame_timestamp, cues_track_)) 3199 if (!AddCuePoint(frame->timestamp(), cues_track_))
2988 return -1; 3200 return -1;
2989 } 3201 }
2990 3202
2991 if (frame_timestamp > last_timestamp_) 3203 if (frame->timestamp() > last_timestamp_) {
2992 last_timestamp_ = frame_timestamp; 3204 last_timestamp_ = frame->timestamp();
3205 last_track_timestamp_[frame->track_number() - 1] = frame->timestamp();
3206 }
2993 3207
2994 delete frame; 3208 delete frame;
2995 frame = NULL; 3209 frame = NULL;
2996 } 3210 }
2997 3211
2998 const int result = frames_size_; 3212 const int result = frames_size_;
2999 frames_size_ = 0; 3213 frames_size_ = 0;
3000 3214
3001 return result; 3215 return result;
3002 } 3216 }
3003 3217
3004 bool Segment::WriteFramesLessThan(uint64 timestamp) { 3218 bool Segment::WriteFramesLessThan(uint64 timestamp) {
3005 // Check |cluster_list_size_| to see if this is the first cluster. If it is 3219 // Check |cluster_list_size_| to see if this is the first cluster. If it is
3006 // the first cluster the audio frames that are less than the first video 3220 // the first cluster the audio frames that are less than the first video
3007 // timesatmp will be written in a later step. 3221 // timesatmp will be written in a later step.
3008 if (frames_size_ > 0 && cluster_list_size_ > 0) { 3222 if (frames_size_ > 0 && cluster_list_size_ > 0) {
3009 if (!frames_) 3223 if (!frames_)
3010 return false; 3224 return false;
3011 3225
3012 Cluster* const cluster = cluster_list_[cluster_list_size_ - 1]; 3226 Cluster* const cluster = cluster_list_[cluster_list_size_ - 1];
3013 if (!cluster) 3227 if (!cluster)
3014 return false; 3228 return false;
3015 3229
3016 const uint64 timecode_scale = segment_info_.timecode_scale();
3017 int32 shift_left = 0; 3230 int32 shift_left = 0;
3018 3231
3019 // TODO(fgalligan): Change this to use the durations of frames instead of 3232 // TODO(fgalligan): Change this to use the durations of frames instead of
3020 // the next frame's start time if the duration is accurate. 3233 // the next frame's start time if the duration is accurate.
3021 for (int32 i = 1; i < frames_size_; ++i) { 3234 for (int32 i = 1; i < frames_size_; ++i) {
3022 const Frame* const frame_curr = frames_[i]; 3235 const Frame* const frame_curr = frames_[i];
3023 3236
3024 if (frame_curr->timestamp() > timestamp) 3237 if (frame_curr->timestamp() > timestamp)
3025 break; 3238 break;
3026 3239
3027 const Frame* const frame_prev = frames_[i - 1]; 3240 const Frame* const frame_prev = frames_[i - 1];
3028 const uint64 frame_timestamp = frame_prev->timestamp(); 3241 if (frame_prev->discard_padding() != 0)
3029 const uint64 frame_timecode = frame_timestamp / timecode_scale; 3242 doc_type_version_ = 4;
3030 const int64 discard_padding = frame_prev->discard_padding(); 3243 if (!cluster->AddFrame(frame_prev))
3031 3244 return false;
3032 if (discard_padding > 0) {
3033 if (!cluster->AddFrameWithDiscardPadding(
3034 frame_prev->frame(), frame_prev->length(), discard_padding,
3035 frame_prev->track_number(), frame_timecode,
3036 frame_prev->is_key())) {
3037 return false;
3038 }
3039 } else {
3040 if (!cluster->AddFrame(frame_prev->frame(), frame_prev->length(),
3041 frame_prev->track_number(), frame_timecode,
3042 frame_prev->is_key())) {
3043 return false;
3044 }
3045 }
3046 3245
3047 if (new_cuepoint_ && cues_track_ == frame_prev->track_number()) { 3246 if (new_cuepoint_ && cues_track_ == frame_prev->track_number()) {
3048 if (!AddCuePoint(frame_timestamp, cues_track_)) 3247 if (!AddCuePoint(frame_prev->timestamp(), cues_track_))
3049 return false; 3248 return false;
3050 } 3249 }
3051 3250
3052 ++shift_left; 3251 ++shift_left;
3053 if (frame_timestamp > last_timestamp_) 3252 if (frame_prev->timestamp() > last_timestamp_) {
3054 last_timestamp_ = frame_timestamp; 3253 last_timestamp_ = frame_prev->timestamp();
3254 last_track_timestamp_[frame_prev->track_number() - 1] =
3255 frame_prev->timestamp();
3256 }
3055 3257
3056 delete frame_prev; 3258 delete frame_prev;
3057 } 3259 }
3058 3260
3059 if (shift_left > 0) { 3261 if (shift_left > 0) {
3060 if (shift_left >= frames_size_) 3262 if (shift_left >= frames_size_)
3061 return false; 3263 return false;
3062 3264
3063 const int32 new_frames_size = frames_size_ - shift_left; 3265 const int32 new_frames_size = frames_size_ - shift_left;
3064 for (int32 i = 0; i < new_frames_size; ++i) { 3266 for (int32 i = 0; i < new_frames_size; ++i) {
3065 frames_[i] = frames_[i + shift_left]; 3267 frames_[i] = frames_[i + shift_left];
3066 } 3268 }
3067 3269
3068 frames_size_ = new_frames_size; 3270 frames_size_ = new_frames_size;
3069 } 3271 }
3070 } 3272 }
3071 3273
3072 return true; 3274 return true;
3073 } 3275 }
3074 3276
3075 } // namespace mkvmuxer 3277 } // namespace mkvmuxer
OLDNEW
« no previous file with comments | « source/libvpx/third_party/libwebm/mkvmuxer.hpp ('k') | source/libvpx/third_party/libwebm/mkvmuxerutil.hpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698