# Copyright 2022 The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Validate video aspect ratio, crop and FoV vs format."""

import logging
import os.path

from mobly import test_runner

import its_base_test
import camera_properties_utils
import capture_request_utils
import image_fov_utils
import image_processing_utils
import its_session_utils
import opencv_processing_utils
import video_processing_utils


_NAME = os.path.splitext(os.path.basename(__file__))[0]
_VIDEO_RECORDING_DURATION_SECONDS = 3
_FOV_PERCENT_RTOL = 0.15  # Relative tolerance on circle FoV % to expected.
_AR_CHECKED_PRE_API_30 = ('4:3', '16:9', '18:9')
_AR_DIFF_ATOL = 0.01
_MAX_8BIT_IMGS = 255
_MAX_10BIT_IMGS = 1023


def _print_failed_test_results(failed_ar, failed_fov, failed_crop,
                               quality):
  """Print failed test results."""
  if failed_ar:
    logging.error('Aspect ratio test summary for %s', quality)
    logging.error('Images failed in the aspect ratio test:')
    logging.error('Aspect ratio value: width / height')
    for fa in failed_ar:
      logging.error('%s', fa)

  if failed_fov:
    logging.error('FoV test summary for %s', quality)
    logging.error('Images failed in the FoV test:')
    for fov in failed_fov:
      logging.error('%s', str(fov))

  if failed_crop:
    logging.error('Crop test summary for %s', quality)
    logging.error('Images failed in the crop test:')
    logging.error('Circle center (H x V) relative to the image center.')
    for fc in failed_crop:
      logging.error('%s', fc)


