active_decode_targets_helper.cc (4669B)
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 11 #include "modules/rtp_rtcp/source/active_decode_targets_helper.h" 12 13 #include <bitset> 14 #include <cstddef> 15 #include <cstdint> 16 17 #include "api/array_view.h" 18 #include "rtc_base/checks.h" 19 #include "rtc_base/logging.h" 20 21 namespace webrtc { 22 namespace { 23 24 // Returns mask of ids of chains previous frame is part of. 25 // Assumes for each chain frames are seen in order and no frame on any chain is 26 // missing. That assumptions allows a simple detection when previous frame is 27 // part of a chain. 28 std::bitset<32> LastSendOnChain(int frame_diff, 29 ArrayView<const int> chain_diffs) { 30 std::bitset<32> bitmask = 0; 31 for (size_t i = 0; i < chain_diffs.size(); ++i) { 32 if (frame_diff == chain_diffs[i]) { 33 bitmask.set(i); 34 } 35 } 36 return bitmask; 37 } 38 39 // Returns bitmask with first `num` bits set to 1. 40 std::bitset<32> AllActive(size_t num) { 41 RTC_DCHECK_LE(num, 32); 42 return (~uint32_t{0}) >> (32 - num); 43 } 44 45 // Returns bitmask of chains that protect at least one active decode target. 46 std::bitset<32> ActiveChains( 47 ArrayView<const int> decode_target_protected_by_chain, 48 int num_chains, 49 std::bitset<32> active_decode_targets) { 50 std::bitset<32> active_chains = 0; 51 for (size_t dt = 0; dt < decode_target_protected_by_chain.size(); ++dt) { 52 if (dt < active_decode_targets.size() && !active_decode_targets[dt]) { 53 continue; 54 } 55 int chain_idx = decode_target_protected_by_chain[dt]; 56 RTC_DCHECK_LT(chain_idx, num_chains); 57 active_chains.set(chain_idx); 58 } 59 return active_chains; 60 } 61 62 } // namespace 63 64 void ActiveDecodeTargetsHelper::OnFrame( 65 ArrayView<const int> decode_target_protected_by_chain, 66 std::bitset<32> active_decode_targets, 67 bool is_keyframe, 68 int64_t frame_id, 69 ArrayView<const int> chain_diffs) { 70 const int num_chains = chain_diffs.size(); 71 if (num_chains == 0) { 72 // Avoid printing the warning 73 // when already printed the warning for the same active decode targets, or 74 // when active_decode_targets are not changed from it's default value of 75 // all are active, including non-existent decode targets. 76 if (last_active_decode_targets_ != active_decode_targets && 77 !active_decode_targets.all()) { 78 RTC_LOG(LS_WARNING) << "No chains are configured, but some decode " 79 "targets might be inactive. Unsupported."; 80 } 81 last_active_decode_targets_ = active_decode_targets; 82 return; 83 } 84 const size_t num_decode_targets = decode_target_protected_by_chain.size(); 85 RTC_DCHECK_GT(num_decode_targets, 0); 86 std::bitset<32> all_decode_targets = AllActive(num_decode_targets); 87 // Default value for active_decode_targets is 'all are active', i.e. all bits 88 // are set. Default value is set before number of decode targets is known. 89 // It is up to this helper to make the value cleaner and unset unused bits. 90 active_decode_targets &= all_decode_targets; 91 92 if (is_keyframe) { 93 // Key frame resets the state. 94 last_active_decode_targets_ = all_decode_targets; 95 last_active_chains_ = AllActive(num_chains); 96 unsent_on_chain_.reset(); 97 } else { 98 // Update state assuming previous frame was sent. 99 unsent_on_chain_ &= 100 ~LastSendOnChain(frame_id - last_frame_id_, chain_diffs); 101 } 102 // Save for the next call to OnFrame. 103 // Though usually `frame_id == last_frame_id_ + 1`, it might not be so when 104 // frame id space is shared by several simulcast rtp streams. 105 last_frame_id_ = frame_id; 106 107 if (active_decode_targets == last_active_decode_targets_) { 108 return; 109 } 110 last_active_decode_targets_ = active_decode_targets; 111 112 if (active_decode_targets.none()) { 113 RTC_LOG(LS_ERROR) << "It is invalid to produce a frame (" << frame_id 114 << ") while there are no active decode targets"; 115 return; 116 } 117 last_active_chains_ = ActiveChains(decode_target_protected_by_chain, 118 num_chains, active_decode_targets); 119 // Frames that are part of inactive chains might not be produced by the 120 // encoder. Thus stop sending `active_decode_target` bitmask when it is sent 121 // on all active chains rather than on all chains. 122 unsent_on_chain_ = last_active_chains_; 123 RTC_DCHECK(!unsent_on_chain_.none()); 124 } 125 126 } // namespace webrtc