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 /**
     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