Home | History | Annotate | Download | only in libstagefright
      1 /*
      2  * Copyright 2016, 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 "ACodecBufferChannel"
     19 #include <utils/Log.h>
     20 
     21 #include <numeric>
     22 
     23 #include <android/media/IDescrambler.h>
     24 #include <binder/MemoryDealer.h>
     25 #include <media/openmax/OMX_Core.h>
     26 #include <media/stagefright/foundation/AMessage.h>
     27 #include <media/stagefright/foundation/AUtils.h>
     28 #include <media/stagefright/MediaCodec.h>
     29 #include <media/MediaCodecBuffer.h>
     30 #include <system/window.h>
     31 
     32 #include "include/ACodecBufferChannel.h"
     33 #include "include/SecureBuffer.h"
     34 #include "include/SharedMemoryBuffer.h"
     35 
     36 namespace android {
     37 using binder::Status;
     38 using MediaDescrambler::DescrambleInfo;
     39 using BufferInfo = ACodecBufferChannel::BufferInfo;
     40 using BufferInfoIterator = std::vector<const BufferInfo>::const_iterator;
     41 
     42 ACodecBufferChannel::~ACodecBufferChannel() {
     43     if (mCrypto != nullptr && mDealer != nullptr && mHeapSeqNum >= 0) {
     44         mCrypto->unsetHeap(mHeapSeqNum);
     45     }
     46 }
     47 
     48 static BufferInfoIterator findClientBuffer(
     49         const std::shared_ptr<const std::vector<const BufferInfo>> &array,
     50         const sp<MediaCodecBuffer> &buffer) {
     51     return std::find_if(
     52             array->begin(), array->end(),
     53             [buffer](const BufferInfo &info) { return info.mClientBuffer == buffer; });
     54 }
     55 
     56 static BufferInfoIterator findBufferId(
     57         const std::shared_ptr<const std::vector<const BufferInfo>> &array,
     58         IOMX::buffer_id bufferId) {
     59     return std::find_if(
     60             array->begin(), array->end(),
     61             [bufferId](const BufferInfo &info) { return bufferId == info.mBufferId; });
     62 }
     63 
     64 ACodecBufferChannel::BufferInfo::BufferInfo(
     65         const sp<MediaCodecBuffer> &buffer,
     66         IOMX::buffer_id bufferId,
     67         const sp<IMemory> &sharedEncryptedBuffer)
     68     : mClientBuffer(
     69           (sharedEncryptedBuffer == nullptr)
     70           ? buffer
     71           : new SharedMemoryBuffer(buffer->format(), sharedEncryptedBuffer)),
     72       mCodecBuffer(buffer),
     73       mBufferId(bufferId),
     74       mSharedEncryptedBuffer(sharedEncryptedBuffer) {
     75 }
     76 
     77 ACodecBufferChannel::ACodecBufferChannel(
     78         const sp<AMessage> &inputBufferFilled, const sp<AMessage> &outputBufferDrained)
     79     : mInputBufferFilled(inputBufferFilled),
     80       mOutputBufferDrained(outputBufferDrained),
     81       mHeapSeqNum(-1) {
     82 }
     83 
     84 status_t ACodecBufferChannel::queueInputBuffer(const sp<MediaCodecBuffer> &buffer) {
     85     if (mDealer != nullptr) {
     86         return -ENOSYS;
     87     }
     88     std::shared_ptr<const std::vector<const BufferInfo>> array(
     89             std::atomic_load(&mInputBuffers));
     90     BufferInfoIterator it = findClientBuffer(array, buffer);
     91     if (it == array->end()) {
     92         return -ENOENT;
     93     }
     94     ALOGV("queueInputBuffer #%d", it->mBufferId);
     95     sp<AMessage> msg = mInputBufferFilled->dup();
     96     msg->setObject("buffer", it->mCodecBuffer);
     97     msg->setInt32("buffer-id", it->mBufferId);
     98     msg->post();
     99     return OK;
    100 }
    101 
    102 status_t ACodecBufferChannel::queueSecureInputBuffer(
    103         const sp<MediaCodecBuffer> &buffer, bool secure, const uint8_t *key,
    104         const uint8_t *iv, CryptoPlugin::Mode mode, CryptoPlugin::Pattern pattern,
    105         const CryptoPlugin::SubSample *subSamples, size_t numSubSamples,
    106         AString *errorDetailMsg) {
    107     if (!hasCryptoOrDescrambler() || mDealer == nullptr) {
    108         return -ENOSYS;
    109     }
    110     std::shared_ptr<const std::vector<const BufferInfo>> array(
    111             std::atomic_load(&mInputBuffers));
    112     BufferInfoIterator it = findClientBuffer(array, buffer);
    113     if (it == array->end()) {
    114         return -ENOENT;
    115     }
    116 
    117     ICrypto::DestinationBuffer destination;
    118     if (secure) {
    119         sp<SecureBuffer> secureData =
    120                 static_cast<SecureBuffer *>(it->mCodecBuffer.get());
    121         destination.mType = secureData->getDestinationType();
    122         if (destination.mType != ICrypto::kDestinationTypeNativeHandle) {
    123             return BAD_VALUE;
    124         }
    125         destination.mHandle =
    126                 static_cast<native_handle_t *>(secureData->getDestinationPointer());
    127     } else {
    128         destination.mType = ICrypto::kDestinationTypeSharedMemory;
    129         destination.mSharedMemory = mDecryptDestination;
    130     }
    131 
    132     ICrypto::SourceBuffer source;
    133     source.mSharedMemory = it->mSharedEncryptedBuffer;
    134     source.mHeapSeqNum = mHeapSeqNum;
    135 
    136     ssize_t result = -1;
    137     if (mCrypto != NULL) {
    138         result = mCrypto->decrypt(key, iv, mode, pattern,
    139                 source, it->mClientBuffer->offset(),
    140                 subSamples, numSubSamples, destination, errorDetailMsg);
    141     } else {
    142         DescrambleInfo descrambleInfo;
    143         descrambleInfo.dstType = destination.mType ==
    144                 ICrypto::kDestinationTypeSharedMemory ?
    145                 DescrambleInfo::kDestinationTypeVmPointer :
    146                 DescrambleInfo::kDestinationTypeNativeHandle;
    147         descrambleInfo.scramblingControl = key != NULL ?
    148                 (DescramblerPlugin::ScramblingControl)key[0] :
    149                 DescramblerPlugin::kScrambling_Unscrambled;
    150         descrambleInfo.numSubSamples = numSubSamples;
    151         descrambleInfo.subSamples = (DescramblerPlugin::SubSample *)subSamples;
    152         descrambleInfo.srcMem = it->mSharedEncryptedBuffer;
    153         descrambleInfo.srcOffset = 0;
    154         descrambleInfo.dstPtr = NULL;
    155         descrambleInfo.dstOffset = 0;
    156 
    157         int32_t descrambleResult = -1;
    158         Status status = mDescrambler->descramble(descrambleInfo, &descrambleResult);
    159 
    160         if (status.isOk()) {
    161             result = descrambleResult;
    162         }
    163 
    164         if (result < 0) {
    165             ALOGE("descramble failed, exceptionCode=%d, err=%d, result=%zd",
    166                     status.exceptionCode(), status.transactionError(), result);
    167         } else {
    168             ALOGV("descramble succeeded, result=%zd", result);
    169         }
    170 
    171         if (result > 0 && destination.mType == ICrypto::kDestinationTypeSharedMemory) {
    172             memcpy(destination.mSharedMemory->pointer(),
    173                     (uint8_t*)it->mSharedEncryptedBuffer->pointer(), result);
    174         }
    175     }
    176 
    177     if (result < 0) {
    178         return result;
    179     }
    180 
    181     if (destination.mType == ICrypto::kDestinationTypeSharedMemory) {
    182         memcpy(it->mCodecBuffer->base(), destination.mSharedMemory->pointer(), result);
    183     }
    184 
    185     it->mCodecBuffer->setRange(0, result);
    186 
    187     // Copy metadata from client to codec buffer.
    188     it->mCodecBuffer->meta()->clear();
    189     int64_t timeUs;
    190     CHECK(it->mClientBuffer->meta()->findInt64("timeUs", &timeUs));
    191     it->mCodecBuffer->meta()->setInt64("timeUs", timeUs);
    192     int32_t eos;
    193     if (it->mClientBuffer->meta()->findInt32("eos", &eos)) {
    194         it->mCodecBuffer->meta()->setInt32("eos", eos);
    195     }
    196     int32_t csd;
    197     if (it->mClientBuffer->meta()->findInt32("csd", &csd)) {
    198         it->mCodecBuffer->meta()->setInt32("csd", csd);
    199     }
    200 
    201     ALOGV("queueSecureInputBuffer #%d", it->mBufferId);
    202     sp<AMessage> msg = mInputBufferFilled->dup();
    203     msg->setObject("buffer", it->mCodecBuffer);
    204     msg->setInt32("buffer-id", it->mBufferId);
    205     msg->post();
    206     return OK;
    207 }
    208 
    209 status_t ACodecBufferChannel::renderOutputBuffer(
    210         const sp<MediaCodecBuffer> &buffer, int64_t timestampNs) {
    211     std::shared_ptr<const std::vector<const BufferInfo>> array(
    212             std::atomic_load(&mOutputBuffers));
    213     BufferInfoIterator it = findClientBuffer(array, buffer);
    214     if (it == array->end()) {
    215         return -ENOENT;
    216     }
    217 
    218     ALOGV("renderOutputBuffer #%d", it->mBufferId);
    219     sp<AMessage> msg = mOutputBufferDrained->dup();
    220     msg->setObject("buffer", buffer);
    221     msg->setInt32("buffer-id", it->mBufferId);
    222     msg->setInt32("render", true);
    223     msg->setInt64("timestampNs", timestampNs);
    224     msg->post();
    225     return OK;
    226 }
    227 
    228 status_t ACodecBufferChannel::discardBuffer(const sp<MediaCodecBuffer> &buffer) {
    229     std::shared_ptr<const std::vector<const BufferInfo>> array(
    230             std::atomic_load(&mInputBuffers));
    231     bool input = true;
    232     BufferInfoIterator it = findClientBuffer(array, buffer);
    233     if (it == array->end()) {
    234         array = std::atomic_load(&mOutputBuffers);
    235         input = false;
    236         it = findClientBuffer(array, buffer);
    237         if (it == array->end()) {
    238             return -ENOENT;
    239         }
    240     }
    241     ALOGV("discardBuffer #%d", it->mBufferId);
    242     sp<AMessage> msg = input ? mInputBufferFilled->dup() : mOutputBufferDrained->dup();
    243     msg->setObject("buffer", it->mCodecBuffer);
    244     msg->setInt32("buffer-id", it->mBufferId);
    245     msg->setInt32("discarded", true);
    246     msg->post();
    247     return OK;
    248 }
    249 
    250 void ACodecBufferChannel::getInputBufferArray(Vector<sp<MediaCodecBuffer>> *array) {
    251     std::shared_ptr<const std::vector<const BufferInfo>> inputBuffers(
    252             std::atomic_load(&mInputBuffers));
    253     array->clear();
    254     for (const BufferInfo &elem : *inputBuffers) {
    255         array->push_back(elem.mClientBuffer);
    256     }
    257 }
    258 
    259 void ACodecBufferChannel::getOutputBufferArray(Vector<sp<MediaCodecBuffer>> *array) {
    260     std::shared_ptr<const std::vector<const BufferInfo>> outputBuffers(
    261             std::atomic_load(&mOutputBuffers));
    262     array->clear();
    263     for (const BufferInfo &elem : *outputBuffers) {
    264         array->push_back(elem.mClientBuffer);
    265     }
    266 }
    267 
    268 sp<MemoryDealer> ACodecBufferChannel::makeMemoryDealer(size_t heapSize) {
    269     sp<MemoryDealer> dealer;
    270     if (mDealer != nullptr && mCrypto != nullptr && mHeapSeqNum >= 0) {
    271         mCrypto->unsetHeap(mHeapSeqNum);
    272     }
    273     dealer = new MemoryDealer(heapSize, "ACodecBufferChannel");
    274     if (mCrypto != nullptr) {
    275         int32_t seqNum = mCrypto->setHeap(dealer->getMemoryHeap());
    276         if (seqNum >= 0) {
    277             mHeapSeqNum = seqNum;
    278             ALOGD("setHeap returned mHeapSeqNum=%d", mHeapSeqNum);
    279         } else {
    280             mHeapSeqNum = -1;
    281             ALOGD("setHeap failed, setting mHeapSeqNum=-1");
    282         }
    283     }
    284     return dealer;
    285 }
    286 
    287 void ACodecBufferChannel::setInputBufferArray(const std::vector<BufferAndId> &array) {
    288     if (hasCryptoOrDescrambler()) {
    289         size_t totalSize = std::accumulate(
    290                 array.begin(), array.end(), 0u,
    291                 [alignment = MemoryDealer::getAllocationAlignment()]
    292                 (size_t sum, const BufferAndId& elem) {
    293                     return sum + align(elem.mBuffer->capacity(), alignment);
    294                 });
    295         size_t maxSize = std::accumulate(
    296                 array.begin(), array.end(), 0u,
    297                 [alignment = MemoryDealer::getAllocationAlignment()]
    298                 (size_t max, const BufferAndId& elem) {
    299                     return std::max(max, align(elem.mBuffer->capacity(), alignment));
    300                 });
    301         size_t destinationBufferSize = maxSize;
    302         size_t heapSize = totalSize + destinationBufferSize;
    303         if (heapSize > 0) {
    304             mDealer = makeMemoryDealer(heapSize);
    305             mDecryptDestination = mDealer->allocate(destinationBufferSize);
    306         }
    307     }
    308     std::vector<const BufferInfo> inputBuffers;
    309     for (const BufferAndId &elem : array) {
    310         sp<IMemory> sharedEncryptedBuffer;
    311         if (hasCryptoOrDescrambler()) {
    312             sharedEncryptedBuffer = mDealer->allocate(elem.mBuffer->capacity());
    313         }
    314         inputBuffers.emplace_back(elem.mBuffer, elem.mBufferId, sharedEncryptedBuffer);
    315     }
    316     std::atomic_store(
    317             &mInputBuffers,
    318             std::make_shared<const std::vector<const BufferInfo>>(inputBuffers));
    319 }
    320 
    321 void ACodecBufferChannel::setOutputBufferArray(const std::vector<BufferAndId> &array) {
    322     std::vector<const BufferInfo> outputBuffers;
    323     for (const BufferAndId &elem : array) {
    324         outputBuffers.emplace_back(elem.mBuffer, elem.mBufferId, nullptr);
    325     }
    326     std::atomic_store(
    327             &mOutputBuffers,
    328             std::make_shared<const std::vector<const BufferInfo>>(outputBuffers));
    329 }
    330 
    331 void ACodecBufferChannel::fillThisBuffer(IOMX::buffer_id bufferId) {
    332     ALOGV("fillThisBuffer #%d", bufferId);
    333     std::shared_ptr<const std::vector<const BufferInfo>> array(
    334             std::atomic_load(&mInputBuffers));
    335     BufferInfoIterator it = findBufferId(array, bufferId);
    336 
    337     if (it == array->end()) {
    338         ALOGE("fillThisBuffer: unrecognized buffer #%d", bufferId);
    339         return;
    340     }
    341     if (it->mClientBuffer != it->mCodecBuffer) {
    342         it->mClientBuffer->setFormat(it->mCodecBuffer->format());
    343     }
    344 
    345     mCallback->onInputBufferAvailable(
    346             std::distance(array->begin(), it),
    347             it->mClientBuffer);
    348 }
    349 
    350 void ACodecBufferChannel::drainThisBuffer(
    351         IOMX::buffer_id bufferId,
    352         OMX_U32 omxFlags) {
    353     ALOGV("drainThisBuffer #%d", bufferId);
    354     std::shared_ptr<const std::vector<const BufferInfo>> array(
    355             std::atomic_load(&mOutputBuffers));
    356     BufferInfoIterator it = findBufferId(array, bufferId);
    357 
    358     if (it == array->end()) {
    359         ALOGE("drainThisBuffer: unrecognized buffer #%d", bufferId);
    360         return;
    361     }
    362     if (it->mClientBuffer != it->mCodecBuffer) {
    363         it->mClientBuffer->setFormat(it->mCodecBuffer->format());
    364     }
    365 
    366     uint32_t flags = 0;
    367     if (omxFlags & OMX_BUFFERFLAG_SYNCFRAME) {
    368         flags |= MediaCodec::BUFFER_FLAG_SYNCFRAME;
    369     }
    370     if (omxFlags & OMX_BUFFERFLAG_CODECCONFIG) {
    371         flags |= MediaCodec::BUFFER_FLAG_CODECCONFIG;
    372     }
    373     if (omxFlags & OMX_BUFFERFLAG_EOS) {
    374         flags |= MediaCodec::BUFFER_FLAG_EOS;
    375     }
    376     it->mClientBuffer->meta()->setInt32("flags", flags);
    377 
    378     mCallback->onOutputBufferAvailable(
    379             std::distance(array->begin(), it),
    380             it->mClientBuffer);
    381 }
    382 
    383 }  // namespace android
    384