1 /*
2 * Copyright (C) 2009 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 //#define LOG_NDEBUG 0
18 #define LOG_TAG "MetaData"
19 #include <utils/Log.h>
20
21 #include <stdlib.h>
22 #include <string.h>
23
24 #include <media/stagefright/foundation/ADebug.h>
25 #include <media/stagefright/MetaData.h>
26
27 namespace android {
28
MetaData()29 MetaData::MetaData() {
30 }
31
MetaData(const MetaData & from)32 MetaData::MetaData(const MetaData &from)
33 : RefBase(),
34 mItems(from.mItems) {
35 }
36
~MetaData()37 MetaData::~MetaData() {
38 clear();
39 }
40
clear()41 void MetaData::clear() {
42 mItems.clear();
43 }
44
remove(uint32_t key)45 bool MetaData::remove(uint32_t key) {
46 ssize_t i = mItems.indexOfKey(key);
47
48 if (i < 0) {
49 return false;
50 }
51
52 mItems.removeItemsAt(i);
53
54 return true;
55 }
56
setCString(uint32_t key,const char * value)57 bool MetaData::setCString(uint32_t key, const char *value) {
58 return setData(key, TYPE_C_STRING, value, strlen(value) + 1);
59 }
60
setInt32(uint32_t key,int32_t value)61 bool MetaData::setInt32(uint32_t key, int32_t value) {
62 return setData(key, TYPE_INT32, &value, sizeof(value));
63 }
64
setInt64(uint32_t key,int64_t value)65 bool MetaData::setInt64(uint32_t key, int64_t value) {
66 return setData(key, TYPE_INT64, &value, sizeof(value));
67 }
68
setFloat(uint32_t key,float value)69 bool MetaData::setFloat(uint32_t key, float value) {
70 return setData(key, TYPE_FLOAT, &value, sizeof(value));
71 }
72
setPointer(uint32_t key,void * value)73 bool MetaData::setPointer(uint32_t key, void *value) {
74 return setData(key, TYPE_POINTER, &value, sizeof(value));
75 }
76
setRect(uint32_t key,int32_t left,int32_t top,int32_t right,int32_t bottom)77 bool MetaData::setRect(
78 uint32_t key,
79 int32_t left, int32_t top,
80 int32_t right, int32_t bottom) {
81 Rect r;
82 r.mLeft = left;
83 r.mTop = top;
84 r.mRight = right;
85 r.mBottom = bottom;
86
87 return setData(key, TYPE_RECT, &r, sizeof(r));
88 }
89
findCString(uint32_t key,const char ** value)90 bool MetaData::findCString(uint32_t key, const char **value) {
91 uint32_t type;
92 const void *data;
93 size_t size;
94 if (!findData(key, &type, &data, &size) || type != TYPE_C_STRING) {
95 return false;
96 }
97
98 *value = (const char *)data;
99
100 return true;
101 }
102
findInt32(uint32_t key,int32_t * value)103 bool MetaData::findInt32(uint32_t key, int32_t *value) {
104 uint32_t type;
105 const void *data;
106 size_t size;
107 if (!findData(key, &type, &data, &size) || type != TYPE_INT32) {
108 return false;
109 }
110
111 CHECK_EQ(size, sizeof(*value));
112
113 *value = *(int32_t *)data;
114
115 return true;
116 }
117
findInt64(uint32_t key,int64_t * value)118 bool MetaData::findInt64(uint32_t key, int64_t *value) {
119 uint32_t type;
120 const void *data;
121 size_t size;
122 if (!findData(key, &type, &data, &size) || type != TYPE_INT64) {
123 return false;
124 }
125
126 CHECK_EQ(size, sizeof(*value));
127
128 *value = *(int64_t *)data;
129
130 return true;
131 }
132
findFloat(uint32_t key,float * value)133 bool MetaData::findFloat(uint32_t key, float *value) {
134 uint32_t type;
135 const void *data;
136 size_t size;
137 if (!findData(key, &type, &data, &size) || type != TYPE_FLOAT) {
138 return false;
139 }
140
141 CHECK_EQ(size, sizeof(*value));
142
143 *value = *(float *)data;
144
145 return true;
146 }
147
findPointer(uint32_t key,void ** value)148 bool MetaData::findPointer(uint32_t key, void **value) {
149 uint32_t type;
150 const void *data;
151 size_t size;
152 if (!findData(key, &type, &data, &size) || type != TYPE_POINTER) {
153 return false;
154 }
155
156 CHECK_EQ(size, sizeof(*value));
157
158 *value = *(void **)data;
159
160 return true;
161 }
162
findRect(uint32_t key,int32_t * left,int32_t * top,int32_t * right,int32_t * bottom)163 bool MetaData::findRect(
164 uint32_t key,
165 int32_t *left, int32_t *top,
166 int32_t *right, int32_t *bottom) {
167 uint32_t type;
168 const void *data;
169 size_t size;
170 if (!findData(key, &type, &data, &size) || type != TYPE_RECT) {
171 return false;
172 }
173
174 CHECK_EQ(size, sizeof(Rect));
175
176 const Rect *r = (const Rect *)data;
177 *left = r->mLeft;
178 *top = r->mTop;
179 *right = r->mRight;
180 *bottom = r->mBottom;
181
182 return true;
183 }
184
setData(uint32_t key,uint32_t type,const void * data,size_t size)185 bool MetaData::setData(
186 uint32_t key, uint32_t type, const void *data, size_t size) {
187 bool overwrote_existing = true;
188
189 ssize_t i = mItems.indexOfKey(key);
190 if (i < 0) {
191 typed_data item;
192 i = mItems.add(key, item);
193
194 overwrote_existing = false;
195 }
196
197 typed_data &item = mItems.editValueAt(i);
198
199 item.setData(type, data, size);
200
201 return overwrote_existing;
202 }
203
findData(uint32_t key,uint32_t * type,const void ** data,size_t * size) const204 bool MetaData::findData(uint32_t key, uint32_t *type,
205 const void **data, size_t *size) const {
206 ssize_t i = mItems.indexOfKey(key);
207
208 if (i < 0) {
209 return false;
210 }
211
212 const typed_data &item = mItems.valueAt(i);
213
214 item.getData(type, data, size);
215
216 return true;
217 }
218
typed_data()219 MetaData::typed_data::typed_data()
220 : mType(0),
221 mSize(0) {
222 }
223
~typed_data()224 MetaData::typed_data::~typed_data() {
225 clear();
226 }
227
typed_data(const typed_data & from)228 MetaData::typed_data::typed_data(const typed_data &from)
229 : mType(from.mType),
230 mSize(0) {
231 allocateStorage(from.mSize);
232 memcpy(storage(), from.storage(), mSize);
233 }
234
operator =(const MetaData::typed_data & from)235 MetaData::typed_data &MetaData::typed_data::operator=(
236 const MetaData::typed_data &from) {
237 if (this != &from) {
238 clear();
239 mType = from.mType;
240 allocateStorage(from.mSize);
241 memcpy(storage(), from.storage(), mSize);
242 }
243
244 return *this;
245 }
246
clear()247 void MetaData::typed_data::clear() {
248 freeStorage();
249
250 mType = 0;
251 }
252
setData(uint32_t type,const void * data,size_t size)253 void MetaData::typed_data::setData(
254 uint32_t type, const void *data, size_t size) {
255 clear();
256
257 mType = type;
258 allocateStorage(size);
259 memcpy(storage(), data, size);
260 }
261
getData(uint32_t * type,const void ** data,size_t * size) const262 void MetaData::typed_data::getData(
263 uint32_t *type, const void **data, size_t *size) const {
264 *type = mType;
265 *size = mSize;
266 *data = storage();
267 }
268
allocateStorage(size_t size)269 void MetaData::typed_data::allocateStorage(size_t size) {
270 mSize = size;
271
272 if (usesReservoir()) {
273 return;
274 }
275
276 u.ext_data = malloc(mSize);
277 }
278
freeStorage()279 void MetaData::typed_data::freeStorage() {
280 if (!usesReservoir()) {
281 if (u.ext_data) {
282 free(u.ext_data);
283 }
284 }
285
286 mSize = 0;
287 }
288
asString() const289 String8 MetaData::typed_data::asString() const {
290 String8 out;
291 const void *data = storage();
292 switch(mType) {
293 case TYPE_NONE:
294 out = String8::format("no type, size %d)", mSize);
295 break;
296 case TYPE_C_STRING:
297 out = String8::format("(char*) %s", (const char *)data);
298 break;
299 case TYPE_INT32:
300 out = String8::format("(int32_t) %d", *(int32_t *)data);
301 break;
302 case TYPE_INT64:
303 out = String8::format("(int64_t) %lld", *(int64_t *)data);
304 break;
305 case TYPE_FLOAT:
306 out = String8::format("(float) %f", *(float *)data);
307 break;
308 case TYPE_POINTER:
309 out = String8::format("(void*) %p", *(void **)data);
310 break;
311 case TYPE_RECT:
312 {
313 const Rect *r = (const Rect *)data;
314 out = String8::format("Rect(%d, %d, %d, %d)",
315 r->mLeft, r->mTop, r->mRight, r->mBottom);
316 break;
317 }
318
319 default:
320 out = String8::format("(unknown type %d, size %d)", mType, mSize);
321 break;
322 }
323 return out;
324 }
325
MakeFourCCString(uint32_t x,char * s)326 static void MakeFourCCString(uint32_t x, char *s) {
327 s[0] = x >> 24;
328 s[1] = (x >> 16) & 0xff;
329 s[2] = (x >> 8) & 0xff;
330 s[3] = x & 0xff;
331 s[4] = '\0';
332 }
333
dumpToLog() const334 void MetaData::dumpToLog() const {
335 for (int i = mItems.size(); --i >= 0;) {
336 int32_t key = mItems.keyAt(i);
337 char cc[5];
338 MakeFourCCString(key, cc);
339 const typed_data &item = mItems.valueAt(i);
340 ALOGI("%s: %s", cc, item.asString().string());
341 }
342 }
343
344 } // namespace android
345
346