feat: Add FPS Counter to Android (enableFpsGraph
) (#2460)
* feat: Add FPS Counter to Android (`enableFpsGraph`) * feat: Add FPS View * Update FpsCounterView.kt * Implement actual graph * fix layout * Update FpsGraphView.kt * Update CameraPage.tsx
This commit is contained in:
parent
8c5b60355f
commit
9089014ed8
@ -81,22 +81,28 @@ class CameraView(context: Context) :
|
||||
previewView.resizeMode = value
|
||||
field = value
|
||||
}
|
||||
var enableFpsGraph: Boolean = false
|
||||
set(value) {
|
||||
field = value
|
||||
updateFpsGraph()
|
||||
}
|
||||
|
||||
// code scanner
|
||||
var codeScannerOptions: CodeScannerOptions? = null
|
||||
|
||||
// private properties
|
||||
private var isMounted = false
|
||||
private val coroutineScope = CoroutineScope(CameraQueues.cameraQueue.coroutineDispatcher)
|
||||
internal val cameraManager = context.getSystemService(Context.CAMERA_SERVICE) as CameraManager
|
||||
|
||||
// session
|
||||
internal val cameraSession: CameraSession
|
||||
private val previewView: PreviewView
|
||||
private var currentConfigureCall: Long = System.currentTimeMillis()
|
||||
|
||||
internal var frameProcessor: FrameProcessor? = null
|
||||
|
||||
private val coroutineScope = CoroutineScope(CameraQueues.cameraQueue.coroutineDispatcher)
|
||||
// other
|
||||
private var fpsGraph: FpsGraphView? = null
|
||||
|
||||
init {
|
||||
this.installHierarchyFitter()
|
||||
@ -225,8 +231,22 @@ class CameraView(context: Context) :
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateFpsGraph() {
|
||||
if (enableFpsGraph) {
|
||||
if (fpsGraph != null) return
|
||||
fpsGraph = FpsGraphView(context)
|
||||
addView(fpsGraph)
|
||||
} else {
|
||||
if (fpsGraph == null) return
|
||||
removeView(fpsGraph)
|
||||
fpsGraph = null
|
||||
}
|
||||
}
|
||||
|
||||
override fun onFrame(frame: Frame) {
|
||||
frameProcessor?.call(frame)
|
||||
|
||||
fpsGraph?.onTick()
|
||||
}
|
||||
|
||||
override fun onError(error: Throwable) {
|
||||
|
@ -79,6 +79,11 @@ class CameraViewManager : ViewGroupManager<CameraView>() {
|
||||
view.enableZoomGesture = enableZoomGesture
|
||||
}
|
||||
|
||||
@ReactProp(name = "enableFpsGraph")
|
||||
fun setEnableFpsGraph(view: CameraView, enableFpsGraph: Boolean) {
|
||||
view.enableFpsGraph = enableFpsGraph
|
||||
}
|
||||
|
||||
@ReactProp(name = "videoStabilizationMode")
|
||||
fun setVideoStabilizationMode(view: CameraView, videoStabilizationMode: String?) {
|
||||
val newMode = VideoStabilizationMode.fromUnionValue(videoStabilizationMode)
|
||||
|
@ -0,0 +1,116 @@
|
||||
package com.mrousavy.camera
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.Context
|
||||
import android.graphics.Canvas
|
||||
import android.graphics.Color
|
||||
import android.graphics.Paint
|
||||
import android.view.Gravity
|
||||
import android.view.View
|
||||
import android.widget.FrameLayout
|
||||
import android.widget.TextView
|
||||
import kotlin.math.max
|
||||
import kotlin.math.roundToInt
|
||||
|
||||
@SuppressLint("SetTextI18n")
|
||||
class FpsGraphView(context: Context) : FrameLayout(context) {
|
||||
private val textView = TextView(context)
|
||||
private val graph = Graph(context)
|
||||
|
||||
init {
|
||||
textView.textSize = 18f
|
||||
textView.setTextColor(Color.WHITE)
|
||||
textView.text = "0 FPS"
|
||||
|
||||
graph.callback = object : Graph.Callback {
|
||||
override fun onAverageFpsChanged(averageFps: Int) {
|
||||
textView.text = "$averageFps FPS"
|
||||
}
|
||||
}
|
||||
|
||||
val layoutParams = LayoutParams(300, 150)
|
||||
layoutParams.setMargins(15, 150, 0, 0)
|
||||
layoutParams.gravity = Gravity.TOP or Gravity.LEFT
|
||||
addView(graph, layoutParams)
|
||||
addView(textView, layoutParams)
|
||||
}
|
||||
|
||||
fun onTick() {
|
||||
graph.onTick()
|
||||
}
|
||||
|
||||
class Graph(context: Context) :
|
||||
View(context),
|
||||
Runnable {
|
||||
private val maxBars = 30
|
||||
private val ticks = arrayListOf<Double>()
|
||||
private val bars = arrayListOf<Int>()
|
||||
private val paint = Paint().apply {
|
||||
color = Color.RED
|
||||
strokeWidth = 5f
|
||||
style = Paint.Style.FILL
|
||||
}
|
||||
var callback: Callback? = null
|
||||
|
||||
init {
|
||||
post(this)
|
||||
}
|
||||
|
||||
override fun run() {
|
||||
val averageFps = getAverageFps(ticks)
|
||||
ticks.clear()
|
||||
|
||||
bars.add(averageFps)
|
||||
if (bars.size > maxBars) {
|
||||
bars.removeAt(0)
|
||||
}
|
||||
|
||||
invalidate()
|
||||
postDelayed(this, 1000)
|
||||
|
||||
callback?.onAverageFpsChanged(averageFps)
|
||||
}
|
||||
|
||||
private fun getAverageFps(ticks: List<Double>): Int {
|
||||
if (ticks.isEmpty()) return 0
|
||||
if (ticks.size < 2) return 1
|
||||
|
||||
val totalDuration = ticks.last() - ticks.first()
|
||||
val averageFrameDuration = totalDuration / (ticks.size - 1).toDouble()
|
||||
|
||||
val double = 1000.0 / averageFrameDuration
|
||||
return double.roundToInt()
|
||||
}
|
||||
|
||||
fun onTick() {
|
||||
val currentTick = System.currentTimeMillis()
|
||||
ticks.add(currentTick.toDouble())
|
||||
}
|
||||
|
||||
override fun onDraw(canvas: Canvas) {
|
||||
super.onDraw(canvas)
|
||||
|
||||
if (bars.size < 2) return
|
||||
|
||||
val maxFps = max(bars.max().toFloat(), 60f)
|
||||
val blockWidth = width.toFloat() / maxBars
|
||||
for (i in 0..maxBars) {
|
||||
val fps = bars.getOrNull(i)
|
||||
if (fps != null) {
|
||||
val blockHeight = (fps / maxFps) * height
|
||||
canvas.drawRect(
|
||||
i * blockWidth,
|
||||
height - blockHeight,
|
||||
(i + 1) * blockWidth,
|
||||
height.toFloat(),
|
||||
paint
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
interface Callback {
|
||||
fun onAverageFpsChanged(averageFps: Int)
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user