| /* |
| * 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/test/encoded_frame_generators.h" |
| |
| #include <cstdint> |
| #include <memory> |
| |
| #include "api/environment/environment.h" |
| #include "api/rtp_packet_info.h" |
| #include "api/rtp_packet_infos.h" |
| #include "api/units/timestamp.h" |
| #include "api/video/encoded_frame.h" |
| #include "rtc_base/checks.h" |
| #include "test/fake_encoded_frame.h" |
| |
| namespace webrtc::video_timing_simulator { |
| |
| namespace { |
| |
| constexpr int kFrameSizeBytes = 2000; |
| constexpr int kPayloadType = 96; |
| |
| } // namespace |
| |
| EncodedFrameBuilderGenerator::EncodedFrameBuilderGenerator( |
| const Environment& env) |
| : env_(env) {} |
| EncodedFrameBuilderGenerator::~EncodedFrameBuilderGenerator() = default; |
| |
| EncodedFrameBuilderGenerator::BuilderWithFrameId |
| EncodedFrameBuilderGenerator::NextEncodedFrameBuilder() { |
| test::FakeFrameBuilder builder; |
| Timestamp now = env_.clock().CurrentTime(); |
| builder = builder.Time(rtp_timestamp_) |
| .Id(frame_id_) |
| .AsLast() |
| .SpatialLayer(0) |
| .ReceivedTime(now) |
| .Size(kFrameSizeBytes) |
| .PayloadType(kPayloadType) |
| .PacketInfos(RtpPacketInfos( |
| {RtpPacketInfo(kSsrc, /*csrcs=*/{}, rtp_timestamp_, now)})); |
| BuilderWithFrameId ret = {.builder = builder, .frame_id = frame_id_}; |
| |
| // 30 fps. |
| rtp_timestamp_ += 3000; |
| ++frame_id_; |
| |
| return ret; |
| } |
| |
| SingleLayerEncodedFrameGenerator::SingleLayerEncodedFrameGenerator( |
| const Environment& env) |
| : builder_generator_(env) {} |
| SingleLayerEncodedFrameGenerator::~SingleLayerEncodedFrameGenerator() = default; |
| |
| std::unique_ptr<EncodedFrame> |
| SingleLayerEncodedFrameGenerator::NextEncodedFrame() { |
| EncodedFrameBuilderGenerator::BuilderWithFrameId builder_and_frame_id = |
| builder_generator_.NextEncodedFrameBuilder(); |
| if (builder_and_frame_id.frame_id == 0) { |
| // Keyframe. |
| return builder_and_frame_id.builder.Build(); |
| } |
| return builder_and_frame_id.builder.Refs({builder_and_frame_id.frame_id - 1}) |
| .Build(); |
| } |
| |
| TemporalLayersEncodedFrameGenerator::TemporalLayersEncodedFrameGenerator( |
| const Environment& env) |
| : builder_generator_(env) {} |
| TemporalLayersEncodedFrameGenerator::~TemporalLayersEncodedFrameGenerator() = |
| default; |
| |
| std::unique_ptr<EncodedFrame> |
| TemporalLayersEncodedFrameGenerator::NextEncodedFrame() { |
| EncodedFrameBuilderGenerator::BuilderWithFrameId builder_and_frame_id = |
| builder_generator_.NextEncodedFrameBuilder(); |
| int64_t frame_id = builder_and_frame_id.frame_id; |
| if (frame_id == 0) { |
| // Keyframe. |
| return builder_and_frame_id.builder.Build(); |
| } |
| test::FakeFrameBuilder builder = builder_and_frame_id.builder; |
| int64_t mod = frame_id % kNumTemporalLayers; |
| if (mod == 0) { |
| // The keyframe is handled above. |
| RTC_CHECK_GE(frame_id, 4); |
| return builder.Refs({frame_id - 4}).Build(); |
| } else if (mod == 1) { |
| RTC_CHECK_GE(frame_id, 1); |
| return builder.Refs({frame_id - 1}).Build(); |
| } else if (mod == 2) { |
| RTC_CHECK_GE(frame_id, 2); |
| return builder.Refs({frame_id - 2}).Build(); |
| } else if (mod == 3) { |
| RTC_CHECK_GE(frame_id, 3); |
| return builder.Refs({frame_id - 1}).Build(); |
| } |
| RTC_CHECK_NOTREACHED(); |
| return test::FakeFrameBuilder().Build(); |
| } |
| |
| } // namespace webrtc::video_timing_simulator |