Home | History | Annotate | Download | only in libstagefright
      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