xref: /aosp_15_r20/frameworks/av/media/codec2/sfplugin/Codec2Buffer.cpp (revision ec779b8e0859a360c3d303172224686826e6e0e1)
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 <aidl/android/hardware/graphics/common/Cta861_3.h>
26 #include <aidl/android/hardware/graphics/common/Smpte2086.h>
27 #include <android-base/no_destructor.h>
28 #include <android-base/properties.h>
29 #include <android/hardware/cas/native/1.0/types.h>
30 #include <android/hardware/drm/1.0/types.h>
31 #include <hidlmemory/FrameworkUtils.h>
32 #include <media/hardware/HardwareAPI.h>
33 #include <media/stagefright/CodecBase.h>
34 #include <media/stagefright/MediaCodecConstants.h>
35 #include <media/stagefright/foundation/ABuffer.h>
36 #include <media/stagefright/foundation/AMessage.h>
37 #include <media/stagefright/foundation/AUtils.h>
38 #include <media/stagefright/foundation/ColorUtils.h>
39 #include <mediadrm/ICrypto.h>
40 #include <nativebase/nativebase.h>
41 #include <ui/GraphicBufferMapper.h>
42 #include <ui/Fence.h>
43 
44 #include <C2AllocatorGralloc.h>
45 #include <C2BlockInternal.h>
46 #include <C2Debug.h>
47 
48 #include "Codec2Buffer.h"
49 #include "Codec2BufferUtils.h"
50 
51 namespace android {
52 
53 // Codec2Buffer
54 
canCopyLinear(const std::shared_ptr<C2Buffer> & buffer) const55 bool Codec2Buffer::canCopyLinear(const std::shared_ptr<C2Buffer> &buffer) const {
56     if (const_cast<Codec2Buffer *>(this)->base() == nullptr) {
57         return false;
58     }
59     if (!buffer) {
60         // Nothing to copy, so we can copy by doing nothing.
61         return true;
62     }
63     if (buffer->data().type() != C2BufferData::LINEAR) {
64         return false;
65     }
66     if (buffer->data().linearBlocks().size() == 0u) {
67         // Nothing to copy, so we can copy by doing nothing.
68         return true;
69     } else if (buffer->data().linearBlocks().size() > 1u) {
70         // We don't know how to copy more than one blocks.
71         return false;
72     }
73     if (buffer->data().linearBlocks()[0].size() > capacity()) {
74         // It won't fit.
75         return false;
76     }
77     return true;
78 }
79 
copyLinear(const std::shared_ptr<C2Buffer> & buffer)80 bool Codec2Buffer::copyLinear(const std::shared_ptr<C2Buffer> &buffer) {
81     // We assume that all canCopyLinear() checks passed.
82     if (!buffer || buffer->data().linearBlocks().size() == 0u
83             || buffer->data().linearBlocks()[0].size() == 0u) {
84         setRange(0, 0);
85         return true;
86     }
87     C2ReadView view = buffer->data().linearBlocks()[0].map().get();
88     if (view.error() != C2_OK) {
89         ALOGD("Error while mapping: %d", view.error());
90         return false;
91     }
92     if (view.capacity() > capacity()) {
93         ALOGD("C2ConstLinearBlock lied --- it actually doesn't fit: view(%u) > this(%zu)",
94                 view.capacity(), capacity());
95         return false;
96     }
97     memcpy(base(), view.data(), view.capacity());
98     setRange(0, view.capacity());
99     return true;
100 }
101 
setImageData(const sp<ABuffer> & imageData)102 void Codec2Buffer::setImageData(const sp<ABuffer> &imageData) {
103     mImageData = imageData;
104 }
105 
106 // LocalLinearBuffer
107 
canCopy(const std::shared_ptr<C2Buffer> & buffer) const108 bool LocalLinearBuffer::canCopy(const std::shared_ptr<C2Buffer> &buffer) const {
109     return canCopyLinear(buffer);
110 }
111 
copy(const std::shared_ptr<C2Buffer> & buffer)112 bool LocalLinearBuffer::copy(const std::shared_ptr<C2Buffer> &buffer) {
113     return copyLinear(buffer);
114 }
115 
116 // DummyContainerBuffer
117 
118 static uint8_t sDummyByte[1] = { 0 };
119 
DummyContainerBuffer(const sp<AMessage> & format,const std::shared_ptr<C2Buffer> & buffer)120 DummyContainerBuffer::DummyContainerBuffer(
121         const sp<AMessage> &format, const std::shared_ptr<C2Buffer> &buffer)
122     : Codec2Buffer(format, new ABuffer(sDummyByte, 1)),
123       mBufferRef(buffer) {
124     setRange(0, buffer ? 1 : 0);
125 }
126 
asC2Buffer()127 std::shared_ptr<C2Buffer> DummyContainerBuffer::asC2Buffer() {
128     return mBufferRef;
129 }
130 
clearC2BufferRefs()131 void DummyContainerBuffer::clearC2BufferRefs() {
132     mBufferRef.reset();
133 }
134 
canCopy(const std::shared_ptr<C2Buffer> &) const135 bool DummyContainerBuffer::canCopy(const std::shared_ptr<C2Buffer> &) const {
136     return !mBufferRef;
137 }
138 
copy(const std::shared_ptr<C2Buffer> & buffer)139 bool DummyContainerBuffer::copy(const std::shared_ptr<C2Buffer> &buffer) {
140     mBufferRef = buffer;
141     setRange(0, mBufferRef ? 1 : 0);
142     return true;
143 }
144 
145 // LinearBlockBuffer
146 
147 // static
Allocate(const sp<AMessage> & format,const std::shared_ptr<C2LinearBlock> & block)148 sp<LinearBlockBuffer> LinearBlockBuffer::Allocate(
149         const sp<AMessage> &format, const std::shared_ptr<C2LinearBlock> &block) {
150     C2WriteView writeView(block->map().get());
151     if (writeView.error() != C2_OK) {
152         return nullptr;
153     }
154     return new LinearBlockBuffer(format, std::move(writeView), block);
155 }
156 
asC2Buffer()157 std::shared_ptr<C2Buffer> LinearBlockBuffer::asC2Buffer() {
158     return C2Buffer::CreateLinearBuffer(mBlock->share(offset(), size(), C2Fence()));
159 }
160 
canCopy(const std::shared_ptr<C2Buffer> & buffer) const161 bool LinearBlockBuffer::canCopy(const std::shared_ptr<C2Buffer> &buffer) const {
162     return canCopyLinear(buffer);
163 }
164 
copy(const std::shared_ptr<C2Buffer> & buffer)165 bool LinearBlockBuffer::copy(const std::shared_ptr<C2Buffer> &buffer) {
166     return copyLinear(buffer);
167 }
168 
LinearBlockBuffer(const sp<AMessage> & format,C2WriteView && writeView,const std::shared_ptr<C2LinearBlock> & block)169 LinearBlockBuffer::LinearBlockBuffer(
170         const sp<AMessage> &format,
171         C2WriteView&& writeView,
172         const std::shared_ptr<C2LinearBlock> &block)
173     : Codec2Buffer(format, new ABuffer(writeView.data(), writeView.size())),
174       mWriteView(writeView),
175       mBlock(block) {
176 }
177 
178 // ConstLinearBlockBuffer
179 
180 // static
Allocate(const sp<AMessage> & format,const std::shared_ptr<C2Buffer> & buffer)181 sp<ConstLinearBlockBuffer> ConstLinearBlockBuffer::Allocate(
182         const sp<AMessage> &format, const std::shared_ptr<C2Buffer> &buffer) {
183     if (!buffer
184             || buffer->data().type() != C2BufferData::LINEAR
185             || buffer->data().linearBlocks().size() != 1u) {
186         if (!buffer) {
187             ALOGD("ConstLinearBlockBuffer::Allocate: null buffer");
188         } else {
189             ALOGW("ConstLinearBlockBuffer::Allocate: type=%d # linear blocks=%zu",
190                   buffer->data().type(), buffer->data().linearBlocks().size());
191         }
192         return nullptr;
193     }
194     C2ReadView readView(buffer->data().linearBlocks()[0].map().get());
195     if (readView.error() != C2_OK) {
196         ALOGW("ConstLinearBlockBuffer::Allocate: readView.error()=%d", readView.error());
197         return nullptr;
198     }
199     return new ConstLinearBlockBuffer(format, std::move(readView), buffer);
200 }
201 
ConstLinearBlockBuffer(const sp<AMessage> & format,C2ReadView && readView,const std::shared_ptr<C2Buffer> & buffer)202 ConstLinearBlockBuffer::ConstLinearBlockBuffer(
203         const sp<AMessage> &format,
204         C2ReadView&& readView,
205         const std::shared_ptr<C2Buffer> &buffer)
206     : Codec2Buffer(format, new ABuffer(
207             // NOTE: ABuffer only takes non-const pointer but this data is
208             //       supposed to be read-only.
209             const_cast<uint8_t *>(readView.data()), readView.capacity())),
210       mReadView(readView),
211       mBufferRef(buffer) {
212 }
213 
asC2Buffer()214 std::shared_ptr<C2Buffer> ConstLinearBlockBuffer::asC2Buffer() {
215     return mBufferRef;
216 }
217 
clearC2BufferRefs()218 void ConstLinearBlockBuffer::clearC2BufferRefs() {
219     mBufferRef.reset();
220 }
221 
222 // GraphicBlockBuffer
223 
224 // static
Allocate(const sp<AMessage> & format,const std::shared_ptr<C2GraphicBlock> & block,std::function<sp<ABuffer> (size_t)> alloc)225 sp<GraphicBlockBuffer> GraphicBlockBuffer::Allocate(
226         const sp<AMessage> &format,
227         const std::shared_ptr<C2GraphicBlock> &block,
228         std::function<sp<ABuffer>(size_t)> alloc) {
229     ATRACE_BEGIN("GraphicBlockBuffer::Allocate block->map()");
230     C2GraphicView view(block->map().get());
231     ATRACE_END();
232     if (view.error() != C2_OK) {
233         ALOGD("C2GraphicBlock::map failed: %d", view.error());
234         return nullptr;
235     }
236 
237     GraphicView2MediaImageConverter converter(view, format, false /* copy */);
238     if (converter.initCheck() != OK) {
239         ALOGD("Converter init failed: %d", converter.initCheck());
240         return nullptr;
241     }
242     bool wrapped = true;
243     sp<ABuffer> buffer = converter.wrap();
244     if (buffer == nullptr) {
245         buffer = alloc(converter.backBufferSize());
246         if (!converter.setBackBuffer(buffer)) {
247             ALOGD("Converter failed to set back buffer");
248             return nullptr;
249         }
250         wrapped = false;
251     }
252     return new GraphicBlockBuffer(
253             format,
254             buffer,
255             std::move(view),
256             block,
257             converter.imageData(),
258             wrapped);
259 }
260 
GraphicBlockBuffer(const sp<AMessage> & format,const sp<ABuffer> & buffer,C2GraphicView && view,const std::shared_ptr<C2GraphicBlock> & block,const sp<ABuffer> & imageData,bool wrapped)261 GraphicBlockBuffer::GraphicBlockBuffer(
262         const sp<AMessage> &format,
263         const sp<ABuffer> &buffer,
264         C2GraphicView &&view,
265         const std::shared_ptr<C2GraphicBlock> &block,
266         const sp<ABuffer> &imageData,
267         bool wrapped)
268     : Codec2Buffer(format, buffer),
269       mView(view),
270       mBlock(block),
271       mWrapped(wrapped) {
272     setImageData(imageData);
273 }
274 
asC2Buffer()275 std::shared_ptr<C2Buffer> GraphicBlockBuffer::asC2Buffer() {
276     ATRACE_CALL();
277     uint32_t width = mView.width();
278     uint32_t height = mView.height();
279     if (!mWrapped) {
280         (void)ImageCopy(mView, base(), imageData());
281     }
282     return C2Buffer::CreateGraphicBuffer(
283             mBlock->share(C2Rect(width, height), C2Fence()));
284 }
285 
286 // GraphicMetadataBuffer
GraphicMetadataBuffer(const sp<AMessage> & format,const std::shared_ptr<C2Allocator> & alloc)287 GraphicMetadataBuffer::GraphicMetadataBuffer(
288         const sp<AMessage> &format,
289         const std::shared_ptr<C2Allocator> &alloc)
290     : Codec2Buffer(format, new ABuffer(sizeof(VideoNativeMetadata))),
291       mAlloc(alloc) {
292     ((VideoNativeMetadata *)base())->pBuffer = nullptr;
293 }
294 
asC2Buffer()295 std::shared_ptr<C2Buffer> GraphicMetadataBuffer::asC2Buffer() {
296 #ifdef __LP64__
297     static std::once_flag s_checkOnce;
298     static bool s_is64bitOk {true};
299     std::call_once(s_checkOnce, [&](){
300         const std::string abi32list =
301         ::android::base::GetProperty("ro.product.cpu.abilist32", "");
302         if (!abi32list.empty()) {
303             int32_t inputSurfaceSetting =
304             ::android::base::GetIntProperty("debug.stagefright.c2inputsurface", int32_t(0));
305             s_is64bitOk = inputSurfaceSetting != 0;
306         }
307     });
308 
309     if (!s_is64bitOk) {
310         ALOGE("GraphicMetadataBuffer does not work in 32+64 system if compiled as 64-bit object"\
311               "when debug.stagefright.c2inputsurface is set to 0");
312         return nullptr;
313     }
314 #endif
315 
316     VideoNativeMetadata *meta = (VideoNativeMetadata *)base();
317     ANativeWindowBuffer *buffer = (ANativeWindowBuffer *)meta->pBuffer;
318     if (buffer == nullptr) {
319         ALOGD("VideoNativeMetadata contains null buffer");
320         return nullptr;
321     }
322 
323     ALOGV("VideoNativeMetadata: %dx%d", buffer->width, buffer->height);
324     C2Handle *handle = WrapNativeCodec2GrallocHandle(
325             buffer->handle,
326             buffer->width,
327             buffer->height,
328             buffer->format,
329             buffer->usage,
330             buffer->stride);
331     std::shared_ptr<C2GraphicAllocation> alloc;
332     c2_status_t err = mAlloc->priorGraphicAllocation(handle, &alloc);
333     if (err != C2_OK) {
334         ALOGD("Failed to wrap VideoNativeMetadata into C2GraphicAllocation");
335         native_handle_close(handle);
336         native_handle_delete(handle);
337         return nullptr;
338     }
339     std::shared_ptr<C2GraphicBlock> block = _C2BlockFactory::CreateGraphicBlock(alloc);
340 
341     meta->pBuffer = 0;
342     // TODO: wrap this in C2Fence so that the component can wait when it
343     //       actually starts processing.
344     if (meta->nFenceFd >= 0) {
345         sp<Fence> fence(new Fence(meta->nFenceFd));
346         fence->waitForever(LOG_TAG);
347     }
348     return C2Buffer::CreateGraphicBuffer(
349             block->share(C2Rect(buffer->width, buffer->height), C2Fence()));
350 }
351 
352 // ConstGraphicBlockBuffer
353 
354 // static
Allocate(const sp<AMessage> & format,const std::shared_ptr<C2Buffer> & buffer,std::function<sp<ABuffer> (size_t)> alloc)355 sp<ConstGraphicBlockBuffer> ConstGraphicBlockBuffer::Allocate(
356         const sp<AMessage> &format,
357         const std::shared_ptr<C2Buffer> &buffer,
358         std::function<sp<ABuffer>(size_t)> alloc) {
359     if (!buffer
360             || buffer->data().type() != C2BufferData::GRAPHIC
361             || buffer->data().graphicBlocks().size() != 1u) {
362         ALOGD("C2Buffer precond fail");
363         return nullptr;
364     }
365     ATRACE_BEGIN("ConstGraphicBlockBuffer::Allocate block->map()");
366     std::unique_ptr<const C2GraphicView> view(std::make_unique<const C2GraphicView>(
367             buffer->data().graphicBlocks()[0].map().get()));
368     ATRACE_END();
369     std::unique_ptr<const C2GraphicView> holder;
370 
371     GraphicView2MediaImageConverter converter(*view, format, false /* copy */);
372     if (converter.initCheck() != OK) {
373         ALOGD("Converter init failed: %d", converter.initCheck());
374         return nullptr;
375     }
376     bool wrapped = true;
377     sp<ABuffer> aBuffer = converter.wrap();
378     if (aBuffer == nullptr) {
379         aBuffer = alloc(converter.backBufferSize());
380         if (!converter.setBackBuffer(aBuffer)) {
381             ALOGD("Converter failed to set back buffer");
382             return nullptr;
383         }
384         wrapped = false;
385         converter.copyToMediaImage();
386         // We don't need the view.
387         holder = std::move(view);
388     }
389     return new ConstGraphicBlockBuffer(
390             format,
391             aBuffer,
392             std::move(view),
393             buffer,
394             converter.imageData(),
395             wrapped);
396 }
397 
398 // static
AllocateEmpty(const sp<AMessage> & format,std::function<sp<ABuffer> (size_t)> alloc)399 sp<ConstGraphicBlockBuffer> ConstGraphicBlockBuffer::AllocateEmpty(
400         const sp<AMessage> &format,
401         std::function<sp<ABuffer>(size_t)> alloc) {
402     int32_t width, height;
403     if (!format->findInt32("width", &width)
404             || !format->findInt32("height", &height)) {
405         ALOGD("format had no width / height");
406         return nullptr;
407     }
408     int32_t colorFormat = COLOR_FormatYUV420Flexible;
409     int32_t bpp = 12;  // 8(Y) + 2(U) + 2(V)
410     if (format->findInt32(KEY_COLOR_FORMAT, &colorFormat)) {
411         if (colorFormat == COLOR_FormatYUVP010) {
412             bpp = 24;  // 16(Y) + 4(U) + 4(V)
413         }
414     }
415     sp<ABuffer> aBuffer(alloc(align(width, 16) * align(height, 16) * bpp / 8));
416     if (aBuffer == nullptr) {
417         ALOGD("%s: failed to allocate buffer", __func__);
418         return nullptr;
419     }
420     return new ConstGraphicBlockBuffer(
421             format,
422             aBuffer,
423             nullptr,
424             nullptr,
425             nullptr,
426             false);
427 }
428 
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)429 ConstGraphicBlockBuffer::ConstGraphicBlockBuffer(
430         const sp<AMessage> &format,
431         const sp<ABuffer> &aBuffer,
432         std::unique_ptr<const C2GraphicView> &&view,
433         const std::shared_ptr<C2Buffer> &buffer,
434         const sp<ABuffer> &imageData,
435         bool wrapped)
436     : Codec2Buffer(format, aBuffer),
437       mView(std::move(view)),
438       mBufferRef(buffer),
439       mWrapped(wrapped) {
440     setImageData(imageData);
441 }
442 
asC2Buffer()443 std::shared_ptr<C2Buffer> ConstGraphicBlockBuffer::asC2Buffer() {
444     return mBufferRef;
445 }
446 
clearC2BufferRefs()447 void ConstGraphicBlockBuffer::clearC2BufferRefs() {
448     mView.reset();
449     mBufferRef.reset();
450 }
451 
canCopy(const std::shared_ptr<C2Buffer> & buffer) const452 bool ConstGraphicBlockBuffer::canCopy(const std::shared_ptr<C2Buffer> &buffer) const {
453     if (mWrapped || mBufferRef) {
454         ALOGD("ConstGraphicBlockBuffer::canCopy: %swrapped ; buffer ref %s",
455                 mWrapped ? "" : "not ", mBufferRef ? "exists" : "doesn't exist");
456         return false;
457     }
458     if (!buffer) {
459         // Nothing to copy, so we can copy by doing nothing.
460         return true;
461     }
462     if (buffer->data().type() != C2BufferData::GRAPHIC) {
463         ALOGD("ConstGraphicBlockBuffer::canCopy: buffer precondition unsatisfied");
464         return false;
465     }
466     if (buffer->data().graphicBlocks().size() == 0) {
467         return true;
468     } else if (buffer->data().graphicBlocks().size() != 1u) {
469         ALOGD("ConstGraphicBlockBuffer::canCopy: too many blocks");
470         return false;
471     }
472 
473     ATRACE_BEGIN("ConstGraphicBlockBuffer::canCopy block->map()");
474     GraphicView2MediaImageConverter converter(
475             buffer->data().graphicBlocks()[0].map().get(),
476             // FIXME: format() is not const, but we cannot change it, so do a const cast here
477             const_cast<ConstGraphicBlockBuffer *>(this)->format(),
478             true /* copy */);
479     ATRACE_END();
480     if (converter.initCheck() != OK) {
481         ALOGD("ConstGraphicBlockBuffer::canCopy: converter init failed: %d", converter.initCheck());
482         return false;
483     }
484     if (converter.backBufferSize() > capacity()) {
485         ALOGD("ConstGraphicBlockBuffer::canCopy: insufficient capacity: req %u has %zu",
486                 converter.backBufferSize(), capacity());
487         return false;
488     }
489     return true;
490 }
491 
copy(const std::shared_ptr<C2Buffer> & buffer)492 bool ConstGraphicBlockBuffer::copy(const std::shared_ptr<C2Buffer> &buffer) {
493     if (!buffer || buffer->data().graphicBlocks().size() == 0) {
494         setRange(0, 0);
495         return true;
496     }
497 
498     GraphicView2MediaImageConverter converter(
499             buffer->data().graphicBlocks()[0].map().get(), format(), true /* copy */);
500     if (converter.initCheck() != OK) {
501         ALOGD("ConstGraphicBlockBuffer::copy: converter init failed: %d", converter.initCheck());
502         return false;
503     }
504     sp<ABuffer> aBuffer = new ABuffer(base(), capacity());
505     if (!converter.setBackBuffer(aBuffer)) {
506         ALOGD("ConstGraphicBlockBuffer::copy: set back buffer failed");
507         return false;
508     }
509     setRange(0, aBuffer->size());  // align size info
510     converter.copyToMediaImage();
511     setImageData(converter.imageData());
512     mBufferRef = buffer;
513     return true;
514 }
515 
516 // EncryptedLinearBlockBuffer
517 
EncryptedLinearBlockBuffer(const sp<AMessage> & format,const std::shared_ptr<C2LinearBlock> & block,const sp<IMemory> & memory,int32_t heapSeqNum)518 EncryptedLinearBlockBuffer::EncryptedLinearBlockBuffer(
519         const sp<AMessage> &format,
520         const std::shared_ptr<C2LinearBlock> &block,
521         const sp<IMemory> &memory,
522         int32_t heapSeqNum)
523     // TODO: Using unsecurePointer() has some associated security pitfalls
524     //       (see declaration for details).
525     //       Either document why it is safe in this case or address the
526     //       issue (e.g. by copying).
527     : Codec2Buffer(format, new ABuffer(memory->unsecurePointer(), memory->size())),
528       mBlock(block),
529       mMemory(memory),
530       mHeapSeqNum(heapSeqNum) {
531 }
532 
asC2Buffer()533 std::shared_ptr<C2Buffer> EncryptedLinearBlockBuffer::asC2Buffer() {
534     return C2Buffer::CreateLinearBuffer(mBlock->share(offset(), size(), C2Fence()));
535 }
536 
fillSourceBuffer(hardware::drm::V1_0::SharedBuffer * source)537 void EncryptedLinearBlockBuffer::fillSourceBuffer(
538         hardware::drm::V1_0::SharedBuffer *source) {
539     BufferChannelBase::IMemoryToSharedBuffer(mMemory, mHeapSeqNum, source);
540 }
541 
fillSourceBuffer(hardware::cas::native::V1_0::SharedBuffer * source)542 void EncryptedLinearBlockBuffer::fillSourceBuffer(
543         hardware::cas::native::V1_0::SharedBuffer *source) {
544     ssize_t offset;
545     size_t size;
546 
547     mHidlMemory = hardware::fromHeap(mMemory->getMemory(&offset, &size));
548     source->heapBase = *mHidlMemory;
549     source->offset = offset;
550     source->size = size;
551 }
552 
copyDecryptedContent(const sp<IMemory> & decrypted,size_t length)553 bool EncryptedLinearBlockBuffer::copyDecryptedContent(
554         const sp<IMemory> &decrypted, size_t length) {
555     C2WriteView view = mBlock->map().get();
556     if (view.error() != C2_OK) {
557         return false;
558     }
559     if (view.size() < length) {
560         return false;
561     }
562     memcpy(view.data(), decrypted->unsecurePointer(), length);
563     return true;
564 }
565 
copyDecryptedContentFromMemory(size_t length)566 bool EncryptedLinearBlockBuffer::copyDecryptedContentFromMemory(size_t length) {
567     return copyDecryptedContent(mMemory, length);
568 }
569 
handle() const570 native_handle_t *EncryptedLinearBlockBuffer::handle() const {
571     return const_cast<native_handle_t *>(mBlock->handle());
572 }
573 
getMappedBlock(std::unique_ptr<MappedBlock> * const mappedBlock) const574 void EncryptedLinearBlockBuffer::getMappedBlock(
575         std::unique_ptr<MappedBlock> * const mappedBlock) const {
576     if (mappedBlock) {
577         mappedBlock->reset(new EncryptedLinearBlockBuffer::MappedBlock(mBlock));
578     }
579     return;
580 }
581 
MappedBlock(const std::shared_ptr<C2LinearBlock> & block)582 EncryptedLinearBlockBuffer::MappedBlock::MappedBlock(
583         const std::shared_ptr<C2LinearBlock> &block) : mView(block->map().get()) {
584 }
585 
copyDecryptedContent(const sp<IMemory> & decrypted,size_t length)586 bool EncryptedLinearBlockBuffer::MappedBlock::copyDecryptedContent(
587         const sp<IMemory> &decrypted, size_t length) {
588     if (mView.error() != C2_OK) {
589         return false;
590     }
591     if (mView.size() < length) {
592         ALOGE("View size(%d) less than decrypted length(%zu)",
593                 mView.size(), length);
594         return false;
595     }
596     memcpy(mView.data(), decrypted->unsecurePointer(), length);
597     mView.setOffset(mView.offset() + length);
598     return true;
599 }
600 
~MappedBlock()601 EncryptedLinearBlockBuffer::MappedBlock::~MappedBlock() {
602     mView.setOffset(0);
603 }
604 
605 using ::aidl::android::hardware::graphics::common::Cta861_3;
606 using ::aidl::android::hardware::graphics::common::Smpte2086;
607 
608 namespace {
609 
610 class GrallocBuffer {
611 public:
GrallocBuffer(const C2Handle * const handle)612     GrallocBuffer(const C2Handle *const handle) : mBuffer(nullptr) {
613         GraphicBufferMapper& mapper = GraphicBufferMapper::get();
614 
615         // Unwrap raw buffer handle from the C2Handle
616         native_handle_t *nh = UnwrapNativeCodec2GrallocHandle(handle);
617         if (!nh) {
618             ALOGE("handle is not compatible to any gralloc C2Handle types");
619             return;
620         }
621         // Import the raw handle so IMapper can use the buffer. The imported
622         // handle must be freed when the client is done with the buffer.
623         status_t status = mapper.importBufferNoValidate(
624                 nh,
625                 &mBuffer);
626 
627         if (status != OK) {
628             ALOGE("Failed to import buffer. Status: %d.", status);
629             return;
630         }
631 
632         // TRICKY: UnwrapNativeCodec2GrallocHandle creates a new handle but
633         //         does not clone the fds. Thus we need to delete the handle
634         //         without closing it.
635         native_handle_delete(nh);
636     }
637 
~GrallocBuffer()638     ~GrallocBuffer() {
639         GraphicBufferMapper& mapper = GraphicBufferMapper::get();
640         if (mBuffer) {
641             // Free the imported buffer handle. This does not release the
642             // underlying buffer itself.
643             mapper.freeBuffer(mBuffer);
644         }
645     }
646 
get() const647     buffer_handle_t get() const { return mBuffer; }
operator bool() const648     operator bool() const { return (mBuffer != nullptr); }
649 private:
650     buffer_handle_t mBuffer;
651 };
652 
653 }  // namspace
654 
GetHdrMetadataFromGralloc4Handle(const C2Handle * const handle,std::shared_ptr<C2StreamHdrStaticMetadataInfo::input> * staticInfo,std::shared_ptr<C2StreamHdrDynamicMetadataInfo::input> * dynamicInfo)655 c2_status_t GetHdrMetadataFromGralloc4Handle(
656         const C2Handle *const handle,
657         std::shared_ptr<C2StreamHdrStaticMetadataInfo::input> *staticInfo,
658         std::shared_ptr<C2StreamHdrDynamicMetadataInfo::input> *dynamicInfo) {
659     c2_status_t err = C2_OK;
660     GraphicBufferMapper& mapper = GraphicBufferMapper::get();
661     GrallocBuffer buffer(handle);
662     if (!buffer) {
663         // Gralloc4 not supported; nothing to do
664         return err;
665     }
666     if (staticInfo) {
667         ALOGV("Grabbing static HDR info from gralloc metadata");
668         staticInfo->reset(new C2StreamHdrStaticMetadataInfo::input(0u));
669         memset(&(*staticInfo)->mastering, 0, sizeof((*staticInfo)->mastering));
670         (*staticInfo)->maxCll = 0;
671         (*staticInfo)->maxFall = 0;
672 
673         std::optional<Smpte2086> smpte2086;
674         status_t status = mapper.getSmpte2086(buffer.get(), &smpte2086);
675         if (status != OK || !smpte2086) {
676             err = C2_CORRUPTED;
677         } else {
678             if (smpte2086) {
679                   (*staticInfo)->mastering.red.x    = smpte2086->primaryRed.x;
680                   (*staticInfo)->mastering.red.y    = smpte2086->primaryRed.y;
681                   (*staticInfo)->mastering.green.x  = smpte2086->primaryGreen.x;
682                   (*staticInfo)->mastering.green.y  = smpte2086->primaryGreen.y;
683                   (*staticInfo)->mastering.blue.x   = smpte2086->primaryBlue.x;
684                   (*staticInfo)->mastering.blue.y   = smpte2086->primaryBlue.y;
685                   (*staticInfo)->mastering.white.x  = smpte2086->whitePoint.x;
686                   (*staticInfo)->mastering.white.y  = smpte2086->whitePoint.y;
687 
688                   (*staticInfo)->mastering.maxLuminance = smpte2086->maxLuminance;
689                   (*staticInfo)->mastering.minLuminance = smpte2086->minLuminance;
690             }
691         }
692 
693         std::optional<Cta861_3> cta861_3;
694         status = mapper.getCta861_3(buffer.get(), &cta861_3);
695         if (status != OK || !cta861_3) {
696             err = C2_CORRUPTED;
697         } else {
698             if (cta861_3) {
699                   (*staticInfo)->maxCll   = cta861_3->maxContentLightLevel;
700                   (*staticInfo)->maxFall  = cta861_3->maxFrameAverageLightLevel;
701             }
702         }
703     }
704 
705     if (err != C2_OK) {
706         staticInfo->reset();
707     }
708 
709     if (dynamicInfo) {
710         ALOGV("Grabbing dynamic HDR info from gralloc metadata");
711         dynamicInfo->reset();
712         std::optional<std::vector<uint8_t>> vec;
713         status_t status = mapper.getSmpte2094_40(buffer.get(), &vec);
714         if (status != OK || !vec) {
715             dynamicInfo->reset();
716             err = C2_CORRUPTED;
717         } else {
718             if (vec) {
719                 *dynamicInfo = C2StreamHdrDynamicMetadataInfo::input::AllocShared(
720                       vec->size(), 0u, C2Config::HDR_DYNAMIC_METADATA_TYPE_SMPTE_2094_40);
721                 memcpy((*dynamicInfo)->m.data, vec->data(), vec->size());
722             }
723         }
724     }
725 
726     return err;
727 }
728 
SetMetadataToGralloc4Handle(android_dataspace_t dataSpace,const std::shared_ptr<const C2StreamHdrStaticMetadataInfo::output> & staticInfo,const std::shared_ptr<const C2StreamHdrDynamicMetadataInfo::output> & dynamicInfo,const C2Handle * const handle)729 c2_status_t SetMetadataToGralloc4Handle(
730         android_dataspace_t dataSpace,
731         const std::shared_ptr<const C2StreamHdrStaticMetadataInfo::output> &staticInfo,
732         const std::shared_ptr<const C2StreamHdrDynamicMetadataInfo::output> &dynamicInfo,
733         const C2Handle *const handle) {
734     c2_status_t err = C2_OK;
735     GraphicBufferMapper& mapper = GraphicBufferMapper::get();
736     GrallocBuffer buffer(handle);
737     if (!buffer) {
738         // Gralloc4 not supported; nothing to do
739         return err;
740     }
741     // Use V0 dataspaces for Gralloc4+
742     if (android::media::codec::provider_->dataspace_v0_partial()) {
743         ColorUtils::convertDataSpaceToV0(dataSpace);
744     }
745     status_t status = mapper.setDataspace(buffer.get(), static_cast<ui::Dataspace>(dataSpace));
746     if (status != OK) {
747        err = C2_CORRUPTED;
748     }
749     if (staticInfo && *staticInfo) {
750         ALOGV("Setting static HDR info as gralloc metadata");
751         std::optional<Smpte2086> smpte2086 = Smpte2086{
752             {staticInfo->mastering.red.x, staticInfo->mastering.red.y},
753             {staticInfo->mastering.green.x, staticInfo->mastering.green.y},
754             {staticInfo->mastering.blue.x, staticInfo->mastering.blue.y},
755             {staticInfo->mastering.white.x, staticInfo->mastering.white.y},
756             staticInfo->mastering.maxLuminance,
757             staticInfo->mastering.minLuminance,
758         };
759         if (0.0 <= smpte2086->primaryRed.x && smpte2086->primaryRed.x <= 1.0
760                 && 0.0 <= smpte2086->primaryRed.y && smpte2086->primaryRed.y <= 1.0
761                 && 0.0 <= smpte2086->primaryGreen.x && smpte2086->primaryGreen.x <= 1.0
762                 && 0.0 <= smpte2086->primaryGreen.y && smpte2086->primaryGreen.y <= 1.0
763                 && 0.0 <= smpte2086->primaryBlue.x && smpte2086->primaryBlue.x <= 1.0
764                 && 0.0 <= smpte2086->primaryBlue.y && smpte2086->primaryBlue.y <= 1.0
765                 && 0.0 <= smpte2086->whitePoint.x && smpte2086->whitePoint.x <= 1.0
766                 && 0.0 <= smpte2086->whitePoint.y && smpte2086->whitePoint.y <= 1.0
767                 && 0.0 <= smpte2086->maxLuminance && 0.0 <= smpte2086->minLuminance) {
768             status = mapper.setSmpte2086(buffer.get(), smpte2086);
769             if (status != OK) {
770                 err = C2_CORRUPTED;
771             }
772         }
773         std::optional<Cta861_3> cta861_3 = Cta861_3{
774             staticInfo->maxCll,
775             staticInfo->maxFall,
776         };
777         if (0.0 <= cta861_3->maxContentLightLevel && 0.0 <= cta861_3->maxFrameAverageLightLevel) {
778             status = mapper.setCta861_3(buffer.get(), cta861_3);
779             if (status != OK) {
780                 err = C2_CORRUPTED;
781             }
782         }
783     }
784     if (dynamicInfo && *dynamicInfo && dynamicInfo->flexCount() > 0) {
785         ALOGV("Setting dynamic HDR info as gralloc metadata");
786         if (dynamicInfo->m.type_ == C2Config::HDR_DYNAMIC_METADATA_TYPE_SMPTE_2094_40) {
787             std::optional<std::vector<uint8_t>> smpte2094_40 = std::vector<uint8_t>();
788             smpte2094_40->resize(dynamicInfo->flexCount());
789             memcpy(smpte2094_40->data(), dynamicInfo->m.data, dynamicInfo->flexCount());
790 
791             status = mapper.setSmpte2094_40(buffer.get(), smpte2094_40);
792             if (status != OK) {
793                 err = C2_CORRUPTED;
794             }
795         } else {
796             err = C2_BAD_VALUE;
797         }
798     }
799 
800     return err;
801 }
802 
803 }  // namespace android
804