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