关于Android录屏并推流
2020-03-27 本文已影响0人
浅吟且行的时光
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);
}
};