Android - Reading VirtualDisplay frames in real time

Viewed 187

I am capturing my Android device's screen using the MediaProjection API by creating a VirtualDisplay and displaying it on a SurfaceView that remains always visible. I would like to perform some image processing on the frames grabbed by the VirtualDisplay then draw them back to the SurfaceView, all in real time. Is there any way to do this with the VirtualDisplay and MediaProjection APIs?

RecordingSession.java

class RecordingSession implements SurfaceHolder.Callback {
  static final int VIRT_DISPLAY_FLAGS=
    DisplayManager.VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY |
      DisplayManager.VIRTUAL_DISPLAY_FLAG_PUBLIC;
  private RecordingConfig config;
  private final Context ctxt;
  private final ToneGenerator beeper;
  private MediaRecorder recorder;
  private MediaProjection projection;
  private VirtualDisplay vdisplay;
  private Window window;
  private Bitmap latestBitmap=null;

  RecordingSession(Context ctxt, RecordingConfig config,
                   MediaProjection projection, Window window) {
    this.ctxt=ctxt.getApplicationContext();
    this.window = window;
    this.config=config;
    this.projection=projection;
    this.beeper=new ToneGenerator(
      AudioManager.STREAM_NOTIFICATION, 100);
  }

  void start() {
    this.window = new Window(this.ctxt);
    this.window.open();
    this.window.getScreenShot().getHolder().addCallback(this);
    vdisplay=projection.createVirtualDisplay("andcorder",
            config.width*4, config.height*4, config.density,
            VIRT_DISPLAY_FLAGS, null, null, null);
    beeper.startTone(ToneGenerator.TONE_PROP_ACK);
  }

  void stop() {
    projection.stop();
    vdisplay.release();
    beeper.startTone(ToneGenerator.TONE_PROP_NACK);
  }

  @Override
  public void surfaceCreated(@NonNull SurfaceHolder surfaceHolder) {

  }

  @Override
  public void surfaceChanged(@NonNull SurfaceHolder surfaceHolder, int i, int i1, int i2) {
    vdisplay.setSurface(surfaceHolder.getSurface());
  }

  @Override
  public void surfaceDestroyed(@NonNull SurfaceHolder surfaceHolder) {

  }

  public void end() {
    this.window.close();
  }
}
0 Answers
Related