// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// This file contains an implementation of a VP8 raw stream parser,
// as defined in RFC 6386.
// Note: ported from Chromium commit head: 1323b9c
#ifndef VP8_PARSER_H_
#define VP8_PARSER_H_
#include <stddef.h>
#include <stdint.h>
#include "base/macros.h"
#include "vp8_bool_decoder.h"
namespace media {
// See spec for definitions of values/fields.
const size_t kMaxMBSegments = 4;
const size_t kNumMBFeatureTreeProbs = 3;
// Member of Vp8FrameHeader and will be 0-initialized
// in Vp8FrameHeader's constructor.
struct Vp8SegmentationHeader {
enum SegmentFeatureMode { FEATURE_MODE_DELTA = 0, FEATURE_MODE_ABSOLUTE = 1 };
bool segmentation_enabled;
bool update_mb_segmentation_map;
bool update_segment_feature_data;
SegmentFeatureMode segment_feature_mode;
int8_t quantizer_update_value[kMaxMBSegments];
int8_t lf_update_value[kMaxMBSegments];
static const int kDefaultSegmentProb = 255;
uint8_t segment_prob[kNumMBFeatureTreeProbs];
};
const size_t kNumBlockContexts = 4;
// Member of Vp8FrameHeader and will be 0-initialized
// in Vp8FrameHeader's constructor.
struct Vp8LoopFilterHeader {
enum Type { LOOP_FILTER_TYPE_NORMAL = 0, LOOP_FILTER_TYPE_SIMPLE = 1 };
Type type;
uint8_t level;
uint8_t sharpness_level;
bool loop_filter_adj_enable;
bool mode_ref_lf_delta_update;
int8_t ref_frame_delta[kNumBlockContexts];
int8_t mb_mode_delta[kNumBlockContexts];
};
// Member of Vp8FrameHeader and will be 0-initialized
// in Vp8FrameHeader's constructor.
struct Vp8QuantizationHeader {
uint8_t y_ac_qi;
int8_t y_dc_delta;
int8_t y2_dc_delta;
int8_t y2_ac_delta;
int8_t uv_dc_delta;
int8_t uv_ac_delta;
};
const size_t kNumBlockTypes = 4;
const size_t kNumCoeffBands = 8;
const size_t kNumPrevCoeffContexts = 3;
const size_t kNumEntropyNodes = 11;
const size_t kNumMVContexts = 2;
const size_t kNumMVProbs = 19;
const size_t kNumYModeProbs = 4;
const size_t kNumUVModeProbs = 3;
// Member of Vp8FrameHeader and will be 0-initialized
// in Vp8FrameHeader's constructor.
struct Vp8EntropyHeader {
uint8_t coeff_probs[kNumBlockTypes][kNumCoeffBands][kNumPrevCoeffContexts]
[kNumEntropyNodes];
uint8_t y_mode_probs[kNumYModeProbs];
uint8_t uv_mode_probs[kNumUVModeProbs];
uint8_t mv_probs[kNumMVContexts][kNumMVProbs];
};
const size_t kMaxDCTPartitions = 8;
struct Vp8FrameHeader {
Vp8FrameHeader();
enum FrameType { KEYFRAME = 0, INTERFRAME = 1 };
bool IsKeyframe() const { return key_frame == KEYFRAME; }
enum GoldenRefreshMode {
COPY_LAST_TO_GOLDEN = 1,
COPY_ALT_TO_GOLDEN = 2,
};
enum AltRefreshMode {
COPY_LAST_TO_ALT = 1,
COPY_GOLDEN_TO_ALT = 2,
};
FrameType key_frame;
uint8_t version;
bool is_experimental;
bool show_frame;
size_t first_part_size;
uint16_t width;
uint8_t horizontal_scale;
uint16_t height;
uint8_t vertical_scale;
Vp8SegmentationHeader segmentation_hdr;
Vp8LoopFilterHeader loopfilter_hdr;
Vp8QuantizationHeader quantization_hdr;
size_t num_of_dct_partitions;
Vp8EntropyHeader entropy_hdr;
bool refresh_entropy_probs;
bool refresh_golden_frame;
bool refresh_alternate_frame;
GoldenRefreshMode copy_buffer_to_golden;
AltRefreshMode copy_buffer_to_alternate;
uint8_t sign_bias_golden;
uint8_t sign_bias_alternate;
bool refresh_last;
bool mb_no_skip_coeff;
uint8_t prob_skip_false;
uint8_t prob_intra;
uint8_t prob_last;
uint8_t prob_gf;
const uint8_t* data;
size_t frame_size;
size_t dct_partition_sizes[kMaxDCTPartitions];
// Offset in bytes from data.
off_t first_part_offset;
// Offset in bits from first_part_offset.
off_t macroblock_bit_offset;
// Bool decoder state
uint8_t bool_dec_range;
uint8_t bool_dec_value;
uint8_t bool_dec_count;
};
// A parser for raw VP8 streams as specified in RFC 6386.
class Vp8Parser {
public:
Vp8Parser();
~Vp8Parser();
// Try to parse exactly one VP8 frame starting at |ptr| and of size |size|,
// filling the parsed data in |fhdr|. Return true on success.
// Size has to be exactly the size of the frame and coming from the caller,
// who needs to acquire it from elsewhere (normally from a container).
bool ParseFrame(const uint8_t* ptr, size_t size, Vp8FrameHeader* fhdr);
private:
bool ParseFrameTag(Vp8FrameHeader* fhdr);
bool ParseFrameHeader(Vp8FrameHeader* fhdr);
bool ParseSegmentationHeader(bool keyframe);
bool ParseLoopFilterHeader(bool keyframe);
bool ParseQuantizationHeader(Vp8QuantizationHeader* qhdr);
bool ParseTokenProbs(Vp8EntropyHeader* ehdr, bool update_curr_probs);
bool ParseIntraProbs(Vp8EntropyHeader* ehdr,
bool update_curr_probs,
bool keyframe);
bool ParseMVProbs(Vp8EntropyHeader* ehdr, bool update_curr_probs);
bool ParsePartitions(Vp8FrameHeader* fhdr);
void ResetProbs();
// These persist across calls to ParseFrame() and may be used and/or updated
// for subsequent frames if the stream instructs us to do so.
Vp8SegmentationHeader curr_segmentation_hdr_;
Vp8LoopFilterHeader curr_loopfilter_hdr_;
Vp8EntropyHeader curr_entropy_hdr_;
const uint8_t* stream_;
size_t bytes_left_;
Vp8BoolDecoder bd_;
DISALLOW_COPY_AND_ASSIGN(Vp8Parser);
};
} // namespace media
#endif // VP8_PARSER_H_