android: SurfaceTexure, camera frame wait time out

后端 未结 2 1486
走了就别回头了
走了就别回头了 2020-12-11 23:55

I\'m trying to use MediaCodec and MediaMux, and I meet some trouble.

Here is the errors from the logcat:

12-13 11:59:58.238: E/AndroidRuntime(23218):         


        
2条回答
  •  南方客
    南方客 (楼主)
    2020-12-12 00:20

    As Florian correctly explained, the issue is that your code is running on a thread that has a looper. You need to make sure that the code is running on a thread that does not have a looper.

    The way I solved it was by modifying the setup() method in OutputSurface and ensuring that the setOnFrameListener() is attached to another Handler Thread.

    Here is the code for the same:

    class OutputSurface implements SurfaceTexture.OnFrameAvailableListener {
        private static final String TAG = "OutputSurface";
        private static final boolean VERBOSE = false;
        private EGLDisplay mEGLDisplay = EGL14.EGL_NO_DISPLAY;
        private EGLContext mEGLContext = EGL14.EGL_NO_CONTEXT;
        private EGLSurface mEGLSurface = EGL14.EGL_NO_SURFACE;
        private SurfaceTexture mSurfaceTexture;
        private Surface mSurface;
        private Object mFrameSyncObject = new Object();     
        private boolean mFrameAvailable;
        private TextureRender mTextureRender;
    
        private HandlerThread mHandlerThread;
        private Handler mHandler;
    
        public OutputSurface(int width, int height) {
            if (width <= 0 || height <= 0) {
                throw new IllegalArgumentException();
            }
            eglSetup(width, height);
            makeCurrent();
            setup();
        }
    
        public OutputSurface() {
            setup();
        }
    
        private void setup() {
            mTextureRender = new TextureRender();
            mTextureRender.surfaceCreated();
    
            mHandlerThread = new HandlerThread("callback-thread");
            mHandlerThread.start();
            mHandler = new Handler(mHandlerThread.getLooper());
    
            // Even if we don't access the SurfaceTexture after the constructor returns, we
            // still need to keep a reference to it.  The Surface doesn't retain a reference
            // at the Java level, so if we don't either then the object can get GCed, which
            // causes the native finalizer to run.
            if (VERBOSE) Log.d(TAG, "textureID=" + mTextureRender.getTextureId());
            mSurfaceTexture = new SurfaceTexture(mTextureRender.getTextureId());
            // This doesn't work if OutputSurface is created on the thread that CTS started for
            // these test cases.
            //
            // The CTS-created thread has a Looper, and the SurfaceTexture constructor will
            // create a Handler that uses it.  The "frame available" message is delivered
            // there, but since we're not a Looper-based thread we'll never see it.  For
            // this to do anything useful, OutputSurface must be created on a thread without
            // a Looper, so that SurfaceTexture uses the main application Looper instead.
            //
            // Java language note: passing "this" out of a constructor is generally unwise,
            // but we should be able to get away with it here.
    
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                mSurfaceTexture.setOnFrameAvailableListener(this, mHandler);
            } else {
                mSurfaceTexture.setOnFrameAvailableListener(this);
            }
    
            mSurface = new Surface(mSurfaceTexture);
        }
    }
    

    The rest of the OutputSurface class can remain the same.

提交回复
热议问题