webrtc/modules/video_coding/codecs/vp8/temporal_layers.cc
Niels Möller 150dcb0a9a Delete logic to set picture id and tl0 pic idx in encoders.
It would be nice to also delete the fields from CodecSpecificInfo,
but those fields are used on the receive side.

Bug: webrtc:8830
Change-Id: I1a3f13ea2c024cbd73b33fd9dd58e531d3576a55
Reviewed-on: https://webrtc-review.googlesource.com/64780
Commit-Queue: Niels Moller <nisse@webrtc.org>
Reviewed-by: Erik Språng <sprang@webrtc.org>
Reviewed-by: Åsa Persson <asapersson@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#22625}
2018-03-27 13:11:16 +00:00

183 lines
6.4 KiB
C++

/* 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/default_temporal_layers.h"
#include "modules/video_coding/codecs/vp8/include/vp8_common_types.h"
#include "modules/video_coding/codecs/vp8/screenshare_layers.h"
#include "modules/video_coding/include/video_codec_interface.h"
#include "rtc_base/checks.h"
#include "rtc_base/logging.h"
#include "rtc_base/ptr_util.h"
#include "system_wrappers/include/clock.h"
#include "system_wrappers/include/field_trial.h"
namespace webrtc {
namespace {
uint8_t NumTemporalLayers(const VideoCodec& codec, int spatial_id) {
uint8_t num_temporal_layers =
std::max<uint8_t>(1, codec.VP8().numberOfTemporalLayers);
if (codec.numberOfSimulcastStreams > 0) {
RTC_DCHECK_LT(spatial_id, codec.numberOfSimulcastStreams);
num_temporal_layers =
std::max(num_temporal_layers,
codec.simulcastStream[spatial_id].numberOfTemporalLayers);
}
return num_temporal_layers;
}
bool IsConferenceModeScreenshare(const VideoCodec& codec) {
if (codec.mode != kScreensharing) {
return false;
}
return NumTemporalLayers(codec, 0) == 2;
}
} // namespace
std::unique_ptr<TemporalLayers> TemporalLayers::CreateTemporalLayers(
const VideoCodec& codec,
size_t spatial_id) {
if (IsConferenceModeScreenshare(codec) && spatial_id == 0) {
// Conference mode temporal layering for screen content in base stream.
return rtc::MakeUnique<ScreenshareLayers>(2, Clock::GetRealTimeClock());
}
return rtc::MakeUnique<DefaultTemporalLayers>(
NumTemporalLayers(codec, spatial_id));
}
std::unique_ptr<TemporalLayersChecker>
TemporalLayers::CreateTemporalLayersChecker(const VideoCodec& codec,
size_t spatial_id) {
if (IsConferenceModeScreenshare(codec) && spatial_id == 0) {
// Conference mode temporal layering for screen content in base stream,
// use generic checker.
return rtc::MakeUnique<TemporalLayersChecker>(2);
}
return rtc::MakeUnique<DefaultTemporalLayersChecker>(
NumTemporalLayers(codec, spatial_id));
}
TemporalLayersChecker::TemporalLayersChecker(int num_temporal_layers)
: 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) {
RTC_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)) {
RTC_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)) {
RTC_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)) {
RTC_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)) {
RTC_LOG(LS_ERROR) << "Error in the Arf buffer";
return false;
}
if (lowest_sequence_referenced < last_sync_sequence_number_ &&
!frame_is_keyframe) {
RTC_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) {
RTC_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