File: vpxpes_parser.h

package info (click to toggle)
chromium 139.0.7258.127-1
  • links: PTS, VCS
  • area: main
  • in suites:
  • size: 6,122,068 kB
  • sloc: cpp: 35,100,771; ansic: 7,163,530; javascript: 4,103,002; python: 1,436,920; asm: 946,517; xml: 746,709; pascal: 187,653; perl: 88,691; sh: 88,436; objc: 79,953; sql: 51,488; cs: 44,583; fortran: 24,137; makefile: 22,147; tcl: 15,277; php: 13,980; yacc: 8,984; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (177 lines) | stat: -rw-r--r-- 6,449 bytes parent folder | download | duplicates (27)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
// 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 LIBWEBM_M2TS_VPXPES_PARSER_H_
#define LIBWEBM_M2TS_VPXPES_PARSER_H_

#include <cstdint>
#include <string>
#include <vector>

#include "common/libwebm_util.h"
#include "common/video_frame.h"

namespace libwebm {

// Parser for VPx PES. Requires that the _entire_ PES stream can be stored in
// a std::vector<std::uint8_t> and read into memory when Open() is called.
// TODO(tomfinegan): Support incremental parse.
class VpxPesParser {
 public:
  typedef std::vector<std::uint8_t> PesFileData;
  typedef std::vector<std::uint8_t> PacketData;

  enum ParseState {
    kFindStartCode,
    kParsePesHeader,
    kParsePesOptionalHeader,
    kParseBcmvHeader,
  };

  struct PesOptionalHeader {
    int marker = 0;
    int scrambling = 0;
    int priority = 0;
    int data_alignment = 0;
    int copyright = 0;
    int original = 0;
    int has_pts = 0;
    int has_dts = 0;
    int unused_fields = 0;
    int remaining_size = 0;
    int pts_dts_flag = 0;
    std::uint64_t pts = 0;
    int stuffing_byte = 0;
  };

  struct BcmvHeader {
    BcmvHeader() = default;
    ~BcmvHeader() = default;
    BcmvHeader(const BcmvHeader&) = delete;
    BcmvHeader(BcmvHeader&&) = delete;

    // Convenience ctor for quick validation of expected values via operator==
    // after parsing input.
    explicit BcmvHeader(std::uint32_t len);

    bool operator==(const BcmvHeader& other) const;

    void Reset();
    bool Valid() const;
    static std::size_t size() { return 10; }

    char id[4] = {0};
    std::uint32_t length = 0;
  };

  struct PesHeader {
    std::uint8_t start_code[4] = {0};
    std::uint16_t packet_length = 0;
    std::uint8_t stream_id = 0;
    PesOptionalHeader opt_header;
    BcmvHeader bcmv_header;
  };

  // Constants for validating known values from input data.
  const std::uint8_t kMinVideoStreamId = 0xE0;
  const std::uint8_t kMaxVideoStreamId = 0xEF;
  const std::size_t kPesHeaderSize = 6;
  const std::size_t kPesOptionalHeaderStartOffset = kPesHeaderSize;
  const std::size_t kPesOptionalHeaderSize = 9;
  const std::size_t kPesOptionalHeaderMarkerValue = 0x2;
  const std::size_t kWebm2PesOptHeaderRemainingSize = 6;
  const std::size_t kBcmvHeaderSize = 10;

  VpxPesParser() = default;
  ~VpxPesParser() = default;

  // Opens file specified by |pes_file_path| and reads its contents. Returns
  // true after successful read of input file.
  bool Open(const std::string& pes_file_path);

  // Parses the next packet in the PES. PES header information is stored in
  // |header|, and the frame payload is stored in |frame|. Returns true when
  // a full frame has been consumed from the PES.
  bool ParseNextPacket(PesHeader* header, VideoFrame* frame);

  // PES Header parsing utility functions.
  // PES Header structure:
  // Start code         Stream ID   Packet length (16 bits)
  // /                  /      ____/
  // |                  |     /
  // Byte0 Byte1  Byte2 Byte3 Byte4 Byte5
  //     0     0      1     X           Y
  bool VerifyPacketStartCode() const;
  bool ReadStreamId(std::uint8_t* stream_id) const;
  bool ReadPacketLength(std::uint16_t* packet_length) const;

  std::uint64_t pes_file_size() const { return pes_file_size_; }
  const PesFileData& pes_file_data() const { return pes_file_data_; }

  // Returns number of unparsed bytes remaining.
  int BytesAvailable() const;

 private:
  // Parses and verifies the static 6 byte portion that begins every PES packet.
  bool ParsePesHeader(PesHeader* header);

  // Parses a PES optional header, the optional header following the static
  // header that begins the VPX PES packet.
  // https://en.wikipedia.org/wiki/Packetized_elementary_stream
  bool ParsePesOptionalHeader(PesOptionalHeader* header);

  // Parses and validates the BCMV header. This immediately follows the optional
  // header.
  bool ParseBcmvHeader(BcmvHeader* header);

  // Returns true when a start code is found and sets |offset| to the position
  // of the start code relative to |pes_file_data_[read_pos_]|.
  // Does not set |offset| value if the end of |pes_file_data_| is reached
  // without locating a start code.
  // Note: A start code is the byte sequence 0x00 0x00 0x01.
  bool FindStartCode(std::size_t origin, std::size_t* offset) const;

  // Returns true when a PES packet containing a BCMV header contains only a
  // portion of the frame payload length reported by the BCMV header.
  bool IsPayloadFragmented(const PesHeader& header) const;

  // Parses PES and PES Optional header while accumulating payload data in
  // |payload_|.
  // Returns true once all payload fragments have been stored in |payload_|.
  // Returns false if unable to accumulate full payload.
  bool AccumulateFragmentedPayload(std::size_t pes_packet_length,
                                   std::size_t payload_length);

  // The byte sequence 0x0 0x0 0x1 is a start code in PES. When PES muxers
  // encounter 0x0 0x0 0x1 or 0x0 0x0 0x3, an additional 0x3 is inserted into
  // the PES. The following change occurs:
  //    0x0 0x0 0x1  =>  0x0 0x0 0x3 0x1
  //    0x0 0x0 0x3  =>  0x0 0x0 0x3 0x3
  // PES demuxers must reverse the change:
  //    0x0 0x0 0x3 0x1  =>  0x0 0x0 0x1
  //    0x0 0x0 0x3 0x3  =>  0x0 0x0 0x3
  // PES optional header, BCMV header, and payload data must be preprocessed to
  // avoid potentially invalid data due to the presence of inserted bytes.
  //
  // Removes start code emulation prevention bytes while copying data from
  // |raw_data| to |processed_data|. Returns true when |bytes_required| bytes
  // have been written to |processed_data|. Reports bytes consumed during the
  // operation via |bytes_consumed|.
  bool RemoveStartCodeEmulationPreventionBytes(
      const std::uint8_t* raw_data, std::size_t bytes_required,
      PacketData* processed_data, std::size_t* bytes_consumed) const;

  std::size_t pes_file_size_ = 0;
  PacketData payload_;
  PesFileData pes_file_data_;
  std::size_t read_pos_ = 0;
  ParseState parse_state_ = kFindStartCode;
};

}  // namespace libwebm

#endif  // LIBWEBM_M2TS_VPXPES_PARSER_H_