Decode Target Information for VP8 libvpx encoder.
In this CL:
- Created static helper function GenericFrameInfo::DecodeTargetInfo to
convert DTI symbols to a list of GenericFrameInfo::OperatingPointIndication.
- Added per frame DTI information for the different stream structures.
Bug: webrtc:10342
Change-Id: I62ff2e9fc9b380fe1d0447ff071e86b6b35ab249
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/129923
Reviewed-by: Danil Chapovalov <danilchap@webrtc.org>
Commit-Queue: Philip Eliasson <philipel@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#27350}
diff --git a/common_video/generic_frame_descriptor/generic_frame_info.cc b/common_video/generic_frame_descriptor/generic_frame_info.cc
index 94a6192..1c01b6c 100644
--- a/common_video/generic_frame_descriptor/generic_frame_info.cc
+++ b/common_video/generic_frame_descriptor/generic_frame_info.cc
@@ -15,6 +15,24 @@
namespace webrtc {
+absl::InlinedVector<GenericFrameInfo::DecodeTargetIndication, 10>
+GenericFrameInfo::DecodeTargetInfo(absl::string_view indication_symbols) {
+ absl::InlinedVector<DecodeTargetIndication, 10> decode_targets;
+ for (char symbol : indication_symbols) {
+ DecodeTargetIndication indication;
+ switch (symbol) {
+ case '-': indication = DecodeTargetIndication::kNotPresent; break;
+ case 'D': indication = DecodeTargetIndication::kDiscardable; break;
+ case 'R': indication = DecodeTargetIndication::kRequired; break;
+ case 'S': indication = DecodeTargetIndication::kSwitch; break;
+ default: RTC_NOTREACHED();
+ }
+ decode_targets.push_back(indication);
+ }
+
+ return decode_targets;
+}
+
GenericFrameInfo::GenericFrameInfo() = default;
GenericFrameInfo::GenericFrameInfo(const GenericFrameInfo&) = default;
GenericFrameInfo::~GenericFrameInfo() = default;
@@ -38,19 +56,7 @@
GenericFrameInfo::Builder& GenericFrameInfo::Builder::Dtis(
absl::string_view indication_symbols) {
- for (const auto& symbol : indication_symbols) {
- DecodeTargetIndication indication;
- switch (symbol) {
- case '-': indication = DecodeTargetIndication::kNotPresent; break;
- case 'D': indication = DecodeTargetIndication::kDiscardable; break;
- case 'R': indication = DecodeTargetIndication::kRequired; break;
- case 'S': indication = DecodeTargetIndication::kSwitch; break;
- default: RTC_NOTREACHED();
- }
-
- info_.decode_target_indications.push_back(indication);
- }
-
+ info_.decode_target_indications = DecodeTargetInfo(indication_symbols);
return *this;
}
diff --git a/common_video/generic_frame_descriptor/generic_frame_info.h b/common_video/generic_frame_descriptor/generic_frame_info.h
index 91a0868..7909291 100644
--- a/common_video/generic_frame_descriptor/generic_frame_info.h
+++ b/common_video/generic_frame_descriptor/generic_frame_info.h
@@ -22,12 +22,15 @@
struct GenericFrameInfo {
enum class DecodeTargetIndication {
- kNotPresent, // GenericFrameInfo::Builder symbol '-'
- kDiscardable, // GenericFrameInfo::Builder symbol 'D'
- kSwitch, // GenericFrameInfo::Builder symbol 'S'
- kRequired // GenericFrameInfo::Builder symbol 'R'
+ kNotPresent, // DecodeTargetInfo symbol '-'
+ kDiscardable, // DecodeTargetInfo symbol 'D'
+ kSwitch, // DecodeTargetInfo symbol 'S'
+ kRequired // DecodeTargetInfo symbol 'R'
};
+ static absl::InlinedVector<DecodeTargetIndication, 10> DecodeTargetInfo(
+ absl::string_view indication_symbols);
+
class Builder;
GenericFrameInfo();
diff --git a/modules/video_coding/codecs/vp8/default_temporal_layers.cc b/modules/video_coding/codecs/vp8/default_temporal_layers.cc
index d47317e..abab490 100644
--- a/modules/video_coding/codecs/vp8/default_temporal_layers.cc
+++ b/modules/video_coding/codecs/vp8/default_temporal_layers.cc
@@ -31,10 +31,10 @@
DefaultTemporalLayers::PendingFrame::PendingFrame(
bool expired,
uint8_t updated_buffers_mask,
- const Vp8FrameConfig& frame_config)
+ const DependencyInfo& dependency_info)
: expired(expired),
updated_buffer_mask(updated_buffers_mask),
- frame_config(frame_config) {}
+ dependency_info(dependency_info) {}
namespace {
using Buffer = Vp8FrameConfig::Buffer;
@@ -99,27 +99,10 @@
}
return flags;
}
-
-// Find the set of buffers that are never updated by the given pattern.
-std::set<Vp8BufferReference> FindKfBuffers(
- const std::vector<Vp8FrameConfig>& frame_configs) {
- std::set<Vp8BufferReference> kf_buffers(kAllBuffers.begin(),
- kAllBuffers.end());
- for (Vp8FrameConfig config : frame_configs) {
- // Get bit-masked set of update buffers for this frame config.
- uint8_t updated_buffers = GetUpdatedBuffers(config);
- for (Vp8BufferReference buffer : kAllBuffers) {
- if (static_cast<uint8_t>(buffer) & updated_buffers) {
- kf_buffers.erase(buffer);
- }
- }
- }
- return kf_buffers;
-}
} // namespace
-std::vector<Vp8FrameConfig> DefaultTemporalLayers::GetTemporalPattern(
- size_t num_layers) {
+std::vector<DefaultTemporalLayers::DependencyInfo>
+DefaultTemporalLayers::GetDependencyInfo(size_t num_layers) {
// For indexing in the patterns described below (which temporal layers they
// belong to), see the diagram above.
// Layer sync is done similarly for all patterns (except single stream) and
@@ -133,10 +116,11 @@
// so that if scene changes occur (user walks between rooms or rotates webcam)
// the 'arf' (or 'golden' respectively) is not stuck on a no-longer relevant
// keyframe.
+
switch (num_layers) {
case 1:
// Always reference and update the same buffer.
- return {Vp8FrameConfig(kReferenceAndUpdate, kNone, kNone)};
+ return {{"S", {kReferenceAndUpdate, kNone, kNone}}};
case 2:
// All layers can reference but not update the 'alt' buffer, this means
// that the 'alt' buffer reference is effectively the last keyframe.
@@ -147,23 +131,23 @@
// 1---1 1---1 ...
// / / / /
// 0---0---0---0 ...
- return {Vp8FrameConfig(kReferenceAndUpdate, kNone, kNone),
- Vp8FrameConfig(kReference, kUpdate, kNone),
- Vp8FrameConfig(kReferenceAndUpdate, kNone, kNone),
- Vp8FrameConfig(kReference, kReference, kNone, kFreezeEntropy)};
+ return {{"SS", {kReferenceAndUpdate, kNone, kNone}},
+ {"-S", {kReference, kUpdate, kNone}},
+ {"SR", {kReferenceAndUpdate, kNone, kNone}},
+ {"-D", {kReference, kReference, kNone, kFreezeEntropy}}};
} else {
// "Default" 8-frame pattern:
// 1---1---1---1 1---1---1---1 ...
// / / / / / / / /
// 0---0---0---0---0---0---0---0 ...
- return {Vp8FrameConfig(kReferenceAndUpdate, kNone, kNone),
- Vp8FrameConfig(kReference, kUpdate, kNone),
- Vp8FrameConfig(kReferenceAndUpdate, kNone, kNone),
- Vp8FrameConfig(kReference, kReferenceAndUpdate, kNone),
- Vp8FrameConfig(kReferenceAndUpdate, kNone, kNone),
- Vp8FrameConfig(kReference, kReferenceAndUpdate, kNone),
- Vp8FrameConfig(kReferenceAndUpdate, kNone, kNone),
- Vp8FrameConfig(kReference, kReference, kNone, kFreezeEntropy)};
+ return {{"SS", {kReferenceAndUpdate, kNone, kNone}},
+ {"-S", {kReference, kUpdate, kNone}},
+ {"SR", {kReferenceAndUpdate, kNone, kNone}},
+ {"-R", {kReference, kReferenceAndUpdate, kNone}},
+ {"SR", {kReferenceAndUpdate, kNone, kNone}},
+ {"-R", {kReference, kReferenceAndUpdate, kNone}},
+ {"SR", {kReferenceAndUpdate, kNone, kNone}},
+ {"-D", {kReference, kReference, kNone, kFreezeEntropy}}};
}
case 3:
if (field_trial::IsEnabled("WebRTC-UseShortVP8TL3Pattern")) {
@@ -183,62 +167,59 @@
// TL1 references 'last' and references and updates 'golden'.
// TL2 references both 'last' & 'golden' and references and updates
// 'arf'.
- return {
- Vp8FrameConfig(kReferenceAndUpdate, kNone, kNone),
- Vp8FrameConfig(kReference, kNone, kUpdate),
- Vp8FrameConfig(kReference, kUpdate, kNone),
- Vp8FrameConfig(kReference, kReference, kReference, kFreezeEntropy)};
+ return {{"SSS", {kReferenceAndUpdate, kNone, kNone}},
+ {"--S", {kReference, kNone, kUpdate}},
+ {"-DR", {kReference, kUpdate, kNone}},
+ {"--D", {kReference, kReference, kReference, kFreezeEntropy}}};
} else {
// All layers can reference but not update the 'alt' buffer, this means
// that the 'alt' buffer reference is effectively the last keyframe.
// TL0 also references and updates the 'last' buffer.
// TL1 also references 'last' and references and updates 'golden'.
// TL2 references both 'last' and 'golden' but updates no buffer.
- return {
- Vp8FrameConfig(kReferenceAndUpdate, kNone, kReference),
- Vp8FrameConfig(kReference, kNone, kReference, kFreezeEntropy),
- Vp8FrameConfig(kReference, kUpdate, kReference),
- Vp8FrameConfig(kReference, kReference, kReference, kFreezeEntropy),
- Vp8FrameConfig(kReferenceAndUpdate, kNone, kReference),
- Vp8FrameConfig(kReference, kReference, kReference, kFreezeEntropy),
- Vp8FrameConfig(kReference, kReferenceAndUpdate, kReference),
- Vp8FrameConfig(kReference, kReference, kReference, kFreezeEntropy)};
+ return {{"SSS", {kReferenceAndUpdate, kNone, kReference}},
+ {"--D", {kReference, kNone, kReference, kFreezeEntropy}},
+ {"-SS", {kReference, kUpdate, kReference}},
+ {"--D", {kReference, kReference, kReference, kFreezeEntropy}},
+ {"SRR", {kReferenceAndUpdate, kNone, kReference}},
+ {"--D", {kReference, kReference, kReference, kFreezeEntropy}},
+ {"-DS", {kReference, kReferenceAndUpdate, kReference}},
+ {"--D", {kReference, kReference, kReference, kFreezeEntropy}}};
}
case 4:
// TL0 references and updates only the 'last' buffer.
// TL1 references 'last' and updates and references 'golden'.
// TL2 references 'last' and 'golden', and references and updates 'arf'.
// TL3 references all buffers but update none of them.
- return {
- Vp8FrameConfig(kReferenceAndUpdate, kNone, kNone),
- Vp8FrameConfig(kReference, kNone, kNone, kFreezeEntropy),
- Vp8FrameConfig(kReference, kNone, kUpdate),
- Vp8FrameConfig(kReference, kNone, kReference, kFreezeEntropy),
- Vp8FrameConfig(kReference, kUpdate, kNone),
- Vp8FrameConfig(kReference, kReference, kReference, kFreezeEntropy),
- Vp8FrameConfig(kReference, kReference, kReferenceAndUpdate),
- Vp8FrameConfig(kReference, kReference, kReference, kFreezeEntropy),
- Vp8FrameConfig(kReferenceAndUpdate, kNone, kNone),
- Vp8FrameConfig(kReference, kReference, kReference, kFreezeEntropy),
- Vp8FrameConfig(kReference, kReference, kReferenceAndUpdate),
- Vp8FrameConfig(kReference, kReference, kReference, kFreezeEntropy),
- Vp8FrameConfig(kReference, kReferenceAndUpdate, kNone),
- Vp8FrameConfig(kReference, kReference, kReference, kFreezeEntropy),
- Vp8FrameConfig(kReference, kReference, kReferenceAndUpdate),
- Vp8FrameConfig(kReference, kReference, kReference, kFreezeEntropy)};
+ // TODO(philipel): Set decode target information for this structure.
+ return {{"----", {kReferenceAndUpdate, kNone, kNone}},
+ {"----", {kReference, kNone, kNone, kFreezeEntropy}},
+ {"----", {kReference, kNone, kUpdate}},
+ {"----", {kReference, kNone, kReference, kFreezeEntropy}},
+ {"----", {kReference, kUpdate, kNone}},
+ {"----", {kReference, kReference, kReference, kFreezeEntropy}},
+ {"----", {kReference, kReference, kReferenceAndUpdate}},
+ {"----", {kReference, kReference, kReference, kFreezeEntropy}},
+ {"----", {kReferenceAndUpdate, kNone, kNone}},
+ {"----", {kReference, kReference, kReference, kFreezeEntropy}},
+ {"----", {kReference, kReference, kReferenceAndUpdate}},
+ {"----", {kReference, kReference, kReference, kFreezeEntropy}},
+ {"----", {kReference, kReferenceAndUpdate, kNone}},
+ {"----", {kReference, kReference, kReference, kFreezeEntropy}},
+ {"----", {kReference, kReference, kReferenceAndUpdate}},
+ {"----", {kReference, kReference, kReference, kFreezeEntropy}}};
default:
RTC_NOTREACHED();
break;
}
RTC_NOTREACHED();
- return {Vp8FrameConfig(kNone, kNone, kNone)};
+ return {{"", {kNone, kNone, kNone}}};
}
DefaultTemporalLayers::DefaultTemporalLayers(int number_of_temporal_layers)
: num_layers_(std::max(1, number_of_temporal_layers)),
temporal_ids_(GetTemporalIds(num_layers_)),
- temporal_pattern_(GetTemporalPattern(num_layers_)),
- kf_buffers_(FindKfBuffers(temporal_pattern_)),
+ temporal_pattern_(GetDependencyInfo(num_layers_)),
pattern_idx_(kUninitializedPatternIndex) {
RTC_CHECK_GE(kMaxTemporalStreams, number_of_temporal_layers);
RTC_CHECK_GE(number_of_temporal_layers, 0);
@@ -257,6 +238,16 @@
for (Vp8BufferReference buffer : kAllBuffers) {
frames_since_buffer_refresh_[buffer] = 0;
}
+
+ kf_buffers_ = {kAllBuffers.begin(), kAllBuffers.end()};
+ for (DependencyInfo info : temporal_pattern_) {
+ uint8_t updated_buffers = GetUpdatedBuffers(info.frame_config);
+
+ for (Vp8BufferReference buffer : kAllBuffers) {
+ if (static_cast<uint8_t>(buffer) & updated_buffers)
+ kf_buffers_.erase(buffer);
+ }
+ }
}
DefaultTemporalLayers::~DefaultTemporalLayers() = default;
@@ -347,7 +338,8 @@
RTC_DCHECK_GT(temporal_pattern_.size(), 0);
pattern_idx_ = (pattern_idx_ + 1) % temporal_pattern_.size();
- Vp8FrameConfig tl_config = temporal_pattern_[pattern_idx_];
+ DependencyInfo dependency_info = temporal_pattern_[pattern_idx_];
+ Vp8FrameConfig& tl_config = dependency_info.frame_config;
tl_config.encoder_layer_id = tl_config.packetizer_temporal_idx =
temporal_ids_[pattern_idx_ % temporal_ids_.size()];
@@ -386,7 +378,7 @@
// Add frame to set of pending frames, awaiting completion.
pending_frames_[timestamp] =
- PendingFrame{false, GetUpdatedBuffers(tl_config), tl_config};
+ PendingFrame{false, GetUpdatedBuffers(tl_config), dependency_info};
#if RTC_DCHECK_IS_ON
// Checker does not yet support encoder frame dropping, so validate flags
@@ -472,10 +464,11 @@
}
PendingFrame& frame = pending_frame->second;
+ const Vp8FrameConfig& frame_config = frame.dependency_info.frame_config;
#if RTC_DCHECK_IS_ON
if (is_keyframe) {
// Signal key-frame so checker resets state.
- RTC_DCHECK(checker_->CheckTemporalConfig(true, frame.frame_config));
+ RTC_DCHECK(checker_->CheckTemporalConfig(true, frame_config));
}
#endif
@@ -503,8 +496,8 @@
}
} else {
// Delta frame, update codec specifics with temporal id and sync flag.
- vp8_info.temporalIdx = frame.frame_config.packetizer_temporal_idx;
- vp8_info.layerSync = frame.frame_config.layer_sync;
+ vp8_info.temporalIdx = frame_config.packetizer_temporal_idx;
+ vp8_info.layerSync = frame_config.layer_sync;
}
}
@@ -513,13 +506,13 @@
RTC_DCHECK_EQ(vp8_info.updatedBuffersCount, 0u);
for (int i = 0; i < static_cast<int>(Buffer::kCount); ++i) {
- if (!is_keyframe && frame.frame_config.References(static_cast<Buffer>(i))) {
+ if (!is_keyframe && frame_config.References(static_cast<Buffer>(i))) {
RTC_DCHECK_LT(vp8_info.referencedBuffersCount,
arraysize(CodecSpecificInfoVP8::referencedBuffers));
vp8_info.referencedBuffers[vp8_info.referencedBuffersCount++] = i;
}
- if (is_keyframe || frame.frame_config.Updates(static_cast<Buffer>(i))) {
+ if (is_keyframe || frame_config.Updates(static_cast<Buffer>(i))) {
RTC_DCHECK_LT(vp8_info.updatedBuffersCount,
arraysize(CodecSpecificInfoVP8::updatedBuffers));
vp8_info.updatedBuffers[vp8_info.updatedBuffersCount++] = i;
@@ -532,6 +525,10 @@
info->template_structure = GetTemplateStructure(num_layers_);
}
+ GenericFrameInfo& generic_frame_info = info->generic_frame_info.emplace();
+ generic_frame_info.decode_target_indications =
+ frame.dependency_info.decode_target_indications;
+
if (!frame.expired) {
for (Vp8BufferReference buffer : kAllBuffers) {
if (frame.updated_buffer_mask & static_cast<uint8_t>(buffer)) {
diff --git a/modules/video_coding/codecs/vp8/default_temporal_layers.h b/modules/video_coding/codecs/vp8/default_temporal_layers.h
index ee2333e..9aa95db 100644
--- a/modules/video_coding/codecs/vp8/default_temporal_layers.h
+++ b/modules/video_coding/codecs/vp8/default_temporal_layers.h
@@ -18,6 +18,7 @@
#include <map>
#include <memory>
#include <set>
+#include <utility>
#include <vector>
#include "absl/types/optional.h"
@@ -61,7 +62,20 @@
void OnRttUpdate(int64_t rtt_ms) override;
private:
- static std::vector<Vp8FrameConfig> GetTemporalPattern(size_t num_layers);
+ struct DependencyInfo {
+ DependencyInfo() = default;
+ DependencyInfo(absl::string_view indication_symbols,
+ Vp8FrameConfig frame_config)
+ : decode_target_indications(
+ GenericFrameInfo::DecodeTargetInfo(indication_symbols)),
+ frame_config(frame_config) {}
+
+ absl::InlinedVector<GenericFrameInfo::DecodeTargetIndication, 10>
+ decode_target_indications;
+ Vp8FrameConfig frame_config;
+ };
+
+ static std::vector<DependencyInfo> GetDependencyInfo(size_t num_layers);
bool IsSyncFrame(const Vp8FrameConfig& config) const;
void ValidateReferences(Vp8FrameConfig::BufferFlags* flags,
Vp8FrameConfig::Vp8BufferReference ref) const;
@@ -69,9 +83,9 @@
const size_t num_layers_;
const std::vector<unsigned int> temporal_ids_;
- const std::vector<Vp8FrameConfig> temporal_pattern_;
+ const std::vector<DependencyInfo> temporal_pattern_;
// Set of buffers that are never updated except by keyframes.
- const std::set<Vp8FrameConfig::Vp8BufferReference> kf_buffers_;
+ std::set<Vp8FrameConfig::Vp8BufferReference> kf_buffers_;
TemplateStructure GetTemplateStructure(int num_layers) const;
uint8_t pattern_idx_;
@@ -82,7 +96,7 @@
PendingFrame();
PendingFrame(bool expired,
uint8_t updated_buffers_mask,
- const Vp8FrameConfig& frame_config);
+ const DependencyInfo& dependency_info);
// Flag indicating if this frame has expired, ie it belongs to a previous
// iteration of the temporal pattern.
bool expired = false;
@@ -90,7 +104,7 @@
// updates.
uint8_t updated_buffer_mask = 0;
// The frame config return by UpdateLayerConfig() for this frame.
- Vp8FrameConfig frame_config;
+ DependencyInfo dependency_info;
};
// Map from rtp timestamp to pending frame status. Reset on pattern loop.
std::map<uint32_t, PendingFrame> pending_frames_;
diff --git a/modules/video_coding/codecs/vp8/screenshare_layers.cc b/modules/video_coding/codecs/vp8/screenshare_layers.cc
index 9412ba4..11a1cbd 100644
--- a/modules/video_coding/codecs/vp8/screenshare_layers.cc
+++ b/modules/video_coding/codecs/vp8/screenshare_layers.cc
@@ -90,16 +90,16 @@
auto it = pending_frame_configs_.find(timestamp);
if (it != pending_frame_configs_.end()) {
// Drop and re-encode, reuse the previous config.
- return it->second;
+ return it->second.frame_config;
}
if (number_of_temporal_layers_ <= 1) {
// No flags needed for 1 layer screenshare.
// TODO(pbos): Consider updating only last, and not all buffers.
- Vp8FrameConfig tl_config(kReferenceAndUpdate, kReferenceAndUpdate,
- kReferenceAndUpdate);
- pending_frame_configs_[timestamp] = tl_config;
- return tl_config;
+ DependencyInfo dependency_info{
+ "S", {kReferenceAndUpdate, kReferenceAndUpdate, kReferenceAndUpdate}};
+ pending_frame_configs_[timestamp] = dependency_info;
+ return dependency_info.frame_config;
}
const int64_t now_ms = rtc::TimeMillis();
@@ -199,35 +199,35 @@
RTC_NOTREACHED();
}
- Vp8FrameConfig tl_config;
+ DependencyInfo dependency_info;
// TODO(pbos): Consider referencing but not updating the 'alt' buffer for all
// layers.
switch (layer_state) {
case TemporalLayerState::kDrop:
- tl_config = Vp8FrameConfig(kNone, kNone, kNone);
+ dependency_info = {"", {kNone, kNone, kNone}};
break;
case TemporalLayerState::kTl0:
// TL0 only references and updates 'last'.
- tl_config = Vp8FrameConfig(kReferenceAndUpdate, kNone, kNone);
- tl_config.packetizer_temporal_idx = 0;
+ dependency_info = {"SS", {kReferenceAndUpdate, kNone, kNone}};
+ dependency_info.frame_config.packetizer_temporal_idx = 0;
break;
case TemporalLayerState::kTl1:
// TL1 references both 'last' and 'golden' but only updates 'golden'.
- tl_config = Vp8FrameConfig(kReference, kReferenceAndUpdate, kNone);
- tl_config.packetizer_temporal_idx = 1;
+ dependency_info = {"-R", {kReference, kReferenceAndUpdate, kNone}};
+ dependency_info.frame_config.packetizer_temporal_idx = 1;
break;
case TemporalLayerState::kTl1Sync:
// Predict from only TL0 to allow participants to switch to the high
// bitrate stream. Updates 'golden' so that TL1 can continue to refer to
// and update 'golden' from this point on.
- tl_config = Vp8FrameConfig(kReference, kUpdate, kNone);
- tl_config.packetizer_temporal_idx = 1;
+ dependency_info = {"-S", {kReference, kUpdate, kNone}};
+ dependency_info.frame_config.packetizer_temporal_idx = 1;
+ dependency_info.frame_config.layer_sync = true;
break;
}
- tl_config.layer_sync = layer_state == TemporalLayerState::kTl1Sync;
- pending_frame_configs_[timestamp] = tl_config;
- return tl_config;
+ pending_frame_configs_[timestamp] = dependency_info;
+ return dependency_info.frame_config;
}
void ScreenshareLayers::OnRatesUpdated(
@@ -286,28 +286,38 @@
return;
}
- absl::optional<Vp8FrameConfig> frame_config;
+ absl::optional<DependencyInfo> dependency_info;
auto it = pending_frame_configs_.find(rtp_timestamp);
if (it != pending_frame_configs_.end()) {
- frame_config = it->second;
+ dependency_info = it->second;
pending_frame_configs_.erase(it);
if (checker_) {
- RTC_DCHECK(checker_->CheckTemporalConfig(is_keyframe, *frame_config));
+ RTC_DCHECK(checker_->CheckTemporalConfig(is_keyframe,
+ dependency_info->frame_config));
}
}
CodecSpecificInfoVP8& vp8_info = info->codecSpecific.VP8;
+ GenericFrameInfo& generic_frame_info = info->generic_frame_info.emplace();
+
if (number_of_temporal_layers_ == 1) {
vp8_info.temporalIdx = kNoTemporalIdx;
vp8_info.layerSync = false;
+ generic_frame_info.decode_target_indications =
+ GenericFrameInfo::DecodeTargetInfo("S");
} else {
int64_t unwrapped_timestamp = time_wrap_handler_.Unwrap(rtp_timestamp);
- if (frame_config) {
- vp8_info.temporalIdx = frame_config->packetizer_temporal_idx;
- vp8_info.layerSync = frame_config->layer_sync;
+ if (dependency_info) {
+ vp8_info.temporalIdx =
+ dependency_info->frame_config.packetizer_temporal_idx;
+ vp8_info.layerSync = dependency_info->frame_config.layer_sync;
+ generic_frame_info.decode_target_indications =
+ dependency_info->decode_target_indications;
} else {
RTC_DCHECK(is_keyframe);
+ generic_frame_info.decode_target_indications =
+ GenericFrameInfo::DecodeTargetInfo("SS");
}
if (is_keyframe) {
@@ -328,13 +338,15 @@
// Note that |frame_config| is not derefernced if |is_keyframe|,
// meaning it's never dereferenced if the optional may be unset.
for (int i = 0; i < static_cast<int>(Buffer::kCount); ++i) {
- if (!is_keyframe && frame_config->References(static_cast<Buffer>(i))) {
+ if (!is_keyframe &&
+ dependency_info->frame_config.References(static_cast<Buffer>(i))) {
RTC_DCHECK_LT(vp8_info.referencedBuffersCount,
arraysize(CodecSpecificInfoVP8::referencedBuffers));
vp8_info.referencedBuffers[vp8_info.referencedBuffersCount++] = i;
}
- if (is_keyframe || frame_config->Updates(static_cast<Buffer>(i))) {
+ if (is_keyframe ||
+ dependency_info->frame_config.Updates(static_cast<Buffer>(i))) {
RTC_DCHECK_LT(vp8_info.updatedBuffersCount,
arraysize(CodecSpecificInfoVP8::updatedBuffers));
vp8_info.updatedBuffers[vp8_info.updatedBuffersCount++] = i;
diff --git a/modules/video_coding/codecs/vp8/screenshare_layers.h b/modules/video_coding/codecs/vp8/screenshare_layers.h
index 6b1bc7e..8fe5fa3 100644
--- a/modules/video_coding/codecs/vp8/screenshare_layers.h
+++ b/modules/video_coding/codecs/vp8/screenshare_layers.h
@@ -11,6 +11,7 @@
#include <map>
#include <memory>
+#include <utility>
#include <vector>
#include "api/video_codecs/vp8_frame_config.h"
@@ -67,6 +68,19 @@
private:
enum class TemporalLayerState : int { kDrop, kTl0, kTl1, kTl1Sync };
+ struct DependencyInfo {
+ DependencyInfo() = default;
+ DependencyInfo(absl::string_view indication_symbols,
+ Vp8FrameConfig frame_config)
+ : decode_target_indications(
+ GenericFrameInfo::DecodeTargetInfo(indication_symbols)),
+ frame_config(frame_config) {}
+
+ absl::InlinedVector<GenericFrameInfo::DecodeTargetIndication, 10>
+ decode_target_indications;
+ Vp8FrameConfig frame_config;
+ };
+
bool TimeToSync(int64_t timestamp) const;
uint32_t GetCodecTargetBitrateKbps() const;
@@ -81,7 +95,7 @@
int max_qp_;
uint32_t max_debt_bytes_;
- std::map<uint32_t, Vp8FrameConfig> pending_frame_configs_;
+ std::map<uint32_t, DependencyInfo> pending_frame_configs_;
// Configured max framerate.
absl::optional<uint32_t> target_framerate_;