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 <C2Buffer.h>
24
25 #include <Codec2BufferUtils.h>
26
27 #include <android/hardware/cas/native/1.0/IDescrambler.h>
28 #include <android/hardware/drm/1.0/types.h>
29 #include <binder/MemoryDealer.h>
30 #include <hidlmemory/FrameworkUtils.h>
31 #include <media/openmax/OMX_Core.h>
32 #include <media/stagefright/foundation/ABuffer.h>
33 #include <media/stagefright/foundation/AMessage.h>
34 #include <media/stagefright/foundation/AUtils.h>
35 #include <media/stagefright/MediaCodec.h>
36 #include <media/MediaCodecBuffer.h>
37 #include <system/window.h>
38
39 #include "include/ACodecBufferChannel.h"
40 #include "include/SecureBuffer.h"
41 #include "include/SharedMemoryBuffer.h"
42
43 namespace android {
44 using hardware::fromHeap;
45 using hardware::hidl_handle;
46 using hardware::hidl_string;
47 using hardware::hidl_vec;
48 using namespace hardware::cas::V1_0;
49 using namespace hardware::cas::native::V1_0;
50 using DrmBufferType = hardware::drm::V1_0::BufferType;
51 using BufferInfo = ACodecBufferChannel::BufferInfo;
52 using BufferInfoIterator = std::vector<const BufferInfo>::const_iterator;
53
~ACodecBufferChannel()54 ACodecBufferChannel::~ACodecBufferChannel() {
55 if (mCrypto != nullptr && mDealer != nullptr && mHeapSeqNum >= 0) {
56 mCrypto->unsetHeap(mHeapSeqNum);
57 }
58 }
59
findClientBuffer(const std::shared_ptr<const std::vector<const BufferInfo>> & array,const sp<MediaCodecBuffer> & buffer)60 static BufferInfoIterator findClientBuffer(
61 const std::shared_ptr<const std::vector<const BufferInfo>> &array,
62 const sp<MediaCodecBuffer> &buffer) {
63 return std::find_if(
64 array->begin(), array->end(),
65 [buffer](const BufferInfo &info) { return info.mClientBuffer == buffer; });
66 }
67
findBufferId(const std::shared_ptr<const std::vector<const BufferInfo>> & array,IOMX::buffer_id bufferId)68 static BufferInfoIterator findBufferId(
69 const std::shared_ptr<const std::vector<const BufferInfo>> &array,
70 IOMX::buffer_id bufferId) {
71 return std::find_if(
72 array->begin(), array->end(),
73 [bufferId](const BufferInfo &info) { return bufferId == info.mBufferId; });
74 }
75
BufferInfo(const sp<MediaCodecBuffer> & buffer,IOMX::buffer_id bufferId,const sp<IMemory> & sharedEncryptedBuffer)76 ACodecBufferChannel::BufferInfo::BufferInfo(
77 const sp<MediaCodecBuffer> &buffer,
78 IOMX::buffer_id bufferId,
79 const sp<IMemory> &sharedEncryptedBuffer)
80 : mClientBuffer(
81 (sharedEncryptedBuffer == nullptr)
82 ? buffer
83 : new SharedMemoryBuffer(buffer->format(), sharedEncryptedBuffer)),
84 mCodecBuffer(buffer),
85 mBufferId(bufferId),
86 mSharedEncryptedBuffer(sharedEncryptedBuffer) {
87 }
88
ACodecBufferChannel(const sp<AMessage> & inputBufferFilled,const sp<AMessage> & outputBufferDrained)89 ACodecBufferChannel::ACodecBufferChannel(
90 const sp<AMessage> &inputBufferFilled, const sp<AMessage> &outputBufferDrained)
91 : mInputBufferFilled(inputBufferFilled),
92 mOutputBufferDrained(outputBufferDrained),
93 mHeapSeqNum(-1) {
94 }
95
queueInputBuffer(const sp<MediaCodecBuffer> & buffer)96 status_t ACodecBufferChannel::queueInputBuffer(const sp<MediaCodecBuffer> &buffer) {
97 std::shared_ptr<const std::vector<const BufferInfo>> array(
98 std::atomic_load(&mInputBuffers));
99 BufferInfoIterator it = findClientBuffer(array, buffer);
100 if (it == array->end()) {
101 return -ENOENT;
102 }
103 if (it->mClientBuffer != it->mCodecBuffer) {
104 // Copy metadata from client to codec buffer.
105 it->mCodecBuffer->meta()->clear();
106 int64_t timeUs;
107 CHECK(it->mClientBuffer->meta()->findInt64("timeUs", &timeUs));
108 it->mCodecBuffer->meta()->setInt64("timeUs", timeUs);
109 int32_t eos;
110 if (it->mClientBuffer->meta()->findInt32("eos", &eos)) {
111 it->mCodecBuffer->meta()->setInt32("eos", eos);
112 }
113 int32_t csd;
114 if (it->mClientBuffer->meta()->findInt32("csd", &csd)) {
115 it->mCodecBuffer->meta()->setInt32("csd", csd);
116 }
117 }
118 ALOGV("queueInputBuffer #%d", it->mBufferId);
119 sp<AMessage> msg = mInputBufferFilled->dup();
120 msg->setObject("buffer", it->mCodecBuffer);
121 msg->setInt32("buffer-id", it->mBufferId);
122 msg->post();
123 return OK;
124 }
125
queueSecureInputBuffer(const sp<MediaCodecBuffer> & buffer,bool secure,const uint8_t * key,const uint8_t * iv,CryptoPlugin::Mode mode,CryptoPlugin::Pattern pattern,const CryptoPlugin::SubSample * subSamples,size_t numSubSamples,AString * errorDetailMsg)126 status_t ACodecBufferChannel::queueSecureInputBuffer(
127 const sp<MediaCodecBuffer> &buffer, bool secure, const uint8_t *key,
128 const uint8_t *iv, CryptoPlugin::Mode mode, CryptoPlugin::Pattern pattern,
129 const CryptoPlugin::SubSample *subSamples, size_t numSubSamples,
130 AString *errorDetailMsg) {
131 if (!hasCryptoOrDescrambler() || mDealer == nullptr) {
132 return -ENOSYS;
133 }
134 std::shared_ptr<const std::vector<const BufferInfo>> array(
135 std::atomic_load(&mInputBuffers));
136 BufferInfoIterator it = findClientBuffer(array, buffer);
137 if (it == array->end()) {
138 return -ENOENT;
139 }
140
141 native_handle_t *secureHandle = NULL;
142 if (secure) {
143 sp<SecureBuffer> secureData =
144 static_cast<SecureBuffer *>(it->mCodecBuffer.get());
145 if (secureData->getDestinationType() != ICrypto::kDestinationTypeNativeHandle) {
146 return BAD_VALUE;
147 }
148 secureHandle = static_cast<native_handle_t *>(secureData->getDestinationPointer());
149 }
150 ssize_t result = -1;
151 ssize_t codecDataOffset = 0;
152 if (numSubSamples == 1
153 && subSamples[0].mNumBytesOfClearData == 0
154 && subSamples[0].mNumBytesOfEncryptedData == 0) {
155 // We don't need to go through crypto or descrambler if the input is empty.
156 result = 0;
157 } else if (mCrypto != NULL) {
158 hardware::drm::V1_0::DestinationBuffer destination;
159 if (secure) {
160 destination.type = DrmBufferType::NATIVE_HANDLE;
161 destination.secureMemory = hidl_handle(secureHandle);
162 } else {
163 destination.type = DrmBufferType::SHARED_MEMORY;
164 IMemoryToSharedBuffer(
165 mDecryptDestination, mHeapSeqNum, &destination.nonsecureMemory);
166 }
167
168 hardware::drm::V1_0::SharedBuffer source;
169 IMemoryToSharedBuffer(it->mSharedEncryptedBuffer, mHeapSeqNum, &source);
170
171 result = mCrypto->decrypt(key, iv, mode, pattern,
172 source, it->mClientBuffer->offset(),
173 subSamples, numSubSamples, destination, errorDetailMsg);
174
175 if (result < 0) {
176 return result;
177 }
178
179 if (destination.type == DrmBufferType::SHARED_MEMORY) {
180 memcpy(it->mCodecBuffer->base(), mDecryptDestination->unsecurePointer(), result);
181 }
182 } else {
183 // Here we cast CryptoPlugin::SubSample to hardware::cas::native::V1_0::SubSample
184 // directly, the structure definitions should match as checked in DescramblerImpl.cpp.
185 hidl_vec<SubSample> hidlSubSamples;
186 hidlSubSamples.setToExternal((SubSample *)subSamples, numSubSamples, false /*own*/);
187
188 ssize_t offset;
189 size_t size;
190 it->mSharedEncryptedBuffer->getMemory(&offset, &size);
191 hardware::cas::native::V1_0::SharedBuffer srcBuffer = {
192 .heapBase = *mHidlMemory,
193 .offset = (uint64_t) offset,
194 .size = size
195 };
196
197 DestinationBuffer dstBuffer;
198 if (secure) {
199 dstBuffer.type = BufferType::NATIVE_HANDLE;
200 dstBuffer.secureMemory = hidl_handle(secureHandle);
201 } else {
202 dstBuffer.type = BufferType::SHARED_MEMORY;
203 dstBuffer.nonsecureMemory = srcBuffer;
204 }
205
206 Status status = Status::OK;
207 hidl_string detailedError;
208 ScramblingControl sctrl = ScramblingControl::UNSCRAMBLED;
209
210 if (key != NULL) {
211 sctrl = (ScramblingControl)key[0];
212 // Adjust for the PES offset
213 codecDataOffset = key[2] | (key[3] << 8);
214 }
215
216 auto returnVoid = mDescrambler->descramble(
217 sctrl,
218 hidlSubSamples,
219 srcBuffer,
220 0,
221 dstBuffer,
222 0,
223 [&status, &result, &detailedError] (
224 Status _status, uint32_t _bytesWritten,
225 const hidl_string& _detailedError) {
226 status = _status;
227 result = (ssize_t)_bytesWritten;
228 detailedError = _detailedError;
229 });
230
231 if (!returnVoid.isOk() || status != Status::OK || result < 0) {
232 ALOGE("descramble failed, trans=%s, status=%d, result=%zd",
233 returnVoid.description().c_str(), status, result);
234 return UNKNOWN_ERROR;
235 }
236
237 if (result < codecDataOffset) {
238 ALOGD("invalid codec data offset: %zd, result %zd", codecDataOffset, result);
239 return BAD_VALUE;
240 }
241
242 ALOGV("descramble succeeded, %zd bytes", result);
243
244 if (dstBuffer.type == BufferType::SHARED_MEMORY) {
245 memcpy(it->mCodecBuffer->base(),
246 (uint8_t*)it->mSharedEncryptedBuffer->unsecurePointer(),
247 result);
248 }
249 }
250
251 it->mCodecBuffer->setRange(codecDataOffset, result - codecDataOffset);
252
253 // Copy metadata from client to codec buffer.
254 it->mCodecBuffer->meta()->clear();
255 int64_t timeUs;
256 CHECK(it->mClientBuffer->meta()->findInt64("timeUs", &timeUs));
257 it->mCodecBuffer->meta()->setInt64("timeUs", timeUs);
258 int32_t eos;
259 if (it->mClientBuffer->meta()->findInt32("eos", &eos)) {
260 it->mCodecBuffer->meta()->setInt32("eos", eos);
261 }
262 int32_t csd;
263 if (it->mClientBuffer->meta()->findInt32("csd", &csd)) {
264 it->mCodecBuffer->meta()->setInt32("csd", csd);
265 }
266
267 ALOGV("queueSecureInputBuffer #%d", it->mBufferId);
268 sp<AMessage> msg = mInputBufferFilled->dup();
269 msg->setObject("buffer", it->mCodecBuffer);
270 msg->setInt32("buffer-id", it->mBufferId);
271 msg->post();
272 return OK;
273 }
274
attachBuffer(const std::shared_ptr<C2Buffer> & c2Buffer,const sp<MediaCodecBuffer> & buffer)275 status_t ACodecBufferChannel::attachBuffer(
276 const std::shared_ptr<C2Buffer> &c2Buffer,
277 const sp<MediaCodecBuffer> &buffer) {
278 switch (c2Buffer->data().type()) {
279 case C2BufferData::LINEAR: {
280 if (c2Buffer->data().linearBlocks().size() != 1u) {
281 return -ENOSYS;
282 }
283 C2ConstLinearBlock block{c2Buffer->data().linearBlocks().front()};
284 C2ReadView view{block.map().get()};
285 size_t copyLength = std::min(size_t(view.capacity()), buffer->capacity());
286 ALOGV_IF(view.capacity() > buffer->capacity(),
287 "view.capacity() = %zu, buffer->capacity() = %zu",
288 view.capacity(), buffer->capacity());
289 memcpy(buffer->base(), view.data(), copyLength);
290 buffer->setRange(0, copyLength);
291 break;
292 }
293 case C2BufferData::GRAPHIC: {
294 sp<ABuffer> imageData;
295 if (!buffer->format()->findBuffer("image-data", &imageData)) {
296 return -ENOSYS;
297 }
298 if (c2Buffer->data().graphicBlocks().size() != 1u) {
299 return -ENOSYS;
300 }
301 C2ConstGraphicBlock block{c2Buffer->data().graphicBlocks().front()};
302 const C2GraphicView view{block.map().get()};
303 status_t err = ImageCopy(
304 buffer->base(), (const MediaImage2 *)(imageData->base()), view);
305 if (err != OK) {
306 return err;
307 }
308 break;
309 }
310 case C2BufferData::LINEAR_CHUNKS: [[fallthrough]];
311 case C2BufferData::GRAPHIC_CHUNKS: [[fallthrough]];
312 default:
313 return -ENOSYS;
314 }
315
316 return OK;
317 }
318
getHeapSeqNum(const sp<HidlMemory> & memory)319 int32_t ACodecBufferChannel::getHeapSeqNum(const sp<HidlMemory> &memory) {
320 CHECK(mCrypto);
321 auto it = mHeapSeqNumMap.find(memory);
322 int32_t heapSeqNum = -1;
323 if (it == mHeapSeqNumMap.end()) {
324 heapSeqNum = mCrypto->setHeap(memory);
325 mHeapSeqNumMap.emplace(memory, heapSeqNum);
326 } else {
327 heapSeqNum = it->second;
328 }
329 return heapSeqNum;
330 }
331
attachEncryptedBuffer(const sp<hardware::HidlMemory> & memory,bool secure,const uint8_t * key,const uint8_t * iv,CryptoPlugin::Mode mode,CryptoPlugin::Pattern pattern,size_t offset,const CryptoPlugin::SubSample * subSamples,size_t numSubSamples,const sp<MediaCodecBuffer> & buffer)332 status_t ACodecBufferChannel::attachEncryptedBuffer(
333 const sp<hardware::HidlMemory> &memory,
334 bool secure,
335 const uint8_t *key,
336 const uint8_t *iv,
337 CryptoPlugin::Mode mode,
338 CryptoPlugin::Pattern pattern,
339 size_t offset,
340 const CryptoPlugin::SubSample *subSamples,
341 size_t numSubSamples,
342 const sp<MediaCodecBuffer> &buffer) {
343 std::shared_ptr<const std::vector<const BufferInfo>> array(
344 std::atomic_load(&mInputBuffers));
345 BufferInfoIterator it = findClientBuffer(array, buffer);
346 if (it == array->end()) {
347 return -ENOENT;
348 }
349
350 native_handle_t *secureHandle = NULL;
351 if (secure) {
352 sp<SecureBuffer> secureData =
353 static_cast<SecureBuffer *>(it->mCodecBuffer.get());
354 if (secureData->getDestinationType() != ICrypto::kDestinationTypeNativeHandle) {
355 return BAD_VALUE;
356 }
357 secureHandle = static_cast<native_handle_t *>(secureData->getDestinationPointer());
358 }
359 size_t size = 0;
360 for (size_t i = 0; i < numSubSamples; ++i) {
361 size += subSamples[i].mNumBytesOfClearData + subSamples[i].mNumBytesOfEncryptedData;
362 }
363 ssize_t result = -1;
364 ssize_t codecDataOffset = 0;
365 if (mCrypto != NULL) {
366 AString errorDetailMsg;
367 hardware::drm::V1_0::DestinationBuffer destination;
368 if (secure) {
369 destination.type = DrmBufferType::NATIVE_HANDLE;
370 destination.secureMemory = hidl_handle(secureHandle);
371 } else {
372 destination.type = DrmBufferType::SHARED_MEMORY;
373 IMemoryToSharedBuffer(
374 mDecryptDestination, mHeapSeqNum, &destination.nonsecureMemory);
375 }
376
377 int32_t heapSeqNum = getHeapSeqNum(memory);
378 hardware::drm::V1_0::SharedBuffer source{(uint32_t)heapSeqNum, offset, size};
379
380 result = mCrypto->decrypt(key, iv, mode, pattern,
381 source, it->mClientBuffer->offset(),
382 subSamples, numSubSamples, destination, &errorDetailMsg);
383
384 if (result < 0) {
385 return result;
386 }
387
388 if (destination.type == DrmBufferType::SHARED_MEMORY) {
389 memcpy(it->mCodecBuffer->base(), mDecryptDestination->unsecurePointer(), result);
390 }
391 } else {
392 // Here we cast CryptoPlugin::SubSample to hardware::cas::native::V1_0::SubSample
393 // directly, the structure definitions should match as checked in DescramblerImpl.cpp.
394 hidl_vec<SubSample> hidlSubSamples;
395 hidlSubSamples.setToExternal((SubSample *)subSamples, numSubSamples, false /*own*/);
396
397 hardware::cas::native::V1_0::SharedBuffer srcBuffer = {
398 .heapBase = *memory,
399 .offset = (uint64_t) offset,
400 .size = size
401 };
402
403 DestinationBuffer dstBuffer;
404 if (secure) {
405 dstBuffer.type = BufferType::NATIVE_HANDLE;
406 dstBuffer.secureMemory = hidl_handle(secureHandle);
407 } else {
408 dstBuffer.type = BufferType::SHARED_MEMORY;
409 dstBuffer.nonsecureMemory = srcBuffer;
410 }
411
412 Status status = Status::OK;
413 hidl_string detailedError;
414 ScramblingControl sctrl = ScramblingControl::UNSCRAMBLED;
415
416 if (key != NULL) {
417 sctrl = (ScramblingControl)key[0];
418 // Adjust for the PES offset
419 codecDataOffset = key[2] | (key[3] << 8);
420 }
421
422 auto returnVoid = mDescrambler->descramble(
423 sctrl,
424 hidlSubSamples,
425 srcBuffer,
426 0,
427 dstBuffer,
428 0,
429 [&status, &result, &detailedError] (
430 Status _status, uint32_t _bytesWritten,
431 const hidl_string& _detailedError) {
432 status = _status;
433 result = (ssize_t)_bytesWritten;
434 detailedError = _detailedError;
435 });
436
437 if (!returnVoid.isOk() || status != Status::OK || result < 0) {
438 ALOGE("descramble failed, trans=%s, status=%d, result=%zd",
439 returnVoid.description().c_str(), status, result);
440 return UNKNOWN_ERROR;
441 }
442
443 if (result < codecDataOffset) {
444 ALOGD("invalid codec data offset: %zd, result %zd", codecDataOffset, result);
445 return BAD_VALUE;
446 }
447
448 ALOGV("descramble succeeded, %zd bytes", result);
449
450 if (dstBuffer.type == BufferType::SHARED_MEMORY) {
451 memcpy(it->mCodecBuffer->base(),
452 (uint8_t*)it->mSharedEncryptedBuffer->unsecurePointer(),
453 result);
454 }
455 }
456
457 it->mCodecBuffer->setRange(codecDataOffset, result - codecDataOffset);
458 return OK;
459 }
460
renderOutputBuffer(const sp<MediaCodecBuffer> & buffer,int64_t timestampNs)461 status_t ACodecBufferChannel::renderOutputBuffer(
462 const sp<MediaCodecBuffer> &buffer, int64_t timestampNs) {
463 std::shared_ptr<const std::vector<const BufferInfo>> array(
464 std::atomic_load(&mOutputBuffers));
465 BufferInfoIterator it = findClientBuffer(array, buffer);
466 if (it == array->end()) {
467 return -ENOENT;
468 }
469
470 ALOGV("renderOutputBuffer #%d", it->mBufferId);
471 sp<AMessage> msg = mOutputBufferDrained->dup();
472 msg->setObject("buffer", buffer);
473 msg->setInt32("buffer-id", it->mBufferId);
474 msg->setInt32("render", true);
475 msg->setInt64("timestampNs", timestampNs);
476 msg->post();
477 return OK;
478 }
479
discardBuffer(const sp<MediaCodecBuffer> & buffer)480 status_t ACodecBufferChannel::discardBuffer(const sp<MediaCodecBuffer> &buffer) {
481 std::shared_ptr<const std::vector<const BufferInfo>> array(
482 std::atomic_load(&mInputBuffers));
483 bool input = true;
484 BufferInfoIterator it = findClientBuffer(array, buffer);
485 if (it == array->end()) {
486 array = std::atomic_load(&mOutputBuffers);
487 input = false;
488 it = findClientBuffer(array, buffer);
489 if (it == array->end()) {
490 return -ENOENT;
491 }
492 }
493 ALOGV("discardBuffer #%d", it->mBufferId);
494 sp<AMessage> msg = input ? mInputBufferFilled->dup() : mOutputBufferDrained->dup();
495 msg->setObject("buffer", it->mCodecBuffer);
496 msg->setInt32("buffer-id", it->mBufferId);
497 msg->setInt32("discarded", true);
498 msg->post();
499 return OK;
500 }
501
getInputBufferArray(Vector<sp<MediaCodecBuffer>> * array)502 void ACodecBufferChannel::getInputBufferArray(Vector<sp<MediaCodecBuffer>> *array) {
503 std::shared_ptr<const std::vector<const BufferInfo>> inputBuffers(
504 std::atomic_load(&mInputBuffers));
505 array->clear();
506 for (const BufferInfo &elem : *inputBuffers) {
507 array->push_back(elem.mClientBuffer);
508 }
509 }
510
getOutputBufferArray(Vector<sp<MediaCodecBuffer>> * array)511 void ACodecBufferChannel::getOutputBufferArray(Vector<sp<MediaCodecBuffer>> *array) {
512 std::shared_ptr<const std::vector<const BufferInfo>> outputBuffers(
513 std::atomic_load(&mOutputBuffers));
514 array->clear();
515 for (const BufferInfo &elem : *outputBuffers) {
516 array->push_back(elem.mClientBuffer);
517 }
518 }
519
makeMemoryDealer(size_t heapSize)520 sp<MemoryDealer> ACodecBufferChannel::makeMemoryDealer(size_t heapSize) {
521 sp<MemoryDealer> dealer;
522 if (mDealer != nullptr && mCrypto != nullptr && mHeapSeqNum >= 0) {
523 mCrypto->unsetHeap(mHeapSeqNum);
524 }
525 dealer = new MemoryDealer(heapSize, "ACodecBufferChannel");
526 if (mCrypto != nullptr) {
527 sp<HidlMemory> hHeap = fromHeap(dealer->getMemoryHeap());
528 int32_t seqNum = mCrypto->setHeap(hHeap);
529 if (seqNum >= 0) {
530 mHeapSeqNum = seqNum;
531 ALOGV("setHeap returned mHeapSeqNum=%d", mHeapSeqNum);
532 } else {
533 mHeapSeqNum = -1;
534 ALOGE("setHeap failed, setting mHeapSeqNum=-1");
535 }
536 } else if (mDescrambler != nullptr) {
537 sp<IMemoryHeap> heap = dealer->getMemoryHeap();
538 mHidlMemory = fromHeap(heap);
539 if (mHidlMemory != NULL) {
540 ALOGV("created hidl_memory for descrambler");
541 } else {
542 ALOGE("failed to create hidl_memory for descrambler");
543 }
544 }
545 return dealer;
546 }
547
setInputBufferArray(const std::vector<BufferAndId> & array)548 void ACodecBufferChannel::setInputBufferArray(const std::vector<BufferAndId> &array) {
549 if (hasCryptoOrDescrambler()) {
550 size_t totalSize = std::accumulate(
551 array.begin(), array.end(), 0u,
552 [alignment = MemoryDealer::getAllocationAlignment()]
553 (size_t sum, const BufferAndId& elem) {
554 return sum + align(elem.mBuffer->capacity(), alignment);
555 });
556 size_t maxSize = std::accumulate(
557 array.begin(), array.end(), 0u,
558 [alignment = MemoryDealer::getAllocationAlignment()]
559 (size_t max, const BufferAndId& elem) {
560 return std::max(max, align(elem.mBuffer->capacity(), alignment));
561 });
562 size_t destinationBufferSize = maxSize;
563 size_t heapSize = totalSize + destinationBufferSize;
564 if (heapSize > 0) {
565 mDealer = makeMemoryDealer(heapSize);
566 mDecryptDestination = mDealer->allocate(destinationBufferSize);
567 }
568 }
569 std::vector<const BufferInfo> inputBuffers;
570 for (const BufferAndId &elem : array) {
571 sp<IMemory> sharedEncryptedBuffer;
572 if (hasCryptoOrDescrambler()) {
573 sharedEncryptedBuffer = mDealer->allocate(elem.mBuffer->capacity());
574 }
575 inputBuffers.emplace_back(elem.mBuffer, elem.mBufferId, sharedEncryptedBuffer);
576 }
577 std::atomic_store(
578 &mInputBuffers,
579 std::make_shared<const std::vector<const BufferInfo>>(inputBuffers));
580 }
581
setOutputBufferArray(const std::vector<BufferAndId> & array)582 void ACodecBufferChannel::setOutputBufferArray(const std::vector<BufferAndId> &array) {
583 std::vector<const BufferInfo> outputBuffers;
584 for (const BufferAndId &elem : array) {
585 outputBuffers.emplace_back(elem.mBuffer, elem.mBufferId, nullptr);
586 }
587 std::atomic_store(
588 &mOutputBuffers,
589 std::make_shared<const std::vector<const BufferInfo>>(outputBuffers));
590 }
591
fillThisBuffer(IOMX::buffer_id bufferId)592 void ACodecBufferChannel::fillThisBuffer(IOMX::buffer_id bufferId) {
593 ALOGV("fillThisBuffer #%d", bufferId);
594 std::shared_ptr<const std::vector<const BufferInfo>> array(
595 std::atomic_load(&mInputBuffers));
596 BufferInfoIterator it = findBufferId(array, bufferId);
597
598 if (it == array->end()) {
599 ALOGE("fillThisBuffer: unrecognized buffer #%d", bufferId);
600 return;
601 }
602 if (it->mClientBuffer != it->mCodecBuffer) {
603 it->mClientBuffer->setFormat(it->mCodecBuffer->format());
604 }
605
606 mCallback->onInputBufferAvailable(
607 std::distance(array->begin(), it),
608 it->mClientBuffer);
609 }
610
drainThisBuffer(IOMX::buffer_id bufferId,OMX_U32 omxFlags)611 void ACodecBufferChannel::drainThisBuffer(
612 IOMX::buffer_id bufferId,
613 OMX_U32 omxFlags) {
614 ALOGV("drainThisBuffer #%d", bufferId);
615 std::shared_ptr<const std::vector<const BufferInfo>> array(
616 std::atomic_load(&mOutputBuffers));
617 BufferInfoIterator it = findBufferId(array, bufferId);
618
619 if (it == array->end()) {
620 ALOGE("drainThisBuffer: unrecognized buffer #%d", bufferId);
621 return;
622 }
623 if (it->mClientBuffer != it->mCodecBuffer) {
624 it->mClientBuffer->setFormat(it->mCodecBuffer->format());
625 }
626
627 uint32_t flags = 0;
628 if (omxFlags & OMX_BUFFERFLAG_SYNCFRAME) {
629 flags |= MediaCodec::BUFFER_FLAG_SYNCFRAME;
630 }
631 if (omxFlags & OMX_BUFFERFLAG_CODECCONFIG) {
632 flags |= MediaCodec::BUFFER_FLAG_CODECCONFIG;
633 }
634 if (omxFlags & OMX_BUFFERFLAG_EOS) {
635 flags |= MediaCodec::BUFFER_FLAG_EOS;
636 }
637 it->mClientBuffer->meta()->setInt32("flags", flags);
638
639 mCallback->onOutputBufferAvailable(
640 std::distance(array->begin(), it),
641 it->mClientBuffer);
642 }
643
setCrypto(const sp<ICrypto> & crypto)644 void ACodecBufferChannel::setCrypto(const sp<ICrypto> &crypto) {
645 if (mCrypto != nullptr) {
646 for (std::pair<wp<HidlMemory>, int32_t> entry : mHeapSeqNumMap) {
647 mCrypto->unsetHeap(entry.second);
648 }
649 mHeapSeqNumMap.clear();
650 if (mHeapSeqNum >= 0) {
651 mCrypto->unsetHeap(mHeapSeqNum);
652 mHeapSeqNum = -1;
653 }
654 }
655 mCrypto = crypto;
656 }
657
setDescrambler(const sp<IDescrambler> & descrambler)658 void ACodecBufferChannel::setDescrambler(const sp<IDescrambler> &descrambler) {
659 mDescrambler = descrambler;
660 }
661
662 } // namespace android
663