Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 // | 4 // |
| 5 // This file contains an implementation of a VP9 bitstream parser. | 5 // This file contains an implementation of a VP9 bitstream parser. |
| 6 // | |
| 7 // VERBOSE level: | |
| 8 // 1 something wrong in bitstream | |
| 9 // 2 parsing steps | |
| 10 // 3 parsed values (selected) | |
| 6 | 11 |
| 7 #include "media/filters/vp9_parser.h" | 12 #include "media/filters/vp9_parser.h" |
| 8 | 13 |
| 9 #include <algorithm> | 14 #include <algorithm> |
| 10 | 15 |
| 16 #include "base/bind.h" | |
| 11 #include "base/logging.h" | 17 #include "base/logging.h" |
| 12 #include "base/macros.h" | 18 #include "base/macros.h" |
| 13 #include "base/numerics/safe_conversions.h" | 19 #include "base/numerics/safe_conversions.h" |
| 14 | 20 #include "media/filters/vp9_compressed_header_parser.h" |
| 15 namespace { | 21 #include "media/filters/vp9_uncompressed_header_parser.h" |
| 16 | |
| 17 const int kMaxLoopFilterLevel = 63; | |
| 18 | |
| 19 // Helper function for Vp9Parser::ReadTiles. Defined as get_min_log2_tile_cols | |
| 20 // in spec. | |
| 21 int GetMinLog2TileCols(int sb64_cols) { | |
| 22 const int kMaxTileWidthB64 = 64; | |
| 23 int min_log2 = 0; | |
| 24 while ((kMaxTileWidthB64 << min_log2) < sb64_cols) | |
| 25 min_log2++; | |
| 26 return min_log2; | |
| 27 } | |
| 28 | |
| 29 // Helper function for Vp9Parser::ReadTiles. Defined as get_max_log2_tile_cols | |
| 30 // in spec. | |
| 31 int GetMaxLog2TileCols(int sb64_cols) { | |
| 32 const int kMinTileWidthB64 = 4; | |
| 33 int max_log2 = 1; | |
| 34 while ((sb64_cols >> max_log2) >= kMinTileWidthB64) | |
| 35 max_log2++; | |
| 36 return max_log2 - 1; | |
| 37 } | |
| 38 | |
| 39 } // namespace | |
| 40 | 22 |
| 41 namespace media { | 23 namespace media { |
| 42 | 24 |
| 43 bool Vp9FrameHeader::IsKeyframe() const { | 25 bool Vp9FrameHeader::IsKeyframe() const { |
| 44 // When show_existing_frame is true, the frame header does not precede an | 26 // When show_existing_frame is true, the frame header does not precede an |
| 45 // actual frame to be decoded, so frame_type does not apply (and is not read | 27 // actual frame to be decoded, so frame_type does not apply (and is not read |
| 46 // from the stream). | 28 // from the stream). |
| 47 return !show_existing_frame && frame_type == KEYFRAME; | 29 return !show_existing_frame && frame_type == KEYFRAME; |
| 48 } | 30 } |
| 49 | 31 |
| 32 bool Vp9FrameHeader::IsIntra() const { | |
| 33 return !show_existing_frame && (frame_type == KEYFRAME || intra_only); | |
| 34 } | |
| 35 | |
| 50 Vp9Parser::FrameInfo::FrameInfo(const uint8_t* ptr, off_t size) | 36 Vp9Parser::FrameInfo::FrameInfo(const uint8_t* ptr, off_t size) |
| 51 : ptr(ptr), size(size) {} | 37 : ptr(ptr), size(size) {} |
| 52 | 38 |
| 53 Vp9Parser::Vp9Parser() { | 39 Vp9FrameContextManager::Vp9FrameContextManager() |
| 40 : initialized_(false), | |
|
Pawel Osciak
2016/08/08 08:13:37
Perhaps we could initialize in class body?
kcwu
2016/08/09 04:29:43
Done.
| |
| 41 needs_client_update_(false), | |
| 42 weak_ptr_factory_(this) {} | |
| 43 | |
| 44 Vp9FrameContextManager::~Vp9FrameContextManager() {} | |
| 45 | |
| 46 bool Vp9FrameContextManager::IsValidFrameContext( | |
| 47 const Vp9FrameContext& context) { | |
| 48 // probs should be in [1, 255] range. | |
| 49 static_assert(sizeof(Vp9Prob) == 1, | |
| 50 "following checks assuming Vp9Prob is single byte"); | |
| 51 if (memchr(context.tx_probs_8x8, 0, sizeof(context.tx_probs_8x8))) | |
| 52 return false; | |
| 53 if (memchr(context.tx_probs_16x16, 0, sizeof(context.tx_probs_16x16))) | |
| 54 return false; | |
| 55 if (memchr(context.tx_probs_32x32, 0, sizeof(context.tx_probs_32x32))) | |
| 56 return false; | |
| 57 | |
| 58 for (auto& a : context.coef_probs) { | |
| 59 for (auto& ai : a) { | |
| 60 for (auto& aj : ai) { | |
| 61 for (auto& ak : aj) { | |
| 62 int max_l = (ak == aj[0]) ? 3 : 6; | |
| 63 for (int l = 0; l < max_l; l++) { | |
| 64 for (auto& x : ak[l]) { | |
| 65 if (x == 0) | |
| 66 return false; | |
| 67 } | |
| 68 } | |
| 69 } | |
| 70 } | |
| 71 } | |
| 72 } | |
| 73 if (memchr(context.skip_prob, 0, sizeof(context.skip_prob))) | |
| 74 return false; | |
| 75 if (memchr(context.inter_mode_probs, 0, sizeof(context.inter_mode_probs))) | |
| 76 return false; | |
| 77 if (memchr(context.interp_filter_probs, 0, | |
| 78 sizeof(context.interp_filter_probs))) | |
| 79 return false; | |
| 80 if (memchr(context.is_inter_prob, 0, sizeof(context.is_inter_prob))) | |
| 81 return false; | |
| 82 if (memchr(context.comp_mode_prob, 0, sizeof(context.comp_mode_prob))) | |
| 83 return false; | |
| 84 if (memchr(context.single_ref_prob, 0, sizeof(context.single_ref_prob))) | |
| 85 return false; | |
| 86 if (memchr(context.comp_ref_prob, 0, sizeof(context.comp_ref_prob))) | |
| 87 return false; | |
| 88 if (memchr(context.y_mode_probs, 0, sizeof(context.y_mode_probs))) | |
| 89 return false; | |
| 90 if (memchr(context.uv_mode_probs, 0, sizeof(context.uv_mode_probs))) | |
| 91 return false; | |
| 92 if (memchr(context.partition_probs, 0, sizeof(context.partition_probs))) | |
| 93 return false; | |
| 94 if (memchr(context.mv_joint_probs, 0, sizeof(context.mv_joint_probs))) | |
| 95 return false; | |
| 96 if (memchr(context.mv_sign_prob, 0, sizeof(context.mv_sign_prob))) | |
| 97 return false; | |
| 98 if (memchr(context.mv_class_probs, 0, sizeof(context.mv_class_probs))) | |
| 99 return false; | |
| 100 if (memchr(context.mv_class0_bit_prob, 0, sizeof(context.mv_class0_bit_prob))) | |
| 101 return false; | |
| 102 if (memchr(context.mv_bits_prob, 0, sizeof(context.mv_bits_prob))) | |
| 103 return false; | |
| 104 if (memchr(context.mv_class0_fr_probs, 0, sizeof(context.mv_class0_fr_probs))) | |
| 105 return false; | |
| 106 if (memchr(context.mv_fr_probs, 0, sizeof(context.mv_fr_probs))) | |
| 107 return false; | |
| 108 if (memchr(context.mv_class0_hp_prob, 0, sizeof(context.mv_class0_hp_prob))) | |
| 109 return false; | |
| 110 if (memchr(context.mv_hp_prob, 0, sizeof(context.mv_hp_prob))) | |
| 111 return false; | |
| 112 | |
| 113 return true; | |
| 114 } | |
| 115 | |
| 116 const Vp9FrameContext& Vp9FrameContextManager::frame_context() const { | |
| 117 DCHECK(initialized_); | |
| 118 DCHECK(!needs_client_update_); | |
| 119 return frame_context_; | |
| 120 } | |
| 121 | |
| 122 void Vp9FrameContextManager::Reset() { | |
| 123 initialized_ = false; | |
| 124 needs_client_update_ = false; | |
| 125 weak_ptr_factory_.InvalidateWeakPtrs(); | |
| 126 } | |
| 127 | |
| 128 Vp9FrameContextManager::ContextRefreshCallback | |
| 129 Vp9FrameContextManager::SetNeedsClientUpdate() { | |
| 130 DCHECK(!needs_client_update_); | |
| 131 initialized_ = true; | |
| 132 needs_client_update_ = true; | |
| 133 | |
| 134 return base::Bind(&Vp9FrameContextManager::UpdateFromClient, | |
| 135 weak_ptr_factory_.GetWeakPtr()); | |
| 136 } | |
| 137 | |
| 138 void Vp9FrameContextManager::Update(const Vp9FrameContext& frame_context) { | |
| 139 // DCHECK because we can trust values from our parser. | |
| 140 DCHECK(IsValidFrameContext(frame_context)); | |
| 141 initialized_ = true; | |
| 142 frame_context_ = frame_context; | |
| 143 | |
| 144 // For frame context we are updating, it may be still awaiting previous | |
| 145 // ContextRefreshCallback. Because we overwrite the value of context here and | |
| 146 // previous ContextRefreshCallback no longer matters, invalidate the weak ptr | |
| 147 // to prevent previous ContextRefreshCallback run. | |
| 148 // With this optimization, we may be able to parse more frames while previous | |
| 149 // are still decoding. | |
| 150 weak_ptr_factory_.InvalidateWeakPtrs(); | |
| 151 needs_client_update_ = false; | |
| 152 } | |
| 153 | |
| 154 void Vp9FrameContextManager::UpdateFromClient( | |
| 155 const Vp9FrameContext& frame_context) { | |
| 156 DVLOG(2) << "Got external frame_context update"; | |
| 157 DCHECK(needs_client_update_); | |
| 158 if (!IsValidFrameContext(frame_context)) { | |
| 159 DLOG(ERROR) << "Invalid prob value in frame_context"; | |
| 160 return; | |
| 161 } | |
| 162 needs_client_update_ = false; | |
| 163 initialized_ = true; | |
| 164 frame_context_ = frame_context; | |
| 165 } | |
| 166 | |
| 167 void Vp9Parser::Context::Reset() { | |
| 168 memset(&segmentation, 0, sizeof(segmentation)); | |
| 169 memset(&loop_filter, 0, sizeof(loop_filter)); | |
| 170 memset(&ref_slots, 0, sizeof(ref_slots)); | |
| 171 for (auto& manager : frame_context_managers) | |
| 172 manager.Reset(); | |
| 173 } | |
| 174 | |
| 175 Vp9Parser::Vp9Parser(bool parsing_compressed_header) | |
| 176 : parsing_compressed_header_(parsing_compressed_header) { | |
| 54 Reset(); | 177 Reset(); |
| 55 } | 178 } |
| 56 | 179 |
| 57 Vp9Parser::~Vp9Parser() {} | 180 Vp9Parser::~Vp9Parser() {} |
| 58 | 181 |
| 59 void Vp9Parser::SetStream(const uint8_t* stream, off_t stream_size) { | 182 void Vp9Parser::SetStream(const uint8_t* stream, off_t stream_size) { |
| 60 DCHECK(stream); | 183 DCHECK(stream); |
| 61 stream_ = stream; | 184 stream_ = stream; |
| 62 bytes_left_ = stream_size; | 185 bytes_left_ = stream_size; |
| 63 frames_.clear(); | 186 frames_.clear(); |
| 64 } | 187 } |
| 65 | 188 |
| 66 void Vp9Parser::Reset() { | 189 void Vp9Parser::Reset() { |
| 67 stream_ = nullptr; | 190 stream_ = nullptr; |
| 68 bytes_left_ = 0; | 191 bytes_left_ = 0; |
| 69 frames_.clear(); | 192 frames_.clear(); |
| 70 | 193 |
| 71 memset(&segmentation_, 0, sizeof(segmentation_)); | 194 context_.Reset(); |
| 72 memset(&loop_filter_, 0, sizeof(loop_filter_)); | 195 } |
| 73 memset(&ref_slots_, 0, sizeof(ref_slots_)); | 196 |
| 74 } | 197 Vp9Parser::Result Vp9Parser::ParseNextFrame( |
| 75 | 198 Vp9FrameHeader* fhdr, |
| 76 uint8_t Vp9Parser::ReadProfile() { | 199 Vp9FrameContextManager::ContextRefreshCallback* context_refresh_cb) { |
| 77 uint8_t profile = 0; | 200 DCHECK(fhdr); |
| 78 | 201 DCHECK(!parsing_compressed_header_ || context_refresh_cb); |
| 79 // LSB first. | 202 DVLOG(2) << "ParseNextFrame"; |
| 80 if (reader_.ReadBool()) | 203 |
| 81 profile |= 1; | 204 // If |curr_frame_info_| is valid, uncompressed header was parsed into |
| 82 if (reader_.ReadBool()) | 205 // |curr_frame_header_| and we are awaiting context update to proceed with |
| 83 profile |= 2; | 206 // compressed header parsing. |
| 84 if (profile > 2 && reader_.ReadBool()) | 207 if (!curr_frame_info_.IsValid()) { |
| 85 profile += 1; | 208 if (frames_.empty()) { |
| 86 return profile; | 209 // No frames to be decoded, if there is no more stream, request more. |
| 87 } | 210 if (!stream_) |
| 88 | 211 return kEOStream; |
| 89 bool Vp9Parser::VerifySyncCode() { | 212 |
| 90 const int kSyncCode = 0x498342; | 213 // New stream to be parsed, parse it and fill frames_. |
| 91 if (reader_.ReadLiteral(8 * 3) != kSyncCode) { | 214 frames_ = ParseSuperframe(); |
| 92 DVLOG(1) << "Invalid frame sync code"; | 215 if (frames_.empty()) { |
| 93 return false; | 216 DVLOG(1) << "Failed parsing superframes"; |
| 94 } | 217 return kInvalidStream; |
| 95 return true; | 218 } |
| 96 } | 219 } |
| 97 | 220 |
| 98 bool Vp9Parser::ReadBitDepthColorSpaceSampling(Vp9FrameHeader* fhdr) { | 221 curr_frame_info_ = frames_.front(); |
| 99 if (fhdr->profile == 2 || fhdr->profile == 3) { | 222 frames_.pop_front(); |
| 100 fhdr->bit_depth = reader_.ReadBool() ? 12 : 10; | 223 |
| 101 } else { | 224 memset(&curr_frame_header_, 0, sizeof(curr_frame_header_)); |
| 102 fhdr->bit_depth = 8; | 225 |
| 103 } | 226 Vp9UncompressedHeaderParser uncompressed_parser(&context_); |
| 104 | 227 if (!uncompressed_parser.Parse(curr_frame_info_.ptr, curr_frame_info_.size, |
| 105 fhdr->color_space = static_cast<Vp9ColorSpace>(reader_.ReadLiteral(3)); | 228 &curr_frame_header_)) |
| 106 if (fhdr->color_space != Vp9ColorSpace::SRGB) { | 229 return kInvalidStream; |
| 107 fhdr->yuv_range = reader_.ReadBool(); | 230 |
| 108 if (fhdr->profile == 1 || fhdr->profile == 3) { | 231 if (curr_frame_header_.header_size_in_bytes == 0) { |
| 109 fhdr->subsampling_x = reader_.ReadBool() ? 1 : 0; | 232 // Verify padding bits are zero. |
| 110 fhdr->subsampling_y = reader_.ReadBool() ? 1 : 0; | 233 for (off_t i = curr_frame_header_.uncompressed_header_size; |
| 111 if (fhdr->subsampling_x == 1 && fhdr->subsampling_y == 1) { | 234 i < curr_frame_info_.size; i++) { |
| 112 DVLOG(1) << "4:2:0 color not supported in profile 1 or 3"; | 235 if (curr_frame_info_.ptr[i] != 0) { |
| 113 return false; | 236 DVLOG(1) << "Padding bits are not zeros."; |
| 114 } | 237 return kInvalidStream; |
| 115 bool reserved = reader_.ReadBool(); | 238 } |
| 116 if (reserved) { | 239 } |
| 117 DVLOG(1) << "reserved bit set"; | 240 *fhdr = curr_frame_header_; |
| 118 return false; | 241 curr_frame_info_.Reset(); |
| 119 } | 242 return kOk; |
| 120 } else { | 243 } |
| 121 fhdr->subsampling_x = fhdr->subsampling_y = 1; | 244 if (curr_frame_header_.uncompressed_header_size + |
| 122 } | 245 curr_frame_header_.header_size_in_bytes > |
| 123 } else { | 246 base::checked_cast<size_t>(curr_frame_info_.size)) { |
| 124 if (fhdr->profile == 1 || fhdr->profile == 3) { | 247 DVLOG(1) << "header_size_in_bytes=" |
| 125 fhdr->subsampling_x = fhdr->subsampling_y = 0; | 248 << curr_frame_header_.header_size_in_bytes |
| 126 | 249 << " is larger than bytes left in buffer: " |
| 127 bool reserved = reader_.ReadBool(); | 250 << curr_frame_info_.size - |
| 128 if (reserved) { | 251 curr_frame_header_.uncompressed_header_size; |
| 129 DVLOG(1) << "reserved bit set"; | 252 return kInvalidStream; |
| 130 return false; | 253 } |
| 131 } | 254 } |
| 132 } else { | 255 |
| 133 DVLOG(1) << "4:4:4 color not supported in profile 0 or 2"; | 256 if (parsing_compressed_header_) { |
| 134 return false; | 257 Vp9FrameContextManager& context_to_load = |
| 135 } | 258 context_.frame_context_managers[curr_frame_header_.frame_context_idx]; |
| 136 } | 259 if (!context_to_load.initialized()) { |
| 137 | 260 // 8.2 Frame order constraints |
| 138 return true; | 261 // must load an initialized set of probabilities. |
| 139 } | 262 DVLOG(1) << "loading uninitialized frame context, index=" |
| 140 | 263 << curr_frame_header_.frame_context_idx; |
| 141 void Vp9Parser::ReadFrameSize(Vp9FrameHeader* fhdr) { | 264 return kInvalidStream; |
| 142 fhdr->width = reader_.ReadLiteral(16) + 1; | 265 } |
| 143 fhdr->height = reader_.ReadLiteral(16) + 1; | 266 if (context_to_load.needs_client_update()) { |
| 144 } | 267 DVLOG(3) << "waiting frame_context_idx=" |
| 145 | 268 << static_cast<int>(curr_frame_header_.frame_context_idx) |
| 146 bool Vp9Parser::ReadFrameSizeFromRefs(Vp9FrameHeader* fhdr) { | 269 << " to update"; |
| 147 for (size_t i = 0; i < kVp9NumRefsPerFrame; i++) { | 270 return kAwaitingRefresh; |
| 148 if (reader_.ReadBool()) { | 271 } |
| 149 fhdr->width = ref_slots_[i].width; | 272 curr_frame_header_.initial_frame_context = |
| 150 fhdr->height = ref_slots_[i].height; | 273 curr_frame_header_.frame_context = context_to_load.frame_context(); |
| 151 | 274 |
| 152 const int kMaxDimension = 1 << 16; | 275 Vp9CompressedHeaderParser compressed_parser; |
| 153 if (fhdr->width == 0 || fhdr->width > kMaxDimension || | 276 if (!compressed_parser.Parse( |
| 154 fhdr->height == 0 || fhdr->height > kMaxDimension) { | 277 curr_frame_info_.ptr + curr_frame_header_.uncompressed_header_size, |
| 155 DVLOG(1) << "The size of reference frame is out of range: " | 278 curr_frame_header_.header_size_in_bytes, &curr_frame_header_)) { |
| 156 << ref_slots_[i].width << "," << ref_slots_[i].height; | 279 return kInvalidStream; |
| 157 return false; | 280 } |
| 158 } | 281 |
| 159 return true; | 282 if (curr_frame_header_.refresh_frame_context) { |
| 160 } | 283 Vp9FrameContextManager& frame_context_manager = |
| 161 } | 284 context_.frame_context_managers[curr_frame_header_.frame_context_idx]; |
| 162 | 285 |
| 163 fhdr->width = reader_.ReadLiteral(16) + 1; | 286 // In frame parallel mode, we can refresh the context without decoding |
| 164 fhdr->height = reader_.ReadLiteral(16) + 1; | 287 // tile data. |
| 165 return true; | 288 if (curr_frame_header_.frame_parallel_decoding_mode) { |
| 166 } | 289 frame_context_manager.Update(curr_frame_header_.frame_context); |
| 167 | |
| 168 void Vp9Parser::ReadDisplayFrameSize(Vp9FrameHeader* fhdr) { | |
| 169 if (reader_.ReadBool()) { | |
| 170 fhdr->display_width = reader_.ReadLiteral(16) + 1; | |
| 171 fhdr->display_height = reader_.ReadLiteral(16) + 1; | |
| 172 } else { | |
| 173 fhdr->display_width = fhdr->width; | |
| 174 fhdr->display_height = fhdr->height; | |
| 175 } | |
| 176 } | |
| 177 | |
| 178 Vp9InterpFilter Vp9Parser::ReadInterpFilter() { | |
| 179 if (reader_.ReadBool()) | |
| 180 return Vp9InterpFilter::SWICHABLE; | |
| 181 | |
| 182 // The mapping table for next two bits. | |
| 183 const Vp9InterpFilter table[] = { | |
| 184 Vp9InterpFilter::EIGHTTAP_SMOOTH, Vp9InterpFilter::EIGHTTAP, | |
| 185 Vp9InterpFilter::EIGHTTAP_SHARP, Vp9InterpFilter::BILINEAR, | |
| 186 }; | |
| 187 return table[reader_.ReadLiteral(2)]; | |
| 188 } | |
| 189 | |
| 190 void Vp9Parser::ReadLoopFilter() { | |
| 191 loop_filter_.filter_level = reader_.ReadLiteral(6); | |
| 192 loop_filter_.sharpness_level = reader_.ReadLiteral(3); | |
| 193 loop_filter_.mode_ref_delta_update = false; | |
| 194 | |
| 195 loop_filter_.mode_ref_delta_enabled = reader_.ReadBool(); | |
| 196 if (loop_filter_.mode_ref_delta_enabled) { | |
| 197 loop_filter_.mode_ref_delta_update = reader_.ReadBool(); | |
| 198 if (loop_filter_.mode_ref_delta_update) { | |
| 199 for (size_t i = 0; i < Vp9LoopFilter::VP9_FRAME_MAX; i++) { | |
| 200 loop_filter_.update_ref_deltas[i] = reader_.ReadBool(); | |
| 201 if (loop_filter_.update_ref_deltas[i]) | |
| 202 loop_filter_.ref_deltas[i] = reader_.ReadSignedLiteral(6); | |
| 203 } | |
| 204 | |
| 205 for (size_t i = 0; i < Vp9LoopFilter::kNumModeDeltas; i++) { | |
| 206 loop_filter_.update_mode_deltas[i] = reader_.ReadBool(); | |
| 207 if (loop_filter_.update_mode_deltas[i]) | |
| 208 loop_filter_.mode_deltas[i] = reader_.ReadLiteral(6); | |
| 209 } | |
| 210 } | |
| 211 } | |
| 212 } | |
| 213 | |
| 214 void Vp9Parser::ReadQuantization(Vp9QuantizationParams* quants) { | |
| 215 quants->base_qindex = reader_.ReadLiteral(8); | |
| 216 | |
| 217 if (reader_.ReadBool()) | |
| 218 quants->y_dc_delta = reader_.ReadSignedLiteral(4); | |
| 219 | |
| 220 if (reader_.ReadBool()) | |
| 221 quants->uv_dc_delta = reader_.ReadSignedLiteral(4); | |
| 222 | |
| 223 if (reader_.ReadBool()) | |
| 224 quants->uv_ac_delta = reader_.ReadSignedLiteral(4); | |
| 225 } | |
| 226 | |
| 227 void Vp9Parser::ReadSegmentationMap() { | |
| 228 for (size_t i = 0; i < Vp9Segmentation::kNumTreeProbs; i++) { | |
| 229 segmentation_.tree_probs[i] = | |
| 230 reader_.ReadBool() ? reader_.ReadLiteral(8) : kVp9MaxProb; | |
| 231 } | |
| 232 | |
| 233 for (size_t i = 0; i < Vp9Segmentation::kNumPredictionProbs; i++) | |
| 234 segmentation_.pred_probs[i] = kVp9MaxProb; | |
| 235 | |
| 236 segmentation_.temporal_update = reader_.ReadBool(); | |
| 237 if (segmentation_.temporal_update) { | |
| 238 for (size_t i = 0; i < Vp9Segmentation::kNumPredictionProbs; i++) { | |
| 239 if (reader_.ReadBool()) | |
| 240 segmentation_.pred_probs[i] = reader_.ReadLiteral(8); | |
| 241 } | |
| 242 } | |
| 243 } | |
| 244 | |
| 245 void Vp9Parser::ReadSegmentationData() { | |
| 246 segmentation_.abs_delta = reader_.ReadBool(); | |
| 247 | |
| 248 const int kFeatureDataBits[] = {8, 6, 2, 0}; | |
| 249 const bool kFeatureDataSigned[] = {true, true, false, false}; | |
| 250 | |
| 251 for (size_t i = 0; i < Vp9Segmentation::kNumSegments; i++) { | |
| 252 for (size_t j = 0; j < Vp9Segmentation::SEG_LVL_MAX; j++) { | |
| 253 int16_t data = 0; | |
| 254 segmentation_.feature_enabled[i][j] = reader_.ReadBool(); | |
| 255 if (segmentation_.feature_enabled[i][j]) { | |
| 256 data = reader_.ReadLiteral(kFeatureDataBits[j]); | |
| 257 if (kFeatureDataSigned[j]) | |
| 258 if (reader_.ReadBool()) | |
| 259 data = -data; | |
| 260 } | |
| 261 segmentation_.feature_data[i][j] = data; | |
| 262 } | |
| 263 } | |
| 264 } | |
| 265 | |
| 266 void Vp9Parser::ReadSegmentation() { | |
| 267 segmentation_.update_map = false; | |
| 268 segmentation_.update_data = false; | |
| 269 | |
| 270 segmentation_.enabled = reader_.ReadBool(); | |
| 271 if (!segmentation_.enabled) | |
| 272 return; | |
| 273 | |
| 274 segmentation_.update_map = reader_.ReadBool(); | |
| 275 if (segmentation_.update_map) | |
| 276 ReadSegmentationMap(); | |
| 277 | |
| 278 segmentation_.update_data = reader_.ReadBool(); | |
| 279 if (segmentation_.update_data) | |
| 280 ReadSegmentationData(); | |
| 281 } | |
| 282 | |
| 283 void Vp9Parser::ReadTiles(Vp9FrameHeader* fhdr) { | |
| 284 int sb64_cols = (fhdr->width + 63) / 64; | |
| 285 | |
| 286 int min_log2_tile_cols = GetMinLog2TileCols(sb64_cols); | |
| 287 int max_log2_tile_cols = GetMaxLog2TileCols(sb64_cols); | |
| 288 | |
| 289 int max_ones = max_log2_tile_cols - min_log2_tile_cols; | |
| 290 fhdr->log2_tile_cols = min_log2_tile_cols; | |
| 291 while (max_ones-- && reader_.ReadBool()) | |
| 292 fhdr->log2_tile_cols++; | |
| 293 | |
| 294 fhdr->log2_tile_rows = reader_.ReadBool() ? 1 : 0; | |
| 295 if (fhdr->log2_tile_rows > 0 && reader_.ReadBool()) | |
| 296 fhdr->log2_tile_rows++; | |
| 297 } | |
| 298 | |
| 299 bool Vp9Parser::ParseUncompressedHeader(const uint8_t* stream, | |
| 300 off_t frame_size, | |
| 301 Vp9FrameHeader* fhdr) { | |
| 302 reader_.Initialize(stream, frame_size); | |
| 303 | |
| 304 fhdr->data = stream; | |
| 305 fhdr->frame_size = frame_size; | |
| 306 | |
| 307 // frame marker | |
| 308 if (reader_.ReadLiteral(2) != 0x2) | |
| 309 return false; | |
| 310 | |
| 311 fhdr->profile = ReadProfile(); | |
| 312 if (fhdr->profile >= kVp9MaxProfile) { | |
| 313 DVLOG(1) << "Unsupported bitstream profile"; | |
| 314 return false; | |
| 315 } | |
| 316 | |
| 317 fhdr->show_existing_frame = reader_.ReadBool(); | |
| 318 if (fhdr->show_existing_frame) { | |
| 319 fhdr->frame_to_show = reader_.ReadLiteral(3); | |
| 320 fhdr->show_frame = true; | |
| 321 | |
| 322 if (!reader_.IsValid()) { | |
| 323 DVLOG(1) << "parser reads beyond the end of buffer"; | |
| 324 return false; | |
| 325 } | |
| 326 fhdr->uncompressed_header_size = reader_.GetBytesRead(); | |
| 327 return true; | |
| 328 } | |
| 329 | |
| 330 fhdr->frame_type = static_cast<Vp9FrameHeader::FrameType>(reader_.ReadBool()); | |
| 331 fhdr->show_frame = reader_.ReadBool(); | |
| 332 fhdr->error_resilient_mode = reader_.ReadBool(); | |
| 333 | |
| 334 if (fhdr->IsKeyframe()) { | |
| 335 if (!VerifySyncCode()) | |
| 336 return false; | |
| 337 | |
| 338 if (!ReadBitDepthColorSpaceSampling(fhdr)) | |
| 339 return false; | |
| 340 | |
| 341 fhdr->refresh_flags = 0xff; | |
| 342 | |
| 343 ReadFrameSize(fhdr); | |
| 344 ReadDisplayFrameSize(fhdr); | |
| 345 } else { | |
| 346 if (!fhdr->show_frame) | |
| 347 fhdr->intra_only = reader_.ReadBool(); | |
| 348 | |
| 349 if (!fhdr->error_resilient_mode) | |
| 350 fhdr->reset_context = reader_.ReadLiteral(2); | |
| 351 | |
| 352 if (fhdr->intra_only) { | |
| 353 if (!VerifySyncCode()) | |
| 354 return false; | |
| 355 | |
| 356 if (fhdr->profile > 0) { | |
| 357 if (!ReadBitDepthColorSpaceSampling(fhdr)) | |
| 358 return false; | |
| 359 } else { | 290 } else { |
| 360 fhdr->bit_depth = 8; | 291 *context_refresh_cb = frame_context_manager.SetNeedsClientUpdate(); |
| 361 fhdr->color_space = Vp9ColorSpace::BT_601; | 292 } |
| 362 fhdr->subsampling_x = fhdr->subsampling_y = 1; | 293 } |
| 363 } | 294 } |
| 364 | 295 |
| 365 fhdr->refresh_flags = reader_.ReadLiteral(8); | 296 SetupSegmentationDequant(); |
| 366 | |
| 367 ReadFrameSize(fhdr); | |
| 368 ReadDisplayFrameSize(fhdr); | |
| 369 } else { | |
| 370 fhdr->refresh_flags = reader_.ReadLiteral(8); | |
| 371 | |
| 372 for (size_t i = 0; i < kVp9NumRefsPerFrame; i++) { | |
| 373 fhdr->frame_refs[i] = reader_.ReadLiteral(kVp9NumRefFramesLog2); | |
| 374 fhdr->ref_sign_biases[i] = reader_.ReadBool(); | |
| 375 } | |
| 376 | |
| 377 if (!ReadFrameSizeFromRefs(fhdr)) | |
| 378 return false; | |
| 379 ReadDisplayFrameSize(fhdr); | |
| 380 | |
| 381 fhdr->allow_high_precision_mv = reader_.ReadBool(); | |
| 382 fhdr->interp_filter = ReadInterpFilter(); | |
| 383 } | |
| 384 } | |
| 385 | |
| 386 if (fhdr->error_resilient_mode) { | |
| 387 fhdr->frame_parallel_decoding_mode = true; | |
| 388 } else { | |
| 389 fhdr->refresh_frame_context = reader_.ReadBool(); | |
| 390 fhdr->frame_parallel_decoding_mode = reader_.ReadBool(); | |
| 391 } | |
| 392 | |
| 393 fhdr->frame_context_idx = reader_.ReadLiteral(2); | |
| 394 | |
| 395 if (fhdr->IsKeyframe() || fhdr->intra_only) | |
| 396 SetupPastIndependence(); | |
| 397 | |
| 398 ReadLoopFilter(); | |
| 399 ReadQuantization(&fhdr->quant_params); | |
| 400 ReadSegmentation(); | |
| 401 | |
| 402 ReadTiles(fhdr); | |
| 403 | |
| 404 fhdr->first_partition_size = reader_.ReadLiteral(16); | |
| 405 if (fhdr->first_partition_size == 0) { | |
| 406 DVLOG(1) << "invalid header size"; | |
| 407 return false; | |
| 408 } | |
| 409 | |
| 410 if (!reader_.IsValid()) { | |
| 411 DVLOG(1) << "parser reads beyond the end of buffer"; | |
| 412 return false; | |
| 413 } | |
| 414 fhdr->uncompressed_header_size = reader_.GetBytesRead(); | |
| 415 | |
| 416 SetupSegmentationDequant(fhdr->quant_params); | |
| 417 SetupLoopFilter(); | 297 SetupLoopFilter(); |
| 418 | 298 UpdateSlots(); |
| 419 UpdateSlots(fhdr); | 299 |
| 420 | 300 *fhdr = curr_frame_header_; |
| 421 return true; | 301 curr_frame_info_.Reset(); |
| 422 } | |
| 423 | |
| 424 void Vp9Parser::UpdateSlots(const Vp9FrameHeader* fhdr) { | |
| 425 for (size_t i = 0; i < kVp9NumRefFrames; i++) { | |
| 426 if (fhdr->RefreshFlag(i)) { | |
| 427 ref_slots_[i].width = fhdr->width; | |
| 428 ref_slots_[i].height = fhdr->height; | |
| 429 } | |
| 430 } | |
| 431 } | |
| 432 | |
| 433 Vp9Parser::Result Vp9Parser::ParseNextFrame(Vp9FrameHeader* fhdr) { | |
| 434 if (frames_.empty()) { | |
| 435 // No frames to be decoded, if there is no more stream, request more. | |
| 436 if (!stream_) | |
| 437 return kEOStream; | |
| 438 | |
| 439 // New stream to be parsed, parse it and fill frames_. | |
| 440 if (!ParseSuperframe()) { | |
| 441 DVLOG(1) << "Failed parsing superframes"; | |
| 442 return kInvalidStream; | |
| 443 } | |
| 444 } | |
| 445 | |
| 446 DCHECK(!frames_.empty()); | |
| 447 FrameInfo frame_info = frames_.front(); | |
| 448 frames_.pop_front(); | |
| 449 | |
| 450 memset(fhdr, 0, sizeof(*fhdr)); | |
| 451 if (!ParseUncompressedHeader(frame_info.ptr, frame_info.size, fhdr)) | |
| 452 return kInvalidStream; | |
| 453 | |
| 454 return kOk; | 302 return kOk; |
| 455 } | 303 } |
| 456 | 304 |
| 457 bool Vp9Parser::ParseSuperframe() { | 305 // Annex B Superframes |
| 306 std::deque<Vp9Parser::FrameInfo> Vp9Parser::ParseSuperframe() { | |
| 458 const uint8_t* stream = stream_; | 307 const uint8_t* stream = stream_; |
| 459 off_t bytes_left = bytes_left_; | 308 off_t bytes_left = bytes_left_; |
| 460 | 309 |
| 461 DCHECK(frames_.empty()); | |
| 462 | |
| 463 // Make sure we don't parse stream_ more than once. | 310 // Make sure we don't parse stream_ more than once. |
| 464 stream_ = nullptr; | 311 stream_ = nullptr; |
| 465 bytes_left_ = 0; | 312 bytes_left_ = 0; |
| 466 | 313 |
| 467 if (bytes_left < 1) | 314 if (bytes_left < 1) |
| 468 return false; | 315 return std::deque<FrameInfo>(); |
| 469 | 316 |
| 470 // If this is a superframe, the last byte in the stream will contain the | 317 // If this is a superframe, the last byte in the stream will contain the |
| 471 // superframe marker. If not, the whole buffer contains a single frame. | 318 // superframe marker. If not, the whole buffer contains a single frame. |
| 472 uint8_t marker = *(stream + bytes_left - 1); | 319 uint8_t marker = *(stream + bytes_left - 1); |
| 473 if ((marker & 0xe0) != 0xc0) { | 320 if ((marker & 0xe0) != 0xc0) { |
| 474 frames_.push_back(FrameInfo(stream, bytes_left)); | 321 return {FrameInfo(stream, bytes_left)}; |
| 475 return true; | |
| 476 } | 322 } |
| 477 | 323 |
| 478 DVLOG(1) << "Parsing a superframe"; | 324 DVLOG(1) << "Parsing a superframe"; |
| 479 | 325 |
| 480 // The bytes immediately before the superframe marker constitute superframe | 326 // The bytes immediately before the superframe marker constitute superframe |
| 481 // index, which stores information about sizes of each frame in it. | 327 // index, which stores information about sizes of each frame in it. |
| 482 // Calculate its size and set index_ptr to the beginning of it. | 328 // Calculate its size and set index_ptr to the beginning of it. |
| 483 size_t num_frames = (marker & 0x7) + 1; | 329 size_t num_frames = (marker & 0x7) + 1; |
| 484 size_t mag = ((marker >> 3) & 0x3) + 1; | 330 size_t mag = ((marker >> 3) & 0x3) + 1; |
| 485 off_t index_size = 2 + mag * num_frames; | 331 off_t index_size = 2 + mag * num_frames; |
| 486 | 332 |
| 487 if (bytes_left < index_size) | 333 if (bytes_left < index_size) |
| 488 return false; | 334 return std::deque<FrameInfo>(); |
| 489 | 335 |
| 490 const uint8_t* index_ptr = stream + bytes_left - index_size; | 336 const uint8_t* index_ptr = stream + bytes_left - index_size; |
| 491 if (marker != *index_ptr) | 337 if (marker != *index_ptr) |
| 492 return false; | 338 return std::deque<FrameInfo>(); |
| 493 | 339 |
| 494 ++index_ptr; | 340 ++index_ptr; |
| 495 bytes_left -= index_size; | 341 bytes_left -= index_size; |
| 496 | 342 |
| 497 // Parse frame information contained in the index and add a pointer to and | 343 // Parse frame information contained in the index and add a pointer to and |
| 498 // size of each frame to frames_. | 344 // size of each frame to frames. |
| 345 std::deque<FrameInfo> frames; | |
| 499 for (size_t i = 0; i < num_frames; ++i) { | 346 for (size_t i = 0; i < num_frames; ++i) { |
| 500 uint32_t size = 0; | 347 uint32_t size = 0; |
| 501 for (size_t j = 0; j < mag; ++j) { | 348 for (size_t j = 0; j < mag; ++j) { |
| 502 size |= *index_ptr << (j * 8); | 349 size |= *index_ptr << (j * 8); |
| 503 ++index_ptr; | 350 ++index_ptr; |
| 504 } | 351 } |
| 505 | 352 |
| 506 if (base::checked_cast<off_t>(size) > bytes_left) { | 353 if (base::checked_cast<off_t>(size) > bytes_left) { |
| 507 DVLOG(1) << "Not enough data in the buffer for frame " << i; | 354 DVLOG(1) << "Not enough data in the buffer for frame " << i; |
| 508 return false; | 355 return std::deque<FrameInfo>(); |
| 509 } | 356 } |
| 510 | 357 |
| 511 frames_.push_back(FrameInfo(stream, size)); | 358 frames.push_back(FrameInfo(stream, size)); |
| 512 stream += size; | 359 stream += size; |
| 513 bytes_left -= size; | 360 bytes_left -= size; |
| 514 | 361 |
| 515 DVLOG(1) << "Frame " << i << ", size: " << size; | 362 DVLOG(1) << "Frame " << i << ", size: " << size; |
| 516 } | 363 } |
| 517 | 364 |
| 518 return true; | 365 return frames; |
| 519 } | 366 } |
| 520 | 367 |
| 521 void Vp9Parser::ResetLoopfilter() { | 368 // 8.6.1 |
| 522 loop_filter_.mode_ref_delta_enabled = true; | |
| 523 loop_filter_.mode_ref_delta_update = true; | |
| 524 | |
| 525 const int8_t default_ref_deltas[] = {1, 0, -1, -1}; | |
| 526 static_assert( | |
| 527 arraysize(default_ref_deltas) == arraysize(loop_filter_.ref_deltas), | |
| 528 "ref_deltas arrays of incorrect size"); | |
| 529 for (size_t i = 0; i < arraysize(loop_filter_.ref_deltas); ++i) | |
| 530 loop_filter_.ref_deltas[i] = default_ref_deltas[i]; | |
| 531 | |
| 532 memset(loop_filter_.mode_deltas, 0, sizeof(loop_filter_.mode_deltas)); | |
| 533 } | |
| 534 | |
| 535 void Vp9Parser::SetupPastIndependence() { | |
| 536 memset(&segmentation_, 0, sizeof(segmentation_)); | |
| 537 ResetLoopfilter(); | |
| 538 } | |
| 539 | |
| 540 const size_t QINDEX_RANGE = 256; | 369 const size_t QINDEX_RANGE = 256; |
| 541 const int16_t kDcQLookup[QINDEX_RANGE] = { | 370 const int16_t kDcQLookup[QINDEX_RANGE] = { |
| 542 4, 8, 8, 9, 10, 11, 12, 12, | 371 4, 8, 8, 9, 10, 11, 12, 12, |
| 543 13, 14, 15, 16, 17, 18, 19, 19, | 372 13, 14, 15, 16, 17, 18, 19, 19, |
| 544 20, 21, 22, 23, 24, 25, 26, 26, | 373 20, 21, 22, 23, 24, 25, 26, 26, |
| 545 27, 28, 29, 30, 31, 32, 32, 33, | 374 27, 28, 29, 30, 31, 32, 32, 33, |
| 546 34, 35, 36, 37, 38, 38, 39, 40, | 375 34, 35, 36, 37, 38, 38, 39, 40, |
| 547 41, 42, 43, 43, 44, 45, 46, 47, | 376 41, 42, 43, 43, 44, 45, 46, 47, |
| 548 48, 48, 49, 50, 51, 52, 53, 53, | 377 48, 48, 49, 50, 51, 52, 53, 53, |
| 549 54, 55, 56, 57, 57, 58, 59, 60, | 378 54, 55, 56, 57, 57, 58, 59, 60, |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 604 864, 881, 898, 915, 933, 951, 969, 988, | 433 864, 881, 898, 915, 933, 951, 969, 988, |
| 605 1007, 1026, 1046, 1066, 1087, 1108, 1129, 1151, | 434 1007, 1026, 1046, 1066, 1087, 1108, 1129, 1151, |
| 606 1173, 1196, 1219, 1243, 1267, 1292, 1317, 1343, | 435 1173, 1196, 1219, 1243, 1267, 1292, 1317, 1343, |
| 607 1369, 1396, 1423, 1451, 1479, 1508, 1537, 1567, | 436 1369, 1396, 1423, 1451, 1479, 1508, 1537, 1567, |
| 608 1597, 1628, 1660, 1692, 1725, 1759, 1793, 1828, | 437 1597, 1628, 1660, 1692, 1725, 1759, 1793, 1828, |
| 609 }; | 438 }; |
| 610 | 439 |
| 611 static_assert(arraysize(kDcQLookup) == arraysize(kAcQLookup), | 440 static_assert(arraysize(kDcQLookup) == arraysize(kAcQLookup), |
| 612 "quantizer lookup arrays of incorrect size"); | 441 "quantizer lookup arrays of incorrect size"); |
| 613 | 442 |
| 614 #define CLAMP_Q(q) \ | 443 static size_t ClampQ(size_t q) { |
| 615 std::min(std::max(static_cast<size_t>(0), q), arraysize(kDcQLookup) - 1) | 444 return std::min(std::max(static_cast<size_t>(0), q), |
| 445 arraysize(kDcQLookup) - 1); | |
| 446 } | |
| 616 | 447 |
| 448 // 8.6.1 Dequantization functions | |
| 617 size_t Vp9Parser::GetQIndex(const Vp9QuantizationParams& quant, | 449 size_t Vp9Parser::GetQIndex(const Vp9QuantizationParams& quant, |
| 618 size_t segid) const { | 450 size_t segid) const { |
| 619 if (segmentation_.FeatureEnabled(segid, Vp9Segmentation::SEG_LVL_ALT_Q)) { | 451 const Vp9SegmentationParams& segmentation = context_.segmentation; |
| 452 | |
| 453 if (segmentation.FeatureEnabled(segid, | |
| 454 Vp9SegmentationParams::SEG_LVL_ALT_Q)) { | |
| 620 int16_t feature_data = | 455 int16_t feature_data = |
| 621 segmentation_.FeatureData(segid, Vp9Segmentation::SEG_LVL_ALT_Q); | 456 segmentation.FeatureData(segid, Vp9SegmentationParams::SEG_LVL_ALT_Q); |
| 622 size_t q_index = segmentation_.abs_delta ? feature_data | 457 size_t q_index = segmentation.abs_or_delta_update |
| 623 : quant.base_qindex + feature_data; | 458 ? feature_data |
| 624 return CLAMP_Q(q_index); | 459 : quant.base_q_idx + feature_data; |
| 460 return ClampQ(q_index); | |
| 625 } | 461 } |
| 626 | 462 |
| 627 return quant.base_qindex; | 463 return quant.base_q_idx; |
| 628 } | 464 } |
| 629 | 465 |
| 630 void Vp9Parser::SetupSegmentationDequant(const Vp9QuantizationParams& quant) { | 466 // 8.6.1 Dequantization functions |
| 631 if (segmentation_.enabled) { | 467 void Vp9Parser::SetupSegmentationDequant() { |
| 632 for (size_t i = 0; i < Vp9Segmentation::kNumSegments; ++i) { | 468 const Vp9QuantizationParams& quant = curr_frame_header_.quant_params; |
| 469 Vp9SegmentationParams& segmentation = context_.segmentation; | |
| 470 | |
| 471 DLOG_IF(ERROR, curr_frame_header_.bit_depth > 8) | |
| 472 << "bit_depth > 8 is not supported " | |
| 473 "yet, kDcQLookup and kAcQLookup " | |
| 474 "need extended"; | |
| 475 if (segmentation.enabled) { | |
| 476 for (size_t i = 0; i < Vp9SegmentationParams::kNumSegments; ++i) { | |
| 633 const size_t q_index = GetQIndex(quant, i); | 477 const size_t q_index = GetQIndex(quant, i); |
| 634 segmentation_.y_dequant[i][0] = | 478 segmentation.y_dequant[i][0] = |
| 635 kDcQLookup[CLAMP_Q(q_index + quant.y_dc_delta)]; | 479 kDcQLookup[ClampQ(q_index + quant.delta_q_y_dc)]; |
| 636 segmentation_.y_dequant[i][1] = kAcQLookup[CLAMP_Q(q_index)]; | 480 segmentation.y_dequant[i][1] = kAcQLookup[ClampQ(q_index)]; |
| 637 segmentation_.uv_dequant[i][0] = | 481 segmentation.uv_dequant[i][0] = |
| 638 kDcQLookup[CLAMP_Q(q_index + quant.uv_dc_delta)]; | 482 kDcQLookup[ClampQ(q_index + quant.delta_q_uv_dc)]; |
| 639 segmentation_.uv_dequant[i][1] = | 483 segmentation.uv_dequant[i][1] = |
| 640 kAcQLookup[CLAMP_Q(q_index + quant.uv_ac_delta)]; | 484 kAcQLookup[ClampQ(q_index + quant.delta_q_uv_ac)]; |
| 641 } | 485 } |
| 642 } else { | 486 } else { |
| 643 const size_t q_index = quant.base_qindex; | 487 const size_t q_index = quant.base_q_idx; |
| 644 segmentation_.y_dequant[0][0] = | 488 segmentation.y_dequant[0][0] = |
| 645 kDcQLookup[CLAMP_Q(q_index + quant.y_dc_delta)]; | 489 kDcQLookup[ClampQ(q_index + quant.delta_q_y_dc)]; |
| 646 segmentation_.y_dequant[0][1] = kAcQLookup[CLAMP_Q(q_index)]; | 490 segmentation.y_dequant[0][1] = kAcQLookup[ClampQ(q_index)]; |
| 647 segmentation_.uv_dequant[0][0] = | 491 segmentation.uv_dequant[0][0] = |
| 648 kDcQLookup[CLAMP_Q(q_index + quant.uv_dc_delta)]; | 492 kDcQLookup[ClampQ(q_index + quant.delta_q_uv_dc)]; |
| 649 segmentation_.uv_dequant[0][1] = | 493 segmentation.uv_dequant[0][1] = |
| 650 kAcQLookup[CLAMP_Q(q_index + quant.uv_ac_delta)]; | 494 kAcQLookup[ClampQ(q_index + quant.delta_q_uv_ac)]; |
| 651 } | 495 } |
| 652 } | 496 } |
| 653 #undef CLAMP_Q | |
| 654 | 497 |
| 655 #define CLAMP_LF(l) std::min(std::max(0, l), kMaxLoopFilterLevel) | 498 static int ClampLf(int lf) { |
| 499 const int kMaxLoopFilterLevel = 63; | |
| 500 return std::min(std::max(0, lf), kMaxLoopFilterLevel); | |
| 501 } | |
| 502 | |
| 503 // 8.8.1 Loop filter frame init process | |
| 656 void Vp9Parser::SetupLoopFilter() { | 504 void Vp9Parser::SetupLoopFilter() { |
| 657 if (!loop_filter_.filter_level) | 505 Vp9LoopFilterParams& loop_filter = context_.loop_filter; |
| 506 if (!loop_filter.level) | |
| 658 return; | 507 return; |
| 659 | 508 |
| 660 int scale = loop_filter_.filter_level < 32 ? 1 : 2; | 509 int scale = loop_filter.level < 32 ? 1 : 2; |
| 661 | 510 |
| 662 for (size_t i = 0; i < Vp9Segmentation::kNumSegments; ++i) { | 511 for (size_t i = 0; i < Vp9SegmentationParams::kNumSegments; ++i) { |
| 663 int level = loop_filter_.filter_level; | 512 int level = loop_filter.level; |
| 513 Vp9SegmentationParams& segmentation = context_.segmentation; | |
| 664 | 514 |
| 665 if (segmentation_.FeatureEnabled(i, Vp9Segmentation::SEG_LVL_ALT_LF)) { | 515 if (segmentation.FeatureEnabled(i, Vp9SegmentationParams::SEG_LVL_ALT_LF)) { |
| 666 int feature_data = | 516 int feature_data = |
| 667 segmentation_.FeatureData(i, Vp9Segmentation::SEG_LVL_ALT_LF); | 517 segmentation.FeatureData(i, Vp9SegmentationParams::SEG_LVL_ALT_LF); |
| 668 level = CLAMP_LF(segmentation_.abs_delta ? feature_data | 518 level = ClampLf(segmentation.abs_or_delta_update ? feature_data |
| 669 : level + feature_data); | 519 : level + feature_data); |
| 670 } | 520 } |
| 671 | 521 |
| 672 if (!loop_filter_.mode_ref_delta_enabled) { | 522 if (!loop_filter.delta_enabled) { |
| 673 memset(loop_filter_.lvl[i], level, sizeof(loop_filter_.lvl[i])); | 523 memset(loop_filter.lvl[i], level, sizeof(loop_filter.lvl[i])); |
| 674 } else { | 524 } else { |
| 675 loop_filter_.lvl[i][Vp9LoopFilter::VP9_FRAME_INTRA][0] = CLAMP_LF( | 525 loop_filter.lvl[i][Vp9RefType::VP9_FRAME_INTRA][0] = ClampLf( |
| 676 level + | 526 level + loop_filter.ref_deltas[Vp9RefType::VP9_FRAME_INTRA] * scale); |
| 677 loop_filter_.ref_deltas[Vp9LoopFilter::VP9_FRAME_INTRA] * scale); | 527 loop_filter.lvl[i][Vp9RefType::VP9_FRAME_INTRA][1] = 0; |
| 678 loop_filter_.lvl[i][Vp9LoopFilter::VP9_FRAME_INTRA][1] = 0; | |
| 679 | 528 |
| 680 for (size_t type = Vp9LoopFilter::VP9_FRAME_LAST; | 529 for (size_t type = Vp9RefType::VP9_FRAME_LAST; |
| 681 type < Vp9LoopFilter::VP9_FRAME_MAX; ++type) { | 530 type < Vp9RefType::VP9_FRAME_MAX; ++type) { |
| 682 for (size_t mode = 0; mode < Vp9LoopFilter::kNumModeDeltas; ++mode) { | 531 for (size_t mode = 0; mode < Vp9LoopFilterParams::kNumModeDeltas; |
| 683 loop_filter_.lvl[i][type][mode] = | 532 ++mode) { |
| 684 CLAMP_LF(level + loop_filter_.ref_deltas[type] * scale + | 533 loop_filter.lvl[i][type][mode] = |
| 685 loop_filter_.mode_deltas[mode] * scale); | 534 ClampLf(level + loop_filter.ref_deltas[type] * scale + |
| 535 loop_filter.mode_deltas[mode] * scale); | |
| 686 } | 536 } |
| 687 } | 537 } |
| 688 } | 538 } |
| 689 } | 539 } |
| 690 } | 540 } |
| 691 #undef CLAMP_LF | 541 |
| 542 void Vp9Parser::UpdateSlots() { | |
| 543 // 8.10 Reference frame update process | |
| 544 for (size_t i = 0; i < kVp9NumRefFrames; i++) { | |
| 545 if (curr_frame_header_.RefreshFlag(i)) { | |
| 546 ReferenceSlot& ref = context_.ref_slots[i]; | |
| 547 ref.initialized = true; | |
| 548 | |
| 549 ref.frame_width = curr_frame_header_.frame_width; | |
| 550 ref.frame_height = curr_frame_header_.frame_height; | |
| 551 ref.subsampling_x = curr_frame_header_.subsampling_x; | |
| 552 ref.subsampling_y = curr_frame_header_.subsampling_y; | |
| 553 ref.bit_depth = curr_frame_header_.bit_depth; | |
| 554 | |
| 555 ref.profile = curr_frame_header_.profile; | |
| 556 ref.color_space = curr_frame_header_.color_space; | |
| 557 } | |
| 558 } | |
| 559 } | |
| 692 | 560 |
| 693 } // namespace media | 561 } // namespace media |
| OLD | NEW |