美文网首页
auto.pro 借用原有API实时录屏,可供录视频、推流、直播

auto.pro 借用原有API实时录屏,可供录视频、推流、直播

作者: 魔力sama | 来源:发表于2020-01-20 22:11 被阅读0次
    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()
        }
    }
    

    代码未作整理,过年有空了再添加说明。

    相关文章

      网友评论

          本文标题:auto.pro 借用原有API实时录屏,可供录视频、推流、直播

          本文链接:https://www.haomeiwen.com/subject/vmdszctx.html