返回
Featured image of post 设计手机投屏安卓app(4)

设计手机投屏安卓app(4)

Android手机录屏

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);
  //发送数据
}