C++程序  |  653行  |  18.91 KB

/* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above
 *       copyright notice, this list of conditions and the following
 *       disclaimer in the documentation and/or other materials provided
 *       with the distribution.
 *     * Neither the name of The Linux Foundation nor the names of its
 *       contributors may be used to endorse or promote products derived
 *       from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 */

// System dependencies
#include <pthread.h>
#include <string.h>
#include <math.h>

// JPEG dependencies
#include "mm_jpeg_dbg.h"
#include "mm_jpeg.h"


#define LOWER(a)               ((a) & 0xFFFF)
#define UPPER(a)               (((a)>>16) & 0xFFFF)
#define CHANGE_ENDIAN_16(a)  ((0x00FF & ((a)>>8)) | (0xFF00 & ((a)<<8)))
#define ROUND(a) \
        ((a >= 0) ? (uint32_t)(a + 0.5) : (uint32_t)(a - 0.5))


/** addExifEntry:
 *
 *  Arguments:
 *   @exif_info : Exif info struct
 *   @p_session: job session
 *   @tagid   : exif tag ID
 *   @type    : data type
 *   @count   : number of data in uint of its type
 *   @data    : input data ptr
 *
 *  Retrun     : int32_t type of status
 *               0  -- success
 *              none-zero failure code
 *
 *  Description:
 *       Function to add an entry to exif data
 *
 **/
int32_t addExifEntry(QOMX_EXIF_INFO *p_exif_info, exif_tag_id_t tagid,
  exif_tag_type_t type, uint32_t count, void *data)
{
    int32_t rc = 0;
    uint32_t numOfEntries = (uint32_t)p_exif_info->numOfEntries;
    QEXIF_INFO_DATA *p_info_data = p_exif_info->exif_data;
    if(numOfEntries >= MAX_EXIF_TABLE_ENTRIES) {
        LOGE("Number of entries exceeded limit");
        return -1;
    }

    p_info_data[numOfEntries].tag_id = tagid;
    p_info_data[numOfEntries].tag_entry.type = type;
    p_info_data[numOfEntries].tag_entry.count = count;
    p_info_data[numOfEntries].tag_entry.copy = 1;
    switch (type) {
    case EXIF_BYTE: {
      if (count > 1) {
        uint8_t *values = (uint8_t *)malloc(count);
        if (values == NULL) {
          LOGE("No memory for byte array");
          rc = -1;
        } else {
          memcpy(values, data, count);
          p_info_data[numOfEntries].tag_entry.data._bytes = values;
        }
      } else {
        p_info_data[numOfEntries].tag_entry.data._byte = *(uint8_t *)data;
      }
    }
    break;
    case EXIF_ASCII: {
      char *str = NULL;
      str = (char *)malloc(count + 1);
      if (str == NULL) {
        LOGE("No memory for ascii string");
        rc = -1;
      } else {
        memset(str, 0, count + 1);
        memcpy(str, data, count);
        p_info_data[numOfEntries].tag_entry.data._ascii = str;
      }
    }
    break;
    case EXIF_SHORT: {
      if (count > 1) {
        uint16_t *values = (uint16_t *)malloc(count * sizeof(uint16_t));
        if (values == NULL) {
          LOGE("No memory for short array");
          rc = -1;
        } else {
          memcpy(values, data, count * sizeof(uint16_t));
          p_info_data[numOfEntries].tag_entry.data._shorts = values;
        }
      } else {
        p_info_data[numOfEntries].tag_entry.data._short = *(uint16_t *)data;
      }
    }
    break;
    case EXIF_LONG: {
      if (count > 1) {
        uint32_t *values = (uint32_t *)malloc(count * sizeof(uint32_t));
        if (values == NULL) {
          LOGE("No memory for long array");
          rc = -1;
        } else {
          memcpy(values, data, count * sizeof(uint32_t));
          p_info_data[numOfEntries].tag_entry.data._longs = values;
        }
      } else {
        p_info_data[numOfEntries].tag_entry.data._long = *(uint32_t *)data;
      }
    }
    break;
    case EXIF_RATIONAL: {
      if (count > 1) {
        rat_t *values = (rat_t *)malloc(count * sizeof(rat_t));
        if (values == NULL) {
          LOGE("No memory for rational array");
          rc = -1;
        } else {
          memcpy(values, data, count * sizeof(rat_t));
          p_info_data[numOfEntries].tag_entry.data._rats = values;
        }
      } else {
        p_info_data[numOfEntries].tag_entry.data._rat = *(rat_t *)data;
      }
    }
    break;
    case EXIF_UNDEFINED: {
      uint8_t *values = (uint8_t *)malloc(count);
      if (values == NULL) {
        LOGE("No memory for undefined array");
        rc = -1;
      } else {
        memcpy(values, data, count);
        p_info_data[numOfEntries].tag_entry.data._undefined = values;
      }
    }
    break;
    case EXIF_SLONG: {
      if (count > 1) {
        int32_t *values = (int32_t *)malloc(count * sizeof(int32_t));
        if (values == NULL) {
          LOGE("No memory for signed long array");
          rc = -1;
        } else {
          memcpy(values, data, count * sizeof(int32_t));
          p_info_data[numOfEntries].tag_entry.data._slongs = values;
        }
      } else {
        p_info_data[numOfEntries].tag_entry.data._slong = *(int32_t *)data;
      }
    }
    break;
    case EXIF_SRATIONAL: {
      if (count > 1) {
        srat_t *values = (srat_t *)malloc(count * sizeof(srat_t));
        if (values == NULL) {
          LOGE("No memory for signed rational array");
          rc = -1;
        } else {
          memcpy(values, data, count * sizeof(srat_t));
          p_info_data[numOfEntries].tag_entry.data._srats = values;
        }
      } else {
        p_info_data[numOfEntries].tag_entry.data._srat = *(srat_t *)data;
      }
    }
    break;
    }

    // Increase number of entries
    p_exif_info->numOfEntries++;
    return rc;
}

