// Copyright 2014 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef PACKAGER_MEDIA_FORMATS_WEBM_WEBM_PARSER_H_ #define PACKAGER_MEDIA_FORMATS_WEBM_WEBM_PARSER_H_ #include #include #include #include "packager/macros.h" namespace shaka { namespace media { /// Interface for receiving WebM parser events. /// /// Each method is called when an element of the specified type is parsed. /// The ID of the element that was parsed is given along with the value /// stored in the element. List elements generate calls at the start and /// end of the list. Any pointers passed to these methods are only guaranteed /// to be valid for the life of that call. Each method (except for OnListStart) /// returns a bool that indicates whether the parsed data is valid. OnListStart /// returns a pointer to a WebMParserClient object, which should be used to /// handle elements parsed out of the list being started. If false (or NULL by /// OnListStart) is returned then the parse is immediately terminated and an /// error is reported by the parser. class WebMParserClient { public: virtual ~WebMParserClient(); virtual WebMParserClient* OnListStart(int id); virtual bool OnListEnd(int id); virtual bool OnUInt(int id, int64_t val); virtual bool OnFloat(int id, double val); virtual bool OnBinary(int id, const uint8_t* data, int size); virtual bool OnString(int id, const std::string& str); protected: WebMParserClient(); DISALLOW_COPY_AND_ASSIGN(WebMParserClient); }; struct ListElementInfo; /// Parses a WebM list element and all of its children. This /// class supports incremental parsing of the list so Parse() /// can be called multiple times with pieces of the list. /// IsParsingComplete() will return true once the entire list has /// been parsed. class WebMListParser { public: /// @param id Element ID of the list we intend to parse. /// @param client Called as different elements in the list are parsed. WebMListParser(int id, WebMParserClient* client); ~WebMListParser(); /// Resets the state of the parser so it can start parsing a new list. void Reset(); /// Parses list data contained in |buf|. /// @return < 0 if the parse fails. /// @return 0 if more data is needed. /// @return > 0 indicates success & the number of bytes parsed. int Parse(const uint8_t* buf, int size); /// @return true if the entire list has been parsed. bool IsParsingComplete() const; private: enum State { NEED_LIST_HEADER, INSIDE_LIST, DONE_PARSING_LIST, PARSE_ERROR, }; struct ListState { int id_; int64_t size_; int64_t bytes_parsed_; const ListElementInfo* element_info_; WebMParserClient* client_; }; void ChangeState(State new_state); // Parses a single element in the current list. // // |header_size| - The size of the element header // |id| - The ID of the element being parsed. // |element_size| - The size of the element body. // |data| - Pointer to the element contents. // |size| - Number of bytes in |data| // |client| - Client to pass the parsed data to. // // Returns < 0 if the parse fails. // Returns 0 if more data is needed. // Returning > 0 indicates success & the number of bytes parsed. int ParseListElement(int header_size, int id, int64_t element_size, const uint8_t* data, int size); // Called when starting to parse a new list. // // |id| - The ID of the new list. // |size| - The size of the new list. // |client| - The client object to notify that a new list is being parsed. // // Returns true if this list can be started in the current context. False // if starting this list causes some sort of parse error. bool OnListStart(int id, int64_t size); // Called when the end of the current list has been reached. This may also // signal the end of the current list's ancestors if the current list happens // to be at the end of its parent. // // Returns true if no errors occurred while ending this list(s). bool OnListEnd(); // Checks to see if |id_b| is a sibling or ancestor of |id_a|. bool IsSiblingOrAncestor(int id_a, int id_b) const; State state_; // Element ID passed to the constructor. const int root_id_; // Element level for |root_id_|. Used to verify that elements appear at // the correct level. const int root_level_; // WebMParserClient to handle the root list. WebMParserClient* const root_client_; // Stack of state for all the lists currently being parsed. Lists are // added and removed from this stack as they are parsed. std::vector list_state_stack_; DISALLOW_COPY_AND_ASSIGN(WebMListParser); }; /// Parses an element header & returns the ID and element size. /// @param[out] id contains the element ID on success and is undefined otherwise. /// @param[out] element_size contains the element size on success and is /// undefined otherwise. /// @return < 0 if the parse fails. /// @return 0 if more data is needed. /// @return > 0 indicates success & the number of bytes parsed. int WebMParseElementHeader(const uint8_t* buf, int size, int* id, int64_t* element_size); } // namespace media } // namespace shaka #endif // PACKAGER_MEDIA_FORMATS_WEBM_WEBM_PARSER_H_