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