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