• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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