blob: ccb2475b16753e1e50f838ad59b4898dcbdf19b1 [file] [log] [blame]
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <chrono>
#include <cmath>
#include <memory>
#include <tuple>
#include "cast/streaming/constants.h"
namespace openscreen {
namespace cast {
struct Answer;
// This namespace contains classes and functions to be used by senders for
// determining what constraints are recommended for the capture device, based on
// the limits reported by the receiver.
// A general note about recommendations: they are NOT maximum operational
// limits, instead they are targeted to provide a delightful cast experience.
// For example, if a receiver is connected to a 1080P display but cannot provide
// 1080P at a stable FPS with a good experience, 1080P will not be recommended.
namespace capture_recommendations {
// Default maximum delay for both audio and video. Used if the sender fails
// to provide any constraints.
constexpr std::chrono::milliseconds kDefaultMaxDelayMs(400);
// Bit rate limits, used for both audio and video streams.
struct BitRateLimits {
bool operator==(const BitRateLimits& other) const;
// Minimum bit rate, in bits per second.
int minimum;
// Maximum bit rate, in bits per second.
int maximum;
// The mirroring control protocol specifies 32kbps as the absolute minimum
// for audio. Depending on the type of audio content (narrowband, fullband,
// etc.) Opus specifically can perform very well at this bitrate.
// See:
constexpr int kDefaultAudioMinBitRate = 32 * 1000;
// Opus generally sees little improvement above 192kbps, but some older codecs
// that we may consider supporting improve at up to 256kbps.
constexpr int kDefaultAudioMaxBitRate = 256 * 1000;
constexpr BitRateLimits kDefaultAudioBitRateLimits{kDefaultAudioMinBitRate,
// While generally audio should be captured at the maximum sample rate, 16kHz is
// the recommended absolute minimum.
constexpr int kDefaultAudioMinSampleRate = 16000;
// Audio capture recommendations. Maximum delay is determined by buffer
// constraints, and capture bit rate may vary between limits as appropriate.
struct Audio {
bool operator==(const Audio& other) const;
// Represents the recommended bit rate range.
BitRateLimits bit_rate_limits = kDefaultAudioBitRateLimits;
// Represents the maximum audio delay, in milliseconds.
std::chrono::milliseconds max_delay = kDefaultMaxDelayMs;
// Represents the maximum number of audio channels.
int max_channels = kDefaultAudioChannels;
// Represents the maximum samples per second.
int max_sample_rate = kDefaultAudioSampleRate;
// Represents the absolute minimum samples per second. Generally speaking,
// audio should be captured at the maximum samples per second rate.
int min_sample_rate = kDefaultAudioMinSampleRate;
struct Resolution {
bool operator==(const Resolution& other) const;
bool operator<(const Resolution& other) const;
bool operator<=(const Resolution& other) const;
void set_minimum(const Resolution& other);
// The effective bit rate is the predicted average bit rate based on the
// properties of the Resolution instance, and is currently just the product.
constexpr int effective_bit_rate() const {
return static_cast<int>(static_cast<double>(width * height) * frame_rate);
int width;
int height;
double frame_rate;
// The minimum dimensions are as close as possible to low-definition
// television, factoring in the receiver's aspect ratio if provided.
constexpr Resolution kDefaultMinResolution{kMinVideoWidth, kMinVideoHeight,
// Currently mirroring only supports 1080P.
constexpr Resolution kDefaultMaxResolution{1920, 1080, kDefaultFrameRate};
// The mirroring spec suggests 300kbps as the absolute minimum bitrate.
constexpr int kDefaultVideoMinBitRate = 300 * 1000;
// The theoretical maximum pixels per second is the maximum bit rate
// divided by 8 (the max byte rate). In practice it should generally be
// less.
constexpr int kDefaultVideoMaxPixelsPerSecond =
kDefaultMaxResolution.effective_bit_rate() / 8;
// Our default limits are merely the product of the minimum and maximum
// dimensions, and are only used if the receiver fails to give better
// constraint information.
constexpr BitRateLimits kDefaultVideoBitRateLimits{
kDefaultVideoMinBitRate, kDefaultMaxResolution.effective_bit_rate()};
// Video capture recommendations.
struct Video {
bool operator==(const Video& other) const;
// Represents the recommended bit rate range.
BitRateLimits bit_rate_limits = kDefaultVideoBitRateLimits;
// Represents the recommended minimum resolution.
Resolution minimum = kDefaultMinResolution;
// Represents the recommended maximum resolution.
Resolution maximum = kDefaultMaxResolution;
// Indicates whether the receiver can scale frames from a different aspect
// ratio, or if it needs to be done by the sender. Default is false, meaning
// that the sender is responsible for letterboxing.
bool supports_scaling = false;
// Represents the maximum video delay, in milliseconds.
std::chrono::milliseconds max_delay = kDefaultMaxDelayMs;
// Represents the maximum pixels per second, not necessarily correlated
// to bit rate.
int max_pixels_per_second = kDefaultVideoMaxPixelsPerSecond;
// Outputted recommendations for usage by capture devices. Note that we always
// return both audio and video (it is up to the sender to determine what
// streams actually get created). If the receiver doesn't give us any
// information for making recommendations, the defaults are used.
struct Recommendations {
bool operator==(const Recommendations& other) const;
// Audio specific recommendations.
Audio audio;
// Video specific recommendations.
Video video;
Recommendations GetRecommendations(const Answer& answer);
} // namespace capture_recommendations
} // namespace cast
} // namespace openscreen