OLD | NEW |
1 /* Copyright (c) 2013 The WebRTC project authors. All Rights Reserved. | 1 /* Copyright (c) 2013 The WebRTC project authors. All Rights Reserved. |
2 * | 2 * |
3 * Use of this source code is governed by a BSD-style license | 3 * Use of this source code is governed by a BSD-style license |
4 * that can be found in the LICENSE file in the root of the source | 4 * that can be found in the LICENSE file in the root of the source |
5 * tree. An additional intellectual property rights grant can be found | 5 * tree. An additional intellectual property rights grant can be found |
6 * in the file PATENTS. All contributing project authors may | 6 * in the file PATENTS. All contributing project authors may |
7 * be found in the AUTHORS file in the root of the source tree. | 7 * be found in the AUTHORS file in the root of the source tree. |
8 */ | 8 */ |
9 | 9 |
10 #include "webrtc/modules/video_coding/codecs/vp8/default_temporal_layers.h" | 10 #include "webrtc/modules/video_coding/codecs/vp8/default_temporal_layers.h" |
11 | 11 |
12 #include <stdlib.h> | 12 #include <stdlib.h> |
13 #include <string.h> | 13 #include <string.h> |
14 | 14 |
15 #include <algorithm> | 15 #include <algorithm> |
16 #include <vector> | 16 #include <vector> |
17 | 17 |
18 #include "webrtc/base/checks.h" | 18 #include "webrtc/base/checks.h" |
19 #include "webrtc/modules/include/module_common_types.h" | 19 #include "webrtc/modules/include/module_common_types.h" |
20 #include "webrtc/modules/video_coding/include/video_codec_interface.h" | 20 #include "webrtc/modules/video_coding/include/video_codec_interface.h" |
21 #include "webrtc/modules/video_coding/codecs/vp8/include/vp8_common_types.h" | 21 #include "webrtc/modules/video_coding/codecs/vp8/include/vp8_common_types.h" |
22 | 22 |
23 #include "vpx/vpx_encoder.h" | 23 #include "vpx/vpx_encoder.h" |
24 #include "vpx/vp8cx.h" | 24 #include "vpx/vp8cx.h" |
25 | 25 |
26 namespace webrtc { | 26 namespace webrtc { |
27 | 27 |
28 TemporalReferences::TemporalReferences(TemporalBufferUsage last, | 28 TemporalReferences::TemporalReferences(TemporalBufferFlags last, |
29 TemporalBufferUsage golden, | 29 TemporalBufferFlags golden, |
30 TemporalBufferUsage arf) | 30 TemporalBufferFlags arf) |
31 : TemporalReferences(last, golden, arf, false, false) {} | 31 : TemporalReferences(last, golden, arf, false, false) {} |
32 | 32 |
33 TemporalReferences::TemporalReferences(TemporalBufferUsage last, | 33 TemporalReferences::TemporalReferences(TemporalBufferFlags last, |
34 TemporalBufferUsage golden, | 34 TemporalBufferFlags golden, |
35 TemporalBufferUsage arf, | 35 TemporalBufferFlags arf, |
36 int extra_flags) | 36 int extra_flags) |
37 : TemporalReferences(last, | 37 : TemporalReferences(last, |
38 golden, | 38 golden, |
39 arf, | 39 arf, |
40 (extra_flags & kLayerSync) != 0, | 40 (extra_flags & kLayerSync) != 0, |
41 (extra_flags & kFreezeEntropy) != 0) {} | 41 (extra_flags & kFreezeEntropy) != 0) {} |
42 | 42 |
43 TemporalReferences::TemporalReferences(TemporalBufferUsage last, | 43 TemporalReferences::TemporalReferences(TemporalBufferFlags last, |
44 TemporalBufferUsage golden, | 44 TemporalBufferFlags golden, |
45 TemporalBufferUsage arf, | 45 TemporalBufferFlags arf, |
46 bool layer_sync, | 46 bool layer_sync, |
47 bool freeze_entropy) | 47 bool freeze_entropy) |
48 : reference_last((last & kReference) != 0), | 48 : drop_frame(last == kNone && golden == kNone && arf == kNone), |
49 update_last((last & kUpdate) != 0), | 49 last_buffer_flags(last), |
50 reference_golden((golden & kReference) != 0), | 50 golden_buffer_flags(golden), |
51 update_golden((golden & kUpdate) != 0), | 51 arf_buffer_flags(arf), |
52 reference_arf((arf & kReference) != 0), | |
53 update_arf((arf & kUpdate) != 0), | |
54 layer_sync(layer_sync), | 52 layer_sync(layer_sync), |
55 freeze_entropy(freeze_entropy) {} | 53 freeze_entropy(freeze_entropy) {} |
56 | 54 |
57 namespace { | 55 namespace { |
58 | 56 |
59 std::vector<unsigned int> GetTemporalIds(size_t num_layers) { | 57 std::vector<unsigned int> GetTemporalIds(size_t num_layers) { |
60 switch (num_layers) { | 58 switch (num_layers) { |
61 case 1: | 59 case 1: |
62 // Temporal layer structure (single layer): | 60 // Temporal layer structure (single layer): |
63 // 0 0 0 0 ... | 61 // 0 0 0 0 ... |
(...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
239 cfg->ts_number_layers = num_layers_; | 237 cfg->ts_number_layers = num_layers_; |
240 cfg->ts_periodicity = temporal_ids_.size(); | 238 cfg->ts_periodicity = temporal_ids_.size(); |
241 memcpy(cfg->ts_layer_id, &temporal_ids_[0], | 239 memcpy(cfg->ts_layer_id, &temporal_ids_[0], |
242 sizeof(unsigned int) * temporal_ids_.size()); | 240 sizeof(unsigned int) * temporal_ids_.size()); |
243 | 241 |
244 new_bitrates_kbps_ = rtc::Optional<std::vector<uint32_t>>(); | 242 new_bitrates_kbps_ = rtc::Optional<std::vector<uint32_t>>(); |
245 | 243 |
246 return true; | 244 return true; |
247 } | 245 } |
248 | 246 |
249 int DefaultTemporalLayers::EncodeFlags(uint32_t timestamp) { | 247 // TODO(pbos): Name method so that it's obvious that it updates state. |
| 248 TemporalReferences DefaultTemporalLayers::UpdateLayerConfig( |
| 249 uint32_t timestamp) { |
250 RTC_DCHECK_GT(num_layers_, 0); | 250 RTC_DCHECK_GT(num_layers_, 0); |
251 RTC_DCHECK_LT(0, temporal_pattern_.size()); | 251 RTC_DCHECK_LT(0, temporal_pattern_.size()); |
| 252 return temporal_pattern_[++pattern_idx_ % temporal_pattern_.size()]; |
| 253 } |
| 254 |
| 255 int TemporalLayers::EncodeFlags(uint32_t timestamp) { |
| 256 TemporalReferences references = UpdateLayerConfig(timestamp); |
| 257 if (references.drop_frame) |
| 258 return -1; |
| 259 |
252 int flags = 0; | 260 int flags = 0; |
253 // TODO(pbos): Move pattern-update out of EncodeFlags. It's not obvious that | |
254 // EncodeFlags() is non-const. | |
255 const TemporalReferences& references = | |
256 temporal_pattern_[++pattern_idx_ % temporal_pattern_.size()]; | |
257 | 261 |
258 if (!references.reference_last) | 262 if ((references.last_buffer_flags & kReference) == 0) |
259 flags |= VP8_EFLAG_NO_REF_LAST; | 263 flags |= VP8_EFLAG_NO_REF_LAST; |
260 if (!references.update_last) | 264 if ((references.last_buffer_flags & kUpdate) == 0) |
261 flags |= VP8_EFLAG_NO_UPD_LAST; | 265 flags |= VP8_EFLAG_NO_UPD_LAST; |
262 if (!references.reference_golden) | 266 if ((references.golden_buffer_flags & kReference) == 0) |
263 flags |= VP8_EFLAG_NO_REF_GF; | 267 flags |= VP8_EFLAG_NO_REF_GF; |
264 if (!references.update_golden) | 268 if ((references.golden_buffer_flags & kUpdate) == 0) |
265 flags |= VP8_EFLAG_NO_UPD_GF; | 269 flags |= VP8_EFLAG_NO_UPD_GF; |
266 if (!references.reference_arf) | 270 if ((references.arf_buffer_flags & kReference) == 0) |
267 flags |= VP8_EFLAG_NO_REF_ARF; | 271 flags |= VP8_EFLAG_NO_REF_ARF; |
268 if (!references.update_arf) | 272 if ((references.arf_buffer_flags & kUpdate) == 0) |
269 flags |= VP8_EFLAG_NO_UPD_ARF; | 273 flags |= VP8_EFLAG_NO_UPD_ARF; |
270 if (references.freeze_entropy) | 274 if (references.freeze_entropy) |
271 flags |= VP8_EFLAG_NO_UPD_ENTROPY; | 275 flags |= VP8_EFLAG_NO_UPD_ENTROPY; |
272 | 276 |
273 return flags; | 277 return flags; |
274 } | 278 } |
275 | 279 |
276 void DefaultTemporalLayers::PopulateCodecSpecific( | 280 void DefaultTemporalLayers::PopulateCodecSpecific( |
277 bool base_layer_sync, | 281 bool frame_is_keyframe, |
278 CodecSpecificInfoVP8* vp8_info, | 282 CodecSpecificInfoVP8* vp8_info, |
279 uint32_t timestamp) { | 283 uint32_t timestamp) { |
280 RTC_DCHECK_GT(num_layers_, 0); | 284 RTC_DCHECK_GT(num_layers_, 0); |
281 | 285 |
282 if (num_layers_ == 1) { | 286 if (num_layers_ == 1) { |
283 vp8_info->temporalIdx = kNoTemporalIdx; | 287 vp8_info->temporalIdx = kNoTemporalIdx; |
284 vp8_info->layerSync = false; | 288 vp8_info->layerSync = false; |
285 vp8_info->tl0PicIdx = kNoTl0PicIdx; | 289 vp8_info->tl0PicIdx = kNoTl0PicIdx; |
286 } else { | 290 } else { |
287 if (base_layer_sync) { | 291 if (frame_is_keyframe) { |
288 vp8_info->temporalIdx = 0; | 292 vp8_info->temporalIdx = 0; |
289 vp8_info->layerSync = true; | 293 vp8_info->layerSync = true; |
290 } else { | 294 } else { |
291 vp8_info->temporalIdx = CurrentLayerId(); | 295 vp8_info->temporalIdx = CurrentLayerId(); |
292 TemporalReferences temporal_reference = | 296 TemporalReferences temporal_reference = |
293 temporal_pattern_[pattern_idx_ % temporal_pattern_.size()]; | 297 temporal_pattern_[pattern_idx_ % temporal_pattern_.size()]; |
294 | 298 |
295 vp8_info->layerSync = temporal_reference.layer_sync; | 299 vp8_info->layerSync = temporal_reference.layer_sync; |
296 } | 300 } |
297 if (last_base_layer_sync_ && vp8_info->temporalIdx != 0) { | 301 if (last_base_layer_sync_ && vp8_info->temporalIdx != 0) { |
298 // Regardless of pattern the frame after a base layer sync will always | 302 // Regardless of pattern the frame after a base layer sync will always |
299 // be a layer sync. | 303 // be a layer sync. |
300 vp8_info->layerSync = true; | 304 vp8_info->layerSync = true; |
301 } | 305 } |
302 if (vp8_info->temporalIdx == 0 && timestamp != timestamp_) { | 306 if (vp8_info->temporalIdx == 0 && timestamp != timestamp_) { |
303 timestamp_ = timestamp; | 307 timestamp_ = timestamp; |
304 tl0_pic_idx_++; | 308 tl0_pic_idx_++; |
305 } | 309 } |
306 last_base_layer_sync_ = base_layer_sync; | 310 last_base_layer_sync_ = frame_is_keyframe; |
307 vp8_info->tl0PicIdx = tl0_pic_idx_; | 311 vp8_info->tl0PicIdx = tl0_pic_idx_; |
308 } | 312 } |
309 } | 313 } |
310 | 314 |
311 TemporalLayers* TemporalLayersFactory::Create( | 315 TemporalLayers* TemporalLayersFactory::Create( |
312 int simulcast_id, | 316 int simulcast_id, |
313 int temporal_layers, | 317 int temporal_layers, |
314 uint8_t initial_tl0_pic_idx) const { | 318 uint8_t initial_tl0_pic_idx) const { |
315 TemporalLayers* tl = | 319 TemporalLayers* tl = |
316 new DefaultTemporalLayers(temporal_layers, initial_tl0_pic_idx); | 320 new DefaultTemporalLayers(temporal_layers, initial_tl0_pic_idx); |
317 if (listener_) | 321 if (listener_) |
318 listener_->OnTemporalLayersCreated(simulcast_id, tl); | 322 listener_->OnTemporalLayersCreated(simulcast_id, tl); |
319 return tl; | 323 return tl; |
320 } | 324 } |
321 | 325 |
322 void TemporalLayersFactory::SetListener(TemporalLayersListener* listener) { | 326 void TemporalLayersFactory::SetListener(TemporalLayersListener* listener) { |
323 listener_ = listener; | 327 listener_ = listener; |
324 } | 328 } |
325 | 329 |
326 } // namespace webrtc | 330 } // namespace webrtc |
OLD | NEW |