关于Android录屏并推流

1.主要流程

  • 录屏(涉及的Android Api: MediaProjectionManager, MediaProjection,VirtualDisplay可以参考:https://blog.csdn.net/ss182172633/article/details/79480853)
  • 编码(通常编为:H264编码,使用api: MediaCodec)
  • 封包(使用的API:MediaMuxer)
  • 发送(rtsp)

2.关于开源项目:ScreenRecorder

  • 在界面中获取所有可配置的信息EncodeConfig(MediaCodec,MediaMuxer都会使用)
  • 主要方法:
    获取MediaProjectionManager实例
mMediaProjectionManager = (MediaProjectionManager) getApplicationContext().getSystemService(MEDIA_PROJECTION_SERVICE);
  • 录屏授权
 Intent captureIntent = mMediaProjectionManager.createScreenCaptureIntent();
 startActivityForResult(captureIntent, REQUEST_MEDIA_PROJECTION);
  • 授权后获取实例
MediaProjection mediaProjection = mMediaProjectionManager.getMediaProjection(resultCode, data);
VirtualDisplay virtualDisplay  = mediaProjection.createVirtualDisplay("ScreenRecorder-display0",
                    config.width, config.height, 1 /*dpi*/,
                    DisplayManager.VIRTUAL_DISPLAY_FLAG_PUBLIC,
                    null /*surface*/, null, null);
mVirtualDisplay.setSurface(mVideoEncoder.getInputSurface());
  • 创建封包器并丢数据进出
mMuxer = new MediaMuxer(mDstPath, MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4);
writeSampleData(mVideoTrackIndex, buffer, encodedData);
  • 通过MediaCodec获取h264数据
MediaFormat format = createMediaFormat();
        Log.d("Encoder", "Create media format: " + format);

        String mimeType = format.getString(MediaFormat.KEY_MIME);
        final MediaCodec encoder = createEncoder(mimeType);
        try {
            if (this.mCallback != null) {
                // NOTE: MediaCodec maybe crash on some devices due to null callback
                encoder.setCallback(mCodecCallback);
            }
            encoder.configure(format, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
            onEncoderConfigured(encoder);
            encoder.start();
        } catch (MediaCodec.CodecException e) {
            Log.e("Encoder", "Configure codec failure!\n  with format" + format, e);
            throw e;
        }
  • MediaCodec 运行状态,编码后的数据通过回掉返回
 /**
     * let media codec run async mode if mCallback != null
     */
    private MediaCodec.Callback mCodecCallback = new MediaCodec.Callback() {
        @Override
        public void onInputBufferAvailable(MediaCodec codec, int index) {
            mCallback.onInputBufferAvailable(BaseEncoder.this, index);
        }

        @Override
        public void onOutputBufferAvailable(MediaCodec codec, int index, MediaCodec.BufferInfo info) {
            mCallback.onOutputBufferAvailable(BaseEncoder.this, index, info);
        }

        @Override
        public void onError(MediaCodec codec, MediaCodec.CodecException e) {
            mCallback.onError(BaseEncoder.this, e);
        }

        @Override
        public void onOutputFormatChanged(MediaCodec codec, MediaFormat format) {
            mCallback.onOutputFormatChanged(BaseEncoder.this, format);
        }
    };

你可能感兴趣的:(关于Android录屏并推流)