diff --git a/app/loopedworld/src/main/java/su/rst10h/loopedworld/HelloSurface.kt b/app/loopedworld/src/main/java/su/rst10h/loopedworld/HelloSurface.kt index b5576a3..5add83e 100644 --- a/app/loopedworld/src/main/java/su/rst10h/loopedworld/HelloSurface.kt +++ b/app/loopedworld/src/main/java/su/rst10h/loopedworld/HelloSurface.kt @@ -200,21 +200,25 @@ class HelloSurface : SurfaceView, SurfaceHolder.Callback { } } fun render() { - persistentSurface?.let { - val pCanvas = it.lockCanvas(null) - clearCanvas(pCanvas) - synchronized(it) { - drawHello(pCanvas, _frameNumber) + persistentSurface?.let {surface -> + val pCanvas = surface.lockCanvas(null) + pCanvas?.let { + clearCanvas(it) + synchronized(surface) { + drawHello(it, _frameNumber) + } + surface.unlockCanvasAndPost(pCanvas) } - it.unlockCanvasAndPost(pCanvas) } } fun preview() { val canvas = holder.lockCanvas() - clearCanvas(canvas) - drawHello(canvas, _frameNumber) - holder.unlockCanvasAndPost(canvas) + canvas?.let { + clearCanvas(it) + drawHello(it, _frameNumber) + holder.unlockCanvasAndPost(it) + } } override fun surfaceChanged(holder: SurfaceHolder, format: Int, width: Int, height: Int) { diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index d9e7b49..dd382af 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -12,10 +12,9 @@ android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/Theme.Inspiry"> - + - diff --git a/app/src/main/java/su/rst10h/inspiry/Constants.kt b/app/src/main/java/su/rst10h/inspiry/Constants.kt new file mode 100644 index 0000000..df6e868 --- /dev/null +++ b/app/src/main/java/su/rst10h/inspiry/Constants.kt @@ -0,0 +1,4 @@ +package su.rst10h.inspiry + +const val MEDIA_FOLDER = "test" +const val MEDIA_FILE_NAME = "TestVideo.mp4" \ No newline at end of file diff --git a/app/src/main/java/su/rst10h/inspiry/data/ActivityState.kt b/app/src/main/java/su/rst10h/inspiry/data/ActivityState.kt index 8c3e936..11c222f 100644 --- a/app/src/main/java/su/rst10h/inspiry/data/ActivityState.kt +++ b/app/src/main/java/su/rst10h/inspiry/data/ActivityState.kt @@ -2,5 +2,7 @@ package su.rst10h.inspiry.data enum class ActivityState { WAIT, - RENDER + RENDERING, + RENDERED, + OPEN_MEDIA } \ No newline at end of file diff --git a/app/src/main/java/su/rst10h/inspiry/repository/CanvasRecorder.kt b/app/src/main/java/su/rst10h/inspiry/repository/CanvasRecorder.kt index 930166f..5e65ec2 100644 --- a/app/src/main/java/su/rst10h/inspiry/repository/CanvasRecorder.kt +++ b/app/src/main/java/su/rst10h/inspiry/repository/CanvasRecorder.kt @@ -7,6 +7,7 @@ import android.view.Surface import su.rst10h.loopedworld.HelloSurface import java.io.File +@Deprecated("Это тоже работает, но кривовато - нет синхронизации фреймов. Лучше использовать VideoEncoder") class CanvasRecorder(private val helloSurface: HelloSurface, appPath: File) { private var recorder: MediaRecorder diff --git a/app/src/main/java/su/rst10h/inspiry/repository/VideoEncoder.kt b/app/src/main/java/su/rst10h/inspiry/repository/VideoEncoder.kt index 368eb8f..fffc124 100644 --- a/app/src/main/java/su/rst10h/inspiry/repository/VideoEncoder.kt +++ b/app/src/main/java/su/rst10h/inspiry/repository/VideoEncoder.kt @@ -8,6 +8,8 @@ import android.util.Log import android.view.Surface import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.launch +import su.rst10h.inspiry.MEDIA_FILE_NAME +import su.rst10h.inspiry.MEDIA_FOLDER import su.rst10h.loopedworld.HelloSurface import java.io.File @@ -15,8 +17,10 @@ class VideoEncoder(private val baseFileDir: File, private val helloSurface: Hell private val bufferInfo = MediaCodec.BufferInfo() private val mediaEncoder: MediaCodec - private val inputSurface: Surface + private lateinit var inputSurface: Surface + var onStopRecord = {} + init { val format = MediaFormat.createVideoFormat(MediaFormat.MIMETYPE_VIDEO_AVC, 1080, 1920) format.setInteger( @@ -31,11 +35,14 @@ class VideoEncoder(private val baseFileDir: File, private val helloSurface: Hell inputSurface = mediaEncoder.createInputSurface() } + private lateinit var mediaMuxer: MediaMuxer private var muxerTrackIndex = -1 @Volatile var isRunning = false fun startRender() { + + muxerTrackIndex = -1 val file = File(prepareFilePath(baseFileDir)) if (!file.exists()) file.delete() mediaMuxer = MediaMuxer(file.absolutePath, MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4) @@ -60,8 +67,7 @@ class VideoEncoder(private val baseFileDir: File, private val helloSurface: Hell while (isRunning) { val encoderStatus = mediaEncoder.dequeueOutputBuffer(bufferInfo, 10000L) when(encoderStatus) { - MediaCodec.INFO_TRY_AGAIN_LATER -> { - } + MediaCodec.INFO_TRY_AGAIN_LATER -> { } MediaCodec.INFO_OUTPUT_FORMAT_CHANGED -> { Log.d("encoder", "start muxer $muxerTrackIndex") val newFormat: MediaFormat = mediaEncoder.outputFormat @@ -83,17 +89,20 @@ class VideoEncoder(private val baseFileDir: File, private val helloSurface: Hell } } } - Log.d("encoder", "File closed") + Log.d("encoder","stop encoding") mediaMuxer.stop() + mediaMuxer.release() + mediaEncoder.stop() + } private fun prepareFilePath(appPath: File): String { - val fullPath = appPath.absolutePath+"/test/" + val fullPath = appPath.absolutePath+"/$MEDIA_FOLDER/" if (!File(fullPath).exists()) { if (!File(fullPath).mkdir()) { Log.d("main", "directory test not created") throw Exception("The test directory does not exist and has not been created:\n$fullPath$\n") } } - return fullPath+"TestVideoEncoder2.mp4" + return fullPath+MEDIA_FILE_NAME } } \ No newline at end of file diff --git a/app/src/main/java/su/rst10h/inspiry/MainActivity.kt b/app/src/main/java/su/rst10h/inspiry/ui/MainActivity.kt similarity index 53% rename from app/src/main/java/su/rst10h/inspiry/MainActivity.kt rename to app/src/main/java/su/rst10h/inspiry/ui/MainActivity.kt index 59d155f..69363ea 100644 --- a/app/src/main/java/su/rst10h/inspiry/MainActivity.kt +++ b/app/src/main/java/su/rst10h/inspiry/ui/MainActivity.kt @@ -1,38 +1,50 @@ -package su.rst10h.inspiry +package su.rst10h.inspiry.ui -import androidx.appcompat.app.AppCompatActivity +import android.content.Intent +import android.net.Uri import android.os.Bundle -import android.util.Log import android.widget.Button import androidx.activity.viewModels +import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatDelegate +import su.rst10h.inspiry.MEDIA_FILE_NAME +import su.rst10h.inspiry.MEDIA_FOLDER +import su.rst10h.inspiry.R import su.rst10h.inspiry.data.ActivityState - import su.rst10h.loopedworld.HelloSurface + class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) + AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO) setContentView(R.layout.activity_main) + val viewModel : MainViewModel by viewModels() val btn = findViewById