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#include <stdlib.h>
18#include <string.h>
19
20#include <media/stagefright/MediaDebug.h>
21#include <media/stagefright/MetaData.h>
22
23namespace android {
24
25MetaData::MetaData() {
26}
27
28MetaData::MetaData(const MetaData &from)
29    : RefBase(),
30      mItems(from.mItems) {
31}
32
33MetaData::~MetaData() {
34    clear();
35}
36
37void MetaData::clear() {
38    mItems.clear();
39}
40
41bool MetaData::remove(uint32_t key) {
42    ssize_t i = mItems.indexOfKey(key);
43
44    if (i < 0) {
45        return false;
46    }
47
48    mItems.removeItemsAt(i);
49
50    return true;
51}
52
53bool MetaData::setCString(uint32_t key, const char *value) {
54    return setData(key, TYPE_C_STRING, value, strlen(value) + 1);
55}
56
57bool MetaData::setInt32(uint32_t key, int32_t value) {
58    return setData(key, TYPE_INT32, &value, sizeof(value));
59}
60
61bool MetaData::setInt64(uint32_t key, int64_t value) {
62    return setData(key, TYPE_INT64, &value, sizeof(value));
63}
64
65bool MetaData::setFloat(uint32_t key, float value) {
66    return setData(key, TYPE_FLOAT, &value, sizeof(value));
67}
68
69bool MetaData::setPointer(uint32_t key, void *value) {
70    return setData(key, TYPE_POINTER, &value, sizeof(value));
71}
72
73bool MetaData::findCString(uint32_t key, const char **value) {
74    uint32_t type;
75    const void *data;
76    size_t size;
77    if (!findData(key, &type, &data, &size) || type != TYPE_C_STRING) {
78        return false;
79    }
80
81    *value = (const char *)data;
82
83    return true;
84}
85
86bool MetaData::findInt32(uint32_t key, int32_t *value) {
87    uint32_t type;
88    const void *data;
89    size_t size;
90    if (!findData(key, &type, &data, &size) || type != TYPE_INT32) {
91        return false;
92    }
93
94    CHECK_EQ(size, sizeof(*value));
95
96    *value = *(int32_t *)data;
97
98    return true;
99}
100
101bool MetaData::findInt64(uint32_t key, int64_t *value) {
102    uint32_t type;
103    const void *data;
104    size_t size;
105    if (!findData(key, &type, &data, &size) || type != TYPE_INT64) {
106        return false;
107    }
108
109    CHECK_EQ(size, sizeof(*value));
110
111    *value = *(int64_t *)data;
112
113    return true;
114}
115
116bool MetaData::findFloat(uint32_t key, float *value) {
117    uint32_t type;
118    const void *data;
119    size_t size;
120    if (!findData(key, &type, &data, &size) || type != TYPE_FLOAT) {
121        return false;
122    }
123
124    CHECK_EQ(size, sizeof(*value));
125
126    *value = *(float *)data;
127
128    return true;
129}
130
131bool MetaData::findPointer(uint32_t key, void **value) {
132    uint32_t type;
133    const void *data;
134    size_t size;
135    if (!findData(key, &type, &data, &size) || type != TYPE_POINTER) {
136        return false;
137    }
138
139    CHECK_EQ(size, sizeof(*value));
140
141    *value = *(void **)data;
142
143    return true;
144}
145
146bool MetaData::setData(
147        uint32_t key, uint32_t type, const void *data, size_t size) {
148    bool overwrote_existing = true;
149
150    ssize_t i = mItems.indexOfKey(key);
151    if (i < 0) {
152        typed_data item;
153        i = mItems.add(key, item);
154
155        overwrote_existing = false;
156    }
157
158    typed_data &item = mItems.editValueAt(i);
159
160    item.setData(type, data, size);
161
162    return overwrote_existing;
163}
164
165bool MetaData::findData(uint32_t key, uint32_t *type,
166                        const void **data, size_t *size) const {
167    ssize_t i = mItems.indexOfKey(key);
168
169    if (i < 0) {
170        return false;
171    }
172
173    const typed_data &item = mItems.valueAt(i);
174
175    item.getData(type, data, size);
176
177    return true;
178}
179
180MetaData::typed_data::typed_data()
181    : mType(0),
182      mSize(0) {
183}
184
185MetaData::typed_data::~typed_data() {
186    clear();
187}
188
189MetaData::typed_data::typed_data(const typed_data &from)
190    : mType(from.mType),
191      mSize(0) {
192    allocateStorage(from.mSize);
193    memcpy(storage(), from.storage(), mSize);
194}
195
196MetaData::typed_data &MetaData::typed_data::operator=(
197        const MetaData::typed_data &from) {
198    if (this != &from) {
199        clear();
200        mType = from.mType;
201        allocateStorage(from.mSize);
202        memcpy(storage(), from.storage(), mSize);
203    }
204
205    return *this;
206}
207
208void MetaData::typed_data::clear() {
209    freeStorage();
210
211    mType = 0;
212}
213
214void MetaData::typed_data::setData(
215        uint32_t type, const void *data, size_t size) {
216    clear();
217
218    mType = type;
219    allocateStorage(size);
220    memcpy(storage(), data, size);
221}
222
223void MetaData::typed_data::getData(
224        uint32_t *type, const void **data, size_t *size) const {
225    *type = mType;
226    *size = mSize;
227    *data = storage();
228}
229
230void MetaData::typed_data::allocateStorage(size_t size) {
231    mSize = size;
232
233    if (usesReservoir()) {
234        return;
235    }
236
237    u.ext_data = malloc(mSize);
238}
239
240void MetaData::typed_data::freeStorage() {
241    if (!usesReservoir()) {
242        if (u.ext_data) {
243            free(u.ext_data);
244        }
245    }
246
247    mSize = 0;
248}
249
250}  // namespace android
251
252