@@ -2,6 +2,7 @@ package com.dan.timelapse.screens
22
33import android.content.Intent
44import android.media.AudioManager
5+ import android.media.MediaMetadataRetriever
56import android.media.MediaScannerConnection
67import android.net.Uri
78import android.os.Bundle
@@ -22,6 +23,7 @@ import com.dan.timelapse.utils.UriFile
2223import com.dan.timelapse.video.VideoTools
2324import com.dan.timelapse.video.VideoWriter
2425import kotlinx.coroutines.*
26+ import org.opencv.android.Utils
2527import org.opencv.core.Mat
2628import java.io.File
2729import java.io.FileNotFoundException
@@ -78,6 +80,7 @@ class MainFragment(activity: MainActivity) : AppFragment(activity) {
7880 private var firstFrame = Mat ()
7981 private val firstFrameMask = Mat ()
8082 private val alignCache = AlignCache ()
83+ private val alignCacheForPhoto = AlignCache ()
8184 private var outputParams: OutputParams ? = null
8285 private var alignMaskId = 0
8386
@@ -118,12 +121,11 @@ class MainFragment(activity: MainActivity) : AppFragment(activity) {
118121 binding.video.start()
119122 }
120123
121- private fun getCurrentOutputParams (framesInput : FramesInput ): OutputParams {
124+ private fun getCurrentOutputParams (framesInput : FramesInput , fullSize : Boolean ): OutputParams {
122125 val outputParams = OutputParams ()
123126
124127 outputParams.set(OutputParams .KEY_H265 , if (settings.h265) 1 else 0 )
125128 outputParams.set(OutputParams .KEY_CROP , if (settings.crop) 1 else 0 )
126- outputParams.set(OutputParams .KEY_4K , if (settings.encode4K) 1 else 0 )
127129
128130 outputParams.set(OutputParams .KEY_SPEED , binding.seekBarSpeed.progress + 1 )
129131 outputParams.set(OutputParams .KEY_ALIGN , if (binding.switchAlign.isChecked) alignMaskId else - 1 )
@@ -148,7 +150,28 @@ class MainFragment(activity: MainActivity) : AppFragment(activity) {
148150 }
149151 }
150152
151- outputParams.set(OutputParams .KEY_ORIENTATION , orientation)
153+ var width: Int
154+ var height: Int
155+
156+ if (fullSize) {
157+ width = framesInput.width
158+ height = framesInput.height
159+ } else if (settings.encode4K) {
160+ width = 1920 * 2
161+ height = 1080 * 2
162+ } else {
163+ width = 1920
164+ height = 1080
165+ }
166+
167+ if ((orientation == ORIENTATION_LANDSCAPE && width < height) || (orientation == ORIENTATION_PORTRAIT && width > height)) {
168+ val tmp = width
169+ width = height
170+ height = tmp
171+ }
172+
173+ outputParams.set(OutputParams .KEY_WIDTH , width)
174+ outputParams.set(OutputParams .KEY_HEIGHT , height)
152175
153176 return outputParams
154177 }
@@ -170,7 +193,7 @@ class MainFragment(activity: MainActivity) : AppFragment(activity) {
170193
171194 videoStop()
172195
173- val outputParams = getCurrentOutputParams(framesInput)
196+ val outputParams = getCurrentOutputParams(framesInput, false )
174197 val changes = outputParams.compareWith(this .outputParams)
175198
176199 if (! tmpOutputVideo.exists() || OutputParams .COMPARE_NOT_CHANGED != changes) {
@@ -230,6 +253,7 @@ class MainFragment(activity: MainActivity) : AppFragment(activity) {
230253 MaskEditFragment .show(activity, firstFrame, firstFrameMask) {
231254 alignMaskId++
232255 alignCache.reset()
256+ alignCacheForPhoto.reset()
233257 }
234258 }
235259
@@ -416,6 +440,7 @@ class MainFragment(activity: MainActivity) : AppFragment(activity) {
416440 private fun setFramesInput (framesInput : FramesInput ) {
417441 outputParams = null
418442 alignCache.resetAll()
443+ alignCacheForPhoto.resetAll()
419444 this .framesInput = framesInput
420445 binding.seekBarFPS.progress = Settings .getClosestFpsIndex(framesInput.fps)
421446 firstFrame.release()
@@ -441,7 +466,7 @@ class MainFragment(activity: MainActivity) : AppFragment(activity) {
441466 val framesInput = this .framesInput ? : return
442467 videoStop()
443468 runAsync(TITLE_SAVE_PHOTO ) {
444- generateAsync(getCurrentOutputParams(framesInput), true )
469+ generateAsync(getCurrentOutputParams(framesInput, true ), true )
445470 }
446471 }
447472
@@ -492,28 +517,10 @@ class MainFragment(activity: MainActivity) : AppFragment(activity) {
492517 outputParams : OutputParams ,
493518 framesInput : FramesInput ,
494519 finalConsumer : FramesConsumer ,
495- alignCache : AlignCache ,
496- _videoWidth : Int = -1,
497- _videoHeight : Int = -1): Boolean {
498- var videoWidth = _videoWidth
499- var videoHeight = _videoHeight
500-
501- if (videoWidth <= 0 || videoHeight <= 0 ) {
502- videoWidth = 1920
503- videoHeight = 1080
504-
505- if (outputParams.get(OutputParams .KEY_4K ) != 0 ) {
506- videoWidth * = 2
507- videoHeight * = 2
508- }
509-
510- if (ORIENTATION_PORTRAIT == outputParams.get(OutputParams .KEY_ORIENTATION )) {
511- val tmp = videoWidth
512- videoWidth = videoHeight
513- videoHeight = tmp
514- }
515- }
520+ alignCache : AlignCache ): Boolean {
516521
522+ val videoWidth = outputParams.get(OutputParams .KEY_WIDTH )
523+ val videoHeight = outputParams.get(OutputParams .KEY_HEIGHT )
517524 var frameConsumer: FramesConsumer = finalConsumer
518525
519526 if (binding.spinnerEffect.selectedItemPosition > 0 ) {
@@ -607,13 +614,32 @@ class MainFragment(activity: MainActivity) : AppFragment(activity) {
607614
608615 try {
609616 val finalFrameConsumer = ImageWriter (outputFile, settings.jpegQuality)
610- generateAsync(
611- outputParams,
612- framesInput,
613- finalFrameConsumer,
614- AlignCache (),
615- framesInput.width,
616- framesInput.height)
617+
618+ val changes = outputParams.compareWith(this .outputParams)
619+ if (tmpOutputVideo.exists() && (OutputParams .COMPARE_NOT_CHANGED == changes || OutputParams .COMPARE_CHANGED_ONLY_FPS == changes)) {
620+ try {
621+ val mediaMetadataRetriever = MediaMetadataRetriever ()
622+ mediaMetadataRetriever.setDataSource(tmpOutputVideo.absolutePath)
623+ val strFrameCount = mediaMetadataRetriever.extractMetadata(MediaMetadataRetriever .METADATA_KEY_VIDEO_FRAME_COUNT ) ? : throw FileNotFoundException ()
624+ val frameCount = strFrameCount.toIntOrNull() ? : throw FileNotFoundException ()
625+ val bitmap = mediaMetadataRetriever.getFrameAtIndex(frameCount- 1 ) ? : throw FileNotFoundException ()
626+ val frame = Mat ()
627+ Utils .bitmapToMat(bitmap, frame)
628+ finalFrameConsumer.start()
629+ finalFrameConsumer.consume(0 , frame)
630+ finalFrameConsumer.stop(false )
631+ } catch (e: Exception ) {
632+ e.printStackTrace()
633+ }
634+ } else {
635+ generateAsync(
636+ outputParams,
637+ framesInput,
638+ finalFrameConsumer,
639+ alignCacheForPhoto
640+ )
641+ }
642+
617643 success = finalFrameConsumer.success
618644 } catch (e: Exception ) {
619645 e.printStackTrace()
0 commit comments