log('hello, world')
if(!requestScreenCapture(device.width, device.height)){
toast("请求截图失败");
exit();
}
importClass(java.io.IOException)
importClass(java.nio.ByteBuffer)
importClass(java.util.concurrent.atomic.AtomicBoolean)
importClass(android.hardware.display.DisplayManager)
importClass(android.hardware.display.VirtualDisplay)
importClass(android.media.MediaCodec)
importClass(android.media.MediaCodecInfo)
importClass(android.media.MediaFormat)
importClass(android.media.MediaMuxer)
importClass(android.app.Activity)
importClass(java.io.File)
let mVideoEncodedFrameCount = 0
// 输出路径
const mDstPath = '/sdcard/mux.mp4'
// H.264
const MIME_TYPE = 'video/avc'
// FPS
const FRAME_RATE = 60
// I-frames
const I_FRAME_INTERVAL = 1
let mMuxing = false
let mOutputVideoTrack
let mMuxerStarted = false
let mVideoTrackIndex = -1
let mBufferInfo = new MediaCodec.BufferInfo()
let javaImages = runtime.getImages()
let mScreenCapturer = javaImages.mScreenCapturer
let mMediaProjection = mScreenCapturer.mMediaProjection
let mMuxer = new MediaMuxer(mDstPath, MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4)
let codec = MediaCodec.createEncoderByType(MIME_TYPE)
const width = 1280
const height = 720
// let mOutputFormat = createOutputFormat()
// let mOutputFormat = MediaFormat.createVideoFormat(MIME_TYPE, device.width, device.height)
let mOutputFormat = MediaFormat.createVideoFormat(MIME_TYPE, width, height)
mOutputFormat.setInteger(MediaFormat.KEY_COLOR_FORMAT, MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface);
mOutputFormat.setInteger(MediaFormat.KEY_BIT_RATE, 4 * 100 * 10000);
mOutputFormat.setInteger(MediaFormat.KEY_FRAME_RATE, FRAME_RATE);
mOutputFormat.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, I_FRAME_INTERVAL);
log("created video output format: ", mOutputFormat)
let done = false
codec.setCallback(new JavaAdapter(MediaCodec.Callback, {
onInputBufferAvailable(codec, inputBufferId) {
log('codec inputBuffer available')
},
onOutputBufferAvailable(codec, index, info) {
muxVideo(index, info)
},
onOutputFormatChanged(mc, format) {
// Subsequent data will conform to new format.
// Can ignore if using getOutputFormat(outputBufferId)
mOutputFormat = format // option B
setupMuxer()
},
onError(err) {
log('error', err)
}
}))
codec.configure(mOutputFormat, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE)
let mSurface = codec.createInputSurface()
// mOutputFormat = codec.getOutputFormat()
codec.start()
let mVirtualDisplay = mMediaProjection.createVirtualDisplay(
"mux-display",
width,
height,
1,
// DisplayManager.VIRTUAL_DISPLAY_FLAG_PUBLIC,
DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR,
mSurface,
null,
null
)
log('display info', mVirtualDisplay.getDisplay())
setTimeout(() => {
done = true
release()
}, 10000);
function createOutputFormat (MIME_TYPE = 'video/avc', mWidth = 1920, mHeight = 1080, mBitRate = 1920 * 1080 * 5) {
const format = MediaFormat.createVideoFormat(MIME_TYPE, mWidth, mHeight)
format.setInteger(MediaFormat.KEY_COLOR_FORMAT, MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface);
format.setInteger(MediaFormat.KEY_BIT_RATE, mBitRate);
format.setInteger(MediaFormat.KEY_FRAME_RATE, FRAME_RATE);
format.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, I_FRAME_INTERVAL);
log("created video format: ", format)
return format
}
function setupMuxer () {
if (mMuxing) {
throw 'muxer: already add track.'
}
mOutputVideoTrack = mMuxer.addTrack(mOutputFormat)
log('muxer: format change to', mOutputFormat)
mMuxer.start()
log('muxer: start')
mMuxing = true
}
function muxVideo (index, info) {
if (!mMuxing) {
return
}
let encoderOutputBuffer = codec.getOutputBuffer(index)
if ((info.flags & MediaCodec.BUFFER_FLAG_CODEC_CONFIG) != 0) {
codec.releaseOutputBuffer(index, false)
return
}
if (info.size != 0) {
mMuxer.writeSampleData(mOutputVideoTrack, encoderOutputBuffer, info)
}
codec.releaseOutputBuffer(index, false);
mVideoEncodedFrameCount++;
if ((info.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) {
done = true
}
}
function release () {
log('release')
if (mVirtualDisplay) {
mVirtualDisplay.setSurface(null)
mVirtualDisplay.release()
mVirtualDisplay = null
}
if (codec) {
codec.stop()
codec.release()
codec = null
}
if (mSurface) {
mSurface.release()
mSurface = null
}
if (mMuxer) {
mMuxer.stop()
mMuxer.release()
mMuxer = null
}
if (mMediaProjection) {
mMediaProjection.stop()
}
}
代码未作整理,过年有空了再添加说明。
网友评论