1 // Copyright (c) 2016 The WebM project authors. All Rights Reserved.
2 //
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
5 // tree. An additional intellectual property rights grant can be found
6 // in the file PATENTS. All contributing project authors may
7 // be found in the AUTHORS file in the root of the source tree.
8 #include <cstdio>
9 #include <cstdlib>
10 #include <iomanip>
11 #include <iostream>
12
13 #include "webm/callback.h"
14 #include "webm/file_reader.h"
15 #include "webm/status.h"
16 #include "webm/webm_parser.h"
17
18 // We use pretty much everything in the webm namespace. Just pull
19 // it all in.
20 using namespace webm; // NOLINT
21
22 template <typename T>
PrintUnknownEnumValue(std::ostream & os,T value)23 std::ostream& PrintUnknownEnumValue(std::ostream& os, T value) {
24 return os << std::to_string(static_cast<std::uint64_t>(value)) << " (?)";
25 }
26
27 // Overloads for operator<< for pretty printing enums.
operator <<(std::ostream & os,Id id)28 std::ostream& operator<<(std::ostream& os, Id id) {
29 switch (id) {
30 case Id::kEbml:
31 return os << "EBML";
32 case Id::kEbmlVersion:
33 return os << "EBMLVersion";
34 case Id::kEbmlReadVersion:
35 return os << "EBMLReadVersion";
36 case Id::kEbmlMaxIdLength:
37 return os << "EBMLMaxIDLength";
38 case Id::kEbmlMaxSizeLength:
39 return os << "EBMLMaxSizeLength";
40 case Id::kDocType:
41 return os << "DocType";
42 case Id::kDocTypeVersion:
43 return os << "DocTypeVersion";
44 case Id::kDocTypeReadVersion:
45 return os << "DocTypeReadVersion";
46 case Id::kVoid:
47 return os << "Void";
48 case Id::kSegment:
49 return os << "Segment";
50 case Id::kSeekHead:
51 return os << "SeekHead";
52 case Id::kSeek:
53 return os << "Seek";
54 case Id::kSeekId:
55 return os << "SeekID";
56 case Id::kSeekPosition:
57 return os << "SeekPosition";
58 case Id::kInfo:
59 return os << "Info";
60 case Id::kTimecodeScale:
61 return os << "TimecodeScale";
62 case Id::kDuration:
63 return os << "Duration";
64 case Id::kDateUtc:
65 return os << "DateUTC";
66 case Id::kTitle:
67 return os << "Title";
68 case Id::kMuxingApp:
69 return os << "MuxingApp";
70 case Id::kWritingApp:
71 return os << "WritingApp";
72 case Id::kCluster:
73 return os << "Cluster";
74 case Id::kTimecode:
75 return os << "Timecode";
76 case Id::kPrevSize:
77 return os << "PrevSize";
78 case Id::kSimpleBlock:
79 return os << "SimpleBlock";
80 case Id::kBlockGroup:
81 return os << "BlockGroup";
82 case Id::kBlock:
83 return os << "Block";
84 case Id::kBlockVirtual:
85 return os << "BlockVirtual";
86 case Id::kBlockAdditions:
87 return os << "BlockAdditions";
88 case Id::kBlockMore:
89 return os << "BlockMore";
90 case Id::kBlockAddId:
91 return os << "BlockAddID";
92 case Id::kBlockAdditional:
93 return os << "BlockAdditional";
94 case Id::kBlockDuration:
95 return os << "BlockDuration";
96 case Id::kReferenceBlock:
97 return os << "ReferenceBlock";
98 case Id::kDiscardPadding:
99 return os << "DiscardPadding";
100 case Id::kSlices:
101 return os << "Slices";
102 case Id::kTimeSlice:
103 return os << "TimeSlice";
104 case Id::kLaceNumber:
105 return os << "LaceNumber";
106 case Id::kTracks:
107 return os << "Tracks";
108 case Id::kTrackEntry:
109 return os << "TrackEntry";
110 case Id::kTrackNumber:
111 return os << "TrackNumber";
112 case Id::kTrackUid:
113 return os << "TrackUID";
114 case Id::kTrackType:
115 return os << "TrackType";
116 case Id::kFlagEnabled:
117 return os << "FlagEnabled";
118 case Id::kFlagDefault:
119 return os << "FlagDefault";
120 case Id::kFlagForced:
121 return os << "FlagForced";
122 case Id::kFlagLacing:
123 return os << "FlagLacing";
124 case Id::kDefaultDuration:
125 return os << "DefaultDuration";
126 case Id::kName:
127 return os << "Name";
128 case Id::kLanguage:
129 return os << "Language";
130 case Id::kCodecId:
131 return os << "CodecID";
132 case Id::kCodecPrivate:
133 return os << "CodecPrivate";
134 case Id::kCodecName:
135 return os << "CodecName";
136 case Id::kCodecDelay:
137 return os << "CodecDelay";
138 case Id::kSeekPreRoll:
139 return os << "SeekPreRoll";
140 case Id::kVideo:
141 return os << "Video";
142 case Id::kFlagInterlaced:
143 return os << "FlagInterlaced";
144 case Id::kStereoMode:
145 return os << "StereoMode";
146 case Id::kAlphaMode:
147 return os << "AlphaMode";
148 case Id::kPixelWidth:
149 return os << "PixelWidth";
150 case Id::kPixelHeight:
151 return os << "PixelHeight";
152 case Id::kPixelCropBottom:
153 return os << "PixelCropBottom";
154 case Id::kPixelCropTop:
155 return os << "PixelCropTop";
156 case Id::kPixelCropLeft:
157 return os << "PixelCropLeft";
158 case Id::kPixelCropRight:
159 return os << "PixelCropRight";
160 case Id::kDisplayWidth:
161 return os << "DisplayWidth";
162 case Id::kDisplayHeight:
163 return os << "DisplayHeight";
164 case Id::kDisplayUnit:
165 return os << "DisplayUnit";
166 case Id::kAspectRatioType:
167 return os << "AspectRatioType";
168 case Id::kFrameRate:
169 return os << "FrameRate";
170 case Id::kColour:
171 return os << "Colour";
172 case Id::kMatrixCoefficients:
173 return os << "MatrixCoefficients";
174 case Id::kBitsPerChannel:
175 return os << "BitsPerChannel";
176 case Id::kChromaSubsamplingHorz:
177 return os << "ChromaSubsamplingHorz";
178 case Id::kChromaSubsamplingVert:
179 return os << "ChromaSubsamplingVert";
180 case Id::kCbSubsamplingHorz:
181 return os << "CbSubsamplingHorz";
182 case Id::kCbSubsamplingVert:
183 return os << "CbSubsamplingVert";
184 case Id::kChromaSitingHorz:
185 return os << "ChromaSitingHorz";
186 case Id::kChromaSitingVert:
187 return os << "ChromaSitingVert";
188 case Id::kRange:
189 return os << "Range";
190 case Id::kTransferCharacteristics:
191 return os << "TransferCharacteristics";
192 case Id::kPrimaries:
193 return os << "Primaries";
194 case Id::kMaxCll:
195 return os << "MaxCLL";
196 case Id::kMaxFall:
197 return os << "MaxFALL";
198 case Id::kMasteringMetadata:
199 return os << "MasteringMetadata";
200 case Id::kPrimaryRChromaticityX:
201 return os << "PrimaryRChromaticityX";
202 case Id::kPrimaryRChromaticityY:
203 return os << "PrimaryRChromaticityY";
204 case Id::kPrimaryGChromaticityX:
205 return os << "PrimaryGChromaticityX";
206 case Id::kPrimaryGChromaticityY:
207 return os << "PrimaryGChromaticityY";
208 case Id::kPrimaryBChromaticityX:
209 return os << "PrimaryBChromaticityX";
210 case Id::kPrimaryBChromaticityY:
211 return os << "PrimaryBChromaticityY";
212 case Id::kWhitePointChromaticityX:
213 return os << "WhitePointChromaticityX";
214 case Id::kWhitePointChromaticityY:
215 return os << "WhitePointChromaticityY";
216 case Id::kLuminanceMax:
217 return os << "LuminanceMax";
218 case Id::kLuminanceMin:
219 return os << "LuminanceMin";
220 case Id::kProjection:
221 return os << "Projection";
222 case Id::kProjectionType:
223 return os << "kProjectionType";
224 case Id::kProjectionPrivate:
225 return os << "kProjectionPrivate";
226 case Id::kProjectionPoseYaw:
227 return os << "kProjectionPoseYaw";
228 case Id::kProjectionPosePitch:
229 return os << "kProjectionPosePitch";
230 case Id::kProjectionPoseRoll:
231 return os << "ProjectionPoseRoll";
232 case Id::kAudio:
233 return os << "Audio";
234 case Id::kSamplingFrequency:
235 return os << "SamplingFrequency";
236 case Id::kOutputSamplingFrequency:
237 return os << "OutputSamplingFrequency";
238 case Id::kChannels:
239 return os << "Channels";
240 case Id::kBitDepth:
241 return os << "BitDepth";
242 case Id::kContentEncodings:
243 return os << "ContentEncodings";
244 case Id::kContentEncoding:
245 return os << "ContentEncoding";
246 case Id::kContentEncodingOrder:
247 return os << "ContentEncodingOrder";
248 case Id::kContentEncodingScope:
249 return os << "ContentEncodingScope";
250 case Id::kContentEncodingType:
251 return os << "ContentEncodingType";
252 case Id::kContentEncryption:
253 return os << "ContentEncryption";
254 case Id::kContentEncAlgo:
255 return os << "ContentEncAlgo";
256 case Id::kContentEncKeyId:
257 return os << "ContentEncKeyID";
258 case Id::kContentEncAesSettings:
259 return os << "ContentEncAESSettings";
260 case Id::kAesSettingsCipherMode:
261 return os << "AESSettingsCipherMode";
262 case Id::kCues:
263 return os << "Cues";
264 case Id::kCuePoint:
265 return os << "CuePoint";
266 case Id::kCueTime:
267 return os << "CueTime";
268 case Id::kCueTrackPositions:
269 return os << "CueTrackPositions";
270 case Id::kCueTrack:
271 return os << "CueTrack";
272 case Id::kCueClusterPosition:
273 return os << "CueClusterPosition";
274 case Id::kCueRelativePosition:
275 return os << "CueRelativePosition";
276 case Id::kCueDuration:
277 return os << "CueDuration";
278 case Id::kCueBlockNumber:
279 return os << "CueBlockNumber";
280 case Id::kChapters:
281 return os << "Chapters";
282 case Id::kEditionEntry:
283 return os << "EditionEntry";
284 case Id::kChapterAtom:
285 return os << "ChapterAtom";
286 case Id::kChapterUid:
287 return os << "ChapterUID";
288 case Id::kChapterStringUid:
289 return os << "ChapterStringUID";
290 case Id::kChapterTimeStart:
291 return os << "ChapterTimeStart";
292 case Id::kChapterTimeEnd:
293 return os << "ChapterTimeEnd";
294 case Id::kChapterDisplay:
295 return os << "ChapterDisplay";
296 case Id::kChapString:
297 return os << "ChapString";
298 case Id::kChapLanguage:
299 return os << "ChapLanguage";
300 case Id::kChapCountry:
301 return os << "ChapCountry";
302 case Id::kTags:
303 return os << "Tags";
304 case Id::kTag:
305 return os << "Tag";
306 case Id::kTargets:
307 return os << "Targets";
308 case Id::kTargetTypeValue:
309 return os << "TargetTypeValue";
310 case Id::kTargetType:
311 return os << "TargetType";
312 case Id::kTagTrackUid:
313 return os << "TagTrackUID";
314 case Id::kSimpleTag:
315 return os << "SimpleTag";
316 case Id::kTagName:
317 return os << "TagName";
318 case Id::kTagLanguage:
319 return os << "TagLanguage";
320 case Id::kTagDefault:
321 return os << "TagDefault";
322 case Id::kTagString:
323 return os << "TagString";
324 case Id::kTagBinary:
325 return os << "TagBinary";
326 default:
327 return PrintUnknownEnumValue(os, id);
328 }
329 }
330
operator <<(std::ostream & os,Lacing value)331 std::ostream& operator<<(std::ostream& os, Lacing value) {
332 switch (value) {
333 case Lacing::kNone:
334 return os << "0 (none)";
335 case Lacing::kXiph:
336 return os << "2 (Xiph)";
337 case Lacing::kFixed:
338 return os << "4 (fixed)";
339 case Lacing::kEbml:
340 return os << "6 (EBML)";
341 default:
342 return PrintUnknownEnumValue(os, value);
343 }
344 }
345
operator <<(std::ostream & os,MatrixCoefficients value)346 std::ostream& operator<<(std::ostream& os, MatrixCoefficients value) {
347 switch (value) {
348 case MatrixCoefficients::kRgb:
349 return os << "0 (identity, RGB/XYZ)";
350 case MatrixCoefficients::kBt709:
351 return os << "1 (Rec. ITU-R BT.709-5)";
352 case MatrixCoefficients::kUnspecified:
353 return os << "2 (unspecified)";
354 case MatrixCoefficients::kFcc:
355 return os << "4 (US FCC)";
356 case MatrixCoefficients::kBt470Bg:
357 return os << "5 (Rec. ITU-R BT.470-6 System B, G)";
358 case MatrixCoefficients::kSmpte170M:
359 return os << "6 (SMPTE 170M)";
360 case MatrixCoefficients::kSmpte240M:
361 return os << "7 (SMPTE 240M)";
362 case MatrixCoefficients::kYCgCo:
363 return os << "8 (YCgCo)";
364 case MatrixCoefficients::kBt2020NonconstantLuminance:
365 return os << "9 (Rec. ITU-R BT.2020, non-constant luma)";
366 case MatrixCoefficients::kBt2020ConstantLuminance:
367 return os << "10 (Rec. ITU-R BT.2020 , constant luma)";
368 default:
369 return PrintUnknownEnumValue(os, value);
370 }
371 }
372
operator <<(std::ostream & os,Range value)373 std::ostream& operator<<(std::ostream& os, Range value) {
374 switch (value) {
375 case Range::kUnspecified:
376 return os << "0 (unspecified)";
377 case Range::kBroadcast:
378 return os << "1 (broadcast)";
379 case Range::kFull:
380 return os << "2 (full)";
381 case Range::kDerived:
382 return os << "3 (defined by MatrixCoefficients/TransferCharacteristics)";
383 default:
384 return PrintUnknownEnumValue(os, value);
385 }
386 }
387
operator <<(std::ostream & os,TransferCharacteristics value)388 std::ostream& operator<<(std::ostream& os, TransferCharacteristics value) {
389 switch (value) {
390 case TransferCharacteristics::kBt709:
391 return os << "1 (Rec. ITU-R BT.709-6)";
392 case TransferCharacteristics::kUnspecified:
393 return os << "2 (unspecified)";
394 case TransferCharacteristics::kGamma22curve:
395 return os << "4 (gamma 2.2, Rec. ITU‑R BT.470‑6 System M)";
396 case TransferCharacteristics::kGamma28curve:
397 return os << "5 (gamma 2.8, Rec. ITU‑R BT.470-6 System B, G)";
398 case TransferCharacteristics::kSmpte170M:
399 return os << "6 (SMPTE 170M)";
400 case TransferCharacteristics::kSmpte240M:
401 return os << "7 (SMPTE 240M)";
402 case TransferCharacteristics::kLinear:
403 return os << "8 (linear)";
404 case TransferCharacteristics::kLog:
405 return os << "9 (log, 100:1 range)";
406 case TransferCharacteristics::kLogSqrt:
407 return os << "10 (log, 316.2:1 range)";
408 case TransferCharacteristics::kIec6196624:
409 return os << "11 (IEC 61966-2-4)";
410 case TransferCharacteristics::kBt1361ExtendedColourGamut:
411 return os << "12 (Rec. ITU-R BT.1361, extended colour gamut)";
412 case TransferCharacteristics::kIec6196621:
413 return os << "13 (IEC 61966-2-1, sRGB or sYCC)";
414 case TransferCharacteristics::k10BitBt2020:
415 return os << "14 (Rec. ITU-R BT.2020-2, 10-bit)";
416 case TransferCharacteristics::k12BitBt2020:
417 return os << "15 (Rec. ITU-R BT.2020-2, 12-bit)";
418 case TransferCharacteristics::kSmpteSt2084:
419 return os << "16 (SMPTE ST 2084)";
420 case TransferCharacteristics::kSmpteSt4281:
421 return os << "17 (SMPTE ST 428-1)";
422 case TransferCharacteristics::kAribStdB67Hlg:
423 return os << "18 (ARIB STD-B67/Rec. ITU-R BT.[HDR-TV] HLG)";
424 default:
425 return PrintUnknownEnumValue(os, value);
426 }
427 }
428
operator <<(std::ostream & os,Primaries value)429 std::ostream& operator<<(std::ostream& os, Primaries value) {
430 switch (value) {
431 case Primaries::kBt709:
432 return os << "1 (Rec. ITU‑R BT.709-6)";
433 case Primaries::kUnspecified:
434 return os << "2 (unspecified)";
435 case Primaries::kBt470M:
436 return os << "4 (Rec. ITU‑R BT.470‑6 System M)";
437 case Primaries::kBt470Bg:
438 return os << "5 (Rec. ITU‑R BT.470‑6 System B, G)";
439 case Primaries::kSmpte170M:
440 return os << "6 (SMPTE 170M)";
441 case Primaries::kSmpte240M:
442 return os << "7 (SMPTE 240M)";
443 case Primaries::kFilm:
444 return os << "8 (generic film)";
445 case Primaries::kBt2020:
446 return os << "9 (Rec. ITU-R BT.2020-2)";
447 case Primaries::kSmpteSt4281:
448 return os << "10 (SMPTE ST 428-1)";
449 case Primaries::kJedecP22Phosphors:
450 return os << "22 (EBU Tech. 3213-E/JEDEC P22 phosphors)";
451 default:
452 return PrintUnknownEnumValue(os, value);
453 }
454 }
455
operator <<(std::ostream & os,ProjectionType value)456 std::ostream& operator<<(std::ostream& os, ProjectionType value) {
457 switch (value) {
458 case ProjectionType::kRectangular:
459 return os << "0 (rectangular)";
460 case ProjectionType::kEquirectangular:
461 return os << "1 (equirectangular)";
462 case ProjectionType::kCubeMap:
463 return os << "2 (cube map)";
464 default:
465 return PrintUnknownEnumValue(os, value);
466 }
467 }
468
operator <<(std::ostream & os,FlagInterlaced value)469 std::ostream& operator<<(std::ostream& os, FlagInterlaced value) {
470 switch (value) {
471 case FlagInterlaced::kUnspecified:
472 return os << "0 (unspecified)";
473 case FlagInterlaced::kInterlaced:
474 return os << "1 (interlaced)";
475 case FlagInterlaced::kProgressive:
476 return os << "2 (progressive)";
477 default:
478 return PrintUnknownEnumValue(os, value);
479 }
480 }
481
operator <<(std::ostream & os,StereoMode value)482 std::ostream& operator<<(std::ostream& os, StereoMode value) {
483 switch (value) {
484 case StereoMode::kMono:
485 return os << "0 (mono)";
486 case StereoMode::kSideBySideLeftFirst:
487 return os << "1 (side-by-side, left eye first)";
488 case StereoMode::kTopBottomRightFirst:
489 return os << "2 (top-bottom, right eye first)";
490 case StereoMode::kTopBottomLeftFirst:
491 return os << "3 (top-bottom, left eye first)";
492 case StereoMode::kCheckboardRightFirst:
493 return os << "4 (checkboard, right eye first)";
494 case StereoMode::kCheckboardLeftFirst:
495 return os << "5 (checkboard, left eye first)";
496 case StereoMode::kRowInterleavedRightFirst:
497 return os << "6 (row interleaved, right eye first)";
498 case StereoMode::kRowInterleavedLeftFirst:
499 return os << "7 (row interleaved, left eye first)";
500 case StereoMode::kColumnInterleavedRightFirst:
501 return os << "8 (column interleaved, right eye first)";
502 case StereoMode::kColumnInterleavedLeftFirst:
503 return os << "9 (column interleaved, left eye first)";
504 case StereoMode::kAnaglyphCyanRed:
505 return os << "10 (anaglyph, cyan/red)";
506 case StereoMode::kSideBySideRightFirst:
507 return os << "11 (side-by-side, right eye first)";
508 case StereoMode::kAnaglyphGreenMagenta:
509 return os << "12 (anaglyph, green/magenta)";
510 case StereoMode::kBlockLacedLeftFirst:
511 return os << "13 (block laced, left eye first)";
512 case StereoMode::kBlockLacedRightFirst:
513 return os << "14 (block laced, right eye first)";
514 default:
515 return PrintUnknownEnumValue(os, value);
516 }
517 }
518
operator <<(std::ostream & os,DisplayUnit value)519 std::ostream& operator<<(std::ostream& os, DisplayUnit value) {
520 switch (value) {
521 case DisplayUnit::kPixels:
522 return os << "0 (pixels)";
523 case DisplayUnit::kCentimeters:
524 return os << "1 (centimeters)";
525 case DisplayUnit::kInches:
526 return os << "2 (inches)";
527 case DisplayUnit::kDisplayAspectRatio:
528 return os << "3 (display aspect ratio)";
529 default:
530 return PrintUnknownEnumValue(os, value);
531 }
532 }
533
operator <<(std::ostream & os,AspectRatioType value)534 std::ostream& operator<<(std::ostream& os, AspectRatioType value) {
535 switch (value) {
536 case AspectRatioType::kFreeResizing:
537 return os << "0 (free resizing)";
538 case AspectRatioType::kKeep:
539 return os << "1 (keep aspect ratio)";
540 case AspectRatioType::kFixed:
541 return os << "2 (fixed)";
542 default:
543 return PrintUnknownEnumValue(os, value);
544 }
545 }
546
operator <<(std::ostream & os,AesSettingsCipherMode value)547 std::ostream& operator<<(std::ostream& os, AesSettingsCipherMode value) {
548 switch (value) {
549 case AesSettingsCipherMode::kCtr:
550 return os << "1 (CTR)";
551 default:
552 return PrintUnknownEnumValue(os, value);
553 }
554 }
555
operator <<(std::ostream & os,ContentEncAlgo value)556 std::ostream& operator<<(std::ostream& os, ContentEncAlgo value) {
557 switch (value) {
558 case ContentEncAlgo::kOnlySigned:
559 return os << "0 (only signed, not encrypted)";
560 case ContentEncAlgo::kDes:
561 return os << "1 (DES)";
562 case ContentEncAlgo::k3Des:
563 return os << "2 (3DES)";
564 case ContentEncAlgo::kTwofish:
565 return os << "3 (Twofish)";
566 case ContentEncAlgo::kBlowfish:
567 return os << "4 (Blowfish)";
568 case ContentEncAlgo::kAes:
569 return os << "5 (AES)";
570 default:
571 return PrintUnknownEnumValue(os, value);
572 }
573 }
574
operator <<(std::ostream & os,ContentEncodingType value)575 std::ostream& operator<<(std::ostream& os, ContentEncodingType value) {
576 switch (value) {
577 case ContentEncodingType::kCompression:
578 return os << "0 (compression)";
579 case ContentEncodingType::kEncryption:
580 return os << "1 (encryption)";
581 default:
582 return PrintUnknownEnumValue(os, value);
583 }
584 }
585
operator <<(std::ostream & os,TrackType value)586 std::ostream& operator<<(std::ostream& os, TrackType value) {
587 switch (value) {
588 case TrackType::kVideo:
589 return os << "1 (video)";
590 case TrackType::kAudio:
591 return os << "2 (audio)";
592 case TrackType::kComplex:
593 return os << "3 (complex)";
594 case TrackType::kLogo:
595 return os << "16 (logo)";
596 case TrackType::kSubtitle:
597 return os << "17 (subtitle)";
598 case TrackType::kButtons:
599 return os << "18 (buttons)";
600 case TrackType::kControl:
601 return os << "32 (control)";
602 default:
603 return PrintUnknownEnumValue(os, value);
604 }
605 }
606
607 // For binary elements, just print out its size.
operator <<(std::ostream & os,const std::vector<std::uint8_t> & value)608 std::ostream& operator<<(std::ostream& os,
609 const std::vector<std::uint8_t>& value) {
610 return os << '<' << value.size() << " bytes>";
611 }
612
613 class DemoCallback : public Callback {
614 public:
615 int indent = 0;
616 int spaces_per_indent = 2;
617
PrintElementMetadata(const std::string & name,const ElementMetadata & metadata)618 void PrintElementMetadata(const std::string& name,
619 const ElementMetadata& metadata) {
620 // Since we aren't doing any seeking in this demo, we don't have to worry
621 // about kUnknownHeaderSize or kUnknownElementPosition when adding the
622 // position and sizes.
623 const std::uint64_t header_start = metadata.position;
624 const std::uint64_t header_end = header_start + metadata.header_size;
625 const std::uint64_t body_start = header_end;
626 std::cout << std::string(indent * spaces_per_indent, ' ') << name;
627 // The ContentEncAESSettings element has the longest name (out of all other
628 // master elements) at 21 characters. It's also the deepest master element
629 // at a level of 6. Insert enough whitespace so there's room for it.
630 std::cout << std::string(21 + 6 * spaces_per_indent -
631 indent * spaces_per_indent - name.size(),
632 ' ')
633 << " header: [" << header_start << ", " << header_end
634 << ") body: [" << body_start << ", ";
635 if (metadata.size != kUnknownElementSize) {
636 const std::uint64_t body_end = body_start + metadata.size;
637 std::cout << body_end;
638 } else {
639 std::cout << '?';
640 }
641 std::cout << ")\n";
642 }
643
644 template <typename T>
PrintMandatoryElement(const std::string & name,const Element<T> & element)645 void PrintMandatoryElement(const std::string& name,
646 const Element<T>& element) {
647 std::cout << std::string(indent * spaces_per_indent, ' ') << name;
648 if (!element.is_present()) {
649 std::cout << " (implicit)";
650 }
651 std::cout << ": " << element.value() << '\n';
652 }
653
654 template <typename T>
PrintMandatoryElement(const std::string & name,const std::vector<Element<T>> & elements)655 void PrintMandatoryElement(const std::string& name,
656 const std::vector<Element<T>>& elements) {
657 for (const Element<T>& element : elements) {
658 PrintMandatoryElement(name, element);
659 }
660 }
661
662 template <typename T>
PrintOptionalElement(const std::string & name,const Element<T> & element)663 void PrintOptionalElement(const std::string& name,
664 const Element<T>& element) {
665 if (element.is_present()) {
666 std::cout << std::string(indent * spaces_per_indent, ' ') << name << ": "
667 << element.value() << '\n';
668 }
669 }
670
671 template <typename T>
PrintOptionalElement(const std::string & name,const std::vector<Element<T>> & elements)672 void PrintOptionalElement(const std::string& name,
673 const std::vector<Element<T>>& elements) {
674 for (const Element<T>& element : elements) {
675 PrintOptionalElement(name, element);
676 }
677 }
678
PrintMasterElement(const BlockAdditions & block_additions)679 void PrintMasterElement(const BlockAdditions& block_additions) {
680 PrintMasterElement("BlockMore", block_additions.block_mores);
681 }
682
PrintMasterElement(const BlockMore & block_more)683 void PrintMasterElement(const BlockMore& block_more) {
684 PrintMandatoryElement("BlockAddID", block_more.id);
685 PrintMandatoryElement("BlockAdditional", block_more.data);
686 }
687
PrintMasterElement(const Slices & slices)688 void PrintMasterElement(const Slices& slices) {
689 PrintMasterElement("TimeSlice", slices.slices);
690 }
691
PrintMasterElement(const TimeSlice & time_slice)692 void PrintMasterElement(const TimeSlice& time_slice) {
693 PrintOptionalElement("LaceNumber", time_slice.lace_number);
694 }
695
PrintMasterElement(const Video & video)696 void PrintMasterElement(const Video& video) {
697 PrintMandatoryElement("FlagInterlaced", video.interlaced);
698 PrintOptionalElement("StereoMode", video.stereo_mode);
699 PrintOptionalElement("AlphaMode", video.alpha_mode);
700 PrintMandatoryElement("PixelWidth", video.pixel_width);
701 PrintMandatoryElement("PixelHeight", video.pixel_height);
702 PrintOptionalElement("PixelCropBottom", video.pixel_crop_bottom);
703 PrintOptionalElement("PixelCropTop", video.pixel_crop_top);
704 PrintOptionalElement("PixelCropLeft", video.pixel_crop_left);
705 PrintOptionalElement("PixelCropRight", video.pixel_crop_right);
706 PrintOptionalElement("DisplayWidth", video.display_width);
707 PrintOptionalElement("DisplayHeight", video.display_height);
708 PrintOptionalElement("DisplayUnit", video.display_unit);
709 PrintOptionalElement("AspectRatioType", video.aspect_ratio_type);
710 PrintOptionalElement("FrameRate", video.frame_rate);
711 PrintMasterElement("Colour", video.colour);
712 PrintMasterElement("Projection", video.projection);
713 }
714
PrintMasterElement(const Colour & colour)715 void PrintMasterElement(const Colour& colour) {
716 PrintOptionalElement("MatrixCoefficients", colour.matrix_coefficients);
717 PrintOptionalElement("BitsPerChannel", colour.bits_per_channel);
718 PrintOptionalElement("ChromaSubsamplingHorz", colour.chroma_subsampling_x);
719 PrintOptionalElement("ChromaSubsamplingVert", colour.chroma_subsampling_y);
720 PrintOptionalElement("CbSubsamplingHorz", colour.cb_subsampling_x);
721 PrintOptionalElement("CbSubsamplingVert", colour.cb_subsampling_y);
722 PrintOptionalElement("ChromaSitingHorz", colour.chroma_siting_x);
723 PrintOptionalElement("ChromaSitingVert", colour.chroma_siting_y);
724 PrintOptionalElement("Range", colour.range);
725 PrintOptionalElement("TransferCharacteristics",
726 colour.transfer_characteristics);
727 PrintOptionalElement("Primaries", colour.primaries);
728 PrintOptionalElement("MaxCLL", colour.max_cll);
729 PrintOptionalElement("MaxFALL", colour.max_fall);
730 PrintMasterElement("MasteringMetadata", colour.mastering_metadata);
731 }
732
PrintMasterElement(const MasteringMetadata & mastering_metadata)733 void PrintMasterElement(const MasteringMetadata& mastering_metadata) {
734 PrintOptionalElement("PrimaryRChromaticityX",
735 mastering_metadata.primary_r_chromaticity_x);
736 PrintOptionalElement("PrimaryRChromaticityY",
737 mastering_metadata.primary_r_chromaticity_y);
738 PrintOptionalElement("PrimaryGChromaticityX",
739 mastering_metadata.primary_g_chromaticity_x);
740 PrintOptionalElement("PrimaryGChromaticityY",
741 mastering_metadata.primary_g_chromaticity_y);
742 PrintOptionalElement("PrimaryBChromaticityX",
743 mastering_metadata.primary_b_chromaticity_x);
744 PrintOptionalElement("PrimaryBChromaticityY",
745 mastering_metadata.primary_b_chromaticity_y);
746 PrintOptionalElement("WhitePointChromaticityX",
747 mastering_metadata.white_point_chromaticity_x);
748 PrintOptionalElement("WhitePointChromaticityY",
749 mastering_metadata.white_point_chromaticity_y);
750 PrintOptionalElement("LuminanceMax", mastering_metadata.luminance_max);
751 PrintOptionalElement("LuminanceMin", mastering_metadata.luminance_min);
752 }
753
PrintMasterElement(const Projection & projection)754 void PrintMasterElement(const Projection& projection) {
755 PrintMandatoryElement("ProjectionType", projection.type);
756 PrintOptionalElement("ProjectionPrivate", projection.projection_private);
757 PrintMandatoryElement("ProjectionPoseYaw", projection.pose_yaw);
758 PrintMandatoryElement("ProjectionPosePitch", projection.pose_pitch);
759 PrintMandatoryElement("ProjectionPoseRoll", projection.pose_roll);
760 }
761
PrintMasterElement(const Audio & audio)762 void PrintMasterElement(const Audio& audio) {
763 PrintMandatoryElement("SamplingFrequency", audio.sampling_frequency);
764 PrintOptionalElement("OutputSamplingFrequency", audio.output_frequency);
765 PrintMandatoryElement("Channels", audio.channels);
766 PrintOptionalElement("BitDepth", audio.bit_depth);
767 }
768
PrintMasterElement(const ContentEncodings & content_encodings)769 void PrintMasterElement(const ContentEncodings& content_encodings) {
770 PrintMasterElement("ContentEncoding", content_encodings.encodings);
771 }
772
PrintMasterElement(const ContentEncoding & content_encoding)773 void PrintMasterElement(const ContentEncoding& content_encoding) {
774 PrintMandatoryElement("ContentEncodingOrder", content_encoding.order);
775 PrintMandatoryElement("ContentEncodingScope", content_encoding.scope);
776 PrintMandatoryElement("ContentEncodingType", content_encoding.type);
777 PrintMasterElement("ContentEncryption", content_encoding.encryption);
778 }
779
PrintMasterElement(const ContentEncryption & content_encryption)780 void PrintMasterElement(const ContentEncryption& content_encryption) {
781 PrintOptionalElement("ContentEncAlgo", content_encryption.algorithm);
782 PrintOptionalElement("ContentEncKeyID", content_encryption.key_id);
783 PrintMasterElement("ContentEncAESSettings",
784 content_encryption.aes_settings);
785 }
786
PrintMasterElement(const ContentEncAesSettings & content_enc_aes_settings)787 void PrintMasterElement(
788 const ContentEncAesSettings& content_enc_aes_settings) {
789 PrintMandatoryElement("AESSettingsCipherMode",
790 content_enc_aes_settings.aes_settings_cipher_mode);
791 }
792
PrintMasterElement(const CueTrackPositions & cue_track_positions)793 void PrintMasterElement(const CueTrackPositions& cue_track_positions) {
794 PrintMandatoryElement("CueTrack", cue_track_positions.track);
795 PrintMandatoryElement("CueClusterPosition",
796 cue_track_positions.cluster_position);
797 PrintOptionalElement("CueRelativePosition",
798 cue_track_positions.relative_position);
799 PrintOptionalElement("CueDuration", cue_track_positions.duration);
800 PrintOptionalElement("CueBlockNumber", cue_track_positions.block_number);
801 }
802
PrintMasterElement(const ChapterAtom & chapter_atom)803 void PrintMasterElement(const ChapterAtom& chapter_atom) {
804 PrintMandatoryElement("ChapterUID", chapter_atom.uid);
805 PrintOptionalElement("ChapterStringUID", chapter_atom.string_uid);
806 PrintMandatoryElement("ChapterTimeStart", chapter_atom.time_start);
807 PrintOptionalElement("ChapterTimeEnd", chapter_atom.time_end);
808 PrintMasterElement("ChapterDisplay", chapter_atom.displays);
809 PrintMasterElement("ChapterAtom", chapter_atom.atoms);
810 }
811
PrintMasterElement(const ChapterDisplay & chapter_display)812 void PrintMasterElement(const ChapterDisplay& chapter_display) {
813 PrintMandatoryElement("ChapString", chapter_display.string);
814 PrintMandatoryElement("ChapLanguage", chapter_display.languages);
815 PrintOptionalElement("ChapCountry", chapter_display.countries);
816 }
817
PrintMasterElement(const Targets & targets)818 void PrintMasterElement(const Targets& targets) {
819 PrintOptionalElement("TargetTypeValue", targets.type_value);
820 PrintOptionalElement("TargetType", targets.type);
821 PrintMandatoryElement("TagTrackUID", targets.track_uids);
822 }
823
PrintMasterElement(const SimpleTag & simple_tag)824 void PrintMasterElement(const SimpleTag& simple_tag) {
825 PrintMandatoryElement("TagName", simple_tag.name);
826 PrintMandatoryElement("TagLanguage", simple_tag.language);
827 PrintMandatoryElement("TagDefault", simple_tag.is_default);
828 PrintOptionalElement("TagString", simple_tag.string);
829 PrintOptionalElement("TagBinary", simple_tag.binary);
830 PrintMasterElement("SimpleTag", simple_tag.tags);
831 }
832
833 // When printing a master element that's wrapped in Element<>, peel off the
834 // Element<> wrapper and print the underlying master element if it's present.
835 template <typename T>
PrintMasterElement(const std::string & name,const Element<T> & element)836 void PrintMasterElement(const std::string& name, const Element<T>& element) {
837 if (element.is_present()) {
838 std::cout << std::string(indent * spaces_per_indent, ' ') << name << "\n";
839 ++indent;
840 PrintMasterElement(element.value());
841 --indent;
842 }
843 }
844
845 template <typename T>
PrintMasterElement(const std::string & name,const std::vector<Element<T>> & elements)846 void PrintMasterElement(const std::string& name,
847 const std::vector<Element<T>>& elements) {
848 for (const Element<T>& element : elements) {
849 PrintMasterElement(name, element);
850 }
851 }
852
853 template <typename T>
PrintValue(const std::string & name,const T & value)854 void PrintValue(const std::string& name, const T& value) {
855 std::cout << std::string(indent * spaces_per_indent, ' ') << name << ": "
856 << value << '\n';
857 }
858
OnElementBegin(const ElementMetadata & metadata,Action * action)859 Status OnElementBegin(const ElementMetadata& metadata,
860 Action* action) override {
861 // Print out metadata for some level 1 elements that don't have explicit
862 // callbacks.
863 switch (metadata.id) {
864 case Id::kSeekHead:
865 indent = 1;
866 PrintElementMetadata("SeekHead", metadata);
867 break;
868 case Id::kTracks:
869 indent = 1;
870 PrintElementMetadata("Tracks", metadata);
871 break;
872 case Id::kCues:
873 indent = 1;
874 PrintElementMetadata("Cues", metadata);
875 break;
876 case Id::kChapters:
877 indent = 1;
878 PrintElementMetadata("Chapters", metadata);
879 break;
880 case Id::kTags:
881 indent = 1;
882 PrintElementMetadata("Tags", metadata);
883 break;
884 default:
885 break;
886 }
887
888 *action = Action::kRead;
889 return Status(Status::kOkCompleted);
890 }
891
OnUnknownElement(const ElementMetadata & metadata,Reader * reader,std::uint64_t * bytes_remaining)892 Status OnUnknownElement(const ElementMetadata& metadata, Reader* reader,
893 std::uint64_t* bytes_remaining) override {
894 // Output unknown elements without any indentation because we aren't
895 // tracking which element contains them.
896 int original_indent = indent;
897 indent = 0;
898 PrintElementMetadata("UNKNOWN_ELEMENT!", metadata);
899 indent = original_indent;
900 // The base class's implementation will just skip the element via
901 // Reader::Skip().
902 return Callback::OnUnknownElement(metadata, reader, bytes_remaining);
903 }
904
OnEbml(const ElementMetadata & metadata,const Ebml & ebml)905 Status OnEbml(const ElementMetadata& metadata, const Ebml& ebml) override {
906 indent = 0;
907 PrintElementMetadata("EBML", metadata);
908 indent = 1;
909 PrintMandatoryElement("EBMLVersion", ebml.ebml_version);
910 PrintMandatoryElement("EBMLReadVersion", ebml.ebml_read_version);
911 PrintMandatoryElement("EBMLMaxIDLength", ebml.ebml_max_id_length);
912 PrintMandatoryElement("EBMLMaxSizeLength", ebml.ebml_max_size_length);
913 PrintMandatoryElement("DocType", ebml.doc_type);
914 PrintMandatoryElement("DocTypeVersion", ebml.doc_type_version);
915 PrintMandatoryElement("DocTypeReadVersion", ebml.doc_type_read_version);
916 return Status(Status::kOkCompleted);
917 }
918
OnVoid(const ElementMetadata & metadata,Reader * reader,std::uint64_t * bytes_remaining)919 Status OnVoid(const ElementMetadata& metadata, Reader* reader,
920 std::uint64_t* bytes_remaining) override {
921 // Output Void elements without any indentation because we aren't tracking
922 // which element contains them.
923 int original_indent = indent;
924 indent = 0;
925 PrintElementMetadata("Void", metadata);
926 indent = original_indent;
927 // The base class's implementation will just skip the element via
928 // Reader::Skip().
929 return Callback::OnVoid(metadata, reader, bytes_remaining);
930 }
931
OnSegmentBegin(const ElementMetadata & metadata,Action * action)932 Status OnSegmentBegin(const ElementMetadata& metadata,
933 Action* action) override {
934 indent = 0;
935 PrintElementMetadata("Segment", metadata);
936 indent = 1;
937 *action = Action::kRead;
938 return Status(Status::kOkCompleted);
939 }
940
OnSeek(const ElementMetadata & metadata,const Seek & seek)941 Status OnSeek(const ElementMetadata& metadata, const Seek& seek) override {
942 indent = 2;
943 PrintElementMetadata("Seek", metadata);
944 indent = 3;
945 PrintMandatoryElement("SeekID", seek.id);
946 PrintMandatoryElement("SeekPosition", seek.position);
947 return Status(Status::kOkCompleted);
948 }
949
OnInfo(const ElementMetadata & metadata,const Info & info)950 Status OnInfo(const ElementMetadata& metadata, const Info& info) override {
951 indent = 1;
952 PrintElementMetadata("Info", metadata);
953 indent = 2;
954 PrintMandatoryElement("TimecodeScale", info.timecode_scale);
955 PrintOptionalElement("Duration", info.duration);
956 PrintOptionalElement("DateUTC", info.date_utc);
957 PrintOptionalElement("Title", info.title);
958 PrintOptionalElement("MuxingApp", info.muxing_app);
959 PrintOptionalElement("WritingApp", info.writing_app);
960 return Status(Status::kOkCompleted);
961 }
962
OnClusterBegin(const ElementMetadata & metadata,const Cluster & cluster,Action * action)963 Status OnClusterBegin(const ElementMetadata& metadata, const Cluster& cluster,
964 Action* action) override {
965 indent = 1;
966 PrintElementMetadata("Cluster", metadata);
967 // A properly muxed file will have Timecode and PrevSize first before any
968 // SimpleBlock or BlockGroups. The parser takes advantage of this and delays
969 // calling OnClusterBegin() until it hits the first SimpleBlock or
970 // BlockGroup child (or the Cluster ends if it's empty). It's possible for
971 // an improperly muxed file to have Timecode or PrevSize after the first
972 // block, in which case they'll be absent here and may be accessed in
973 // OnClusterEnd() when the Cluster and all its children have been fully
974 // parsed. In this demo we assume the file has been properly muxed.
975 indent = 2;
976 PrintMandatoryElement("Timecode", cluster.timecode);
977 PrintOptionalElement("PrevSize", cluster.previous_size);
978 *action = Action::kRead;
979 return Status(Status::kOkCompleted);
980 }
981
OnSimpleBlockBegin(const ElementMetadata & metadata,const SimpleBlock & simple_block,Action * action)982 Status OnSimpleBlockBegin(const ElementMetadata& metadata,
983 const SimpleBlock& simple_block,
984 Action* action) override {
985 indent = 2;
986 PrintElementMetadata("SimpleBlock", metadata);
987 indent = 3;
988 PrintValue("track number", simple_block.track_number);
989 PrintValue("frames", simple_block.num_frames);
990 PrintValue("timecode", simple_block.timecode);
991 PrintValue("lacing", simple_block.lacing);
992 std::string flags = (simple_block.is_visible) ? "visible" : "invisible";
993 if (simple_block.is_key_frame)
994 flags += ", key frame";
995 if (simple_block.is_discardable)
996 flags += ", discardable";
997 PrintValue("flags", flags);
998 *action = Action::kRead;
999 return Status(Status::kOkCompleted);
1000 }
1001
OnSimpleBlockEnd(const ElementMetadata &,const SimpleBlock &)1002 Status OnSimpleBlockEnd(const ElementMetadata& /* metadata */,
1003 const SimpleBlock& /* simple_block */) override {
1004 return Status(Status::kOkCompleted);
1005 }
1006
OnBlockGroupBegin(const ElementMetadata & metadata,Action * action)1007 Status OnBlockGroupBegin(const ElementMetadata& metadata,
1008 Action* action) override {
1009 indent = 2;
1010 PrintElementMetadata("BlockGroup", metadata);
1011 *action = Action::kRead;
1012 return Status(Status::kOkCompleted);
1013 }
1014
OnBlockBegin(const ElementMetadata & metadata,const Block & block,Action * action)1015 Status OnBlockBegin(const ElementMetadata& metadata, const Block& block,
1016 Action* action) override {
1017 indent = 3;
1018 PrintElementMetadata("Block", metadata);
1019 indent = 4;
1020 PrintValue("track number", block.track_number);
1021 PrintValue("frames", block.num_frames);
1022 PrintValue("timecode", block.timecode);
1023 PrintValue("lacing", block.lacing);
1024 PrintValue("flags", (block.is_visible) ? "visible" : "invisible");
1025 *action = Action::kRead;
1026 return Status(Status::kOkCompleted);
1027 }
1028
OnBlockEnd(const ElementMetadata &,const Block &)1029 Status OnBlockEnd(const ElementMetadata& /* metadata */,
1030 const Block& /* block */) override {
1031 return Status(Status::kOkCompleted);
1032 }
1033
OnBlockGroupEnd(const ElementMetadata &,const BlockGroup & block_group)1034 Status OnBlockGroupEnd(const ElementMetadata& /* metadata */,
1035 const BlockGroup& block_group) override {
1036 if (block_group.virtual_block.is_present()) {
1037 std::cout << std::string(indent * spaces_per_indent, ' ')
1038 << "BlockVirtual\n";
1039 indent = 4;
1040 PrintValue("track number",
1041 block_group.virtual_block.value().track_number);
1042 PrintValue("timecode", block_group.virtual_block.value().timecode);
1043 }
1044 indent = 3;
1045 PrintMasterElement("BlockAdditions", block_group.additions);
1046 PrintOptionalElement("BlockDuration", block_group.duration);
1047 PrintOptionalElement("ReferenceBlock", block_group.references);
1048 PrintOptionalElement("DiscardPadding", block_group.discard_padding);
1049 PrintMasterElement("Slices", block_group.slices);
1050 // BlockGroup::block has been set, but we've already printed it in
1051 // OnBlockBegin().
1052 return Status(Status::kOkCompleted);
1053 }
1054
OnFrame(const FrameMetadata & metadata,Reader * reader,std::uint64_t * bytes_remaining)1055 Status OnFrame(const FrameMetadata& metadata, Reader* reader,
1056 std::uint64_t* bytes_remaining) override {
1057 PrintValue("frame byte range",
1058 '[' + std::to_string(metadata.position) + ", " +
1059 std::to_string(metadata.position + metadata.size) + ')');
1060 // The base class's implementation will just skip the frame via
1061 // Reader::Skip().
1062 return Callback::OnFrame(metadata, reader, bytes_remaining);
1063 }
1064
OnClusterEnd(const ElementMetadata &,const Cluster &)1065 Status OnClusterEnd(const ElementMetadata& /* metadata */,
1066 const Cluster& /* cluster */) override {
1067 // The Cluster and all its children have been fully parsed at this point. If
1068 // the file wasn't properly muxed and Timecode or PrevSize were missing in
1069 // OnClusterBegin(), they'll be set here (if the Cluster contained them). In
1070 // this demo we already handled them, though.
1071 return Status(Status::kOkCompleted);
1072 }
1073
OnTrackEntry(const ElementMetadata & metadata,const TrackEntry & track_entry)1074 Status OnTrackEntry(const ElementMetadata& metadata,
1075 const TrackEntry& track_entry) override {
1076 indent = 2;
1077 PrintElementMetadata("TrackEntry", metadata);
1078 indent = 3;
1079 PrintMandatoryElement("TrackNumber", track_entry.track_number);
1080 PrintMandatoryElement("TrackUID", track_entry.track_uid);
1081 PrintMandatoryElement("TrackType", track_entry.track_type);
1082 PrintMandatoryElement("FlagEnabled", track_entry.is_enabled);
1083 PrintMandatoryElement("FlagDefault", track_entry.is_default);
1084 PrintMandatoryElement("FlagForced", track_entry.is_forced);
1085 PrintMandatoryElement("FlagLacing", track_entry.uses_lacing);
1086 PrintOptionalElement("DefaultDuration", track_entry.default_duration);
1087 PrintOptionalElement("Name", track_entry.name);
1088 PrintOptionalElement("Language", track_entry.language);
1089 PrintMandatoryElement("CodecID", track_entry.codec_id);
1090 PrintOptionalElement("CodecPrivate", track_entry.codec_private);
1091 PrintOptionalElement("CodecName", track_entry.codec_name);
1092 PrintOptionalElement("CodecDelay", track_entry.codec_delay);
1093 PrintMandatoryElement("SeekPreRoll", track_entry.seek_pre_roll);
1094 PrintMasterElement("Video", track_entry.video);
1095 PrintMasterElement("Audio", track_entry.audio);
1096 PrintMasterElement("ContentEncodings", track_entry.content_encodings);
1097 return Status(Status::kOkCompleted);
1098 }
1099
OnCuePoint(const ElementMetadata & metadata,const CuePoint & cue_point)1100 Status OnCuePoint(const ElementMetadata& metadata,
1101 const CuePoint& cue_point) override {
1102 indent = 2;
1103 PrintElementMetadata("CuePoint", metadata);
1104 indent = 3;
1105 PrintMandatoryElement("CueTime", cue_point.time);
1106 PrintMasterElement("CueTrackPositions", cue_point.cue_track_positions);
1107 return Status(Status::kOkCompleted);
1108 }
1109
OnEditionEntry(const ElementMetadata & metadata,const EditionEntry & edition_entry)1110 Status OnEditionEntry(const ElementMetadata& metadata,
1111 const EditionEntry& edition_entry) override {
1112 indent = 2;
1113 PrintElementMetadata("EditionEntry", metadata);
1114 indent = 3;
1115 PrintMasterElement("ChapterAtom", edition_entry.atoms);
1116 return Status(Status::kOkCompleted);
1117 }
1118
OnTag(const ElementMetadata & metadata,const Tag & tag)1119 Status OnTag(const ElementMetadata& metadata, const Tag& tag) override {
1120 indent = 2;
1121 PrintElementMetadata("Tag", metadata);
1122 indent = 3;
1123 PrintMasterElement("Targets", tag.targets);
1124 PrintMasterElement("SimpleTag", tag.tags);
1125 return Status(Status::kOkCompleted);
1126 }
1127
OnSegmentEnd(const ElementMetadata &)1128 Status OnSegmentEnd(const ElementMetadata& /* metadata */) override {
1129 return Status(Status::kOkCompleted);
1130 }
1131 };
1132
main(int argc,char * argv[])1133 int main(int argc, char* argv[]) {
1134 if ((argc != 1 && argc != 2) ||
1135 (argc == 2 && argv[1] == std::string("--help"))) {
1136 std::cerr << "Usage:\n"
1137 << argv[0] << " [path-to-webm-file]\n\n"
1138 << "Prints info for the WebM file specified in the command line. "
1139 "If no file is\n"
1140 << "specified, stdin is used as input.\n";
1141 return EXIT_FAILURE;
1142 }
1143
1144 FILE* file = (argc == 2) ? std::fopen(argv[1], "rb")
1145 : std::freopen(nullptr, "rb", stdin);
1146 if (!file) {
1147 std::cerr << "File cannot be opened\n";
1148 return EXIT_FAILURE;
1149 }
1150
1151 FileReader reader(file);
1152 DemoCallback callback;
1153 WebmParser parser;
1154 Status status = parser.Feed(&callback, &reader);
1155 if (!status.completed_ok()) {
1156 std::cerr << "Parsing error; status code: " << status.code << '\n';
1157 return EXIT_FAILURE;
1158 }
1159
1160 return 0;
1161 }
1162