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:
committed by
Commit Bot
parent
bff80f3c19
commit
586629155c
@ -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.
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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_
|
||||
|
||||
135
modules/video_coding/codecs/vp8/temporal_layers.cc
Normal file
135
modules/video_coding/codecs/vp8/temporal_layers.cc
Normal 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
|
||||
@ -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
|
||||
|
||||
Reference in New Issue
Block a user