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

Side by Side Diff: media/formats/webm/tracks_builder.cc

Issue 213153008: MSE: Parse WebM TrackEntry DefaultDuration field (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Fixes lint err (c-style cast). Created 6 years, 8 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 | Annotate | Revision Log
« no previous file with comments | « media/formats/webm/tracks_builder.h ('k') | media/formats/webm/webm_tracks_parser.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "media/formats/webm/tracks_builder.h" 5 #include "media/formats/webm/tracks_builder.h"
6 6
7 #include "base/logging.h"
7 #include "media/formats/webm/webm_constants.h" 8 #include "media/formats/webm/webm_constants.h"
8 9
9 namespace media { 10 namespace media {
10 11
11 // Returns size of an integer, formatted using Matroska serialization. 12 // Returns size of an integer, formatted using Matroska serialization.
12 static int GetUIntMkvSize(uint64 value) { 13 static int GetUIntMkvSize(uint64 value) {
13 if (value < 0x07FULL) 14 if (value < 0x07FULL)
14 return 1; 15 return 1;
15 if (value < 0x03FFFULL) 16 if (value < 0x03FFFULL)
16 return 2; 17 return 2;
(...skipping 30 matching lines...) Expand all
47 } 48 }
48 49
49 static int MasterElementSize(int element_id, int payload_size) { 50 static int MasterElementSize(int element_id, int payload_size) {
50 return GetUIntSize(element_id) + GetUIntMkvSize(payload_size) + payload_size; 51 return GetUIntSize(element_id) + GetUIntMkvSize(payload_size) + payload_size;
51 } 52 }
52 53
53 static int IntElementSize(int element_id, int value) { 54 static int IntElementSize(int element_id, int value) {
54 return GetUIntSize(element_id) + 1 + GetUIntSize(value); 55 return GetUIntSize(element_id) + 1 + GetUIntSize(value);
55 } 56 }
56 57
58 static int DoubleElementSize(int element_id) {
59 return GetUIntSize(element_id) + 1 + 8;
60 }
61
57 static int StringElementSize(int element_id, const std::string& value) { 62 static int StringElementSize(int element_id, const std::string& value) {
58 return GetUIntSize(element_id) + 63 return GetUIntSize(element_id) +
59 GetUIntMkvSize(value.length()) + 64 GetUIntMkvSize(value.length()) +
60 value.length(); 65 value.length();
61 } 66 }
62 67
63 static void SerializeInt(uint8** buf_ptr, int* buf_size_ptr, 68 static void SerializeInt(uint8** buf_ptr, int* buf_size_ptr,
64 int64 value, int size) { 69 int64 value, int size) {
65 uint8*& buf = *buf_ptr; 70 uint8*& buf = *buf_ptr;
66 int& buf_size = *buf_size_ptr; 71 int& buf_size = *buf_size_ptr;
67 72
68 for (int idx = 1; idx <= size; ++idx) { 73 for (int idx = 1; idx <= size; ++idx) {
69 *buf++ = static_cast<uint8>(value >> ((size - idx) * 8)); 74 *buf++ = static_cast<uint8>(value >> ((size - idx) * 8));
70 --buf_size; 75 --buf_size;
71 } 76 }
72 } 77 }
73 78
79 static void SerializeDouble(uint8** buf_ptr, int* buf_size_ptr,
80 double value) {
81 // Use a union to convert |value| to native endian integer bit pattern.
82 union {
83 double src;
84 int64 dst;
85 } tmp;
86 tmp.src = value;
87
88 // Write the bytes from native endian |tmp.dst| to big-endian form in |buf|.
89 SerializeInt(buf_ptr, buf_size_ptr, tmp.dst, 8);
90 }
91
74 static void WriteElementId(uint8** buf, int* buf_size, int element_id) { 92 static void WriteElementId(uint8** buf, int* buf_size, int element_id) {
75 SerializeInt(buf, buf_size, element_id, GetUIntSize(element_id)); 93 SerializeInt(buf, buf_size, element_id, GetUIntSize(element_id));
76 } 94 }
77 95
78 static void WriteUInt(uint8** buf, int* buf_size, uint64 value) { 96 static void WriteUInt(uint8** buf, int* buf_size, uint64 value) {
79 const int size = GetUIntMkvSize(value); 97 const int size = GetUIntMkvSize(value);
80 value |= (1ULL << (size * 7)); // Matroska formatting 98 value |= (1ULL << (size * 7)); // Matroska formatting
81 SerializeInt(buf, buf_size, value, size); 99 SerializeInt(buf, buf_size, value, size);
82 } 100 }
83 101
84 static void WriteMasterElement(uint8** buf, int* buf_size, 102 static void WriteMasterElement(uint8** buf, int* buf_size,
85 int element_id, int payload_size) { 103 int element_id, int payload_size) {
86 WriteElementId(buf, buf_size, element_id); 104 WriteElementId(buf, buf_size, element_id);
87 WriteUInt(buf, buf_size, payload_size); 105 WriteUInt(buf, buf_size, payload_size);
88 } 106 }
89 107
90 static void WriteIntElement(uint8** buf, int* buf_size, 108 static void WriteIntElement(uint8** buf, int* buf_size,
91 int element_id, int value) { 109 int element_id, int value) {
92 WriteElementId(buf, buf_size, element_id); 110 WriteElementId(buf, buf_size, element_id);
93 111
94 const int size = GetUIntSize(value); 112 const int size = GetUIntSize(value);
95 WriteUInt(buf, buf_size, size); 113 WriteUInt(buf, buf_size, size);
96 114
97 SerializeInt(buf, buf_size, value, size); 115 SerializeInt(buf, buf_size, value, size);
98 } 116 }
99 117
118 static void WriteDoubleElement(uint8** buf, int* buf_size,
119 int element_id, double value) {
120 WriteElementId(buf, buf_size, element_id);
121 WriteUInt(buf, buf_size, 8);
122 SerializeDouble(buf, buf_size, value);
123 }
124
100 static void WriteStringElement(uint8** buf_ptr, int* buf_size_ptr, 125 static void WriteStringElement(uint8** buf_ptr, int* buf_size_ptr,
101 int element_id, const std::string& value) { 126 int element_id, const std::string& value) {
102 uint8*& buf = *buf_ptr; 127 uint8*& buf = *buf_ptr;
103 int& buf_size = *buf_size_ptr; 128 int& buf_size = *buf_size_ptr;
104 129
105 WriteElementId(&buf, &buf_size, element_id); 130 WriteElementId(&buf, &buf_size, element_id);
106 131
107 const uint64 size = value.length(); 132 const uint64 size = value.length();
108 WriteUInt(&buf, &buf_size, size); 133 WriteUInt(&buf, &buf_size, size);
109 134
110 memcpy(buf, value.data(), size); 135 memcpy(buf, value.data(), size);
111 buf += size; 136 buf += size;
112 buf_size -= size; 137 buf_size -= size;
113 } 138 }
114 139
115 TracksBuilder::TracksBuilder() {} 140 TracksBuilder::TracksBuilder(bool allow_invalid_values)
141 : allow_invalid_values_(allow_invalid_values) {}
142 TracksBuilder::TracksBuilder()
143 : allow_invalid_values_(false) {}
116 TracksBuilder::~TracksBuilder() {} 144 TracksBuilder::~TracksBuilder() {}
117 145
118 void TracksBuilder::AddTrack( 146 void TracksBuilder::AddVideoTrack(
119 int track_num, 147 int track_num,
120 int track_type, 148 int track_uid,
149 const std::string& codec_id,
150 const std::string& name,
151 const std::string& language,
152 int default_duration,
153 int video_pixel_width,
154 int video_pixel_height) {
155 AddTrackInternal(track_num, kWebMTrackTypeVideo, track_uid, codec_id, name,
156 language, default_duration, video_pixel_width,
157 video_pixel_height, -1, -1);
158 }
159
160 void TracksBuilder::AddAudioTrack(
161 int track_num,
162 int track_uid,
163 const std::string& codec_id,
164 const std::string& name,
165 const std::string& language,
166 int default_duration,
167 int audio_channels,
168 double audio_sampling_frequency) {
169 AddTrackInternal(track_num, kWebMTrackTypeAudio, track_uid, codec_id, name,
170 language, default_duration, -1, -1, audio_channels,
171 audio_sampling_frequency);
172 }
173
174 void TracksBuilder::AddTextTrack(
175 int track_num,
121 int track_uid, 176 int track_uid,
122 const std::string& codec_id, 177 const std::string& codec_id,
123 const std::string& name, 178 const std::string& name,
124 const std::string& language) { 179 const std::string& language) {
125 tracks_.push_back(Track(track_num, track_type, track_uid, codec_id, name, 180 AddTrackInternal(track_num, kWebMTrackTypeSubtitlesOrCaptions, track_uid,
126 language)); 181 codec_id, name, language, -1, -1, -1, -1, -1);
127 } 182 }
128 183
129 std::vector<uint8> TracksBuilder::Finish() { 184 std::vector<uint8> TracksBuilder::Finish() {
130 // Allocate the storage 185 // Allocate the storage
131 std::vector<uint8> buffer; 186 std::vector<uint8> buffer;
132 buffer.resize(GetTracksSize()); 187 buffer.resize(GetTracksSize());
133 188
134 // Populate the storage with a tracks header 189 // Populate the storage with a tracks header
135 WriteTracks(&buffer[0], buffer.size()); 190 WriteTracks(&buffer[0], buffer.size());
136 191
137 return buffer; 192 return buffer;
138 } 193 }
139 194
195 void TracksBuilder::AddTrackInternal(
196 int track_num,
197 int track_type,
198 int track_uid,
199 const std::string& codec_id,
200 const std::string& name,
201 const std::string& language,
202 int default_duration,
203 int video_pixel_width,
204 int video_pixel_height,
205 int audio_channels,
206 double audio_sampling_frequency) {
207 tracks_.push_back(Track(track_num, track_type, track_uid, codec_id, name,
208 language, default_duration, video_pixel_width,
209 video_pixel_height, audio_channels,
210 audio_sampling_frequency, allow_invalid_values_));
211 }
212
140 int TracksBuilder::GetTracksSize() const { 213 int TracksBuilder::GetTracksSize() const {
141 return MasterElementSize(kWebMIdTracks, GetTracksPayloadSize()); 214 return MasterElementSize(kWebMIdTracks, GetTracksPayloadSize());
142 } 215 }
143 216
144 int TracksBuilder::GetTracksPayloadSize() const { 217 int TracksBuilder::GetTracksPayloadSize() const {
145 int payload_size = 0; 218 int payload_size = 0;
146 219
147 for (TrackList::const_iterator itr = tracks_.begin(); 220 for (TrackList::const_iterator itr = tracks_.begin();
148 itr != tracks_.end(); ++itr) { 221 itr != tracks_.end(); ++itr) {
149 payload_size += itr->GetSize(); 222 payload_size += itr->GetSize();
150 } 223 }
151 224
152 return payload_size; 225 return payload_size;
153 } 226 }
154 227
155 void TracksBuilder::WriteTracks(uint8* buf, int buf_size) const { 228 void TracksBuilder::WriteTracks(uint8* buf, int buf_size) const {
156 WriteMasterElement(&buf, &buf_size, kWebMIdTracks, GetTracksPayloadSize()); 229 WriteMasterElement(&buf, &buf_size, kWebMIdTracks, GetTracksPayloadSize());
157 230
158 for (TrackList::const_iterator itr = tracks_.begin(); 231 for (TrackList::const_iterator itr = tracks_.begin();
159 itr != tracks_.end(); ++itr) { 232 itr != tracks_.end(); ++itr) {
160 itr->Write(&buf, &buf_size); 233 itr->Write(&buf, &buf_size);
161 } 234 }
162 } 235 }
163 236
164 TracksBuilder::Track::Track(int track_num, int track_type, int track_uid, 237 TracksBuilder::Track::Track(int track_num, int track_type, int track_uid,
165 const std::string& codec_id, 238 const std::string& codec_id,
166 const std::string& name, 239 const std::string& name,
167 const std::string& language) 240 const std::string& language,
241 int default_duration,
242 int video_pixel_width, int video_pixel_height,
243 int audio_channels, double audio_sampling_frequency,
244 bool allow_invalid_values)
168 : track_num_(track_num), 245 : track_num_(track_num),
169 track_type_(track_type), 246 track_type_(track_type),
170 track_uid_(track_uid), 247 track_uid_(track_uid),
171 codec_id_(codec_id), 248 codec_id_(codec_id),
172 name_(name), 249 name_(name),
173 language_(language) { 250 language_(language),
251 default_duration_(default_duration),
252 video_pixel_width_(video_pixel_width),
253 video_pixel_height_(video_pixel_height),
254 audio_channels_(audio_channels),
255 audio_sampling_frequency_(audio_sampling_frequency) {
256 if (!allow_invalid_values) {
257 CHECK_GT(track_num_, 0);
258 CHECK_GT(track_type_, 0);
259 CHECK_LT(track_type_, 255);
260 CHECK_GT(track_uid_, 0);
261 if (track_type != kWebMTrackTypeVideo &&
262 track_type != kWebMTrackTypeAudio) {
263 CHECK_EQ(default_duration_, -1);
264 } else {
265 CHECK(default_duration_ == -1 || default_duration_ > 0);
266 }
267
268 if (track_type == kWebMTrackTypeVideo) {
269 CHECK_GT(video_pixel_width_, 0);
270 CHECK_GT(video_pixel_height_, 0);
271 } else {
272 CHECK_EQ(video_pixel_width_, -1);
273 CHECK_EQ(video_pixel_height_, -1);
274 }
275
276 if (track_type == kWebMTrackTypeAudio) {
277 CHECK_GT(audio_channels_, 0);
278 CHECK_GT(audio_sampling_frequency_, 0.0);
279 } else {
280 CHECK_EQ(audio_channels_, -1);
281 CHECK_EQ(audio_sampling_frequency_, -1.0);
282 }
283 }
174 } 284 }
175 285
176 int TracksBuilder::Track::GetSize() const { 286 int TracksBuilder::Track::GetSize() const {
177 return MasterElementSize(kWebMIdTrackEntry, GetPayloadSize()); 287 return MasterElementSize(kWebMIdTrackEntry, GetPayloadSize());
178 } 288 }
179 289
290 int TracksBuilder::Track::GetVideoPayloadSize() const {
291 int payload_size = 0;
292
293 if (video_pixel_width_ >= 0)
294 payload_size += IntElementSize(kWebMIdPixelWidth, video_pixel_width_);
295 if (video_pixel_height_ >= 0)
296 payload_size += IntElementSize(kWebMIdPixelHeight, video_pixel_height_);
297
298 return payload_size;
299 }
300
301 int TracksBuilder::Track::GetAudioPayloadSize() const {
302 int payload_size = 0;
303
304 if (audio_channels_ >= 0)
305 payload_size += IntElementSize(kWebMIdChannels, audio_channels_);
306 if (audio_sampling_frequency_ >= 0)
307 payload_size += DoubleElementSize(kWebMIdSamplingFrequency);
308
309 return payload_size;
310 }
311
180 int TracksBuilder::Track::GetPayloadSize() const { 312 int TracksBuilder::Track::GetPayloadSize() const {
181 int size = 0; 313 int size = 0;
182 314
183 size += IntElementSize(kWebMIdTrackNumber, track_num_); 315 size += IntElementSize(kWebMIdTrackNumber, track_num_);
184 size += IntElementSize(kWebMIdTrackType, track_type_); 316 size += IntElementSize(kWebMIdTrackType, track_type_);
185 size += IntElementSize(kWebMIdTrackUID, track_uid_); 317 size += IntElementSize(kWebMIdTrackUID, track_uid_);
186 318
319 if (default_duration_ >= 0)
320 size += IntElementSize(kWebMIdDefaultDuration, default_duration_);
321
187 if (!codec_id_.empty()) 322 if (!codec_id_.empty())
188 size += StringElementSize(kWebMIdCodecID, codec_id_); 323 size += StringElementSize(kWebMIdCodecID, codec_id_);
189 324
190 if (!name_.empty()) 325 if (!name_.empty())
191 size += StringElementSize(kWebMIdName, name_); 326 size += StringElementSize(kWebMIdName, name_);
192 327
193 if (!language_.empty()) 328 if (!language_.empty())
194 size += StringElementSize(kWebMIdLanguage, language_); 329 size += StringElementSize(kWebMIdLanguage, language_);
195 330
331 if (GetVideoPayloadSize() > 0) {
332 size += MasterElementSize(kWebMIdVideo, GetVideoPayloadSize());
333 }
334
335 if (GetAudioPayloadSize() > 0) {
336 size += MasterElementSize(kWebMIdAudio, GetAudioPayloadSize());
337 }
338
196 return size; 339 return size;
197 } 340 }
198 341
199 void TracksBuilder::Track::Write(uint8** buf, int* buf_size) const { 342 void TracksBuilder::Track::Write(uint8** buf, int* buf_size) const {
200 WriteMasterElement(buf, buf_size, kWebMIdTrackEntry, GetPayloadSize()); 343 WriteMasterElement(buf, buf_size, kWebMIdTrackEntry, GetPayloadSize());
201 344
202 WriteIntElement(buf, buf_size, kWebMIdTrackNumber, track_num_); 345 WriteIntElement(buf, buf_size, kWebMIdTrackNumber, track_num_);
203 WriteIntElement(buf, buf_size, kWebMIdTrackType, track_type_); 346 WriteIntElement(buf, buf_size, kWebMIdTrackType, track_type_);
204 WriteIntElement(buf, buf_size, kWebMIdTrackUID, track_uid_); 347 WriteIntElement(buf, buf_size, kWebMIdTrackUID, track_uid_);
205 348
349 if (default_duration_ >= 0)
350 WriteIntElement(buf, buf_size, kWebMIdDefaultDuration, default_duration_);
351
206 if (!codec_id_.empty()) 352 if (!codec_id_.empty())
207 WriteStringElement(buf, buf_size, kWebMIdCodecID, codec_id_); 353 WriteStringElement(buf, buf_size, kWebMIdCodecID, codec_id_);
208 354
209 if (!name_.empty()) 355 if (!name_.empty())
210 WriteStringElement(buf, buf_size, kWebMIdName, name_); 356 WriteStringElement(buf, buf_size, kWebMIdName, name_);
211 357
212 if (!language_.empty()) 358 if (!language_.empty())
213 WriteStringElement(buf, buf_size, kWebMIdLanguage, language_); 359 WriteStringElement(buf, buf_size, kWebMIdLanguage, language_);
360
361 if (GetVideoPayloadSize() > 0) {
362 WriteMasterElement(buf, buf_size, kWebMIdVideo, GetVideoPayloadSize());
363
364 if (video_pixel_width_ >= 0)
365 WriteIntElement(buf, buf_size, kWebMIdPixelWidth, video_pixel_width_);
366
367 if (video_pixel_height_ >= 0)
368 WriteIntElement(buf, buf_size, kWebMIdPixelHeight, video_pixel_height_);
369 }
370
371 if (GetAudioPayloadSize() > 0) {
372 WriteMasterElement(buf, buf_size, kWebMIdAudio, GetAudioPayloadSize());
373
374 if (audio_channels_ >= 0)
375 WriteIntElement(buf, buf_size, kWebMIdChannels, audio_channels_);
376
377 if (audio_sampling_frequency_ >= 0) {
378 WriteDoubleElement(buf, buf_size, kWebMIdSamplingFrequency,
379 audio_sampling_frequency_);
380 }
381 }
214 } 382 }
215 383
216 } // namespace media 384 } // namespace media
OLDNEW
« no previous file with comments | « media/formats/webm/tracks_builder.h ('k') | media/formats/webm/webm_tracks_parser.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698