Help with displaying video

Hello all,

Currently working on porting my windows app to Android. The Windows app has a startup animation in the form of a video. I tried to use the built in video library of Processing, but that just crashes the app and yields this in the console:

FATAL EXCEPTION: Animation Thread
Process: com.TechMasterIndustries.TechmasterQueueManager, PID: 4912
java.lang.ExceptionInInitializerError
	at processing.video.Video.init(Unknown Source:0)
	at processing.video.Movie.initGStreamer(Unknown Source:6)
	at processing.video.Movie.<init>(Unknown Source:28)
	at com.TechMasterIndustries.TechmasterQueueManager.TechMasterQueueManagerAndroidBeta.setup(TechMasterQueueManagerAndroidBeta.java:89)
	at processing.core.PApplet.handleDraw(PApplet.java:1835)
	at processing.core.PSurfaceNone.callDraw(PSurfaceNone.java:476)
	at processing.core.PSurfaceNone$AnimationThread.run(PSurfaceNone.java:516)
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'int java.lang.String.indexOf(int)' on a null object reference
	at processing.core.PApplet.parseInt(PApplet.java:6791)
	at processing.core.PApplet.parseInt(PApplet.java:6782)
	at processing.video.Video.<clinit>(Unknown Source:29)
	... 7 more

I then did some digging and found this Library which claims to be a video mode for android. This also crashes the app and yields this in the console:

FATAL EXCEPTION: Animation Thread
Process: com.TechMasterIndustries.TechmasterQueueManager, PID: 2504
java.lang.NoSuchMethodError: No virtual method getSurfaceView()Landroid/view/SurfaceView; in class Lprocessing/core/PApplet; or its super classes (declaration of 'processing.core.PApplet' appears in /data/app/com.TechMasterIndustries.TechmasterQueueManager-KQpbRXVpXCnyeeuQo0LY8g==/base.apk)
	at in.omerjerk.processing.video.android.VideoBase.<init>(Unknown Source:48)
	at in.omerjerk.processing.video.android.Movie.<init>(Unknown Source:1)
	at com.TechMasterIndustries.TechmasterQueueManager.TechMasterQueueManagerAndroidBeta.setup(TechMasterQueueManagerAndroidBeta.java:93)
	at processing.core.PApplet.handleDraw(PApplet.java:1835)
	at processing.core.PSurfaceNone.callDraw(PSurfaceNone.java:476)
	at processing.core.PSurfaceNone$AnimationThread.run(PSurfaceNone.java:516)


Not sure what I’m doing wrong, but here’s my code: My Code

Anyone know how to fix this/what I’m doing wrong?

Thanks in advance

Hi @TechMaster04
Have you tried this one?

No, not yet. I’ll give it a try now

Unfortunately, it still crashes. I get this error in the console:

FATAL EXCEPTION: Animation Thread
Process: processing.test.gettingstartedmovie, PID: 2084
java.lang.NoSuchMethodError: No virtual method getSurfaceView()Landroid/view/SurfaceView; in class Lprocessing/core/PApplet; or its super classes (declaration of 'processing.core.PApplet' appears in /data/app/processing.test.gettingstartedmovie-xiS_47YJhoSqxEq49WQytw==/base.apk)
	at in.omerjerk.processing.video.android.VideoBase.<init>(Unknown Source:48)
	at in.omerjerk.processing.video.android.Movie.<init>(Unknown Source:1)
	at processing.test.gettingstartedmovie.GettingStartedMovie.setup(GettingStartedMovie.java:31)
	at processing.core.PApplet.handleDraw(PApplet.java:1835)
	at processing.core.PSurfaceNone.callDraw(PSurfaceNone.java:476)
	at processing.core.PSurfaceNone$AnimationThread.run(PSurfaceNone.java:516)

Have you seen this topic?

I have, but it confused me quite a bit. I’ll take another look and see if I can get it to work

UPDATE: Turns out that the topic wasn’t going to achieve the end result I desire. I’m gonna do some more research with broader terms and see if that helps, because at this point I am extremely stumped

@TechMaster04 ===

  • Could be better to put the relevant code here
  • Processing video lib does not work with android
  • Anyway why not using the Mediaplayer class from android?- I have already posted code for that on this forum or previous one, i dont know

@akenaton
Code below is running quite well, but when I set the surface xy values, the movie(placed in data folder) disappears as if it were below the actually sketch layout frame.
Any idea?
(Using APDE app mode)

import android.media.MediaMetadataRetriever;
import android.os.Looper;
import android.app.Activity;
import android.view.ViewGroup;
import android.view.View;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.media.MediaMetadataRetriever;
import android.media.MediaPlayer;
import android.content.res.Resources;
import android.content.res.AssetFileDescriptor;
import android.content.res.AssetManager;
import android.content.Context;

