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