• 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/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