Feature: add MediaProjectionController

pull/209/head
xufuji456 3 years ago
parent f24bd1f809
commit e288658223
  1. 23
      AndroidMedia/src/main/java/com/frank/androidmedia/controller/MediaMuxController.kt
  2. 100
      AndroidMedia/src/main/java/com/frank/androidmedia/controller/MediaProjectionController.kt
  3. 10
      AndroidMedia/src/main/java/com/frank/androidmedia/controller/MediaRecordController.kt

@ -21,6 +21,7 @@ open class MediaMuxController {
return false
}
var happenError = false
// 1、create MediaMuxer
val mediaMuxer = MediaMuxer(outputPath, MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4)
val mediaExtractor = MediaExtractor()
try {
@ -28,7 +29,11 @@ open class MediaMuxController {
var audioIndex = 0
var audioFormat: MediaFormat? = null
var videoFormat: MediaFormat? = null
var finished = false
val bufferInfo = MediaCodec.BufferInfo()
val inputBuffer = ByteBuffer.allocate(2 * 1024 * 1024)
mediaExtractor.setDataSource(inputPath)
// select track with mimetype
for (i in 0 until mediaExtractor.trackCount) {
val mediaFormat = mediaExtractor.getTrackFormat(i)
val mimeType = mediaFormat.getString(MediaFormat.KEY_MIME)
@ -42,25 +47,24 @@ open class MediaMuxController {
mediaExtractor.selectTrack(i)
}
}
// 2、add MediaFormat into track
if (videoFormat != null) {
mediaMuxer.addTrack(videoFormat)
}
if (audioFormat != null) {
mediaMuxer.addTrack(audioFormat)
}
var finished = false
val bufferInfo = MediaCodec.BufferInfo()
val inputBuffer = ByteBuffer.allocate(2 * 1024 * 1024)
// 3、start the muxer
mediaMuxer.start()
while (!finished) {
// demux media stream
val sampleSize = mediaExtractor.readSampleData(inputBuffer, 0)
if (sampleSize > 0) {
bufferInfo.size = sampleSize
bufferInfo.flags = mediaExtractor.sampleFlags
bufferInfo.presentationTimeUs = mediaExtractor.sampleTime
// 4、call MediaMuxer to mux media stream
if (mediaExtractor.sampleTrackIndex == videoIndex) {
mediaMuxer.writeSampleData(videoIndex, inputBuffer, bufferInfo)
} else if (mediaExtractor.sampleTrackIndex == audioIndex) {
@ -77,12 +81,9 @@ open class MediaMuxController {
Log.e("MediaMuxController", "mux error=$e")
happenError = true
} finally {
try {
mediaMuxer.release()
mediaExtractor.release()
} catch (e1: Exception) {
Log.e("MediaMuxController", "release error=$e1")
}
// 5、release resource
mediaMuxer.release()
mediaExtractor.release()
return !happenError
}
}

@ -0,0 +1,100 @@
package com.frank.androidmedia.controller
import android.app.Activity
import android.content.Context
import android.content.Intent
import android.graphics.Bitmap
import android.graphics.PixelFormat
import android.hardware.display.DisplayManager
import android.media.ImageReader
import android.media.projection.MediaProjection
import android.media.projection.MediaProjectionManager
import android.os.Environment
import android.util.DisplayMetrics
import android.view.Surface
import android.view.WindowManager
import java.io.FileOutputStream
import java.lang.Exception
/**
* Using MediaProjectionManager to screenshot,
* and using MediaProjection recording screen.
*
* @author frank
* @date 2022/3/25
*/
open class MediaProjectionController(screenshot: Boolean) {
private var screenshot = true
private val requestCode = 1234
private var displayMetrics: DisplayMetrics? = null
private var mediaProjection: MediaProjection? = null
private var mediaProjectionManager: MediaProjectionManager? = null
init {
this.screenshot = screenshot
}
fun startScreenRecord(context: Context) {
val windowManager = context.getSystemService(Context.WINDOW_SERVICE) as WindowManager
displayMetrics = DisplayMetrics()
windowManager.defaultDisplay.getMetrics(displayMetrics)
mediaProjectionManager = context.getSystemService(Context.MEDIA_PROJECTION_SERVICE) as MediaProjectionManager
val intent = mediaProjectionManager?.createScreenCaptureIntent()
(context as Activity).startActivityForResult(intent, requestCode)
}
private fun saveBitmap(bitmap: Bitmap?, path: String) {
if (path.isEmpty() || bitmap == null)
return
var outputStream: FileOutputStream? = null
try {
outputStream = FileOutputStream(path)
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, outputStream)
} catch (e: Exception) {
} finally {
outputStream?.close()
}
}
private fun createVirtualDisplay(surface: Surface) {
mediaProjection?.createVirtualDisplay("hello", displayMetrics!!.widthPixels, displayMetrics!!.heightPixels,
displayMetrics!!.densityDpi, DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR,
surface, null, null)
}
private fun getBitmap() {
val imageReader = ImageReader.newInstance(displayMetrics!!.widthPixels,
displayMetrics!!.heightPixels, PixelFormat.RGBA_8888, 3)
createVirtualDisplay(imageReader.surface)
imageReader.setOnImageAvailableListener ({ reader: ImageReader ->
val image = reader.acquireNextImage()
val planes = image.planes
val buffer = planes[0].buffer
val pixelStride = planes[0].pixelStride
val rowStride = planes[0].rowStride
val rowPadding = rowStride - pixelStride * image.width
val bitmap = Bitmap.createBitmap(image.width + rowPadding / pixelStride, image.height, Bitmap.Config.ARGB_8888)
bitmap.copyPixelsFromBuffer(buffer)
val filePath = Environment.getExternalStorageDirectory().path + "/hello.jpg"
saveBitmap(bitmap, filePath)
image.close()
imageReader.close()
}, null)
}
fun onActivityResult(resultCode: Int, data: Intent) {
mediaProjection = mediaProjectionManager?.getMediaProjection(resultCode, data)
if (screenshot) {
getBitmap()
}
}
fun stopScreenRecord() {
mediaProjection?.stop()
}
}

@ -35,11 +35,11 @@ open class MediaRecordController {
mMediaRecorder?.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4)
mMediaRecorder?.setAudioEncoder(MediaRecorder.AudioEncoder.AAC)
mMediaRecorder?.setVideoEncoder(MediaRecorder.VideoEncoder.H264)
// mMediaRecorder?.setVideoSize(640, 480)
// mMediaRecorder?.setVideoEncodingBitRate(5000 * 1000)
// mMediaRecorder?.setVideoFrameRate(25)
// mMediaRecorder?.setAudioChannels(2)
// mMediaRecorder?.setAudioSamplingRate(48000)
mMediaRecorder?.setVideoSize(640, 480)
mMediaRecorder?.setVideoEncodingBitRate(5000 * 1000)
mMediaRecorder?.setVideoFrameRate(25)
mMediaRecorder?.setAudioChannels(2)
mMediaRecorder?.setAudioSamplingRate(48000)
}
mMediaRecorder?.setOutputFile(outputPath)
mMediaRecorder?.setPreviewDisplay(surface)

Loading…
Cancel
Save