content: /*
   * Copyright (C) 2013 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.
   */
  
  package com.example.android.common.media;
  
  import android.annotation.TargetApi;
  import android.hardware.Camera;
  import android.os.Build;
  import android.os.Environment;
  import android.util.Log;
  
  import java.io.File;
  import java.text.SimpleDateFormat;
  import java.util.Date;
  import java.util.List;
  import java.util.Locale;
  
  /**
   * Camera related utilities.
   */
  public class CameraHelper {
  
      public static final int MEDIA_TYPE_IMAGE = 1;
      public static final int MEDIA_TYPE_VIDEO = 2;
  
      /**
       * Iterate over supported camera video sizes to see which one best fits the
       * dimensions of the given view while maintaining the aspect ratio. If none can,
       * be lenient with the aspect ratio.
       *
       * @param supportedVideoSizes Supported camera video sizes.
       * @param previewSizes Supported camera preview sizes.
       * @param w     The width of the view.
       * @param h     The height of the view.
       * @return Best match camera video size to fit in the view.
       */
      public static Camera.Size getOptimalVideoSize(List<Camera.Size> supportedVideoSizes,
              List<Camera.Size> previewSizes, int w, int h) {
          // Use a very small tolerance because we want an exact match.
          final double ASPECT_TOLERANCE = 0.1;
          double targetRatio = (double) w / h;
  
          // Supported video sizes list might be null, it means that we are allowed to use the preview
          // sizes
          List<Camera.Size> videoSizes;
          if (supportedVideoSizes != null) {
              videoSizes = supportedVideoSizes;
          } else {
              videoSizes = previewSizes;
          }
          Camera.Size optimalSize = null;
  
          // Start with max value and refine as we iterate over available video sizes. This is the
          // minimum difference between view and camera height.
          double minDiff = Double.MAX_VALUE;
  
          // Target view height
          int targetHeight = h;
  
          // Try to find a video size that matches aspect ratio and the target view size.
          // Iterate over all available sizes and pick the largest size that can fit in the view and
          // still maintain the aspect ratio.
          for (Camera.Size size : videoSizes) {
              double ratio = (double) size.width / size.height;
              if (Math.abs(ratio - targetRatio) > ASPECT_TOLERANCE)
                  continue;
              if (Math.abs(size.height - targetHeight) < minDiff && previewSizes.contains(size)) {
                  optimalSize = size;
                  minDiff = Math.abs(size.height - targetHeight);
              }
          }
  
          // Cannot find video size that matches the aspect ratio, ignore the requirement
          if (optimalSize == null) {
              minDiff = Double.MAX_VALUE;
              for (Camera.Size size : videoSizes) {
                  if (Math.abs(size.height - targetHeight) < minDiff && previewSizes.contains(size)) {
                      optimalSize = size;
                      minDiff = Math.abs(size.height - targetHeight);
                  }
              }
          }
          return optimalSize;
      }
  
      /**
       * @return the default camera on the device. Return null if there is no camera on the device.
       */
      public static Camera getDefaultCameraInstance() {
          return Camera.open();
      }
  
  
      /**
       * @return the default rear/back facing camera on the device. Returns null if camera is not
       * available.
       */
      public static Camera getDefaultBackFacingCameraInstance() {
          return getDefaultCamera(Camera.CameraInfo.CAMERA_FACING_BACK);
      }
  
      /**
       * @return the default front facing camera on the device. Returns null if camera is not
       * available.
       */
      public static Camera getDefaultFrontFacingCameraInstance() {
          return getDefaultCamera(Camera.CameraInfo.CAMERA_FACING_FRONT);
      }
  
  
      /**
       *
       * @param position Physical position of the camera i.e Camera.CameraInfo.CAMERA_FACING_FRONT
       *                 or Camera.CameraInfo.CAMERA_FACING_BACK.
       * @return the default camera on the device. Returns null if camera is not available.
       */
      @TargetApi(Build.VERSION_CODES.GINGERBREAD)
      private static Camera getDefaultCamera(int position) {
          // Find the total number of cameras available
          int  mNumberOfCameras = Camera.getNumberOfCameras();
  
          // Find the ID of the back-facing ("default") camera
          Camera.CameraInfo cameraInfo = new Camera.CameraInfo();
          for (int i = 0; i < mNumberOfCameras; i++) {
              Camera.getCameraInfo(i, cameraInfo);
              if (cameraInfo.facing == position) {
                  return Camera.open(i);
  
              }
          }
  
          return null;
      }
  
      /**
       * Creates a media file in the {@code Environment.DIRECTORY_PICTURES} directory. The directory
       * is persistent and available to other applications like gallery.
       *
       * @param type Media type. Can be video or image.
       * @return A file object pointing to the newly created file.
       */
      public  static File getOutputMediaFile(int type){
          // To be safe, you should check that the SDCard is mounted
          // using Environment.getExternalStorageState() before doing this.
          if (!Environment.getExternalStorageState().equalsIgnoreCase(Environment.MEDIA_MOUNTED)) {
              return  null;
          }
  
          File mediaStorageDir = new File(Environment.getExternalStoragePublicDirectory(
                  Environment.DIRECTORY_PICTURES), "CameraSample");
          // This location works best if you want the created images to be shared
          // between applications and persist after your app has been uninstalled.
  
          // Create the storage directory if it does not exist
          if (! mediaStorageDir.exists()){
              if (! mediaStorageDir.mkdirs()) {
                  Log.d("CameraSample", "failed to create directory");
                  return null;
              }
          }
  
          // Create a media file name
          String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.US).format(new Date());
          File mediaFile;
          if (type == MEDIA_TYPE_IMAGE){
              mediaFile = new File(mediaStorageDir.getPath() + File.separator +
                      "IMG_"+ timeStamp + ".jpg");
          } else if(type == MEDIA_TYPE_VIDEO) {
              mediaFile = new File(mediaStorageDir.getPath() + File.separator +
                      "VID_"+ timeStamp + ".mp4");
          } else {
              return null;
          }
  
          return mediaFile;
      }
  
  }
  