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