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 #include "vpxpes_parser.h"
9*103e46e4SHarish Mahendrakar
10*103e46e4SHarish Mahendrakar #include <cstdint>
11*103e46e4SHarish Mahendrakar #include <cstdio>
12*103e46e4SHarish Mahendrakar #include <cstring>
13*103e46e4SHarish Mahendrakar #include <limits>
14*103e46e4SHarish Mahendrakar #include <vector>
15*103e46e4SHarish Mahendrakar
16*103e46e4SHarish Mahendrakar #include "common/file_util.h"
17*103e46e4SHarish Mahendrakar
18*103e46e4SHarish Mahendrakar namespace libwebm {
19*103e46e4SHarish Mahendrakar
BcmvHeader(std::uint32_t len)20*103e46e4SHarish Mahendrakar VpxPesParser::BcmvHeader::BcmvHeader(std::uint32_t len) : length(len) {
21*103e46e4SHarish Mahendrakar id[0] = 'B';
22*103e46e4SHarish Mahendrakar id[1] = 'C';
23*103e46e4SHarish Mahendrakar id[2] = 'M';
24*103e46e4SHarish Mahendrakar id[3] = 'V';
25*103e46e4SHarish Mahendrakar }
26*103e46e4SHarish Mahendrakar
operator ==(const BcmvHeader & other) const27*103e46e4SHarish Mahendrakar bool VpxPesParser::BcmvHeader::operator==(const BcmvHeader& other) const {
28*103e46e4SHarish Mahendrakar return (other.length == length && other.id[0] == id[0] &&
29*103e46e4SHarish Mahendrakar other.id[1] == id[1] && other.id[2] == id[2] && other.id[3] == id[3]);
30*103e46e4SHarish Mahendrakar }
31*103e46e4SHarish Mahendrakar
Valid() const32*103e46e4SHarish Mahendrakar bool VpxPesParser::BcmvHeader::Valid() const {
33*103e46e4SHarish Mahendrakar return (length > 0 && id[0] == 'B' && id[1] == 'C' && id[2] == 'M' &&
34*103e46e4SHarish Mahendrakar id[3] == 'V');
35*103e46e4SHarish Mahendrakar }
36*103e46e4SHarish Mahendrakar
37*103e46e4SHarish Mahendrakar // TODO(tomfinegan): Break Open() into separate functions. One that opens the
38*103e46e4SHarish Mahendrakar // file, and one that reads one packet at a time. As things are files larger
39*103e46e4SHarish Mahendrakar // than the maximum availble memory for the current process cannot be loaded.
Open(const std::string & pes_file)40*103e46e4SHarish Mahendrakar bool VpxPesParser::Open(const std::string& pes_file) {
41*103e46e4SHarish Mahendrakar pes_file_size_ = static_cast<size_t>(libwebm::GetFileSize(pes_file));
42*103e46e4SHarish Mahendrakar if (pes_file_size_ <= 0)
43*103e46e4SHarish Mahendrakar return false;
44*103e46e4SHarish Mahendrakar pes_file_data_.reserve(static_cast<size_t>(pes_file_size_));
45*103e46e4SHarish Mahendrakar libwebm::FilePtr file = libwebm::FilePtr(std::fopen(pes_file.c_str(), "rb"),
46*103e46e4SHarish Mahendrakar libwebm::FILEDeleter());
47*103e46e4SHarish Mahendrakar int byte;
48*103e46e4SHarish Mahendrakar while ((byte = fgetc(file.get())) != EOF) {
49*103e46e4SHarish Mahendrakar pes_file_data_.push_back(static_cast<std::uint8_t>(byte));
50*103e46e4SHarish Mahendrakar }
51*103e46e4SHarish Mahendrakar
52*103e46e4SHarish Mahendrakar if (!feof(file.get()) || ferror(file.get()) ||
53*103e46e4SHarish Mahendrakar pes_file_size_ != pes_file_data_.size()) {
54*103e46e4SHarish Mahendrakar return false;
55*103e46e4SHarish Mahendrakar }
56*103e46e4SHarish Mahendrakar
57*103e46e4SHarish Mahendrakar read_pos_ = 0;
58*103e46e4SHarish Mahendrakar parse_state_ = kFindStartCode;
59*103e46e4SHarish Mahendrakar return true;
60*103e46e4SHarish Mahendrakar }
61*103e46e4SHarish Mahendrakar
VerifyPacketStartCode() const62*103e46e4SHarish Mahendrakar bool VpxPesParser::VerifyPacketStartCode() const {
63*103e46e4SHarish Mahendrakar if (read_pos_ + 2 > pes_file_data_.size())
64*103e46e4SHarish Mahendrakar return false;
65*103e46e4SHarish Mahendrakar
66*103e46e4SHarish Mahendrakar // PES packets all start with the byte sequence 0x0 0x0 0x1.
67*103e46e4SHarish Mahendrakar if (pes_file_data_[read_pos_] != 0 || pes_file_data_[read_pos_ + 1] != 0 ||
68*103e46e4SHarish Mahendrakar pes_file_data_[read_pos_ + 2] != 1) {
69*103e46e4SHarish Mahendrakar return false;
70*103e46e4SHarish Mahendrakar }
71*103e46e4SHarish Mahendrakar
72*103e46e4SHarish Mahendrakar return true;
73*103e46e4SHarish Mahendrakar }
74*103e46e4SHarish Mahendrakar
ReadStreamId(std::uint8_t * stream_id) const75*103e46e4SHarish Mahendrakar bool VpxPesParser::ReadStreamId(std::uint8_t* stream_id) const {
76*103e46e4SHarish Mahendrakar if (!stream_id || BytesAvailable() < 4)
77*103e46e4SHarish Mahendrakar return false;
78*103e46e4SHarish Mahendrakar
79*103e46e4SHarish Mahendrakar *stream_id = pes_file_data_[read_pos_ + 3];
80*103e46e4SHarish Mahendrakar return true;
81*103e46e4SHarish Mahendrakar }
82*103e46e4SHarish Mahendrakar
ReadPacketLength(std::uint16_t * packet_length) const83*103e46e4SHarish Mahendrakar bool VpxPesParser::ReadPacketLength(std::uint16_t* packet_length) const {
84*103e46e4SHarish Mahendrakar if (!packet_length || BytesAvailable() < 6)
85*103e46e4SHarish Mahendrakar return false;
86*103e46e4SHarish Mahendrakar
87*103e46e4SHarish Mahendrakar // Read and byte swap 16 bit big endian length.
88*103e46e4SHarish Mahendrakar *packet_length =
89*103e46e4SHarish Mahendrakar (pes_file_data_[read_pos_ + 4] << 8) | pes_file_data_[read_pos_ + 5];
90*103e46e4SHarish Mahendrakar
91*103e46e4SHarish Mahendrakar return true;
92*103e46e4SHarish Mahendrakar }
93*103e46e4SHarish Mahendrakar
ParsePesHeader(PesHeader * header)94*103e46e4SHarish Mahendrakar bool VpxPesParser::ParsePesHeader(PesHeader* header) {
95*103e46e4SHarish Mahendrakar if (!header || parse_state_ != kParsePesHeader)
96*103e46e4SHarish Mahendrakar return false;
97*103e46e4SHarish Mahendrakar
98*103e46e4SHarish Mahendrakar if (!VerifyPacketStartCode())
99*103e46e4SHarish Mahendrakar return false;
100*103e46e4SHarish Mahendrakar
101*103e46e4SHarish Mahendrakar std::size_t pos = read_pos_;
102*103e46e4SHarish Mahendrakar for (auto& a : header->start_code) {
103*103e46e4SHarish Mahendrakar a = pes_file_data_[pos++];
104*103e46e4SHarish Mahendrakar }
105*103e46e4SHarish Mahendrakar
106*103e46e4SHarish Mahendrakar // PES Video stream IDs start at E0.
107*103e46e4SHarish Mahendrakar if (!ReadStreamId(&header->stream_id))
108*103e46e4SHarish Mahendrakar return false;
109*103e46e4SHarish Mahendrakar
110*103e46e4SHarish Mahendrakar if (header->stream_id < kMinVideoStreamId ||
111*103e46e4SHarish Mahendrakar header->stream_id > kMaxVideoStreamId)
112*103e46e4SHarish Mahendrakar return false;
113*103e46e4SHarish Mahendrakar
114*103e46e4SHarish Mahendrakar if (!ReadPacketLength(&header->packet_length))
115*103e46e4SHarish Mahendrakar return false;
116*103e46e4SHarish Mahendrakar
117*103e46e4SHarish Mahendrakar read_pos_ += kPesHeaderSize;
118*103e46e4SHarish Mahendrakar parse_state_ = kParsePesOptionalHeader;
119*103e46e4SHarish Mahendrakar return true;
120*103e46e4SHarish Mahendrakar }
121*103e46e4SHarish Mahendrakar
122*103e46e4SHarish Mahendrakar // TODO(tomfinegan): Make these masks constants.
ParsePesOptionalHeader(PesOptionalHeader * header)123*103e46e4SHarish Mahendrakar bool VpxPesParser::ParsePesOptionalHeader(PesOptionalHeader* header) {
124*103e46e4SHarish Mahendrakar if (!header || parse_state_ != kParsePesOptionalHeader ||
125*103e46e4SHarish Mahendrakar read_pos_ >= pes_file_size_) {
126*103e46e4SHarish Mahendrakar return false;
127*103e46e4SHarish Mahendrakar }
128*103e46e4SHarish Mahendrakar
129*103e46e4SHarish Mahendrakar std::size_t consumed = 0;
130*103e46e4SHarish Mahendrakar PacketData poh_buffer;
131*103e46e4SHarish Mahendrakar if (!RemoveStartCodeEmulationPreventionBytes(&pes_file_data_[read_pos_],
132*103e46e4SHarish Mahendrakar kPesOptionalHeaderSize,
133*103e46e4SHarish Mahendrakar &poh_buffer, &consumed)) {
134*103e46e4SHarish Mahendrakar return false;
135*103e46e4SHarish Mahendrakar }
136*103e46e4SHarish Mahendrakar
137*103e46e4SHarish Mahendrakar std::size_t offset = 0;
138*103e46e4SHarish Mahendrakar header->marker = (poh_buffer[offset] & 0x80) >> 6;
139*103e46e4SHarish Mahendrakar header->scrambling = (poh_buffer[offset] & 0x30) >> 4;
140*103e46e4SHarish Mahendrakar header->priority = (poh_buffer[offset] & 0x8) >> 3;
141*103e46e4SHarish Mahendrakar header->data_alignment = (poh_buffer[offset] & 0xc) >> 2;
142*103e46e4SHarish Mahendrakar header->copyright = (poh_buffer[offset] & 0x2) >> 1;
143*103e46e4SHarish Mahendrakar header->original = poh_buffer[offset] & 0x1;
144*103e46e4SHarish Mahendrakar offset++;
145*103e46e4SHarish Mahendrakar
146*103e46e4SHarish Mahendrakar header->has_pts = (poh_buffer[offset] & 0x80) >> 7;
147*103e46e4SHarish Mahendrakar header->has_dts = (poh_buffer[offset] & 0x40) >> 6;
148*103e46e4SHarish Mahendrakar header->unused_fields = poh_buffer[offset] & 0x3f;
149*103e46e4SHarish Mahendrakar offset++;
150*103e46e4SHarish Mahendrakar
151*103e46e4SHarish Mahendrakar header->remaining_size = poh_buffer[offset];
152*103e46e4SHarish Mahendrakar if (header->remaining_size !=
153*103e46e4SHarish Mahendrakar static_cast<int>(kWebm2PesOptHeaderRemainingSize))
154*103e46e4SHarish Mahendrakar return false;
155*103e46e4SHarish Mahendrakar
156*103e46e4SHarish Mahendrakar size_t bytes_left = header->remaining_size;
157*103e46e4SHarish Mahendrakar offset++;
158*103e46e4SHarish Mahendrakar
159*103e46e4SHarish Mahendrakar if (header->has_pts) {
160*103e46e4SHarish Mahendrakar // Read PTS markers. Format:
161*103e46e4SHarish Mahendrakar // PTS: 5 bytes
162*103e46e4SHarish Mahendrakar // 4 bits (flag: PTS present, but no DTS): 0x2 ('0010')
163*103e46e4SHarish Mahendrakar // 36 bits (90khz PTS):
164*103e46e4SHarish Mahendrakar // top 3 bits
165*103e46e4SHarish Mahendrakar // marker ('1')
166*103e46e4SHarish Mahendrakar // middle 15 bits
167*103e46e4SHarish Mahendrakar // marker ('1')
168*103e46e4SHarish Mahendrakar // bottom 15 bits
169*103e46e4SHarish Mahendrakar // marker ('1')
170*103e46e4SHarish Mahendrakar // TODO(tomfinegan): read/store the timestamp.
171*103e46e4SHarish Mahendrakar header->pts_dts_flag = (poh_buffer[offset] & 0x20) >> 4;
172*103e46e4SHarish Mahendrakar // Check the marker bits.
173*103e46e4SHarish Mahendrakar if ((poh_buffer[offset + 0] & 1) != 1 ||
174*103e46e4SHarish Mahendrakar (poh_buffer[offset + 2] & 1) != 1 ||
175*103e46e4SHarish Mahendrakar (poh_buffer[offset + 4] & 1) != 1) {
176*103e46e4SHarish Mahendrakar return false;
177*103e46e4SHarish Mahendrakar }
178*103e46e4SHarish Mahendrakar
179*103e46e4SHarish Mahendrakar header->pts = (poh_buffer[offset] & 0xe) << 29 |
180*103e46e4SHarish Mahendrakar ((ReadUint16(&poh_buffer[offset + 1]) & ~1) << 14) |
181*103e46e4SHarish Mahendrakar (ReadUint16(&poh_buffer[offset + 3]) >> 1);
182*103e46e4SHarish Mahendrakar offset += 5;
183*103e46e4SHarish Mahendrakar bytes_left -= 5;
184*103e46e4SHarish Mahendrakar }
185*103e46e4SHarish Mahendrakar
186*103e46e4SHarish Mahendrakar // Validate stuffing byte(s).
187*103e46e4SHarish Mahendrakar for (size_t i = 0; i < bytes_left; ++i) {
188*103e46e4SHarish Mahendrakar if (poh_buffer[offset + i] != 0xff)
189*103e46e4SHarish Mahendrakar return false;
190*103e46e4SHarish Mahendrakar }
191*103e46e4SHarish Mahendrakar
192*103e46e4SHarish Mahendrakar read_pos_ += consumed;
193*103e46e4SHarish Mahendrakar parse_state_ = kParseBcmvHeader;
194*103e46e4SHarish Mahendrakar
195*103e46e4SHarish Mahendrakar return true;
196*103e46e4SHarish Mahendrakar }
197*103e46e4SHarish Mahendrakar
198*103e46e4SHarish Mahendrakar // Parses and validates a BCMV header.
ParseBcmvHeader(BcmvHeader * header)199*103e46e4SHarish Mahendrakar bool VpxPesParser::ParseBcmvHeader(BcmvHeader* header) {
200*103e46e4SHarish Mahendrakar if (!header || parse_state_ != kParseBcmvHeader)
201*103e46e4SHarish Mahendrakar return false;
202*103e46e4SHarish Mahendrakar
203*103e46e4SHarish Mahendrakar PacketData bcmv_buffer;
204*103e46e4SHarish Mahendrakar std::size_t consumed = 0;
205*103e46e4SHarish Mahendrakar if (!RemoveStartCodeEmulationPreventionBytes(&pes_file_data_[read_pos_],
206*103e46e4SHarish Mahendrakar kBcmvHeaderSize, &bcmv_buffer,
207*103e46e4SHarish Mahendrakar &consumed)) {
208*103e46e4SHarish Mahendrakar return false;
209*103e46e4SHarish Mahendrakar }
210*103e46e4SHarish Mahendrakar
211*103e46e4SHarish Mahendrakar std::size_t offset = 0;
212*103e46e4SHarish Mahendrakar header->id[0] = bcmv_buffer[offset++];
213*103e46e4SHarish Mahendrakar header->id[1] = bcmv_buffer[offset++];
214*103e46e4SHarish Mahendrakar header->id[2] = bcmv_buffer[offset++];
215*103e46e4SHarish Mahendrakar header->id[3] = bcmv_buffer[offset++];
216*103e46e4SHarish Mahendrakar
217*103e46e4SHarish Mahendrakar header->length = 0;
218*103e46e4SHarish Mahendrakar header->length |= bcmv_buffer[offset++] << 24;
219*103e46e4SHarish Mahendrakar header->length |= bcmv_buffer[offset++] << 16;
220*103e46e4SHarish Mahendrakar header->length |= bcmv_buffer[offset++] << 8;
221*103e46e4SHarish Mahendrakar header->length |= bcmv_buffer[offset++];
222*103e46e4SHarish Mahendrakar
223*103e46e4SHarish Mahendrakar // Length stored in the BCMV header is followed by 2 bytes of 0 padding.
224*103e46e4SHarish Mahendrakar if (bcmv_buffer[offset++] != 0 || bcmv_buffer[offset++] != 0)
225*103e46e4SHarish Mahendrakar return false;
226*103e46e4SHarish Mahendrakar
227*103e46e4SHarish Mahendrakar if (!header->Valid())
228*103e46e4SHarish Mahendrakar return false;
229*103e46e4SHarish Mahendrakar
230*103e46e4SHarish Mahendrakar parse_state_ = kFindStartCode;
231*103e46e4SHarish Mahendrakar read_pos_ += consumed;
232*103e46e4SHarish Mahendrakar
233*103e46e4SHarish Mahendrakar return true;
234*103e46e4SHarish Mahendrakar }
235*103e46e4SHarish Mahendrakar
FindStartCode(std::size_t origin,std::size_t * offset) const236*103e46e4SHarish Mahendrakar bool VpxPesParser::FindStartCode(std::size_t origin,
237*103e46e4SHarish Mahendrakar std::size_t* offset) const {
238*103e46e4SHarish Mahendrakar if (read_pos_ + 2 >= pes_file_size_)
239*103e46e4SHarish Mahendrakar return false;
240*103e46e4SHarish Mahendrakar
241*103e46e4SHarish Mahendrakar const std::size_t length = pes_file_size_ - origin;
242*103e46e4SHarish Mahendrakar if (length < 3)
243*103e46e4SHarish Mahendrakar return false;
244*103e46e4SHarish Mahendrakar
245*103e46e4SHarish Mahendrakar const uint8_t* const data = &pes_file_data_[origin];
246*103e46e4SHarish Mahendrakar for (std::size_t i = 0; i < length - 3; ++i) {
247*103e46e4SHarish Mahendrakar if (data[i] == 0 && data[i + 1] == 0 && data[i + 2] == 1) {
248*103e46e4SHarish Mahendrakar *offset = origin + i;
249*103e46e4SHarish Mahendrakar return true;
250*103e46e4SHarish Mahendrakar }
251*103e46e4SHarish Mahendrakar }
252*103e46e4SHarish Mahendrakar
253*103e46e4SHarish Mahendrakar return false;
254*103e46e4SHarish Mahendrakar }
255*103e46e4SHarish Mahendrakar
IsPayloadFragmented(const PesHeader & header) const256*103e46e4SHarish Mahendrakar bool VpxPesParser::IsPayloadFragmented(const PesHeader& header) const {
257*103e46e4SHarish Mahendrakar return (header.packet_length != 0 &&
258*103e46e4SHarish Mahendrakar (header.packet_length - kPesOptionalHeaderSize) !=
259*103e46e4SHarish Mahendrakar header.bcmv_header.length);
260*103e46e4SHarish Mahendrakar }
261*103e46e4SHarish Mahendrakar
AccumulateFragmentedPayload(std::size_t pes_packet_length,std::size_t payload_length)262*103e46e4SHarish Mahendrakar bool VpxPesParser::AccumulateFragmentedPayload(std::size_t pes_packet_length,
263*103e46e4SHarish Mahendrakar std::size_t payload_length) {
264*103e46e4SHarish Mahendrakar const std::size_t first_fragment_length =
265*103e46e4SHarish Mahendrakar pes_packet_length - kPesOptionalHeaderSize - kBcmvHeaderSize;
266*103e46e4SHarish Mahendrakar for (std::size_t i = 0; i < first_fragment_length; ++i) {
267*103e46e4SHarish Mahendrakar payload_.push_back(pes_file_data_[read_pos_ + i]);
268*103e46e4SHarish Mahendrakar }
269*103e46e4SHarish Mahendrakar read_pos_ += first_fragment_length;
270*103e46e4SHarish Mahendrakar parse_state_ = kFindStartCode;
271*103e46e4SHarish Mahendrakar
272*103e46e4SHarish Mahendrakar while (payload_.size() < payload_length) {
273*103e46e4SHarish Mahendrakar PesHeader header;
274*103e46e4SHarish Mahendrakar std::size_t packet_start_pos = read_pos_;
275*103e46e4SHarish Mahendrakar if (!FindStartCode(read_pos_, &packet_start_pos)) {
276*103e46e4SHarish Mahendrakar return false;
277*103e46e4SHarish Mahendrakar }
278*103e46e4SHarish Mahendrakar parse_state_ = kParsePesHeader;
279*103e46e4SHarish Mahendrakar read_pos_ = packet_start_pos;
280*103e46e4SHarish Mahendrakar
281*103e46e4SHarish Mahendrakar if (!ParsePesHeader(&header)) {
282*103e46e4SHarish Mahendrakar return false;
283*103e46e4SHarish Mahendrakar }
284*103e46e4SHarish Mahendrakar if (!ParsePesOptionalHeader(&header.opt_header)) {
285*103e46e4SHarish Mahendrakar return false;
286*103e46e4SHarish Mahendrakar }
287*103e46e4SHarish Mahendrakar
288*103e46e4SHarish Mahendrakar const std::size_t fragment_length =
289*103e46e4SHarish Mahendrakar header.packet_length - kPesOptionalHeaderSize;
290*103e46e4SHarish Mahendrakar std::size_t consumed = 0;
291*103e46e4SHarish Mahendrakar if (!RemoveStartCodeEmulationPreventionBytes(&pes_file_data_[read_pos_],
292*103e46e4SHarish Mahendrakar fragment_length, &payload_,
293*103e46e4SHarish Mahendrakar &consumed)) {
294*103e46e4SHarish Mahendrakar return false;
295*103e46e4SHarish Mahendrakar }
296*103e46e4SHarish Mahendrakar read_pos_ += consumed;
297*103e46e4SHarish Mahendrakar }
298*103e46e4SHarish Mahendrakar return true;
299*103e46e4SHarish Mahendrakar }
300*103e46e4SHarish Mahendrakar
RemoveStartCodeEmulationPreventionBytes(const std::uint8_t * raw_data,std::size_t bytes_required,PacketData * processed_data,std::size_t * bytes_consumed) const301*103e46e4SHarish Mahendrakar bool VpxPesParser::RemoveStartCodeEmulationPreventionBytes(
302*103e46e4SHarish Mahendrakar const std::uint8_t* raw_data, std::size_t bytes_required,
303*103e46e4SHarish Mahendrakar PacketData* processed_data, std::size_t* bytes_consumed) const {
304*103e46e4SHarish Mahendrakar if (bytes_required == 0 || !processed_data)
305*103e46e4SHarish Mahendrakar return false;
306*103e46e4SHarish Mahendrakar
307*103e46e4SHarish Mahendrakar std::size_t num_zeros = 0;
308*103e46e4SHarish Mahendrakar std::size_t bytes_copied = 0;
309*103e46e4SHarish Mahendrakar const std::uint8_t* const end_of_input =
310*103e46e4SHarish Mahendrakar &pes_file_data_[0] + pes_file_data_.size();
311*103e46e4SHarish Mahendrakar std::size_t i;
312*103e46e4SHarish Mahendrakar for (i = 0; bytes_copied < bytes_required; ++i) {
313*103e46e4SHarish Mahendrakar if (raw_data + i > end_of_input)
314*103e46e4SHarish Mahendrakar return false;
315*103e46e4SHarish Mahendrakar
316*103e46e4SHarish Mahendrakar bool skip = false;
317*103e46e4SHarish Mahendrakar
318*103e46e4SHarish Mahendrakar const std::uint8_t byte = raw_data[i];
319*103e46e4SHarish Mahendrakar if (byte == 0) {
320*103e46e4SHarish Mahendrakar ++num_zeros;
321*103e46e4SHarish Mahendrakar } else if (byte == 0x3 && num_zeros == 2) {
322*103e46e4SHarish Mahendrakar skip = true;
323*103e46e4SHarish Mahendrakar num_zeros = 0;
324*103e46e4SHarish Mahendrakar } else {
325*103e46e4SHarish Mahendrakar num_zeros = 0;
326*103e46e4SHarish Mahendrakar }
327*103e46e4SHarish Mahendrakar
328*103e46e4SHarish Mahendrakar if (skip == false) {
329*103e46e4SHarish Mahendrakar processed_data->push_back(byte);
330*103e46e4SHarish Mahendrakar ++bytes_copied;
331*103e46e4SHarish Mahendrakar }
332*103e46e4SHarish Mahendrakar }
333*103e46e4SHarish Mahendrakar *bytes_consumed = i;
334*103e46e4SHarish Mahendrakar return true;
335*103e46e4SHarish Mahendrakar }
336*103e46e4SHarish Mahendrakar
BytesAvailable() const337*103e46e4SHarish Mahendrakar int VpxPesParser::BytesAvailable() const {
338*103e46e4SHarish Mahendrakar return static_cast<int>(pes_file_data_.size() - read_pos_);
339*103e46e4SHarish Mahendrakar }
340*103e46e4SHarish Mahendrakar
ParseNextPacket(PesHeader * header,VideoFrame * frame)341*103e46e4SHarish Mahendrakar bool VpxPesParser::ParseNextPacket(PesHeader* header, VideoFrame* frame) {
342*103e46e4SHarish Mahendrakar if (!header || !frame || parse_state_ != kFindStartCode ||
343*103e46e4SHarish Mahendrakar BytesAvailable() == 0) {
344*103e46e4SHarish Mahendrakar return false;
345*103e46e4SHarish Mahendrakar }
346*103e46e4SHarish Mahendrakar
347*103e46e4SHarish Mahendrakar std::size_t packet_start_pos = read_pos_;
348*103e46e4SHarish Mahendrakar if (!FindStartCode(read_pos_, &packet_start_pos)) {
349*103e46e4SHarish Mahendrakar return false;
350*103e46e4SHarish Mahendrakar }
351*103e46e4SHarish Mahendrakar parse_state_ = kParsePesHeader;
352*103e46e4SHarish Mahendrakar read_pos_ = packet_start_pos;
353*103e46e4SHarish Mahendrakar
354*103e46e4SHarish Mahendrakar if (!ParsePesHeader(header)) {
355*103e46e4SHarish Mahendrakar return false;
356*103e46e4SHarish Mahendrakar }
357*103e46e4SHarish Mahendrakar if (!ParsePesOptionalHeader(&header->opt_header)) {
358*103e46e4SHarish Mahendrakar return false;
359*103e46e4SHarish Mahendrakar }
360*103e46e4SHarish Mahendrakar if (!ParseBcmvHeader(&header->bcmv_header)) {
361*103e46e4SHarish Mahendrakar return false;
362*103e46e4SHarish Mahendrakar }
363*103e46e4SHarish Mahendrakar
364*103e46e4SHarish Mahendrakar // BCMV header length includes the length of the BCMVHeader itself. Adjust:
365*103e46e4SHarish Mahendrakar const std::size_t payload_length =
366*103e46e4SHarish Mahendrakar header->bcmv_header.length - BcmvHeader::size();
367*103e46e4SHarish Mahendrakar
368*103e46e4SHarish Mahendrakar // Make sure there's enough input data to read the entire frame.
369*103e46e4SHarish Mahendrakar if (read_pos_ + payload_length > pes_file_data_.size()) {
370*103e46e4SHarish Mahendrakar // Need more data.
371*103e46e4SHarish Mahendrakar printf("VpxPesParser: Not enough data. Required: %u Available: %u\n",
372*103e46e4SHarish Mahendrakar static_cast<unsigned int>(payload_length),
373*103e46e4SHarish Mahendrakar static_cast<unsigned int>(pes_file_data_.size() - read_pos_));
374*103e46e4SHarish Mahendrakar parse_state_ = kFindStartCode;
375*103e46e4SHarish Mahendrakar read_pos_ = packet_start_pos;
376*103e46e4SHarish Mahendrakar return false;
377*103e46e4SHarish Mahendrakar }
378*103e46e4SHarish Mahendrakar
379*103e46e4SHarish Mahendrakar if (IsPayloadFragmented(*header)) {
380*103e46e4SHarish Mahendrakar if (!AccumulateFragmentedPayload(header->packet_length, payload_length)) {
381*103e46e4SHarish Mahendrakar fprintf(stderr, "VpxPesParser: Failed parsing fragmented payload!\n");
382*103e46e4SHarish Mahendrakar return false;
383*103e46e4SHarish Mahendrakar }
384*103e46e4SHarish Mahendrakar } else {
385*103e46e4SHarish Mahendrakar std::size_t consumed = 0;
386*103e46e4SHarish Mahendrakar if (!RemoveStartCodeEmulationPreventionBytes(
387*103e46e4SHarish Mahendrakar &pes_file_data_[read_pos_], payload_length, &payload_, &consumed)) {
388*103e46e4SHarish Mahendrakar return false;
389*103e46e4SHarish Mahendrakar }
390*103e46e4SHarish Mahendrakar read_pos_ += consumed;
391*103e46e4SHarish Mahendrakar }
392*103e46e4SHarish Mahendrakar
393*103e46e4SHarish Mahendrakar if (frame->buffer().capacity < payload_.size()) {
394*103e46e4SHarish Mahendrakar if (frame->Init(payload_.size()) == false) {
395*103e46e4SHarish Mahendrakar fprintf(stderr, "VpxPesParser: Out of memory.\n");
396*103e46e4SHarish Mahendrakar return false;
397*103e46e4SHarish Mahendrakar }
398*103e46e4SHarish Mahendrakar }
399*103e46e4SHarish Mahendrakar frame->set_nanosecond_pts(Khz90TicksToNanoseconds(header->opt_header.pts));
400*103e46e4SHarish Mahendrakar std::memcpy(frame->buffer().data.get(), &payload_[0], payload_.size());
401*103e46e4SHarish Mahendrakar frame->SetBufferLength(payload_.size());
402*103e46e4SHarish Mahendrakar
403*103e46e4SHarish Mahendrakar payload_.clear();
404*103e46e4SHarish Mahendrakar parse_state_ = kFindStartCode;
405*103e46e4SHarish Mahendrakar
406*103e46e4SHarish Mahendrakar return true;
407*103e46e4SHarish Mahendrakar }
408*103e46e4SHarish Mahendrakar
409*103e46e4SHarish Mahendrakar } // namespace libwebm
410