AssetFileDescriptor afd;
Context context;
Activity act;
SurfaceView mySurface;
SurfaceHolder mSurfaceHolder;
MediaMetadataRetriever metaRetriever;
MediaPlayer mp;

void setup() {
  size(400, 400, P2D);
  act = this.getActivity();
  context = act.getApplicationContext();
  Looper.prepare();
  mp = new MediaPlayer();
  try {
    afd = context.getAssets().openFd("m.mp4");
    MediaMetadataRetriever metaRetriever = new MediaMetadataRetriever();
    metaRetriever.setDataSource(afd.getFileDescriptor(), afd.getStartOffset(), afd.getLength());
    String height = metaRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_HEIGHT);
  }
    catch (IOException e) {
    e.printStackTrace();
  }
    mySurface = new SurfaceView(act);
    mSurfaceHolder = mySurface.getHolder();
    mSurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
    mSurfaceHolder.addCallback(new SurfaceHolder.Callback() {
    @Override
      public void surfaceCreated(SurfaceHolder surfaceHolder) {
      mp.setDisplay(surfaceHolder);
    }
    @Override
      public void surfaceChanged(SurfaceHolder surfaceHolder, int i, int i2, int i3) {
      mp.setDisplay(surfaceHolder);
    }
    @Override
      public void surfaceDestroyed(SurfaceHolder surfaceHolder) {
    }
  }
  );
    startVideo();
}

void startVideo() {
  act.runOnUiThread(new Runnable() {
    public void run() {
      try {
        mp.setDataSource(afd.getFileDescriptor(), afd.getStartOffset(), afd.getLength());
        mSurfaceHolder = mySurface.getHolder();
        mSurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
        mp.prepare();
        act.addContentView(mySurface, new ViewGroup.LayoutParams(400, 400));
        mySurface.setX(width/2);
        mySurface.setY(height/2);
        if (mp.isPlaying() == false) {
          mp.start();
        }
      }
      catch (IOException e) {
        e.printStackTrace();
      }
    }
  }
    );
}

void draw() {
}

void onStop() {
    if (mp!=null) {
        mp.release();
        mp = null;
  }
    super.onStop() ;
}

@noel ===
yes, your video is behind the surfaceView (normally if it has sound you can hear it) you have created and that is exactly what your code is doing; onStart you have to create a VideoView and that is the view you add to the surface; dont forget also to set the zOrder “on top” param to true. If needed i can put code for that but i am quite sure that you can find by yourself!

@noel ===
excuse me; i have not taken time enough to look to your code in details; the zOrder param is not only the culprit in your code, there is another error / your player: you have to setDataSource and prepare() BEFORE starting the runnable. With some modifs i can get your code running successfully (and there is no need for a videoView which is only a sublclass for the player itself) - If you want i can put the code (i think it will run the same with APDE)_

@akenaton
I’ve attached the surface View to a FrameLayout like I normally do The sketch runs well with video and sound. But still behind my sketch window. How can I set this order.

import android.media.MediaMetadataRetriever;
import android.os.Looper;
import android.app.Activity;
import android.view.ViewGroup;
import android.view.View;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.media.MediaMetadataRetriever;
import android.media.MediaPlayer;
import android.content.res.Resources;
import android.content.res.AssetFileDescriptor;
import android.content.res.AssetManager;
import android.content.Context;
import android.widget.FrameLayout;
import android.R;
import android.content.*; 
import android.view.Gravity;
import android.view.ViewGroup.LayoutParams;

AssetFileDescriptor afd;
Context context;
Activity act;
SurfaceView mySurface;
SurfaceHolder mSurfaceHolder;
MediaMetadataRetriever metaRetriever;
MediaPlayer mp;
FrameLayout fl;

void setup() {
  size(10, 10);
  Looper.prepare();
  try {
    afd = context.getAssets().openFd("m.mp4");
    MediaMetadataRetriever metaRetriever = new MediaMetadataRetriever();
    metaRetriever.setDataSource(afd.getFileDescriptor(), afd.getStartOffset(), afd.getLength());
    String height = metaRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_HEIGHT);
  }
    catch (IOException e) {
    e.printStackTrace();
  }
  mp = new MediaPlayer();
  try {
    mp.setDataSource(afd.getFileDescriptor(), afd.getStartOffset(), afd.getLength());   
    mp.prepare();
  }
  catch (IOException e) {
    e.printStackTrace();
  }
  startVideo();
}

void startVideo() {
  act.runOnUiThread(new Runnable() {
    public void run() {

      if (mp.isPlaying() == false) {
        mp.start();
      }
    }
  }
  );
}

