open media state added
This commit is contained in:
@@ -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) {
|
||||
|
||||
@@ -12,10 +12,9 @@
|
||||
android:roundIcon="@mipmap/ic_launcher_round"
|
||||
android:supportsRtl="true"
|
||||
android:theme="@style/Theme.Inspiry">
|
||||
<activity android:name=".MainActivity">
|
||||
<activity android:name=".ui.MainActivity">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
4
app/src/main/java/su/rst10h/inspiry/Constants.kt
Normal file
4
app/src/main/java/su/rst10h/inspiry/Constants.kt
Normal file
@@ -0,0 +1,4 @@
|
||||
package su.rst10h.inspiry
|
||||
|
||||
const val MEDIA_FOLDER = "test"
|
||||
const val MEDIA_FILE_NAME = "TestVideo.mp4"
|
||||
@@ -2,5 +2,7 @@ package su.rst10h.inspiry.data
|
||||
|
||||
enum class ActivityState {
|
||||
WAIT,
|
||||
RENDER
|
||||
RENDERING,
|
||||
RENDERED,
|
||||
OPEN_MEDIA
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -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<Button>(R.id.button)
|
||||
val surfaceView = findViewById<HelloSurface>(R.id.testView)
|
||||
|
||||
viewModel.state.observe(this,{
|
||||
when(it) {
|
||||
viewModel.state.observe(this, { state ->
|
||||
when (state) {
|
||||
ActivityState.WAIT -> {
|
||||
Log.d("main", "record stopped")
|
||||
btn.text = "Render Template"
|
||||
btn.isEnabled = true
|
||||
}
|
||||
ActivityState.RENDER -> {
|
||||
Log.d("main", "record started")
|
||||
btn.text = "Rendering.."
|
||||
ActivityState.RENDERING -> {
|
||||
btn.text = "RENDERING.."
|
||||
btn.isEnabled = false
|
||||
}
|
||||
ActivityState.RENDERED -> {
|
||||
btn.isEnabled = true
|
||||
btn.text = "OPEN MEDIA"
|
||||
}
|
||||
ActivityState.OPEN_MEDIA -> {
|
||||
openMedia()
|
||||
viewModel.reset_state()
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
@@ -41,7 +53,15 @@ class MainActivity : AppCompatActivity() {
|
||||
}
|
||||
|
||||
btn.setOnClickListener {
|
||||
viewModel.renderTemplate()
|
||||
viewModel.action()
|
||||
}
|
||||
}
|
||||
private fun openMedia() {
|
||||
val intent = Intent(Intent.ACTION_VIEW)
|
||||
intent.setDataAndType(Uri.parse(
|
||||
getExternalFilesDir(null)?.absolutePath+
|
||||
"/$MEDIA_FOLDER/$MEDIA_FILE_NAME"),
|
||||
"video/mp4")
|
||||
startActivity(intent)
|
||||
}
|
||||
}
|
||||
@@ -1,11 +1,9 @@
|
||||
package su.rst10h.inspiry
|
||||
package su.rst10h.inspiry.ui
|
||||
|
||||
import android.graphics.Canvas
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import androidx.lifecycle.ViewModel
|
||||
import su.rst10h.inspiry.data.*
|
||||
import su.rst10h.inspiry.data.ActivityState.*
|
||||
import su.rst10h.inspiry.repository.CanvasRecorder
|
||||
import su.rst10h.inspiry.repository.VideoEncoder
|
||||
import su.rst10h.loopedworld.HelloSurface
|
||||
import java.io.File
|
||||
@@ -23,18 +21,24 @@ class MainViewModel: ViewModel() {
|
||||
videoEncoder = VideoEncoder(appPath, surface)
|
||||
}
|
||||
|
||||
fun renderTemplate() {
|
||||
fun reset_state() {
|
||||
state.postValue(WAIT)
|
||||
}
|
||||
|
||||
fun action() {
|
||||
when (state.value) {
|
||||
WAIT -> {
|
||||
videoEncoder.onStopRecord = {
|
||||
state.postValue(WAIT)
|
||||
state.postValue(RENDERED)
|
||||
}
|
||||
videoEncoder.startRender()
|
||||
state.postValue(RENDER)
|
||||
state.postValue(RENDERING)
|
||||
}
|
||||
RENDER -> {
|
||||
state.postValue(WAIT)
|
||||
RENDERED -> {
|
||||
state.postValue(OPEN_MEDIA)
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:context=".MainActivity">
|
||||
tools:context=".ui.MainActivity">
|
||||
|
||||
<su.rst10h.loopedworld.HelloSurface
|
||||
android:id="@+id/testView"
|
||||
|
||||
Reference in New Issue
Block a user