MetaData.cpp revision feba11fd788c99b0b63e0bce724730817688d82f
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
27namespace android {
28
29MetaData::MetaData() {
30}
31
32MetaData::MetaData(const MetaData &from)
33    : RefBase(),
34      mItems(from.mItems) {
35}
36
37MetaData::~MetaData() {
38    clear();
39}
40
41void MetaData::clear() {
42    mItems.clear();
43}
44
45bool 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
57bool MetaData::setCString(uint32_t key, const char *value) {
58    return setData(key, TYPE_C_STRING, value, strlen(value) + 1);
59}
60
61bool MetaData::setInt32(uint32_t key, int32_t value) {
62    return setData(key, TYPE_INT32, &value, sizeof(value));
63}
64
65bool MetaData::setInt64(uint32_t key, int64_t value) {
66    return setData(key, TYPE_INT64, &value, sizeof(value));
67}
68
69bool MetaData::setFloat(uint32_t key, float value) {
70    return setData(key, TYPE_FLOAT, &value, sizeof(value));
71}
72
73bool MetaData::setPointer(uint32_t key, void *value) {
74    return setData(key, TYPE_POINTER, &value, sizeof(value));
75}
76
77bool 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
90bool 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
103bool 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
118bool 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
133bool 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
148bool 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
163bool 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
185bool 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
204bool 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
219MetaData::typed_data::typed_data()
220    : mType(0),
221      mSize(0) {
222}
223
224MetaData::typed_data::~typed_data() {
225    clear();
226}
227
228MetaData::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
235MetaData::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
247void MetaData::typed_data::clear() {
248    freeStorage();
249
250    mType = 0;
251}
252
253void 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
262void 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
269void 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
279void 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
289String8 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
326static 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
334void 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