xref: /aosp_15_r20/external/libwebm/webm_parser/demo/demo.cc (revision 103e46e4cd4b6efcf6001f23fa8665fb110abf8d)
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