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 // | 6 // |
7 // VERBOSE level: | 7 // VERBOSE level: |
8 // 1 something wrong in bitstream | 8 // 1 something wrong in bitstream |
9 // 2 parsing steps | 9 // 2 parsing steps |
10 // 3 parsed values (selected) | 10 // 3 parsed values (selected) |
(...skipping 18 matching lines...) Expand all Loading... | |
29 return !show_existing_frame && frame_type == KEYFRAME; | 29 return !show_existing_frame && frame_type == KEYFRAME; |
30 } | 30 } |
31 | 31 |
32 bool Vp9FrameHeader::IsIntra() const { | 32 bool Vp9FrameHeader::IsIntra() const { |
33 return !show_existing_frame && (frame_type == KEYFRAME || intra_only); | 33 return !show_existing_frame && (frame_type == KEYFRAME || intra_only); |
34 } | 34 } |
35 | 35 |
36 Vp9Parser::FrameInfo::FrameInfo(const uint8_t* ptr, off_t size) | 36 Vp9Parser::FrameInfo::FrameInfo(const uint8_t* ptr, off_t size) |
37 : ptr(ptr), size(size) {} | 37 : ptr(ptr), size(size) {} |
38 | 38 |
39 Vp9FrameContextManager::Vp9FrameContextManager() : weak_ptr_factory_(this) {} | 39 // static |
40 | 40 bool Vp9FrameContext::IsValid(const Vp9FrameContext& context) { |
41 Vp9FrameContextManager::~Vp9FrameContextManager() {} | |
42 | |
43 bool Vp9FrameContextManager::IsValidFrameContext( | |
44 const Vp9FrameContext& context) { | |
45 // probs should be in [1, 255] range. | 41 // probs should be in [1, 255] range. |
46 static_assert(sizeof(Vp9Prob) == 1, | 42 static_assert(sizeof(Vp9Prob) == 1, |
47 "following checks assuming Vp9Prob is single byte"); | 43 "following checks assuming Vp9Prob is single byte"); |
48 if (memchr(context.tx_probs_8x8, 0, sizeof(context.tx_probs_8x8))) | 44 if (memchr(context.tx_probs_8x8, 0, sizeof(context.tx_probs_8x8))) |
49 return false; | 45 return false; |
50 if (memchr(context.tx_probs_16x16, 0, sizeof(context.tx_probs_16x16))) | 46 if (memchr(context.tx_probs_16x16, 0, sizeof(context.tx_probs_16x16))) |
51 return false; | 47 return false; |
52 if (memchr(context.tx_probs_32x32, 0, sizeof(context.tx_probs_32x32))) | 48 if (memchr(context.tx_probs_32x32, 0, sizeof(context.tx_probs_32x32))) |
53 return false; | 49 return false; |
54 | 50 |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
103 if (memchr(context.mv_fr_probs, 0, sizeof(context.mv_fr_probs))) | 99 if (memchr(context.mv_fr_probs, 0, sizeof(context.mv_fr_probs))) |
104 return false; | 100 return false; |
105 if (memchr(context.mv_class0_hp_prob, 0, sizeof(context.mv_class0_hp_prob))) | 101 if (memchr(context.mv_class0_hp_prob, 0, sizeof(context.mv_class0_hp_prob))) |
106 return false; | 102 return false; |
107 if (memchr(context.mv_hp_prob, 0, sizeof(context.mv_hp_prob))) | 103 if (memchr(context.mv_hp_prob, 0, sizeof(context.mv_hp_prob))) |
108 return false; | 104 return false; |
109 | 105 |
110 return true; | 106 return true; |
111 } | 107 } |
112 | 108 |
113 const Vp9FrameContext& Vp9FrameContextManager::frame_context() const { | 109 Vp9Parser::Context::Vp9FrameContextManager::Vp9FrameContextManager() |
110 : weak_ptr_factory_(this) {} | |
111 | |
112 Vp9Parser::Context::Vp9FrameContextManager::~Vp9FrameContextManager() {} | |
113 | |
114 const Vp9FrameContext& | |
115 Vp9Parser::Context::Vp9FrameContextManager::frame_context() const { | |
114 DCHECK(initialized_); | 116 DCHECK(initialized_); |
115 DCHECK(!needs_client_update_); | 117 DCHECK(!needs_client_update_); |
116 return frame_context_; | 118 return frame_context_; |
117 } | 119 } |
118 | 120 |
119 void Vp9FrameContextManager::Reset() { | 121 void Vp9Parser::Context::Vp9FrameContextManager::Reset() { |
120 initialized_ = false; | 122 initialized_ = false; |
121 needs_client_update_ = false; | 123 needs_client_update_ = false; |
122 weak_ptr_factory_.InvalidateWeakPtrs(); | 124 weak_ptr_factory_.InvalidateWeakPtrs(); |
123 } | 125 } |
124 | 126 |
125 Vp9FrameContextManager::ContextRefreshCallback | 127 void Vp9Parser::Context::Vp9FrameContextManager::SetNeedsClientUpdate() { |
126 Vp9FrameContextManager::SetNeedsClientUpdate() { | |
127 DCHECK(!needs_client_update_); | 128 DCHECK(!needs_client_update_); |
128 initialized_ = true; | 129 initialized_ = true; |
129 needs_client_update_ = true; | 130 needs_client_update_ = true; |
130 | |
131 return base::Bind(&Vp9FrameContextManager::UpdateFromClient, | |
132 weak_ptr_factory_.GetWeakPtr()); | |
133 } | 131 } |
134 | 132 |
135 void Vp9FrameContextManager::Update(const Vp9FrameContext& frame_context) { | 133 Vp9Parser::ContextRefreshCallback |
134 Vp9Parser::Context::Vp9FrameContextManager::GetUpdateCb() { | |
135 if (needs_client_update_) | |
136 return base::Bind(&Vp9FrameContextManager::UpdateFromClient, | |
137 weak_ptr_factory_.GetWeakPtr()); | |
138 else | |
139 return Vp9Parser::ContextRefreshCallback(); | |
140 } | |
141 | |
142 void Vp9Parser::Context::Vp9FrameContextManager::Update( | |
143 const Vp9FrameContext& frame_context) { | |
136 // DCHECK because we can trust values from our parser. | 144 // DCHECK because we can trust values from our parser. |
137 DCHECK(IsValidFrameContext(frame_context)); | 145 DCHECK(Vp9FrameContext::IsValid(frame_context)); |
138 initialized_ = true; | 146 initialized_ = true; |
139 frame_context_ = frame_context; | 147 frame_context_ = frame_context; |
140 | 148 |
141 // For frame context we are updating, it may be still awaiting previous | 149 // For frame context we are updating, it may be still awaiting previous |
142 // ContextRefreshCallback. Because we overwrite the value of context here and | 150 // ContextRefreshCallback. Because we overwrite the value of context here and |
143 // previous ContextRefreshCallback no longer matters, invalidate the weak ptr | 151 // previous ContextRefreshCallback no longer matters, invalidate the weak ptr |
144 // to prevent previous ContextRefreshCallback run. | 152 // to prevent previous ContextRefreshCallback run. |
145 // With this optimization, we may be able to parse more frames while previous | 153 // With this optimization, we may be able to parse more frames while previous |
146 // are still decoding. | 154 // are still decoding. |
147 weak_ptr_factory_.InvalidateWeakPtrs(); | 155 weak_ptr_factory_.InvalidateWeakPtrs(); |
148 needs_client_update_ = false; | 156 needs_client_update_ = false; |
149 } | 157 } |
150 | 158 |
151 void Vp9FrameContextManager::UpdateFromClient( | 159 void Vp9Parser::Context::Vp9FrameContextManager::UpdateFromClient( |
152 const Vp9FrameContext& frame_context) { | 160 const Vp9FrameContext& frame_context) { |
153 DVLOG(2) << "Got external frame_context update"; | 161 DVLOG(2) << "Got external frame_context update"; |
154 DCHECK(needs_client_update_); | 162 DCHECK(needs_client_update_); |
155 if (!IsValidFrameContext(frame_context)) { | 163 if (!Vp9FrameContext::IsValid(frame_context)) { |
156 DLOG(ERROR) << "Invalid prob value in frame_context"; | 164 DLOG(ERROR) << "Invalid prob value in frame_context"; |
157 return; | 165 return; |
158 } | 166 } |
159 needs_client_update_ = false; | 167 needs_client_update_ = false; |
160 initialized_ = true; | 168 initialized_ = true; |
161 frame_context_ = frame_context; | 169 frame_context_ = frame_context; |
162 } | 170 } |
163 | 171 |
164 void Vp9Parser::Context::Reset() { | 172 void Vp9Parser::Context::Reset() { |
165 memset(&segmentation, 0, sizeof(segmentation)); | 173 memset(&segmentation, 0, sizeof(segmentation)); |
166 memset(&loop_filter, 0, sizeof(loop_filter)); | 174 memset(&loop_filter, 0, sizeof(loop_filter)); |
167 memset(&ref_slots, 0, sizeof(ref_slots)); | 175 memset(&ref_slots, 0, sizeof(ref_slots)); |
168 for (auto& manager : frame_context_managers) | 176 for (auto& manager : frame_context_managers) |
169 manager.Reset(); | 177 manager.Reset(); |
170 } | 178 } |
171 | 179 |
180 void Vp9Parser::Context::MarkFrameContextForUpdate(size_t frame_context_idx) { | |
181 DCHECK_LT(frame_context_idx, arraysize(frame_context_managers)); | |
182 frame_context_managers[frame_context_idx].SetNeedsClientUpdate(); | |
183 } | |
184 | |
185 void Vp9Parser::Context::UpdateFrameContext( | |
186 size_t frame_context_idx, | |
187 const Vp9FrameContext& frame_context) { | |
188 DCHECK_LT(frame_context_idx, arraysize(frame_context_managers)); | |
189 frame_context_managers[frame_context_idx].Update(frame_context); | |
190 } | |
191 | |
172 Vp9Parser::Vp9Parser(bool parsing_compressed_header) | 192 Vp9Parser::Vp9Parser(bool parsing_compressed_header) |
173 : parsing_compressed_header_(parsing_compressed_header) { | 193 : parsing_compressed_header_(parsing_compressed_header) { |
174 Reset(); | 194 Reset(); |
175 } | 195 } |
176 | 196 |
177 Vp9Parser::~Vp9Parser() {} | 197 Vp9Parser::~Vp9Parser() {} |
178 | 198 |
179 void Vp9Parser::SetStream(const uint8_t* stream, off_t stream_size) { | 199 void Vp9Parser::SetStream(const uint8_t* stream, off_t stream_size) { |
180 DCHECK(stream); | 200 DCHECK(stream); |
181 stream_ = stream; | 201 stream_ = stream; |
182 bytes_left_ = stream_size; | 202 bytes_left_ = stream_size; |
183 frames_.clear(); | 203 frames_.clear(); |
184 } | 204 } |
185 | 205 |
186 void Vp9Parser::Reset() { | 206 void Vp9Parser::Reset() { |
187 stream_ = nullptr; | 207 stream_ = nullptr; |
188 bytes_left_ = 0; | 208 bytes_left_ = 0; |
189 frames_.clear(); | 209 frames_.clear(); |
190 | 210 |
191 context_.Reset(); | 211 context_.Reset(); |
192 } | 212 } |
193 | 213 |
194 Vp9Parser::Result Vp9Parser::ParseNextFrame( | 214 Vp9Parser::Result Vp9Parser::ParseNextFrame(Vp9FrameHeader* fhdr) { |
195 Vp9FrameHeader* fhdr, | |
196 Vp9FrameContextManager::ContextRefreshCallback* context_refresh_cb) { | |
197 DCHECK(fhdr); | 215 DCHECK(fhdr); |
198 DCHECK(!parsing_compressed_header_ || context_refresh_cb); | |
199 DVLOG(2) << "ParseNextFrame"; | 216 DVLOG(2) << "ParseNextFrame"; |
200 | 217 |
201 // If |curr_frame_info_| is valid, uncompressed header was parsed into | 218 // If |curr_frame_info_| is valid, uncompressed header was parsed into |
202 // |curr_frame_header_| and we are awaiting context update to proceed with | 219 // |curr_frame_header_| and we are awaiting context update to proceed with |
203 // compressed header parsing. | 220 // compressed header parsing. |
204 if (!curr_frame_info_.IsValid()) { | 221 if (!curr_frame_info_.IsValid()) { |
205 if (frames_.empty()) { | 222 if (frames_.empty()) { |
206 // No frames to be decoded, if there is no more stream, request more. | 223 // No frames to be decoded, if there is no more stream, request more. |
207 if (!stream_) | 224 if (!stream_) |
208 return kEOStream; | 225 return kEOStream; |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
244 DVLOG(1) << "header_size_in_bytes=" | 261 DVLOG(1) << "header_size_in_bytes=" |
245 << curr_frame_header_.header_size_in_bytes | 262 << curr_frame_header_.header_size_in_bytes |
246 << " is larger than bytes left in buffer: " | 263 << " is larger than bytes left in buffer: " |
247 << curr_frame_info_.size - | 264 << curr_frame_info_.size - |
248 curr_frame_header_.uncompressed_header_size; | 265 curr_frame_header_.uncompressed_header_size; |
249 return kInvalidStream; | 266 return kInvalidStream; |
250 } | 267 } |
251 } | 268 } |
252 | 269 |
253 if (parsing_compressed_header_) { | 270 if (parsing_compressed_header_) { |
254 Vp9FrameContextManager& context_to_load = | 271 size_t frame_context_idx = curr_frame_header_.frame_context_idx; |
255 context_.frame_context_managers[curr_frame_header_.frame_context_idx]; | 272 const Context::Vp9FrameContextManager& context_to_load = |
273 context_.frame_context_managers[frame_context_idx]; | |
256 if (!context_to_load.initialized()) { | 274 if (!context_to_load.initialized()) { |
257 // 8.2 Frame order constraints | 275 // 8.2 Frame order constraints |
258 // must load an initialized set of probabilities. | 276 // must load an initialized set of probabilities. |
259 DVLOG(1) << "loading uninitialized frame context, index=" | 277 DVLOG(1) << "loading uninitialized frame context, index=" |
260 << curr_frame_header_.frame_context_idx; | 278 << frame_context_idx; |
261 return kInvalidStream; | 279 return kInvalidStream; |
262 } | 280 } |
263 if (context_to_load.needs_client_update()) { | 281 if (context_to_load.needs_client_update()) { |
264 DVLOG(3) << "waiting frame_context_idx=" | 282 DVLOG(3) << "waiting frame_context_idx=" |
265 << static_cast<int>(curr_frame_header_.frame_context_idx) | 283 << static_cast<int>(frame_context_idx) << " to update"; |
kcwu
2016/08/10 09:59:18
no longer needed to cast for size_t.
Pawel Osciak
2016/08/13 01:51:30
Done.
| |
266 << " to update"; | |
267 return kAwaitingRefresh; | 284 return kAwaitingRefresh; |
268 } | 285 } |
269 curr_frame_header_.initial_frame_context = | 286 curr_frame_header_.initial_frame_context = |
270 curr_frame_header_.frame_context = context_to_load.frame_context(); | 287 curr_frame_header_.frame_context = context_to_load.frame_context(); |
271 | 288 |
272 Vp9CompressedHeaderParser compressed_parser; | 289 Vp9CompressedHeaderParser compressed_parser; |
273 if (!compressed_parser.Parse( | 290 if (!compressed_parser.Parse( |
274 curr_frame_info_.ptr + curr_frame_header_.uncompressed_header_size, | 291 curr_frame_info_.ptr + curr_frame_header_.uncompressed_header_size, |
275 curr_frame_header_.header_size_in_bytes, &curr_frame_header_)) { | 292 curr_frame_header_.header_size_in_bytes, &curr_frame_header_)) { |
276 return kInvalidStream; | 293 return kInvalidStream; |
277 } | 294 } |
278 | 295 |
279 if (curr_frame_header_.refresh_frame_context) { | 296 if (curr_frame_header_.refresh_frame_context) { |
280 Vp9FrameContextManager& frame_context_manager = | |
281 context_.frame_context_managers[curr_frame_header_.frame_context_idx]; | |
282 | |
283 // In frame parallel mode, we can refresh the context without decoding | 297 // In frame parallel mode, we can refresh the context without decoding |
284 // tile data. | 298 // tile data. |
285 if (curr_frame_header_.frame_parallel_decoding_mode) { | 299 if (curr_frame_header_.frame_parallel_decoding_mode) { |
286 frame_context_manager.Update(curr_frame_header_.frame_context); | 300 context_.UpdateFrameContext(frame_context_idx, |
301 curr_frame_header_.frame_context); | |
287 } else { | 302 } else { |
288 *context_refresh_cb = frame_context_manager.SetNeedsClientUpdate(); | 303 context_.MarkFrameContextForUpdate(frame_context_idx); |
289 } | 304 } |
290 } | 305 } |
291 } | 306 } |
292 | 307 |
293 SetupSegmentationDequant(); | 308 SetupSegmentationDequant(); |
294 SetupLoopFilter(); | 309 SetupLoopFilter(); |
295 UpdateSlots(); | 310 UpdateSlots(); |
296 | 311 |
297 *fhdr = curr_frame_header_; | 312 *fhdr = curr_frame_header_; |
298 curr_frame_info_.Reset(); | 313 curr_frame_info_.Reset(); |
299 return kOk; | 314 return kOk; |
300 } | 315 } |
301 | 316 |
317 Vp9Parser::ContextRefreshCallback Vp9Parser::GetContextRefreshCb( | |
318 const std::unique_ptr<Vp9FrameHeader>& frame_hdr) { | |
319 auto& frame_context_manager = | |
320 context_.frame_context_managers[frame_hdr->frame_context_idx]; | |
321 | |
322 return frame_context_manager.GetUpdateCb(); | |
323 } | |
324 | |
302 // Annex B Superframes | 325 // Annex B Superframes |
303 std::deque<Vp9Parser::FrameInfo> Vp9Parser::ParseSuperframe() { | 326 std::deque<Vp9Parser::FrameInfo> Vp9Parser::ParseSuperframe() { |
304 const uint8_t* stream = stream_; | 327 const uint8_t* stream = stream_; |
305 off_t bytes_left = bytes_left_; | 328 off_t bytes_left = bytes_left_; |
306 | 329 |
307 // Make sure we don't parse stream_ more than once. | 330 // Make sure we don't parse stream_ more than once. |
308 stream_ = nullptr; | 331 stream_ = nullptr; |
309 bytes_left_ = 0; | 332 bytes_left_ = 0; |
310 | 333 |
311 if (bytes_left < 1) | 334 if (bytes_left < 1) |
(...skipping 237 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
549 ref.subsampling_y = curr_frame_header_.subsampling_y; | 572 ref.subsampling_y = curr_frame_header_.subsampling_y; |
550 ref.bit_depth = curr_frame_header_.bit_depth; | 573 ref.bit_depth = curr_frame_header_.bit_depth; |
551 | 574 |
552 ref.profile = curr_frame_header_.profile; | 575 ref.profile = curr_frame_header_.profile; |
553 ref.color_space = curr_frame_header_.color_space; | 576 ref.color_space = curr_frame_header_.color_space; |
554 } | 577 } |
555 } | 578 } |
556 } | 579 } |
557 | 580 |
558 } // namespace media | 581 } // namespace media |
OLD | NEW |