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 "Utils"
     19 #include <utils/Log.h>
     20 
     21 #include "include/ESDS.h"
     22 
     23 #include <arpa/inet.h>
     24 
     25 #include <media/stagefright/foundation/ABuffer.h>
     26 #include <media/stagefright/foundation/ADebug.h>
     27 #include <media/stagefright/foundation/AMessage.h>
     28 #include <media/stagefright/MetaData.h>
     29 #include <media/stagefright/Utils.h>
     30 
     31 namespace android {
     32 
     33 uint16_t U16_AT(const uint8_t *ptr) {
     34     return ptr[0] << 8 | ptr[1];
     35 }
     36 
     37 uint32_t U32_AT(const uint8_t *ptr) {
     38     return ptr[0] << 24 | ptr[1] << 16 | ptr[2] << 8 | ptr[3];
     39 }
     40 
     41 uint64_t U64_AT(const uint8_t *ptr) {
     42     return ((uint64_t)U32_AT(ptr)) << 32 | U32_AT(ptr + 4);
     43 }
     44 
     45 uint16_t U16LE_AT(const uint8_t *ptr) {
     46     return ptr[0] | (ptr[1] << 8);
     47 }
     48 
     49 uint32_t U32LE_AT(const uint8_t *ptr) {
     50     return ptr[3] << 24 | ptr[2] << 16 | ptr[1] << 8 | ptr[0];
     51 }
     52 
     53 uint64_t U64LE_AT(const uint8_t *ptr) {
     54     return ((uint64_t)U32LE_AT(ptr + 4)) << 32 | U32LE_AT(ptr);
     55 }
     56 
     57 // XXX warning: these won't work on big-endian host.
     58 uint64_t ntoh64(uint64_t x) {
     59     return ((uint64_t)ntohl(x & 0xffffffff) << 32) | ntohl(x >> 32);
     60 }
     61 
     62 uint64_t hton64(uint64_t x) {
     63     return ((uint64_t)htonl(x & 0xffffffff) << 32) | htonl(x >> 32);
     64 }
     65 
     66 status_t convertMetaDataToMessage(
     67         const sp<MetaData> &meta, sp<AMessage> *format) {
     68     format->clear();
     69 
     70     const char *mime;
     71     CHECK(meta->findCString(kKeyMIMEType, &mime));
     72 
     73     sp<AMessage> msg = new AMessage;
     74     msg->setString("mime", mime);
     75 
     76     int64_t durationUs;
     77     if (meta->findInt64(kKeyDuration, &durationUs)) {
     78         msg->setInt64("durationUs", durationUs);
     79     }
     80 
     81     if (!strncasecmp("video/", mime, 6)) {
     82         int32_t width, height;
     83         CHECK(meta->findInt32(kKeyWidth, &width));
     84         CHECK(meta->findInt32(kKeyHeight, &height));
     85 
     86         msg->setInt32("width", width);
     87         msg->setInt32("height", height);
     88     } else if (!strncasecmp("audio/", mime, 6)) {
     89         int32_t numChannels, sampleRate;
     90         CHECK(meta->findInt32(kKeyChannelCount, &numChannels));
     91         CHECK(meta->findInt32(kKeySampleRate, &sampleRate));
     92 
     93         msg->setInt32("channel-count", numChannels);
     94         msg->setInt32("sample-rate", sampleRate);
     95 
     96         int32_t channelMask;
     97         if (meta->findInt32(kKeyChannelMask, &channelMask)) {
     98             msg->setInt32("channel-mask", channelMask);
     99         }
    100 
    101         int32_t delay = 0;
    102         if (meta->findInt32(kKeyEncoderDelay, &delay)) {
    103             msg->setInt32("encoder-delay", delay);
    104         }
    105         int32_t padding = 0;
    106         if (meta->findInt32(kKeyEncoderPadding, &padding)) {
    107             msg->setInt32("encoder-padding", padding);
    108         }
    109 
    110         int32_t isADTS;
    111         if (meta->findInt32(kKeyIsADTS, &isADTS)) {
    112             msg->setInt32("is-adts", true);
    113         }
    114     }
    115 
    116     int32_t maxInputSize;
    117     if (meta->findInt32(kKeyMaxInputSize, &maxInputSize)) {
    118         msg->setInt32("max-input-size", maxInputSize);
    119     }
    120 
    121     uint32_t type;
    122     const void *data;
    123     size_t size;
    124     if (meta->findData(kKeyAVCC, &type, &data, &size)) {
    125         // Parse the AVCDecoderConfigurationRecord
    126 
    127         const uint8_t *ptr = (const uint8_t *)data;
    128 
    129         CHECK(size >= 7);
    130         CHECK_EQ((unsigned)ptr[0], 1u);  // configurationVersion == 1
    131         uint8_t profile = ptr[1];
    132         uint8_t level = ptr[3];
    133 
    134         // There is decodable content out there that fails the following
    135         // assertion, let's be lenient for now...
    136         // CHECK((ptr[4] >> 2) == 0x3f);  // reserved
    137 
    138         size_t lengthSize = 1 + (ptr[4] & 3);
    139 
    140         // commented out check below as H264_QVGA_500_NO_AUDIO.3gp
    141         // violates it...
    142         // CHECK((ptr[5] >> 5) == 7);  // reserved
    143 
    144         size_t numSeqParameterSets = ptr[5] & 31;
    145 
    146         ptr += 6;
    147         size -= 6;
    148 
    149         sp<ABuffer> buffer = new ABuffer(1024);
    150         buffer->setRange(0, 0);
    151 
    152         for (size_t i = 0; i < numSeqParameterSets; ++i) {
    153             CHECK(size >= 2);
    154             size_t length = U16_AT(ptr);
    155 
    156             ptr += 2;
    157             size -= 2;
    158 
    159             CHECK(size >= length);
    160 
    161             memcpy(buffer->data() + buffer->size(), "\x00\x00\x00\x01", 4);
    162             memcpy(buffer->data() + buffer->size() + 4, ptr, length);
    163             buffer->setRange(0, buffer->size() + 4 + length);
    164 
    165             ptr += length;
    166             size -= length;
    167         }
    168 
    169         buffer->meta()->setInt32("csd", true);
    170         buffer->meta()->setInt64("timeUs", 0);
    171 
    172         msg->setBuffer("csd-0", buffer);
    173 
    174         buffer = new ABuffer(1024);
    175         buffer->setRange(0, 0);
    176 
    177         CHECK(size >= 1);
    178         size_t numPictureParameterSets = *ptr;
    179         ++ptr;
    180         --size;
    181 
    182         for (size_t i = 0; i < numPictureParameterSets; ++i) {
    183             CHECK(size >= 2);
    184             size_t length = U16_AT(ptr);
    185 
    186             ptr += 2;
    187             size -= 2;
    188 
    189             CHECK(size >= length);
    190 
    191             memcpy(buffer->data() + buffer->size(), "\x00\x00\x00\x01", 4);
    192             memcpy(buffer->data() + buffer->size() + 4, ptr, length);
    193             buffer->setRange(0, buffer->size() + 4 + length);
    194 
    195             ptr += length;
    196             size -= length;
    197         }
    198 
    199         buffer->meta()->setInt32("csd", true);
    200         buffer->meta()->setInt64("timeUs", 0);
    201         msg->setBuffer("csd-1", buffer);
    202     } else if (meta->findData(kKeyESDS, &type, &data, &size)) {
    203         ESDS esds((const char *)data, size);
    204         CHECK_EQ(esds.InitCheck(), (status_t)OK);
    205 
    206         const void *codec_specific_data;
    207         size_t codec_specific_data_size;
    208         esds.getCodecSpecificInfo(
    209                 &codec_specific_data, &codec_specific_data_size);
    210 
    211         sp<ABuffer> buffer = new ABuffer(codec_specific_data_size);
    212 
    213         memcpy(buffer->data(), codec_specific_data,
    214                codec_specific_data_size);
    215 
    216         buffer->meta()->setInt32("csd", true);
    217         buffer->meta()->setInt64("timeUs", 0);
    218         msg->setBuffer("csd-0", buffer);
    219     } else if (meta->findData(kKeyVorbisInfo, &type, &data, &size)) {
    220         sp<ABuffer> buffer = new ABuffer(size);
    221         memcpy(buffer->data(), data, size);
    222 
    223         buffer->meta()->setInt32("csd", true);
    224         buffer->meta()->setInt64("timeUs", 0);
    225         msg->setBuffer("csd-0", buffer);
    226 
    227         if (!meta->findData(kKeyVorbisBooks, &type, &data, &size)) {
    228             return -EINVAL;
    229         }
    230 
    231         buffer = new ABuffer(size);
    232         memcpy(buffer->data(), data, size);
    233 
    234         buffer->meta()->setInt32("csd", true);
    235         buffer->meta()->setInt64("timeUs", 0);
    236         msg->setBuffer("csd-1", buffer);
    237     }
    238 
    239     *format = msg;
    240 
    241     return OK;
    242 }
    243 
    244 }  // namespace android
    245 
    246