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