问题描述
我正在尝试使用SurfaceView
从Android播放视频.
I'm trying to play a video from Android using a SurfaceView
.
我可以加载视频,声音可以正确播放,但是看不到视频.
I can load the video, the sound is played correctly but I can't see the video.
这是我的活动:
public class VideoTest extends Activity implements OnBufferingUpdateListener, OnCompletionListener, OnPreparedListener, OnVideoSizeChangedListener, SurfaceHolder.Callback, OnErrorListener {
private static final String TAG = "MediaPlayerDemo";
private int mVideoWidth;
private int mVideoHeight;
private MediaPlayer mMediaPlayer;
private SurfaceView mPreview;
private SurfaceHolder holder;
private String path;
private Bundle extras;
public static final String MEDIA = "media";
private static final int LOCAL_AUDIO = 1;
public static final int STREAM_AUDIO = 2;
private static final int RESOURCES_AUDIO = 3;
private static final int LOCAL_VIDEO = 4;
public static final int STREAM_VIDEO = 5;
private boolean mIsVideoSizeKnown = false;
private boolean mIsVideoReadyToBePlayed = false;
private RelativeLayout layout;
/**
*
* Called when the activity is first created.
*/
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
mPreview = new SurfaceView(this);
holder = mPreview.getHolder();
holder.addCallback(this);
holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
extras = getIntent().getExtras();
mPreview.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT));
layout = new RelativeLayout(this);
layout.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT, ViewGroup.LayoutParams.FILL_PARENT));
layout.addView(mPreview, 0);
setContentView(layout);
}
private void playVideo(Integer Media) {
doCleanUp();
try {
mMediaPlayer = MediaPlayer.create(this, R.raw.video);
mMediaPlayer.setDisplay(holder);
mMediaPlayer.setOnBufferingUpdateListener(this);
mMediaPlayer.setOnCompletionListener(this);
mMediaPlayer.setOnPreparedListener(this);
mMediaPlayer.setOnVideoSizeChangedListener(this);
mMediaPlayer.setOnErrorListener(this);
mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
} catch (Exception e) {
Log.e(TAG, "error: " + e.getMessage(), e);
}
}
public void onBufferingUpdate(MediaPlayer arg0, int percent) {
Log.d(TAG, "onBufferingUpdate percent:" + percent + " pos : " + mMediaPlayer.getCurrentPosition() + " / " + mMediaPlayer.getDuration());
if (mMediaPlayer.isPlaying()) {
Log.d(TAG, "Playing");
} else {
mMediaPlayer.start();
}
}
public void onCompletion(MediaPlayer arg0) {
Log.d(TAG, "onCompletion called");
}
public void onVideoSizeChanged(MediaPlayer mp, int width, int height) {
Log.v(TAG, "onVideoSizeChanged called");
if (width == 0 || height == 0) {
Log.e(TAG, "invalid video width(" + width + ") or height(" + height
+ ")");
return;
}
mIsVideoSizeKnown = true;
mVideoWidth = width;
mVideoHeight = height;
if (mIsVideoReadyToBePlayed && mIsVideoSizeKnown) {
startVideoPlayback();
}
}
public void onPrepared(MediaPlayer mediaplayer) {
Log.d(TAG, "onPrepared called");
mIsVideoReadyToBePlayed = true;
if (mIsVideoReadyToBePlayed && mIsVideoSizeKnown) {
startVideoPlayback();
}
}
public void surfaceChanged(SurfaceHolder surfaceholder, int i, int j, int k) {
Log.d(TAG, "surfaceChanged called. Width : " + j + ", height : " + k);
holder = surfaceholder;
mMediaPlayer.setDisplay(holder);
mIsVideoSizeKnown = true;
mVideoWidth = j;
mVideoHeight = k;
if (mIsVideoReadyToBePlayed && mIsVideoSizeKnown) {
startVideoPlayback();
}
}
public void surfaceDestroyed(SurfaceHolder surfaceholder) {
Log.d(TAG, "surfaceDestroyed called");
}
public void surfaceCreated(SurfaceHolder holder) {
Log.d(TAG, "surfaceCreated called");
playVideo(extras.getInt(MEDIA));
}
@Override
protected void onPause() {
super.onPause();
releaseMediaPlayer();
doCleanUp();
}
@Override
protected void onDestroy() {
super.onDestroy();
releaseMediaPlayer();
doCleanUp();
}
private void releaseMediaPlayer() {
if (mMediaPlayer != null) {
mMediaPlayer.release();
mMediaPlayer = null;
}
}
private void doCleanUp() {
mVideoWidth = 0;
mVideoHeight = 0;
mIsVideoReadyToBePlayed = false;
mIsVideoSizeKnown = false;
}
private void startVideoPlayback() {
Log.v(TAG, "startVideoPlayback " + mVideoWidth + "x" + mVideoHeight);
int width = mPreview.getWidth();
int height = mPreview.getHeight();
float boxWidth = width;
float boxHeight = height;
float videoWidth = mMediaPlayer.getVideoWidth();
float videoHeight = mMediaPlayer.getVideoHeight();
Log.i(TAG, String.format("startVideoPlayback @ video %dx%d - box %dx%d", (int) videoWidth, (int) videoHeight, width, height));
float wr = boxWidth / videoWidth;
float hr = boxHeight / videoHeight;
float ar = videoWidth / videoHeight;
if (wr > hr) {
width = (int) (boxHeight * ar);
} else {
height = (int) (boxWidth / ar);
}
Log.i(TAG, String.format("Scaled to %dx%d", width, height));
holder.setFixedSize(width, height);
mMediaPlayer.start();
}
public boolean onError(MediaPlayer arg0, int arg1, int arg2) {
Log.e(TAG, "ERROR called : " + arg1 + ", " + arg2);
return false;
}
}
从不调用onVideoSizeChanged
函数,但调用onPrepared
和surfaceChanged
.因此调用了startVideoPlayback
函数,但视频的宽度和高度均为0.
The onVideoSizeChanged
function is never called but the onPrepared
and surfaceChanged
are called.Thus the startVideoPlayback
function is called, but the video width and height are 0.
我正在播放视频,因为我可以听到声音,但是屏幕上什么都没有显示.我还尝试为SurfaceHolder
对象的setFixedSize
函数提供原始宽度和高度,但仍然没有显示任何内容.
My video is playing, as I can hear the sound, but nothing is displayed on the screen.I also tried to give raw width and height to the setFixedSize
function of the SurfaceHolder
object but I still don't have anything displayed.
你能帮我吗?我正在使用Android 8
Can you help me?I'm using Android 8
编辑
这是我从资源中播放视频时的日志:
Here is the log I have when I'm playing a video from the resources :
WARN info/warning (1, 35)
WARN info/warning (1, 44)
DEBUG Duration : 101248
DEBUG surfaceChanged called. Width : 480, height : 270
INFO Info (1,35)
INFO Info (1,44)
DEBUG onPrepared called
VERBOSE startVideoPlayback 480x270
INFO startVideoPlayback @ video 0x0 - box 480x270
INFO Scaled to 480x0
DEBUG surfaceDestroyed called
编辑2
我尝试了另一个视频,并且可以正常工作.
I tried with another video and it's working.
以下是无效"视频的规格:
Here are the specifications of the "not working" video :
- 容器:MP4-QuickTime
- 速率:2340 Kbps
- 格式:H.264/MPEG-4-AVC
- 大小:1280 * 640
- 纵横像素:未定义
- 图片比例:2.000
- 编码配置文件:[email protected]
- Container : MP4 - QuickTime
- Rate : 2 340 Kbps
- Format : H.264/MPEG-4-AVC
- Size : 1280*640
- Aspect pixel : undefined
- Image proportion : 2.000
- Encoding profile : [email protected]
以下是工作视频的规格:
Here are the specifications for the working video :
- 容器:MP4-QuickTime
- 费率:537 Kbps
- 格式:H.264/MPEG-4-AVC
- 大小:640 * 360
- 纵横像素:未定义
- 图像比例:16:9
- 编码配置文件:基准@ L3.0
- Container : MP4 - QuickTime
- Rate : 537 Kbps
- Format : H.264/MPEG-4-AVC
- Size : 640*360
- Aspect pixel : undefined
- Image proportion : 16:9
- Encoding profile : [email protected]
您知道第一个视频出了什么问题吗?
Do you know what's wrong with the first video ?
推荐答案
可尝试的一些方法:
1)您是否应该在playVideo方法中调用mMediaPlayer.prepareAsync()?
1) Should you be calling mMediaPlayer.prepareAsync() in your playVideo method?
2)尝试删除onPrepared中的if语句
2) Try removing your if statement in onPrepared
3)我会打电话给holder.setSizeFromLayout();然后从onPrepared回调(而不是onBufferingUpdate)中选择mMediaPlayer.start().
3) I would call holder.setSizeFromLayout(); and then mMediaPlayer.start() from your onPrepared callback (rather than onBufferingUpdate).
这篇关于MediaPlayer播放声音但不播放视频的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!