That fuck shit the fascists are using
at master 265 lines 8.3 kB view raw
1package org.tm.archive.mediasend; 2 3import android.graphics.SurfaceTexture; 4import android.hardware.Camera; 5import android.view.Surface; 6 7import androidx.annotation.NonNull; 8 9import org.signal.core.util.logging.Log; 10 11import java.util.Collections; 12import java.util.Comparator; 13import java.util.List; 14 15class Camera1Controller { 16 17 private static final String TAG = Log.tag(Camera1Controller.class); 18 19 private final int screenWidth; 20 private final int screenHeight; 21 private final OrderEnforcer<Stage> enforcer; 22 private final EventListener eventListener; 23 24 private Camera camera; 25 private int cameraId; 26 private SurfaceTexture previewSurface; 27 private int screenRotation; 28 29 Camera1Controller(int preferredDirection, int screenWidth, int screenHeight, @NonNull EventListener eventListener) { 30 this.eventListener = eventListener; 31 this.enforcer = new OrderEnforcer<>(Stage.INITIALIZED, Stage.PREVIEW_STARTED); 32 this.cameraId = Camera.getNumberOfCameras() > 1 ? preferredDirection : Camera.CameraInfo.CAMERA_FACING_BACK; 33 this.screenWidth = screenWidth; 34 this.screenHeight = screenHeight; 35 } 36 37 void initialize() { 38 Log.d(TAG, "initialize()"); 39 40 if (Camera.getNumberOfCameras() <= 0) { 41 Log.w(TAG, "Device doesn't have any cameras."); 42 onCameraUnavailable(); 43 return; 44 } 45 46 try { 47 camera = Camera.open(cameraId); 48 } catch (Exception e) { 49 Log.w(TAG, "Failed to open camera.", e); 50 onCameraUnavailable(); 51 return; 52 } 53 54 if (camera == null) { 55 Log.w(TAG, "Null camera instance."); 56 onCameraUnavailable(); 57 return; 58 } 59 60 Camera.Parameters params = camera.getParameters(); 61 Camera.Size previewSize = getClosestSize(camera.getParameters().getSupportedPreviewSizes(), screenWidth, screenHeight); 62 Camera.Size pictureSize = getClosestSize(camera.getParameters().getSupportedPictureSizes(), screenWidth, screenHeight); 63 final List<String> focusModes = params.getSupportedFocusModes(); 64 65 Log.d(TAG, "Preview size: " + previewSize.width + "x" + previewSize.height + " Picture size: " + pictureSize.width + "x" + pictureSize.height); 66 67 params.setPreviewSize(previewSize.width, previewSize.height); 68 params.setPictureSize(pictureSize.width, pictureSize.height); 69 params.setFlashMode(Camera.Parameters.FLASH_MODE_OFF); 70 params.setColorEffect(Camera.Parameters.EFFECT_NONE); 71 params.setWhiteBalance(Camera.Parameters.WHITE_BALANCE_AUTO); 72 73 if (focusModes.contains(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE)) { 74 params.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE); 75 } else if (focusModes.contains(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO)) { 76 params.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO); 77 } 78 79 80 camera.setParameters(params); 81 82 enforcer.markCompleted(Stage.INITIALIZED); 83 84 eventListener.onPropertiesAvailable(getProperties()); 85 } 86 87 void release() { 88 Log.d(TAG, "release() called"); 89 enforcer.run(Stage.INITIALIZED, () -> { 90 Log.d(TAG, "release() executing"); 91 previewSurface = null; 92 camera.stopPreview(); 93 camera.release(); 94 enforcer.reset(); 95 }); 96 } 97 98 void linkSurface(@NonNull SurfaceTexture surfaceTexture) { 99 Log.d(TAG, "linkSurface() called"); 100 enforcer.run(Stage.INITIALIZED, () -> { 101 try { 102 Log.d(TAG, "linkSurface() executing"); 103 previewSurface = surfaceTexture; 104 105 camera.setPreviewTexture(surfaceTexture); 106 camera.startPreview(); 107 enforcer.markCompleted(Stage.PREVIEW_STARTED); 108 } catch (Exception e) { 109 Log.w(TAG, "Failed to start preview.", e); 110 eventListener.onCameraUnavailable(); 111 } 112 }); 113 } 114 115 void capture(@NonNull CaptureCallback callback) { 116 enforcer.run(Stage.PREVIEW_STARTED, () -> { 117 camera.takePicture(null, null, null, (data, camera) -> { 118 callback.onCaptureAvailable(data, cameraId == Camera.CameraInfo.CAMERA_FACING_FRONT); 119 }); 120 }); 121 } 122 123 boolean isCameraFacingFront() { 124 return cameraId == Camera.CameraInfo.CAMERA_FACING_FRONT; 125 } 126 127 int flip() { 128 Log.d(TAG, "flip()"); 129 SurfaceTexture surfaceTexture = previewSurface; 130 cameraId = (cameraId == Camera.CameraInfo.CAMERA_FACING_BACK) ? Camera.CameraInfo.CAMERA_FACING_FRONT : Camera.CameraInfo.CAMERA_FACING_BACK; 131 132 release(); 133 initialize(); 134 linkSurface(surfaceTexture); 135 setScreenRotation(screenRotation); 136 137 return cameraId; 138 } 139 140 void setScreenRotation(int screenRotation) { 141 Log.d(TAG, "setScreenRotation(" + screenRotation + ") called"); 142 enforcer.run(Stage.PREVIEW_STARTED, () -> { 143 Log.d(TAG, "setScreenRotation(" + screenRotation + ") executing"); 144 this.screenRotation = screenRotation; 145 146 int previewRotation = getPreviewRotation(screenRotation); 147 int outputRotation = getOutputRotation(screenRotation); 148 149 Log.d(TAG, "Preview rotation: " + previewRotation + " Output rotation: " + outputRotation); 150 151 camera.setDisplayOrientation(previewRotation); 152 153 Camera.Parameters params = camera.getParameters(); 154 params.setRotation(outputRotation); 155 camera.setParameters(params); 156 }); 157 } 158 159 private void onCameraUnavailable() { 160 enforcer.reset(); 161 eventListener.onCameraUnavailable(); 162 } 163 164 private Properties getProperties() { 165 Camera.Size previewSize = camera.getParameters().getPreviewSize(); 166 return new Properties(Camera.getNumberOfCameras(), previewSize.width, previewSize.height); 167 } 168 169 private Camera.Size getClosestSize(List<Camera.Size> sizes, int width, int height) { 170 Collections.sort(sizes, ASC_SIZE_COMPARATOR); 171 172 int i = 0; 173 while (i < sizes.size() && (sizes.get(i).width * sizes.get(i).height) < (width * height)) { 174 i++; 175 } 176 i++; 177 178 return sizes.get(Math.min(i, sizes.size() - 1)); 179 } 180 181 private int getOutputRotation(int displayRotationCode) { 182 int degrees = convertRotationToDegrees(displayRotationCode); 183 184 Camera.CameraInfo info = new Camera.CameraInfo(); 185 Camera.getCameraInfo(cameraId, info); 186 187 if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) { 188 return (info.orientation + degrees) % 360; 189 } else { 190 return (info.orientation - degrees + 360) % 360; 191 } 192 } 193 194 private int getPreviewRotation(int displayRotationCode) { 195 int degrees = convertRotationToDegrees(displayRotationCode); 196 197 Camera.CameraInfo info = new Camera.CameraInfo(); 198 Camera.getCameraInfo(cameraId, info); 199 200 int result; 201 if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) { 202 result = (info.orientation + degrees) % 360; 203 result = (360 - result) % 360; 204 } else { 205 result = (info.orientation - degrees + 360) % 360; 206 } 207 208 return result; 209 } 210 211 private int convertRotationToDegrees(int screenRotation) { 212 switch (screenRotation) { 213 case Surface.ROTATION_0: return 0; 214 case Surface.ROTATION_90: return 90; 215 case Surface.ROTATION_180: return 180; 216 case Surface.ROTATION_270: return 270; 217 } 218 return 0; 219 } 220 221 private final Comparator<Camera.Size> ASC_SIZE_COMPARATOR = (o1, o2) -> Integer.compare(o1.width * o1.height, o2.width * o2.height); 222 223 private enum Stage { 224 INITIALIZED, PREVIEW_STARTED 225 } 226 227 class Properties { 228 229 private final int cameraCount; 230 private final int previewWidth; 231 private final int previewHeight; 232 233 Properties(int cameraCount, int previewWidth, int previewHeight) { 234 this.cameraCount = cameraCount; 235 this.previewWidth = previewWidth; 236 this.previewHeight = previewHeight; 237 } 238 239 int getCameraCount() { 240 return cameraCount; 241 } 242 243 int getPreviewWidth() { 244 return previewWidth; 245 } 246 247 int getPreviewHeight() { 248 return previewHeight; 249 } 250 251 @Override 252 public @NonNull String toString() { 253 return "cameraCount: " + cameraCount + " previewWidth: " + previewWidth + " previewHeight: " + previewHeight; 254 } 255 } 256 257 interface EventListener { 258 void onPropertiesAvailable(@NonNull Properties properties); 259 void onCameraUnavailable(); 260 } 261 262 interface CaptureCallback { 263 void onCaptureAvailable(@NonNull byte[] jpegData, boolean frontFacing); 264 } 265}