video_coding_impl.cc (8901B)
1 /* 2 * Copyright (c) 2012 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/video_coding/video_coding_impl.h" 12 13 #include <algorithm> 14 #include <cstddef> 15 #include <cstdint> 16 #include <memory> 17 #include <optional> 18 19 #include "api/environment/environment.h" 20 #include "api/rtp_headers.h" 21 #include "api/sequence_checker.h" 22 #include "api/video/encoded_image.h" 23 #include "api/video/render_resolution.h" 24 #include "api/video_codecs/video_decoder.h" 25 #include "modules/rtp_rtcp/source/rtp_video_header.h" 26 #include "modules/video_coding/encoded_frame.h" 27 #include "modules/video_coding/generic_decoder.h" 28 #include "modules/video_coding/include/video_coding.h" 29 #include "modules/video_coding/include/video_coding_defines.h" 30 #include "modules/video_coding/timing/timing.h" 31 #include "rtc_base/checks.h" 32 #include "rtc_base/logging.h" 33 #include "system_wrappers/include/clock.h" 34 35 namespace webrtc { 36 namespace vcm { 37 38 int64_t VCMProcessTimer::Period() const { 39 return _periodMs; 40 } 41 42 int64_t VCMProcessTimer::TimeUntilProcess() const { 43 const int64_t time_since_process = _clock->TimeInMilliseconds() - _latestMs; 44 const int64_t time_until_process = _periodMs - time_since_process; 45 return std::max<int64_t>(time_until_process, 0); 46 } 47 48 void VCMProcessTimer::Processed() { 49 _latestMs = _clock->TimeInMilliseconds(); 50 } 51 52 DEPRECATED_VCMDecoderDataBase::DEPRECATED_VCMDecoderDataBase() { 53 decoder_sequence_checker_.Detach(); 54 } 55 56 VideoDecoder* DEPRECATED_VCMDecoderDataBase::DeregisterExternalDecoder( 57 uint8_t payload_type) { 58 RTC_DCHECK_RUN_ON(&decoder_sequence_checker_); 59 auto it = decoders_.find(payload_type); 60 if (it == decoders_.end()) { 61 return nullptr; 62 } 63 64 // We can't use payload_type to check if the decoder is currently in use, 65 // because payload type may be out of date (e.g. before we decode the first 66 // frame after RegisterReceiveCodec). 67 if (current_decoder_ && current_decoder_->IsSameDecoder(it->second)) { 68 // Release it if it was registered and in use. 69 current_decoder_ = std::nullopt; 70 } 71 VideoDecoder* ret = it->second; 72 decoders_.erase(it); 73 return ret; 74 } 75 76 // Add the external decoder object to the list of external decoders. 77 // Won't be registered as a receive codec until RegisterReceiveCodec is called. 78 void DEPRECATED_VCMDecoderDataBase::RegisterExternalDecoder( 79 uint8_t payload_type, 80 VideoDecoder* external_decoder) { 81 RTC_DCHECK_RUN_ON(&decoder_sequence_checker_); 82 // If payload value already exists, erase old and insert new. 83 DeregisterExternalDecoder(payload_type); 84 decoders_[payload_type] = external_decoder; 85 } 86 87 bool DEPRECATED_VCMDecoderDataBase::IsExternalDecoderRegistered( 88 uint8_t payload_type) const { 89 RTC_DCHECK_RUN_ON(&decoder_sequence_checker_); 90 return payload_type == current_payload_type_ || 91 decoders_.find(payload_type) != decoders_.end(); 92 } 93 94 void DEPRECATED_VCMDecoderDataBase::RegisterReceiveCodec( 95 uint8_t payload_type, 96 const VideoDecoder::Settings& settings) { 97 // If payload value already exists, erase old and insert new. 98 if (payload_type == current_payload_type_) { 99 current_payload_type_ = std::nullopt; 100 } 101 decoder_settings_[payload_type] = settings; 102 } 103 104 bool DEPRECATED_VCMDecoderDataBase::DeregisterReceiveCodec( 105 uint8_t payload_type) { 106 if (decoder_settings_.erase(payload_type) == 0) { 107 return false; 108 } 109 if (payload_type == current_payload_type_) { 110 // This codec is currently in use. 111 current_payload_type_ = std::nullopt; 112 } 113 return true; 114 } 115 116 VCMGenericDecoder* DEPRECATED_VCMDecoderDataBase::GetDecoder( 117 const VCMEncodedFrame& frame, 118 VCMDecodedFrameCallback* decoded_frame_callback) { 119 RTC_DCHECK_RUN_ON(&decoder_sequence_checker_); 120 RTC_DCHECK(decoded_frame_callback->UserReceiveCallback()); 121 uint8_t payload_type = frame.PayloadType(); 122 if (payload_type == current_payload_type_ || payload_type == 0) { 123 return current_decoder_.has_value() ? &*current_decoder_ : nullptr; 124 } 125 // If decoder exists - delete. 126 if (current_decoder_.has_value()) { 127 current_decoder_ = std::nullopt; 128 current_payload_type_ = std::nullopt; 129 } 130 131 CreateAndInitDecoder(frame); 132 if (current_decoder_ == std::nullopt) { 133 return nullptr; 134 } 135 136 VCMReceiveCallback* callback = decoded_frame_callback->UserReceiveCallback(); 137 callback->OnIncomingPayloadType(payload_type); 138 if (current_decoder_->RegisterDecodeCompleteCallback(decoded_frame_callback) < 139 0) { 140 current_decoder_ = std::nullopt; 141 return nullptr; 142 } 143 144 current_payload_type_ = payload_type; 145 return &*current_decoder_; 146 } 147 148 void DEPRECATED_VCMDecoderDataBase::CreateAndInitDecoder( 149 const VCMEncodedFrame& frame) { 150 uint8_t payload_type = frame.PayloadType(); 151 RTC_LOG(LS_INFO) << "Initializing decoder with payload type '" 152 << int{payload_type} << "'."; 153 auto decoder_item = decoder_settings_.find(payload_type); 154 if (decoder_item == decoder_settings_.end()) { 155 RTC_LOG(LS_ERROR) << "Can't find a decoder associated with payload type: " 156 << int{payload_type}; 157 return; 158 } 159 auto external_dec_item = decoders_.find(payload_type); 160 if (external_dec_item == decoders_.end()) { 161 RTC_LOG(LS_ERROR) << "No decoder of this type exists."; 162 return; 163 } 164 current_decoder_.emplace(external_dec_item->second); 165 166 // Copy over input resolutions to prevent codec reinitialization due to 167 // the first frame being of a different resolution than the database values. 168 // This is best effort, since there's no guarantee that width/height have been 169 // parsed yet (and may be zero). 170 RenderResolution frame_resolution(frame.EncodedImage()._encodedWidth, 171 frame.EncodedImage()._encodedHeight); 172 if (frame_resolution.Valid()) { 173 decoder_item->second.set_max_render_resolution(frame_resolution); 174 } 175 if (!current_decoder_->Configure(decoder_item->second)) { 176 current_decoder_ = std::nullopt; 177 RTC_LOG(LS_ERROR) << "Failed to initialize decoder."; 178 } 179 } 180 181 } // namespace vcm 182 183 namespace { 184 185 class VideoCodingModuleImpl : public VideoCodingModule { 186 public: 187 explicit VideoCodingModuleImpl(const Environment& env) 188 : env_(env), 189 timing_(&env_.clock(), env_.field_trials()), 190 receiver_(&env_.clock(), &timing_, env_.field_trials()) {} 191 192 ~VideoCodingModuleImpl() override = default; 193 194 void Process() override { receiver_.Process(); } 195 196 void RegisterReceiveCodec( 197 uint8_t payload_type, 198 const VideoDecoder::Settings& decoder_settings) override { 199 receiver_.RegisterReceiveCodec(payload_type, decoder_settings); 200 } 201 202 void RegisterExternalDecoder(VideoDecoder* externalDecoder, 203 uint8_t payloadType) override { 204 receiver_.RegisterExternalDecoder(externalDecoder, payloadType); 205 } 206 207 int32_t RegisterReceiveCallback( 208 VCMReceiveCallback* receiveCallback) override { 209 RTC_DCHECK(construction_thread_.IsCurrent()); 210 return receiver_.RegisterReceiveCallback(receiveCallback); 211 } 212 213 int32_t RegisterFrameTypeCallback( 214 VCMFrameTypeCallback* frameTypeCallback) override { 215 return receiver_.RegisterFrameTypeCallback(frameTypeCallback); 216 } 217 218 int32_t RegisterPacketRequestCallback( 219 VCMPacketRequestCallback* callback) override { 220 RTC_DCHECK(construction_thread_.IsCurrent()); 221 return receiver_.RegisterPacketRequestCallback(callback); 222 } 223 224 int32_t Decode(uint16_t maxWaitTimeMs) override { 225 return receiver_.Decode(maxWaitTimeMs); 226 } 227 228 int32_t IncomingPacket(const uint8_t* incomingPayload, 229 size_t payloadLength, 230 const RTPHeader& rtp_header, 231 const RTPVideoHeader& video_header) override { 232 return receiver_.IncomingPacket(incomingPayload, payloadLength, rtp_header, 233 video_header); 234 } 235 236 void SetNackSettings(size_t max_nack_list_size, 237 int max_packet_age_to_nack, 238 int max_incomplete_time_ms) override { 239 return receiver_.SetNackSettings(max_nack_list_size, max_packet_age_to_nack, 240 max_incomplete_time_ms); 241 } 242 243 private: 244 const Environment env_; 245 SequenceChecker construction_thread_; 246 VCMTiming timing_; 247 vcm::VideoReceiver receiver_; 248 }; 249 } // namespace 250 251 // DEPRECATED. Create method for current interface, will be removed when the 252 // new jitter buffer is in place. 253 std::unique_ptr<VideoCodingModule> VideoCodingModule::CreateDeprecated( 254 const Environment& env) { 255 return std::make_unique<VideoCodingModuleImpl>(env); 256 } 257 258 } // namespace webrtc