| /* | |
| * Copyright 2017 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. | |
| */ | |
| package org.webrtc; | |
| import androidx.annotation.Nullable; | |
| import org.webrtc.EncodedImage; | |
| /** | |
| * Interface for a video encoder that can be used with WebRTC. All calls will be made on the | |
| * encoding thread. The encoder may be constructed on a different thread and changing thread after | |
| * calling release is allowed. | |
| */ | |
| public interface VideoEncoder { | |
| /** Settings passed to the encoder by WebRTC. */ | |
| public class Settings { | |
| public final int numberOfCores; | |
| public final int width; | |
| public final int height; | |
| public final int startBitrate; // Kilobits per second. | |
| public final int maxFramerate; | |
| public final int numberOfSimulcastStreams; | |
| public final boolean automaticResizeOn; | |
| public final Capabilities capabilities; | |
| // TODO(bugs.webrtc.org/10720): Remove. | |
| @Deprecated | |
| public Settings(int numberOfCores, int width, int height, int startBitrate, int maxFramerate, | |
| int numberOfSimulcastStreams, boolean automaticResizeOn) { | |
| this(numberOfCores, width, height, startBitrate, maxFramerate, numberOfSimulcastStreams, | |
| automaticResizeOn, new VideoEncoder.Capabilities(false /* lossNotification */)); | |
| } | |
| @CalledByNative("Settings") | |
| public Settings(int numberOfCores, int width, int height, int startBitrate, int maxFramerate, | |
| int numberOfSimulcastStreams, boolean automaticResizeOn, Capabilities capabilities) { | |
| this.numberOfCores = numberOfCores; | |
| this.width = width; | |
| this.height = height; | |
| this.startBitrate = startBitrate; | |
| this.maxFramerate = maxFramerate; | |
| this.numberOfSimulcastStreams = numberOfSimulcastStreams; | |
| this.automaticResizeOn = automaticResizeOn; | |
| this.capabilities = capabilities; | |
| } | |
| } | |
| /** Capabilities (loss notification, etc.) passed to the encoder by WebRTC. */ | |
| public class Capabilities { | |
| /** | |
| * The remote side has support for the loss notification RTCP feedback message format, and will | |
| * be sending these feedback messages if necessary. | |
| */ | |
| public final boolean lossNotification; | |
| @CalledByNative("Capabilities") | |
| public Capabilities(boolean lossNotification) { | |
| this.lossNotification = lossNotification; | |
| } | |
| } | |
| /** Additional info for encoding. */ | |
| public class EncodeInfo { | |
| public final EncodedImage.FrameType[] frameTypes; | |
| @CalledByNative("EncodeInfo") | |
| public EncodeInfo(EncodedImage.FrameType[] frameTypes) { | |
| this.frameTypes = frameTypes; | |
| } | |
| } | |
| // TODO(sakal): Add values to these classes as necessary. | |
| /** Codec specific information about the encoded frame. */ | |
| public class CodecSpecificInfo {} | |
| public class CodecSpecificInfoVP8 extends CodecSpecificInfo {} | |
| public class CodecSpecificInfoVP9 extends CodecSpecificInfo {} | |
| public class CodecSpecificInfoH264 extends CodecSpecificInfo {} | |
| public class CodecSpecificInfoAV1 extends CodecSpecificInfo {} | |
| /** | |
| * Represents bitrate allocated for an encoder to produce frames. Bitrate can be divided between | |
| * spatial and temporal layers. | |
| */ | |
| public class BitrateAllocation { | |
| // First index is the spatial layer and second the temporal layer. | |
| public final int[][] bitratesBbs; | |
| /** | |
| * Initializes the allocation with a two dimensional array of bitrates. The first index of the | |
| * array is the spatial layer and the second index in the temporal layer. | |
| */ | |
| @CalledByNative("BitrateAllocation") | |
| public BitrateAllocation(int[][] bitratesBbs) { | |
| this.bitratesBbs = bitratesBbs; | |
| } | |
| /** | |
| * Gets the total bitrate allocated for all layers. | |
| */ | |
| public int getSum() { | |
| int sum = 0; | |
| for (int[] spatialLayer : bitratesBbs) { | |
| for (int bitrate : spatialLayer) { | |
| sum += bitrate; | |
| } | |
| } | |
| return sum; | |
| } | |
| } | |
| /** Settings for WebRTC quality based scaling. */ | |
| public class ScalingSettings { | |
| public final boolean on; | |
| @Nullable public final Integer low; | |
| @Nullable public final Integer high; | |
| /** | |
| * Settings to disable quality based scaling. | |
| */ | |
| public static final ScalingSettings OFF = new ScalingSettings(); | |
| /** | |
| * Creates settings to enable quality based scaling. | |
| * | |
| * @param low Average QP at which to scale up the resolution. | |
| * @param high Average QP at which to scale down the resolution. | |
| */ | |
| public ScalingSettings(int low, int high) { | |
| this.on = true; | |
| this.low = low; | |
| this.high = high; | |
| } | |
| private ScalingSettings() { | |
| this.on = false; | |
| this.low = null; | |
| this.high = null; | |
| } | |
| // TODO(bugs.webrtc.org/8830): Below constructors are deprecated. | |
| // Default thresholds are going away, so thresholds have to be set | |
| // when scaling is on. | |
| /** | |
| * Creates quality based scaling setting. | |
| * | |
| * @param on True if quality scaling is turned on. | |
| */ | |
| @Deprecated | |
| public ScalingSettings(boolean on) { | |
| this.on = on; | |
| this.low = null; | |
| this.high = null; | |
| } | |
| /** | |
| * Creates quality based scaling settings with custom thresholds. | |
| * | |
| * @param on True if quality scaling is turned on. | |
| * @param low Average QP at which to scale up the resolution. | |
| * @param high Average QP at which to scale down the resolution. | |
| */ | |
| @Deprecated | |
| public ScalingSettings(boolean on, int low, int high) { | |
| this.on = on; | |
| this.low = low; | |
| this.high = high; | |
| } | |
| @Override | |
| public String toString() { | |
| return on ? "[ " + low + ", " + high + " ]" : "OFF"; | |
| } | |
| } | |
| /** | |
| * Bitrate limits for resolution. | |
| */ | |
| public class ResolutionBitrateLimits { | |
| /** | |
| * Maximum size of video frame, in pixels, the bitrate limits are intended for. | |
| */ | |
| public final int frameSizePixels; | |
| /** | |
| * Recommended minimum bitrate to start encoding. | |
| */ | |
| public final int minStartBitrateBps; | |
| /** | |
| * Recommended minimum bitrate. | |
| */ | |
| public final int minBitrateBps; | |
| /** | |
| * Recommended maximum bitrate. | |
| */ | |
| public final int maxBitrateBps; | |
| public ResolutionBitrateLimits( | |
| int frameSizePixels, int minStartBitrateBps, int minBitrateBps, int maxBitrateBps) { | |
| this.frameSizePixels = frameSizePixels; | |
| this.minStartBitrateBps = minStartBitrateBps; | |
| this.minBitrateBps = minBitrateBps; | |
| this.maxBitrateBps = maxBitrateBps; | |
| } | |
| @CalledByNative("ResolutionBitrateLimits") | |
| public int getFrameSizePixels() { | |
| return frameSizePixels; | |
| } | |
| @CalledByNative("ResolutionBitrateLimits") | |
| public int getMinStartBitrateBps() { | |
| return minStartBitrateBps; | |
| } | |
| @CalledByNative("ResolutionBitrateLimits") | |
| public int getMinBitrateBps() { | |
| return minBitrateBps; | |
| } | |
| @CalledByNative("ResolutionBitrateLimits") | |
| public int getMaxBitrateBps() { | |
| return maxBitrateBps; | |
| } | |
| } | |
| /** Rate control parameters. */ | |
| public class RateControlParameters { | |
| /** | |
| * Adjusted target bitrate, per spatial/temporal layer. May be lower or higher than the target | |
| * depending on encoder behaviour. | |
| */ | |
| public final BitrateAllocation bitrate; | |
| /** | |
| * Target framerate, in fps. A value <= 0.0 is invalid and should be interpreted as framerate | |
| * target not available. In this case the encoder should fall back to the max framerate | |
| * specified in `codec_settings` of the last InitEncode() call. | |
| */ | |
| public final double framerateFps; | |
| @CalledByNative("RateControlParameters") | |
| public RateControlParameters(BitrateAllocation bitrate, double framerateFps) { | |
| this.bitrate = bitrate; | |
| this.framerateFps = framerateFps; | |
| } | |
| } | |
| /** | |
| * Metadata about the Encoder. | |
| */ | |
| public class EncoderInfo { | |
| /** | |
| * The width and height of the incoming video frames should be divisible by | |
| * |requested_resolution_alignment| | |
| */ | |
| public final int requestedResolutionAlignment; | |
| /** | |
| * Same as above but if true, each simulcast layer should also be divisible by | |
| * |requested_resolution_alignment|. | |
| */ | |
| public final boolean applyAlignmentToAllSimulcastLayers; | |
| public EncoderInfo( | |
| int requestedResolutionAlignment, boolean applyAlignmentToAllSimulcastLayers) { | |
| this.requestedResolutionAlignment = requestedResolutionAlignment; | |
| this.applyAlignmentToAllSimulcastLayers = applyAlignmentToAllSimulcastLayers; | |
| } | |
| @CalledByNative("EncoderInfo") | |
| public int getRequestedResolutionAlignment() { | |
| return requestedResolutionAlignment; | |
| } | |
| @CalledByNative("EncoderInfo") | |
| public boolean getApplyAlignmentToAllSimulcastLayers() { | |
| return applyAlignmentToAllSimulcastLayers; | |
| } | |
| } | |
| public interface Callback { | |
| /** | |
| * Old encoders assume that the byte buffer held by `frame` is not accessed after the call to | |
| * this method returns. If the pipeline downstream needs to hold on to the buffer, it then has | |
| * to make its own copy. We want to move to a model where no copying is needed, and instead use | |
| * retain()/release() to signal to the encoder when it is safe to reuse the buffer. | |
| * | |
| * Over the transition, implementations of this class should use the maybeRetain() method if | |
| * they want to keep a reference to the buffer, and fall back to copying if that method returns | |
| * false. | |
| */ | |
| void onEncodedFrame(EncodedImage frame, CodecSpecificInfo info); | |
| } | |
| /** | |
| * The encoder implementation backing this interface is either 1) a Java | |
| * encoder (e.g., an Android platform encoder), or alternatively 2) a native | |
| * encoder (e.g., a software encoder or a C++ encoder adapter). | |
| * | |
| * For case 1), createNativeVideoEncoder() should return zero. | |
| * In this case, we expect the native library to call the encoder through | |
| * JNI using the Java interface declared below. | |
| * | |
| * For case 2), createNativeVideoEncoder() should return a non-zero value. | |
| * In this case, we expect the native library to treat the returned value as | |
| * a raw pointer of type webrtc::VideoEncoder* (ownership is transferred to | |
| * the caller). The native library should then directly call the | |
| * webrtc::VideoEncoder interface without going through JNI. All calls to | |
| * the Java interface methods declared below should thus throw an | |
| * UnsupportedOperationException. | |
| */ | |
| @CalledByNative | |
| default long createNativeVideoEncoder() { | |
| return 0; | |
| } | |
| /** | |
| * Returns true if the encoder is backed by hardware. | |
| */ | |
| @CalledByNative | |
| default boolean isHardwareEncoder() { | |
| return true; | |
| } | |
| /** | |
| * Initializes the encoding process. Call before any calls to encode. | |
| */ | |
| @CalledByNative VideoCodecStatus initEncode(Settings settings, Callback encodeCallback); | |
| /** | |
| * Releases the encoder. No more calls to encode will be made after this call. | |
| */ | |
| @CalledByNative VideoCodecStatus release(); | |
| /** | |
| * Requests the encoder to encode a frame. | |
| */ | |
| @CalledByNative VideoCodecStatus encode(VideoFrame frame, EncodeInfo info); | |
| /** Sets the bitrate allocation and the target framerate for the encoder. */ | |
| VideoCodecStatus setRateAllocation(BitrateAllocation allocation, int framerate); | |
| /** Sets the bitrate allocation and the target framerate for the encoder. */ | |
| default @CalledByNative VideoCodecStatus setRates(RateControlParameters rcParameters) { | |
| // Round frame rate up to avoid overshoots. | |
| int framerateFps = (int) Math.ceil(rcParameters.framerateFps); | |
| return setRateAllocation(rcParameters.bitrate, framerateFps); | |
| } | |
| /** Any encoder that wants to use WebRTC provided quality scaler must implement this method. */ | |
| @CalledByNative ScalingSettings getScalingSettings(); | |
| /** Returns the list of bitrate limits. */ | |
| @CalledByNative | |
| default ResolutionBitrateLimits[] getResolutionBitrateLimits() { | |
| // TODO(ssilkin): Update downstream projects and remove default implementation. | |
| ResolutionBitrateLimits bitrate_limits[] = {}; | |
| return bitrate_limits; | |
| } | |
| /** | |
| * Should return a descriptive name for the implementation. Gets called once and cached. May be | |
| * called from arbitrary thread. | |
| */ | |
| @CalledByNative String getImplementationName(); | |
| @CalledByNative | |
| default EncoderInfo getEncoderInfo() { | |
| return new EncoderInfo( | |
| /* requestedResolutionAlignment= */ 1, /* applyAlignmentToAllSimulcastLayers= */ false); | |
| } | |
| } |