LCOV - code coverage report
Current view: top level - media/libstagefright/frameworks/av/media/libstagefright - Utils.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 23 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 8 0.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.13