4

I am working with some code that creates a Surface programmatically and uses it to display the camera preview. I am trying to modify it to instead display a video. The changed code (below) plays the video's audio but there is no video--just a black screen.

The camera preview version works fine, so I don't think the issue is with how the SurfaceTexture or Surface are created or displayed.

   int texid = getTexture(); //native method 
   mSurfaceTexture = new SurfaceTexture(texid);
   Log.e(TAG, "texid is "+texid);
   mSurfaceTexture.setOnFrameAvailableListener(new OnFrameAvailableListener() {
       @Override
       public void onFrameAvailable(SurfaceTexture surfaceTexture) {
           Log.d(TAG, "onFrameAvailable");
       }
   });

   final Surface surface = new Surface(mSurfaceTexture);
   mediaPlayer.setSurface(surface);

   String mSourceString = "clips/key_frames_movie_small.mp4";
   AssetManager assetManager = mContext.getResources().getAssets();
   AssetFileDescriptor clipFd = assetManager.openFd(mSourceString);
   mediaPlayer.setDataSource(clipFd.getFileDescriptor(),
           clipFd.getStartOffset(),
           clipFd.getLength());
   clipFd.close();

   mediaPlayer.setOnErrorListener(new MediaPlayer.OnErrorListener() {
       @Override
       public boolean onError(MediaPlayer mp, int what, int extra) {
           Log.e(TAG, "ERROR: "+what + ", " + extra);
           return false;
       }
   });

   mediaPlayer.setOnInfoListener(new MediaPlayer.OnInfoListener() {
       @Override
       public boolean onInfo(MediaPlayer mp, int what, int extra) {
           Log.e(TAG, "INFO: "+what + ", " + extra);
           return false;
       }
   });

   mediaPlayer.setOnVideoSizeChangedListener(new MediaPlayer.OnVideoSizeChangedListener() {
       @Override
       public void onVideoSizeChanged(MediaPlayer mp, int width, int height) {
           Log.e(TAG, "onVideoSizeChanged: "+width + ", " + height);
       }
   });

   mediaPlayer.prepare();
   mediaPlayer.start();

Things I've tried:

  • Using the MediaPlayer to play the same video in a SurfaceView that's in the xml layout. This works fine, so I don't think there's any problem with the video itself.
  • Removing background colors from xml, as suggested here. No effect.
  • Playing a small video (320x240) (screen dimens are 1920x1080) in case resolution was a problem, as described here
  • Used logs to verify that the surface was created before calling mediaPlayer.setSurface(surface) as suggested here.
  • Called surfaceView.setZOrderOnTop(true), surfaceView.setZOrderMediaOverlay(true), surfaceView.setVisibility(View.VISIBLE) to make sure the view isn't partially hidden by anything. No effect.
  • Called holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS) as described here out of desperation, even though I'm running on 6.0.1.

How can I get the video to play in the surface without changing how the surface texture or surface are created?

Edit:

Logs look like this:

E/com.package: texid is 1
D/MediaPlayer: setSubtitleAnchor in MediaPlayer
W/MediaPlayer: info/warning (3, 0)
D/MediaPlayer: setSubtitleAnchor in MediaPlayer
E/com.package: onVideoSizeChanged: 960, 540
E/com.package: onVideoSizeChanged: 960, 540
E/com.package: INFO: 3, 0
D/com.package: onFrameAvailable

According to the docs, the info code 3 indicates that "The player just pushed the very first video frame for rendering."

onFrameAvailable is called only once. If I do surfaceTexture.updateTexImage(); inside the onFrameAvailable() callback, there are (perhaps once a second) additional calls to onFrameAvailable(), but it doesn't affect the display, which stays black.

Community
  • 1
  • 1
Michiyo
  • 1,161
  • 1
  • 14
  • 33

0 Answers0