• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
Metadata()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 
~Metadata()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 
Metadata(uint8_t mode,uint8_t intent)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 
addUInt8(uint32_t tag,int count,uint8_t * data)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 
addInt32(uint32_t tag,int count,int32_t * data)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 
addFloat(uint32_t tag,int count,float * data)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 
addInt64(uint32_t tag,int count,int64_t * data)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 
addDouble(uint32_t tag,int count,double * data)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 
addRational(uint32_t tag,int count,camera_metadata_rational_t * data)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 
validate(uint32_t tag,int tag_type,int count)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 
add(uint32_t tag,int count,void * tag_data)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 
generate()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 
Entry(uint32_t tag,void * data,int count)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 
push(Entry * e)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 
~Entry()227 Metadata::Entry::~Entry()
228 {
229     if (mNext != NULL)
230         mNext->mPrev = mPrev;
231     if (mPrev != NULL)
232         mPrev->mNext = mNext;
233 }
234 
insertAfter(Entry * e)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