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