void draw() {
}

void onStop() {
    if (mp!=null) {
        mp.release();
        mp = null;
  }
    super.onStop() ;
}

@Override 
  public void onStart() {
  act = this.getActivity();
  context = act.getApplicationContext();
  mySurface = new SurfaceView(act);
  mSurfaceHolder = mySurface.getHolder();
  mSurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
  mSurfaceHolder.addCallback(new SurfaceHolder.Callback() {
    @Override
      public void surfaceCreated(SurfaceHolder surfaceHolder) {
      mp.setDisplay(surfaceHolder);
    }
    @Override
      public void surfaceChanged(SurfaceHolder surfaceHolder, int i, int i2, int i3) {
      mp.setDisplay(surfaceHolder);
    }
    @Override
      public void surfaceDestroyed(SurfaceHolder surfaceHolder) {
    }
  }
  );
  mySurface.bringToFront();
  //mySurface.setX(100);
  //mySurface.setY(100);
  fl = (FrameLayout)act.findViewById(R.id.content);
  FrameLayout.LayoutParams params1 = new FrameLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT, Gravity.CENTER);
  fl.addView(mySurface);
}

@noel ===
working code (from the first one you posted ) but i have also the version getting the frameLayout::


import android.media.MediaMetadataRetriever;
import android.os.Looper;
import android.app.Activity;
import android.view.ViewGroup;
import android.view.View;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.media.MediaMetadataRetriever;
import android.media.MediaPlayer;
import android.content.res.Resources;
import android.content.res.AssetFileDescriptor;
import android.content.res.AssetManager;
import android.content.Context;

AssetFileDescriptor afd;
Context context;
Activity act;
SurfaceView mySurface;
SurfaceHolder mSurfaceHolder;
MediaMetadataRetriever metaRetriever;
MediaPlayer mp;
int videoH = 0;
int videoL= 0;

void settings(){
  size(displayWidth, displayHeight);
}

void setup() {
  //size(400, 400, P2D);
  background(0);
  act = this.getActivity();
  context = act.getApplicationContext();
  Looper.prepare();
  mp = new MediaPlayer();
  try {
    afd = context.getAssets().openFd("who.mp4");
    MediaMetadataRetriever metaRetriever = new MediaMetadataRetriever();
    metaRetriever.setDataSource(afd.getFileDescriptor(), afd.getStartOffset(), afd.getLength());
    String h = metaRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_HEIGHT);
    String w = metaRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_WIDTH);
    videoL= int(w);
      videoH=int(h);
  mp.setDataSource(afd.getFileDescriptor(), afd.getStartOffset(), afd.getLength());
  mp.prepare();

}
    catch (IOException e) {
    e.printStackTrace();
  }
    mySurface = new SurfaceView(act);
    mSurfaceHolder = mySurface.getHolder();
    mSurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
    mSurfaceHolder.addCallback(new SurfaceHolder.Callback() {
    @Override
      public void surfaceCreated(SurfaceHolder surfaceHolder) {
      mp.setDisplay(surfaceHolder);
      println("surface créeé");
    }
    @Override
      public void surfaceChanged(SurfaceHolder surfaceHolder, int i, int i2, int i3) {
      mp.setDisplay(surfaceHolder);
      println("surface changée");
    }
    @Override
      public void surfaceDestroyed(SurfaceHolder surfaceHolder) {
        println("surface détruite");
    }
  }
  );
    startVideo();
}

void startVideo() {
  act.runOnUiThread(new Runnable() {
    public void run() {
      //try {
        println("jexecute le runnable");
        //mp.setDataSource(afd.getFileDescriptor(), afd.getStartOffset(), afd.getLength());
        mSurfaceHolder = mySurface.getHolder();
        mSurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
        
        //mp.prepare();
        act.addContentView(mySurface, new ViewGroup.LayoutParams(videoL, videoH));
        mySurface.bringToFront();
      mySurface.setZOrderOnTop(true);
        mySurface.setX(displayWidth/2-videoL/2);
        mySurface.setY((displayHeight/2)-videoH/2);
        if (mp.isPlaying() == false) {
          mp.start();
        }
      //}
      //catch (IOException e) {
        //e.printStackTrace();
      //}
    }
  }
    );
}

void draw() {
}

void onStop() {
    if (mp!=null) {
        mp.release();
        mp = null;
  }
    super.onStop() ;
}
1 Like

@akenaton
Thank you very much.
I understood the setDataSource and prepare() tip.
But the mySurface.setZOrderOnTop(true); really did the trick.
Great!

@noel ===
yes; i have told you that in the previous post… Note that this solution is one (as often) among others (videoView…textureView) but that is not really important!