| /* |
| * 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/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; |
| // The value of `local_ssrc` is not really used, but we need to set it to |
| // _something_ due to an RTC_DCHECK in rtp_video_stream_receiver2.cc. |
| config.rtp.local_ssrc = ssrc + 1; |
| 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_, |
| /*current_queue=*/nullptr, |
| /*transport=*/this, |
| /*rtt_stats=*/nullptr, |
| /*packet_router=*/nullptr, |
| &video_receive_stream_config_, |
| rtp_receive_statistics_.get(), |
| /*rtcp_packet_type_counter_observer=*/nullptr, |
| /*rtcp_cname_callback=*/nullptr, |
| /*nack_periodic_processor=*/nullptr, |
| /*complete_frame_callback=*/this, |
| /*frame_decryptor=*/nullptr, |
| /*frame_transformer=*/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::InsertPacket(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::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 |