Utils.cpp revision ccad786f3497f223cbc5af981b08b460433ee622
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#include <ctype.h> 21 22#include "include/ESDS.h" 23 24#include <arpa/inet.h> 25#include <cutils/properties.h> 26#include <media/openmax/OMX_Audio.h> 27#include <media/stagefright/foundation/ABuffer.h> 28#include <media/stagefright/foundation/ADebug.h> 29#include <media/stagefright/foundation/AMessage.h> 30#include <media/stagefright/MetaData.h> 31#include <media/stagefright/MediaDefs.h> 32#include <media/AudioSystem.h> 33#include <media/MediaPlayerInterface.h> 34#include <hardware/audio.h> 35#include <media/stagefright/Utils.h> 36#include <media/AudioParameter.h> 37 38namespace android { 39 40uint16_t U16_AT(const uint8_t *ptr) { 41 return ptr[0] << 8 | ptr[1]; 42} 43 44uint32_t U32_AT(const uint8_t *ptr) { 45 return ptr[0] << 24 | ptr[1] << 16 | ptr[2] << 8 | ptr[3]; 46} 47 48uint64_t U64_AT(const uint8_t *ptr) { 49 return ((uint64_t)U32_AT(ptr)) << 32 | U32_AT(ptr + 4); 50} 51 52uint16_t U16LE_AT(const uint8_t *ptr) { 53 return ptr[0] | (ptr[1] << 8); 54} 55 56uint32_t U32LE_AT(const uint8_t *ptr) { 57 return ptr[3] << 24 | ptr[2] << 16 | ptr[1] << 8 | ptr[0]; 58} 59 60uint64_t U64LE_AT(const uint8_t *ptr) { 61 return ((uint64_t)U32LE_AT(ptr + 4)) << 32 | U32LE_AT(ptr); 62} 63 64// XXX warning: these won't work on big-endian host. 65uint64_t ntoh64(uint64_t x) { 66 return ((uint64_t)ntohl(x & 0xffffffff) << 32) | ntohl(x >> 32); 67} 68 69uint64_t hton64(uint64_t x) { 70 return ((uint64_t)htonl(x & 0xffffffff) << 32) | htonl(x >> 32); 71} 72 73status_t convertMetaDataToMessage( 74 const sp<MetaData> &meta, sp<AMessage> *format) { 75 format->clear(); 76 77 const char *mime; 78 CHECK(meta->findCString(kKeyMIMEType, &mime)); 79 80 sp<AMessage> msg = new AMessage; 81 msg->setString("mime", mime); 82 83 int64_t durationUs; 84 if (meta->findInt64(kKeyDuration, &durationUs)) { 85 msg->setInt64("durationUs", durationUs); 86 } 87 88 int avgBitRate; 89 if (meta->findInt32(kKeyBitRate, &avgBitRate)) { 90 msg->setInt32("bit-rate", avgBitRate); 91 } 92 93 int32_t isSync; 94 if (meta->findInt32(kKeyIsSyncFrame, &isSync) && isSync != 0) { 95 msg->setInt32("is-sync-frame", 1); 96 } 97 98 if (!strncasecmp("video/", mime, 6)) { 99 int32_t width, height; 100 CHECK(meta->findInt32(kKeyWidth, &width)); 101 CHECK(meta->findInt32(kKeyHeight, &height)); 102 103 msg->setInt32("width", width); 104 msg->setInt32("height", height); 105 106 int32_t sarWidth, sarHeight; 107 if (meta->findInt32(kKeySARWidth, &sarWidth) 108 && meta->findInt32(kKeySARHeight, &sarHeight)) { 109 msg->setInt32("sar-width", sarWidth); 110 msg->setInt32("sar-height", sarHeight); 111 } 112 } else if (!strncasecmp("audio/", mime, 6)) { 113 int32_t numChannels, sampleRate; 114 CHECK(meta->findInt32(kKeyChannelCount, &numChannels)); 115 CHECK(meta->findInt32(kKeySampleRate, &sampleRate)); 116 117 msg->setInt32("channel-count", numChannels); 118 msg->setInt32("sample-rate", sampleRate); 119 120 int32_t channelMask; 121 if (meta->findInt32(kKeyChannelMask, &channelMask)) { 122 msg->setInt32("channel-mask", channelMask); 123 } 124 125 int32_t delay = 0; 126 if (meta->findInt32(kKeyEncoderDelay, &delay)) { 127 msg->setInt32("encoder-delay", delay); 128 } 129 int32_t padding = 0; 130 if (meta->findInt32(kKeyEncoderPadding, &padding)) { 131 msg->setInt32("encoder-padding", padding); 132 } 133 134 int32_t isADTS; 135 if (meta->findInt32(kKeyIsADTS, &isADTS)) { 136 msg->setInt32("is-adts", true); 137 } 138 139 int32_t aacProfile = -1; 140 if (meta->findInt32(kKeyAACAOT, &aacProfile)) { 141 msg->setInt32("aac-profile", aacProfile); 142 } 143 } 144 145 int32_t maxInputSize; 146 if (meta->findInt32(kKeyMaxInputSize, &maxInputSize)) { 147 msg->setInt32("max-input-size", maxInputSize); 148 } 149 150 int32_t rotationDegrees; 151 if (meta->findInt32(kKeyRotation, &rotationDegrees)) { 152 msg->setInt32("rotation-degrees", rotationDegrees); 153 } 154 155 uint32_t type; 156 const void *data; 157 size_t size; 158 if (meta->findData(kKeyAVCC, &type, &data, &size)) { 159 // Parse the AVCDecoderConfigurationRecord 160 161 const uint8_t *ptr = (const uint8_t *)data; 162 163 CHECK(size >= 7); 164 CHECK_EQ((unsigned)ptr[0], 1u); // configurationVersion == 1 165 uint8_t profile = ptr[1]; 166 uint8_t level = ptr[3]; 167 168 // There is decodable content out there that fails the following 169 // assertion, let's be lenient for now... 170 // CHECK((ptr[4] >> 2) == 0x3f); // reserved 171 172 size_t lengthSize = 1 + (ptr[4] & 3); 173 174 // commented out check below as H264_QVGA_500_NO_AUDIO.3gp 175 // violates it... 176 // CHECK((ptr[5] >> 5) == 7); // reserved 177 178 size_t numSeqParameterSets = ptr[5] & 31; 179 180 ptr += 6; 181 size -= 6; 182 183 sp<ABuffer> buffer = new ABuffer(1024); 184 buffer->setRange(0, 0); 185 186 for (size_t i = 0; i < numSeqParameterSets; ++i) { 187 CHECK(size >= 2); 188 size_t length = U16_AT(ptr); 189 190 ptr += 2; 191 size -= 2; 192 193 CHECK(size >= length); 194 195 memcpy(buffer->data() + buffer->size(), "\x00\x00\x00\x01", 4); 196 memcpy(buffer->data() + buffer->size() + 4, ptr, length); 197 buffer->setRange(0, buffer->size() + 4 + length); 198 199 ptr += length; 200 size -= length; 201 } 202 203 buffer->meta()->setInt32("csd", true); 204 buffer->meta()->setInt64("timeUs", 0); 205 206 msg->setBuffer("csd-0", buffer); 207 208 buffer = new ABuffer(1024); 209 buffer->setRange(0, 0); 210 211 CHECK(size >= 1); 212 size_t numPictureParameterSets = *ptr; 213 ++ptr; 214 --size; 215 216 for (size_t i = 0; i < numPictureParameterSets; ++i) { 217 CHECK(size >= 2); 218 size_t length = U16_AT(ptr); 219 220 ptr += 2; 221 size -= 2; 222 223 CHECK(size >= length); 224 225 memcpy(buffer->data() + buffer->size(), "\x00\x00\x00\x01", 4); 226 memcpy(buffer->data() + buffer->size() + 4, ptr, length); 227 buffer->setRange(0, buffer->size() + 4 + length); 228 229 ptr += length; 230 size -= length; 231 } 232 233 buffer->meta()->setInt32("csd", true); 234 buffer->meta()->setInt64("timeUs", 0); 235 msg->setBuffer("csd-1", buffer); 236 } else if (meta->findData(kKeyHVCC, &type, &data, &size)) { 237 const uint8_t *ptr = (const uint8_t *)data; 238 239 CHECK(size >= 7); 240 CHECK_EQ((unsigned)ptr[0], 1u); // configurationVersion == 1 241 uint8_t profile = ptr[1] & 31; 242 uint8_t level = ptr[12]; 243 ptr += 22; 244 size -= 22; 245 246 247 size_t numofArrays = (char)ptr[0]; 248 ptr += 1; 249 size -= 1; 250 size_t j = 0, i = 0; 251 252 sp<ABuffer> buffer = new ABuffer(1024); 253 buffer->setRange(0, 0); 254 255 for (i = 0; i < numofArrays; i++) { 256 ptr += 1; 257 size -= 1; 258 259 //Num of nals 260 size_t numofNals = U16_AT(ptr); 261 262 ptr += 2; 263 size -= 2; 264 265 for (j = 0; j < numofNals; j++) { 266 CHECK(size >= 2); 267 size_t length = U16_AT(ptr); 268 269 ptr += 2; 270 size -= 2; 271 272 CHECK(size >= length); 273 274 memcpy(buffer->data() + buffer->size(), "\x00\x00\x00\x01", 4); 275 memcpy(buffer->data() + buffer->size() + 4, ptr, length); 276 buffer->setRange(0, buffer->size() + 4 + length); 277 278 ptr += length; 279 size -= length; 280 } 281 } 282 buffer->meta()->setInt32("csd", true); 283 buffer->meta()->setInt64("timeUs", 0); 284 msg->setBuffer("csd-0", buffer); 285 286 } else if (meta->findData(kKeyESDS, &type, &data, &size)) { 287 ESDS esds((const char *)data, size); 288 CHECK_EQ(esds.InitCheck(), (status_t)OK); 289 290 const void *codec_specific_data; 291 size_t codec_specific_data_size; 292 esds.getCodecSpecificInfo( 293 &codec_specific_data, &codec_specific_data_size); 294 295 sp<ABuffer> buffer = new ABuffer(codec_specific_data_size); 296 297 memcpy(buffer->data(), codec_specific_data, 298 codec_specific_data_size); 299 300 buffer->meta()->setInt32("csd", true); 301 buffer->meta()->setInt64("timeUs", 0); 302 msg->setBuffer("csd-0", buffer); 303 } else if (meta->findData(kKeyVorbisInfo, &type, &data, &size)) { 304 sp<ABuffer> buffer = new ABuffer(size); 305 memcpy(buffer->data(), data, size); 306 307 buffer->meta()->setInt32("csd", true); 308 buffer->meta()->setInt64("timeUs", 0); 309 msg->setBuffer("csd-0", buffer); 310 311 if (!meta->findData(kKeyVorbisBooks, &type, &data, &size)) { 312 return -EINVAL; 313 } 314 315 buffer = new ABuffer(size); 316 memcpy(buffer->data(), data, size); 317 318 buffer->meta()->setInt32("csd", true); 319 buffer->meta()->setInt64("timeUs", 0); 320 msg->setBuffer("csd-1", buffer); 321 } else if (meta->findData(kKeyOpusHeader, &type, &data, &size)) { 322 sp<ABuffer> buffer = new ABuffer(size); 323 memcpy(buffer->data(), data, size); 324 325 buffer->meta()->setInt32("csd", true); 326 buffer->meta()->setInt64("timeUs", 0); 327 msg->setBuffer("csd-0", buffer); 328 } 329 330 *format = msg; 331 332 return OK; 333} 334 335static size_t reassembleAVCC(const sp<ABuffer> &csd0, const sp<ABuffer> csd1, char *avcc) { 336 337 avcc[0] = 1; // version 338 avcc[1] = 0x64; // profile 339 avcc[2] = 0; // unused (?) 340 avcc[3] = 0xd; // level 341 avcc[4] = 0xff; // reserved+size 342 343 size_t i = 0; 344 int numparams = 0; 345 int lastparamoffset = 0; 346 int avccidx = 6; 347 do { 348 if (i >= csd0->size() - 4 || 349 memcmp(csd0->data() + i, "\x00\x00\x00\x01", 4) == 0) { 350 if (i >= csd0->size() - 4) { 351 // there can't be another param here, so use all the rest 352 i = csd0->size(); 353 } 354 ALOGV("block at %zu, last was %d", i, lastparamoffset); 355 if (lastparamoffset > 0) { 356 int size = i - lastparamoffset; 357 avcc[avccidx++] = size >> 8; 358 avcc[avccidx++] = size & 0xff; 359 memcpy(avcc+avccidx, csd0->data() + lastparamoffset, size); 360 avccidx += size; 361 numparams++; 362 } 363 i += 4; 364 lastparamoffset = i; 365 } else { 366 i++; 367 } 368 } while(i < csd0->size()); 369 ALOGV("csd0 contains %d params", numparams); 370 371 avcc[5] = 0xe0 | numparams; 372 //and now csd-1 373 i = 0; 374 numparams = 0; 375 lastparamoffset = 0; 376 int numpicparamsoffset = avccidx; 377 avccidx++; 378 do { 379 if (i >= csd1->size() - 4 || 380 memcmp(csd1->data() + i, "\x00\x00\x00\x01", 4) == 0) { 381 if (i >= csd1->size() - 4) { 382 // there can't be another param here, so use all the rest 383 i = csd1->size(); 384 } 385 ALOGV("block at %zu, last was %d", i, lastparamoffset); 386 if (lastparamoffset > 0) { 387 int size = i - lastparamoffset; 388 avcc[avccidx++] = size >> 8; 389 avcc[avccidx++] = size & 0xff; 390 memcpy(avcc+avccidx, csd1->data() + lastparamoffset, size); 391 avccidx += size; 392 numparams++; 393 } 394 i += 4; 395 lastparamoffset = i; 396 } else { 397 i++; 398 } 399 } while(i < csd1->size()); 400 avcc[numpicparamsoffset] = numparams; 401 return avccidx; 402} 403 404static void reassembleESDS(const sp<ABuffer> &csd0, char *esds) { 405 int csd0size = csd0->size(); 406 esds[0] = 3; // kTag_ESDescriptor; 407 int esdescriptorsize = 26 + csd0size; 408 CHECK(esdescriptorsize < 268435456); // 7 bits per byte, so max is 2^28-1 409 esds[1] = 0x80 | (esdescriptorsize >> 21); 410 esds[2] = 0x80 | ((esdescriptorsize >> 14) & 0x7f); 411 esds[3] = 0x80 | ((esdescriptorsize >> 7) & 0x7f); 412 esds[4] = (esdescriptorsize & 0x7f); 413 esds[5] = esds[6] = 0; // es id 414 esds[7] = 0; // flags 415 esds[8] = 4; // kTag_DecoderConfigDescriptor 416 int configdescriptorsize = 18 + csd0size; 417 esds[9] = 0x80 | (configdescriptorsize >> 21); 418 esds[10] = 0x80 | ((configdescriptorsize >> 14) & 0x7f); 419 esds[11] = 0x80 | ((configdescriptorsize >> 7) & 0x7f); 420 esds[12] = (configdescriptorsize & 0x7f); 421 esds[13] = 0x40; // objectTypeIndication 422 esds[14] = 0x15; // not sure what 14-25 mean, they are ignored by ESDS.cpp, 423 esds[15] = 0x00; // but the actual values here were taken from a real file. 424 esds[16] = 0x18; 425 esds[17] = 0x00; 426 esds[18] = 0x00; 427 esds[19] = 0x00; 428 esds[20] = 0xfa; 429 esds[21] = 0x00; 430 esds[22] = 0x00; 431 esds[23] = 0x00; 432 esds[24] = 0xfa; 433 esds[25] = 0x00; 434 esds[26] = 5; // kTag_DecoderSpecificInfo; 435 esds[27] = 0x80 | (csd0size >> 21); 436 esds[28] = 0x80 | ((csd0size >> 14) & 0x7f); 437 esds[29] = 0x80 | ((csd0size >> 7) & 0x7f); 438 esds[30] = (csd0size & 0x7f); 439 memcpy((void*)&esds[31], csd0->data(), csd0size); 440 // data following this is ignored, so don't bother appending it 441 442} 443 444void convertMessageToMetaData(const sp<AMessage> &msg, sp<MetaData> &meta) { 445 AString mime; 446 if (msg->findString("mime", &mime)) { 447 meta->setCString(kKeyMIMEType, mime.c_str()); 448 } else { 449 ALOGW("did not find mime type"); 450 } 451 452 int64_t durationUs; 453 if (msg->findInt64("durationUs", &durationUs)) { 454 meta->setInt64(kKeyDuration, durationUs); 455 } 456 457 int32_t isSync; 458 if (msg->findInt32("is-sync-frame", &isSync) && isSync != 0) { 459 meta->setInt32(kKeyIsSyncFrame, 1); 460 } 461 462 if (mime.startsWith("video/")) { 463 int32_t width; 464 int32_t height; 465 if (msg->findInt32("width", &width) && msg->findInt32("height", &height)) { 466 meta->setInt32(kKeyWidth, width); 467 meta->setInt32(kKeyHeight, height); 468 } else { 469 ALOGW("did not find width and/or height"); 470 } 471 472 int32_t sarWidth, sarHeight; 473 if (msg->findInt32("sar-width", &sarWidth) 474 && msg->findInt32("sar-height", &sarHeight)) { 475 meta->setInt32(kKeySARWidth, sarWidth); 476 meta->setInt32(kKeySARHeight, sarHeight); 477 } 478 } else if (mime.startsWith("audio/")) { 479 int32_t numChannels; 480 if (msg->findInt32("channel-count", &numChannels)) { 481 meta->setInt32(kKeyChannelCount, numChannels); 482 } 483 int32_t sampleRate; 484 if (msg->findInt32("sample-rate", &sampleRate)) { 485 meta->setInt32(kKeySampleRate, sampleRate); 486 } 487 int32_t channelMask; 488 if (msg->findInt32("channel-mask", &channelMask)) { 489 meta->setInt32(kKeyChannelMask, channelMask); 490 } 491 int32_t delay = 0; 492 if (msg->findInt32("encoder-delay", &delay)) { 493 meta->setInt32(kKeyEncoderDelay, delay); 494 } 495 int32_t padding = 0; 496 if (msg->findInt32("encoder-padding", &padding)) { 497 meta->setInt32(kKeyEncoderPadding, padding); 498 } 499 500 int32_t isADTS; 501 if (msg->findInt32("is-adts", &isADTS)) { 502 meta->setInt32(kKeyIsADTS, isADTS); 503 } 504 } 505 506 int32_t maxInputSize; 507 if (msg->findInt32("max-input-size", &maxInputSize)) { 508 meta->setInt32(kKeyMaxInputSize, maxInputSize); 509 } 510 511 // reassemble the csd data into its original form 512 sp<ABuffer> csd0; 513 if (msg->findBuffer("csd-0", &csd0)) { 514 if (mime.startsWith("video/")) { // do we need to be stricter than this? 515 sp<ABuffer> csd1; 516 if (msg->findBuffer("csd-1", &csd1)) { 517 char avcc[1024]; // that oughta be enough, right? 518 size_t outsize = reassembleAVCC(csd0, csd1, avcc); 519 meta->setData(kKeyAVCC, kKeyAVCC, avcc, outsize); 520 } 521 } else if (mime.startsWith("audio/")) { 522 int csd0size = csd0->size(); 523 char esds[csd0size + 31]; 524 reassembleESDS(csd0, esds); 525 meta->setData(kKeyESDS, kKeyESDS, esds, sizeof(esds)); 526 } 527 } 528 529 int32_t timeScale; 530 if (msg->findInt32("time-scale", &timeScale)) { 531 meta->setInt32(kKeyTimeScale, timeScale); 532 } 533 534 // XXX TODO add whatever other keys there are 535 536#if 0 537 ALOGI("converted %s to:", msg->debugString(0).c_str()); 538 meta->dumpToLog(); 539#endif 540} 541 542AString MakeUserAgent() { 543 AString ua; 544 ua.append("stagefright/1.2 (Linux;Android "); 545 546#if (PROPERTY_VALUE_MAX < 8) 547#error "PROPERTY_VALUE_MAX must be at least 8" 548#endif 549 550 char value[PROPERTY_VALUE_MAX]; 551 property_get("ro.build.version.release", value, "Unknown"); 552 ua.append(value); 553 ua.append(")"); 554 555 return ua; 556} 557 558status_t sendMetaDataToHal(sp<MediaPlayerBase::AudioSink>& sink, 559 const sp<MetaData>& meta) 560{ 561 int32_t sampleRate = 0; 562 int32_t bitRate = 0; 563 int32_t channelMask = 0; 564 int32_t delaySamples = 0; 565 int32_t paddingSamples = 0; 566 567 AudioParameter param = AudioParameter(); 568 569 if (meta->findInt32(kKeySampleRate, &sampleRate)) { 570 param.addInt(String8(AUDIO_OFFLOAD_CODEC_SAMPLE_RATE), sampleRate); 571 } 572 if (meta->findInt32(kKeyChannelMask, &channelMask)) { 573 param.addInt(String8(AUDIO_OFFLOAD_CODEC_NUM_CHANNEL), channelMask); 574 } 575 if (meta->findInt32(kKeyBitRate, &bitRate)) { 576 param.addInt(String8(AUDIO_OFFLOAD_CODEC_AVG_BIT_RATE), bitRate); 577 } 578 if (meta->findInt32(kKeyEncoderDelay, &delaySamples)) { 579 param.addInt(String8(AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES), delaySamples); 580 } 581 if (meta->findInt32(kKeyEncoderPadding, &paddingSamples)) { 582 param.addInt(String8(AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES), paddingSamples); 583 } 584 585 ALOGV("sendMetaDataToHal: bitRate %d, sampleRate %d, chanMask %d," 586 "delaySample %d, paddingSample %d", bitRate, sampleRate, 587 channelMask, delaySamples, paddingSamples); 588 589 sink->setParameters(param.toString()); 590 return OK; 591} 592 593struct mime_conv_t { 594 const char* mime; 595 audio_format_t format; 596}; 597 598static const struct mime_conv_t mimeLookup[] = { 599 { MEDIA_MIMETYPE_AUDIO_MPEG, AUDIO_FORMAT_MP3 }, 600 { MEDIA_MIMETYPE_AUDIO_RAW, AUDIO_FORMAT_PCM_16_BIT }, 601 { MEDIA_MIMETYPE_AUDIO_AMR_NB, AUDIO_FORMAT_AMR_NB }, 602 { MEDIA_MIMETYPE_AUDIO_AMR_WB, AUDIO_FORMAT_AMR_WB }, 603 { MEDIA_MIMETYPE_AUDIO_AAC, AUDIO_FORMAT_AAC }, 604 { MEDIA_MIMETYPE_AUDIO_VORBIS, AUDIO_FORMAT_VORBIS }, 605 { MEDIA_MIMETYPE_AUDIO_OPUS, AUDIO_FORMAT_OPUS}, 606 { 0, AUDIO_FORMAT_INVALID } 607}; 608 609status_t mapMimeToAudioFormat( audio_format_t& format, const char* mime ) 610{ 611const struct mime_conv_t* p = &mimeLookup[0]; 612 while (p->mime != NULL) { 613 if (0 == strcasecmp(mime, p->mime)) { 614 format = p->format; 615 return OK; 616 } 617 ++p; 618 } 619 620 return BAD_VALUE; 621} 622 623struct aac_format_conv_t { 624 OMX_AUDIO_AACPROFILETYPE eAacProfileType; 625 audio_format_t format; 626}; 627 628static const struct aac_format_conv_t profileLookup[] = { 629 { OMX_AUDIO_AACObjectMain, AUDIO_FORMAT_AAC_MAIN}, 630 { OMX_AUDIO_AACObjectLC, AUDIO_FORMAT_AAC_LC}, 631 { OMX_AUDIO_AACObjectSSR, AUDIO_FORMAT_AAC_SSR}, 632 { OMX_AUDIO_AACObjectLTP, AUDIO_FORMAT_AAC_LTP}, 633 { OMX_AUDIO_AACObjectHE, AUDIO_FORMAT_AAC_HE_V1}, 634 { OMX_AUDIO_AACObjectScalable, AUDIO_FORMAT_AAC_SCALABLE}, 635 { OMX_AUDIO_AACObjectERLC, AUDIO_FORMAT_AAC_ERLC}, 636 { OMX_AUDIO_AACObjectLD, AUDIO_FORMAT_AAC_LD}, 637 { OMX_AUDIO_AACObjectHE_PS, AUDIO_FORMAT_AAC_HE_V2}, 638 { OMX_AUDIO_AACObjectELD, AUDIO_FORMAT_AAC_ELD}, 639 { OMX_AUDIO_AACObjectNull, AUDIO_FORMAT_AAC}, 640}; 641 642void mapAACProfileToAudioFormat( audio_format_t& format, uint64_t eAacProfile) 643{ 644const struct aac_format_conv_t* p = &profileLookup[0]; 645 while (p->eAacProfileType != OMX_AUDIO_AACObjectNull) { 646 if (eAacProfile == p->eAacProfileType) { 647 format = p->format; 648 return; 649 } 650 ++p; 651 } 652 format = AUDIO_FORMAT_AAC; 653 return; 654} 655 656bool canOffloadStream(const sp<MetaData>& meta, bool hasVideo, 657 bool isStreaming, audio_stream_type_t streamType) 658{ 659 const char *mime; 660 if (meta == NULL) { 661 return false; 662 } 663 CHECK(meta->findCString(kKeyMIMEType, &mime)); 664 665 audio_offload_info_t info = AUDIO_INFO_INITIALIZER; 666 667 info.format = AUDIO_FORMAT_INVALID; 668 if (mapMimeToAudioFormat(info.format, mime) != OK) { 669 ALOGE(" Couldn't map mime type \"%s\" to a valid AudioSystem::audio_format !", mime); 670 return false; 671 } else { 672 ALOGV("Mime type \"%s\" mapped to audio_format %d", mime, info.format); 673 } 674 675 if (AUDIO_FORMAT_INVALID == info.format) { 676 // can't offload if we don't know what the source format is 677 ALOGE("mime type \"%s\" not a known audio format", mime); 678 return false; 679 } 680 681 // Redefine aac format according to its profile 682 // Offloading depends on audio DSP capabilities. 683 int32_t aacaot = -1; 684 if (meta->findInt32(kKeyAACAOT, &aacaot)) { 685 mapAACProfileToAudioFormat(info.format,(OMX_AUDIO_AACPROFILETYPE) aacaot); 686 } 687 688 int32_t srate = -1; 689 if (!meta->findInt32(kKeySampleRate, &srate)) { 690 ALOGV("track of type '%s' does not publish sample rate", mime); 691 } 692 info.sample_rate = srate; 693 694 int32_t cmask = 0; 695 if (!meta->findInt32(kKeyChannelMask, &cmask)) { 696 ALOGV("track of type '%s' does not publish channel mask", mime); 697 698 // Try a channel count instead 699 int32_t channelCount; 700 if (!meta->findInt32(kKeyChannelCount, &channelCount)) { 701 ALOGV("track of type '%s' does not publish channel count", mime); 702 } else { 703 cmask = audio_channel_out_mask_from_count(channelCount); 704 } 705 } 706 info.channel_mask = cmask; 707 708 int64_t duration = 0; 709 if (!meta->findInt64(kKeyDuration, &duration)) { 710 ALOGV("track of type '%s' does not publish duration", mime); 711 } 712 info.duration_us = duration; 713 714 int32_t brate = -1; 715 if (!meta->findInt32(kKeyBitRate, &brate)) { 716 ALOGV("track of type '%s' does not publish bitrate", mime); 717 } 718 info.bit_rate = brate; 719 720 721 info.stream_type = streamType; 722 info.has_video = hasVideo; 723 info.is_streaming = isStreaming; 724 725 // Check if offload is possible for given format, stream type, sample rate, 726 // bit rate, duration, video and streaming 727 return AudioSystem::isOffloadSupported(info); 728} 729 730AString uriDebugString(const AString &uri, bool incognito) { 731 if (incognito) { 732 return AString("<URI suppressed>"); 733 } 734 735 char prop[PROPERTY_VALUE_MAX]; 736 if (property_get("media.stagefright.log-uri", prop, "false") && 737 (!strcmp(prop, "1") || !strcmp(prop, "true"))) { 738 return uri; 739 } 740 741 // find scheme 742 AString scheme; 743 const char *chars = uri.c_str(); 744 for (size_t i = 0; i < uri.size(); i++) { 745 const char c = chars[i]; 746 if (!isascii(c)) { 747 break; 748 } else if (isalpha(c)) { 749 continue; 750 } else if (i == 0) { 751 // first character must be a letter 752 break; 753 } else if (isdigit(c) || c == '+' || c == '.' || c =='-') { 754 continue; 755 } else if (c != ':') { 756 break; 757 } 758 scheme = AString(uri, 0, i); 759 scheme.append("://<suppressed>"); 760 return scheme; 761 } 762 return AString("<no-scheme URI suppressed>"); 763} 764 765} // namespace android 766 767