/** releaseExifEntry
 *
 *  Arguments:
 *   @p_exif_data : Exif info struct
 *
 *  Retrun     : int32_t type of status
 *               0  -- success
 *              none-zero failure code
 *
 *  Description:
 *       Function to release an entry from exif data
 *
 **/
int32_t releaseExifEntry(QEXIF_INFO_DATA *p_exif_data)
{
 switch (p_exif_data->tag_entry.type) {
  case EXIF_BYTE: {
    if (p_exif_data->tag_entry.count > 1 &&
      p_exif_data->tag_entry.data._bytes != NULL) {
      free(p_exif_data->tag_entry.data._bytes);
      p_exif_data->tag_entry.data._bytes = NULL;
    }
  }
  break;
  case EXIF_ASCII: {
    if (p_exif_data->tag_entry.data._ascii != NULL) {
      free(p_exif_data->tag_entry.data._ascii);
      p_exif_data->tag_entry.data._ascii = NULL;
    }
  }
  break;
  case EXIF_SHORT: {
    if (p_exif_data->tag_entry.count > 1 &&
      p_exif_data->tag_entry.data._shorts != NULL) {
      free(p_exif_data->tag_entry.data._shorts);
      p_exif_data->tag_entry.data._shorts = NULL;
    }
  }
  break;
  case EXIF_LONG: {
    if (p_exif_data->tag_entry.count > 1 &&
      p_exif_data->tag_entry.data._longs != NULL) {
      free(p_exif_data->tag_entry.data._longs);
      p_exif_data->tag_entry.data._longs = NULL;
    }
  }
  break;
  case EXIF_RATIONAL: {
    if (p_exif_data->tag_entry.count > 1 &&
      p_exif_data->tag_entry.data._rats != NULL) {
      free(p_exif_data->tag_entry.data._rats);
      p_exif_data->tag_entry.data._rats = NULL;
    }
  }
  break;
  case EXIF_UNDEFINED: {
    if (p_exif_data->tag_entry.data._undefined != NULL) {
      free(p_exif_data->tag_entry.data._undefined);
      p_exif_data->tag_entry.data._undefined = NULL;
    }
  }
  break;
  case EXIF_SLONG: {
    if (p_exif_data->tag_entry.count > 1 &&
      p_exif_data->tag_entry.data._slongs != NULL) {
      free(p_exif_data->tag_entry.data._slongs);
      p_exif_data->tag_entry.data._slongs = NULL;
    }
  }
  break;
  case EXIF_SRATIONAL: {
    if (p_exif_data->tag_entry.count > 1 &&
      p_exif_data->tag_entry.data._srats != NULL) {
      free(p_exif_data->tag_entry.data._srats);
      p_exif_data->tag_entry.data._srats = NULL;
    }
  }
  break;
  } /*end of switch*/

  return 0;
}

/** process_sensor_data:
 *
 *  Arguments:
 *   @p_sensor_params : ptr to sensor data
 *
 *  Return     : int32_t type of status
 *               NO_ERROR  -- success
 *              none-zero failure code
 *
 *  Description:
 *       process sensor data
 *
 *  Notes: this needs to be filled for the metadata
 **/
