blob: a906826150a278ad1889bc4c86daca75b409ab9a [file] [log] [blame]
// Copyright (c) 2016 The WebM project authors. All Rights Reserved.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the LICENSE file in the root of the source
// tree. An additional intellectual property rights grant can be found
// in the file PATENTS. All contributing project authors may
// be found in the AUTHORS file in the root of the source tree.
#ifndef SRC_BLOCK_PARSER_H_
#define SRC_BLOCK_PARSER_H_
#include <cassert>
#include <cstdint>
#include <type_traits>
#include <vector>
#include "src/block_header_parser.h"
#include "src/element_parser.h"
#include "src/var_int_parser.h"
#include "webm/callback.h"
#include "webm/dom_types.h"
#include "webm/element.h"
#include "webm/reader.h"
#include "webm/status.h"
namespace webm {
// Parses Block and SimpleBlock elements. It is recommended to use the
// BlockParser and SimpleBlockParser aliases.
// Spec reference:
// http://matroska.org/technical/specs/index.html#Block
// http://matroska.org/technical/specs/index.html#SimpleBlock
// http://www.webmproject.org/docs/container/#SimpleBlock
// http://www.webmproject.org/docs/container/#Block
// http://matroska.org/technical/specs/index.html#block_structure
// http://matroska.org/technical/specs/index.html#simpleblock_structure
template <typename T>
class BasicBlockParser : public ElementParser {
static_assert(std::is_same<T, Block>::value ||
std::is_same<T, SimpleBlock>::value,
"T must be Block or SimpleBlock");
public:
Status Init(const ElementMetadata& metadata, std::uint64_t max_size) override;
Status Feed(Callback* callback, Reader* reader,
std::uint64_t* num_bytes_read) override;
bool WasSkipped() const override;
// Gets the parsed block header information. The frames are not included. This
// must not be called until the parse has been successfully completed.
const T& value() const {
assert(state_ == State::kDone);
return value_;
}
// Gets the parsed block header information. The frames are not included. This
// must not be called until the parse has been successfully completed.
T* mutable_value() {
assert(state_ == State::kDone);
return &value_;
}
private:
// The number of header bytes read (header meaning everything before the
// frames).
std::uint64_t header_bytes_read_ = 0;
// The parsed header value for the element.
T value_{};
// Metadata for the frame that is currently being read.
FrameMetadata frame_metadata_;
// Parser for parsing header metadata that is common between Block and
// SimpleBlock.
BlockHeaderParser header_parser_;
// Parser for parsing unsigned EBML variable-sized integers.
VarIntParser uint_parser_;
// The current lace size when parsing Xiph lace sizes.
std::uint64_t xiph_lace_size_ = 0;
// Lace (frame) sizes, where each entry represents the size of a frame.
std::vector<std::uint64_t> lace_sizes_;
// The current index into lace_sizes_ for the current frame being read.
std::size_t current_lace_ = 0;
// Parsing states for the finite-state machine.
enum class State {
/* clang-format off */
// State Transitions to state When
kReadingHeader, // kGettingAction no lacing
// kReadingLaceCount yes lacing
kReadingLaceCount, // kGettingAction no errors
kGettingAction, // kSkipping action == skip
// kValidatingSize no lacing
// kReadingXiphLaceSizes xiph lacing
// kReadingFirstEbmlLaceSize ebml lacing
// kCalculatingFixedLaceSizes fixed lacing
kReadingXiphLaceSizes, // kValidatingSize all sizes read
kReadingFirstEbmlLaceSize, // kReadingEbmlLaceSizes first size read
kReadingEbmlLaceSizes, // kValidatingSize all sizes read
kCalculatingFixedLaceSizes, // kReadingFrames no errors
kValidatingSize, // kReadingFrames no errors
kSkipping, // No transitions from here (must call Init)
kReadingFrames, // kDone all frames read
kDone, // No transitions from here (must call Init)
/* clang-format on */
};
// The current state of the parser.
State state_ = State::kReadingHeader;
};
extern template class BasicBlockParser<Block>;
extern template class BasicBlockParser<SimpleBlock>;
using BlockParser = BasicBlockParser<Block>;
using SimpleBlockParser = BasicBlockParser<SimpleBlock>;
} // namespace webm
#endif // SRC_BLOCK_PARSER_H_