1 /* 2 * Copyright 2021 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package androidx.camera.video; 18 19 import android.view.Surface; 20 21 import androidx.annotation.RestrictTo; 22 import androidx.annotation.RestrictTo.Scope; 23 import androidx.camera.core.CameraInfo; 24 import androidx.camera.core.SurfaceRequest; 25 import androidx.camera.core.impl.ConstantObservable; 26 import androidx.camera.core.impl.Observable; 27 import androidx.camera.core.impl.Timebase; 28 import androidx.core.util.Consumer; 29 30 import org.jspecify.annotations.NonNull; 31 32 import java.util.concurrent.Executor; 33 34 /** 35 * A class that will produce video data from a {@link Surface}. 36 * 37 * <p>Implementations will provide a {@link Surface} to a video frame producer via the 38 * {@link SurfaceRequest} sent to {@link #onSurfaceRequested(SurfaceRequest)}. 39 * 40 * <p>The type of video data produced by a video output and API for saving or communicating that 41 * data is left to the implementation. An implementation commonly used for local video saving is 42 * {@link Recorder}. This interface is usually only needs to be implemented by applications for 43 * advanced use cases. 44 */ 45 public interface VideoOutput { 46 /** 47 * A state which represents whether the video frame producer is producing frames to the 48 * provided {@link Surface}. 49 */ 50 @RestrictTo(Scope.LIBRARY) 51 enum SourceState { 52 /** The video frame producer is active and is producing frames. */ 53 ACTIVE_STREAMING, 54 /** The video frame producer is active but is not producing frames. */ 55 ACTIVE_NON_STREAMING, 56 /** The video frame producer is inactive. */ 57 INACTIVE 58 } 59 60 /** 61 * Called when a new {@link Surface} has been requested by a video frame producer. 62 * 63 * <p>Users of this class should not call this method directly. It will be called by the 64 * video frame producer. Implementors of this class should be aware that this method is 65 * called when a video frame producer is ready to receive a surface that it can use to send 66 * video frames to the video output. The video frame producer may repeatedly request a 67 * surface more than once, but only the latest {@link SurfaceRequest} should be considered 68 * active. All previous surface requests will complete by sending a 69 * {@link androidx.camera.core.SurfaceRequest.Result} to the consumer passed to 70 * {@link SurfaceRequest#provideSurface(Surface, Executor, Consumer)}. 71 * 72 * <p>A request is considered active until it is 73 * {@linkplain SurfaceRequest#provideSurface(Surface, Executor, androidx.core.util.Consumer) 74 * fulfilled}, {@linkplain SurfaceRequest#willNotProvideSurface() marked as 'will not 75 * complete'}, or 76 * {@linkplain SurfaceRequest#addRequestCancellationListener(Executor, Runnable) cancelled 77 * by the video frame producer}. After one of these conditions occurs, a request is considered 78 * completed. 79 * 80 * <p>Once a request is successfully completed, it is guaranteed that if a new request is 81 * made, the {@link Surface} used to fulfill the previous request will be detached from the 82 * video frame producer and the {@code resultListener} provided in 83 * {@link SurfaceRequest#provideSurface(Surface, Executor, Consumer)} 84 * will be invoked with a {@link androidx.camera.core.SurfaceRequest.Result} containing 85 * {@link androidx.camera.core.SurfaceRequest.Result#RESULT_SURFACE_USED_SUCCESSFULLY}. 86 * 87 * @param request the request for a surface which contains the requirements of the 88 * surface and methods for completing the request. 89 */ onSurfaceRequested(@onNull SurfaceRequest request)90 void onSurfaceRequested(@NonNull SurfaceRequest request); 91 92 /** 93 * Called when a new {@link Surface} has been requested by a video frame producer. 94 * 95 * @param request the request for a surface which contains the requirements of the 96 * surface and methods for completing the request. 97 * @param timebase the video source timebase. 98 * @param hasGlProcessing whether the video recording pipeline involves OpenGL processing. 99 */ 100 @RestrictTo(Scope.LIBRARY) onSurfaceRequested(@onNull SurfaceRequest request, @NonNull Timebase timebase, boolean hasGlProcessing)101 default void onSurfaceRequested(@NonNull SurfaceRequest request, @NonNull Timebase timebase, 102 boolean hasGlProcessing) { 103 onSurfaceRequested(request); 104 } 105 106 /** 107 * Returns an observable {@link StreamInfo} which contains the information of the 108 * {@link VideoOutput}. 109 */ 110 @RestrictTo(Scope.LIBRARY) getStreamInfo()111 default @NonNull Observable<StreamInfo> getStreamInfo() { 112 return StreamInfo.ALWAYS_ACTIVE_OBSERVABLE; 113 } 114 115 /** 116 * Returns an observable {@link MediaSpec} which contains hints about what kind of input the 117 * {@link VideoOutput} is expecting. 118 * 119 * <p>All values contained in the media specification are considered hints and may be ignored 120 * by the video frame producer. The {@link VideoOutput} should always respect the surface 121 * requirements given in the {@link SurfaceRequest} in 122 * {@link #onSurfaceRequested(SurfaceRequest)}, or the video frame producer may not be able 123 * to produce frames. 124 * 125 * <p>Implementations should be careful about updating the {@link MediaSpec} too often, as 126 * changes may not come for free and may require the video frame producer to re-initialize, 127 * which could cause a new {@link SurfaceRequest} to be sent to 128 * {@link #onSurfaceRequested(SurfaceRequest)}. 129 */ 130 @RestrictTo(Scope.LIBRARY) getMediaSpec()131 default @NonNull Observable<MediaSpec> getMediaSpec() { 132 return ConstantObservable.withValue(null); 133 } 134 135 /** 136 * Returns an observable to know if the streaming from a video frame producer is required. 137 * 138 * <p> This should be true for cases like when user is starting a video recording or streaming 139 * and false when user has decided to stop the recording/streaming. The video frame producer 140 * will use this information to do know whether it's now safe to do operations which may disrupt 141 * video quality/consistency (e.g. AE precapture). 142 */ 143 @RestrictTo(Scope.LIBRARY) isSourceStreamRequired()144 default @NonNull Observable<Boolean> isSourceStreamRequired() { 145 return ConstantObservable.withValue(false); 146 } 147 148 /** 149 * Called when the state of the video frame producer is changed. 150 */ 151 @RestrictTo(Scope.LIBRARY) onSourceStateChanged(@onNull SourceState sourceState)152 default void onSourceStateChanged(@NonNull SourceState sourceState) { 153 154 } 155 156 // TODO(b/278170231): wraps getMediaSpec and getMediaCapabilities for increased scalability and 157 // easier retrieval of initial specs and capabilities. 158 /** 159 * Returns the {@link VideoCapabilities} information of the {@link VideoOutput}. 160 */ 161 @RestrictTo(Scope.LIBRARY) getMediaCapabilities(@onNull CameraInfo cameraInfo, int sessionType)162 default @NonNull VideoCapabilities getMediaCapabilities(@NonNull CameraInfo cameraInfo, 163 int sessionType) { 164 return VideoCapabilities.EMPTY; 165 } 166 } 167