|
@@ -11,12 +11,14 @@ import com.bomostory.sceneeditmodule.basicdata.Scene
|
|
|
import com.example.exportmedia.MediaHelper
|
|
|
import com.example.exportmedia.data.AudioSource
|
|
|
import com.example.exportmedia.vedio.MovieMaker
|
|
|
+import io.reactivex.Completable
|
|
|
import io.reactivex.Observable
|
|
|
+import io.reactivex.schedulers.Schedulers
|
|
|
import java.io.File
|
|
|
import java.util.AbstractMap
|
|
|
+import java.util.concurrent.Semaphore
|
|
|
import kotlin.collections.ArrayList
|
|
|
import kotlin.collections.LinkedHashMap
|
|
|
-import kotlin.collections.List
|
|
|
import kotlin.collections.set
|
|
|
import kotlin.math.pow
|
|
|
|
|
@@ -35,35 +37,33 @@ class SuperMovieMaker {
|
|
|
movieBuilder.audioSources = generateAudioSource(musics)
|
|
|
|
|
|
val inputSceneStatus = LinkedHashMap<Int, Int>()
|
|
|
- var sceneIndex = -1
|
|
|
- var sceneRepeatCount = 0
|
|
|
- var sceneCount = 0
|
|
|
-
|
|
|
- var totalFrame = 0
|
|
|
- scene?.record?.period?.let {
|
|
|
- totalFrame = (it / ((1f / FPS) * 1000).toLong()).toInt()
|
|
|
- }
|
|
|
-
|
|
|
- generateMovieFilms(
|
|
|
- scene,
|
|
|
- scaleWidth,
|
|
|
- scaleHeight
|
|
|
- )
|
|
|
- .subscribe {
|
|
|
- val msg = "progress ${sceneCount++}/$totalFrame"
|
|
|
- emitter.onNext("Compute image $msg")
|
|
|
- Log.d("Debug", msg)
|
|
|
- if (it.key == sceneIndex) {
|
|
|
- sceneRepeatCount++
|
|
|
- } else {
|
|
|
- sceneIndex = it.key
|
|
|
- sceneRepeatCount = 1
|
|
|
- movieBuilder.addImage(it.key, it.value).subscribe()
|
|
|
- emitter.onNext("Save image $msg")
|
|
|
+ val frameDataList = generateFrameDataList(scene)
|
|
|
+ var bitmapIndex = 0
|
|
|
+ val permitCount = frameDataList.size
|
|
|
+ val semaphore = Semaphore(permitCount)
|
|
|
+ var completeCount = 0
|
|
|
+ emitter.onNext("$completeCount/${frameDataList.size}")
|
|
|
+
|
|
|
+ var beginTime = System.currentTimeMillis()
|
|
|
+ frameDataList.forEach { frameData ->
|
|
|
+ val i = bitmapIndex++
|
|
|
+ inputSceneStatus[i] = frameData.repeat
|
|
|
+ semaphore.acquire()
|
|
|
+ Completable.create {
|
|
|
+ val bitmap = drawScene(scene, frameData.x, scaleWidth, scaleHeight)
|
|
|
+ movieBuilder.addImage(i, bitmap!!).blockingSubscribe()
|
|
|
+ it.onComplete()
|
|
|
+ }
|
|
|
+ .subscribeOn(Schedulers.computation())
|
|
|
+ .subscribe {
|
|
|
+ completeCount++
|
|
|
+ emitter.onNext("$completeCount/${frameDataList.size}")
|
|
|
+ semaphore.release()
|
|
|
}
|
|
|
- inputSceneStatus[sceneIndex] = sceneRepeatCount
|
|
|
- }
|
|
|
-
|
|
|
+ }
|
|
|
+ semaphore.acquire(permitCount)
|
|
|
+ var endTime = System.currentTimeMillis()
|
|
|
+ Log.d(this@SuperMovieMaker::class.java.simpleName, "draw + save duration = ${endTime - beginTime}")
|
|
|
movieBuilder.inputFilePath = movieBuilder.addInputFile(inputSceneStatus).blockingFirst()
|
|
|
emitter.onNext("Encoding video")
|
|
|
movieBuilder.build().output(outputFile).blockingSubscribe()
|
|
@@ -83,6 +83,35 @@ class SuperMovieMaker {
|
|
|
return audioSources
|
|
|
}
|
|
|
|
|
|
+ fun generateFrameDataList(scene: Scene): List<FrameData> {
|
|
|
+ val frameDataList = ArrayList<FrameData>()
|
|
|
+ scene.record?.apply {
|
|
|
+ var x = 0
|
|
|
+ var trackPosition = -1
|
|
|
+
|
|
|
+ for (t in 0..period step ((1f / FPS) * 1000).toLong()) {
|
|
|
+ for (track in tracks) {
|
|
|
+ if (t >= track.time && tracks.indexOf(track) > trackPosition) {
|
|
|
+ x = track.positionX
|
|
|
+ trackPosition = tracks.indexOf(track)
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (frameDataList.isEmpty()) {
|
|
|
+ frameDataList.add(FrameData(x, 1))
|
|
|
+ } else {
|
|
|
+ val frameData = frameDataList.last()
|
|
|
+ if (frameData.x == x) {
|
|
|
+ frameData.repeat++
|
|
|
+ } else {
|
|
|
+ frameDataList.add(FrameData(x, 1))
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return frameDataList
|
|
|
+ }
|
|
|
+
|
|
|
private fun generateMovieFilms(
|
|
|
scene: Scene,
|
|
|
scaleWidth: Int,
|
|
@@ -140,4 +169,6 @@ class SuperMovieMaker {
|
|
|
}
|
|
|
return sceneBitmap
|
|
|
}
|
|
|
+
|
|
|
+ data class FrameData(var x: Int, var repeat: Int)
|
|
|
}
|