即使没有synchronized关键字,为什么此代码存在性能问题?

时间:2016-07-11 12:06:46

标签: java android multithreading synchronized

为什么以下代码存在性能问题,相机的帧不流畅。

public class VideoCaptureAndroid implements PreviewCallback, Callback{
  private Integer deviceRotation = Integer.MAX_VALUE;

  public VideoCaptureAndroid(Context context, int id, long native_capturer) {
    deviceRotationNotifier = new OrientationEventListener(context, SensorManager.SENSOR_DELAY_NORMAL) {
      public void onOrientationChanged(int orientation) {
        if (orientation == ORIENTATION_UNKNOWN) {
          Log.d(TAG, "The device rotation angle is unknown.");
          return;
        }

        synchronized(deviceRotation) {
          if (deviceRotation != orientation) {
            deviceRotation = orientation;
          }
        }
      }
    };

    Exchanger<Handler> handlerExchanger = new Exchanger<Handler>();
    cameraThread = new CameraThread(handlerExchanger);
    cameraThread.start();
  }

  public synchronized void onPreviewFrame(byte[] data, Camera callbackCamera) {

    int frameRotation = info.orientation;
    if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
       frameRotation = (info.orientation - deviceRotation + 360) % 360;
    } else if (info.facing == Camera.CameraInfo.CAMERA_FACING_BACK) {
       frameRotation = (info.orientation + deviceRotation) % 360;
    }
    onFrame(data, data.length, native_capturer, frameRotation);
    camera.addCallbackBuffer(data);
  }

  }

似乎我注释掉以下代码,框架是平滑的,没有性能问题。但我没有使用synchronized中的onPreviewFrame来访问deviceRotation,为什么会受到onOrientationChanged的影响?

if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
   frameRotation = (info.orientation - deviceRotation + 360) % 360;
} else if (info.facing == Camera.CameraInfo.CAMERA_FACING_BACK) {
   frameRotation = (info.orientation + deviceRotation) % 360;
}

1 个答案:

答案 0 :(得分:0)

您指出的代码很可能问题。模数运算很慢,但每帧执行一次不会产生巨大影响。 frameRotation值传递给onFrame(),我们只能假设是应用矩阵或其他变换来旋转数据。这是一项昂贵的操作,很可能涉及使用一个或多个临时缓冲区(或Bitmap个对象),这些缓冲区使用堆并且速度也很慢。我假设info.orientation未经更改传递给onFrame()将导致不对帧进行调整。因此,删除已指示的2行将导致onFrame()中没有繁重的处理,这就是抖动消失的原因。

您可以使用traceview或systrace进行更好地跟踪,以确认。