From 11c0b87f2c083b6acc5902e5e5f99f1c68dac634 Mon Sep 17 00:00:00 2001 From: biaowu Date: Mon, 4 Jul 2022 10:28:43 +0800 Subject: [PATCH 1/2] =?UTF-8?q?refactor:=20=E8=9E=8D=E5=90=88=E5=8A=A8?= =?UTF-8?q?=E7=94=BB=E8=B5=84=E6=BA=90=E8=8E=B7=E5=8F=96=E9=80=BB=E8=BE=91?= =?UTF-8?q?=E6=8A=BD=E5=8F=96=EF=BC=8C=E4=BB=A5=E5=88=A9=E4=BA=8E=E6=94=AF?= =?UTF-8?q?=E6=8C=81=E5=BC=82=E6=AD=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../animplayer/mix/IMixResourceRequest.kt | 6 + .../qgame/animplayer/mix/MixAnimPlugin.kt | 104 +-------------- .../animplayer/mix/MixResourceRequestSync.kt | 122 ++++++++++++++++++ 3 files changed, 135 insertions(+), 97 deletions(-) create mode 100644 Android/PlayerProj/animplayer/src/main/java/com/tencent/qgame/animplayer/mix/IMixResourceRequest.kt create mode 100644 Android/PlayerProj/animplayer/src/main/java/com/tencent/qgame/animplayer/mix/MixResourceRequestSync.kt diff --git a/Android/PlayerProj/animplayer/src/main/java/com/tencent/qgame/animplayer/mix/IMixResourceRequest.kt b/Android/PlayerProj/animplayer/src/main/java/com/tencent/qgame/animplayer/mix/IMixResourceRequest.kt new file mode 100644 index 00000000..6cc42b58 --- /dev/null +++ b/Android/PlayerProj/animplayer/src/main/java/com/tencent/qgame/animplayer/mix/IMixResourceRequest.kt @@ -0,0 +1,6 @@ +package com.tencent.qgame.animplayer.mix + +interface IMixResourceRequest { + fun fetchResource(): Int + fun destroy() +} \ No newline at end of file diff --git a/Android/PlayerProj/animplayer/src/main/java/com/tencent/qgame/animplayer/mix/MixAnimPlugin.kt b/Android/PlayerProj/animplayer/src/main/java/com/tencent/qgame/animplayer/mix/MixAnimPlugin.kt index 88160462..1090befa 100644 --- a/Android/PlayerProj/animplayer/src/main/java/com/tencent/qgame/animplayer/mix/MixAnimPlugin.kt +++ b/Android/PlayerProj/animplayer/src/main/java/com/tencent/qgame/animplayer/mix/MixAnimPlugin.kt @@ -15,10 +15,8 @@ */ package com.tencent.qgame.animplayer.mix -import android.graphics.Bitmap import android.os.Handler import android.os.Looper -import android.os.SystemClock import android.view.MotionEvent import com.tencent.qgame.animplayer.AnimConfig import com.tencent.qgame.animplayer.AnimPlayer @@ -27,7 +25,6 @@ import com.tencent.qgame.animplayer.inter.IFetchResource import com.tencent.qgame.animplayer.inter.OnResourceClickListener import com.tencent.qgame.animplayer.plugin.IAnimPlugin import com.tencent.qgame.animplayer.util.ALog -import com.tencent.qgame.animplayer.util.BitmapUtil class MixAnimPlugin(val player: AnimPlayer): IAnimPlugin { @@ -39,15 +36,11 @@ class MixAnimPlugin(val player: AnimPlayer): IAnimPlugin { var srcMap: SrcMap? = null var frameAll: FrameAll? = null var curFrameIndex = -1 // 当前帧 - private var resultCbCount = 0 // 回调次数 private var mixRender:MixRender? = null private val mixTouch by lazy { MixTouch(this) } var autoTxtColorFill = true // 是否启动自动文字填充 默认开启 - // 同步锁 - private val lock = Object() - private var forceStopLock = false - + private var mixResourceRequest: IMixResourceRequest? = null override fun onConfigCreate(config: AnimConfig): Int { if (!config.isMix) return Constant.OK @@ -62,27 +55,12 @@ class MixAnimPlugin(val player: AnimPlayer): IAnimPlugin { // step 2 parse frame parseFrame(config) - // step 3 fetch resource - fetchResourceSync() - - // step 4 生成文字bitmap - val result = createBitmap() - if (!result) { - return Constant.REPORT_ERROR_TYPE_CONFIG_PLUGIN_MIX - } + mixResourceRequest = createMixResourceRequest() + return mixResourceRequest?.fetchResource() ?: Constant.OK + } - // step 5 check resource - ALog.i(TAG, "load resource $resultCbCount") - srcMap?.map?.values?.forEach { - if (it.bitmap == null) { - ALog.e(TAG, "missing src $it") - return Constant.REPORT_ERROR_TYPE_CONFIG_PLUGIN_MIX - } else if (it.bitmap?.config == Bitmap.Config.ALPHA_8) { - ALog.e(TAG, "src $it bitmap must not be ALPHA_8") - return Constant.REPORT_ERROR_TYPE_CONFIG_PLUGIN_MIX - } - } - return Constant.OK + private fun createMixResourceRequest(): IMixResourceRequest { + return MixResourceRequestSync(resourceRequest, srcMap) } override fun onRenderCreate() { @@ -126,8 +104,7 @@ class MixAnimPlugin(val player: AnimPlayer): IAnimPlugin { } private fun destroy() { - // 强制结束等待 - forceStopLockThread() + mixResourceRequest?.destroy() if (player.configManager.config?.isMix == false) return val resources = ArrayList() srcMap?.map?.values?.forEach {src -> @@ -159,71 +136,4 @@ class MixAnimPlugin(val player: AnimPlayer): IAnimPlugin { } } - - private fun fetchResourceSync() { - synchronized(lock) { - forceStopLock = false // 开始时不会强制关闭 - } - val time = SystemClock.elapsedRealtime() - val totalSrc = srcMap?.map?.size ?: 0 - ALog.i(TAG, "load resource totalSrc = $totalSrc") - - resultCbCount = 0 - srcMap?.map?.values?.forEach {src -> - if (src.srcType == Src.SrcType.IMG) { - ALog.i(TAG, "fetch image ${src.srcId}") - resourceRequest?.fetchImage(Resource(src)) { - src.bitmap = if (it == null) { - ALog.e(TAG, "fetch image ${src.srcId} bitmap return null") - BitmapUtil.createEmptyBitmap() - } else it - ALog.i(TAG, "fetch image ${src.srcId} finish bitmap is ${it?.hashCode()}") - resultCall() - } - } else if (src.srcType == Src.SrcType.TXT) { - ALog.i(TAG, "fetch txt ${src.srcId}") - resourceRequest?.fetchText(Resource(src)) { - src.txt = it ?: "" - ALog.i(TAG, "fetch text ${src.srcId} finish txt is $it") - resultCall() - } - } - } - - // 同步等待所有资源完成 - synchronized(lock) { - while (resultCbCount < totalSrc && !forceStopLock) { - lock.wait() - } - } - ALog.i(TAG, "fetchResourceSync cost=${SystemClock.elapsedRealtime() - time}ms") - } - - private fun forceStopLockThread() { - synchronized(lock) { - forceStopLock = true - lock.notifyAll() - } - } - - private fun resultCall() { - synchronized(lock) { - resultCbCount++ - lock.notifyAll() - } - } - - private fun createBitmap(): Boolean { - return try { - srcMap?.map?.values?.forEach { src -> - if (src.srcType == Src.SrcType.TXT) { - src.bitmap = BitmapUtil.createTxtBitmap(src) - } - } - true - } catch (e: OutOfMemoryError) { - ALog.e(TAG, "draw text OOM $e", e) - false - } - } } \ No newline at end of file diff --git a/Android/PlayerProj/animplayer/src/main/java/com/tencent/qgame/animplayer/mix/MixResourceRequestSync.kt b/Android/PlayerProj/animplayer/src/main/java/com/tencent/qgame/animplayer/mix/MixResourceRequestSync.kt new file mode 100644 index 00000000..adb1b002 --- /dev/null +++ b/Android/PlayerProj/animplayer/src/main/java/com/tencent/qgame/animplayer/mix/MixResourceRequestSync.kt @@ -0,0 +1,122 @@ +package com.tencent.qgame.animplayer.mix + +import android.graphics.Bitmap +import android.os.SystemClock +import com.tencent.qgame.animplayer.Constant +import com.tencent.qgame.animplayer.inter.IFetchResource +import com.tencent.qgame.animplayer.util.ALog +import com.tencent.qgame.animplayer.util.BitmapUtil + +class MixResourceRequestSync( + private val resourceRequest: IFetchResource?, + private val srcMap: SrcMap? +) : + IMixResourceRequest { + companion object { + private const val TAG = "${Constant.TAG}.MixResourceRequestSync" + } + + private var resultCbCount = 0 // 回调次数 + + // 同步锁 + private val lock = Object() + private var forceStopLock = false + + + override fun fetchResource(): Int { + // step 3 fetch resource + fetchResourceSync() + + // step 4 生成文字bitmap + val result = createBitmap() + if (!result) { + return Constant.REPORT_ERROR_TYPE_CONFIG_PLUGIN_MIX + } + + // step 5 check resource + ALog.i(TAG, "load resource $resultCbCount") + srcMap?.map?.values?.forEach { + if (it.bitmap == null) { + ALog.e(TAG, "missing src $it") + return Constant.REPORT_ERROR_TYPE_CONFIG_PLUGIN_MIX + } else if (it.bitmap?.config == Bitmap.Config.ALPHA_8) { + ALog.e(TAG, "src $it bitmap must not be ALPHA_8") + return Constant.REPORT_ERROR_TYPE_CONFIG_PLUGIN_MIX + } + } + return Constant.OK + } + + override fun destroy() { + // 强制结束等待 + forceStopLockThread() + } + + private fun fetchResourceSync() { + synchronized(lock) { + forceStopLock = false // 开始时不会强制关闭 + } + val time = SystemClock.elapsedRealtime() + val totalSrc = srcMap?.map?.size ?: 0 + ALog.i(TAG, "load resource totalSrc = $totalSrc") + + resultCbCount = 0 + srcMap?.map?.values?.forEach {src -> + if (src.srcType == Src.SrcType.IMG) { + ALog.i(TAG, "fetch image ${src.srcId}") + resourceRequest?.fetchImage(Resource(src)) { + src.bitmap = if (it == null) { + ALog.e(TAG, "fetch image ${src.srcId} bitmap return null") + BitmapUtil.createEmptyBitmap() + } else it + ALog.i(TAG, "fetch image ${src.srcId} finish bitmap is ${it?.hashCode()}") + resultCall() + } + } else if (src.srcType == Src.SrcType.TXT) { + ALog.i(TAG, "fetch txt ${src.srcId}") + resourceRequest?.fetchText(Resource(src)) { + src.txt = it ?: "" + ALog.i(TAG, "fetch text ${src.srcId} finish txt is $it") + resultCall() + } + } + } + + // 同步等待所有资源完成 + synchronized(lock) { + while (resultCbCount < totalSrc && !forceStopLock) { + lock.wait() + } + } + ALog.i(TAG, "fetchResourceSync cost=${SystemClock.elapsedRealtime() - time}ms") + } + + private fun forceStopLockThread() { + synchronized(lock) { + forceStopLock = true + lock.notifyAll() + } + } + + private fun resultCall() { + synchronized(lock) { + resultCbCount++ + lock.notifyAll() + } + } + + private fun createBitmap(): Boolean { + return try { + srcMap?.map?.values?.forEach { src -> + if (src.srcType == Src.SrcType.TXT) { + src.bitmap = BitmapUtil.createTxtBitmap(src) + } + } + true + } catch (e: OutOfMemoryError) { + ALog.e(TAG, "draw text OOM $e", e) + false + } + } + +} \ No newline at end of file From 83a84c114522d23c2e3748e0bea7c5eec1f5d7ad Mon Sep 17 00:00:00 2001 From: biaowu Date: Mon, 4 Jul 2022 10:52:55 +0800 Subject: [PATCH 2/2] =?UTF-8?q?feat:=20=E8=9E=8D=E5=90=88=E5=8A=A8?= =?UTF-8?q?=E7=94=BB=E8=B5=84=E6=BA=90=E8=8E=B7=E5=8F=96=E5=BC=82=E6=AD=A5?= =?UTF-8?q?=E5=AE=9E=E7=8E=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/tencent/qgame/animplayer/AnimView.kt | 4 + .../com/tencent/qgame/animplayer/IAnimView.kt | 2 + .../qgame/animplayer/mix/MixAnimPlugin.kt | 7 +- .../animplayer/mix/MixResourceRequestASync.kt | 96 +++++++++++++++++++ .../playerproj/player/AnimVapxDemoActivity.kt | 33 +++++++ .../res/layout/activity_anim_simple_demo.xml | 11 ++- 6 files changed, 151 insertions(+), 2 deletions(-) create mode 100644 Android/PlayerProj/animplayer/src/main/java/com/tencent/qgame/animplayer/mix/MixResourceRequestASync.kt diff --git a/Android/PlayerProj/animplayer/src/main/java/com/tencent/qgame/animplayer/AnimView.kt b/Android/PlayerProj/animplayer/src/main/java/com/tencent/qgame/animplayer/AnimView.kt index 4a7961bd..6bb74dfd 100644 --- a/Android/PlayerProj/animplayer/src/main/java/com/tencent/qgame/animplayer/AnimView.kt +++ b/Android/PlayerProj/animplayer/src/main/java/com/tencent/qgame/animplayer/AnimView.kt @@ -193,6 +193,10 @@ open class AnimView @JvmOverloads constructor(context: Context, attrs: Attribute player.pluginManager.getMixAnimPlugin()?.resourceRequest = fetchResource } + override fun setFetchResourceAsync(async: Boolean) { + player.pluginManager.getMixAnimPlugin()?.async = async + } + override fun setOnResourceClickListener(resourceClickListener: OnResourceClickListener?) { player.pluginManager.getMixAnimPlugin()?.resourceClickListener = resourceClickListener } diff --git a/Android/PlayerProj/animplayer/src/main/java/com/tencent/qgame/animplayer/IAnimView.kt b/Android/PlayerProj/animplayer/src/main/java/com/tencent/qgame/animplayer/IAnimView.kt index d967b31d..098314bf 100644 --- a/Android/PlayerProj/animplayer/src/main/java/com/tencent/qgame/animplayer/IAnimView.kt +++ b/Android/PlayerProj/animplayer/src/main/java/com/tencent/qgame/animplayer/IAnimView.kt @@ -36,6 +36,8 @@ interface IAnimView { fun setFetchResource(fetchResource: IFetchResource?) + fun setFetchResourceAsync(async: Boolean) + fun setOnResourceClickListener(resourceClickListener: OnResourceClickListener?) fun setLoop(playLoop: Int) diff --git a/Android/PlayerProj/animplayer/src/main/java/com/tencent/qgame/animplayer/mix/MixAnimPlugin.kt b/Android/PlayerProj/animplayer/src/main/java/com/tencent/qgame/animplayer/mix/MixAnimPlugin.kt index 1090befa..5cf79ac2 100644 --- a/Android/PlayerProj/animplayer/src/main/java/com/tencent/qgame/animplayer/mix/MixAnimPlugin.kt +++ b/Android/PlayerProj/animplayer/src/main/java/com/tencent/qgame/animplayer/mix/MixAnimPlugin.kt @@ -40,6 +40,7 @@ class MixAnimPlugin(val player: AnimPlayer): IAnimPlugin { private val mixTouch by lazy { MixTouch(this) } var autoTxtColorFill = true // 是否启动自动文字填充 默认开启 + var async: Boolean = false private var mixResourceRequest: IMixResourceRequest? = null override fun onConfigCreate(config: AnimConfig): Int { @@ -60,7 +61,11 @@ class MixAnimPlugin(val player: AnimPlayer): IAnimPlugin { } private fun createMixResourceRequest(): IMixResourceRequest { - return MixResourceRequestSync(resourceRequest, srcMap) + return if (async) { + MixResourceRequestASync(resourceRequest, srcMap) + } else { + MixResourceRequestSync(resourceRequest, srcMap) + } } override fun onRenderCreate() { diff --git a/Android/PlayerProj/animplayer/src/main/java/com/tencent/qgame/animplayer/mix/MixResourceRequestASync.kt b/Android/PlayerProj/animplayer/src/main/java/com/tencent/qgame/animplayer/mix/MixResourceRequestASync.kt new file mode 100644 index 00000000..1f44283b --- /dev/null +++ b/Android/PlayerProj/animplayer/src/main/java/com/tencent/qgame/animplayer/mix/MixResourceRequestASync.kt @@ -0,0 +1,96 @@ +package com.tencent.qgame.animplayer.mix + +import android.graphics.Bitmap +import android.os.Handler +import android.os.SystemClock +import com.tencent.qgame.animplayer.Constant +import com.tencent.qgame.animplayer.inter.IFetchResource +import com.tencent.qgame.animplayer.util.ALog +import com.tencent.qgame.animplayer.util.BitmapUtil +import com.tencent.qgame.animplayer.util.TextureLoadUtil + + +class MixResourceRequestASync( + private val resourceRequest: IFetchResource?, + private val srcMap: SrcMap? +) : + IMixResourceRequest { + companion object { + private const val TAG = "${Constant.TAG}.MixResourceRequestASync" + } + + private var resultCbCount = 0 // 回调次数 + + var handler: Handler? = null + + override fun fetchResource(): Int { + fetchResourceASync() + + ALog.i(TAG, "load resource $resultCbCount") + srcMap?.map?.values?.forEach { + if (it.bitmap?.config == Bitmap.Config.ALPHA_8) { + ALog.e(TAG, "src $it bitmap must not be ALPHA_8") + return Constant.REPORT_ERROR_TYPE_CONFIG_PLUGIN_MIX + } + } + return Constant.OK + } + + override fun destroy() { + handler = null + } + + private fun fetchResourceASync() { + val time = SystemClock.elapsedRealtime() + val totalSrc = srcMap?.map?.size ?: 0 + ALog.i(TAG, "load resource totalSrc = $totalSrc") + + resultCbCount = 0 + srcMap?.map?.values?.apply { + handler = Handler() + forEach { src -> + if (src.srcType == Src.SrcType.IMG) { + ALog.i(TAG, "fetch image ${src.srcId}") + resourceRequest?.fetchImage(Resource(src)) { + handler?.post { + src.bitmap = if (it == null) { + ALog.e(TAG, "fetch image ${src.srcId} bitmap return null") + BitmapUtil.createEmptyBitmap() + } else it + src.srcTextureId = TextureLoadUtil.loadTexture(src.bitmap) + ALog.i( + TAG, + "fetch image ${src.srcId} finish bitmap is ${it?.hashCode()}" + + ",cost=${SystemClock.elapsedRealtime() - time}ms" + ) + resultCall() + } + } + } else if (src.srcType == Src.SrcType.TXT) { + ALog.i(TAG, "fetch txt ${src.srcId}") + resourceRequest?.fetchText(Resource(src)) { + handler?.post { + src.txt = it ?: "" + try { + src.bitmap = BitmapUtil.createTxtBitmap(src) + src.srcTextureId = TextureLoadUtil.loadTexture(src.bitmap) + } catch (e: OutOfMemoryError) { + ALog.e(TAG, "draw text OOM $e", e) + } + ALog.i( + TAG, "fetch text ${src.srcId} finish txt is $it" + + ",cost=${SystemClock.elapsedRealtime() - time}ms" + ) + resultCall() + } + } + } + } + } + } + + private fun resultCall() { + resultCbCount++ + } + +} diff --git a/Android/PlayerProj/app/src/main/java/com/tencent/qgame/playerproj/player/AnimVapxDemoActivity.kt b/Android/PlayerProj/app/src/main/java/com/tencent/qgame/playerproj/player/AnimVapxDemoActivity.kt index b23ad69b..5f3dc999 100644 --- a/Android/PlayerProj/app/src/main/java/com/tencent/qgame/playerproj/player/AnimVapxDemoActivity.kt +++ b/Android/PlayerProj/app/src/main/java/com/tencent/qgame/playerproj/player/AnimVapxDemoActivity.kt @@ -70,6 +70,8 @@ class AnimVapxDemoActivity : Activity(), IAnimListener { Handler(Looper.getMainLooper()) } + private var isAsync = false + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_anim_simple_demo) @@ -90,11 +92,25 @@ class AnimVapxDemoActivity : Activity(), IAnimListener { * 注册资源获取类 */ animView.setFetchResource(object : IFetchResource { + val asyncDelayTime = 9_000L + /** * 获取图片资源 * 无论图片是否获取成功都必须回调 result 否则会无限等待资源 */ override fun fetchImage(resource: Resource, result: (Bitmap?) -> Unit) { + if (isAsync) { + ALog.i(TAG, "fetchImage start ${resource.tag}, ${resource.id}") + Handler().postDelayed({ + ALog.i(TAG, "fetchImage real start ${resource.tag}, ${resource.id}") + realFetchImage(resource, result) + }, asyncDelayTime + 1000) + } else { + realFetchImage(resource, result) + } + } + + private fun realFetchImage(resource: Resource, result: (Bitmap?) -> Unit) { /** * srcTag是素材中的一个标记,在制作素材时定义 * 解析时由业务读取tag决定需要播放的内容是什么 @@ -117,6 +133,16 @@ class AnimVapxDemoActivity : Activity(), IAnimListener { * 获取文字资源 */ override fun fetchText(resource: Resource, result: (String?) -> Unit) { + if (isAsync) { + Handler().postDelayed({ + realFetchText(resource, result) + }, asyncDelayTime) + } else { + realFetchText(resource, result) + } + } + + fun realFetchText(resource: Resource, result: (String?) -> Unit) { val str = "恭喜 No.${1000 + Random().nextInt(8999)}用户 升神" val srcTag = resource.tag @@ -251,6 +277,13 @@ class AnimVapxDemoActivity : Activity(), IAnimListener { private fun initTestView() { btnLayout.visibility = View.VISIBLE + /** + * 是否异步 + */ + async.setOnCheckedChangeListener { _, async -> + isAsync = async + animView.setFetchResourceAsync(async) + } /** * 开始播放按钮 */ diff --git a/Android/PlayerProj/app/src/main/res/layout/activity_anim_simple_demo.xml b/Android/PlayerProj/app/src/main/res/layout/activity_anim_simple_demo.xml index 038e2b21..93099f93 100644 --- a/Android/PlayerProj/app/src/main/res/layout/activity_anim_simple_demo.xml +++ b/Android/PlayerProj/app/src/main/res/layout/activity_anim_simple_demo.xml @@ -13,7 +13,16 @@ android:layout_height="wrap_content" android:layout_gravity="bottom|right" android:orientation="horizontal" - android:visibility="gone"> + android:visibility="gone" + tools:visibility="visible"> + +