1// Copyright 2015 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4//
5// This file contains an implementation of a VP8 raw stream parser,
6// as defined in RFC 6386.
7// Note: ported from Chromium commit head: 1323b9c
8
9#ifndef VP8_PARSER_H_
10#define VP8_PARSER_H_
11
12#include <stddef.h>
13#include <stdint.h>
14
15#include "base/macros.h"
16#include "vp8_bool_decoder.h"
17
18namespace media {
19
20// See spec for definitions of values/fields.
21const size_t kMaxMBSegments = 4;
22const size_t kNumMBFeatureTreeProbs = 3;
23
24// Member of Vp8FrameHeader and will be 0-initialized
25// in Vp8FrameHeader's constructor.
26struct Vp8SegmentationHeader {
27  enum SegmentFeatureMode { FEATURE_MODE_DELTA = 0, FEATURE_MODE_ABSOLUTE = 1 };
28
29  bool segmentation_enabled;
30  bool update_mb_segmentation_map;
31  bool update_segment_feature_data;
32  SegmentFeatureMode segment_feature_mode;
33
34  int8_t quantizer_update_value[kMaxMBSegments];
35  int8_t lf_update_value[kMaxMBSegments];
36  static const int kDefaultSegmentProb = 255;
37  uint8_t segment_prob[kNumMBFeatureTreeProbs];
38};
39
40const size_t kNumBlockContexts = 4;
41
42// Member of Vp8FrameHeader and will be 0-initialized
43// in Vp8FrameHeader's constructor.
44struct Vp8LoopFilterHeader {
45  enum Type { LOOP_FILTER_TYPE_NORMAL = 0, LOOP_FILTER_TYPE_SIMPLE = 1 };
46  Type type;
47  uint8_t level;
48  uint8_t sharpness_level;
49  bool loop_filter_adj_enable;
50  bool mode_ref_lf_delta_update;
51
52  int8_t ref_frame_delta[kNumBlockContexts];
53  int8_t mb_mode_delta[kNumBlockContexts];
54};
55
56// Member of Vp8FrameHeader and will be 0-initialized
57// in Vp8FrameHeader's constructor.
58struct Vp8QuantizationHeader {
59  uint8_t y_ac_qi;
60  int8_t y_dc_delta;
61  int8_t y2_dc_delta;
62  int8_t y2_ac_delta;
63  int8_t uv_dc_delta;
64  int8_t uv_ac_delta;
65};
66
67const size_t kNumBlockTypes = 4;
68const size_t kNumCoeffBands = 8;
69const size_t kNumPrevCoeffContexts = 3;
70const size_t kNumEntropyNodes = 11;
71
72const size_t kNumMVContexts = 2;
73const size_t kNumMVProbs = 19;
74
75const size_t kNumYModeProbs = 4;
76const size_t kNumUVModeProbs = 3;
77
78// Member of Vp8FrameHeader and will be 0-initialized
79// in Vp8FrameHeader's constructor.
80struct Vp8EntropyHeader {
81  uint8_t coeff_probs[kNumBlockTypes][kNumCoeffBands][kNumPrevCoeffContexts]
82                     [kNumEntropyNodes];
83
84  uint8_t y_mode_probs[kNumYModeProbs];
85  uint8_t uv_mode_probs[kNumUVModeProbs];
86
87  uint8_t mv_probs[kNumMVContexts][kNumMVProbs];
88};
89
90const size_t kMaxDCTPartitions = 8;
91
92struct Vp8FrameHeader {
93  Vp8FrameHeader();
94
95  enum FrameType { KEYFRAME = 0, INTERFRAME = 1 };
96  bool IsKeyframe() const { return key_frame == KEYFRAME; }
97
98  enum GoldenRefreshMode {
99    COPY_LAST_TO_GOLDEN = 1,
100    COPY_ALT_TO_GOLDEN = 2,
101  };
102
103  enum AltRefreshMode {
104    COPY_LAST_TO_ALT = 1,
105    COPY_GOLDEN_TO_ALT = 2,
106  };
107
108  FrameType key_frame;
109  uint8_t version;
110  bool is_experimental;
111  bool show_frame;
112  size_t first_part_size;
113
114  uint16_t width;
115  uint8_t horizontal_scale;
116  uint16_t height;
117  uint8_t vertical_scale;
118
119  Vp8SegmentationHeader segmentation_hdr;
120  Vp8LoopFilterHeader loopfilter_hdr;
121  Vp8QuantizationHeader quantization_hdr;
122
123  size_t num_of_dct_partitions;
124
125  Vp8EntropyHeader entropy_hdr;
126
127  bool refresh_entropy_probs;
128  bool refresh_golden_frame;
129  bool refresh_alternate_frame;
130  GoldenRefreshMode copy_buffer_to_golden;
131  AltRefreshMode copy_buffer_to_alternate;
132  uint8_t sign_bias_golden;
133  uint8_t sign_bias_alternate;
134  bool refresh_last;
135
136  bool mb_no_skip_coeff;
137  uint8_t prob_skip_false;
138  uint8_t prob_intra;
139  uint8_t prob_last;
140  uint8_t prob_gf;
141
142  const uint8_t* data;
143  size_t frame_size;
144
145  size_t dct_partition_sizes[kMaxDCTPartitions];
146  // Offset in bytes from data.
147  off_t first_part_offset;
148  // Offset in bits from first_part_offset.
149  off_t macroblock_bit_offset;
150
151  // Bool decoder state
152  uint8_t bool_dec_range;
153  uint8_t bool_dec_value;
154  uint8_t bool_dec_count;
155};
156
157// A parser for raw VP8 streams as specified in RFC 6386.
158class Vp8Parser {
159 public:
160  Vp8Parser();
161  ~Vp8Parser();
162
163  // Try to parse exactly one VP8 frame starting at |ptr| and of size |size|,
164  // filling the parsed data in |fhdr|. Return true on success.
165  // Size has to be exactly the size of the frame and coming from the caller,
166  // who needs to acquire it from elsewhere (normally from a container).
167  bool ParseFrame(const uint8_t* ptr, size_t size, Vp8FrameHeader* fhdr);
168
169 private:
170  bool ParseFrameTag(Vp8FrameHeader* fhdr);
171  bool ParseFrameHeader(Vp8FrameHeader* fhdr);
172
173  bool ParseSegmentationHeader(bool keyframe);
174  bool ParseLoopFilterHeader(bool keyframe);
175  bool ParseQuantizationHeader(Vp8QuantizationHeader* qhdr);
176  bool ParseTokenProbs(Vp8EntropyHeader* ehdr, bool update_curr_probs);
177  bool ParseIntraProbs(Vp8EntropyHeader* ehdr,
178                       bool update_curr_probs,
179                       bool keyframe);
180  bool ParseMVProbs(Vp8EntropyHeader* ehdr, bool update_curr_probs);
181  bool ParsePartitions(Vp8FrameHeader* fhdr);
182  void ResetProbs();
183
184  // These persist across calls to ParseFrame() and may be used and/or updated
185  // for subsequent frames if the stream instructs us to do so.
186  Vp8SegmentationHeader curr_segmentation_hdr_;
187  Vp8LoopFilterHeader curr_loopfilter_hdr_;
188  Vp8EntropyHeader curr_entropy_hdr_;
189
190  const uint8_t* stream_;
191  size_t bytes_left_;
192  Vp8BoolDecoder bd_;
193
194  DISALLOW_COPY_AND_ASSIGN(Vp8Parser);
195};
196
197}  // namespace media
198
199#endif  // VP8_PARSER_H_
200