private int bufferCopiedCallback(long nCopiedSize, long nAvailableSize) {
    if (!super.mValid) {
      Log.e(TAG, "Invalid state");
      return -1;
    }
    if (mPreview == null || !mPreview.isReady()) {
      // Not on the top
      return 0;
    }

    if (mVideoFrame == null || mVideoFrame.capacity() != nAvailableSize) {
      synchronized (mPreview) {
        long newWidth = mConsumer.getDisplayWidth();
        long newHeight = mConsumer.getDisplayHeight();

        mVideoFrame = ByteBuffer.allocateDirect((int) nAvailableSize);
        mConsumer.setConsumeBuffer(mVideoFrame, mVideoFrame.capacity());

        mWidth = (int) newWidth;
        mHeight = (int) newHeight;
        mPreview.setBuffer(mVideoFrame, mWidth, mHeight);
      }
      return 0;
    }

    mPreview.requestRender();

    return 0;
  }
  private int consumeCallback(ProxyVideoFrame _frame) {
    if (!super.mValid) {
      Log.e(TAG, "Invalid state");
      return -1;
    }
    if (mPreview == null || !mPreview.isReady()) {
      // Not on the top
      return 0;
    }

    // Get video frame content from native code
    _frame.getContent(mVideoFrame, mVideoFrame.capacity());

    mPreview.requestRender();

    return 0;
  }
 @Override
 public final View startPreview(Context context) {
   mContext = context == null ? mContext : context;
   if (mContext != null) {
     if (mPreview == null || mPreview.isDestroyed()) {
       mPreview = new NgnProxyVideoConsumerGLPreview(mContext, mVideoFrame, mWidth, mHeight, mFps);
     }
   }
   return mPreview;
 }