Home | History | Annotate | Download | only in libnbaio
      1 /*
      2  * Copyright (C) 2012 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_TAG "NBAIO"
     18 //#define LOG_NDEBUG 0
     19 
     20 #include <utils/Log.h>
     21 #include <media/nbaio/NBAIO.h>
     22 
     23 namespace android {
     24 
     25 size_t Format_frameSize(const NBAIO_Format& format)
     26 {
     27     return format.mFrameSize;
     28 }
     29 
     30 const NBAIO_Format Format_Invalid = { 0, 0, AUDIO_FORMAT_INVALID, 0 };
     31 
     32 unsigned Format_sampleRate(const NBAIO_Format& format)
     33 {
     34     if (!Format_isValid(format)) {
     35         return 0;
     36     }
     37     return format.mSampleRate;
     38 }
     39 
     40 unsigned Format_channelCount(const NBAIO_Format& format)
     41 {
     42     if (!Format_isValid(format)) {
     43         return 0;
     44     }
     45     return format.mChannelCount;
     46 }
     47 
     48 NBAIO_Format Format_from_SR_C(unsigned sampleRate, unsigned channelCount,
     49         audio_format_t format)
     50 {
     51     if (sampleRate == 0 || channelCount == 0 || !audio_is_valid_format(format)) {
     52         return Format_Invalid;
     53     }
     54     NBAIO_Format ret;
     55     ret.mSampleRate = sampleRate;
     56     ret.mChannelCount = channelCount;
     57     ret.mFormat = format;
     58     ret.mFrameSize = audio_is_linear_pcm(format) ?
     59             channelCount * audio_bytes_per_sample(format) : sizeof(uint8_t);
     60     return ret;
     61 }
     62 
     63 // This is a default implementation; it is expected that subclasses will optimize this.
     64 ssize_t NBAIO_Sink::writeVia(writeVia_t via, size_t total, void *user, size_t block)
     65 {
     66     if (!mNegotiated) {
     67         return (ssize_t) NEGOTIATE;
     68     }
     69     static const size_t maxBlock = 32;
     70     size_t frameSize = Format_frameSize(mFormat);
     71     ALOG_ASSERT(frameSize > 0 && frameSize <= 8);
     72     // double guarantees alignment for stack similar to what malloc() gives for heap
     73     if (block == 0 || block > maxBlock) {
     74         block = maxBlock;
     75     }
     76     double buffer[((frameSize * block) + sizeof(double) - 1) / sizeof(double)];
     77     size_t accumulator = 0;
     78     while (accumulator < total) {
     79         size_t count = total - accumulator;
     80         if (count > block) {
     81             count = block;
     82         }
     83         ssize_t ret = via(user, buffer, count);
     84         if (ret > 0) {
     85             ALOG_ASSERT((size_t) ret <= count);
     86             size_t maxRet = ret;
     87             ret = write(buffer, maxRet);
     88             if (ret > 0) {
     89                 ALOG_ASSERT((size_t) ret <= maxRet);
     90                 accumulator += ret;
     91                 continue;
     92             }
     93         }
     94         return accumulator > 0 ? accumulator : ret;
     95     }
     96     return accumulator;
     97 }
     98 
     99 // This is a default implementation; it is expected that subclasses will optimize this.
    100 ssize_t NBAIO_Source::readVia(readVia_t via, size_t total, void *user,
    101                               int64_t readPTS, size_t block)
    102 {
    103     if (!mNegotiated) {
    104         return (ssize_t) NEGOTIATE;
    105     }
    106     static const size_t maxBlock = 32;
    107     size_t frameSize = Format_frameSize(mFormat);
    108     ALOG_ASSERT(frameSize > 0 && frameSize <= 8);
    109     // double guarantees alignment for stack similar to what malloc() gives for heap
    110     if (block == 0 || block > maxBlock) {
    111         block = maxBlock;
    112     }
    113     double buffer[((frameSize * block) + sizeof(double) - 1) / sizeof(double)];
    114     size_t accumulator = 0;
    115     while (accumulator < total) {
    116         size_t count = total - accumulator;
    117         if (count > block) {
    118             count = block;
    119         }
    120         ssize_t ret = read(buffer, count, readPTS);
    121         if (ret > 0) {
    122             ALOG_ASSERT((size_t) ret <= count);
    123             size_t maxRet = ret;
    124             ret = via(user, buffer, maxRet, readPTS);
    125             if (ret > 0) {
    126                 ALOG_ASSERT((size_t) ret <= maxRet);
    127                 accumulator += ret;
    128                 continue;
    129             }
    130         }
    131         return accumulator > 0 ? accumulator : ret;
    132     }
    133     return accumulator;
    134 }
    135 
    136 // Default implementation that only accepts my mFormat
    137 ssize_t NBAIO_Port::negotiate(const NBAIO_Format offers[], size_t numOffers,
    138                                   NBAIO_Format counterOffers[], size_t& numCounterOffers)
    139 {
    140     ALOGV("negotiate offers=%p numOffers=%zu countersOffers=%p numCounterOffers=%zu",
    141             offers, numOffers, counterOffers, numCounterOffers);
    142     if (Format_isValid(mFormat)) {
    143         for (size_t i = 0; i < numOffers; ++i) {
    144             if (Format_isEqual(offers[i], mFormat)) {
    145                 mNegotiated = true;
    146                 return i;
    147             }
    148         }
    149         if (numCounterOffers > 0) {
    150             counterOffers[0] = mFormat;
    151         }
    152         numCounterOffers = 1;
    153     } else {
    154         numCounterOffers = 0;
    155     }
    156     return (ssize_t) NEGOTIATE;
    157 }
    158 
    159 bool Format_isValid(const NBAIO_Format& format)
    160 {
    161     return format.mSampleRate != 0 && format.mChannelCount != 0 &&
    162             format.mFormat != AUDIO_FORMAT_INVALID && format.mFrameSize != 0;
    163 }
    164 
    165 bool Format_isEqual(const NBAIO_Format& format1, const NBAIO_Format& format2)
    166 {
    167     return format1.mSampleRate == format2.mSampleRate &&
    168             format1.mChannelCount == format2.mChannelCount && format1.mFormat == format2.mFormat &&
    169             format1.mFrameSize == format2.mFrameSize;
    170 }
    171 
    172 }   // namespace android
    173