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_BLOCK_PARSER_H_
9 #define SRC_BLOCK_PARSER_H_
10 
11 #include <cassert>
12 #include <cstdint>
13 #include <type_traits>
14 #include <vector>
15 
16 #include "src/block_header_parser.h"
17 #include "src/element_parser.h"
18 #include "src/var_int_parser.h"
19 #include "webm/callback.h"
20 #include "webm/dom_types.h"
21 #include "webm/element.h"
22 #include "webm/reader.h"
23 #include "webm/status.h"
24 
25 namespace webm {
26 
27 // Parses Block and SimpleBlock elements. It is recommended to use the
28 // BlockParser and SimpleBlockParser aliases.
29 // Spec reference:
30 // http://matroska.org/technical/specs/index.html#Block
31 // http://matroska.org/technical/specs/index.html#SimpleBlock
32 // http://www.webmproject.org/docs/container/#SimpleBlock
33 // http://www.webmproject.org/docs/container/#Block
34 // http://matroska.org/technical/specs/index.html#block_structure
35 // http://matroska.org/technical/specs/index.html#simpleblock_structure
36 template <typename T>
37 class BasicBlockParser : public ElementParser {
38   static_assert(std::is_same<T, Block>::value ||
39                     std::is_same<T, SimpleBlock>::value,
40                 "T must be Block or SimpleBlock");
41 
42  public:
43   Status Init(const ElementMetadata& metadata, std::uint64_t max_size) override;
44 
45   Status Feed(Callback* callback, Reader* reader,
46               std::uint64_t* num_bytes_read) override;
47 
48   bool WasSkipped() const override;
49 
50   // Gets the parsed block header information. The frames are not included. This
51   // must not be called until the parse has been successfully completed.
value()52   const T& value() const {
53     assert(state_ == State::kDone);
54     return value_;
55   }
56 
57   // Gets the parsed block header information. The frames are not included. This
58   // must not be called until the parse has been successfully completed.
mutable_value()59   T* mutable_value() {
60     assert(state_ == State::kDone);
61     return &value_;
62   }
63 
64  private:
65   // The number of header bytes read (header meaning everything before the
66   // frames).
67   std::uint64_t header_bytes_read_ = 0;
68 
69   // The parsed header value for the element.
70   T value_{};
71 
72   // Metadata for the frame that is currently being read.
73   FrameMetadata frame_metadata_;
74 
75   // Parser for parsing header metadata that is common between Block and
76   // SimpleBlock.
77   BlockHeaderParser header_parser_;
78 
79   // Parser for parsing unsigned EBML variable-sized integers.
80   VarIntParser uint_parser_;
81 
82   // The current lace size when parsing Xiph lace sizes.
83   std::uint64_t xiph_lace_size_ = 0;
84 
85   // Lace (frame) sizes, where each entry represents the size of a frame.
86   std::vector<std::uint64_t> lace_sizes_;
87 
88   // The current index into lace_sizes_ for the current frame being read.
89   std::size_t current_lace_ = 0;
90 
91   // Parsing states for the finite-state machine.
92   enum class State {
93     /* clang-format off */
94     // State                        Transitions to state        When
95     kReadingHeader,              // kGettingAction              no lacing
96                                  // kReadingLaceCount           yes lacing
97     kReadingLaceCount,           // kGettingAction              no errors
98     kGettingAction,              // kSkipping                   action == skip
99                                  // kValidatingSize             no lacing
100                                  // kReadingXiphLaceSizes       xiph lacing
101                                  // kReadingFirstEbmlLaceSize   ebml lacing
102                                  // kCalculatingFixedLaceSizes  fixed lacing
103     kReadingXiphLaceSizes,       // kValidatingSize             all sizes read
104     kReadingFirstEbmlLaceSize,   // kReadingEbmlLaceSizes       first size read
105     kReadingEbmlLaceSizes,       // kValidatingSize             all sizes read
106     kCalculatingFixedLaceSizes,  // kReadingFrames              no errors
107     kValidatingSize,             // kReadingFrames              no errors
108     kSkipping,                   // No transitions from here (must call Init)
109     kReadingFrames,              // kDone                       all frames read
110     kDone,                       // No transitions from here (must call Init)
111     /* clang-format on */
112   };
113 
114   // The current state of the parser.
115   State state_ = State::kReadingHeader;
116 };
117 
118 extern template class BasicBlockParser<Block>;
119 extern template class BasicBlockParser<SimpleBlock>;
120 
121 using BlockParser = BasicBlockParser<Block>;
122 using SimpleBlockParser = BasicBlockParser<SimpleBlock>;
123 
124 }  // namespace webm
125 
126 #endif  // SRC_BLOCK_PARSER_H_
127