1 /* 2 * Copyright (c) 2021 The WebRTC project authors. All Rights Reserved. 3 * 4 * Use of this source code is governed by a BSD-style license 5 * that can be found in the LICENSE file in the root of the source 6 * tree. An additional intellectual property rights grant can be found 7 * in the file PATENTS. All contributing project authors may 8 * be found in the AUTHORS file in the root of the source tree. 9 */ 10 11 #ifndef API_VIDEO_FRAME_BUFFER_H_ 12 #define API_VIDEO_FRAME_BUFFER_H_ 13 14 #include <map> 15 #include <memory> 16 #include <utility> 17 18 #include "absl/container/inlined_vector.h" 19 #include "absl/types/optional.h" 20 #include "api/field_trials_view.h" 21 #include "api/video/encoded_frame.h" 22 #include "modules/video_coding/utility/decoded_frames_history.h" 23 24 namespace webrtc { 25 // The high level idea of the FrameBuffer is to order frames received from the 26 // network into a decodable stream. Frames are order by frame ID, and grouped 27 // into temporal units by timestamp. A temporal unit is decodable after all 28 // referenced frames outside the unit has been decoded, and a temporal unit is 29 // continuous if all referenced frames are directly or indirectly decodable. 30 // The FrameBuffer is thread-unsafe. 31 class FrameBuffer { 32 public: 33 struct DecodabilityInfo { 34 uint32_t next_rtp_timestamp; 35 uint32_t last_rtp_timestamp; 36 }; 37 38 // The `max_size` determines the maximum number of frames the buffer will 39 // store, and max_decode_history determines how far back (by frame ID) the 40 // buffer will store if a frame was decoded or not. 41 FrameBuffer(int max_size, 42 int max_decode_history, 43 // TODO(hta): remove field trials! 44 const FieldTrialsView& field_trials); 45 FrameBuffer(const FrameBuffer&) = delete; 46 FrameBuffer& operator=(const FrameBuffer&) = delete; 47 ~FrameBuffer() = default; 48 49 // Inserted frames may only reference backwards, and must have no duplicate 50 // references. Frame insertion will fail if `frame` is a duplicate, has 51 // already been decoded, invalid, or if the buffer is full and the frame is 52 // not a keyframe. Returns true if the frame was successfully inserted. 53 bool InsertFrame(std::unique_ptr<EncodedFrame> frame); 54 55 // Mark all frames belonging to the next decodable temporal unit as decoded 56 // and returns them. 57 absl::InlinedVector<std::unique_ptr<EncodedFrame>, 4> 58 ExtractNextDecodableTemporalUnit(); 59 60 // Drop all frames in the next decodable unit. 61 void DropNextDecodableTemporalUnit(); 62 63 absl::optional<int64_t> LastContinuousFrameId() const; 64 absl::optional<int64_t> LastContinuousTemporalUnitFrameId() const; 65 absl::optional<DecodabilityInfo> DecodableTemporalUnitsInfo() const; 66 67 int GetTotalNumberOfContinuousTemporalUnits() const; 68 int GetTotalNumberOfDroppedFrames() const; 69 size_t CurrentSize() const; 70 71 private: 72 struct FrameInfo { 73 std::unique_ptr<EncodedFrame> encoded_frame; 74 bool continuous = false; 75 }; 76 77 using FrameMap = std::map<int64_t, FrameInfo>; 78 using FrameIterator = FrameMap::iterator; 79 80 struct TemporalUnit { 81 // Both first and last are inclusive. 82 FrameIterator first_frame; 83 FrameIterator last_frame; 84 }; 85 86 bool IsContinuous(const FrameIterator& it) const; 87 void PropagateContinuity(const FrameIterator& frame_it); 88 void FindNextAndLastDecodableTemporalUnit(); 89 void Clear(); 90 91 const bool legacy_frame_id_jump_behavior_; 92 const size_t max_size_; 93 FrameMap frames_; 94 absl::optional<TemporalUnit> next_decodable_temporal_unit_; 95 absl::optional<DecodabilityInfo> decodable_temporal_units_info_; 96 absl::optional<int64_t> last_continuous_frame_id_; 97 absl::optional<int64_t> last_continuous_temporal_unit_frame_id_; 98 video_coding::DecodedFramesHistory decoded_frame_history_; 99 100 int num_continuous_temporal_units_ = 0; 101 int num_dropped_frames_ = 0; 102 }; 103 104 } // namespace webrtc 105 106 #endif // API_VIDEO_FRAME_BUFFER_H_ 107