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