Index: webrtc/modules/video_coding/frame_buffer2.h |
diff --git a/webrtc/modules/video_coding/frame_buffer2.h b/webrtc/modules/video_coding/frame_buffer2.h |
index d0f896133f116cecef7491070c1ebd6508ae28ff..8f726d0d869dee1856bb6d2e924c0c6b534ddde2 100644 |
--- a/webrtc/modules/video_coding/frame_buffer2.h |
+++ b/webrtc/modules/video_coding/frame_buffer2.h |
@@ -14,15 +14,16 @@ |
#include <array> |
#include <map> |
#include <memory> |
-#include <set> |
#include <utility> |
#include "webrtc/base/constructormagic.h" |
#include "webrtc/base/criticalsection.h" |
#include "webrtc/base/event.h" |
#include "webrtc/base/thread_annotations.h" |
+#include "webrtc/modules/video_coding/frame_object.h" |
#include "webrtc/modules/video_coding/include/video_coding_defines.h" |
#include "webrtc/modules/video_coding/inter_frame_delay.h" |
+#include "webrtc/modules/video_coding/sequence_number_util.h" |
namespace webrtc { |
@@ -32,8 +33,6 @@ class VCMTiming; |
namespace video_coding { |
-class FrameObject; |
- |
class FrameBuffer { |
public: |
enum ReturnReason { kFrameFound, kTimeout, kStopped }; |
@@ -42,12 +41,13 @@ class FrameBuffer { |
VCMJitterEstimator* jitter_estimator, |
VCMTiming* timing); |
- // Insert a frame into the frame buffer. |
- void InsertFrame(std::unique_ptr<FrameObject> frame); |
+ // Insert a frame into the frame buffer. Returns the picture id |
+ // of the last continuous frame or -1 if there is no continuous frame. |
+ int InsertFrame(std::unique_ptr<FrameObject> frame); |
// Get the next frame for decoding. Will return at latest after |
// |max_wait_time_ms|. |
- // - If a frame is availiable within |max_wait_time_ms| it will return |
+ // - If a frame is available within |max_wait_time_ms| it will return |
// kFrameFound and set |frame_out| to the resulting frame. |
// - If no frame is available after |max_wait_time_ms| it will return |
// kTimeout. |
@@ -70,33 +70,85 @@ class FrameBuffer { |
void Stop(); |
private: |
- // FrameKey is a pair of (picture id, spatial layer). |
- using FrameKey = std::pair<uint16_t, uint8_t>; |
+ struct FrameKey { |
+ FrameKey() : picture_id(0), spatial_layer(0) {} |
+ FrameKey(uint16_t picture_id, uint8_t spatial_layer) |
+ : picture_id(picture_id), spatial_layer(spatial_layer) {} |
+ |
+ bool operator<(const FrameKey& rhs) const { |
+ if (picture_id == rhs.picture_id) |
+ return spatial_layer < rhs.spatial_layer; |
+ return AheadOf(rhs.picture_id, picture_id); |
+ } |
+ |
+ bool operator<=(const FrameKey& rhs) const { return !(rhs < *this); } |
+ |
+ uint16_t picture_id; |
+ uint8_t spatial_layer; |
+ }; |
+ |
+ struct FrameInfo { |
+ // The maximum number of frames that can depend on this frame. |
+ static constexpr size_t kMaxNumDependentFrames = 8; |
+ |
+ // Which other frames that have direct unfulfilled dependencies |
+ // on this frame. |
+ FrameKey dependent_frames[kMaxNumDependentFrames]; |
+ size_t num_dependent_frames = 0; |
+ |
+ // A frame is continiuous if it has all its referenced/indirectly |
+ // referenced frames. |
+ // |
+ // How many unfulfilled frames this frame have until it becomes continuous. |
+ size_t num_missing_continuous = 0; |
- // Comparator used to sort frames, first on their picture id, and second |
- // on their spatial layer. |
- struct FrameComp { |
- bool operator()(const FrameKey& f1, const FrameKey& f2) const; |
+ // A frame is decodable if all its referenced frames have been decoded. |
+ // |
+ // How many unfulfilled frames this frame have until it becomes decodable. |
+ size_t num_missing_decodable = 0; |
+ |
+ // If this frame is continuous or not. |
+ bool continuous = false; |
+ |
+ // The actual FrameObject. |
+ std::unique_ptr<FrameObject> frame; |
}; |
- // Determines whether a frame is continuous. |
- bool IsContinuous(const FrameObject& frame) const |
+ using FrameMap = std::map<FrameKey, FrameInfo>; |
+ |
+ // Update all directly dependent and indirectly dependent frames and mark |
+ // them as continuous if all their references has been fulfilled. |
+ void PropagateContinuity(FrameMap::iterator start) |
+ EXCLUSIVE_LOCKS_REQUIRED(crit_); |
+ |
+ // Marks the frame as decoded and updates all directly dependent frames. |
+ void PropagateDecodability(const FrameInfo& info) |
+ EXCLUSIVE_LOCKS_REQUIRED(crit_); |
+ |
+ // Advances |last_decoded_frame_it_| to |decoded| and removes old |
+ // frame info. |
+ void AdvanceLastDecodedFrame(FrameMap::iterator decoded) |
EXCLUSIVE_LOCKS_REQUIRED(crit_); |
- // Keep track of decoded frames. |
- std::set<FrameKey, FrameComp> decoded_frames_ GUARDED_BY(crit_); |
+ // Update the corresponding FrameInfo of |frame| and all FrameInfos that |
+ // |frame| references. |
+ // Return false if |frame| will never be decodable, true otherwise. |
+ bool UpdateFrameInfoWithIncomingFrame(const FrameObject& frame, |
+ FrameMap::iterator info) |
+ EXCLUSIVE_LOCKS_REQUIRED(crit_); |
- // The actual buffer that holds the FrameObjects. |
- std::map<FrameKey, std::unique_ptr<FrameObject>, FrameComp> frames_ |
- GUARDED_BY(crit_); |
+ FrameMap frames_ GUARDED_BY(crit_); |
rtc::CriticalSection crit_; |
Clock* const clock_; |
- rtc::Event frame_inserted_event_; |
+ rtc::Event new_countinuous_frame_event_; |
VCMJitterEstimator* const jitter_estimator_ GUARDED_BY(crit_); |
VCMTiming* const timing_ GUARDED_BY(crit_); |
VCMInterFrameDelay inter_frame_delay_ GUARDED_BY(crit_); |
- int newest_picture_id_ GUARDED_BY(crit_); |
+ FrameMap::iterator last_decoded_frame_it_ GUARDED_BY(crit_); |
+ FrameMap::iterator last_continuous_frame_it_ GUARDED_BY(crit_); |
+ int num_frames_history_ GUARDED_BY(crit_); |
+ int num_frames_buffered_ GUARDED_BY(crit_); |
bool stopped_ GUARDED_BY(crit_); |
VCMVideoProtection protection_mode_ GUARDED_BY(crit_); |