xref: /aosp_15_r20/external/libwebm/m2ts/vpxpes_parser.h (revision 103e46e4cd4b6efcf6001f23fa8665fb110abf8d)
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