Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android: MediaPlayer video aspect ratio issue

I am having an issue that I am unable to resolve. I am using MediaPlayer class to play video; however, I am always loosing the original aspect ratio. The media player code and the xml code is mentioned here. I have tried so many things but still not able to resolve the issue. I need to maintain the original aspect ratio. I have declared this activity to be full screen in my Android Manifest File. I have also attached the xml code here after the media player code. Please advise me.

private class ErrorListener implements OnErrorListener {
    // FIXME: @Override
    public boolean onError(MediaPlayer mp, int what, int extra) {
        String message = "Unknown error";
        switch (what) {
        case MediaPlayer.MEDIA_ERROR_UNKNOWN:
            message = "Unable to play media";
            showError(message);
            break;
        case MediaPlayer.MEDIA_ERROR_SERVER_DIED:
            message = "Server failed";
            showError(message);
            break;
        case MediaPlayer.MEDIA_ERROR_NOT_VALID_FOR_PROGRESSIVE_PLAYBACK:
            message = "Invalid media";
            showError(message);
            break;
        }
        return false;
    }
}

public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
    setContentView(R.layout.videoview);
    Intent intent = getIntent();
    uri = intent.getData();
    new loadMovie().execute();
    mPreview = (SurfaceView) findViewById(R.id.videoview);
    mPreview.bringToFront();
    holder = mPreview.getHolder();
    holder.addCallback(this);
    holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
    mediaPlayer = new MediaPlayer();

}// onCreate Method Ends

private void playVideo() {
    doCleanUp();
    try {
        mediaPlayer.setDataSource(this, uri);
    } catch (IllegalArgumentException e) {
        e.printStackTrace();
    } catch (SecurityException e) {
        e.printStackTrace();
    } catch (IllegalStateException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }
    mediaPlayer.setDisplay(holder);
    try {
        mediaPlayer.prepare();
    } catch (IllegalStateException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }
    mediaPlayer.setOnErrorListener(new ErrorListener());
    mediaPlayer.setOnBufferingUpdateListener(this);
    mediaPlayer.setOnCompletionListener(this);
    mediaPlayer.setOnPreparedListener(this);
    mediaPlayer.setOnVideoSizeChangedListener(this);
    mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
    mediaController = new MediaController(this);
}

@Override
public boolean onTouchEvent(MotionEvent event) {
    mediaController.show();
    return false;
}

// --MediaPlayerControl
// methods----------------------------------------------------
public void start() {
    mediaPlayer.start();
}

public void pause() {
    mediaPlayer.pause();
}

public int getDuration() {
    return mediaPlayer.getDuration();
}

public int getCurrentPosition() {
    return mediaPlayer.getCurrentPosition();
}

public void seekTo(int i) {
    mediaPlayer.seekTo(i);
}

public boolean isPlaying() {
    return mediaPlayer.isPlaying();
}

public int getBufferPercentage() {
    return 0;
}

public boolean canPause() {
    return true;
}

public boolean canSeekBackward() {
    return true;
}

public boolean canSeekForward() {
    return true;
}

// End of MediaPlayer
// Controls--------------------------------------------------------
// ------------------------

public void onPrepared(MediaPlayer mediaPlayer) {
    mediaController.setMediaPlayer(this);
    mediaController.setAnchorView(findViewById(R.id.videoview));
    mIsVideoReadyToBePlayed = true;

    if (mIsVideoReadyToBePlayed && mIsVideoSizeKnown) {
        startVideoPlayback();
    }

    handler.post(new Runnable() {
        public void run() {
            mediaController.setEnabled(true);
            mediaController.show();
        }
    });
}

public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3) {
    // TODO Auto-generated method stub

}

public void surfaceCreated(SurfaceHolder holder) {
    // TODO Auto-generated method stub
    playVideo();
}

public void surfaceDestroyed(SurfaceHolder arg0) {

}

private void startVideoPlayback() {
    holder.setFixedSize(mVideoWidth, mVideoHeight);
    mediaPlayer.start();
}

public void onVideoSizeChanged(MediaPlayer mp, int width, int height) {
    if (width == 0 || height == 0) {
        return;
    }
    mIsVideoSizeKnown = true;
    mVideoWidth = width;
    mVideoHeight = height;
    if (mIsVideoReadyToBePlayed && mIsVideoSizeKnown) {
        startVideoPlayback();
    }

}

public void onCompletion(MediaPlayer arg0) {

}

public void onBufferingUpdate(MediaPlayer mp, int percent) {

}

private void releaseMediaPlayer() {
    mediaPlayer.release();
    mediaPlayer = null;
}

private void doCleanUp() {
    mVideoWidth = 0;
    mVideoHeight = 0;
    mIsVideoReadyToBePlayed = false;
    mIsVideoSizeKnown = false;
}

And here is the XML:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:gravity="center"
>
<SurfaceView android:id="@+id/videoview"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    />
 </LinearLayout>

Can anyone please advise me how can I maintain the aspect ratio of the video?

like image 646
Farhan Avatar asked Nov 23 '11 09:11

Farhan


1 Answers

First create a Relative Layout with Gravity.CENTER, and attach your Surface View in it. This will ensure that the video will be centred inside the screen.

Also if you are using an activity, use the 'black' theme to avoid the gradient

In your SurfaceView, create a Listener:

mMediaPlayer = new MediaPlayer();

...

MediaPlayer.OnVideoSizeChangedListener mOnVideoSizeChangedListener = new MediaPlayer.OnVideoSizeChangedListener() {

    @Override
    public void onVideoSizeChanged(MediaPlayer mp, int width, int height) {

         setFitToFillAspectRatio(mp, width, height);

    }
};
mMediaPlayer.setOnVideoSizeChangedListener(mOnVideoSizeChangedListener);

...

Finally the fit to fill method in your SurfaceView. This will works on landscape and portrait

private void setFitToFillAspectRatio(MediaPlayer mp, int videoWidth, int videoHeight)
{
    if(mp != null)
    {       
        Integer screenWidth = ((Activity) mContext).getWindowManager().getDefaultDisplay().getWidth();
        Integer screenHeight = ((Activity) mContext).getWindowManager().getDefaultDisplay().getHeight();
        android.view.ViewGroup.LayoutParams videoParams = getLayoutParams();


        if (videoWidth > videoHeight)
        {
            videoParams.width = screenWidth;
            videoParams.height = screenWidth * videoHeight / videoWidth;
        }
        else
        {
            videoParams.width = screenHeight * videoWidth / videoHeight;
            videoParams.height = screenHeight;
        }


        setLayoutParams(videoParams);
    }
}
like image 151
execomrt Avatar answered Nov 10 '22 08:11

execomrt