| /* | |
| * Copyright (c) 2025 The WebRTC project authors. All Rights Reserved. | |
| * | |
| * Use of this source code is governed by a BSD-style license | |
| * that can be found in the LICENSE file in the root of the source | |
| * tree. An additional intellectual property rights grant can be found | |
| * in the file PATENTS. All contributing project authors may | |
| * be found in the AUTHORS file in the root of the source tree. | |
| */ | |
| #include "video/timing/simulator/assembler.h" | |
| #include <cstdint> | |
| #include <memory> | |
| #include <utility> | |
| #include "absl/base/nullability.h" | |
| #include "api/environment/environment.h" | |
| #include "api/rtp_parameters.h" | |
| #include "api/sequence_checker.h" | |
| #include "api/task_queue/task_queue_base.h" | |
| #include "api/units/time_delta.h" | |
| #include "api/video/encoded_frame.h" | |
| #include "api/video/video_codec_type.h" | |
| #include "call/video_receive_stream.h" | |
| #include "modules/rtp_rtcp/include/receive_statistics.h" | |
| #include "modules/rtp_rtcp/source/rtp_packet_received.h" | |
| namespace webrtc::video_timing_simulator { | |
| namespace { | |
| VideoReceiveStreamInterface::Config CreateVideoReceiveStreamConfig( | |
| uint32_t ssrc) { | |
| VideoReceiveStreamInterface::Config config(/*rtcp_send_transport=*/nullptr); | |
| config.rtp.remote_ssrc = ssrc; | |
| // From `kNackHistoryMs` in webrtc_video_engine.cc. This enables creating the | |
| // `NackRequester`. | |
| config.rtp.nack.rtp_history_ms = 1000; | |
| return config; | |
| } | |
| } // namespace | |
| Assembler::Assembler(const Environment& env, | |
| uint32_t ssrc, | |
| AssemblerEvents* absl_nonnull observer, | |
| AssembledFrameCallback* absl_nonnull assembled_frame_cb) | |
| : env_(env), | |
| video_receive_stream_config_(CreateVideoReceiveStreamConfig(ssrc)), | |
| rtp_receive_statistics_( | |
| ReceiveStatistics::CreateThreadCompatible(&env_.clock())), | |
| // Provide the minimal needed dependencies to the | |
| // `RtpVideoStreamReceiver2`. | |
| rtp_video_stream_receiver2_( | |
| env_, | |
| TaskQueueBase::Current(), | |
| /*transport=*/this, | |
| /*rtt_stats=*/nullptr, | |
| /*packet_router=*/nullptr, | |
| &video_receive_stream_config_, | |
| /*max_wait_for_keyframe=*/TimeDelta::Millis(200), | |
| rtp_receive_statistics_.get(), | |
| /*rtcp_packet_type_counter_observer=*/nullptr, | |
| /*rtcp_cname_callback=*/nullptr, | |
| &nack_periodic_processor_, | |
| /*complete_frame_callback=*/this, | |
| /*frame_decryptor=*/nullptr, | |
| /*frame_transformer=*/nullptr, | |
| /*on_first_packet=*/nullptr), | |
| observer_(*observer), | |
| assembled_frame_cb_(*assembled_frame_cb) { | |
| RTC_DCHECK_RUN_ON(&sequence_checker_); | |
| rtp_video_stream_receiver2_.StartReceive(); | |
| } | |
| Assembler::~Assembler() { | |
| RTC_DCHECK_RUN_ON(&sequence_checker_); | |
| rtp_video_stream_receiver2_.StopReceive(); | |
| } | |
| void Assembler::OnReceivedRtpPacket(const RtpPacketReceived& rtp_packet) { | |
| RTC_DCHECK_RUN_ON(&sequence_checker_); | |
| // Register all payload types as generic codec with raw packetization. | |
| uint8_t payload_type = rtp_packet.PayloadType(); | |
| if (registered_payload_types_.find(payload_type) == | |
| registered_payload_types_.end()) { | |
| CodecParameterMap unused_map; | |
| rtp_video_stream_receiver2_.AddReceiveCodec( | |
| payload_type, VideoCodecType::kVideoCodecGeneric, unused_map, | |
| /*raw_payload=*/true); | |
| registered_payload_types_.insert(payload_type); | |
| } | |
| rtp_video_stream_receiver2_.OnRtpPacket(rtp_packet); | |
| } | |
| void Assembler::OnDecodedFrameId(int64_t frame_id) { | |
| RTC_DCHECK_RUN_ON(&sequence_checker_); | |
| // Clear the internal `PacketBuffer` when the frames have been "decoded". | |
| rtp_video_stream_receiver2_.FrameDecoded(frame_id); | |
| } | |
| void Assembler::UpdateMaxRtt(TimeDelta max_rtt) { | |
| RTC_DCHECK_RUN_ON(&sequence_checker_); | |
| rtp_video_stream_receiver2_.UpdateRtt(max_rtt.ms()); | |
| } | |
| void Assembler::OnCompleteFrame(std::unique_ptr<EncodedFrame> encoded_frame) { | |
| RTC_DCHECK_RUN_ON(&sequence_checker_); | |
| // We rename this callback from `OnCompleteFrame` to `OnAssembledFrame`, since | |
| // the latter is a more descriptive. | |
| observer_.OnAssembledFrame(*encoded_frame); | |
| assembled_frame_cb_.OnAssembledFrame(std::move(encoded_frame)); | |
| } | |
| } // namespace webrtc::video_timing_simulator |