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