Feature: add screen recording

pull/209/head
xufuji456 3 years ago
parent e288658223
commit ec75aee0f8
  1. 39
      AndroidMedia/src/main/java/com/frank/androidmedia/controller/MediaProjectionController.kt
  2. 79
      AndroidMedia/src/main/java/com/frank/androidmedia/controller/MediaRecordController.kt

@ -6,6 +6,7 @@ import android.content.Intent
import android.graphics.Bitmap
import android.graphics.PixelFormat
import android.hardware.display.DisplayManager
import android.hardware.display.VirtualDisplay
import android.media.ImageReader
import android.media.projection.MediaProjection
import android.media.projection.MediaProjectionManager
@ -23,16 +24,23 @@ import java.lang.Exception
* @author frank
* @date 2022/3/25
*/
open class MediaProjectionController(screenshot: Boolean) {
open class MediaProjectionController(type: Int) {
private var screenshot = true
private val requestCode = 1234
companion object {
const val TYPE_SCREEN_SHOT = 0
const val TYPE_SCREEN_RECORD = 1
const val TYPE_SCREEN_LIVING = 2
}
private var type = TYPE_SCREEN_SHOT
private val requestCode = 123456
private var virtualDisplay: VirtualDisplay? = null
private var displayMetrics: DisplayMetrics? = null
private var mediaProjection: MediaProjection? = null
private var mediaProjectionManager: MediaProjectionManager? = null
init {
this.screenshot = screenshot
this.type = type
}
fun startScreenRecord(context: Context) {
@ -44,6 +52,13 @@ open class MediaProjectionController(screenshot: Boolean) {
(context as Activity).startActivityForResult(intent, requestCode)
}
fun createVirtualDisplay(surface: Surface) {
virtualDisplay = mediaProjection?.createVirtualDisplay("hello", displayMetrics!!.widthPixels,
displayMetrics!!.heightPixels, displayMetrics!!.densityDpi,
DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR,
surface, null, null)
}
private fun saveBitmap(bitmap: Bitmap?, path: String) {
if (path.isEmpty() || bitmap == null)
return
@ -58,12 +73,6 @@ open class MediaProjectionController(screenshot: Boolean) {
}
}
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)
@ -76,7 +85,8 @@ open class MediaProjectionController(screenshot: Boolean) {
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)
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)
@ -87,14 +97,19 @@ open class MediaProjectionController(screenshot: Boolean) {
fun onActivityResult(resultCode: Int, data: Intent) {
mediaProjection = mediaProjectionManager?.getMediaProjection(resultCode, data)
if (screenshot) {
if (type == TYPE_SCREEN_SHOT) {
getBitmap()
}
}
fun getRequestCode(): Int {
return requestCode
}
fun stopScreenRecord() {
mediaProjection?.stop()
virtualDisplay?.release()
}
}

@ -1,5 +1,7 @@
package com.frank.androidmedia.controller
import android.content.Context
import android.content.Intent
import android.hardware.Camera
import android.media.CamcorderProfile
import android.media.MediaRecorder
@ -16,17 +18,22 @@ open class MediaRecordController {
private val usingProfile = true
private var mCamera: Camera? = null
private var mOutputPath: String? = null
private var mMediaRecorder: MediaRecorder? = null
private var mMediaProjectionController: MediaProjectionController? = null
private fun initMediaRecord(surface: Surface, outputPath: String) {
// open camera
mCamera = Camera.open()
mCamera!!.setDisplayOrientation(90)
mCamera!!.unlock()
private fun initMediaRecord(videoSource: Int, surface: Surface?, outputPath: String) {
if (videoSource == MediaRecorder.VideoSource.CAMERA
|| videoSource == MediaRecorder.VideoSource.DEFAULT) {
// open camera
mCamera = Camera.open()
mCamera!!.setDisplayOrientation(90)
mCamera!!.unlock()
mMediaRecorder?.setCamera(mCamera)
}
// Note: pay attention to calling order
mMediaRecorder?.setCamera(mCamera)
mMediaRecorder?.setVideoSource(videoSource)
mMediaRecorder?.setAudioSource(MediaRecorder.AudioSource.MIC)
mMediaRecorder?.setVideoSource(MediaRecorder.VideoSource.CAMERA)
if (usingProfile) {
// QUALITY_480P QUALITY_720P QUALITY_1080P QUALITY_2160P
val profile = CamcorderProfile.get(CamcorderProfile.QUALITY_720P)
@ -42,34 +49,74 @@ open class MediaRecordController {
mMediaRecorder?.setAudioSamplingRate(48000)
}
mMediaRecorder?.setOutputFile(outputPath)
mMediaRecorder?.setPreviewDisplay(surface)
}
fun startRecord(surface: Surface, outputPath: String) {
if (mMediaRecorder == null) {
mMediaRecorder = MediaRecorder()
if (surface != null && (videoSource == MediaRecorder.VideoSource.CAMERA
|| videoSource == MediaRecorder.VideoSource.DEFAULT)) {
mMediaRecorder?.setPreviewDisplay(surface)
}
}
initMediaRecord(surface, outputPath)
private fun startRecordInternal(videoSource: Int, surface: Surface?, outputPath: String) {
initMediaRecord(videoSource, surface, outputPath)
try {
mMediaRecorder?.prepare()
if (videoSource == MediaRecorder.VideoSource.SURFACE) {
mMediaProjectionController?.createVirtualDisplay(mMediaRecorder?.surface!!)
}
mMediaRecorder?.start()
} catch (e: Exception) {
Log.e("MediaRecorder", "start recorder error=$e")
}
}
/**
* Start record camera or screen
* @param videoSource the source of video, see {@link MediaRecorderVideoSource.CAMERA}
* or {@link MediaRecorder.VideoSource.SURFACE}
* @param surface the Surface to preview, when videoSource = MediaRecorderVideoSource.CAMERA
* @param context the Context of Activity
* @param outputPath the output path to save media file
*/
fun startRecord(videoSource: Int, surface: Surface?, context: Context, outputPath: String) {
if (mMediaRecorder == null) {
mMediaRecorder = MediaRecorder()
}
if (videoSource == MediaRecorder.VideoSource.SURFACE) {
mOutputPath = outputPath
mMediaProjectionController = MediaProjectionController(MediaProjectionController.TYPE_SCREEN_RECORD)
mMediaProjectionController?.startScreenRecord(context)
return
}
startRecordInternal(videoSource, surface, outputPath)
Log.i("MediaRecorder", "startRecord...")
}
/**
* Stop recording camera or screen,
* and release everything.
*/
fun stopRecord() {
if (mMediaRecorder != null) {
mMediaRecorder?.stop()
mMediaRecorder?.reset()
}
mCamera?.stopPreview()
if (mCamera != null) {
mCamera!!.stopPreview()
}
if (mMediaProjectionController != null) {
mMediaProjectionController!!.stopScreenRecord()
}
Log.i("MediaRecorder", "stopRecord...")
}
fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent) {
if (requestCode == mMediaProjectionController?.getRequestCode()) {
mMediaProjectionController?.onActivityResult(resultCode, data)
startRecordInternal(MediaRecorder.VideoSource.SURFACE, mMediaRecorder?.surface, mOutputPath!!)
}
}
fun release() {
if (mMediaRecorder != null) {
mMediaRecorder?.release()

Loading…
Cancel
Save