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