Home | History | Annotate | Download | only in camera
      1 /*
      2  * Copyright (C) 2013 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #include <pthread.h>
     18 #include <system/camera_metadata.h>
     19 
     20 //#define LOG_NDEBUG 0
     21 #define LOG_TAG "Metadata"
     22 #include <cutils/log.h>
     23 
     24 #define ATRACE_TAG (ATRACE_TAG_CAMERA | ATRACE_TAG_HAL)
     25 #include <cutils/trace.h>
     26 #include "ScopedTrace.h"
     27 
     28 #include "Metadata.h"
     29 
     30 namespace default_camera_hal {
     31 
     32 Metadata::Metadata()
     33   : mHead(NULL),
     34     mTail(NULL),
     35     mEntryCount(0),
     36     mDataCount(0),
     37     mGenerated(NULL),
     38     mDirty(true)
     39 {
     40     // NULL (default) pthread mutex attributes
     41     pthread_mutex_init(&mMutex, NULL);
     42 }
     43 
     44 Metadata::~Metadata()
     45 {
     46     Entry *current = mHead;
     47 
     48     while (current != NULL) {
     49         Entry *tmp = current;
     50         current = current->mNext;
     51         delete tmp;
     52     }
     53 
     54     if (mGenerated != NULL)
     55         free_camera_metadata(mGenerated);
     56 
     57     pthread_mutex_destroy(&mMutex);
     58 }
     59 
     60 Metadata::Metadata(uint8_t mode, uint8_t intent)
     61   : mHead(NULL),
     62     mTail(NULL),
     63     mEntryCount(0),
     64     mDataCount(0),
     65     mGenerated(NULL),
     66     mDirty(true)
     67 {
     68     pthread_mutex_init(&mMutex, NULL);
     69 
     70     if (validate(ANDROID_CONTROL_MODE, TYPE_BYTE, 1)) {
     71         int res = add(ANDROID_CONTROL_MODE, 1, &mode);
     72         if (res != 0) {
     73             ALOGE("%s: Unable to add mode to template!", __func__);
     74         }
     75     } else {
     76         ALOGE("%s: Invalid mode constructing template!", __func__);
     77     }
     78 
     79     if (validate(ANDROID_CONTROL_CAPTURE_INTENT, TYPE_BYTE, 1)) {
     80         int res = add(ANDROID_CONTROL_CAPTURE_INTENT, 1, &intent);
     81         if (res != 0) {
     82             ALOGE("%s: Unable to add capture intent to template!", __func__);
     83         }
     84     } else {
     85         ALOGE("%s: Invalid capture intent constructing template!", __func__);
     86     }
     87 }
     88 
     89 int Metadata::addUInt8(uint32_t tag, int count, uint8_t *data)
     90 {
     91     if (!validate(tag, TYPE_BYTE, count)) return -EINVAL;
     92     return add(tag, count, data);
     93 }
     94 
     95 int Metadata::addInt32(uint32_t tag, int count, int32_t *data)
     96 {
     97     if (!validate(tag, TYPE_INT32, count)) return -EINVAL;
     98     return add(tag, count, data);
     99 }
    100 
    101 int Metadata::addFloat(uint32_t tag, int count, float *data)
    102 {
    103     if (!validate(tag, TYPE_FLOAT, count)) return -EINVAL;
    104     return add(tag, count, data);
    105 }
    106 
    107 int Metadata::addInt64(uint32_t tag, int count, int64_t *data)
    108 {
    109     if (!validate(tag, TYPE_INT64, count)) return -EINVAL;
    110     return add(tag, count, data);
    111 }
    112 
    113 int Metadata::addDouble(uint32_t tag, int count, double *data)
    114 {
    115     if (!validate(tag, TYPE_DOUBLE, count)) return -EINVAL;
    116     return add(tag, count, data);
    117 }
    118 
    119 int Metadata::addRational(uint32_t tag, int count,
    120         camera_metadata_rational_t *data)
    121 {
    122     if (!validate(tag, TYPE_RATIONAL, count)) return -EINVAL;
    123     return add(tag, count, data);
    124 }
    125 
    126 bool Metadata::validate(uint32_t tag, int tag_type, int count)
    127 {
    128     if (get_camera_metadata_tag_type(tag) < 0) {
    129         ALOGE("%s: Invalid metadata entry tag: %d", __func__, tag);
    130         return false;
    131     }
    132     if (tag_type < 0 || tag_type >= NUM_TYPES) {
    133         ALOGE("%s: Invalid metadata entry tag type: %d", __func__, tag_type);
    134         return false;
    135     }
    136     if (tag_type != get_camera_metadata_tag_type(tag)) {
    137         ALOGE("%s: Tag %d called with incorrect type: %s(%d)", __func__, tag,
    138                 camera_metadata_type_names[tag_type], tag_type);
    139         return false;
    140     }
    141     if (count < 1) {
    142         ALOGE("%s: Invalid metadata entry count: %d", __func__, count);
    143         return false;
    144     }
    145     return true;
    146 }
    147 
    148 int Metadata::add(uint32_t tag, int count, void *tag_data)
    149 {
    150     int tag_type = get_camera_metadata_tag_type(tag);
    151     size_t type_sz = camera_metadata_type_size[tag_type];
    152 
    153     // Allocate array to hold new metadata
    154     void *data = malloc(count * type_sz);
    155     if (data == NULL)
    156         return -ENOMEM;
    157     memcpy(data, tag_data, count * type_sz);
    158 
    159     pthread_mutex_lock(&mMutex);
    160     mEntryCount++;
    161     mDataCount += calculate_camera_metadata_entry_data_size(tag_type, count);
    162     push(new Entry(tag, data, count));
    163     mDirty = true;
    164     pthread_mutex_unlock(&mMutex);
    165     return 0;
    166 }
    167 
    168 camera_metadata_t* Metadata::generate()
    169 {
    170     pthread_mutex_lock(&mMutex);
    171     // Reuse if old generated metadata still valid
    172     if (!mDirty && mGenerated != NULL) {
    173         ALOGV("%s: Reusing generated metadata at %p", __func__, mGenerated);
    174         goto out;
    175     }
    176     // Destroy old metadata
    177     if (mGenerated != NULL) {
    178         ALOGV("%s: Freeing generated metadata at %p", __func__, mGenerated);
    179         free_camera_metadata(mGenerated);
    180         mGenerated = NULL;
    181     }
    182     // Generate new metadata structure
    183     ALOGV("%s: Generating new camera metadata structure, Entries:%d Data:%d",
    184             __func__, mEntryCount, mDataCount);
    185     mGenerated = allocate_camera_metadata(mEntryCount, mDataCount);
    186     if (mGenerated == NULL) {
    187         ALOGE("%s: Failed to allocate metadata (%d entries %d data)",
    188                 __func__, mEntryCount, mDataCount);
    189         goto out;
    190     }
    191     // Walk list of entries adding each one to newly allocated metadata
    192     for (Entry *current = mHead; current != NULL; current = current->mNext) {
    193         int res = add_camera_metadata_entry(mGenerated, current->mTag,
    194                 current->mData, current->mCount);
    195         if (res != 0) {
    196             ALOGE("%s: Failed to add camera metadata: %d", __func__, res);
    197             free_camera_metadata(mGenerated);
    198             mGenerated = NULL;
    199             goto out;
    200         }
    201     }
    202 
    203 out:
    204     pthread_mutex_unlock(&mMutex);
    205     return mGenerated;
    206 }
    207 
    208 Metadata::Entry::Entry(uint32_t tag, void *data, int count)
    209   : mNext(NULL),
    210     mPrev(NULL),
    211     mTag(tag),
    212     mData(data),
    213     mCount(count)
    214 {
    215 }
    216 
    217 void Metadata::push(Entry *e)
    218 {
    219     if (mHead == NULL) {
    220         mHead = mTail = e;
    221     } else {
    222         mTail->insertAfter(e);
    223         mTail = e;
    224     }
    225 }
    226 
    227 Metadata::Entry::~Entry()
    228 {
    229     if (mNext != NULL)
    230         mNext->mPrev = mPrev;
    231     if (mPrev != NULL)
    232         mPrev->mNext = mNext;
    233 }
    234 
    235 void Metadata::Entry::insertAfter(Entry *e)
    236 {
    237     if (e == NULL)
    238         return;
    239     if (mNext != NULL)
    240         mNext->mPrev = e;
    241     e->mNext = mNext;
    242     e->mPrev = this;
    243     mNext = e;
    244 }
    245 
    246 } // namespace default_camera_hal
    247