1*103e46e4SHarish Mahendrakar // Copyright (c) 2016 The WebM project authors. All Rights Reserved. 2*103e46e4SHarish Mahendrakar // 3*103e46e4SHarish Mahendrakar // Use of this source code is governed by a BSD-style license 4*103e46e4SHarish Mahendrakar // that can be found in the LICENSE file in the root of the source 5*103e46e4SHarish Mahendrakar // tree. An additional intellectual property rights grant can be found 6*103e46e4SHarish Mahendrakar // in the file PATENTS. All contributing project authors may 7*103e46e4SHarish Mahendrakar // be found in the AUTHORS file in the root of the source tree. 8*103e46e4SHarish Mahendrakar #ifndef LIBWEBM_M2TS_VPXPES_PARSER_H_ 9*103e46e4SHarish Mahendrakar #define LIBWEBM_M2TS_VPXPES_PARSER_H_ 10*103e46e4SHarish Mahendrakar 11*103e46e4SHarish Mahendrakar #include <cstdint> 12*103e46e4SHarish Mahendrakar #include <string> 13*103e46e4SHarish Mahendrakar #include <vector> 14*103e46e4SHarish Mahendrakar 15*103e46e4SHarish Mahendrakar #include "common/libwebm_util.h" 16*103e46e4SHarish Mahendrakar #include "common/video_frame.h" 17*103e46e4SHarish Mahendrakar 18*103e46e4SHarish Mahendrakar namespace libwebm { 19*103e46e4SHarish Mahendrakar 20*103e46e4SHarish Mahendrakar // Parser for VPx PES. Requires that the _entire_ PES stream can be stored in 21*103e46e4SHarish Mahendrakar // a std::vector<std::uint8_t> and read into memory when Open() is called. 22*103e46e4SHarish Mahendrakar // TODO(tomfinegan): Support incremental parse. 23*103e46e4SHarish Mahendrakar class VpxPesParser { 24*103e46e4SHarish Mahendrakar public: 25*103e46e4SHarish Mahendrakar typedef std::vector<std::uint8_t> PesFileData; 26*103e46e4SHarish Mahendrakar typedef std::vector<std::uint8_t> PacketData; 27*103e46e4SHarish Mahendrakar 28*103e46e4SHarish Mahendrakar enum ParseState { 29*103e46e4SHarish Mahendrakar kFindStartCode, 30*103e46e4SHarish Mahendrakar kParsePesHeader, 31*103e46e4SHarish Mahendrakar kParsePesOptionalHeader, 32*103e46e4SHarish Mahendrakar kParseBcmvHeader, 33*103e46e4SHarish Mahendrakar }; 34*103e46e4SHarish Mahendrakar 35*103e46e4SHarish Mahendrakar struct PesOptionalHeader { 36*103e46e4SHarish Mahendrakar int marker = 0; 37*103e46e4SHarish Mahendrakar int scrambling = 0; 38*103e46e4SHarish Mahendrakar int priority = 0; 39*103e46e4SHarish Mahendrakar int data_alignment = 0; 40*103e46e4SHarish Mahendrakar int copyright = 0; 41*103e46e4SHarish Mahendrakar int original = 0; 42*103e46e4SHarish Mahendrakar int has_pts = 0; 43*103e46e4SHarish Mahendrakar int has_dts = 0; 44*103e46e4SHarish Mahendrakar int unused_fields = 0; 45*103e46e4SHarish Mahendrakar int remaining_size = 0; 46*103e46e4SHarish Mahendrakar int pts_dts_flag = 0; 47*103e46e4SHarish Mahendrakar std::uint64_t pts = 0; 48*103e46e4SHarish Mahendrakar int stuffing_byte = 0; 49*103e46e4SHarish Mahendrakar }; 50*103e46e4SHarish Mahendrakar 51*103e46e4SHarish Mahendrakar struct BcmvHeader { 52*103e46e4SHarish Mahendrakar BcmvHeader() = default; 53*103e46e4SHarish Mahendrakar ~BcmvHeader() = default; 54*103e46e4SHarish Mahendrakar BcmvHeader(const BcmvHeader&) = delete; 55*103e46e4SHarish Mahendrakar BcmvHeader(BcmvHeader&&) = delete; 56*103e46e4SHarish Mahendrakar 57*103e46e4SHarish Mahendrakar // Convenience ctor for quick validation of expected values via operator== 58*103e46e4SHarish Mahendrakar // after parsing input. 59*103e46e4SHarish Mahendrakar explicit BcmvHeader(std::uint32_t len); 60*103e46e4SHarish Mahendrakar 61*103e46e4SHarish Mahendrakar bool operator==(const BcmvHeader& other) const; 62*103e46e4SHarish Mahendrakar 63*103e46e4SHarish Mahendrakar void Reset(); 64*103e46e4SHarish Mahendrakar bool Valid() const; sizeBcmvHeader65*103e46e4SHarish Mahendrakar static std::size_t size() { return 10; } 66*103e46e4SHarish Mahendrakar 67*103e46e4SHarish Mahendrakar char id[4] = {0}; 68*103e46e4SHarish Mahendrakar std::uint32_t length = 0; 69*103e46e4SHarish Mahendrakar }; 70*103e46e4SHarish Mahendrakar 71*103e46e4SHarish Mahendrakar struct PesHeader { 72*103e46e4SHarish Mahendrakar std::uint8_t start_code[4] = {0}; 73*103e46e4SHarish Mahendrakar std::uint16_t packet_length = 0; 74*103e46e4SHarish Mahendrakar std::uint8_t stream_id = 0; 75*103e46e4SHarish Mahendrakar PesOptionalHeader opt_header; 76*103e46e4SHarish Mahendrakar BcmvHeader bcmv_header; 77*103e46e4SHarish Mahendrakar }; 78*103e46e4SHarish Mahendrakar 79*103e46e4SHarish Mahendrakar // Constants for validating known values from input data. 80*103e46e4SHarish Mahendrakar const std::uint8_t kMinVideoStreamId = 0xE0; 81*103e46e4SHarish Mahendrakar const std::uint8_t kMaxVideoStreamId = 0xEF; 82*103e46e4SHarish Mahendrakar const std::size_t kPesHeaderSize = 6; 83*103e46e4SHarish Mahendrakar const std::size_t kPesOptionalHeaderStartOffset = kPesHeaderSize; 84*103e46e4SHarish Mahendrakar const std::size_t kPesOptionalHeaderSize = 9; 85*103e46e4SHarish Mahendrakar const std::size_t kPesOptionalHeaderMarkerValue = 0x2; 86*103e46e4SHarish Mahendrakar const std::size_t kWebm2PesOptHeaderRemainingSize = 6; 87*103e46e4SHarish Mahendrakar const std::size_t kBcmvHeaderSize = 10; 88*103e46e4SHarish Mahendrakar 89*103e46e4SHarish Mahendrakar VpxPesParser() = default; 90*103e46e4SHarish Mahendrakar ~VpxPesParser() = default; 91*103e46e4SHarish Mahendrakar 92*103e46e4SHarish Mahendrakar // Opens file specified by |pes_file_path| and reads its contents. Returns 93*103e46e4SHarish Mahendrakar // true after successful read of input file. 94*103e46e4SHarish Mahendrakar bool Open(const std::string& pes_file_path); 95*103e46e4SHarish Mahendrakar 96*103e46e4SHarish Mahendrakar // Parses the next packet in the PES. PES header information is stored in 97*103e46e4SHarish Mahendrakar // |header|, and the frame payload is stored in |frame|. Returns true when 98*103e46e4SHarish Mahendrakar // a full frame has been consumed from the PES. 99*103e46e4SHarish Mahendrakar bool ParseNextPacket(PesHeader* header, VideoFrame* frame); 100*103e46e4SHarish Mahendrakar 101*103e46e4SHarish Mahendrakar // PES Header parsing utility functions. 102*103e46e4SHarish Mahendrakar // PES Header structure: 103*103e46e4SHarish Mahendrakar // Start code Stream ID Packet length (16 bits) 104*103e46e4SHarish Mahendrakar // / / ____/ 105*103e46e4SHarish Mahendrakar // | | / 106*103e46e4SHarish Mahendrakar // Byte0 Byte1 Byte2 Byte3 Byte4 Byte5 107*103e46e4SHarish Mahendrakar // 0 0 1 X Y 108*103e46e4SHarish Mahendrakar bool VerifyPacketStartCode() const; 109*103e46e4SHarish Mahendrakar bool ReadStreamId(std::uint8_t* stream_id) const; 110*103e46e4SHarish Mahendrakar bool ReadPacketLength(std::uint16_t* packet_length) const; 111*103e46e4SHarish Mahendrakar pes_file_size()112*103e46e4SHarish Mahendrakar std::uint64_t pes_file_size() const { return pes_file_size_; } pes_file_data()113*103e46e4SHarish Mahendrakar const PesFileData& pes_file_data() const { return pes_file_data_; } 114*103e46e4SHarish Mahendrakar 115*103e46e4SHarish Mahendrakar // Returns number of unparsed bytes remaining. 116*103e46e4SHarish Mahendrakar int BytesAvailable() const; 117*103e46e4SHarish Mahendrakar 118*103e46e4SHarish Mahendrakar private: 119*103e46e4SHarish Mahendrakar // Parses and verifies the static 6 byte portion that begins every PES packet. 120*103e46e4SHarish Mahendrakar bool ParsePesHeader(PesHeader* header); 121*103e46e4SHarish Mahendrakar 122*103e46e4SHarish Mahendrakar // Parses a PES optional header, the optional header following the static 123*103e46e4SHarish Mahendrakar // header that begins the VPX PES packet. 124*103e46e4SHarish Mahendrakar // https://en.wikipedia.org/wiki/Packetized_elementary_stream 125*103e46e4SHarish Mahendrakar bool ParsePesOptionalHeader(PesOptionalHeader* header); 126*103e46e4SHarish Mahendrakar 127*103e46e4SHarish Mahendrakar // Parses and validates the BCMV header. This immediately follows the optional 128*103e46e4SHarish Mahendrakar // header. 129*103e46e4SHarish Mahendrakar bool ParseBcmvHeader(BcmvHeader* header); 130*103e46e4SHarish Mahendrakar 131*103e46e4SHarish Mahendrakar // Returns true when a start code is found and sets |offset| to the position 132*103e46e4SHarish Mahendrakar // of the start code relative to |pes_file_data_[read_pos_]|. 133*103e46e4SHarish Mahendrakar // Does not set |offset| value if the end of |pes_file_data_| is reached 134*103e46e4SHarish Mahendrakar // without locating a start code. 135*103e46e4SHarish Mahendrakar // Note: A start code is the byte sequence 0x00 0x00 0x01. 136*103e46e4SHarish Mahendrakar bool FindStartCode(std::size_t origin, std::size_t* offset) const; 137*103e46e4SHarish Mahendrakar 138*103e46e4SHarish Mahendrakar // Returns true when a PES packet containing a BCMV header contains only a 139*103e46e4SHarish Mahendrakar // portion of the frame payload length reported by the BCMV header. 140*103e46e4SHarish Mahendrakar bool IsPayloadFragmented(const PesHeader& header) const; 141*103e46e4SHarish Mahendrakar 142*103e46e4SHarish Mahendrakar // Parses PES and PES Optional header while accumulating payload data in 143*103e46e4SHarish Mahendrakar // |payload_|. 144*103e46e4SHarish Mahendrakar // Returns true once all payload fragments have been stored in |payload_|. 145*103e46e4SHarish Mahendrakar // Returns false if unable to accumulate full payload. 146*103e46e4SHarish Mahendrakar bool AccumulateFragmentedPayload(std::size_t pes_packet_length, 147*103e46e4SHarish Mahendrakar std::size_t payload_length); 148*103e46e4SHarish Mahendrakar 149*103e46e4SHarish Mahendrakar // The byte sequence 0x0 0x0 0x1 is a start code in PES. When PES muxers 150*103e46e4SHarish Mahendrakar // encounter 0x0 0x0 0x1 or 0x0 0x0 0x3, an additional 0x3 is inserted into 151*103e46e4SHarish Mahendrakar // the PES. The following change occurs: 152*103e46e4SHarish Mahendrakar // 0x0 0x0 0x1 => 0x0 0x0 0x3 0x1 153*103e46e4SHarish Mahendrakar // 0x0 0x0 0x3 => 0x0 0x0 0x3 0x3 154*103e46e4SHarish Mahendrakar // PES demuxers must reverse the change: 155*103e46e4SHarish Mahendrakar // 0x0 0x0 0x3 0x1 => 0x0 0x0 0x1 156*103e46e4SHarish Mahendrakar // 0x0 0x0 0x3 0x3 => 0x0 0x0 0x3 157*103e46e4SHarish Mahendrakar // PES optional header, BCMV header, and payload data must be preprocessed to 158*103e46e4SHarish Mahendrakar // avoid potentially invalid data due to the presence of inserted bytes. 159*103e46e4SHarish Mahendrakar // 160*103e46e4SHarish Mahendrakar // Removes start code emulation prevention bytes while copying data from 161*103e46e4SHarish Mahendrakar // |raw_data| to |processed_data|. Returns true when |bytes_required| bytes 162*103e46e4SHarish Mahendrakar // have been written to |processed_data|. Reports bytes consumed during the 163*103e46e4SHarish Mahendrakar // operation via |bytes_consumed|. 164*103e46e4SHarish Mahendrakar bool RemoveStartCodeEmulationPreventionBytes( 165*103e46e4SHarish Mahendrakar const std::uint8_t* raw_data, std::size_t bytes_required, 166*103e46e4SHarish Mahendrakar PacketData* processed_data, std::size_t* bytes_consumed) const; 167*103e46e4SHarish Mahendrakar 168*103e46e4SHarish Mahendrakar std::size_t pes_file_size_ = 0; 169*103e46e4SHarish Mahendrakar PacketData payload_; 170*103e46e4SHarish Mahendrakar PesFileData pes_file_data_; 171*103e46e4SHarish Mahendrakar std::size_t read_pos_ = 0; 172*103e46e4SHarish Mahendrakar ParseState parse_state_ = kFindStartCode; 173*103e46e4SHarish Mahendrakar }; 174*103e46e4SHarish Mahendrakar 175*103e46e4SHarish Mahendrakar } // namespace libwebm 176*103e46e4SHarish Mahendrakar 177*103e46e4SHarish Mahendrakar #endif // LIBWEBM_M2TS_VPXPES_PARSER_H_ 178