class VideoAspectRatioAndCropTest(its_base_test.ItsBaseTest):
  """Test aspect ratio/field of view/cropping for each tested fmt.

    This test checks for:
    1. Aspect ratio: images are not stretched
    2. Crop: center of images is not shifted
    3. FOV: images cropped to keep maximum possible FOV with only 1 dimension
       (horizontal or veritical) cropped.

  Video recording will be done using the SDR profile as well as HLG10
  if available.

  The test video is a black circle on a white background.

  When RAW capture is available, set the height vs. width ratio of the circle in
  the full-frame RAW as ground truth. In an ideal setup such ratio should be
  very close to 1.0, but here we just use the value derived from full resolution
  RAW as ground truth to account for the possibility that the chart is not
  well positioned to be precisely parallel to image sensor plane.
  The test then compares the ground truth ratio with the same ratio measured
  on videos captued using different formats.

  If RAW capture is unavailable, a full resolution JPEG image is used to setup
  ground truth. In this case, the ground truth aspect ratio is defined as 1.0
  and it is the tester's responsibility to make sure the test chart is
  properly positioned so the detected circles indeed have aspect ratio close
  to 1.0 assuming no bugs causing image stretched.

  The aspect ratio test checks the aspect ratio of the detected circle and
  it will fail if the aspect ratio differs too much from the ground truth
  aspect ratio mentioned above.

  The FOV test examines the ratio between the detected circle area and the
  image size. When the aspect ratio of the test image is the same as the
  ground truth image, the ratio should be very close to the ground truth
  value. When the aspect ratio is different, the difference is factored in
  per the expectation of the Camera2 API specification, which mandates the
  FOV reduction from full sensor area must only occur in one dimension:
  horizontally or vertically, and never both. For example, let's say a sensor
  has a 16:10 full sensor FOV. For all 16:10 output images there should be no
  FOV reduction on them. For 16:9 output images the FOV should be vertically
  cropped by 9/10. For 4:3 output images the FOV should be cropped
  horizontally instead and the ratio (r) can be calculated as follows:
      (16 * r) / 10 = 4 / 3 => r = 40 / 48 = 0.8333
  Say the circle is covering x percent of the 16:10 sensor on the full 16:10
  FOV, and assume the circle in the center will never be cut in any output
  sizes (this can be achieved by picking the right size and position of the
  test circle), the from above cropping expectation we can derive on a 16:9
  output image the circle will cover (x / 0.9) percent of the 16:9 image; on
  a 4:3 output image the circle will cover (x / 0.8333) percent of the 4:3
  image.

  The crop test checks that the center of any output image remains aligned
  with center of sensor's active area, no matter what kind of cropping or
  scaling is applied. The test verifies that by checking the relative vector
  from the image center to the center of detected circle remains unchanged.
  The relative part is normalized by the detected circle size to account for
  scaling effect.
  """

  def test_video_aspect_ratio_and_crop(self):
    logging.debug('Starting %s', _NAME)
    failed_ar = []  # Streams failed the aspect ratio test.
    failed_crop = []  # Streams failed the crop test.
    failed_fov = []  # Streams that fail FoV test.

    with its_session_utils.ItsSession(
        device_id=self.dut.serial,
        camera_id=self.camera_id,
        hidden_physical_id=self.hidden_physical_id) as cam:
      props = cam.get_camera_properties()
      fls_logical = props['android.lens.info.availableFocalLengths']
      logging.debug('logical available focal lengths: %s', str(fls_logical))
      props = cam.override_with_hidden_physical_camera_props(props)
      fls_physical = props['android.lens.info.availableFocalLengths']
      logging.debug('physical available focal lengths: %s', str(fls_physical))

      # Check SKIP conditions.
      vendor_api_level = its_session_utils.get_vendor_api_level(self.dut.serial)
      camera_properties_utils.skip_unless(
          vendor_api_level >= its_session_utils.ANDROID13_API_LEVEL)

      # Load scene.
      its_session_utils.load_scene(cam, props, self.scene,
                                   self.tablet, self.chart_distance)

      # Determine camera capabilities.
      supported_video_qualities = cam.get_supported_video_qualities(
          self.camera_id)
      logging.debug('Supported video qualities: %s', supported_video_qualities)
      full_or_better = camera_properties_utils.full_or_better(props)
      raw_avlb = camera_properties_utils.raw16(props)
      debug = self.debug_mode

      # Converge 3A.
      cam.do_3a()
      req = capture_request_utils.auto_capture_request()
      ref_img_name_stem = f'{os.path.join(self.log_path, _NAME)}'

      if raw_avlb and (fls_physical == fls_logical):
        logging.debug('RAW')
      else:
        logging.debug('JPEG')

      ref_fov, cc_ct_gt, aspect_ratio_gt = image_fov_utils.find_fov_reference(
          cam, req, props, raw_avlb, ref_img_name_stem)

      run_crop_test = full_or_better and raw_avlb

      # Get ffmpeg version being used.
      ffmpeg_version = video_processing_utils.get_ffmpeg_version()
      logging.debug('ffmpeg_version: %s', ffmpeg_version)

      for quality_profile_id_pair in supported_video_qualities:
        quality = quality_profile_id_pair.split(':')[0]
        profile_id = quality_profile_id_pair.split(':')[-1]
        # Check if we support testing this quality.
        if quality in video_processing_utils.ITS_SUPPORTED_QUALITIES:
          logging.debug('Testing video recording for quality: %s', quality)
          hlg10_params = [False]
          hlg10_supported = cam.is_hlg10_recording_supported(profile_id)
          logging.debug('HLG10 supported: %s', hlg10_supported)
          if hlg10_supported:
            hlg10_params.append(hlg10_supported)

          for hlg10_param in hlg10_params:
            video_recording_obj = cam.do_basic_recording(
                profile_id, quality, _VIDEO_RECORDING_DURATION_SECONDS, 0,
                hlg10_param)
            logging.debug('video_recording_obj: %s', video_recording_obj)
            # TODO(ruchamk): Modify video recording object to send videoFrame
            # width and height instead of videoSize to avoid string operation
            # here.
            video_size = video_recording_obj['videoSize']
            width = int(video_size.split('x')[0])
            height = int(video_size.split('x')[-1])

            # Pull the video recording file from the device.
            self.dut.adb.pull([video_recording_obj['recordedOutputPath'],
                               self.log_path])
            logging.debug('Recorded video is available at: %s',
                          self.log_path)
            video_file_name = video_recording_obj[
                'recordedOutputPath'].split('/')[-1]
            logging.debug('video_file_name: %s', video_file_name)

            key_frame_files = []
            key_frame_files = video_processing_utils.extract_key_frames_from_video(
                self.log_path, video_file_name)
            logging.debug('key_frame_files:%s', key_frame_files)

            # Get the key frame file to process.
            last_key_frame_file = video_processing_utils.get_key_frame_to_process(
                key_frame_files)
            logging.debug('last_key_frame: %s', last_key_frame_file)
            last_key_frame_path = os.path.join(
                self.log_path, last_key_frame_file)

            # Convert lastKeyFrame to numpy array
            np_image = image_processing_utils.convert_image_to_numpy_array(
                last_key_frame_path)
            logging.debug('numpy image shape: %s', np_image.shape)

            # Check fov
            ref_img_name = '%s_%s_w%d_h%d_circle.png' % (
                os.path.join(self.log_path, _NAME), quality, width, height)
            circle = opencv_processing_utils.find_circle(
                np_image, ref_img_name, image_fov_utils.CIRCLE_MIN_AREA,
                image_fov_utils.CIRCLE_COLOR)

            if debug:
              opencv_processing_utils.append_circle_center_to_img(
                  circle, np_image, ref_img_name)

            max_img_value = _MAX_8BIT_IMGS
            if hlg10_param:
              max_img_value = _MAX_10BIT_IMGS

            # Check pass/fail for fov coverage for all fmts in AR_CHECKED
            fov_chk_msg = image_fov_utils.check_fov(
                circle, ref_fov, width, height)
            if fov_chk_msg:
              img_name = '%s_%s_w%d_h%d_fov.png' % (
                  os.path.join(self.log_path, _NAME), quality, width, height)
              fov_chk_quality_msg = f'Quality: {quality} {fov_chk_msg}'
              failed_fov.append(fov_chk_quality_msg)
              image_processing_utils.write_image(
                  np_image/max_img_value, img_name, True)

            # Check pass/fail for aspect ratio.
            ar_chk_msg = image_fov_utils.check_ar(
                circle, aspect_ratio_gt, width, height,
                f'{quality}')
            if ar_chk_msg:
              img_name = '%s_%s_w%d_h%d_ar.png' % (
                  os.path.join(self.log_path, _NAME), quality, width, height)
              failed_ar.append(ar_chk_msg)
              image_processing_utils.write_image(
                  np_image/max_img_value, img_name, True)

            # Check pass/fail for crop.
            if run_crop_test:
              # Normalize the circle size to 1/4 of the image size, so that
              # circle size won't affect the crop test result
              crop_thresh_factor = ((min(ref_fov['w'], ref_fov['h']) / 4.0) /
                                    max(ref_fov['circle_w'],
                                        ref_fov['circle_h']))
              crop_chk_msg = image_fov_utils.check_crop(
                  circle, cc_ct_gt, width, height,
                  f'{quality}', crop_thresh_factor)
              if crop_chk_msg:
                crop_img_name = '%s_%s_w%d_h%d_crop.png' % (
                    os.path.join(self.log_path, _NAME), quality, width, height)
                failed_crop.append(crop_chk_msg)
                image_processing_utils.write_image(np_image/max_img_value,
                                                   crop_img_name, True)
            else:
              logging.debug('Crop test skipped')

      # Print any failed test results.
      _print_failed_test_results(failed_ar, failed_fov, failed_crop, quality)
      e_msg = ''
      if failed_ar:
        e_msg = 'Aspect ratio '
      if failed_fov:
        e_msg += 'FoV '
      if failed_crop:
        e_msg += 'Crop '
      if e_msg:
        raise AssertionError(f'{e_msg}check failed.')

if __name__ == '__main__':
  test_runner.main()
