androidvideo-processinginteractiveonscrollmediametadataretriever

Faster gesture feedback for onScroll


I have a video file and would like to let the user play it back and forth with swipe right and left gestures. The user experience should be smooth in the sense that if the video file contains a static scene from left to right the user should have the impression he scrolls left and right on a picture (a part from ligthning changes). This is the code I am currently having.

private GestureDetectorCompat mDetector;
private long lengthTourMs;
private long currentPositionMs;
private FFmpegMediaMetadataRetriever mmr;
ImageView video;

@Override
protected void onCreate(Bundle savedInstanceState) {

    video = (ImageView)findViewById(R.id.video_frame);

    mDetector = new GestureDetectorCompat(this, new SwipeGestureListener());

    mmr = new FFmpegMediaMetadataRetriever();
    mmr.setDataSource(this, Uri.parse("path/to/video/file"));
    lengthTourMs = Long.parseLong(mmr.extractMetadata(FFmpegMediaMetadataRetriever.METADATA_KEY_DURATION));
    currentPositionMs = 2000;
    Bitmap frame = mmr.getFrameAtTime(currentPositionMs * 1000, FFmpegMediaMetadataRetriever.OPTION_CLOSEST);
    video.setImageBitmap(frame); 
}


class SwipeGestureListener extends GestureDetector.SimpleOnGestureListener {
  private static final String TAG = "Gestures";

  @Override
  public boolean onScroll(MotionEvent event1, MotionEvent event2,
      float distanceX, float distanceY) {
    Log.d(TAG, "onScroll: " + String.valueOf(distanceX));

    currentPositionMs += (long)distanceX;
    currentPositionMs += lengthTourMs;
    currentPositionMs %= lengthTourMs;
    Bitmap frame = mmr.getFrameAtTime(currentPositionMs * 1000, FFmpegMediaMetadataRetriever.OPTION_CLOSEST);
    Log.d(TAG, "currentPositionMs: " + String.valueOf(currentPositionMs));
      video.setImageBitmap(frame);
    return true;
  }
}

The problem is that a normal swipe right/left gesture gives around two to three calls to onScroll and the result of the above code is therefore just two to three frames that the user sees and not all a smooth video-like experience.

Is there a way to more/faster feedback for a gesture like onScroll? I am also open to other suggestions for solving the problem.


Solution

  • I solved the issue with an OnTouchListener for the ImageView.

    private int x,y;
    private long lengthTourMs;
    private long currentPositionMs;
    private FFmpegMediaMetadataRetriever mmr;
    ImageView video = (ImageView)findViewById(R.id.video_frame);
    
    video.setOnTouchListener( new View.OnTouchListener() {
      @Override
      public boolean onTouch(View v, MotionEvent event) {
        int xx,changeX;
        switch (event.getAction()) {
          case MotionEvent.ACTION_DOWN:
            x = (int) event.getX();
            break;
          case MotionEvent.ACTION_MOVE:
            xx = (int) event.getX();
            changeX = x - xx;
            currentPositionMs += changeX;
            currentPositionMs += lengthTourMs;
            currentPositionMs %= lengthTourMs;
            video.setImageBitmap(mmr.getFrameAtTime(currentPositionMs * 1000, FFmpegMediaMetadataRetriever.OPTION_CLOSEST));
            x = xx;
            break;
          default:
            break;
        }
        return true;
      }
    });
    

    I am actually no longer using the FFmpegeMediaMetadataRetriever as it is to slow for realtime seeking, but that is another issue.