1 /* 2 * Copyright (C) 2024 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 com.android.deviceaswebcam; 18 19 import android.hardware.HardwareBuffer; 20 import android.media.Image; 21 import android.util.Log; 22 import android.util.Size; 23 24 import java.lang.ref.WeakReference; 25 26 /** Primary interface for calls between the host and webcam controls. */ 27 public abstract class WebcamController { 28 private static final String TAG = WebcamController.class.getSimpleName(); 29 30 private WeakReference<DeviceAsWebcamFgService> mServiceRef = null; 31 32 /** 33 * Called when the host selects a stream configuration. This is considered inviolable, not 34 * honoring the size and frame rate is an error. 35 * 36 * @param size resolution of the video frame 37 * @param frameRate framerate requested by the host. Webcam does not support variable framerate. 38 */ setStreamConfig(Size size, int frameRate)39 public abstract void setStreamConfig(Size size, int frameRate); 40 41 /** Called when the host wants the webcam to start sending it frames. */ startStream()42 public abstract void startStream(); 43 44 /** Called when the host wants to webcam to stop sending it frames. */ stopStream()45 public abstract void stopStream(); 46 47 /** 48 * Method to be used to send camera frames from Java implementation to the host. This method 49 * (optionally) rotates the frames 180 degrees, encodes the frame to the format expected by the 50 * host, and queues the encoded frames to be sent to the host. 51 * 52 * <p>The passed HardwareBuffer must remain valid until {@link #onImageReturned} is called with 53 * the corresponding token. For example, if {@code image} is fetched from {@link 54 * Image#getHardwareBuffer()}, {@link Image#close()} must not be called until {@code image} is 55 * returned with {@link #onImageReturned}. 56 * 57 * <p>NOTE: This method _must not_ be overridden. 58 * 59 * @param image Camera Frame to be sent to the host 60 * @param token unique token that can be used to identify the corresponding image 61 * @return {@code true} if the image was successfully queued to the host, \ {@code false} 62 * otherwise. {@link #onImageReturned} will only be called for the {@code image} if {@code 63 * true} is returned. 64 */ queueImageToHost( HardwareBuffer image, long token, boolean rotate180Degrees)65 public final boolean queueImageToHost( 66 HardwareBuffer image, long token, boolean rotate180Degrees) { 67 DeviceAsWebcamFgService service = mServiceRef.get(); 68 if (service == null) { 69 Log.e(TAG, "queueImageToHost called but service has already been garbage collected?"); 70 return false; 71 } 72 73 return service.nativeEncodeImage(image, token, rotate180Degrees ? 180 : 0) == 0; 74 } 75 76 /** 77 * Internal method used by the {@link DeviceAsWebcamFgService} allow {@link #queueImageToHost} 78 * to call the native implementation. 79 */ registerServiceInstance(DeviceAsWebcamFgService service)80 final void registerServiceInstance(DeviceAsWebcamFgService service) { 81 mServiceRef = new WeakReference<>(service); 82 } 83 84 /** 85 * Called every time a frame is encoded and queued to the host. The encoded frame's token (as 86 * specified {@link #queueImageToHost}) is passed as the parameter. 87 * 88 * @param token token corresponding to the returned Image. 89 */ onImageReturned(long token)90 public abstract void onImageReturned(long token); 91 92 /** 93 * Called when the service is being destroyed. This typically happens when the host has been 94 * disconnected, or the Android system is killing the service. This may happen even if {@link 95 * #stopStream} was not called. 96 * 97 * <p>This should close/finish any user facing views or resources such as the PreviewActivity. 98 */ onDestroy()99 public abstract void onDestroy(); 100 } 101