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