¿Cómo ajustar el video en el fondo de pantalla en vivo, por recorte central y ajustando el ancho / alto?

Fond

Estoy haciendo un fondo de pantalla en vivo que puede mostrar un video. Al principio pensé que esto sería muy difícil, por lo que algunas personas sugirieron usar soluciones OpenGL u otras soluciones muy complejas (comoést).

e todos modos, para esto, he encontrado varios lugares hablando de eso, y en base a estogithub library (que tiene algunos errores), finalmente lo puse a trabajar.

El problem

Mientras logré mostrar un video, no puedo encontrar la forma de controlar cómo se muestra en comparación con la resolución de la pantalla.

Actualmente siempre se estira al tamaño de la pantalla, lo que significa que esto (video tomado deaqu):

se muestra como esto:

Reason es la relación de aspecto diferente: 560x320 (resolución de video) vs 1080x1920 (resolución del dispositivo).

Nota: Conozco bien las soluciones de escalado de videos, que están disponibles en varios repositorios de Github (comoaqu), pero estoy preguntando acerca de un fondo de pantalla en vivo. Como tal, no tiene una vista, por lo que es más limitado sobre cómo hacer las cosas. Para ser más específicos, una solución no puede tener ningún tipo de diseño, un TextureView o un SurfaceView, o cualquier otro tipo de Vista.

Lo que he probado

Intenté jugar con varios campos y funciones de SurfaceHolder, pero hasta ahora no he tenido suerte. Ejemplos:

setVideoScalingMode - se bloquea o no hace nada.

cambiando surfaceFrame - igual.

Aquí está el código actual que hice (proyecto completo disponibleaqu):

class MovieLiveWallpaperService : WallpaperService() {
    override fun onCreateEngine(): WallpaperService.Engine {
        return VideoLiveWallpaperEngine()
    }

    private enum class PlayerState {
        NONE, PREPARING, READY, PLAYING
    }

    inner class VideoLiveWallpaperEngine : WallpaperService.Engine() {
        private var mp: MediaPlayer? = null
        private var playerState: PlayerState = PlayerState.NONE

        override fun onSurfaceCreated(holder: SurfaceHolder) {
            super.onSurfaceCreated(holder)
            Log.d("AppLog", "onSurfaceCreated")
            mp = MediaPlayer()
            val mySurfaceHolder = MySurfaceHolder(holder)
            mp!!.setDisplay(mySurfaceHolder)
            mp!!.isLooping = true
            mp!!.setVolume(0.0f, 0.0f)
            mp!!.setOnPreparedListener { mp ->
                playerState = PlayerState.READY
                setPlay(true)
            }
            try {
                //mp!!.setDataSource(this@MovieLiveWallpaperService, Uri.parse("http://techslides.com/demos/sample-videos/small.mp4"))
                mp!!.setDataSource(this@MovieLiveWallpaperService, Uri.parse("android.resource://" + packageName + "/" + R.raw.small))
            } catch (e: Exception) {
            }
        }

        override fun onDestroy() {
            super.onDestroy()
            Log.d("AppLog", "onDestroy")
            if (mp == null)
                return
            mp!!.stop()
            mp!!.release()
            playerState = PlayerState.NONE
        }

        private fun setPlay(play: Boolean) {
            if (mp == null)
                return
            if (play == mp!!.isPlaying)
                return
            when {
                !play -> {
                    mp!!.pause()
                    playerState = PlayerState.READY
                }
                mp!!.isPlaying -> return
                playerState == PlayerState.READY -> {
                    Log.d("AppLog", "ready, so starting to play")
                    mp!!.start()
                    playerState = PlayerState.PLAYING
                }
                playerState == PlayerState.NONE -> {
                    Log.d("AppLog", "not ready, so preparing")
                    mp!!.prepareAsync()
                    playerState = PlayerState.PREPARING
                }
            }
        }

        override fun onVisibilityChanged(visible: Boolean) {
            super.onVisibilityChanged(visible)
            Log.d("AppLog", "onVisibilityChanged:" + visible + " " + playerState)
            if (mp == null)
                return
            setPlay(visible)
        }

    }

    class MySurfaceHolder(private val surfaceHolder: SurfaceHolder) : SurfaceHolder {
        override fun addCallback(callback: SurfaceHolder.Callback) = surfaceHolder.addCallback(callback)

        override fun getSurface() = surfaceHolder.surface!!

        override fun getSurfaceFrame() = surfaceHolder.surfaceFrame

        override fun isCreating(): Boolean = surfaceHolder.isCreating

        override fun lockCanvas(): Canvas = surfaceHolder.lockCanvas()

        override fun lockCanvas(dirty: Rect): Canvas = surfaceHolder.lockCanvas(dirty)

        override fun removeCallback(callback: SurfaceHolder.Callback) = surfaceHolder.removeCallback(callback)

        override fun setFixedSize(width: Int, height: Int) = surfaceHolder.setFixedSize(width, height)

        override fun setFormat(format: Int) = surfaceHolder.setFormat(format)

        override fun setKeepScreenOn(screenOn: Boolean) {}

        override fun setSizeFromLayout() = surfaceHolder.setSizeFromLayout()

        override fun setType(type: Int) = surfaceHolder.setType(type)

        override fun unlockCanvasAndPost(canvas: Canvas) = surfaceHolder.unlockCanvasAndPost(canvas)
    }
}
Las pregunta

Me gustaría saber cómo ajustar la escala del contenido en función de lo que tenemos para ImageView, todo manteniendo la relación de aspecto:

center-crop: se ajusta al 100% del contenedor (la pantalla en este caso), recortando a los lados (arriba y abajo o izquierda y derecha) cuando sea necesario. No estira nada. Esto significa que el contenido parece estar bien, pero no todo se puede mostrar. fit-center - estirar para ajustar ancho / alto center-inside: establecer como tamaño original, centrado y estirar para ajustar el ancho / alto solo si es demasiado grande.

Respuestas a la pregunta(3)

Su respuesta a la pregunta