Don't update internal state of the FrameBuffer2 when an undecodable frame is inserted.

Bug: chromium:844313
Change-Id: I034bcb47092815695084e37c81150bafbfbc6b9c
Reviewed-on: https://webrtc-review.googlesource.com/79944
Commit-Queue: Philip Eliasson <philipel@webrtc.org>
Reviewed-by: Björn Terelius <terelius@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#23577}
This commit is contained in:
philipel
2018-06-11 13:10:14 +02:00
committed by Commit Bot
parent dadaaee3e8
commit 798b28279e
2 changed files with 64 additions and 45 deletions

View File

@ -13,6 +13,7 @@
#include <algorithm>
#include <cstring>
#include <queue>
#include <vector>
#include "modules/video_coding/include/video_coding_defines.h"
#include "modules/video_coding/jitter_estimator.h"
@ -486,20 +487,34 @@ bool FrameBuffer::UpdateFrameInfoWithIncomingFrame(const EncodedFrame& frame,
FrameMap::iterator info) {
TRACE_EVENT0("webrtc", "FrameBuffer::UpdateFrameInfoWithIncomingFrame");
const VideoLayerFrameId& id = frame.id;
info->second.num_missing_continuous = frame.num_references;
info->second.num_missing_decodable = frame.num_references;
RTC_DCHECK(last_decoded_frame_it_ == frames_.end() ||
last_decoded_frame_it_->first < info->first);
// Check how many dependencies that have already been fulfilled.
// In this function we determine how many missing dependencies this |frame|
// has to become continuous/decodable. If a frame that this |frame| depend
// on has already been decoded then we can ignore that dependency since it has
// already been fulfilled.
//
// For all other frames we will register a backwards reference to this |frame|
// so that |num_missing_continuous| and |num_missing_decodable| can be
// decremented as frames become continuous/are decoded.
struct Dependency {
VideoLayerFrameId id;
bool continuous;
};
std::vector<Dependency> not_yet_fulfilled_dependencies;
// Find all dependencies that have not yet been fulfilled.
for (size_t i = 0; i < frame.num_references; ++i) {
VideoLayerFrameId ref_key(frame.references[i], frame.id.spatial_layer);
auto ref_info = frames_.find(ref_key);
// Does |frame| depend on a frame earlier than the last decoded frame?
// Does |frame| depend on a frame earlier than the last decoded one?
if (last_decoded_frame_it_ != frames_.end() &&
ref_key <= last_decoded_frame_it_->first) {
// Was that frame decoded? If not, this |frame| will never become
// decodable.
if (ref_info == frames_.end()) {
int64_t now_ms = clock_->TimeInMilliseconds();
if (last_log_non_decoded_ms_ + kLogNonDecodedIntervalMs < now_ms) {
@ -512,57 +527,51 @@ bool FrameBuffer::UpdateFrameInfoWithIncomingFrame(const EncodedFrame& frame,
}
return false;
}
--info->second.num_missing_continuous;
--info->second.num_missing_decodable;
} else {
if (ref_info == frames_.end())
ref_info = frames_.insert(std::make_pair(ref_key, FrameInfo())).first;
if (ref_info->second.continuous)
--info->second.num_missing_continuous;
// Add backwards reference so |frame| can be updated when new
// frames are inserted or decoded.
ref_info->second.dependent_frames[ref_info->second.num_dependent_frames] =
id;
RTC_DCHECK_LT(ref_info->second.num_dependent_frames,
(FrameInfo::kMaxNumDependentFrames - 1));
// TODO(philipel): Look into why this could happen and handle
// appropriately.
if (ref_info->second.num_dependent_frames <
(FrameInfo::kMaxNumDependentFrames - 1)) {
++ref_info->second.num_dependent_frames;
}
bool ref_continuous =
ref_info != frames_.end() && ref_info->second.continuous;
not_yet_fulfilled_dependencies.push_back({ref_key, ref_continuous});
}
RTC_DCHECK_LE(ref_info->second.num_missing_continuous,
ref_info->second.num_missing_decodable);
}
// Check if we have the lower spatial layer frame.
// Does |frame| depend on the lower spatial layer?
if (frame.inter_layer_predicted) {
++info->second.num_missing_continuous;
++info->second.num_missing_decodable;
VideoLayerFrameId ref_key(frame.id.picture_id, frame.id.spatial_layer - 1);
// Gets or create the FrameInfo for the referenced frame.
auto ref_info = frames_.insert(std::make_pair(ref_key, FrameInfo())).first;
if (ref_info->second.continuous)
--info->second.num_missing_continuous;
auto ref_info = frames_.find(ref_key);
if (ref_info == last_decoded_frame_it_) {
--info->second.num_missing_decodable;
} else {
ref_info->second.dependent_frames[ref_info->second.num_dependent_frames] =
id;
++ref_info->second.num_dependent_frames;
bool lower_layer_continuous =
ref_info != frames_.end() && ref_info->second.continuous;
bool lower_layer_decoded = last_decoded_frame_it_ != frames_.end() &&
last_decoded_frame_it_->first == ref_key;
if (!lower_layer_continuous || !lower_layer_decoded) {
not_yet_fulfilled_dependencies.push_back(
{ref_key, lower_layer_continuous});
}
RTC_DCHECK_LE(ref_info->second.num_missing_continuous,
ref_info->second.num_missing_decodable);
}
RTC_DCHECK_LE(info->second.num_missing_continuous,
info->second.num_missing_decodable);
info->second.num_missing_continuous = not_yet_fulfilled_dependencies.size();
info->second.num_missing_decodable = not_yet_fulfilled_dependencies.size();
for (const Dependency& dep : not_yet_fulfilled_dependencies) {
if (dep.continuous)
--info->second.num_missing_continuous;
// At this point we know we want to insert this frame, so here we
// intentionally get or create the FrameInfo for this dependency.
FrameInfo* dep_info = &frames_[dep.id];
if (dep_info->num_dependent_frames <
(FrameInfo::kMaxNumDependentFrames - 1)) {
dep_info->dependent_frames[dep_info->num_dependent_frames] = id;
++dep_info->num_dependent_frames;
} else {
RTC_LOG(LS_WARNING) << "Frame with (picture_id:spatial_id) ("
<< dep.id.picture_id << ":"
<< static_cast<int>(dep.id.spatial_layer)
<< ") is referenced by too many frames.";
}
}
return true;
}