2 * Copyright (c) 2021 The WebRTC project authors. All Rights Reserved.
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.
11 #include "modules/video_coding/frame_helpers.h"
15 #include "rtc_base/logging.h"
20 constexpr TimeDelta kMaxVideoDelay
= TimeDelta::Millis(10000);
23 bool FrameHasBadRenderTiming(Timestamp render_time
, Timestamp now
) {
24 // Zero render time means render immediately.
25 if (render_time
.IsZero()) {
28 if (render_time
< Timestamp::Zero()) {
31 TimeDelta frame_delay
= render_time
- now
;
32 if (frame_delay
.Abs() > kMaxVideoDelay
) {
33 RTC_LOG(LS_WARNING
) << "Frame has bad render timing because it is out of "
34 "the delay bounds (frame_delay_ms="
36 << ", kMaxVideoDelay_ms=" << kMaxVideoDelay
.ms() << ")";
42 bool TargetVideoDelayIsTooLarge(TimeDelta target_video_delay
) {
43 if (target_video_delay
> kMaxVideoDelay
) {
45 << "Target video delay is too large. (target_video_delay_ms="
46 << target_video_delay
.ms()
47 << ", kMaxVideoDelay_ms=" << kMaxVideoDelay
.ms() << ")";
53 std::unique_ptr
<EncodedFrame
> CombineAndDeleteFrames(
54 absl::InlinedVector
<std::unique_ptr
<EncodedFrame
>, 4> frames
) {
55 RTC_DCHECK(!frames
.empty());
57 if (frames
.size() == 1) {
58 return std::move(frames
[0]);
61 size_t total_length
= 0;
62 for (const auto& frame
: frames
) {
63 total_length
+= frame
->size();
65 const EncodedFrame
& last_frame
= *frames
.back();
66 std::unique_ptr
<EncodedFrame
> first_frame
= std::move(frames
[0]);
67 auto encoded_image_buffer
= EncodedImageBuffer::Create(total_length
);
68 uint8_t* buffer
= encoded_image_buffer
->data();
69 first_frame
->SetSpatialLayerFrameSize(first_frame
->SpatialIndex().value_or(0),
71 memcpy(buffer
, first_frame
->data(), first_frame
->size());
72 buffer
+= first_frame
->size();
74 // Spatial index of combined frame is set equal to spatial index of its top
76 first_frame
->SetSpatialIndex(last_frame
.SpatialIndex().value_or(0));
78 first_frame
->video_timing_mutable()->network2_timestamp_ms
=
79 last_frame
.video_timing().network2_timestamp_ms
;
80 first_frame
->video_timing_mutable()->receive_finish_ms
=
81 last_frame
.video_timing().receive_finish_ms
;
83 // Append all remaining frames to the first one.
84 for (size_t i
= 1; i
< frames
.size(); ++i
) {
85 // Let |next_frame| fall out of scope so it is deleted after copying.
86 std::unique_ptr
<EncodedFrame
> next_frame
= std::move(frames
[i
]);
87 first_frame
->SetSpatialLayerFrameSize(
88 next_frame
->SpatialIndex().value_or(0), next_frame
->size());
89 memcpy(buffer
, next_frame
->data(), next_frame
->size());
90 buffer
+= next_frame
->size();
92 first_frame
->SetEncodedData(encoded_image_buffer
);