Home | History | Annotate | Download | only in libstagefright
      1 /*
      2  * Copyright 2018 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 "MetaDataUtils"
     19 #include <utils/Log.h>
     20 
     21 #include <media/stagefright/foundation/avc_utils.h>
     22 #include <media/stagefright/foundation/base64.h>
     23 #include <media/stagefright/foundation/ABitReader.h>
     24 #include <media/stagefright/foundation/ABuffer.h>
     25 #include <media/stagefright/foundation/ByteUtils.h>
     26 #include <media/stagefright/MediaDefs.h>
     27 #include <media/stagefright/MetaDataUtils.h>
     28 #include <media/stagefright/Utils.h>
     29 #include <media/NdkMediaFormat.h>
     30 
     31 namespace android {
     32 
     33 bool MakeAVCCodecSpecificData(MetaDataBase &meta, const uint8_t *data, size_t size) {
     34     if (data == nullptr || size == 0) {
     35         return false;
     36     }
     37 
     38     int32_t width;
     39     int32_t height;
     40     int32_t sarWidth;
     41     int32_t sarHeight;
     42     sp<ABuffer> accessUnit = new ABuffer((void*)data,  size);
     43     sp<ABuffer> csd = MakeAVCCodecSpecificData(accessUnit, &width, &height, &sarWidth, &sarHeight);
     44     if (csd == nullptr) {
     45         return false;
     46     }
     47     meta.setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_AVC);
     48 
     49     meta.setData(kKeyAVCC, kTypeAVCC, csd->data(), csd->size());
     50     meta.setInt32(kKeyWidth, width);
     51     meta.setInt32(kKeyHeight, height);
     52     if (sarWidth > 0 && sarHeight > 0) {
     53         meta.setInt32(kKeySARWidth, sarWidth);
     54         meta.setInt32(kKeySARHeight, sarHeight);
     55     }
     56     return true;
     57 }
     58 
     59 bool MakeAVCCodecSpecificData(AMediaFormat *meta, const uint8_t *data, size_t size) {
     60     if (meta == nullptr || data == nullptr || size == 0) {
     61         return false;
     62     }
     63 
     64     int32_t width;
     65     int32_t height;
     66     int32_t sarWidth;
     67     int32_t sarHeight;
     68     sp<ABuffer> accessUnit = new ABuffer((void*)data,  size);
     69     sp<ABuffer> csd = MakeAVCCodecSpecificData(accessUnit, &width, &height, &sarWidth, &sarHeight);
     70     if (csd == nullptr) {
     71         return false;
     72     }
     73     AMediaFormat_setString(meta, AMEDIAFORMAT_KEY_MIME, MEDIA_MIMETYPE_VIDEO_AVC);
     74 
     75     AMediaFormat_setBuffer(meta, AMEDIAFORMAT_KEY_CSD_AVC, csd->data(), csd->size());
     76     AMediaFormat_setInt32(meta, AMEDIAFORMAT_KEY_WIDTH, width);
     77     AMediaFormat_setInt32(meta, AMEDIAFORMAT_KEY_HEIGHT, height);
     78     if (sarWidth > 0 && sarHeight > 0) {
     79         AMediaFormat_setInt32(meta, AMEDIAFORMAT_KEY_SAR_WIDTH, sarWidth);
     80         AMediaFormat_setInt32(meta, AMEDIAFORMAT_KEY_SAR_HEIGHT, sarHeight);
     81     }
     82     return true;
     83 }
     84 
     85 bool MakeAACCodecSpecificData(MetaDataBase &meta, const uint8_t *data, size_t size) {
     86     if (data == nullptr || size < 7) {
     87         return false;
     88     }
     89 
     90     ABitReader bits(data, size);
     91 
     92     // adts_fixed_header
     93 
     94     if (bits.getBits(12) != 0xfffu) {
     95         ALOGE("Wrong atds_fixed_header");
     96         return false;
     97     }
     98 
     99     bits.skipBits(4);  // ID, layer, protection_absent
    100 
    101     unsigned profile = bits.getBits(2);
    102     if (profile == 3u) {
    103         ALOGE("profile should not be 3");
    104         return false;
    105     }
    106     unsigned sampling_freq_index = bits.getBits(4);
    107     bits.getBits(1);  // private_bit
    108     unsigned channel_configuration = bits.getBits(3);
    109     if (channel_configuration == 0u) {
    110         ALOGE("channel_config should not be 0");
    111         return false;
    112     }
    113 
    114     if (!MakeAACCodecSpecificData(
    115             meta, profile, sampling_freq_index, channel_configuration)) {
    116         return false;
    117     }
    118 
    119     meta.setInt32(kKeyIsADTS, true);
    120     return true;
    121 }
    122 
    123 bool MakeAACCodecSpecificData(
    124         uint8_t *csd, /* out */
    125         size_t *esds_size, /* in/out */
    126         unsigned profile, /* in */
    127         unsigned sampling_freq_index, /* in */
    128         unsigned channel_configuration, /* in */
    129         int32_t *sampling_rate /* out */
    130 ) {
    131     if(sampling_freq_index > 11u) {
    132         return false;
    133     }
    134     static const int32_t kSamplingFreq[] = {
    135         96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050,
    136         16000, 12000, 11025, 8000
    137     };
    138     *sampling_rate = kSamplingFreq[sampling_freq_index];
    139 
    140     static const uint8_t kStaticESDS[] = {
    141         0x03, 22,
    142         0x00, 0x00,     // ES_ID
    143         0x00,           // streamDependenceFlag, URL_Flag, OCRstreamFlag
    144 
    145         0x04, 17,
    146         0x40,                       // Audio ISO/IEC 14496-3
    147         0x00, 0x00, 0x00, 0x00,
    148         0x00, 0x00, 0x00, 0x00,
    149         0x00, 0x00, 0x00, 0x00,
    150 
    151         0x05, 2,
    152         // AudioSpecificInfo follows
    153 
    154         // oooo offf fccc c000
    155         // o - audioObjectType
    156         // f - samplingFreqIndex
    157         // c - channelConfig
    158     };
    159 
    160     size_t csdSize = sizeof(kStaticESDS) + 2;
    161     if (csdSize > *esds_size) {
    162         return false;
    163     }
    164     memcpy(csd, kStaticESDS, sizeof(kStaticESDS));
    165 
    166     csd[sizeof(kStaticESDS)] =
    167         ((profile + 1) << 3) | (sampling_freq_index >> 1);
    168 
    169     csd[sizeof(kStaticESDS) + 1] =
    170         ((sampling_freq_index << 7) & 0x80) | (channel_configuration << 3);
    171 
    172     *esds_size = csdSize;
    173     return true;
    174 }
    175 
    176 bool MakeAACCodecSpecificData(AMediaFormat *meta, unsigned profile, unsigned sampling_freq_index,
    177         unsigned channel_configuration) {
    178 
    179     if(sampling_freq_index > 11u) {
    180         return false;
    181     }
    182 
    183     uint8_t csd[2];
    184     csd[0] = ((profile + 1) << 3) | (sampling_freq_index >> 1);
    185     csd[1] = ((sampling_freq_index << 7) & 0x80) | (channel_configuration << 3);
    186 
    187     static const int32_t kSamplingFreq[] = {
    188         96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050,
    189         16000, 12000, 11025, 8000
    190     };
    191     int32_t sampleRate = kSamplingFreq[sampling_freq_index];
    192 
    193     AMediaFormat_setBuffer(meta, AMEDIAFORMAT_KEY_CSD_0, csd, sizeof(csd));
    194     AMediaFormat_setString(meta, AMEDIAFORMAT_KEY_MIME, MEDIA_MIMETYPE_AUDIO_AAC);
    195     AMediaFormat_setInt32(meta, AMEDIAFORMAT_KEY_SAMPLE_RATE, sampleRate);
    196     AMediaFormat_setInt32(meta, AMEDIAFORMAT_KEY_CHANNEL_COUNT, channel_configuration);
    197 
    198     return true;
    199 }
    200 
    201 bool MakeAACCodecSpecificData(
    202         MetaDataBase &meta,
    203         unsigned profile, unsigned sampling_freq_index,
    204         unsigned channel_configuration) {
    205 
    206     uint8_t csd[24];
    207     size_t csdSize = sizeof(csd);
    208     int32_t sampleRate;
    209 
    210     if (!MakeAACCodecSpecificData(csd, &csdSize, profile, sampling_freq_index,
    211             channel_configuration, &sampleRate)) {
    212         return false;
    213     }
    214 
    215     meta.setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_AAC);
    216 
    217     meta.setInt32(kKeySampleRate, sampleRate);
    218     meta.setInt32(kKeyChannelCount, channel_configuration);
    219     meta.setData(kKeyESDS, 0, csd, csdSize);
    220     return true;
    221 }
    222 
    223 
    224 static void extractAlbumArt(
    225         AMediaFormat *fileMeta, const void *data, size_t size) {
    226     ALOGV("extractAlbumArt from '%s'", (const char *)data);
    227 
    228     size_t inLen = strnlen((const char *)data, size);
    229     size_t flacSize = inLen / 4 * 3;
    230     uint8_t *flac = new uint8_t[flacSize];
    231     if (!decodeBase64(flac, &flacSize, (const char*)data)) {
    232         ALOGE("malformed base64 encoded data.");
    233         delete[] flac;
    234         return;
    235     }
    236 
    237     ALOGV("got flac of size %zu", flacSize);
    238 
    239     uint32_t picType;
    240     uint32_t typeLen;
    241     uint32_t descLen;
    242     uint32_t dataLen;
    243     char type[128];
    244 
    245     if (flacSize < 8) {
    246         delete[] flac;
    247         return;
    248     }
    249 
    250     picType = U32_AT(flac);
    251 
    252     if (picType != 3) {
    253         // This is not a front cover.
    254         delete[] flac;
    255         return;
    256     }
    257 
    258     typeLen = U32_AT(&flac[4]);
    259     if (typeLen > sizeof(type) - 1) {
    260         delete[] flac;
    261         return;
    262     }
    263 
    264     // we've already checked above that flacSize >= 8
    265     if (flacSize - 8 < typeLen) {
    266         delete[] flac;
    267         return;
    268     }
    269 
    270     memcpy(type, &flac[8], typeLen);
    271     type[typeLen] = '\0';
    272 
    273     ALOGV("picType = %d, type = '%s'", picType, type);
    274 
    275     if (!strcmp(type, "-->")) {
    276         // This is not inline cover art, but an external url instead.
    277         delete[] flac;
    278         return;
    279     }
    280 
    281     if (flacSize < 32 || flacSize - 32 < typeLen) {
    282         delete[] flac;
    283         return;
    284     }
    285 
    286     descLen = U32_AT(&flac[8 + typeLen]);
    287     if (flacSize - 32 - typeLen < descLen) {
    288         delete[] flac;
    289         return;
    290     }
    291 
    292     dataLen = U32_AT(&flac[8 + typeLen + 4 + descLen + 16]);
    293 
    294     // we've already checked above that (flacSize - 32 - typeLen - descLen) >= 0
    295     if (flacSize - 32 - typeLen - descLen < dataLen) {
    296         delete[] flac;
    297         return;
    298     }
    299 
    300     ALOGV("got image data, %zu trailing bytes",
    301          flacSize - 32 - typeLen - descLen - dataLen);
    302 
    303     AMediaFormat_setBuffer(fileMeta, AMEDIAFORMAT_KEY_ALBUMART,
    304             &flac[8 + typeLen + 4 + descLen + 20], dataLen);
    305 
    306     delete[] flac;
    307 }
    308 
    309 void parseVorbisComment(
    310         AMediaFormat *fileMeta, const char *comment, size_t commentLength) {
    311     // Haptic tag is only kept here as it will only be used in extractor to generate channel mask.
    312     struct {
    313         const char *const mTag;
    314         const char *mKey;
    315     } kMap[] = {
    316         { "TITLE", AMEDIAFORMAT_KEY_TITLE },
    317         { "ARTIST", AMEDIAFORMAT_KEY_ARTIST },
    318         { "ALBUMARTIST", AMEDIAFORMAT_KEY_ALBUMARTIST },
    319         { "ALBUM ARTIST", AMEDIAFORMAT_KEY_ALBUMARTIST },
    320         { "COMPILATION", AMEDIAFORMAT_KEY_COMPILATION },
    321         { "ALBUM", AMEDIAFORMAT_KEY_ALBUM },
    322         { "COMPOSER", AMEDIAFORMAT_KEY_COMPOSER },
    323         { "GENRE", AMEDIAFORMAT_KEY_GENRE },
    324         { "AUTHOR", AMEDIAFORMAT_KEY_AUTHOR },
    325         { "TRACKNUMBER", AMEDIAFORMAT_KEY_CDTRACKNUMBER },
    326         { "DISCNUMBER", AMEDIAFORMAT_KEY_DISCNUMBER },
    327         { "DATE", AMEDIAFORMAT_KEY_DATE },
    328         { "YEAR", AMEDIAFORMAT_KEY_YEAR },
    329         { "LYRICIST", AMEDIAFORMAT_KEY_LYRICIST },
    330         { "METADATA_BLOCK_PICTURE", AMEDIAFORMAT_KEY_ALBUMART },
    331         { "ANDROID_LOOP", AMEDIAFORMAT_KEY_LOOP },
    332         { "ANDROID_HAPTIC", AMEDIAFORMAT_KEY_HAPTIC_CHANNEL_COUNT },
    333     };
    334 
    335         for (size_t j = 0; j < sizeof(kMap) / sizeof(kMap[0]); ++j) {
    336             size_t tagLen = strlen(kMap[j].mTag);
    337             if (!strncasecmp(kMap[j].mTag, comment, tagLen)
    338                     && comment[tagLen] == '=') {
    339                 if (kMap[j].mKey == AMEDIAFORMAT_KEY_ALBUMART) {
    340                     extractAlbumArt(
    341                             fileMeta,
    342                             &comment[tagLen + 1],
    343                             commentLength - tagLen - 1);
    344                 } else if (kMap[j].mKey == AMEDIAFORMAT_KEY_LOOP) {
    345                     if (!strcasecmp(&comment[tagLen + 1], "true")) {
    346                         AMediaFormat_setInt32(fileMeta, AMEDIAFORMAT_KEY_LOOP, 1);
    347                     }
    348                 } else if (kMap[j].mKey == AMEDIAFORMAT_KEY_HAPTIC_CHANNEL_COUNT) {
    349                     char *end;
    350                     errno = 0;
    351                     const int hapticChannelCount = strtol(&comment[tagLen + 1], &end, 10);
    352                     if (errno == 0) {
    353                         AMediaFormat_setInt32(fileMeta, kMap[j].mKey, hapticChannelCount);
    354                     } else {
    355                         ALOGE("Error(%d) when parsing haptic channel count", errno);
    356                     }
    357                 } else {
    358                     AMediaFormat_setString(fileMeta, kMap[j].mKey, &comment[tagLen + 1]);
    359                 }
    360             }
    361         }
    362 
    363 }
    364 
    365 }  // namespace android
    366