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 36namespace android { 37using binder::Status; 38using MediaDescrambler::DescrambleInfo; 39using BufferInfo = ACodecBufferChannel::BufferInfo; 40using BufferInfoIterator = std::vector<const BufferInfo>::const_iterator; 41 42ACodecBufferChannel::~ACodecBufferChannel() { 43 if (mCrypto != nullptr && mDealer != nullptr && mHeapSeqNum >= 0) { 44 mCrypto->unsetHeap(mHeapSeqNum); 45 } 46} 47 48static 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 56static 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 64ACodecBufferChannel::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 77ACodecBufferChannel::ACodecBufferChannel( 78 const sp<AMessage> &inputBufferFilled, const sp<AMessage> &outputBufferDrained) 79 : mInputBufferFilled(inputBufferFilled), 80 mOutputBufferDrained(outputBufferDrained), 81 mHeapSeqNum(-1) { 82} 83 84status_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 102status_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 209status_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 228status_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 250void 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 259void 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 268sp<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 287void 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 321void 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 331void 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 350void 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