Skip to content

Commit

Permalink
Properly set output orientation (I think)
Browse files Browse the repository at this point in the history
  • Loading branch information
mrousavy committed Jun 4, 2024
1 parent 2623619 commit c99d92b
Show file tree
Hide file tree
Showing 5 changed files with 39 additions and 10 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,10 @@ class CameraSession(private val context: Context, private val callback: Callback
// Threading
private val mainExecutor = ContextCompat.getMainExecutor(context)

// Orientation
val outputOrientation: Orientation
get() = orientationManager.outputOrientation

init {
lifecycleRegistry.currentState = Lifecycle.State.CREATED
lifecycle.addObserver(object : LifecycleEventObserver {
Expand Down Expand Up @@ -511,6 +515,7 @@ class CameraSession(private val context: Context, private val callback: Callback
}

override fun onOutputOrientationChanged(outputOrientation: Orientation) {
Log.i(TAG, "Output orientation changed! $outputOrientation")
photoOutput?.targetRotation = outputOrientation.toSurfaceRotation()
videoOutput?.targetRotation = outputOrientation.toSurfaceRotation()
frameProcessorOutput?.targetRotation = outputOrientation.toSurfaceRotation()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import android.content.Context
import android.hardware.display.DisplayManager
import android.util.Log
import android.view.OrientationEventListener
import android.view.Surface
import androidx.camera.core.UseCase
import com.mrousavy.camera.core.types.Orientation
import com.mrousavy.camera.core.types.OutputOrientation

Expand All @@ -15,30 +17,42 @@ class OrientationManager(private val context: Context, private val callback: Cal
private var targetOutputOrientation = OutputOrientation.DEVICE

// Screen Orientation Listener
private var screenRotation = Surface.ROTATION_0
private val displayManager = context.getSystemService(Context.DISPLAY_SERVICE) as DisplayManager
private val displayListener = object : DisplayManager.DisplayListener {
override fun onDisplayAdded(displayId: Int) = Unit
override fun onDisplayRemoved(displayId: Int) = Unit
override fun onDisplayChanged(displayId: Int) {
// Display rotated!
val display = displayManager.getDisplay(displayId) ?: return
val surfaceRotation = display.rotation
val orientation = Orientation.fromRotationDegrees(surfaceRotation)
Log.i(TAG, "Output orientation changed! $orientation (screen)")
callback.onOutputOrientationChanged(orientation)
screenRotation = display.rotation
callback.onOutputOrientationChanged(outputOrientation)
}
}

// Physical Device Orientation listener
private var deviceRotation = Surface.ROTATION_0
private val orientationListener = object: OrientationEventListener(context) {
override fun onOrientationChanged(rotationDegrees: Int) {
// Phone rotated!
val orientation = Orientation.fromRotationDegrees(rotationDegrees)
Log.i(TAG, "Output orientation changed! $orientation (device)")
callback.onOutputOrientationChanged(orientation)
deviceRotation = degreesToSurfaceRotation(rotationDegrees)
callback.onOutputOrientationChanged(outputOrientation)
}
}

// Get the current output orientation (a computed value)
val outputOrientation: Orientation
get() {
return when (targetOutputOrientation) {
OutputOrientation.DEVICE -> Orientation.fromSurfaceRotation(deviceRotation)
OutputOrientation.PREVIEW -> Orientation.fromSurfaceRotation(screenRotation)
OutputOrientation.PORTRAIT -> Orientation.PORTRAIT
OutputOrientation.LANDSCAPE_LEFT -> Orientation.LANDSCAPE_LEFT
OutputOrientation.PORTRAIT_UPSIDE_DOWN -> Orientation.PORTRAIT_UPSIDE_DOWN
OutputOrientation.LANDSCAPE_RIGHT -> Orientation.LANDSCAPE_RIGHT
}
}

fun setTargetOutputOrientation(targetOrientation: OutputOrientation) {
if (targetOutputOrientation == targetOrientation) {
// already the same
Expand Down Expand Up @@ -66,6 +80,15 @@ class OrientationManager(private val context: Context, private val callback: Cal
}
}

private fun degreesToSurfaceRotation(degrees: Int): Int {
return when (degrees) {
in 45..135 -> Surface.ROTATION_90
in 135..225 -> Surface.ROTATION_180
in 225..315 -> Surface.ROTATION_270
else -> Surface.ROTATION_0
}
}

interface Callback {
fun onOutputOrientationChanged(outputOrientation: Orientation)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ fun CameraView.startRecording(options: RecordVideoOptions, onRecordCallback: Cal
val errorMap = makeErrorMap(error.code, error.message)
onRecordCallback(null, errorMap)
}
cameraSession.startRecording(audio, options, orientation, callback, onError)
cameraSession.startRecording(audio, options, callback, onError)
}

fun CameraView.pauseRecording() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,7 @@ suspend fun CameraView.takePhoto(optionsMap: ReadableMap): WritableMap {

val photo = cameraSession.takePhoto(
Flash.fromUnionValue(flash),
enableShutterSound,
orientation
enableShutterSound
)

Log.i(TAG, "Successfully captured ${photo.width} x ${photo.height} photo!")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ fun CameraView.takeSnapshot(options: SnapshotOptions): WritableMap {

Log.i(TAG, "Successfully saved snapshot to file!")

val orientation = cameraSession.outputOrientation

val map = Arguments.createMap()
map.putString("path", file.absolutePath)
map.putInt("width", bitmap.width)
Expand Down

0 comments on commit c99d92b

Please sign in to comment.