#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 {
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;
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;
};
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;
bool Open(const std::string& pes_file_path);
bool ParseNextPacket(PesHeader* header, VideoFrame* frame);
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_; }
int BytesAvailable() const;
private:
bool ParsePesHeader(PesHeader* header);
bool ParsePesOptionalHeader(PesOptionalHeader* header);
bool ParseBcmvHeader(BcmvHeader* header);
bool FindStartCode(std::size_t origin, std::size_t* offset) const;
bool IsPayloadFragmented(const PesHeader& header) const;
bool AccumulateFragmentedPayload(std::size_t pes_packet_length,
std::size_t payload_length);
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;
};
}
#endif