MediaPlayer 播放声音但不播放视频
Posted
技术标签:
【中文标题】MediaPlayer 播放声音但不播放视频【英文标题】:MediaPlayer playing sound but not video 【发布时间】:2014-01-15 14:02:47 【问题描述】:我正在尝试使用 SurfaceView
播放来自 android 的视频。
我可以加载视频,声音可以正常播放,但我看不到视频。
这是我的活动:
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。
我的视频正在播放,我可以听到声音,但屏幕上没有显示任何内容。
我还尝试为SurfaceHolder
对象的setFixedSize
函数提供原始宽度和高度,但我仍然没有显示任何内容。
你能帮帮我吗? 我使用的是 Android 8
编辑
这是我从资源中播放视频时的日志:
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
我尝试了另一个视频,它可以正常工作。
以下是“不工作”视频的规格:
容器:MP4 - QuickTime 速率:2 340 Kbps 格式:H.264/MPEG-4-AVC 尺寸:1280*640 纵横比像素:未定义 图像比例:2.000 编码配置文件:Baseline@L3.1以下是工作视频的规格:
容器:MP4 - QuickTime 速率:537 Kbps 格式:H.264/MPEG-4-AVC 尺寸:640*360 纵横比像素:未定义 图像比例:16:9 编码配置文件:Baseline@L3.0你知道第一个视频有什么问题吗?
【问题讨论】:
logcat 是否显示错误? @Nfear 我编辑了我的问题以添加日志。我只有一些警告,但我不知道它们是什么意思 实际上它正在使用另一个视频,我更新了我的问题。你知道为什么第一个视频不起作用(使用相同的编码) 我也遇到过同样的问题。原因是您尝试播放的视频超出了屏幕的尺寸。当我做一些测试时,我侥幸发现了这一点。为了解决这个问题,我不得不改用MediaCodec
API,这样无论分辨率如何,视频都可以播放。我的直觉是由于视频的大小。当您更改第二个视频的分辨率时,它可以正常工作,因为它可以舒适地放在屏幕上。
【参考方案1】:
一些尝试:
1) 你应该在你的 playVideo 方法中调用 mMediaPlayer.prepareAsync() 吗?
2) 尝试删除 onPrepared 中的 if 语句
3) 我会调用 holder.setSizeFromLayout();然后是来自 onPrepared 回调(而不是 onBufferingUpdate)的 mMediaPlayer.start()。
【讨论】:
1) 应用程序崩溃是因为构造函数已经调用了 prepare。 2-3) 我的 OnPrepare 只调用了 setSizeFromLayout 并开始。视频正在开始,但屏幕上仍然没有显示任何内容 @FabienHenon 我认为你指定了错误的纵横比,检查一下以上是关于MediaPlayer 播放声音但不播放视频的主要内容,如果未能解决你的问题,请参考以下文章
MediaPlayer音乐播放器上一首下一首播放停止自动下一首进度条
在 mediaplayer 中播放的 Android webview 视频