Implement ScreenshareTemporalLayersChecker

Bug: none
Change-Id: Ic95156d0f47d186e2289264aa9a916511a8e4510
Reviewed-on: https://webrtc-review.googlesource.com/4960
Commit-Queue: Ilya Nikolaevskiy <ilnik@webrtc.org>
Reviewed-by: Erik Språng <sprang@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#20143}
This commit is contained in:
Ilya Nikolaevskiy
2017-10-04 15:07:09 +02:00
committed by Commit Bot
parent bff80f3c19
commit 586629155c
6 changed files with 172 additions and 27 deletions

View File

@ -469,7 +469,8 @@ std::vector<std::set<uint8_t>> GetTemporalDependencies(
DefaultTemporalLayersChecker::DefaultTemporalLayersChecker(
int num_temporal_layers,
uint8_t initial_tl0_pic_idx)
: num_layers_(std::max(1, num_temporal_layers)),
: TemporalLayersChecker(num_temporal_layers, initial_tl0_pic_idx),
num_layers_(std::max(1, num_temporal_layers)),
temporal_ids_(GetTemporalIds(num_layers_)),
temporal_dependencies_(GetTemporalDependencies(num_layers_)),
pattern_idx_(255) {
@ -482,6 +483,13 @@ DefaultTemporalLayersChecker::DefaultTemporalLayersChecker(
bool DefaultTemporalLayersChecker::CheckTemporalConfig(
bool frame_is_keyframe,
const TemporalLayers::FrameConfig& frame_config) {
if (!TemporalLayersChecker::CheckTemporalConfig(frame_is_keyframe,
frame_config)) {
return false;
}
if (frame_config.drop_frame) {
return true;
}
++pattern_idx_;
if (pattern_idx_ == temporal_ids_.size()) {
// All non key-frame buffers should be updated each pattern cycle.

View File

@ -16,6 +16,7 @@
#include "modules/video_coding/include/video_codec_interface.h"
#include "rtc_base/checks.h"
#include "rtc_base/logging.h"
#include "system_wrappers/include/clock.h"
#include "system_wrappers/include/metrics.h"
#include "vpx/vp8cx.h"
@ -62,8 +63,8 @@ ScreenshareTemporalLayersFactory::CreateChecker(
uint8_t initial_tl0_pic_idx) const {
webrtc::TemporalLayersChecker* tlc;
if (simulcast_id == 0) {
tlc = new webrtc::ScreenshareTemporalLayersChecker(temporal_layers,
initial_tl0_pic_idx);
tlc =
new webrtc::TemporalLayersChecker(temporal_layers, initial_tl0_pic_idx);
} else {
TemporalLayersFactory rt_tl_factory;
return rt_tl_factory.CreateChecker(simulcast_id, temporal_layers,
@ -474,17 +475,4 @@ void ScreenshareLayers::UpdateHistograms() {
}
}
}
ScreenshareTemporalLayersChecker::ScreenshareTemporalLayersChecker(
int /*num_temporal_layers*/,
uint8_t /*initial_tl0_pic_idx*/) {}
// TODO(ilnik): Implement layers dependency checks here. Keep track of
// last/golden/arf buffers and sync bits.
bool ScreenshareTemporalLayersChecker::CheckTemporalConfig(
bool /*frame_is_keyframe*/,
const TemporalLayers::FrameConfig& /*frame_config*/) {
return true;
}
} // namespace webrtc

View File

@ -122,15 +122,6 @@ class ScreenshareLayers : public TemporalLayers {
int64_t tl1_target_bitrate_sum_ = 0;
} stats_;
};
class ScreenshareTemporalLayersChecker : public TemporalLayersChecker {
public:
ScreenshareTemporalLayersChecker(int number_of_temporal_layers,
uint8_t initial_tl0_pic_idx);
bool CheckTemporalConfig(
bool frame_is_keyframe,
const TemporalLayers::FrameConfig& frame_config) override;
};
} // namespace webrtc
#endif // MODULES_VIDEO_CODING_CODECS_VP8_SCREENSHARE_LAYERS_H_

View File

@ -0,0 +1,135 @@
/* Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "modules/video_coding/codecs/vp8/temporal_layers.h"
#include <algorithm>
#include <memory>
#include <set>
#include <vector>
#include "modules/include/module_common_types.h"
#include "modules/video_coding/codecs/vp8/include/vp8_common_types.h"
#include "modules/video_coding/include/video_codec_interface.h"
#include "rtc_base/checks.h"
#include "rtc_base/logging.h"
#include "system_wrappers/include/field_trial.h"
namespace webrtc {
TemporalLayersChecker::TemporalLayersChecker(int num_temporal_layers,
uint8_t /*initial_tl0_pic_idx*/)
: num_temporal_layers_(num_temporal_layers),
sequence_number_(0),
last_sync_sequence_number_(0),
last_tl0_sequence_number_(0) {}
bool TemporalLayersChecker::CheckAndUpdateBufferState(
BufferState* state,
bool* need_sync,
bool frame_is_keyframe,
uint8_t temporal_layer,
webrtc::TemporalLayers::BufferFlags flags,
uint32_t sequence_number,
uint32_t* lowest_sequence_referenced) {
if (flags & TemporalLayers::BufferFlags::kReference) {
if (state->temporal_layer > 0) {
*need_sync = false;
}
if (!state->is_keyframe && !frame_is_keyframe &&
state->sequence_number < *lowest_sequence_referenced) {
*lowest_sequence_referenced = state->sequence_number;
}
if (!frame_is_keyframe && !state->is_keyframe &&
state->temporal_layer > temporal_layer) {
LOG(LS_ERROR) << "Frame is referencing higher temporal layer.";
return false;
}
}
if ((flags & TemporalLayers::BufferFlags::kUpdate)) {
state->temporal_layer = temporal_layer;
state->sequence_number = sequence_number;
state->is_keyframe = frame_is_keyframe;
}
if (frame_is_keyframe)
state->is_keyframe = true;
return true;
}
bool TemporalLayersChecker::CheckTemporalConfig(
bool frame_is_keyframe,
const TemporalLayers::FrameConfig& frame_config) {
if (frame_config.drop_frame) {
return true;
}
++sequence_number_;
if (frame_config.packetizer_temporal_idx >= num_temporal_layers_ ||
(frame_config.packetizer_temporal_idx == kNoTemporalIdx &&
num_temporal_layers_ > 1)) {
LOG(LS_ERROR) << "Incorrect temporal layer set for frame: "
<< frame_config.packetizer_temporal_idx
<< " num_temporal_layers: " << num_temporal_layers_;
return false;
}
uint32_t lowest_sequence_referenced = sequence_number_;
bool need_sync = frame_config.packetizer_temporal_idx > 0 &&
frame_config.packetizer_temporal_idx != kNoTemporalIdx;
if (!CheckAndUpdateBufferState(
&last_, &need_sync, frame_is_keyframe,
frame_config.packetizer_temporal_idx, frame_config.last_buffer_flags,
sequence_number_, &lowest_sequence_referenced)) {
LOG(LS_ERROR) << "Error in the Last buffer";
return false;
}
if (!CheckAndUpdateBufferState(&golden_, &need_sync, frame_is_keyframe,
frame_config.packetizer_temporal_idx,
frame_config.golden_buffer_flags,
sequence_number_,
&lowest_sequence_referenced)) {
LOG(LS_ERROR) << "Error in the Golden buffer";
return false;
}
if (!CheckAndUpdateBufferState(
&arf_, &need_sync, frame_is_keyframe,
frame_config.packetizer_temporal_idx, frame_config.arf_buffer_flags,
sequence_number_, &lowest_sequence_referenced)) {
LOG(LS_ERROR) << "Error in the Arf buffer";
return false;
}
if (lowest_sequence_referenced < last_sync_sequence_number_ &&
!frame_is_keyframe) {
LOG(LS_ERROR) << "Reference past the last sync frame. Referenced "
<< lowest_sequence_referenced << ", but sync was at "
<< last_sync_sequence_number_;
return false;
}
if (frame_config.packetizer_temporal_idx == 0) {
last_tl0_sequence_number_ = sequence_number_;
}
if (frame_is_keyframe) {
last_sync_sequence_number_ = sequence_number_;
}
if (need_sync) {
last_sync_sequence_number_ = last_tl0_sequence_number_;
}
if (need_sync != frame_config.layer_sync) {
LOG(LS_ERROR) << "Sync bit is set incorrectly on a frame. Expected: "
<< need_sync << " Actual: " << frame_config.layer_sync;
return false;
}
return true;
}
} // namespace webrtc

View File

@ -171,12 +171,34 @@ class TemporalLayersListener {
// each UpdateLayersConfig() of a corresponding TemporalLayers class.
class TemporalLayersChecker {
public:
TemporalLayersChecker() {}
TemporalLayersChecker(int num_temporal_layers, uint8_t initial_tl0_pic_idx);
virtual ~TemporalLayersChecker() {}
virtual bool CheckTemporalConfig(
bool frame_is_keyframe,
const TemporalLayers::FrameConfig& frame_config) = 0;
const TemporalLayers::FrameConfig& frame_config);
private:
struct BufferState {
BufferState() : is_keyframe(true), temporal_layer(0), sequence_number(0) {}
bool is_keyframe;
uint8_t temporal_layer;
uint32_t sequence_number;
};
bool CheckAndUpdateBufferState(BufferState* state,
bool* need_sync,
bool frame_is_keyframe,
uint8_t temporal_layer,
webrtc::TemporalLayers::BufferFlags flags,
uint32_t sequence_number,
uint32_t* lowest_sequence_referenced);
BufferState last_;
BufferState arf_;
BufferState golden_;
int num_temporal_layers_;
uint32_t sequence_number_;
uint32_t last_sync_sequence_number_;
uint32_t last_tl0_sequence_number_;
};
} // namespace webrtc