DecodeFrameHistory can now deal with negative picture IDs.
Bug: webrtc:10263
Change-Id: I5c4f9511074b86dc73c9677a14dd10ee18c6ea4f
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/128422
Reviewed-by: Ilya Nikolaevskiy <ilnik@webrtc.org>
Reviewed-by: Johannes Kron <kron@webrtc.org>
Commit-Queue: Philip Eliasson <philipel@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#27176}
diff --git a/modules/video_coding/utility/decoded_frames_history.cc b/modules/video_coding/utility/decoded_frames_history.cc
index b8709ad..d15cf26 100644
--- a/modules/video_coding/utility/decoded_frames_history.cc
+++ b/modules/video_coding/utility/decoded_frames_history.cc
@@ -33,41 +33,41 @@
if (static_cast<int>(layers_.size()) < frameid.spatial_layer + 1) {
size_t old_size = layers_.size();
layers_.resize(frameid.spatial_layer + 1);
- for (size_t i = old_size; i < layers_.size(); ++i) {
+
+ for (size_t i = old_size; i < layers_.size(); ++i)
layers_[i].buffer.resize(window_size_);
- layers_[i].last_stored_index = 0;
- }
- layers_[frameid.spatial_layer].last_stored_index = frameid.picture_id;
- layers_[frameid.spatial_layer].buffer[frameid.picture_id % window_size_] =
- true;
+
+ layers_[frameid.spatial_layer].last_picture_id = frameid.picture_id;
+ layers_[frameid.spatial_layer]
+ .buffer[PictureIdToIndex(frameid.picture_id)] = true;
return;
}
+ int new_index = PictureIdToIndex(frameid.picture_id);
LayerHistory& history = layers_[frameid.spatial_layer];
- RTC_DCHECK_LT(history.last_stored_index, frameid.picture_id);
+ RTC_DCHECK(history.last_picture_id < frameid.picture_id);
- int64_t id_jump = frameid.picture_id - history.last_stored_index;
- int last_index = history.last_stored_index % window_size_;
- int new_index = frameid.picture_id % window_size_;
+ // Clears expired values from the cyclic buffer.
+ if (history.last_picture_id) {
+ int64_t id_jump = frameid.picture_id - *history.last_picture_id;
+ int last_index = PictureIdToIndex(*history.last_picture_id);
- // Need to clear indexes between last_index + 1 and new_index as they fall
- // out of the history window and now represent new unseen picture ids.
- if (id_jump >= window_size_) {
- // Wraps around whole buffer - clear it all.
- std::fill(history.buffer.begin(), history.buffer.end(), false);
- } else if (new_index > last_index) {
- std::fill(history.buffer.begin() + last_index + 1,
- history.buffer.begin() + new_index, false);
- } else {
- std::fill(history.buffer.begin() + last_index + 1, history.buffer.end(),
- false);
- std::fill(history.buffer.begin(), history.buffer.begin() + new_index,
- false);
+ if (id_jump >= window_size_) {
+ std::fill(history.buffer.begin(), history.buffer.end(), false);
+ } else if (new_index > last_index) {
+ std::fill(history.buffer.begin() + last_index + 1,
+ history.buffer.begin() + new_index, false);
+ } else {
+ std::fill(history.buffer.begin() + last_index + 1, history.buffer.end(),
+ false);
+ std::fill(history.buffer.begin(), history.buffer.begin() + new_index,
+ false);
+ }
}
history.buffer[new_index] = true;
- history.last_stored_index = frameid.picture_id;
+ history.last_picture_id = frameid.picture_id;
}
bool DecodedFramesHistory::WasDecoded(const VideoLayerFrameId& frameid) {
@@ -77,24 +77,24 @@
LayerHistory& history = layers_[frameid.spatial_layer];
+ if (!history.last_picture_id)
+ return false;
+
// Reference to the picture_id out of the stored history should happen.
- if (frameid.picture_id <= history.last_stored_index - window_size_) {
+ if (frameid.picture_id <= *history.last_picture_id - window_size_) {
RTC_LOG(LS_WARNING) << "Referencing a frame out of the history window. "
"Assuming it was undecoded to avoid artifacts.";
return false;
}
- if (frameid.picture_id > history.last_stored_index)
+ if (frameid.picture_id > history.last_picture_id)
return false;
- return history.buffer[frameid.picture_id % window_size_];
+ return history.buffer[PictureIdToIndex(frameid.picture_id)];
}
void DecodedFramesHistory::Clear() {
- for (LayerHistory& layer : layers_) {
- std::fill(layer.buffer.begin(), layer.buffer.end(), false);
- layer.last_stored_index = 0;
- }
+ layers_.clear();
last_decoded_frame_timestamp_.reset();
last_decoded_frame_.reset();
}
@@ -108,5 +108,10 @@
return last_decoded_frame_timestamp_;
}
+int DecodedFramesHistory::PictureIdToIndex(int64_t frame_id) const {
+ int m = frame_id % window_size_;
+ return m >= 0 ? m : m + window_size_;
+}
+
} // namespace video_coding
} // namespace webrtc
diff --git a/modules/video_coding/utility/decoded_frames_history.h b/modules/video_coding/utility/decoded_frames_history.h
index 3790946..07c21e6 100644
--- a/modules/video_coding/utility/decoded_frames_history.h
+++ b/modules/video_coding/utility/decoded_frames_history.h
@@ -42,13 +42,12 @@
LayerHistory();
~LayerHistory();
// Cyclic bitset buffer. Stores last known |window_size| bits.
- // last_stored_index is the last actually stored bit. Previous
- // |window_size-1| bits are also in the memory. Value for i-th bit is at
- // buffer[i % window_size].
std::vector<bool> buffer;
- int64_t last_stored_index;
+ absl::optional<int64_t> last_picture_id;
};
+ int PictureIdToIndex(int64_t frame_id) const;
+
const int window_size_;
std::vector<LayerHistory> layers_;
absl::optional<VideoLayerFrameId> last_decoded_frame_;
diff --git a/modules/video_coding/utility/decoded_frames_history_unittest.cc b/modules/video_coding/utility/decoded_frames_history_unittest.cc
index 12ed282..b3bcf48 100644
--- a/modules/video_coding/utility/decoded_frames_history_unittest.cc
+++ b/modules/video_coding/utility/decoded_frames_history_unittest.cc
@@ -121,6 +121,25 @@
EXPECT_EQ(history.GetLastDecodedFrameTimestamp(), 12366u);
}
+TEST(DecodedFramesHistory, NegativePictureIds) {
+ DecodedFramesHistory history(kHistorySize);
+ history.InsertDecoded({-1234, 0}, 12345);
+ history.InsertDecoded({-1233, 0}, 12366);
+ EXPECT_EQ(history.GetLastDecodedFrameId()->picture_id, -1233);
+
+ history.InsertDecoded({-1, 0}, 12377);
+ history.InsertDecoded({0, 0}, 12388);
+ EXPECT_EQ(history.GetLastDecodedFrameId()->picture_id, 0);
+
+ history.InsertDecoded({1, 0}, 12399);
+ EXPECT_EQ(history.GetLastDecodedFrameId()->picture_id, 1);
+
+ EXPECT_EQ(history.WasDecoded({-1234, 0}), true);
+ EXPECT_EQ(history.WasDecoded({-1, 0}), true);
+ EXPECT_EQ(history.WasDecoded({0, 0}), true);
+ EXPECT_EQ(history.WasDecoded({1, 0}), true);
+}
+
} // namespace
} // namespace video_coding
} // namespace webrtc