int process_sensor_data(cam_sensor_params_t *p_sensor_params,
  QOMX_EXIF_INFO *exif_info)
{
  int rc = 0;
  rat_t val_rat;

  if (NULL == p_sensor_params) {
    LOGE("Sensor params are null");
    return 0;
  }

  LOGD("From metadata aperture = %f ",
    p_sensor_params->aperture_value );

  if (p_sensor_params->aperture_value >= 1.0) {
    double apex_value;
    apex_value = (double)2.0 * log(p_sensor_params->aperture_value) / log(2.0);
    val_rat.num = (uint32_t)(apex_value * 100);
    val_rat.denom = 100;
    rc = addExifEntry(exif_info, EXIFTAGID_APERTURE, EXIF_RATIONAL, 1, &val_rat);
    if (rc) {
      LOGE(": Error adding Exif Entry");
    }

    val_rat.num = (uint32_t)(p_sensor_params->aperture_value * 100);
    val_rat.denom = 100;
    rc = addExifEntry(exif_info, EXIFTAGID_F_NUMBER, EXIF_RATIONAL, 1, &val_rat);
    if (rc) {
      LOGE(": Error adding Exif Entry");
    }
  }

  /*Flash*/
  short val_short = 0;
  int flash_mode_exif, flash_fired;
  if (p_sensor_params->flash_state == CAM_FLASH_STATE_FIRED) {
    flash_fired = 1;
  } else {
    flash_fired = 0;
  }
  LOGD("Flash mode %d flash state %d",
    p_sensor_params->flash_mode, p_sensor_params->flash_state);

  switch(p_sensor_params->flash_mode) {
  case  CAM_FLASH_MODE_OFF:
    flash_mode_exif = MM_JPEG_EXIF_FLASH_MODE_OFF;
    break;
  case CAM_FLASH_MODE_ON:
    flash_mode_exif = MM_JPEG_EXIF_FLASH_MODE_ON;
    break;
  case CAM_FLASH_MODE_AUTO:
    flash_mode_exif = MM_JPEG_EXIF_FLASH_MODE_AUTO;
    break;
  default:
    flash_mode_exif = MM_JPEG_EXIF_FLASH_MODE_AUTO;
    LOGE(": Unsupported flash mode");
  }
  val_short = (short)(flash_fired | (flash_mode_exif << 3));

  rc = addExifEntry(exif_info, EXIFTAGID_FLASH, EXIF_SHORT, 1, &val_short);
  if (rc) {
    LOGE(": Error adding flash exif entry");
  }
  /* Sensing Method */
  val_short = (short) p_sensor_params->sensing_method;
  rc = addExifEntry(exif_info, EXIFTAGID_SENSING_METHOD, EXIF_SHORT,
    sizeof(val_short)/2, &val_short);
  if (rc) {
    LOGE(": Error adding flash Exif Entry");
  }

  /* Focal Length in 35 MM Film */
  val_short = (short)
    ((p_sensor_params->focal_length * p_sensor_params->crop_factor) + 0.5f);
  rc = addExifEntry(exif_info, EXIFTAGID_FOCAL_LENGTH_35MM, EXIF_SHORT,
    1, &val_short);
  if (rc) {
    LOGE(": Error adding Exif Entry");
  }

  /* F Number */
  val_rat.num = (uint32_t)(p_sensor_params->f_number * 100);
  val_rat.denom = 100;
  rc = addExifEntry(exif_info, EXIFTAGTYPE_F_NUMBER, EXIF_RATIONAL, 1, &val_rat);
  if (rc) {
    LOGE(": Error adding Exif Entry");
  }
  return rc;
}


/** process_3a_data:
 *
 *  Arguments:
 *   @p_3a_params : ptr to 3a data
 *   @exif_info : Exif info struct
 *
 *  Return     : int32_t type of status
 *               NO_ERROR  -- success
 *               none-zero failure code
 *
 *  Description:
 *       process 3a data
 *
 *  Notes: this needs to be filled for the metadata
 **/
