Move decoder instance ownership to VideoReceiver2
This moves the ownership away from VideoReceiveStream2 and closer to
VCMDecoderDataBase. That facilitates unregistration (upcoming change)
without recreating receive streams.
Bug: none
Change-Id: I812175134730a0ffbf7077fd149c8489481c73d8
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/272481
Reviewed-by: Danil Chapovalov <danilchap@webrtc.org>
Commit-Queue: Tomas Gunnarsson <tommi@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#37866}
diff --git a/media/engine/webrtc_video_engine.cc b/media/engine/webrtc_video_engine.cc
index 4005de8..dc404dc 100644
--- a/media/engine/webrtc_video_engine.cc
+++ b/media/engine/webrtc_video_engine.cc
@@ -3012,7 +3012,6 @@
}
if (codec.ulpfec.red_rtx_payload_type != -1) {
- // TODO(tommi): Look into if/when this happens in practice.
rtx_associated_payload_types[codec.ulpfec.red_rtx_payload_type] =
codec.ulpfec.red_payload_type;
}
diff --git a/modules/video_coding/decoder_database.cc b/modules/video_coding/decoder_database.cc
index 882de27..15d8dcc 100644
--- a/modules/video_coding/decoder_database.cc
+++ b/modules/video_coding/decoder_database.cc
@@ -19,13 +19,14 @@
decoder_sequence_checker_.Detach();
}
-bool VCMDecoderDataBase::DeregisterExternalDecoder(uint8_t payload_type) {
+VideoDecoder* VCMDecoderDataBase::DeregisterExternalDecoder(
+ uint8_t payload_type) {
RTC_DCHECK_RUN_ON(&decoder_sequence_checker_);
auto it = decoders_.find(payload_type);
if (it == decoders_.end()) {
- // Not found.
- return false;
+ return nullptr;
}
+
// We can't use payload_type to check if the decoder is currently in use,
// because payload type may be out of date (e.g. before we decode the first
// frame after RegisterReceiveCodec).
@@ -33,8 +34,9 @@
// Release it if it was registered and in use.
current_decoder_ = absl::nullopt;
}
+ VideoDecoder* ret = it->second;
decoders_.erase(it);
- return true;
+ return ret;
}
// Add the external decoder object to the list of external decoders.
diff --git a/modules/video_coding/decoder_database.h b/modules/video_coding/decoder_database.h
index 98bbf85..59b683b 100644
--- a/modules/video_coding/decoder_database.h
+++ b/modules/video_coding/decoder_database.h
@@ -30,7 +30,9 @@
VCMDecoderDataBase& operator=(const VCMDecoderDataBase&) = delete;
~VCMDecoderDataBase() = default;
- bool DeregisterExternalDecoder(uint8_t payload_type);
+ // Returns a pointer to the previously registered decoder or nullptr if none
+ // was registered for the `payload_type`.
+ VideoDecoder* DeregisterExternalDecoder(uint8_t payload_type);
void RegisterExternalDecoder(uint8_t payload_type,
VideoDecoder* external_decoder);
bool IsExternalDecoderRegistered(uint8_t payload_type) const;
diff --git a/modules/video_coding/video_receiver2.cc b/modules/video_coding/video_receiver2.cc
index fe35420..36f53a7 100644
--- a/modules/video_coding/video_receiver2.cc
+++ b/modules/video_coding/video_receiver2.cc
@@ -13,8 +13,10 @@
#include <stddef.h>
#include <cstdint>
+#include <utility>
#include <vector>
+#include "absl/algorithm/container.h"
#include "api/video_codecs/video_codec.h"
#include "api/video_codecs/video_decoder.h"
#include "modules/video_coding/decoder_database.h"
@@ -32,9 +34,8 @@
VCMTiming* timing,
const FieldTrialsView& field_trials)
: clock_(clock),
- timing_(timing),
- decodedFrameCallback_(timing_, clock_, field_trials),
- codecDataBase_() {
+ decoded_frame_callback_(timing, clock_, field_trials),
+ codec_database_() {
decoder_sequence_checker_.Detach();
}
@@ -45,29 +46,38 @@
// Register a receive callback. Will be called whenever there is a new frame
// ready for rendering.
int32_t VideoReceiver2::RegisterReceiveCallback(
- VCMReceiveCallback* receiveCallback) {
+ VCMReceiveCallback* receive_callback) {
RTC_DCHECK_RUN_ON(&construction_sequence_checker_);
// This value is set before the decoder thread starts and unset after
// the decoder thread has been stopped.
- decodedFrameCallback_.SetUserReceiveCallback(receiveCallback);
+ decoded_frame_callback_.SetUserReceiveCallback(receive_callback);
return VCM_OK;
}
-void VideoReceiver2::RegisterExternalDecoder(VideoDecoder* externalDecoder,
- uint8_t payloadType) {
+void VideoReceiver2::RegisterExternalDecoder(
+ std::unique_ptr<VideoDecoder> decoder,
+ uint8_t payload_type) {
RTC_DCHECK_RUN_ON(&decoder_sequence_checker_);
- RTC_DCHECK(decodedFrameCallback_.UserReceiveCallback());
+ RTC_DCHECK(decoded_frame_callback_.UserReceiveCallback());
- if (externalDecoder == nullptr) {
- codecDataBase_.DeregisterExternalDecoder(payloadType);
+ if (decoder) {
+ RTC_DCHECK(!codec_database_.IsExternalDecoderRegistered(payload_type));
+ codec_database_.RegisterExternalDecoder(payload_type, decoder.get());
+ video_decoders_.push_back(std::move(decoder));
} else {
- codecDataBase_.RegisterExternalDecoder(payloadType, externalDecoder);
+ VideoDecoder* registered =
+ codec_database_.DeregisterExternalDecoder(payload_type);
+ if (registered) {
+ video_decoders_.erase(absl::c_find_if(
+ video_decoders_,
+ [registered](const auto& d) { return d.get() == registered; }));
+ }
}
}
-bool VideoReceiver2::IsExternalDecoderRegistered(uint8_t payloadType) const {
+bool VideoReceiver2::IsExternalDecoderRegistered(uint8_t payload_type) const {
RTC_DCHECK_RUN_ON(&decoder_sequence_checker_);
- return codecDataBase_.IsExternalDecoderRegistered(payloadType);
+ return codec_database_.IsExternalDecoderRegistered(payload_type);
}
// Must be called from inside the receive side critical section.
@@ -76,7 +86,7 @@
TRACE_EVENT0("webrtc", "VideoReceiver2::Decode");
// Change decoder if payload type has changed.
VCMGenericDecoder* decoder =
- codecDataBase_.GetDecoder(*frame, &decodedFrameCallback_);
+ codec_database_.GetDecoder(*frame, &decoded_frame_callback_);
if (decoder == nullptr) {
return VCM_NO_CODEC_REGISTERED;
}
@@ -89,7 +99,7 @@
uint8_t payload_type,
const VideoDecoder::Settings& settings) {
RTC_DCHECK_RUN_ON(&construction_sequence_checker_);
- codecDataBase_.RegisterReceiveCodec(payload_type, settings);
+ codec_database_.RegisterReceiveCodec(payload_type, settings);
}
} // namespace webrtc
diff --git a/modules/video_coding/video_receiver2.h b/modules/video_coding/video_receiver2.h
index 86f7f55..cbc7885 100644
--- a/modules/video_coding/video_receiver2.h
+++ b/modules/video_coding/video_receiver2.h
@@ -11,6 +11,9 @@
#ifndef MODULES_VIDEO_CODING_VIDEO_RECEIVER2_H_
#define MODULES_VIDEO_CODING_VIDEO_RECEIVER2_H_
+#include <memory>
+#include <vector>
+
#include "api/field_trials_view.h"
#include "api/sequence_checker.h"
#include "api/video_codecs/video_decoder.h"
@@ -37,24 +40,27 @@
void RegisterReceiveCodec(uint8_t payload_type,
const VideoDecoder::Settings& decoder_settings);
- void RegisterExternalDecoder(VideoDecoder* externalDecoder,
- uint8_t payloadType);
- bool IsExternalDecoderRegistered(uint8_t payloadType) const;
- int32_t RegisterReceiveCallback(VCMReceiveCallback* receiveCallback);
+ void RegisterExternalDecoder(std::unique_ptr<VideoDecoder> decoder,
+ uint8_t payload_type);
- int32_t Decode(const webrtc::VCMEncodedFrame* frame);
+ bool IsExternalDecoderRegistered(uint8_t payload_type) const;
+ int32_t RegisterReceiveCallback(VCMReceiveCallback* receive_callback);
+
+ int32_t Decode(const VCMEncodedFrame* frame);
private:
SequenceChecker construction_sequence_checker_;
SequenceChecker decoder_sequence_checker_;
Clock* const clock_;
- VCMTiming* timing_;
- VCMDecodedFrameCallback decodedFrameCallback_;
+ VCMDecodedFrameCallback decoded_frame_callback_;
+ // Holds/owns the decoder instances that are registered via
+ // `RegisterExternalDecoder` and referenced by `codec_database_`.
+ std::vector<std::unique_ptr<VideoDecoder>> video_decoders_;
// Callbacks are set before the decoder thread starts.
// Once the decoder thread has been started, usage of `_codecDataBase` moves
// over to the decoder thread.
- VCMDecoderDataBase codecDataBase_;
+ VCMDecoderDataBase codec_database_;
};
} // namespace webrtc
diff --git a/video/video_receive_stream2.cc b/video/video_receive_stream2.cc
index 94dedaa..0c2ab0f 100644
--- a/video/video_receive_stream2.cc
+++ b/video/video_receive_stream2.cc
@@ -602,8 +602,7 @@
std::move(video_decoder), FileWrapper::OpenWriteOnly(ssb.str()));
}
- video_decoders_.push_back(std::move(video_decoder));
- video_receiver_.RegisterExternalDecoder(video_decoders_.back().get(),
+ video_receiver_.RegisterExternalDecoder(std::move(video_decoder),
decoder.payload_type);
}
diff --git a/video/video_receive_stream2.h b/video/video_receive_stream2.h
index 753d5bb..9d4cac7 100644
--- a/video/video_receive_stream2.h
+++ b/video/video_receive_stream2.h
@@ -276,10 +276,6 @@
std::unique_ptr<VideoStreamDecoder> video_stream_decoder_;
RtpStreamsSynchronizer rtp_stream_sync_;
- // TODO(nisse, philipel): Creation and ownership of video encoders should be
- // moved to the new VideoStreamDecoder.
- std::vector<std::unique_ptr<VideoDecoder>> video_decoders_;
-
std::unique_ptr<VideoStreamBufferController> buffer_;
std::unique_ptr<RtpStreamReceiverInterface> media_receiver_