寻求帮助,因为我已经在这个问题上停留了几天,并且不知道如何解决!我正在使用代码中定义的扩展Surfaceview来播放sd卡中的视频mp4文件,播放之后,我想在MediaPlayer顶部绘制位图。我可以正常播放视频,但是当我打电话时c = this.surfaceHolder.lockCanvas();
我收到强制关闭并出现以下错误:E/Surface ( 665): surface (identity=44) is invalid, err=-19 (No such device)D/CallStack( 665): Surface#00 pc 00013d08 /system/lib/libsurfaceflinger_client.soD/CallStack( 665): Surface#01 pc 000140d2 /system/lib/libsurfaceflinger_client.soD/CallStack( 665): Surface#02 pc 000142d0 /system/lib/libsurfaceflinger_client.soD/CallStack( 665): Surface#03 pc 00043bb6 /system/lib/libandroid_runtime.soE/Surface ( 665): dequeueBuffer failed (No such device)E/SurfaceHolder( 665): Exception locking surface
更多细节:
这是我扩展的Surface类:
public class MainMenu extends SurfaceView implements
SurfaceHolder.Callback {
private static final String TAG = MainMenu.class.getSimpleName();
private MainThread thread;
private VideoPlayer videPlayer;
public MainMenu(Context context) {
super(context);
// TODO Auto-generated constructor stub
getHolder().addCallback(this);
Log.d(TAG,"Context menu called---" );
setFocusable(true);
Log.d(TAG,"Context menu end call---" );
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
// TODO Auto-generated method stub
Log.d(TAG, "surfaceChanged called"+holder);
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
// TODO Auto-generated method stub
Log.d(TAG, "surfaceCreated called"+holder);
if (holder == null){
Log.d(TAG, "surfaceCreated called holder is null="+holder);
}
videPlayer = new VideoPlayer(getHolder(),this);
videPlayer.VideoPlayerF();
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
// TODO Auto-generated method stub
Log.d(TAG,"Surface is being destroyed");
boolean retry = true;
while (retry) {
try {
thread.join();
retry = false;
} catch (InterruptedException e) {
// try again shutting down the thread
}
}
Log.d(TAG, "Thread was shut down cleanly");
}
@Override
public boolean onTouchEvent(MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
// delegating event handling to the droid
// check if in the lower part of the screen we exit
if (event.getY() > getHeight() - 50) {
thread.setRunning(false);
((Activity)getContext()).finish();
} else {
Log.d(TAG, "Coords: x=" + event.getX() + ",y=" + event.getY());
}
} if (event.getAction() == MotionEvent.ACTION_MOVE) {
// the gestures
if (button_left.isTouched()) {
// the droid was picked up and is being dragged
}
} if (event.getAction() == MotionEvent.ACTION_UP) {
// touch was released
}
return true;
}
public void render(Canvas canvas){
canvas.drawColor(Color.WHITE);
//Will draw something here
}
}
第二类,VidePlayer。
public class VideoPlayer implements OnErrorListener,OnBufferingUpdateListener, OnCompletionListener,
MediaPlayer.OnPreparedListener, OnVideoSizeChangedListener {
private static final String TAG = MainMenu.class.getSimpleName();
public MediaPlayer mp;
public MainMenu mainMenu;
private SurfaceHolder surfaceHolder;
private Surface surface;
public VideoPlayer(SurfaceHolder surfaceHolder, MainMenu mainMenu) {
Log.d(TAG, "VideoPlayer called ");
this.surfaceHolder = surfaceHolder;
this.mainMenu=mainMenu;
Log.d(TAG, "VideoPlayer MediaPlayer created ");
Log.d(TAG, "VideoPlayer MediaPlayer created Surface name" + this.surfaceHolder.getSurface());
}
public void VideoPlayerF(){
Log.d(TAG, "VideoPlayer VideoPlayerF called "+this.surfaceHolder);
if (this.surfaceHolder == null){
Log.d(TAG, "VideoPlayer VideoPlayerF holder is null"+surfaceHolder);
}
try {
String path = "/sdcard/video/sample.mp4";
Log.d(TAG, "path: " + path);
mp = new MediaPlayer();
mp.setDataSource(path);
mp.setDisplay(this.surfaceHolder);
mp.prepare();
mp.setOnErrorListener(this);
mp.setOnBufferingUpdateListener(this);
mp.setOnCompletionListener(this);
mp.setOnPreparedListener(this);
mp.setOnVideoSizeChangedListener(this);
mp.setAudioStreamType(AudioManager.STREAM_MUSIC);
} catch (Exception e) {
Log.e(TAG, "error: " + e.getMessage(), e);
}
}
public void onPrepared(MediaPlayer mp) {
// TODO Auto-generated method stub
Log.d(TAG, "onPrepared called");
startVideoPlayback();
}
@Override
public void onCompletion(MediaPlayer mp) {
// TODO Auto-generated method stub
Log.d(TAG, "onCompletion called Surface size" + this.surfaceHolder.getSurfaceFrame());
if (mp != null) {
mp.stop();
mp.reset();
mp.release();
mp=null;
callthread();
Log.d(TAG, "onCompletion called mp released");
Log.d(TAG, "Prepared to send surface " + this.surfaceHolder);
Log.d(TAG, "Prepared surface " + this.surfaceHolder.getSurface());
}
return;
}
@Override
public void onBufferingUpdate(MediaPlayer arg0, int percent) {
// TODO Auto-generated method stub
Log.d(TAG, "onBufferingUpdate called ---> percent:" + percent);
}
public void callthread(){
/*
*
* Will start drawing here
*/
surface=this.surfaceHolder.getSurface();
Canvas c = new Canvas();
if (surface.isValid()){
Log.d(TAG, "callthread called ---> surface.isValid" + surface.isValid());
c = this.surfaceHolder.lockCanvas();
}else{
Log.d(TAG, "callthread called else ---> surface.isValid" + surface.isValid());
}
this.mainMenu.render(c);
}
@Override
public boolean onError(MediaPlayer mediaPlayer, int what, int extra) {
Log.e(TAG, "onError---> what:" + what + " extra:" + extra);
if (mediaPlayer != null) {
Log.e(TAG, "onError mediaPlayer != null ");
}
return false;
}
private void startVideoPlayback() {
Log.v(TAG, "startVideoPlayback");
Log.v(TAG, "Video Sizw "+ mp.getVideoHeight() + mp.getVideoWidth());
mp.start();
}
@Override
public void onVideoSizeChanged(MediaPlayer mp, int arg1, int arg2) {
// TODO Auto-generated method stub
this.surfaceHolder.setFixedSize(arg1, arg2);
Log.d(TAG, "VideoPlayer onVideoSizeChanged called"+arg1 + arg2);
}
}
这是logcat
D/dalvikvm( 657): Debugger has detached; object registry had 1 entries
D/ling ( 665): View added==dspSizeHeight===752and dsp size 1280
D/MainMenu( 665): Context menu called---
D/MainMenu( 665): Context menu end call---
D/ling ( 665): View added
D/MainMenu( 665): surfaceCreated calledandroid.view.SurfaceView$4@40646ec8
D/MainMenu( 665): VideoPlayer called
D/MainMenu( 665): VideoPlayer MediaPlayer created
D/MainMenu( 665): VideoPlayer MediaPlayer created Surface nameSurface(name=null
, identity=44)
D/MainMenu( 665): VideoPlayer VideoPlayerF called android.view.SurfaceView$4@4
0646ec8
D/MainMenu( 665): path: /sdcard/video/sample.mp4
I/AwesomePlayer( 34): reset
I/AwesomePlayer( 34): cancel player events
I/AwesomePlayer( 34): cancel player events
I/AwesomePlayer( 34): setDataSource_l('/sdcard/video/sample.mp4')
D/MainMenu( 665): VideoPlayer VideoPlayerF called this.surfaceHolder=android.v
iew.SurfaceView$4@40646ec8
D/MainMenu( 665): surfaceChanged calledandroid.view.SurfaceView$4@40646ec8
I/ActivityManager( 82): Displayed com.clapp.ling/.ling: +3s729ms
D/MainMenu( 665): VideoPlayer onVideoSizeChanged called190240
D/MainMenu( 665): onPrepared called
V/MainMenu( 665): startVideoPlayback
V/MainMenu( 665): Video Sizw 240190
D/AudioSink( 34): bufferCount (4) is too small and increased to 12
D/MainMenu( 665): surfaceChanged calledandroid.view.SurfaceView$4@40646ec8
W/AudioFlinger( 34): write blocked for 128 msecs, 34 delayed writes, thread 0x
10108
D/MainMenu( 665): VideoPlayer onVideoSizeChanged called190240
I/AwesomePlayer( 34): we're much too late (0.85 secs), video skipping ahead
D/dalvikvm( 155): GC_EXPLICIT freed 504K, 20% free 12897K/16007K, paused 13ms+1
1ms
I/AwesomePlayer( 34): we're much too late (0.55 secs), video skipping ahead
I/AwesomePlayer( 34): we're much too late (0.50 secs), video skipping ahead
W/AudioFlinger( 34): write blocked for 94 msecs, 42 delayed writes, thread 0x1
0108
D/MainMenu( 665): onCompletion called Surface sizeRect(0, 0 - 1280, 752)
I/AwesomePlayer( 34): reset
I/AwesomePlayer( 34): cancel player events
I/AwesomePlayer( 34): video decoder shutdown completed
D/MainMenu( 665): callthread() lockCanvas
D/MainMenu( 665): callthread called ---> surface.isValidtrue
E/Surface ( 665): surface (identity=44) is invalid, err=-19 (No such device)
D/CallStack( 665): Surface#00 pc 00013d08 /system/lib/libsurfaceflinger_clien
t.so
D/CallStack( 665): Surface#01 pc 000140d2 /system/lib/libsurfaceflinger_clien
t.so
D/CallStack( 665): Surface#02 pc 000142d0 /system/lib/libsurfaceflinger_clien
t.so
D/CallStack( 665): Surface#03 pc 00043bb6 /system/lib/libandroid_runtime.so
E/Surface ( 665): dequeueBuffer failed (No such device)
E/SurfaceHolder( 665): Exception locking surface
E/SurfaceHolder( 665): java.lang.IllegalArgumentException
E/SurfaceHolder( 665): at android.view.Surface.lockCanvasNative(Native
Method)
E/SurfaceHolder( 665): at android.view.Surface.lockCanvas(Surface.java:
350)
E/SurfaceHolder( 665): at android.view.SurfaceView$4.internalLockCanvas
(SurfaceView.java:772)
E/SurfaceHolder( 665): at android.view.SurfaceView$4.lockCanvas(Surface
View.java:748)
E/SurfaceHolder( 665): at com.clapp.ling.VideoPlayer.callthread(VideoPl
ayer.java:157)
E/SurfaceHolder( 665): at com.clapp.ling.VideoPlayer.onCompletion(Video
Player.java:122)
E/SurfaceHolder( 665): at android.media.MediaPlayer$EventHandler.handle
Message(MediaPlayer.java:1325)
E/SurfaceHolder( 665): at android.os.Handler.dispatchMessage(Handler.ja
va:99)
E/SurfaceHolder( 665): at android.os.Looper.loop(Looper.java:132)
E/SurfaceHolder( 665): at android.app.ActivityThread.main(ActivityThrea
d.java:4123)
E/SurfaceHolder( 665): at java.lang.reflect.Method.invokeNative(Native
Method)
E/SurfaceHolder( 665): at java.lang.reflect.Method.invoke(Method.java:4
91)
E/SurfaceHolder( 665): at com.android.internal.os.ZygoteInit$MethodAndA
rgsCaller.run(ZygoteInit.java:841)
E/SurfaceHolder( 665): at com.android.internal.os.ZygoteInit.main(Zygot
eInit.java:599)
E/SurfaceHolder( 665): at dalvik.system.NativeStart.main(Native Method)
D/AndroidRuntime( 665): Shutting down VM
W/dalvikvm( 665): threadid=1: thread exiting with uncaught exception (group=0x4
0014760)
E/AndroidRuntime( 665): FATAL EXCEPTION: main
E/AndroidRuntime( 665): java.lang.NullPointerException
E/AndroidRuntime( 665): at com.clapp.ling.MainMenu.render(MainMenu.java:
201)
E/AndroidRuntime( 665): at com.clapp.ling.VideoPlayer.callthread(VideoPl
ayer.java:162)
E/AndroidRuntime( 665): at com.clapp.ling.VideoPlayer.onCompletion(Video
Player.java:122)
E/AndroidRuntime( 665): at android.media.MediaPlayer$EventHandler.handle
Message(MediaPlayer.java:1325)
E/AndroidRuntime( 665): at android.os.Handler.dispatchMessage(Handler.ja
va:99)
E/AndroidRuntime( 665): at android.os.Looper.loop(Looper.java:132)
E/AndroidRuntime( 665): at android.app.ActivityThread.main(ActivityThrea
d.java:4123)
E/AndroidRuntime( 665): at java.lang.reflect.Method.invokeNative(Native
Method)
E/AndroidRuntime( 665): at java.lang.reflect.Method.invoke(Method.java:4
91)
E/AndroidRuntime( 665): at com.android.internal.os.ZygoteInit$MethodAndA
rgsCaller.run(ZygoteInit.java:841)
E/AndroidRuntime( 665): at com.android.internal.os.ZygoteInit.main(Zygot
eInit.java:599)
E/AndroidRuntime( 665): at dalvik.system.NativeStart.main(Native Method)
I/AwesomePlayer( 34): reset
I/AwesomePlayer( 34): cancel player events
I/AwesomePlayer( 34): reset
I/AwesomePlayer( 34): cancel player events
I/AwesomePlayer( 34): reset
I/AwesomePlayer( 34): cancel player events
W/ActivityManager( 82): Force finishing activity com.clapp.ling/.ling
W/WindowManager( 82): Failure taking screenshot for (230x135) to layer 21015
W/ActivityManager( 82): Activity pause timeout for ActivityRecord{407d3060 com
.clapp.ling/.ling}
I/dalvikvm( 155): Jit: resizing JitTable from 512 to 1024
I/Process ( 665): Sending signal. PID: 665 SIG: 9
I/ActivityManager( 82): Process com.clapp.ling (pid 665) has died.
E/InputDispatcher( 82): channel '40893f68 com.clapp.ling/com.clapp.ling.ling (
server)' ~ Consumer closed input channel or an error occurred. events=0x8
E/InputDispatcher( 82): channel '40893f68 com.clapp.ling/com.clapp.ling.ling (
server)' ~ Channel is unrecoverably broken and will be disposed!
D/dalvikvm( 155): GC_CONCURRENT freed 1449K, 17% free 13383K/16007K, paused 6ms
+44ms
I/WindowManager( 82): WIN DEATH: Window{40893f68 com.clapp.ling/com.clapp.ling
.ling paused=false}
I/WindowManager( 82): WIN DEATH: Window{40c132e0 SurfaceView paused=false}
I/WindowManager( 82): WINDOW DIED Window{40893f68 com.clapp.ling/com.clapp.lin
g.ling paused=false}
W/InputManagerService( 82): Got RemoteException sending setActive(false) notif
ication to pid 665 uid 10036
D/dalvikvm( 262): GC_EXPLICIT freed 8K, 5% free 6300K/6595K, paused 7ms+7ms
D/dalvikvm( 333): GC_EXPLICIT freed 17K, 6% free 6381K/6727K, paused 7ms+10ms
D/SntpClient( 82): request time failed: java.net.SocketException: Address fami
ly not supported by protocol
问题是为什么即使通过验证检查也无法锁定画布以进行绘图
if (surface.isValid())
以及我应该在代码中添加或覆盖哪些内容以锁定画布并绘制位图。
感谢您的帮助!
最佳答案
您正在将SurfaceView的表面提供给MediaPlayer ...,这意味着您不能再使用它了! MediaPlayer将产生一个每秒多次锁定并在其上绘制的线程,您无法与其进行同步,也不应尝试这样做。
Surface.isValid()仅指示对象是否已附加到物理表面(即帧缓冲区)。在surfaceCreated()和surfaceDestroyed()之间返回true,在其余时间返回false。
关于android - 将MediaPlayer与Surfaceview一起使用时锁定 Canvas 失败,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/8993677/