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