|
|
|
@ -5,6 +5,7 @@ import android.content.pm.PackageManager |
|
|
|
import android.content.Context |
|
|
|
import android.content.Context |
|
|
|
import android.graphics.Matrix |
|
|
|
import android.graphics.Matrix |
|
|
|
import android.graphics.SurfaceTexture |
|
|
|
import android.graphics.SurfaceTexture |
|
|
|
|
|
|
|
import android.os.Build |
|
|
|
import android.view.Surface |
|
|
|
import android.view.Surface |
|
|
|
import android.view.TextureView |
|
|
|
import android.view.TextureView |
|
|
|
import androidx.activity.compose.rememberLauncherForActivityResult |
|
|
|
import androidx.activity.compose.rememberLauncherForActivityResult |
|
|
|
@ -128,6 +129,19 @@ private class CallVideoTexture(context: Context, private val video: CallVideoEng |
|
|
|
private var closed = false |
|
|
|
private var closed = false |
|
|
|
private var format: CallVideoFormat? = null |
|
|
|
private var format: CallVideoFormat? = null |
|
|
|
private var large = false |
|
|
|
private var large = false |
|
|
|
|
|
|
|
private var commitPending = false |
|
|
|
|
|
|
|
private var lastCommitPts = -1L |
|
|
|
|
|
|
|
private val committed = Runnable { |
|
|
|
|
|
|
|
commitPending = false |
|
|
|
|
|
|
|
if (!closed) surfaceTexture?.let { texture -> |
|
|
|
|
|
|
|
val pts = texture.timestamp / 1000 |
|
|
|
|
|
|
|
if (pts > 0 && pts != lastCommitPts && pts % 1_000_000 < 34_000) |
|
|
|
|
|
|
|
com.utun.chat.data.LogManager.addLog("DEBUG", "debug", |
|
|
|
|
|
|
|
"video timing stage=commit pts=$pts mono_us=${System.nanoTime() / 1000} generation=${format?.generation} " + |
|
|
|
|
|
|
|
"visible=$isShown alpha=$alpha size=${width}x$height") |
|
|
|
|
|
|
|
lastCommitPts = pts |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
fun update(next: CallVideoFormat?, expanded: Boolean) { |
|
|
|
fun update(next: CallVideoFormat?, expanded: Boolean) { |
|
|
|
if (format == next && large == expanded) return |
|
|
|
if (format == next && large == expanded) return |
|
|
|
format = next; large = expanded; fit() |
|
|
|
format = next; large = expanded; fit() |
|
|
|
@ -144,11 +158,14 @@ private class CallVideoTexture(context: Context, private val video: CallVideoEng |
|
|
|
override fun onSurfaceTextureSizeChanged(texture: SurfaceTexture, width: Int, height: Int) { fit() } |
|
|
|
override fun onSurfaceTextureSizeChanged(texture: SurfaceTexture, width: Int, height: Int) { fit() } |
|
|
|
override fun onSurfaceTextureDestroyed(texture: SurfaceTexture): Boolean { closeOutput(); return false } |
|
|
|
override fun onSurfaceTextureDestroyed(texture: SurfaceTexture): Boolean { closeOutput(); return false } |
|
|
|
override fun onSurfaceTextureUpdated(texture: SurfaceTexture) { |
|
|
|
override fun onSurfaceTextureUpdated(texture: SurfaceTexture) { |
|
|
|
// MediaCodec передаёт исходный PTS в SurfaceTexture; не вычитаем его из локальных часов телефона. |
|
|
|
// applyUpdate лишь передаёт работу RenderThread: timestamp здесь ещё может принадлежать предыдущему кадру. |
|
|
|
val pts = texture.timestamp / 1000 |
|
|
|
val pts = texture.timestamp / 1000 |
|
|
|
if (pts > 0 && pts % 1_000_000 < 34_000) com.utun.chat.data.LogManager.addLog("DEBUG", "debug", |
|
|
|
if (pts > 0 && pts % 1_000_000 < 34_000) com.utun.chat.data.LogManager.addLog("DEBUG", "debug", |
|
|
|
"video timing stage=texture pts=$pts mono_us=${System.nanoTime() / 1000} generation=${format?.generation} " + |
|
|
|
"video timing stage=texture_update pts=$pts mono_us=${System.nanoTime() / 1000} generation=${format?.generation} " + |
|
|
|
"visible=$isShown alpha=$alpha size=${width}x$height") |
|
|
|
"visible=$isShown alpha=$alpha size=${width}x$height") |
|
|
|
|
|
|
|
if (Build.VERSION.SDK_INT >= 29 && isHardwareAccelerated && !commitPending) { |
|
|
|
|
|
|
|
commitPending = true; viewTreeObserver.registerFrameCommitCallback(committed) |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
@ -168,7 +185,11 @@ private class CallVideoTexture(context: Context, private val video: CallVideoEng |
|
|
|
com.utun.chat.data.LogManager.addLog("DEBUG", "call", "video fit view=${width}x$height frame=${w}x$h expanded=$large turn=$turn") |
|
|
|
com.utun.chat.data.LogManager.addLog("DEBUG", "call", "video fit view=${width}x$height frame=${w}x$h expanded=$large turn=$turn") |
|
|
|
} |
|
|
|
} |
|
|
|
private fun closeOutput() { attached?.let(video::detachSurface); attached = null } |
|
|
|
private fun closeOutput() { attached?.let(video::detachSurface); attached = null } |
|
|
|
fun close() { closed = true; closeOutput() } |
|
|
|
fun close() { |
|
|
|
|
|
|
|
closed = true |
|
|
|
|
|
|
|
if (Build.VERSION.SDK_INT >= 29 && viewTreeObserver.isAlive) viewTreeObserver.unregisterFrameCommitCallback(committed) |
|
|
|
|
|
|
|
closeOutput() |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@Composable |
|
|
|
@Composable |
|
|
|
|