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 #ifndef SRC_VIDEO_PARSER_H_
9 #define SRC_VIDEO_PARSER_H_
10 
11 #include <cassert>
12 #include <cstdint>
13 
14 #include "src/bool_parser.h"
15 #include "src/colour_parser.h"
16 #include "src/float_parser.h"
17 #include "src/int_parser.h"
18 #include "src/master_value_parser.h"
19 #include "src/projection_parser.h"
20 #include "webm/callback.h"
21 #include "webm/dom_types.h"
22 #include "webm/id.h"
23 #include "webm/reader.h"
24 #include "webm/status.h"
25 
26 namespace webm {
27 
28 // Spec reference:
29 // http://matroska.org/technical/specs/index.html#Video
30 // http://www.webmproject.org/docs/container/#Video
31 class VideoParser : public MasterValueParser<Video> {
32  public:
VideoParser()33   VideoParser()
34       : MasterValueParser<Video>(
35             MakeChild<IntParser<FlagInterlaced>>(Id::kFlagInterlaced,
36                                                  &Video::interlaced),
37             MakeChild<IntParser<StereoMode>>(Id::kStereoMode,
38                                              &Video::stereo_mode),
39             MakeChild<UnsignedIntParser>(Id::kAlphaMode, &Video::alpha_mode),
40             MakeChild<UnsignedIntParser>(Id::kPixelWidth, &Video::pixel_width),
41             MakeChild<UnsignedIntParser>(Id::kPixelHeight,
42                                          &Video::pixel_height),
43             MakeChild<UnsignedIntParser>(Id::kPixelCropBottom,
44                                          &Video::pixel_crop_bottom),
45             MakeChild<UnsignedIntParser>(Id::kPixelCropTop,
46                                          &Video::pixel_crop_top),
47             MakeChild<UnsignedIntParser>(Id::kPixelCropLeft,
48                                          &Video::pixel_crop_left),
49             MakeChild<UnsignedIntParser>(Id::kPixelCropRight,
50                                          &Video::pixel_crop_right),
51             MakeChild<UnsignedIntParser>(Id::kDisplayWidth,
52                                          &Video::display_width)
53                 .NotifyOnParseComplete(),
54             MakeChild<UnsignedIntParser>(Id::kDisplayHeight,
55                                          &Video::display_height)
56                 .NotifyOnParseComplete(),
57             MakeChild<IntParser<DisplayUnit>>(Id::kDisplayUnit,
58                                               &Video::display_unit),
59             MakeChild<IntParser<AspectRatioType>>(Id::kAspectRatioType,
60                                                   &Video::aspect_ratio_type),
61             MakeChild<FloatParser>(Id::kFrameRate, &Video::frame_rate),
62             MakeChild<ColourParser>(Id::kColour, &Video::colour),
63             MakeChild<ProjectionParser>(Id::kProjection, &Video::projection)) {}
64 
Init(const ElementMetadata & metadata,std::uint64_t max_size)65   Status Init(const ElementMetadata& metadata,
66               std::uint64_t max_size) override {
67     display_width_has_value_ = false;
68     display_height_has_value_ = false;
69 
70     return MasterValueParser::Init(metadata, max_size);
71   }
72 
InitAfterSeek(const Ancestory & child_ancestory,const ElementMetadata & child_metadata)73   void InitAfterSeek(const Ancestory& child_ancestory,
74                      const ElementMetadata& child_metadata) override {
75     display_width_has_value_ = false;
76     display_height_has_value_ = false;
77 
78     return MasterValueParser::InitAfterSeek(child_ancestory, child_metadata);
79   }
80 
Feed(Callback * callback,Reader * reader,std::uint64_t * num_bytes_read)81   Status Feed(Callback* callback, Reader* reader,
82               std::uint64_t* num_bytes_read) override {
83     const Status status =
84         MasterValueParser::Feed(callback, reader, num_bytes_read);
85     if (status.completed_ok()) {
86       FixMissingDisplaySize();
87     }
88     return status;
89   }
90 
91  protected:
OnChildParsed(const ElementMetadata & metadata)92   void OnChildParsed(const ElementMetadata& metadata) override {
93     assert(metadata.id == Id::kDisplayWidth ||
94            metadata.id == Id::kDisplayHeight);
95 
96     if (metadata.id == Id::kDisplayWidth) {
97       display_width_has_value_ = metadata.size > 0;
98     } else {
99       display_height_has_value_ = metadata.size > 0;
100     }
101   }
102 
103  private:
104   bool display_width_has_value_;
105   bool display_height_has_value_;
106 
FixMissingDisplaySize()107   void FixMissingDisplaySize() {
108     if (!display_width_has_value_) {
109       *mutable_value()->display_width.mutable_value() =
110           value().pixel_width.value();
111     }
112 
113     if (!display_height_has_value_) {
114       *mutable_value()->display_height.mutable_value() =
115           value().pixel_height.value();
116     }
117   }
118 };
119 
120 }  // namespace webm
121 
122 #endif  // SRC_VIDEO_PARSER_H_
123