ACodecBufferChannel.cpp revision 11b72100e02e02b6cd8a6b14cd2068c96dc49b7d
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 <binder/MemoryDealer.h> 24#include <media/openmax/OMX_Core.h> 25#include <media/stagefright/foundation/AMessage.h> 26#include <media/stagefright/foundation/AUtils.h> 27#include <media/stagefright/MediaCodec.h> 28#include <media/MediaCodecBuffer.h> 29#include <system/window.h> 30 31#include "include/ACodecBufferChannel.h" 32#include "include/SecureBuffer.h" 33#include "include/SharedMemoryBuffer.h" 34 35namespace android { 36 37using BufferInfo = ACodecBufferChannel::BufferInfo; 38using BufferInfoIterator = std::vector<const BufferInfo>::const_iterator; 39 40static BufferInfoIterator findClientBuffer( 41 const std::shared_ptr<const std::vector<const BufferInfo>> &array, 42 const sp<MediaCodecBuffer> &buffer) { 43 return std::find_if( 44 array->begin(), array->end(), 45 [buffer](const BufferInfo &info) { return info.mClientBuffer == buffer; }); 46} 47 48static BufferInfoIterator findBufferId( 49 const std::shared_ptr<const std::vector<const BufferInfo>> &array, 50 IOMX::buffer_id bufferId) { 51 return std::find_if( 52 array->begin(), array->end(), 53 [bufferId](const BufferInfo &info) { return bufferId == info.mBufferId; }); 54} 55 56ACodecBufferChannel::BufferInfo::BufferInfo( 57 const sp<MediaCodecBuffer> &buffer, 58 IOMX::buffer_id bufferId, 59 const sp<IMemory> &sharedEncryptedBuffer) 60 : mClientBuffer( 61 (sharedEncryptedBuffer == nullptr) 62 ? buffer 63 : new SharedMemoryBuffer(buffer->format(), sharedEncryptedBuffer)), 64 mCodecBuffer(buffer), 65 mBufferId(bufferId), 66 mSharedEncryptedBuffer(sharedEncryptedBuffer) { 67} 68 69ACodecBufferChannel::ACodecBufferChannel( 70 const sp<AMessage> &inputBufferFilled, const sp<AMessage> &outputBufferDrained) 71 : mInputBufferFilled(inputBufferFilled), 72 mOutputBufferDrained(outputBufferDrained) { 73} 74 75status_t ACodecBufferChannel::queueInputBuffer(const sp<MediaCodecBuffer> &buffer) { 76 std::shared_ptr<const std::vector<const BufferInfo>> array( 77 std::atomic_load(&mInputBuffers)); 78 BufferInfoIterator it = findClientBuffer(array, buffer); 79 if (it == array->end()) { 80 return -ENOENT; 81 } 82 ALOGV("queueInputBuffer #%d", it->mBufferId); 83 sp<AMessage> msg = mInputBufferFilled->dup(); 84 msg->setObject("buffer", it->mCodecBuffer); 85 msg->setInt32("buffer-id", it->mBufferId); 86 msg->post(); 87 return OK; 88} 89 90status_t ACodecBufferChannel::queueSecureInputBuffer( 91 const sp<MediaCodecBuffer> &buffer, 92 bool secure, 93 const uint8_t *key, 94 const uint8_t *iv, 95 CryptoPlugin::Mode mode, 96 CryptoPlugin::Pattern pattern, 97 const CryptoPlugin::SubSample *subSamples, 98 size_t numSubSamples, 99 AString *errorDetailMsg) { 100 if (mCrypto == 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 void *dst_pointer = nullptr; 111 ICrypto::DestinationType dst_type = ICrypto::kDestinationTypeOpaqueHandle; 112 113 if (secure) { 114 sp<SecureBuffer> secureData = static_cast<SecureBuffer *>(it->mCodecBuffer.get()); 115 dst_pointer = secureData->getDestinationPointer(); 116 dst_type = secureData->getDestinationType(); 117 } else { 118 dst_pointer = it->mCodecBuffer->base(); 119 dst_type = ICrypto::kDestinationTypeVmPointer; 120 } 121 122 ssize_t result = mCrypto->decrypt( 123 dst_type, 124 key, 125 iv, 126 mode, 127 pattern, 128 it->mSharedEncryptedBuffer, 129 it->mClientBuffer->offset(), 130 subSamples, 131 numSubSamples, 132 dst_pointer, 133 errorDetailMsg); 134 135 if (result < 0) { 136 return result; 137 } 138 139 it->mCodecBuffer->setRange(0, result); 140 141 // Copy metadata from client to codec buffer. 142 it->mCodecBuffer->meta()->clear(); 143 int64_t timeUs; 144 CHECK(it->mClientBuffer->meta()->findInt64("timeUs", &timeUs)); 145 it->mCodecBuffer->meta()->setInt64("timeUs", timeUs); 146 int32_t eos; 147 if (it->mClientBuffer->meta()->findInt32("eos", &eos)) { 148 it->mCodecBuffer->meta()->setInt32("eos", eos); 149 } 150 int32_t csd; 151 if (it->mClientBuffer->meta()->findInt32("csd", &csd)) { 152 it->mCodecBuffer->meta()->setInt32("csd", csd); 153 } 154 155 ALOGV("queueSecureInputBuffer #%d", it->mBufferId); 156 sp<AMessage> msg = mInputBufferFilled->dup(); 157 msg->setObject("buffer", it->mCodecBuffer); 158 msg->setInt32("buffer-id", it->mBufferId); 159 msg->post(); 160 return OK; 161} 162 163status_t ACodecBufferChannel::renderOutputBuffer( 164 const sp<MediaCodecBuffer> &buffer, int64_t timestampNs) { 165 std::shared_ptr<const std::vector<const BufferInfo>> array( 166 std::atomic_load(&mOutputBuffers)); 167 BufferInfoIterator it = findClientBuffer(array, buffer); 168 if (it == array->end()) { 169 return -ENOENT; 170 } 171 172 ALOGV("renderOutputBuffer #%d", it->mBufferId); 173 sp<AMessage> msg = mOutputBufferDrained->dup(); 174 msg->setObject("buffer", buffer); 175 msg->setInt32("buffer-id", it->mBufferId); 176 msg->setInt32("render", true); 177 msg->setInt64("timestampNs", timestampNs); 178 msg->post(); 179 return OK; 180} 181 182status_t ACodecBufferChannel::discardBuffer(const sp<MediaCodecBuffer> &buffer) { 183 std::shared_ptr<const std::vector<const BufferInfo>> array( 184 std::atomic_load(&mInputBuffers)); 185 bool input = true; 186 BufferInfoIterator it = findClientBuffer(array, buffer); 187 if (it == array->end()) { 188 array = std::atomic_load(&mOutputBuffers); 189 input = false; 190 it = findClientBuffer(array, buffer); 191 if (it == array->end()) { 192 return -ENOENT; 193 } 194 } 195 ALOGV("discardBuffer #%d", it->mBufferId); 196 sp<AMessage> msg = input ? mInputBufferFilled->dup() : mOutputBufferDrained->dup(); 197 msg->setObject("buffer", it->mCodecBuffer); 198 msg->setInt32("buffer-id", it->mBufferId); 199 msg->setInt32("discarded", true); 200 msg->post(); 201 return OK; 202} 203 204void ACodecBufferChannel::getInputBufferArray(Vector<sp<MediaCodecBuffer>> *array) { 205 std::shared_ptr<const std::vector<const BufferInfo>> inputBuffers( 206 std::atomic_load(&mInputBuffers)); 207 array->clear(); 208 for (const BufferInfo &elem : *inputBuffers) { 209 array->push_back(elem.mClientBuffer); 210 } 211} 212 213void ACodecBufferChannel::getOutputBufferArray(Vector<sp<MediaCodecBuffer>> *array) { 214 std::shared_ptr<const std::vector<const BufferInfo>> outputBuffers( 215 std::atomic_load(&mOutputBuffers)); 216 array->clear(); 217 for (const BufferInfo &elem : *outputBuffers) { 218 array->push_back(elem.mClientBuffer); 219 } 220} 221 222void ACodecBufferChannel::setInputBufferArray(const std::vector<BufferAndId> &array) { 223 bool secure = (mCrypto != nullptr); 224 if (secure) { 225 size_t totalSize = std::accumulate( 226 array.begin(), array.end(), 0u, 227 [alignment = MemoryDealer::getAllocationAlignment()] 228 (size_t sum, const BufferAndId& elem) { 229 return sum + align(elem.mBuffer->capacity(), alignment); 230 }); 231 mDealer = new MemoryDealer(totalSize, "ACodecBufferChannel"); 232 } 233 std::vector<const BufferInfo> inputBuffers; 234 for (const BufferAndId &elem : array) { 235 sp<IMemory> sharedEncryptedBuffer; 236 if (secure) { 237 sharedEncryptedBuffer = mDealer->allocate(elem.mBuffer->capacity()); 238 } 239 inputBuffers.emplace_back(elem.mBuffer, elem.mBufferId, sharedEncryptedBuffer); 240 } 241 std::atomic_store( 242 &mInputBuffers, 243 std::make_shared<const std::vector<const BufferInfo>>(inputBuffers)); 244} 245 246void ACodecBufferChannel::setOutputBufferArray(const std::vector<BufferAndId> &array) { 247 std::vector<const BufferInfo> outputBuffers; 248 for (const BufferAndId &elem : array) { 249 outputBuffers.emplace_back(elem.mBuffer, elem.mBufferId, nullptr); 250 } 251 std::atomic_store( 252 &mOutputBuffers, 253 std::make_shared<const std::vector<const BufferInfo>>(outputBuffers)); 254} 255 256void ACodecBufferChannel::fillThisBuffer(IOMX::buffer_id bufferId) { 257 ALOGV("fillThisBuffer #%d", bufferId); 258 std::shared_ptr<const std::vector<const BufferInfo>> array( 259 std::atomic_load(&mInputBuffers)); 260 BufferInfoIterator it = findBufferId(array, bufferId); 261 262 if (it == array->end()) { 263 ALOGE("fillThisBuffer: unrecognized buffer #%d", bufferId); 264 return; 265 } 266 if (it->mClientBuffer != it->mCodecBuffer) { 267 it->mClientBuffer->setFormat(it->mCodecBuffer->format()); 268 } 269 270 mCallback->onInputBufferAvailable( 271 std::distance(array->begin(), it), 272 it->mClientBuffer); 273} 274 275void ACodecBufferChannel::drainThisBuffer( 276 IOMX::buffer_id bufferId, 277 OMX_U32 omxFlags) { 278 ALOGV("drainThisBuffer #%d", bufferId); 279 std::shared_ptr<const std::vector<const BufferInfo>> array( 280 std::atomic_load(&mOutputBuffers)); 281 BufferInfoIterator it = findBufferId(array, bufferId); 282 283 if (it == array->end()) { 284 ALOGE("drainThisBuffer: unrecognized buffer #%d", bufferId); 285 return; 286 } 287 if (it->mClientBuffer != it->mCodecBuffer) { 288 it->mClientBuffer->setFormat(it->mCodecBuffer->format()); 289 } 290 291 uint32_t flags = 0; 292 if (omxFlags & OMX_BUFFERFLAG_SYNCFRAME) { 293 flags |= MediaCodec::BUFFER_FLAG_SYNCFRAME; 294 } 295 if (omxFlags & OMX_BUFFERFLAG_CODECCONFIG) { 296 flags |= MediaCodec::BUFFER_FLAG_CODECCONFIG; 297 } 298 if (omxFlags & OMX_BUFFERFLAG_EOS) { 299 flags |= MediaCodec::BUFFER_FLAG_EOS; 300 } 301 it->mClientBuffer->meta()->setInt32("flags", flags); 302 303 mCallback->onOutputBufferAvailable( 304 std::distance(array->begin(), it), 305 it->mClientBuffer); 306} 307 308} // namespace android 309