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