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