int process_3a_data(cam_3a_params_t *p_3a_params, QOMX_EXIF_INFO *exif_info)
{
  int rc = 0;
  srat_t val_srat;
  rat_t val_rat;
  double shutter_speed_value;

  if (NULL == p_3a_params) {
    LOGE("3A params are null");
    return 0;
  }

  LOGD("exp_time %f, iso_value %d, wb_mode %d",
    p_3a_params->exp_time, p_3a_params->iso_value, p_3a_params->wb_mode);

  /* Exposure time */
  if (p_3a_params->exp_time <= 0.0f) {
    val_rat.num = 0;
    val_rat.denom = 0;
  } else if (p_3a_params->exp_time < 1.0f) {
    val_rat.num = 1;
    val_rat.denom = ROUND(1.0/p_3a_params->exp_time);
  } else {
    val_rat.num = ROUND(p_3a_params->exp_time);
    val_rat.denom = 1;
  }
  LOGD("numer %d denom %d %zd", val_rat.num, val_rat.denom,
    sizeof(val_rat) / (8));

  rc = addExifEntry(exif_info, EXIFTAGID_EXPOSURE_TIME, EXIF_RATIONAL,
    (sizeof(val_rat)/(8)), &val_rat);
  if (rc) {
    LOGE(": Error adding Exif Entry Exposure time");
  }

  /* Shutter Speed*/
  if (p_3a_params->exp_time > 0) {
    shutter_speed_value = log10(1/p_3a_params->exp_time)/log10(2);
    val_srat.num = (int32_t)(shutter_speed_value * 1000);
    val_srat.denom = 1000;
  } else {
    val_srat.num = 0;
    val_srat.denom = 0;
  }
  rc = addExifEntry(exif_info, EXIFTAGID_SHUTTER_SPEED, EXIF_SRATIONAL,
    (sizeof(val_srat)/(8)), &val_srat);
  if (rc) {
    LOGE(": Error adding Exif Entry");
  }

  /*ISO*/
  short val_short;
  val_short = (short)p_3a_params->iso_value;
  rc = addExifEntry(exif_info, EXIFTAGID_ISO_SPEED_RATING, EXIF_SHORT,
    sizeof(val_short)/2, &val_short);
  if (rc) {
     LOGE(": Error adding Exif Entry");
  }

  /*WB mode*/
  if (p_3a_params->wb_mode == CAM_WB_MODE_AUTO)
    val_short = 0;
  else
    val_short = 1;
  rc = addExifEntry(exif_info, EXIFTAGID_WHITE_BALANCE, EXIF_SHORT,
    sizeof(val_short)/2, &val_short);
  if (rc) {
    LOGE(": Error adding Exif Entry");
  }

  /* Metering Mode   */
  val_short = (short) p_3a_params->metering_mode;
  rc = addExifEntry(exif_info,EXIFTAGID_METERING_MODE, EXIF_SHORT,
     sizeof(val_short)/2, &val_short);
  if (rc) {
     LOGE(": Error adding Exif Entry");
   }

  /*Exposure Program*/
   val_short = (short) p_3a_params->exposure_program;
   rc = addExifEntry(exif_info,EXIFTAGID_EXPOSURE_PROGRAM, EXIF_SHORT,
      sizeof(val_short)/2, &val_short);
   if (rc) {
      LOGE(": Error adding Exif Entry");
    }

   /*Exposure Mode */
    val_short = (short) p_3a_params->exposure_mode;
    rc = addExifEntry(exif_info,EXIFTAGID_EXPOSURE_MODE, EXIF_SHORT,
       sizeof(val_short)/2, &val_short);
    if (rc) {
       LOGE(": Error adding Exif Entry");
     }

    /*Scenetype*/
     uint8_t val_undef;
     val_undef = (uint8_t) p_3a_params->scenetype;
     rc = addExifEntry(exif_info,EXIFTAGID_SCENE_TYPE, EXIF_UNDEFINED,
        sizeof(val_undef), &val_undef);
     if (rc) {
        LOGE(": Error adding Exif Entry");
      }

     LOGD("brightness %f",
       p_3a_params->brightness);

    /* Brightness Value*/
     val_srat.num = (int32_t) (p_3a_params->brightness * 100.0f);
     val_srat.denom = 100;
     rc = addExifEntry(exif_info,EXIFTAGID_BRIGHTNESS, EXIF_SRATIONAL,
                 (sizeof(val_srat)/(8)), &val_srat);
     if (rc) {
        LOGE(": Error adding Exif Entry");
     }

  return rc;
}

/** process_meta_data
 *
 *  Arguments:
 *   @p_meta : ptr to metadata
 *   @exif_info: Exif info struct
 *   @mm_jpeg_exif_params: exif params
 *
 *  Return     : int32_t type of status
 *               NO_ERROR  -- success
 *              none-zero failure code
 *
 *  Description:
 *       Extract exif data from the metadata
 **/
