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