Use direct camera preview instead of a local stream decoder

This commit is contained in:
evgeny committed 2026-10-14 14:58:03 +02:00
1 parent e8a63ec40d
commit 548e64c963
3 files changed
+146 -55

No files matched your search

@@ -4,45 +4,58 @@ import org.junit.Assert.*
import org.junit.Test
class StreamPreviewTest {
@Test fun manualRotationMovesRearTopMarkerWithoutRotatingCameraPreview() {
val camera = StreamPreviewCamera(90, false)
val display = StreamOrientation.values().map {
StreamVideoDisplay.forFrame(it.sensorRotation(90, false), camera, 0)
@Test fun cameraPreviewUsesSensorAndDisplayOrientation() {
val rear = StreamPreviewFormat(1280, 720, StreamPreviewCamera(90, false))
val front = StreamPreviewFormat(1280, 720, StreamPreviewCamera(270, true))
assertEquals(9f / 16f, rear.aspect(0), 0f)
assertEquals(16f / 9f, rear.aspect(90), 0f)
assertEquals(9f / 16f, front.aspect(0), 0f)
assertEquals(16f / 9f, front.aspect(90), 0f)
assertArrayEquals(floatArrayOf(1f, 0f, 1f, 1f, 0f, 1f, 0f, 0f), rear.corners(0), 0f)
assertArrayEquals(floatArrayOf(0f, 1f, 0f, 0f, 1f, 0f, 1f, 1f), front.corners(0), 0f)
assertArrayEquals(floatArrayOf(0f, 0f, 1f, 0f, 1f, 1f, 0f, 1f), rear.corners(90), 0f)
assertArrayEquals(floatArrayOf(0f, 0f, 1f, 0f, 1f, 1f, 0f, 1f), front.corners(90), 0f)
}
@Test fun allPreviewRotationsPreserveRectangleCorners() {
for (front in listOf(false, true)) for (sensor in listOf(0, 90, 180, 270)) for (display in listOf(0, 90, 180, 270)) {
val format = StreamPreviewFormat(640, 480, StreamPreviewCamera(sensor, front))
val corners = format.corners(display).toList().chunked(2)
assertEquals(setOf(listOf(0f, 0f), listOf(1f, 0f), listOf(1f, 1f), listOf(0f, 1f)), corners.toSet())
assertEquals(if (format.camera.rotation(display) % 180 == 0) 4f / 3f else 3f / 4f, format.aspect(display), 0f)
}
assertEquals(listOf(90, 90, 90, 90), display.map { it.rotation })
assertEquals(listOf(0, 90, 180, 270), display.map { it.top })
}
@Test fun frontCameraTopMarkerUsesItsOwnSensorDirection() {
val camera = StreamPreviewCamera(270, true)
val display = StreamOrientation.values().map {
StreamVideoDisplay.forFrame(it.sensorRotation(270, true), camera, 0)
}
assertEquals(listOf(270, 270, 270, 270), display.map { it.rotation })
assertEquals(listOf(0, 270, 180, 90), display.map { it.top })
@Test fun destroyedViewDoesNotReleaseCameraOrPendingCommandSurface() {
var released = 0
val lease = StreamPreviewLease { released++ }
lease.retain() // Команда, ожидающая camera handler.
lease.retain() // Сессия камеры.
lease.release() // UI TextureView уничтожен.
assertEquals(0, released)
lease.release() // Отменена ожидающая команда.
assertEquals(0, released)
lease.release() // Последняя сессия закрыта.
assertEquals(1, released)
}
@Test fun previewFollowsScreenWhileBroadcastKeepsManualOrientation() {
assertEquals(StreamVideoDisplay(0, 270), StreamVideoDisplay.forFrame(90, StreamPreviewCamera(90, false), 90))
assertEquals(StreamVideoDisplay(0, 90), StreamVideoDisplay.forFrame(270, StreamPreviewCamera(270, true), 90))
@Test fun sessionReplacementKeepsSurfaceUntilBothSessionsClose() {
var released = 0
val lease = StreamPreviewLease { released++ }
lease.retain(); lease.retain()
lease.release() // Старая сессия.
lease.release() // UI исчез, новая сессия ещё работает.
assertEquals(0, released)
lease.release()
assertEquals(1, released)
}
@Test fun remoteViewerKeepsBroadcastRotationWithoutLocalMarker() {
for (rotation in listOf(0, 90, 180, 270))
assertEquals(StreamVideoDisplay(rotation, null), StreamVideoDisplay.forFrame(rotation, null, 90))
}
@Test fun cameraSwitchRetainsPoseForAlreadyQueuedFrames() {
val preview = StreamPreview()
val rear = StreamPreviewCamera(90, false)
val front = StreamPreviewCamera(270, true)
preview.register(1, rear); preview.register(3, front)
assertEquals(rear, preview.camera(1))
assertEquals(front, preview.camera(3))
assertNull(preview.camera(2))
for (revision in 4L..40L) preview.register(revision, rear)
assertNull(preview.camera(1))
assertEquals(rear, preview.camera(9))
assertEquals(rear, preview.camera(40))
@Test fun closedSurfaceCannotBeRetainedOrReleasedAgain() {
var released = 0
val lease = StreamPreviewLease { released++ }
lease.release()
try { lease.retain(); fail("retained a closed surface") } catch (_: IllegalStateException) {}
try { lease.release(); fail("released a closed surface twice") } catch (_: IllegalStateException) {}
assertEquals(1, released)
}
}