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