寻求帮助,因为我已经在这个问题上停留了几天,并且不知道如何解决!我正在使用代码中定义的扩展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/

10-12 02:33