MediaCodec, MediaCodec class can be used to access low-level media codecs, i.e. encoder/decoder components. It is part of the Android low-level multimedia support infrastructure (normally used together with MediaExtractor, MediaSync, MediaMuxer, MediaCrypto, MediaDrm, Image, Surface, and AudioTrack.)
投屏需要录屏并编码,不用保存视频文件到磁盘,MediaCodec非常合适作为我们的数据中转站,通过配置h264 encoder,一方面它从Surface中得到yuv raw数据并编码,一方面我们获取h264的视频编码流向下送到传输层就可以了。
申请MediaProjection并创建VirtualDisplay
MediaProjectionManager x = (MediaProjectionManager)getSystemService(MEDIA_PROJECTION_SERVICE);
int mResultCode = intent.getIntExtra("code", -1);
Intent mResultData = intent.getParcelableExtra("data");
//mResultData = intent.getSelector();
MediaProjection mediaProjection=x.getMediaProjection(mResultCode, Objects.requireNonNull(mResultData));
public VirtualDisplay createVirtuaDisplay(){
DisplayMetrics metric = new DisplayMetrics();
WindowManager wm = (WindowManager) RenderApplication.getInstance().getSystemService(Context.WINDOW_SERVICE);
wm.getDefaultDisplay().getRealMetrics(metric);
return mediaProjection.createVirtualDisplay(recorderService.START_RENDER_ENGINE, metric.widthPixels, metric.heightPixels, metric.densityDpi,
DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR, null, null, null);
}
创建MediaCodec
MediaCodec codec = MediaCodec.createEncoderByType(MediaFormat.MIMETYPE_VIDEO_AVC);
关联VirtualDisplay和MediaCodec
Surface surface = codec.createInputSurface();
VirtualDisplay display = createDisplay();
display.setSurface(surface);
从MediaCodec获取视频流送到传输层
MediaCodec.BufferInfo bufferInfo = new MediaCodec.BufferInfo();
int outputBufferId = codec.dequeueOutputBuffer(bufferInfo, -1);
if (outputBufferId >= 0) {
ByteBuffer codecBuffer = codec.getOutputBuffer(outputBufferId);
//发送数据
}