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