int process_meta_data(metadata_buffer_t *p_meta, QOMX_EXIF_INFO *exif_info,
  mm_jpeg_exif_params_t *p_cam_exif_params, cam_hal_version_t hal_version)
{
  int rc = 0;
  cam_sensor_params_t p_sensor_params;
  cam_3a_params_t p_3a_params;
  bool is_3a_meta_valid = false, is_sensor_meta_valid = false;

  memset(&p_3a_params,  0,  sizeof(cam_3a_params_t));
  memset(&p_sensor_params, 0, sizeof(cam_sensor_params_t));

  if (p_meta) {
    /* for HAL V1*/
    if (hal_version == CAM_HAL_V1) {

      IF_META_AVAILABLE(cam_3a_params_t, l_3a_params, CAM_INTF_META_AEC_INFO,
          p_meta) {
        p_3a_params = *l_3a_params;
        is_3a_meta_valid = true;
      }

      IF_META_AVAILABLE(int32_t, wb_mode, CAM_INTF_PARM_WHITE_BALANCE, p_meta) {
        p_3a_params.wb_mode = *wb_mode;
      }

      IF_META_AVAILABLE(cam_sensor_params_t, l_sensor_params,
          CAM_INTF_META_SENSOR_INFO, p_meta) {
        p_sensor_params = *l_sensor_params;
        is_sensor_meta_valid = true;
      }
    } else {
      /* HAL V3 */
      IF_META_AVAILABLE(int32_t, iso, CAM_INTF_META_SENSOR_SENSITIVITY, p_meta) {
        p_3a_params.iso_value= *iso;
      } else {
        LOGE("Cannot extract Iso value");
      }

      IF_META_AVAILABLE(int64_t, sensor_exposure_time,
          CAM_INTF_META_SENSOR_EXPOSURE_TIME, p_meta) {
        p_3a_params.exp_time =
          (float)((double)(*sensor_exposure_time) / 1000000000.0);
      } else {
        LOGE("Cannot extract Exp time value");
      }

      IF_META_AVAILABLE(int32_t, wb_mode, CAM_INTF_PARM_WHITE_BALANCE, p_meta) {
        p_3a_params.wb_mode = *wb_mode;
      } else {
        LOGE("Cannot extract white balance mode");
      }

      /* Process sensor data */
      IF_META_AVAILABLE(float, aperture, CAM_INTF_META_LENS_APERTURE, p_meta) {
        p_sensor_params.aperture_value = *aperture;
      } else {
        LOGE("Cannot extract Aperture value");
      }

      IF_META_AVAILABLE(uint32_t, flash_mode, CAM_INTF_META_FLASH_MODE, p_meta) {
        p_sensor_params.flash_mode = *flash_mode;
      } else {
        LOGE("Cannot extract flash mode value");
      }

      IF_META_AVAILABLE(int32_t, flash_state, CAM_INTF_META_FLASH_STATE, p_meta) {
        p_sensor_params.flash_state = (cam_flash_state_t) *flash_state;
      } else {
        LOGE("Cannot extract flash state value");
      }
    }
  }

  /* take the cached values if meta is invalid */
  if ((!is_3a_meta_valid) && (hal_version == CAM_HAL_V1)) {
    p_3a_params = p_cam_exif_params->cam_3a_params;
    LOGW("Warning using cached values for 3a");
  }

  if ((!is_sensor_meta_valid) && (hal_version == CAM_HAL_V1)) {
    p_sensor_params = p_cam_exif_params->sensor_params;
    LOGW("Warning using cached values for sensor");
  }

  if ((hal_version != CAM_HAL_V1) || (p_sensor_params.sens_type != CAM_SENSOR_YUV)) {
    rc = process_3a_data(&p_3a_params, exif_info);
    if (rc) {
      LOGE("Failed to add 3a exif params");
    }
  }

  rc = process_sensor_data(&p_sensor_params, exif_info);
  if (rc) {
    LOGE("Failed to extract sensor params");
  }

  if (p_meta) {
    short val_short = 0;
    cam_asd_decision_t *scene_info = NULL;

    IF_META_AVAILABLE(cam_asd_decision_t, scene_cap_type,
        CAM_INTF_META_ASD_SCENE_INFO, p_meta) {
      scene_info = (cam_asd_decision_t*)scene_cap_type;
      val_short = (short) scene_info->detected_scene;
    }

    rc = addExifEntry(exif_info, EXIFTAGID_SCENE_CAPTURE_TYPE, EXIF_SHORT,
      sizeof(val_short)/2, &val_short);
    if (rc) {
      LOGE(": Error adding ASD Exif Entry");
    }
  } else {
    LOGE(": Error adding ASD Exif Entry, no meta");
  }
  return rc;
}