1 /*
2 * Copyright 2018, 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 "Codec2Buffer"
19 #define ATRACE_TAG ATRACE_TAG_VIDEO
20 #include <utils/Log.h>
21 #include <utils/Trace.h>
22
23 #include <android_media_codec.h>
24
25 #include <android-base/no_destructor.h>
26 #include <android-base/properties.h>
27 #include <android/hardware/cas/native/1.0/types.h>
28 #include <android/hardware/drm/1.0/types.h>
29 #include <hidlmemory/FrameworkUtils.h>
30 #include <media/hardware/HardwareAPI.h>
31 #include <media/stagefright/CodecBase.h>
32 #include <media/stagefright/MediaCodecConstants.h>
33 #include <media/stagefright/foundation/ABuffer.h>
34 #include <media/stagefright/foundation/AMessage.h>
35 #include <media/stagefright/foundation/AUtils.h>
36 #include <media/stagefright/foundation/ColorUtils.h>
37 #include <mediadrm/ICrypto.h>
38 #include <nativebase/nativebase.h>
39 #include <ui/Fence.h>
40
41 #include <C2AllocatorGralloc.h>
42 #include <C2BlockInternal.h>
43 #include <C2Debug.h>
44
45 #include "Codec2Buffer.h"
46 #include "Codec2BufferUtils.h"
47
48 namespace android {
49
50 // Codec2Buffer
51
canCopyLinear(const std::shared_ptr<C2Buffer> & buffer) const52 bool Codec2Buffer::canCopyLinear(const std::shared_ptr<C2Buffer> &buffer) const {
53 if (const_cast<Codec2Buffer *>(this)->base() == nullptr) {
54 return false;
55 }
56 if (!buffer) {
57 // Nothing to copy, so we can copy by doing nothing.
58 return true;
59 }
60 if (buffer->data().type() != C2BufferData::LINEAR) {
61 return false;
62 }
63 if (buffer->data().linearBlocks().size() == 0u) {
64 // Nothing to copy, so we can copy by doing nothing.
65 return true;
66 } else if (buffer->data().linearBlocks().size() > 1u) {
67 // We don't know how to copy more than one blocks.
68 return false;
69 }
70 if (buffer->data().linearBlocks()[0].size() > capacity()) {
71 // It won't fit.
72 return false;
73 }
74 return true;
75 }
76
copyLinear(const std::shared_ptr<C2Buffer> & buffer)77 bool Codec2Buffer::copyLinear(const std::shared_ptr<C2Buffer> &buffer) {
78 // We assume that all canCopyLinear() checks passed.
79 if (!buffer || buffer->data().linearBlocks().size() == 0u
80 || buffer->data().linearBlocks()[0].size() == 0u) {
81 setRange(0, 0);
82 return true;
83 }
84 C2ReadView view = buffer->data().linearBlocks()[0].map().get();
85 if (view.error() != C2_OK) {
86 ALOGD("Error while mapping: %d", view.error());
87 return false;
88 }
89 if (view.capacity() > capacity()) {
90 ALOGD("C2ConstLinearBlock lied --- it actually doesn't fit: view(%u) > this(%zu)",
91 view.capacity(), capacity());
92 return false;
93 }
94 memcpy(base(), view.data(), view.capacity());
95 setRange(0, view.capacity());
96 return true;
97 }
98
setImageData(const sp<ABuffer> & imageData)99 void Codec2Buffer::setImageData(const sp<ABuffer> &imageData) {
100 mImageData = imageData;
101 }
102
103 // LocalLinearBuffer
104
canCopy(const std::shared_ptr<C2Buffer> & buffer) const105 bool LocalLinearBuffer::canCopy(const std::shared_ptr<C2Buffer> &buffer) const {
106 return canCopyLinear(buffer);
107 }
108
copy(const std::shared_ptr<C2Buffer> & buffer)109 bool LocalLinearBuffer::copy(const std::shared_ptr<C2Buffer> &buffer) {
110 return copyLinear(buffer);
111 }
112
113 // DummyContainerBuffer
114
115 static uint8_t sDummyByte[1] = { 0 };
116
DummyContainerBuffer(const sp<AMessage> & format,const std::shared_ptr<C2Buffer> & buffer)117 DummyContainerBuffer::DummyContainerBuffer(
118 const sp<AMessage> &format, const std::shared_ptr<C2Buffer> &buffer)
119 : Codec2Buffer(format, new ABuffer(sDummyByte, 1)),
120 mBufferRef(buffer) {
121 setRange(0, buffer ? 1 : 0);
122 }
123
asC2Buffer()124 std::shared_ptr<C2Buffer> DummyContainerBuffer::asC2Buffer() {
125 return mBufferRef;
126 }
127
clearC2BufferRefs()128 void DummyContainerBuffer::clearC2BufferRefs() {
129 mBufferRef.reset();
130 }
131
canCopy(const std::shared_ptr<C2Buffer> &) const132 bool DummyContainerBuffer::canCopy(const std::shared_ptr<C2Buffer> &) const {
133 return !mBufferRef;
134 }
135
copy(const std::shared_ptr<C2Buffer> & buffer)136 bool DummyContainerBuffer::copy(const std::shared_ptr<C2Buffer> &buffer) {
137 mBufferRef = buffer;
138 setRange(0, mBufferRef ? 1 : 0);
139 return true;
140 }
141
142 // LinearBlockBuffer
143
144 // static
Allocate(const sp<AMessage> & format,const std::shared_ptr<C2LinearBlock> & block)145 sp<LinearBlockBuffer> LinearBlockBuffer::Allocate(
146 const sp<AMessage> &format, const std::shared_ptr<C2LinearBlock> &block) {
147 C2WriteView writeView(block->map().get());
148 if (writeView.error() != C2_OK) {
149 return nullptr;
150 }
151 return new LinearBlockBuffer(format, std::move(writeView), block);
152 }
153
asC2Buffer()154 std::shared_ptr<C2Buffer> LinearBlockBuffer::asC2Buffer() {
155 return C2Buffer::CreateLinearBuffer(mBlock->share(offset(), size(), C2Fence()));
156 }
157
canCopy(const std::shared_ptr<C2Buffer> & buffer) const158 bool LinearBlockBuffer::canCopy(const std::shared_ptr<C2Buffer> &buffer) const {
159 return canCopyLinear(buffer);
160 }
161
copy(const std::shared_ptr<C2Buffer> & buffer)162 bool LinearBlockBuffer::copy(const std::shared_ptr<C2Buffer> &buffer) {
163 return copyLinear(buffer);
164 }
165
LinearBlockBuffer(const sp<AMessage> & format,C2WriteView && writeView,const std::shared_ptr<C2LinearBlock> & block)166 LinearBlockBuffer::LinearBlockBuffer(
167 const sp<AMessage> &format,
168 C2WriteView&& writeView,
169 const std::shared_ptr<C2LinearBlock> &block)
170 : Codec2Buffer(format, new ABuffer(writeView.data(), writeView.size())),
171 mWriteView(writeView),
172 mBlock(block) {
173 }
174
175 // ConstLinearBlockBuffer
176
177 // static
Allocate(const sp<AMessage> & format,const std::shared_ptr<C2Buffer> & buffer)178 sp<ConstLinearBlockBuffer> ConstLinearBlockBuffer::Allocate(
179 const sp<AMessage> &format, const std::shared_ptr<C2Buffer> &buffer) {
180 if (!buffer
181 || buffer->data().type() != C2BufferData::LINEAR
182 || buffer->data().linearBlocks().size() != 1u) {
183 if (!buffer) {
184 ALOGD("ConstLinearBlockBuffer::Allocate: null buffer");
185 } else {
186 ALOGW("ConstLinearBlockBuffer::Allocate: type=%d # linear blocks=%zu",
187 buffer->data().type(), buffer->data().linearBlocks().size());
188 }
189 return nullptr;
190 }
191 C2ReadView readView(buffer->data().linearBlocks()[0].map().get());
192 if (readView.error() != C2_OK) {
193 ALOGW("ConstLinearBlockBuffer::Allocate: readView.error()=%d", readView.error());
194 return nullptr;
195 }
196 return new ConstLinearBlockBuffer(format, std::move(readView), buffer);
197 }
198
ConstLinearBlockBuffer(const sp<AMessage> & format,C2ReadView && readView,const std::shared_ptr<C2Buffer> & buffer)199 ConstLinearBlockBuffer::ConstLinearBlockBuffer(
200 const sp<AMessage> &format,
201 C2ReadView&& readView,
202 const std::shared_ptr<C2Buffer> &buffer)
203 : Codec2Buffer(format, new ABuffer(
204 // NOTE: ABuffer only takes non-const pointer but this data is
205 // supposed to be read-only.
206 const_cast<uint8_t *>(readView.data()), readView.capacity())),
207 mReadView(readView),
208 mBufferRef(buffer) {
209 }
210
asC2Buffer()211 std::shared_ptr<C2Buffer> ConstLinearBlockBuffer::asC2Buffer() {
212 return mBufferRef;
213 }
214
clearC2BufferRefs()215 void ConstLinearBlockBuffer::clearC2BufferRefs() {
216 mBufferRef.reset();
217 }
218
219 // GraphicBlockBuffer
220
221 // static
Allocate(const sp<AMessage> & format,const std::shared_ptr<C2GraphicBlock> & block,std::function<sp<ABuffer> (size_t)> alloc)222 sp<GraphicBlockBuffer> GraphicBlockBuffer::Allocate(
223 const sp<AMessage> &format,
224 const std::shared_ptr<C2GraphicBlock> &block,
225 std::function<sp<ABuffer>(size_t)> alloc) {
226 ATRACE_BEGIN("GraphicBlockBuffer::Allocate block->map()");
227 C2GraphicView view(block->map().get());
228 ATRACE_END();
229 if (view.error() != C2_OK) {
230 ALOGD("C2GraphicBlock::map failed: %d", view.error());
231 return nullptr;
232 }
233
234 GraphicView2MediaImageConverter converter(view, format, false /* copy */);
235 if (converter.initCheck() != OK) {
236 ALOGD("Converter init failed: %d", converter.initCheck());
237 return nullptr;
238 }
239 bool wrapped = true;
240 sp<ABuffer> buffer = converter.wrap();
241 if (buffer == nullptr) {
242 buffer = alloc(converter.backBufferSize());
243 if (!converter.setBackBuffer(buffer)) {
244 ALOGD("Converter failed to set back buffer");
245 return nullptr;
246 }
247 wrapped = false;
248 }
249 return new GraphicBlockBuffer(
250 format,
251 buffer,
252 std::move(view),
253 block,
254 converter.imageData(),
255 wrapped);
256 }
257
GraphicBlockBuffer(const sp<AMessage> & format,const sp<ABuffer> & buffer,C2GraphicView && view,const std::shared_ptr<C2GraphicBlock> & block,const sp<ABuffer> & imageData,bool wrapped)258 GraphicBlockBuffer::GraphicBlockBuffer(
259 const sp<AMessage> &format,
260 const sp<ABuffer> &buffer,
261 C2GraphicView &&view,
262 const std::shared_ptr<C2GraphicBlock> &block,
263 const sp<ABuffer> &imageData,
264 bool wrapped)
265 : Codec2Buffer(format, buffer),
266 mView(view),
267 mBlock(block),
268 mWrapped(wrapped) {
269 setImageData(imageData);
270 }
271
asC2Buffer()272 std::shared_ptr<C2Buffer> GraphicBlockBuffer::asC2Buffer() {
273 ATRACE_CALL();
274 uint32_t width = mView.width();
275 uint32_t height = mView.height();
276 if (!mWrapped) {
277 (void)ImageCopy(mView, base(), imageData());
278 }
279 return C2Buffer::CreateGraphicBuffer(
280 mBlock->share(C2Rect(width, height), C2Fence()));
281 }
282
283 // GraphicMetadataBuffer
GraphicMetadataBuffer(const sp<AMessage> & format,const std::shared_ptr<C2Allocator> & alloc)284 GraphicMetadataBuffer::GraphicMetadataBuffer(
285 const sp<AMessage> &format,
286 const std::shared_ptr<C2Allocator> &alloc)
287 : Codec2Buffer(format, new ABuffer(sizeof(VideoNativeMetadata))),
288 mAlloc(alloc) {
289 ((VideoNativeMetadata *)base())->pBuffer = nullptr;
290 }
291
asC2Buffer()292 std::shared_ptr<C2Buffer> GraphicMetadataBuffer::asC2Buffer() {
293 #ifdef __LP64__
294 static std::once_flag s_checkOnce;
295 static bool s_is64bitOk {true};
296 std::call_once(s_checkOnce, [&](){
297 const std::string abi32list =
298 ::android::base::GetProperty("ro.product.cpu.abilist32", "");
299 if (!abi32list.empty()) {
300 int32_t inputSurfaceSetting =
301 ::android::base::GetIntProperty("debug.stagefright.c2inputsurface", int32_t(0));
302 s_is64bitOk = inputSurfaceSetting != 0;
303 }
304 });
305
306 if (!s_is64bitOk) {
307 ALOGE("GraphicMetadataBuffer does not work in 32+64 system if compiled as 64-bit object"\
308 "when debug.stagefright.c2inputsurface is set to 0");
309 return nullptr;
310 }
311 #endif
312
313 VideoNativeMetadata *meta = (VideoNativeMetadata *)base();
314 ANativeWindowBuffer *buffer = (ANativeWindowBuffer *)meta->pBuffer;
315 if (buffer == nullptr) {
316 ALOGD("VideoNativeMetadata contains null buffer");
317 return nullptr;
318 }
319
320 ALOGV("VideoNativeMetadata: %dx%d", buffer->width, buffer->height);
321 C2Handle *handle = WrapNativeCodec2GrallocHandle(
322 buffer->handle,
323 buffer->width,
324 buffer->height,
325 buffer->format,
326 buffer->usage,
327 buffer->stride);
328 std::shared_ptr<C2GraphicAllocation> alloc;
329 c2_status_t err = mAlloc->priorGraphicAllocation(handle, &alloc);
330 if (err != C2_OK) {
331 ALOGD("Failed to wrap VideoNativeMetadata into C2GraphicAllocation");
332 native_handle_close(handle);
333 native_handle_delete(handle);
334 return nullptr;
335 }
336 std::shared_ptr<C2GraphicBlock> block = _C2BlockFactory::CreateGraphicBlock(alloc);
337
338 meta->pBuffer = 0;
339 // TODO: wrap this in C2Fence so that the component can wait when it
340 // actually starts processing.
341 if (meta->nFenceFd >= 0) {
342 sp<Fence> fence(new Fence(meta->nFenceFd));
343 fence->waitForever(LOG_TAG);
344 }
345 return C2Buffer::CreateGraphicBuffer(
346 block->share(C2Rect(buffer->width, buffer->height), C2Fence()));
347 }
348
349 // ConstGraphicBlockBuffer
350
351 // static
Allocate(const sp<AMessage> & format,const std::shared_ptr<C2Buffer> & buffer,std::function<sp<ABuffer> (size_t)> alloc)352 sp<ConstGraphicBlockBuffer> ConstGraphicBlockBuffer::Allocate(
353 const sp<AMessage> &format,
354 const std::shared_ptr<C2Buffer> &buffer,
355 std::function<sp<ABuffer>(size_t)> alloc) {
356 if (!buffer
357 || buffer->data().type() != C2BufferData::GRAPHIC
358 || buffer->data().graphicBlocks().size() != 1u) {
359 ALOGD("C2Buffer precond fail");
360 return nullptr;
361 }
362 ATRACE_BEGIN("ConstGraphicBlockBuffer::Allocate block->map()");
363 std::unique_ptr<const C2GraphicView> view(std::make_unique<const C2GraphicView>(
364 buffer->data().graphicBlocks()[0].map().get()));
365 ATRACE_END();
366 std::unique_ptr<const C2GraphicView> holder;
367
368 GraphicView2MediaImageConverter converter(*view, format, false /* copy */);
369 if (converter.initCheck() != OK) {
370 ALOGD("Converter init failed: %d", converter.initCheck());
371 return nullptr;
372 }
373 bool wrapped = true;
374 sp<ABuffer> aBuffer = converter.wrap();
375 if (aBuffer == nullptr) {
376 aBuffer = alloc(converter.backBufferSize());
377 if (!converter.setBackBuffer(aBuffer)) {
378 ALOGD("Converter failed to set back buffer");
379 return nullptr;
380 }
381 wrapped = false;
382 converter.copyToMediaImage();
383 // We don't need the view.
384 holder = std::move(view);
385 }
386 return new ConstGraphicBlockBuffer(
387 format,
388 aBuffer,
389 std::move(view),
390 buffer,
391 converter.imageData(),
392 wrapped);
393 }
394
395 // static
AllocateEmpty(const sp<AMessage> & format,std::function<sp<ABuffer> (size_t)> alloc)396 sp<ConstGraphicBlockBuffer> ConstGraphicBlockBuffer::AllocateEmpty(
397 const sp<AMessage> &format,
398 std::function<sp<ABuffer>(size_t)> alloc) {
399 int32_t width, height;
400 if (!format->findInt32("width", &width)
401 || !format->findInt32("height", &height)) {
402 ALOGD("format had no width / height");
403 return nullptr;
404 }
405 int32_t colorFormat = COLOR_FormatYUV420Flexible;
406 int32_t bpp = 12; // 8(Y) + 2(U) + 2(V)
407 if (format->findInt32(KEY_COLOR_FORMAT, &colorFormat)) {
408 if (colorFormat == COLOR_FormatYUVP010) {
409 bpp = 24; // 16(Y) + 4(U) + 4(V)
410 }
411 }
412 sp<ABuffer> aBuffer(alloc(align(width, 16) * align(height, 16) * bpp / 8));
413 if (aBuffer == nullptr) {
414 ALOGD("%s: failed to allocate buffer", __func__);
415 return nullptr;
416 }
417 return new ConstGraphicBlockBuffer(
418 format,
419 aBuffer,
420 nullptr,
421 nullptr,
422 nullptr,
423 false);
424 }
425
ConstGraphicBlockBuffer(const sp<AMessage> & format,const sp<ABuffer> & aBuffer,std::unique_ptr<const C2GraphicView> && view,const std::shared_ptr<C2Buffer> & buffer,const sp<ABuffer> & imageData,bool wrapped)426 ConstGraphicBlockBuffer::ConstGraphicBlockBuffer(
427 const sp<AMessage> &format,
428 const sp<ABuffer> &aBuffer,
429 std::unique_ptr<const C2GraphicView> &&view,
430 const std::shared_ptr<C2Buffer> &buffer,
431 const sp<ABuffer> &imageData,
432 bool wrapped)
433 : Codec2Buffer(format, aBuffer),
434 mView(std::move(view)),
435 mBufferRef(buffer),
436 mWrapped(wrapped) {
437 setImageData(imageData);
438 }
439
asC2Buffer()440 std::shared_ptr<C2Buffer> ConstGraphicBlockBuffer::asC2Buffer() {
441 return mBufferRef;
442 }
443
clearC2BufferRefs()444 void ConstGraphicBlockBuffer::clearC2BufferRefs() {
445 mView.reset();
446 mBufferRef.reset();
447 }
448
canCopy(const std::shared_ptr<C2Buffer> & buffer) const449 bool ConstGraphicBlockBuffer::canCopy(const std::shared_ptr<C2Buffer> &buffer) const {
450 if (mWrapped || mBufferRef) {
451 ALOGD("ConstGraphicBlockBuffer::canCopy: %swrapped ; buffer ref %s",
452 mWrapped ? "" : "not ", mBufferRef ? "exists" : "doesn't exist");
453 return false;
454 }
455 if (!buffer) {
456 // Nothing to copy, so we can copy by doing nothing.
457 return true;
458 }
459 if (buffer->data().type() != C2BufferData::GRAPHIC) {
460 ALOGD("ConstGraphicBlockBuffer::canCopy: buffer precondition unsatisfied");
461 return false;
462 }
463 if (buffer->data().graphicBlocks().size() == 0) {
464 return true;
465 } else if (buffer->data().graphicBlocks().size() != 1u) {
466 ALOGD("ConstGraphicBlockBuffer::canCopy: too many blocks");
467 return false;
468 }
469
470 ATRACE_BEGIN("ConstGraphicBlockBuffer::canCopy block->map()");
471 GraphicView2MediaImageConverter converter(
472 buffer->data().graphicBlocks()[0].map().get(),
473 // FIXME: format() is not const, but we cannot change it, so do a const cast here
474 const_cast<ConstGraphicBlockBuffer *>(this)->format(),
475 true /* copy */);
476 ATRACE_END();
477 if (converter.initCheck() != OK) {
478 ALOGD("ConstGraphicBlockBuffer::canCopy: converter init failed: %d", converter.initCheck());
479 return false;
480 }
481 if (converter.backBufferSize() > capacity()) {
482 ALOGD("ConstGraphicBlockBuffer::canCopy: insufficient capacity: req %u has %zu",
483 converter.backBufferSize(), capacity());
484 return false;
485 }
486 return true;
487 }
488
copy(const std::shared_ptr<C2Buffer> & buffer)489 bool ConstGraphicBlockBuffer::copy(const std::shared_ptr<C2Buffer> &buffer) {
490 if (!buffer || buffer->data().graphicBlocks().size() == 0) {
491 setRange(0, 0);
492 return true;
493 }
494
495 GraphicView2MediaImageConverter converter(
496 buffer->data().graphicBlocks()[0].map().get(), format(), true /* copy */);
497 if (converter.initCheck() != OK) {
498 ALOGD("ConstGraphicBlockBuffer::copy: converter init failed: %d", converter.initCheck());
499 return false;
500 }
501 sp<ABuffer> aBuffer = new ABuffer(base(), capacity());
502 if (!converter.setBackBuffer(aBuffer)) {
503 ALOGD("ConstGraphicBlockBuffer::copy: set back buffer failed");
504 return false;
505 }
506 setRange(0, aBuffer->size()); // align size info
507 converter.copyToMediaImage();
508 setImageData(converter.imageData());
509 mBufferRef = buffer;
510 return true;
511 }
512
513 // EncryptedLinearBlockBuffer
514
EncryptedLinearBlockBuffer(const sp<AMessage> & format,const std::shared_ptr<C2LinearBlock> & block,const sp<IMemory> & memory,int32_t heapSeqNum)515 EncryptedLinearBlockBuffer::EncryptedLinearBlockBuffer(
516 const sp<AMessage> &format,
517 const std::shared_ptr<C2LinearBlock> &block,
518 const sp<IMemory> &memory,
519 int32_t heapSeqNum)
520 // TODO: Using unsecurePointer() has some associated security pitfalls
521 // (see declaration for details).
522 // Either document why it is safe in this case or address the
523 // issue (e.g. by copying).
524 : Codec2Buffer(format, new ABuffer(memory->unsecurePointer(), memory->size())),
525 mBlock(block),
526 mMemory(memory),
527 mHeapSeqNum(heapSeqNum) {
528 }
529
asC2Buffer()530 std::shared_ptr<C2Buffer> EncryptedLinearBlockBuffer::asC2Buffer() {
531 return C2Buffer::CreateLinearBuffer(mBlock->share(offset(), size(), C2Fence()));
532 }
533
fillSourceBuffer(hardware::drm::V1_0::SharedBuffer * source)534 void EncryptedLinearBlockBuffer::fillSourceBuffer(
535 hardware::drm::V1_0::SharedBuffer *source) {
536 BufferChannelBase::IMemoryToSharedBuffer(mMemory, mHeapSeqNum, source);
537 }
538
fillSourceBuffer(hardware::cas::native::V1_0::SharedBuffer * source)539 void EncryptedLinearBlockBuffer::fillSourceBuffer(
540 hardware::cas::native::V1_0::SharedBuffer *source) {
541 ssize_t offset;
542 size_t size;
543
544 mHidlMemory = hardware::fromHeap(mMemory->getMemory(&offset, &size));
545 source->heapBase = *mHidlMemory;
546 source->offset = offset;
547 source->size = size;
548 }
549
copyDecryptedContent(const sp<IMemory> & decrypted,size_t length)550 bool EncryptedLinearBlockBuffer::copyDecryptedContent(
551 const sp<IMemory> &decrypted, size_t length) {
552 C2WriteView view = mBlock->map().get();
553 if (view.error() != C2_OK) {
554 return false;
555 }
556 if (view.size() < length) {
557 return false;
558 }
559 memcpy(view.data(), decrypted->unsecurePointer(), length);
560 return true;
561 }
562
copyDecryptedContentFromMemory(size_t length)563 bool EncryptedLinearBlockBuffer::copyDecryptedContentFromMemory(size_t length) {
564 return copyDecryptedContent(mMemory, length);
565 }
566
handle() const567 native_handle_t *EncryptedLinearBlockBuffer::handle() const {
568 return const_cast<native_handle_t *>(mBlock->handle());
569 }
570
getMappedBlock(std::unique_ptr<MappedBlock> * const mappedBlock) const571 void EncryptedLinearBlockBuffer::getMappedBlock(
572 std::unique_ptr<MappedBlock> * const mappedBlock) const {
573 if (mappedBlock) {
574 mappedBlock->reset(new EncryptedLinearBlockBuffer::MappedBlock(mBlock));
575 }
576 return;
577 }
578
MappedBlock(const std::shared_ptr<C2LinearBlock> & block)579 EncryptedLinearBlockBuffer::MappedBlock::MappedBlock(
580 const std::shared_ptr<C2LinearBlock> &block) : mView(block->map().get()) {
581 }
582
copyDecryptedContent(const sp<IMemory> & decrypted,size_t length)583 bool EncryptedLinearBlockBuffer::MappedBlock::copyDecryptedContent(
584 const sp<IMemory> &decrypted, size_t length) {
585 if (mView.error() != C2_OK) {
586 return false;
587 }
588 if (mView.size() < length) {
589 ALOGE("View size(%d) less than decrypted length(%zu)",
590 mView.size(), length);
591 return false;
592 }
593 memcpy(mView.data(), decrypted->unsecurePointer(), length);
594 mView.setOffset(mView.offset() + length);
595 return true;
596 }
597
~MappedBlock()598 EncryptedLinearBlockBuffer::MappedBlock::~MappedBlock() {
599 mView.setOffset(0);
600 }
601
602 } // namespace android
603