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