blob: c80540065455b60983ded88c9b18ecba2efe618f [file] [log] [blame]
/*
* Copyright (c) 2021 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.
*/
#ifndef VIDEO_FRAME_CADENCE_ADAPTER_H_
#define VIDEO_FRAME_CADENCE_ADAPTER_H_
#include <memory>
#include "absl/base/attributes.h"
#include "api/task_queue/task_queue_base.h"
#include "api/units/time_delta.h"
#include "api/video/video_frame.h"
#include "api/video/video_sink_interface.h"
#include "rtc_base/synchronization/mutex.h"
#include "rtc_base/thread_annotations.h"
#include "system_wrappers/include/clock.h"
namespace webrtc {
// A sink adapter implementing mutations to the received frame cadence.
// With the exception of the constructor and the methods overridden in
// VideoSinkInterface, the rest of the interface to this class (including dtor)
// needs to happen on the queue passed in Create.
class FrameCadenceAdapterInterface
: public rtc::VideoSinkInterface<VideoFrame> {
public:
// Averaging window spanning 90 frames at default 30fps, matching old media
// optimization module defaults.
// TODO(crbug.com/1255737): Use TimeDelta.
static constexpr int64_t kFrameRateAveragingWindowSizeMs = (1000 / 30) * 90;
// In zero-hertz mode, the idle repeat rate is a compromise between
// RTP receiver keyframe-requesting timeout (3s), other backend limitations
// and some worst case RTT.
static constexpr TimeDelta kZeroHertzIdleRepeatRatePeriod =
TimeDelta::Millis(1000);
struct ZeroHertzModeParams {
// The number of simulcast layers used in this configuration.
int num_simulcast_layers = 0;
};
// Callback interface used to inform instance owners.
class Callback {
public:
virtual ~Callback() = default;
// Called when a frame arrives on the |queue| specified in Create.
//
// The |post_time| parameter indicates the current time sampled when
// FrameCadenceAdapterInterface::OnFrame was called.
//
// |frames_scheduled_for_processing| indicates how many frames that have
// been scheduled for processing. During sequential conditions where
// FrameCadenceAdapterInterface::OnFrame is invoked and subsequently ending
// up in this callback, this value will read 1. Otherwise if the
// |queue| gets stalled for some reason, the value will increase
// beyond 1.
virtual void OnFrame(Timestamp post_time,
int frames_scheduled_for_processing,
const VideoFrame& frame) = 0;
// Called when the source has discarded a frame.
virtual void OnDiscardedFrame() = 0;
};
// Factory function creating a production instance. Deletion of the returned
// instance needs to happen on the same sequence that Create() was called on.
// Frames arriving in FrameCadenceAdapterInterface::OnFrame are posted to
// Callback::OnFrame on the |queue|.
static std::unique_ptr<FrameCadenceAdapterInterface> Create(
Clock* clock,
TaskQueueBase* queue);
// Call before using the rest of the API.
virtual void Initialize(Callback* callback) = 0;
// Pass zero hertz parameters in |params| as a prerequisite to enable
// zero-hertz operation. If absl:::nullopt is passed, the cadence adapter will
// switch to passthrough mode.
virtual void SetZeroHertzModeEnabled(
absl::optional<ZeroHertzModeParams> params) = 0;
// Returns the input framerate. This is measured by RateStatistics when
// zero-hertz mode is off, and returns the max framerate in zero-hertz mode.
virtual absl::optional<uint32_t> GetInputFrameRateFps() = 0;
// Updates frame rate. This is done unconditionally irrespective of adapter
// mode.
virtual void UpdateFrameRate() = 0;
// Updates quality convergence status for an enabled spatial layer.
// Convergence means QP has dropped to a low-enough level to warrant ceasing
// to send identical frames at high frequency.
virtual void UpdateLayerQualityConvergence(int spatial_index,
bool converged) = 0;
// Updates spatial layer enabled status.
virtual void UpdateLayerStatus(int spatial_index, bool enabled) = 0;
// Returns true if a key frame request should cause generation of a new frame
// from the source.
virtual ABSL_MUST_USE_RESULT bool ProcessKeyFrameRequest() = 0;
};
} // namespace webrtc
#endif // VIDEO_FRAME_CADENCE_ADAPTER_H_