Skip to content

Commit

Permalink
chore: Clean up Android codebase a bit (#1748)
Browse files Browse the repository at this point in the history
<!--
                    ❤️ Thank you for your contribution! ❤️
              Make sure you have read the Contributing Guidelines:

https://github.com/mrousavy/react-native-vision-camera/blob/main/CONTRIBUTING.md
-->

## What

<!--
  Enter a short description on what this pull-request does.
  Examples:
    This PR adds support for the HEVC format.
    This PR fixes a "unsupported device" error on iPhone 8 and below.
    This PR fixes a typo in a CameraError.
    This PR adds support for Quadruple Cameras.
-->

## Changes

<!--
  Create a short list of logic-changes.
  Examples:
    * This PR changes the default value of X to Y.
    * This PR changes the configure() function to cache results.
-->

## Tested on

<!--
Create a short list of devices and operating-systems you have tested
this change on. (And verified that everything works as expected).
  Examples:
    * iPhone 11 Pro, iOS 14.3
    * Huawai P20, Android 10
-->

## Related issues

<!--
  Link related issues here.
  Examples:
    * Fixes #29
    * Closes #30
    * Resolves #5
-->
  • Loading branch information
mrousavy authored Sep 1, 2023
1 parent 272504f commit f3fd3f1
Show file tree
Hide file tree
Showing 22 changed files with 38 additions and 181 deletions.
20 changes: 10 additions & 10 deletions .github/workflows/build-android.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,19 @@ on:
- main
paths:
- '.github/workflows/build-android.yml'
- 'cpp/**'
- 'android/**'
- 'example/android/**'
- 'yarn.lock'
- 'example/yarn.lock'
- 'package/cpp/**'
- 'package/android/**'
- 'package/example/android/**'
- 'package/yarn.lock'
- 'package/example/yarn.lock'
pull_request:
paths:
- '.github/workflows/build-android.yml'
- 'cpp/**'
- 'android/**'
- 'example/android/**'
- 'yarn.lock'
- 'example/yarn.lock'
- 'package/cpp/**'
- 'package/android/**'
- 'package/example/android/**'
- 'package/yarn.lock'
- 'package/example/yarn.lock'

jobs:
build:
Expand Down
16 changes: 8 additions & 8 deletions .github/workflows/build-ios.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,17 @@ on:
- main
paths:
- '.github/workflows/build-ios.yml'
- 'cpp/**'
- 'ios/**'
- '*.podspec'
- 'example/ios/**'
- 'package/cpp/**'
- 'package/ios/**'
- 'package/*.podspec'
- 'package/example/ios/**'
pull_request:
paths:
- '.github/workflows/build-ios.yml'
- 'cpp/**'
- 'ios/**'
- '*.podspec'
- 'example/ios/**'
- 'package/cpp/**'
- 'package/ios/**'
- 'package/*.podspec'
- 'package/example/ios/**'

jobs:
build:
Expand Down
8 changes: 4 additions & 4 deletions .github/workflows/validate-android.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,13 @@ on:
- main
paths:
- '.github/workflows/validate-android.yml'
- 'android/**'
- '.editorconfig'
- 'package/android/**'
- 'package/.editorconfig'
pull_request:
paths:
- '.github/workflows/validate-android.yml'
- 'android/**'
- '.editorconfig'
- 'package/android/**'
- 'package/.editorconfig'

jobs:
lint:
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/validate-ios.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@ on:
- main
paths:
- '.github/workflows/validate-ios.yml'
- 'ios/**'
- 'package/ios/**'
pull_request:
paths:
- '.github/workflows/validate-ios.yml'
- 'ios/**'
- 'package/ios/**'

jobs:
SwiftLint:
Expand Down
15 changes: 0 additions & 15 deletions package/android/src/main/java/com/mrousavy/camera/CameraView.kt
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import android.Manifest
import android.annotation.SuppressLint
import android.content.Context
import android.content.pm.PackageManager
import android.content.res.Configuration
import android.hardware.camera2.CameraManager
import android.util.Log
import android.util.Size
Expand All @@ -31,13 +30,8 @@ import kotlinx.coroutines.launch
//
// TODOs for the CameraView which are currently too hard to implement either because of CameraX' limitations, or my brain capacity.
//
// CameraView
// TODO: High-speed video recordings (export in CameraViewModule::getAvailableVideoDevices(), and set in CameraView::configurePreview()) (120FPS+)

// CameraView+RecordVideo
// TODO: Better startRecording()/stopRecording() (promise + callback, wait for TurboModules/JSI)

// CameraView+TakePhoto
// TODO: takePhoto() depth data
// TODO: takePhoto() raw capture
// TODO: takePhoto() return with jsi::Value Image reference for faster capture
Expand Down Expand Up @@ -103,11 +97,6 @@ class CameraView(context: Context) : FrameLayout(context) {
cameraSession = CameraSession(context, cameraManager, { invokeOnInitialized() }, { error -> invokeOnError(error) })
}

override fun onConfigurationChanged(newConfig: Configuration?) {
super.onConfigurationChanged(newConfig)
// TODO: updateOrientation()
}

override fun onAttachedToWindow() {
super.onAttachedToWindow()
if (!isMounted) {
Expand Down Expand Up @@ -144,7 +133,6 @@ class CameraView(context: Context) : FrameLayout(context) {
val shouldReconfigureFormat = shouldReconfigureSession || changedProps.containsAny(propsThatRequireFormatReconfiguration)
val shouldReconfigureZoom = shouldReconfigureSession || changedProps.contains("zoom")
val shouldReconfigureTorch = shouldReconfigureSession || changedProps.contains("torch")
val shouldUpdateOrientation = /* TODO: When should we reconfigure this? */ shouldReconfigureSession || changedProps.contains("orientation")
val shouldCheckActive = shouldReconfigureFormat || changedProps.contains("isActive")
val shouldReconfigureZoomGesture = changedProps.contains("enableZoomGesture")

Expand All @@ -167,9 +155,6 @@ class CameraView(context: Context) : FrameLayout(context) {
if (shouldReconfigureTorch) {
updateTorch()
}
if (shouldUpdateOrientation) {
// TODO: updateOrientation()
}
if (shouldReconfigureZoomGesture) {
updateZoomGesture()
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ import com.mrousavy.camera.parsers.VideoStabilizationMode

@Suppress("unused")
class CameraViewManager : ViewGroupManager<CameraView>() {

public override fun createViewInstance(context: ThemedReactContext): CameraView {
return CameraView(context)
}
Expand Down
7 changes: 0 additions & 7 deletions package/android/src/main/java/com/mrousavy/camera/Errors.kt
Original file line number Diff line number Diff line change
Expand Up @@ -37,15 +37,8 @@ class CameraPermissionError : CameraError("permission", "camera-permission-denie
class InvalidTypeScriptUnionError(unionName: String, unionValue: String) : CameraError("parameter", "invalid-parameter", "The given value for $unionName could not be parsed! (Received: $unionValue)")

class NoCameraDeviceError : CameraError("device", "no-device", "No device was set! Use `getAvailableCameraDevices()` to select a suitable Camera device.")
class NoFlashAvailableError : CameraError("device", "flash-unavailable", "The Camera Device does not have a flash unit! Make sure you select a device where `hasFlash`/`hasTorch` is true!")
class PixelFormatNotSupportedError(format: String) : CameraError("device", "pixel-format-not-supported", "The pixelFormat $format is not supported on the given Camera Device!")

class HdrNotContainedInFormatError : CameraError(
"format", "invalid-hdr",
"The currently selected format does not support HDR capture! " +
"Make sure you select a format which includes `supportsPhotoHDR`!"
)

class CameraNotReadyError : CameraError("session", "camera-not-ready", "The Camera is not ready yet! Wait for the onInitialized() callback!")
class CameraCannotBeOpenedError(cameraId: String, error: CameraDeviceError) : CameraError("session", "camera-cannot-be-opened", "The given Camera device (id: $cameraId) could not be opened! Error: $error")
class CameraSessionCannotBeConfiguredError(cameraId: String, outputs: CameraOutputs) : CameraError("session", "cannot-create-session", "Failed to create a Camera Session for Camera $cameraId! Outputs: $outputs")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,6 @@ class CameraDeviceDetails(private val cameraManager: CameraManager, private val
return array
}


// 35mm is 135 film format, a standard in which focal lengths are usually measured
private val size35mm = Size(36, 24)

Expand Down Expand Up @@ -153,7 +152,6 @@ class CameraDeviceDetails(private val cameraManager: CameraManager, private val
return array
}

// Get available pixel formats for the given Size
private fun createPixelFormats(size: Size): ReadableArray {
val formats = cameraConfig.outputFormats
val array = Arguments.createArray()
Expand Down Expand Up @@ -186,7 +184,6 @@ class CameraDeviceDetails(private val cameraManager: CameraManager, private val
return map
}

// convert to React Native JS object (map)
fun toMap(): ReadableMap {
val map = Arguments.createMap()
map.putString("id", cameraId)
Expand All @@ -205,39 +202,7 @@ class CameraDeviceDetails(private val cameraManager: CameraManager, private val
map.putDouble("neutralZoom", 1.0) // Zoom is always relative to 1.0 on Android
map.putString("hardwareLevel", hardwareLevel.unionValue)
map.putString("sensorOrientation", Orientation.fromRotationDegrees(sensorOrientation).unionValue)

val array = Arguments.createArray()
cameraConfig.outputFormats.forEach { f ->
val str = when (f) {
ImageFormat.YUV_420_888 -> "YUV_420_888"
ImageFormat.YUV_422_888 -> "YUV_422_888"
ImageFormat.YUV_444_888 -> "YUV_444_888"
ImageFormat.JPEG -> "JPEG"
ImageFormat.DEPTH16 -> "DEPTH16"
ImageFormat.DEPTH_JPEG -> "DEPTH_JPEG"
ImageFormat.FLEX_RGBA_8888 -> "FLEX_RGBA_8888"
ImageFormat.FLEX_RGB_888 -> "FLEX_RGB_888"
ImageFormat.YUY2 -> "YUY2"
ImageFormat.Y8 -> "Y8"
ImageFormat.YV12 -> "YV12"
ImageFormat.HEIC -> "HEIC"
ImageFormat.PRIVATE -> "PRIVATE"
ImageFormat.RAW_PRIVATE -> "RAW_PRIVATE"
ImageFormat.RAW_SENSOR -> "RAW_SENSOR"
ImageFormat.RAW10 -> "RAW10"
ImageFormat.RAW12 -> "RAW12"
ImageFormat.NV16 -> "NV16"
ImageFormat.NV21 -> "NV21"
ImageFormat.UNKNOWN -> "UNKNOWN"
ImageFormat.YCBCR_P010 -> "YCBCR_P010"
else -> "unknown ($f)"
}
array.pushString(str)
}
map.putArray("pixelFormats", array)

map.putArray("formats", getFormats())

return map
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,10 @@ import com.mrousavy.camera.PhotoNotEnabledError
import com.mrousavy.camera.RecorderError
import com.mrousavy.camera.RecordingInProgressError
import com.mrousavy.camera.VideoNotEnabledError
import com.mrousavy.camera.extensions.SessionType
import com.mrousavy.camera.extensions.capture
import com.mrousavy.camera.extensions.createCaptureSession
import com.mrousavy.camera.extensions.createPhotoCaptureRequest
import com.mrousavy.camera.extensions.openCamera
import com.mrousavy.camera.extensions.tryClose
import com.mrousavy.camera.extensions.zoomed
import com.mrousavy.camera.frameprocessor.FrameProcessor
import com.mrousavy.camera.parsers.Flash
Expand Down Expand Up @@ -116,7 +114,7 @@ class CameraSession(private val context: Context,
cameraManager.unregisterAvailabilityCallback(this)
photoOutputSynchronizer.clear()
captureSession?.close()
cameraDevice?.tryClose()
cameraDevice?.close()
outputs?.close()
isRunning = false
}
Expand Down Expand Up @@ -206,7 +204,6 @@ class CameraSession(private val context: Context,

private fun updateVideoOutputs() {
val videoPipeline = outputs?.videoOutput?.videoPipeline ?: return
val previewOutput = outputs?.previewOutput
videoPipeline.setRecordingSessionOutput(this.recording)
videoPipeline.setFrameProcessorOutput(this.frameProcessor)
}
Expand Down Expand Up @@ -377,7 +374,7 @@ class CameraSession(private val context: Context,
return currentDevice
}
// Close previous device
cameraDevice?.tryClose()
cameraDevice?.close()
cameraDevice = null

val device = cameraManager.openCamera(cameraId, { camera, reason ->
Expand Down Expand Up @@ -410,7 +407,7 @@ class CameraSession(private val context: Context,
captureSession?.close()
captureSession = null

val session = cameraDevice.createCaptureSession(cameraManager, SessionType.REGULAR, outputs, { session ->
val session = cameraDevice.createCaptureSession(cameraManager, outputs, { session ->
Log.d(TAG, "Capture Session Closed ($captureSession == $session)")
if (captureSession == session) {
// The current CameraCaptureSession has been closed, handle that!
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,6 @@ class PreviewView(context: Context,
}

companion object {
private const val TAG = "NativePreviewView"
private const val TAG = "PreviewView"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -108,10 +108,7 @@ class VideoPipeline(val width: Int,
}

/**
* Configures the Pipeline to also call the given [FrameProcessor].
* * If the [frameProcessor] is `null`, this output channel will be removed.
* * If the [frameProcessor] is not `null`, the [VideoPipeline] will create Frames
* using an [ImageWriter] and call the [FrameProcessor] with those Frames.
* Configures the Pipeline to also call the given [FrameProcessor] (or null).
*/
fun setFrameProcessorOutput(frameProcessor: FrameProcessor?) {
synchronized(this) {
Expand All @@ -138,9 +135,7 @@ class VideoPipeline(val width: Int,
}

/**
* Configures the Pipeline to also write Frames to a Surface from a [MediaRecorder].
* * If the [surface] is `null`, this output channel will be removed.
* * If the [surface] is not `null`, the [VideoPipeline] will write Frames to this Surface.
* Configures the Pipeline to also write Frames to a Surface from a [MediaRecorder] (or null)
*/
fun setRecordingSessionOutput(recordingSession: RecordingSession?) {
synchronized(this) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,7 @@ class CameraOutputs(val cameraId: String,
val photo: PhotoOutput? = null,
val video: VideoOutput? = null,
val enableHdr: Boolean? = false,
val callback: Callback
): Closeable {
val callback: Callback): Closeable {
companion object {
private const val TAG = "CameraOutputs"
const val PHOTO_OUTPUT_BUFFER_SIZE = 3
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,6 @@ import android.util.Log
import android.util.Size
import java.io.Closeable

/**
* A [SurfaceOutput] that uses an [ImageReader] as it's surface.
*/
class ImageReaderOutput(private val imageReader: ImageReader,
outputType: OutputType,
dynamicRangeProfile: Long? = null): Closeable, SurfaceOutput(imageReader.surface, Size(imageReader.width, imageReader.height), outputType, dynamicRangeProfile) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,6 @@ import android.view.Surface
import androidx.annotation.RequiresApi
import java.io.Closeable

/**
* A general-purpose Camera Output that writes to a [Surface]
*/
open class SurfaceOutput(val surface: Surface,
val size: Size,
val outputType: OutputType,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,6 @@ import android.util.Size
import com.mrousavy.camera.core.VideoPipeline
import java.io.Closeable

/**
* A [SurfaceOutput] that uses a [VideoPipeline] as it's surface.
*/
class VideoPipelineOutput(val videoPipeline: VideoPipeline,
outputType: OutputType,
dynamicRangeProfile: Long? = null): Closeable, SurfaceOutput(videoPipeline.surface, Size(videoPipeline.width, videoPipeline.height), outputType, dynamicRangeProfile) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,24 +16,10 @@ import kotlinx.coroutines.suspendCancellableCoroutine
import kotlin.coroutines.resume
import kotlin.coroutines.resumeWithException

enum class SessionType {
REGULAR,
HIGH_SPEED;

@RequiresApi(Build.VERSION_CODES.P)
fun toSessionType(): Int {
return when(this) {
REGULAR -> SessionConfiguration.SESSION_REGULAR
HIGH_SPEED -> SessionConfiguration.SESSION_HIGH_SPEED
}
}
}

private const val TAG = "CreateCaptureSession"
private var sessionId = 1000

suspend fun CameraDevice.createCaptureSession(cameraManager: CameraManager,
sessionType: SessionType,
outputs: CameraOutputs,
onClosed: (session: CameraCaptureSession) -> Unit,
queue: CameraQueues.CameraQueue): CameraCaptureSession {
Expand Down Expand Up @@ -85,7 +71,7 @@ suspend fun CameraDevice.createCaptureSession(cameraManager: CameraManager,

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
Log.i(TAG, "Using new API (>=28)")
val config = SessionConfiguration(sessionType.toSessionType(), outputConfigurations, queue.executor, callback)
val config = SessionConfiguration(SessionConfiguration.SESSION_REGULAR, outputConfigurations, queue.executor, callback)
this.createCaptureSession(config)
} else {
Log.i(TAG, "Using legacy API (<28)")
Expand Down
Loading

1 comment on commit f3fd3f1

@vercel
Copy link

@vercel vercel bot commented on f3fd3f1 Sep 1, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.