1 /*
2  *  Copyright (c) 2020 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 #include "modules/video_coding/frame_dependencies_calculator.h"
11 
12 #include <stdint.h>
13 
14 #include <iterator>
15 #include <set>
16 
17 #include "absl/algorithm/container.h"
18 #include "absl/container/inlined_vector.h"
19 #include "api/array_view.h"
20 #include "rtc_base/checks.h"
21 #include "rtc_base/logging.h"
22 
23 namespace webrtc {
24 
FromBuffersUsage(int64_t frame_id,rtc::ArrayView<const CodecBufferUsage> buffers_usage)25 absl::InlinedVector<int64_t, 5> FrameDependenciesCalculator::FromBuffersUsage(
26     int64_t frame_id,
27     rtc::ArrayView<const CodecBufferUsage> buffers_usage) {
28   absl::InlinedVector<int64_t, 5> dependencies;
29   RTC_DCHECK_GT(buffers_usage.size(), 0);
30   for (const CodecBufferUsage& buffer_usage : buffers_usage) {
31     RTC_CHECK_GE(buffer_usage.id, 0);
32     if (buffers_.size() <= static_cast<size_t>(buffer_usage.id)) {
33       buffers_.resize(buffer_usage.id + 1);
34     }
35   }
36   std::set<int64_t> direct_depenendencies;
37   std::set<int64_t> indirect_depenendencies;
38 
39   for (const CodecBufferUsage& buffer_usage : buffers_usage) {
40     if (!buffer_usage.referenced) {
41       continue;
42     }
43     const BufferUsage& buffer = buffers_[buffer_usage.id];
44     if (buffer.frame_id == absl::nullopt) {
45       RTC_LOG(LS_ERROR) << "Odd configuration: frame " << frame_id
46                         << " references buffer #" << buffer_usage.id
47                         << " that was never updated.";
48       continue;
49     }
50     direct_depenendencies.insert(*buffer.frame_id);
51     indirect_depenendencies.insert(buffer.dependencies.begin(),
52                                    buffer.dependencies.end());
53   }
54   // Reduce references: if frame #3 depends on frame #2 and #1, and frame #2
55   // depends on frame #1, then frame #3 needs to depend just on frame #2.
56   // Though this set diff removes only 1 level of indirection, it seems
57   // enough for all currently used structures.
58   absl::c_set_difference(direct_depenendencies, indirect_depenendencies,
59                          std::back_inserter(dependencies));
60 
61   // Update buffers.
62   for (const CodecBufferUsage& buffer_usage : buffers_usage) {
63     if (!buffer_usage.updated) {
64       continue;
65     }
66     BufferUsage& buffer = buffers_[buffer_usage.id];
67     buffer.frame_id = frame_id;
68     buffer.dependencies.assign(direct_depenendencies.begin(),
69                                direct_depenendencies.end());
70   }
71 
72   return dependencies;
73 }
74 
75 }  // namespace webrtc
76