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 <aidl/android/hardware/graphics/common/Cta861_3.h>
24 #include <aidl/android/hardware/graphics/common/Smpte2086.h>
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 <mediadrm/ICrypto.h>
37 #include <nativebase/nativebase.h>
38 #include <ui/GraphicBufferMapper.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 
47 namespace android {
48 
49 // Codec2Buffer
50 
canCopyLinear(const std::shared_ptr<C2Buffer> & buffer) const51 bool Codec2Buffer::canCopyLinear(const std::shared_ptr<C2Buffer> &buffer) const {
52     if (const_cast<Codec2Buffer *>(this)->base() == nullptr) {
53         return false;
54     }
55     if (!buffer) {
56         // Nothing to copy, so we can copy by doing nothing.
57         return true;
58     }
59     if (buffer->data().type() != C2BufferData::LINEAR) {
60         return false;
61     }
62     if (buffer->data().linearBlocks().size() == 0u) {
63         // Nothing to copy, so we can copy by doing nothing.
64         return true;
65     } else if (buffer->data().linearBlocks().size() > 1u) {
66         // We don't know how to copy more than one blocks.
67         return false;
68     }
69     if (buffer->data().linearBlocks()[0].size() > capacity()) {
70         // It won't fit.
71         return false;
72     }
73     return true;
74 }
75 
copyLinear(const std::shared_ptr<C2Buffer> & buffer)76 bool Codec2Buffer::copyLinear(const std::shared_ptr<C2Buffer> &buffer) {
77     // We assume that all canCopyLinear() checks passed.
78     if (!buffer || buffer->data().linearBlocks().size() == 0u
79             || buffer->data().linearBlocks()[0].size() == 0u) {
80         setRange(0, 0);
81         return true;
82     }
83     C2ReadView view = buffer->data().linearBlocks()[0].map().get();
84     if (view.error() != C2_OK) {
85         ALOGD("Error while mapping: %d", view.error());
86         return false;
87     }
88     if (view.capacity() > capacity()) {
89         ALOGD("C2ConstLinearBlock lied --- it actually doesn't fit: view(%u) > this(%zu)",
90                 view.capacity(), capacity());
91         return false;
92     }
93     memcpy(base(), view.data(), view.capacity());
94     setRange(0, view.capacity());
95     return true;
96 }
97 
setImageData(const sp<ABuffer> & imageData)98 void Codec2Buffer::setImageData(const sp<ABuffer> &imageData) {
99     mImageData = imageData;
100 }
101 
102 // LocalLinearBuffer
103 
canCopy(const std::shared_ptr<C2Buffer> & buffer) const104 bool LocalLinearBuffer::canCopy(const std::shared_ptr<C2Buffer> &buffer) const {
105     return canCopyLinear(buffer);
106 }
107 
copy(const std::shared_ptr<C2Buffer> & buffer)108 bool LocalLinearBuffer::copy(const std::shared_ptr<C2Buffer> &buffer) {
109     return copyLinear(buffer);
110 }
111 
112 // DummyContainerBuffer
113 
114 static uint8_t sDummyByte[1] = { 0 };
115 
DummyContainerBuffer(const sp<AMessage> & format,const std::shared_ptr<C2Buffer> & buffer)116 DummyContainerBuffer::DummyContainerBuffer(
117         const sp<AMessage> &format, const std::shared_ptr<C2Buffer> &buffer)
118     : Codec2Buffer(format, new ABuffer(sDummyByte, 1)),
119       mBufferRef(buffer) {
120     setRange(0, buffer ? 1 : 0);
121 }
122 
asC2Buffer()123 std::shared_ptr<C2Buffer> DummyContainerBuffer::asC2Buffer() {
124     return mBufferRef;
125 }
126 
clearC2BufferRefs()127 void DummyContainerBuffer::clearC2BufferRefs() {
128     mBufferRef.reset();
129 }
130 
canCopy(const std::shared_ptr<C2Buffer> &) const131 bool DummyContainerBuffer::canCopy(const std::shared_ptr<C2Buffer> &) const {
132     return !mBufferRef;
133 }
134 
copy(const std::shared_ptr<C2Buffer> & buffer)135 bool DummyContainerBuffer::copy(const std::shared_ptr<C2Buffer> &buffer) {
136     mBufferRef = buffer;
137     setRange(0, mBufferRef ? 1 : 0);
138     return true;
139 }
140 
141 // LinearBlockBuffer
142 
143 // static
Allocate(const sp<AMessage> & format,const std::shared_ptr<C2LinearBlock> & block)144 sp<LinearBlockBuffer> LinearBlockBuffer::Allocate(
145         const sp<AMessage> &format, const std::shared_ptr<C2LinearBlock> &block) {
146     C2WriteView writeView(block->map().get());
147     if (writeView.error() != C2_OK) {
148         return nullptr;
149     }
150     return new LinearBlockBuffer(format, std::move(writeView), block);
151 }
152 
asC2Buffer()153 std::shared_ptr<C2Buffer> LinearBlockBuffer::asC2Buffer() {
154     return C2Buffer::CreateLinearBuffer(mBlock->share(offset(), size(), C2Fence()));
155 }
156 
canCopy(const std::shared_ptr<C2Buffer> & buffer) const157 bool LinearBlockBuffer::canCopy(const std::shared_ptr<C2Buffer> &buffer) const {
158     return canCopyLinear(buffer);
159 }
160 
copy(const std::shared_ptr<C2Buffer> & buffer)161 bool LinearBlockBuffer::copy(const std::shared_ptr<C2Buffer> &buffer) {
162     return copyLinear(buffer);
163 }
164 
LinearBlockBuffer(const sp<AMessage> & format,C2WriteView && writeView,const std::shared_ptr<C2LinearBlock> & block)165 LinearBlockBuffer::LinearBlockBuffer(
166         const sp<AMessage> &format,
167         C2WriteView&& writeView,
168         const std::shared_ptr<C2LinearBlock> &block)
169     : Codec2Buffer(format, new ABuffer(writeView.data(), writeView.size())),
170       mWriteView(writeView),
171       mBlock(block) {
172 }
173 
174 // ConstLinearBlockBuffer
175 
176 // static
Allocate(const sp<AMessage> & format,const std::shared_ptr<C2Buffer> & buffer)177 sp<ConstLinearBlockBuffer> ConstLinearBlockBuffer::Allocate(
178         const sp<AMessage> &format, const std::shared_ptr<C2Buffer> &buffer) {
179     if (!buffer
180             || buffer->data().type() != C2BufferData::LINEAR
181             || buffer->data().linearBlocks().size() != 1u) {
182         if (!buffer) {
183             ALOGD("ConstLinearBlockBuffer::Allocate: null buffer");
184         } else {
185             ALOGW("ConstLinearBlockBuffer::Allocate: type=%d # linear blocks=%zu",
186                   buffer->data().type(), buffer->data().linearBlocks().size());
187         }
188         return nullptr;
189     }
190     C2ReadView readView(buffer->data().linearBlocks()[0].map().get());
191     if (readView.error() != C2_OK) {
192         ALOGW("ConstLinearBlockBuffer::Allocate: readView.error()=%d", readView.error());
193         return nullptr;
194     }
195     return new ConstLinearBlockBuffer(format, std::move(readView), buffer);
196 }
197 
ConstLinearBlockBuffer(const sp<AMessage> & format,C2ReadView && readView,const std::shared_ptr<C2Buffer> & buffer)198 ConstLinearBlockBuffer::ConstLinearBlockBuffer(
199         const sp<AMessage> &format,
200         C2ReadView&& readView,
201         const std::shared_ptr<C2Buffer> &buffer)
202     : Codec2Buffer(format, new ABuffer(
203             // NOTE: ABuffer only takes non-const pointer but this data is
204             //       supposed to be read-only.
205             const_cast<uint8_t *>(readView.data()), readView.capacity())),
206       mReadView(readView),
207       mBufferRef(buffer) {
208 }
209 
asC2Buffer()210 std::shared_ptr<C2Buffer> ConstLinearBlockBuffer::asC2Buffer() {
211     return mBufferRef;
212 }
213 
clearC2BufferRefs()214 void ConstLinearBlockBuffer::clearC2BufferRefs() {
215     mBufferRef.reset();
216 }
217 
218 // GraphicView2MediaImageConverter
219 
220 namespace {
221 
222 class GraphicView2MediaImageConverter {
223 public:
224     /**
225      * Creates a C2GraphicView <=> MediaImage converter
226      *
227      * \param view C2GraphicView object
228      * \param format buffer format
229      * \param copy whether the converter is used for copy or not
230      */
GraphicView2MediaImageConverter(const C2GraphicView & view,const sp<AMessage> & format,bool copy)231     GraphicView2MediaImageConverter(
232             const C2GraphicView &view, const sp<AMessage> &format, bool copy)
233         : mInitCheck(NO_INIT),
234           mView(view),
235           mWidth(view.width()),
236           mHeight(view.height()),
237           mAllocatedDepth(0),
238           mBackBufferSize(0),
239           mMediaImage(new ABuffer(sizeof(MediaImage2))) {
240         ATRACE_CALL();
241         if (!format->findInt32(KEY_COLOR_FORMAT, &mClientColorFormat)) {
242             mClientColorFormat = COLOR_FormatYUV420Flexible;
243         }
244         if (!format->findInt32("android._color-format", &mComponentColorFormat)) {
245             mComponentColorFormat = COLOR_FormatYUV420Flexible;
246         }
247         if (view.error() != C2_OK) {
248             ALOGD("Converter: view.error() = %d", view.error());
249             mInitCheck = BAD_VALUE;
250             return;
251         }
252         MediaImage2 *mediaImage = (MediaImage2 *)mMediaImage->base();
253         const C2PlanarLayout &layout = view.layout();
254         if (layout.numPlanes == 0) {
255             ALOGD("Converter: 0 planes");
256             mInitCheck = BAD_VALUE;
257             return;
258         }
259         memset(mediaImage, 0, sizeof(*mediaImage));
260         mAllocatedDepth = layout.planes[0].allocatedDepth;
261         uint32_t bitDepth = layout.planes[0].bitDepth;
262 
263         // align width and height to support subsampling cleanly
264         uint32_t stride = align(view.crop().width, 2) * divUp(layout.planes[0].allocatedDepth, 8u);
265         uint32_t vStride = align(view.crop().height, 2);
266 
267         bool tryWrapping = !copy;
268 
269         switch (layout.type) {
270             case C2PlanarLayout::TYPE_YUV: {
271                 mediaImage->mType = MediaImage2::MEDIA_IMAGE_TYPE_YUV;
272                 if (layout.numPlanes != 3) {
273                     ALOGD("Converter: %d planes for YUV layout", layout.numPlanes);
274                     mInitCheck = BAD_VALUE;
275                     return;
276                 }
277                 std::optional<int> clientBitDepth = {};
278                 switch (mClientColorFormat) {
279                     case COLOR_FormatYUVP010:
280                         clientBitDepth = 10;
281                         break;
282                     case COLOR_FormatYUV411PackedPlanar:
283                     case COLOR_FormatYUV411Planar:
284                     case COLOR_FormatYUV420Flexible:
285                     case COLOR_FormatYUV420PackedPlanar:
286                     case COLOR_FormatYUV420PackedSemiPlanar:
287                     case COLOR_FormatYUV420Planar:
288                     case COLOR_FormatYUV420SemiPlanar:
289                     case COLOR_FormatYUV422Flexible:
290                     case COLOR_FormatYUV422PackedPlanar:
291                     case COLOR_FormatYUV422PackedSemiPlanar:
292                     case COLOR_FormatYUV422Planar:
293                     case COLOR_FormatYUV422SemiPlanar:
294                     case COLOR_FormatYUV444Flexible:
295                     case COLOR_FormatYUV444Interleaved:
296                         clientBitDepth = 8;
297                         break;
298                     default:
299                         // no-op; used with optional
300                         break;
301 
302                 }
303                 // conversion fails if client bit-depth and the component bit-depth differs
304                 if ((clientBitDepth) && (bitDepth != clientBitDepth.value())) {
305                     ALOGD("Bit depth of client: %d and component: %d differs",
306                         *clientBitDepth, bitDepth);
307                     mInitCheck = BAD_VALUE;
308                     return;
309                 }
310                 C2PlaneInfo yPlane = layout.planes[C2PlanarLayout::PLANE_Y];
311                 C2PlaneInfo uPlane = layout.planes[C2PlanarLayout::PLANE_U];
312                 C2PlaneInfo vPlane = layout.planes[C2PlanarLayout::PLANE_V];
313                 if (yPlane.channel != C2PlaneInfo::CHANNEL_Y
314                         || uPlane.channel != C2PlaneInfo::CHANNEL_CB
315                         || vPlane.channel != C2PlaneInfo::CHANNEL_CR) {
316                     ALOGD("Converter: not YUV layout");
317                     mInitCheck = BAD_VALUE;
318                     return;
319                 }
320                 bool yuv420888 = yPlane.rowSampling == 1 && yPlane.colSampling == 1
321                         && uPlane.rowSampling == 2 && uPlane.colSampling == 2
322                         && vPlane.rowSampling == 2 && vPlane.colSampling == 2;
323                 if (yuv420888) {
324                     for (uint32_t i = 0; i < 3; ++i) {
325                         const C2PlaneInfo &plane = layout.planes[i];
326                         if (plane.allocatedDepth != 8 || plane.bitDepth != 8) {
327                             yuv420888 = false;
328                             break;
329                         }
330                     }
331                     yuv420888 = yuv420888 && yPlane.colInc == 1 && uPlane.rowInc == vPlane.rowInc;
332                 }
333                 int32_t copyFormat = mClientColorFormat;
334                 if (yuv420888 && mClientColorFormat == COLOR_FormatYUV420Flexible) {
335                     if (uPlane.colInc == 2 && vPlane.colInc == 2
336                             && yPlane.rowInc == uPlane.rowInc) {
337                         copyFormat = COLOR_FormatYUV420PackedSemiPlanar;
338                     } else if (uPlane.colInc == 1 && vPlane.colInc == 1
339                             && yPlane.rowInc == uPlane.rowInc * 2) {
340                         copyFormat = COLOR_FormatYUV420PackedPlanar;
341                     }
342                 }
343                 ALOGV("client_fmt=0x%x y:{colInc=%d rowInc=%d} u:{colInc=%d rowInc=%d} "
344                         "v:{colInc=%d rowInc=%d}",
345                         mClientColorFormat,
346                         yPlane.colInc, yPlane.rowInc,
347                         uPlane.colInc, uPlane.rowInc,
348                         vPlane.colInc, vPlane.rowInc);
349                 switch (copyFormat) {
350                     case COLOR_FormatYUV420Flexible:
351                     case COLOR_FormatYUV420Planar:
352                     case COLOR_FormatYUV420PackedPlanar:
353                         mediaImage->mPlane[mediaImage->Y].mOffset = 0;
354                         mediaImage->mPlane[mediaImage->Y].mColInc = 1;
355                         mediaImage->mPlane[mediaImage->Y].mRowInc = stride;
356                         mediaImage->mPlane[mediaImage->Y].mHorizSubsampling = 1;
357                         mediaImage->mPlane[mediaImage->Y].mVertSubsampling = 1;
358 
359                         mediaImage->mPlane[mediaImage->U].mOffset = stride * vStride;
360                         mediaImage->mPlane[mediaImage->U].mColInc = 1;
361                         mediaImage->mPlane[mediaImage->U].mRowInc = stride / 2;
362                         mediaImage->mPlane[mediaImage->U].mHorizSubsampling = 2;
363                         mediaImage->mPlane[mediaImage->U].mVertSubsampling = 2;
364 
365                         mediaImage->mPlane[mediaImage->V].mOffset = stride * vStride * 5 / 4;
366                         mediaImage->mPlane[mediaImage->V].mColInc = 1;
367                         mediaImage->mPlane[mediaImage->V].mRowInc = stride / 2;
368                         mediaImage->mPlane[mediaImage->V].mHorizSubsampling = 2;
369                         mediaImage->mPlane[mediaImage->V].mVertSubsampling = 2;
370 
371                         if (tryWrapping && mClientColorFormat != COLOR_FormatYUV420Flexible) {
372                             tryWrapping = yuv420888 && uPlane.colInc == 1 && vPlane.colInc == 1
373                                     && yPlane.rowInc == uPlane.rowInc * 2
374                                     && view.data()[0] < view.data()[1]
375                                     && view.data()[1] < view.data()[2];
376                         }
377                         break;
378 
379                     case COLOR_FormatYUV420SemiPlanar:
380                     case COLOR_FormatYUV420PackedSemiPlanar:
381                         mediaImage->mPlane[mediaImage->Y].mOffset = 0;
382                         mediaImage->mPlane[mediaImage->Y].mColInc = 1;
383                         mediaImage->mPlane[mediaImage->Y].mRowInc = stride;
384                         mediaImage->mPlane[mediaImage->Y].mHorizSubsampling = 1;
385                         mediaImage->mPlane[mediaImage->Y].mVertSubsampling = 1;
386 
387                         mediaImage->mPlane[mediaImage->U].mOffset = stride * vStride;
388                         mediaImage->mPlane[mediaImage->U].mColInc = 2;
389                         mediaImage->mPlane[mediaImage->U].mRowInc = stride;
390                         mediaImage->mPlane[mediaImage->U].mHorizSubsampling = 2;
391                         mediaImage->mPlane[mediaImage->U].mVertSubsampling = 2;
392 
393                         mediaImage->mPlane[mediaImage->V].mOffset = stride * vStride + 1;
394                         mediaImage->mPlane[mediaImage->V].mColInc = 2;
395                         mediaImage->mPlane[mediaImage->V].mRowInc = stride;
396                         mediaImage->mPlane[mediaImage->V].mHorizSubsampling = 2;
397                         mediaImage->mPlane[mediaImage->V].mVertSubsampling = 2;
398 
399                         if (tryWrapping && mClientColorFormat != COLOR_FormatYUV420Flexible) {
400                             tryWrapping = yuv420888 && uPlane.colInc == 2 && vPlane.colInc == 2
401                                     && yPlane.rowInc == uPlane.rowInc
402                                     && view.data()[0] < view.data()[1]
403                                     && view.data()[1] < view.data()[2];
404                         }
405                         break;
406 
407                     case COLOR_FormatYUVP010:
408                         // stride is in bytes
409                         mediaImage->mPlane[mediaImage->Y].mOffset = 0;
410                         mediaImage->mPlane[mediaImage->Y].mColInc = 2;
411                         mediaImage->mPlane[mediaImage->Y].mRowInc = stride;
412                         mediaImage->mPlane[mediaImage->Y].mHorizSubsampling = 1;
413                         mediaImage->mPlane[mediaImage->Y].mVertSubsampling = 1;
414 
415                         mediaImage->mPlane[mediaImage->U].mOffset = stride * vStride;
416                         mediaImage->mPlane[mediaImage->U].mColInc = 4;
417                         mediaImage->mPlane[mediaImage->U].mRowInc = stride;
418                         mediaImage->mPlane[mediaImage->U].mHorizSubsampling = 2;
419                         mediaImage->mPlane[mediaImage->U].mVertSubsampling = 2;
420 
421                         mediaImage->mPlane[mediaImage->V].mOffset = stride * vStride + 2;
422                         mediaImage->mPlane[mediaImage->V].mColInc = 4;
423                         mediaImage->mPlane[mediaImage->V].mRowInc = stride;
424                         mediaImage->mPlane[mediaImage->V].mHorizSubsampling = 2;
425                         mediaImage->mPlane[mediaImage->V].mVertSubsampling = 2;
426                         if (tryWrapping) {
427                             tryWrapping = yPlane.allocatedDepth == 16
428                                     && uPlane.allocatedDepth == 16
429                                     && vPlane.allocatedDepth == 16
430                                     && yPlane.bitDepth == 10
431                                     && uPlane.bitDepth == 10
432                                     && vPlane.bitDepth == 10
433                                     && yPlane.rightShift == 6
434                                     && uPlane.rightShift == 6
435                                     && vPlane.rightShift == 6
436                                     && yPlane.rowSampling == 1 && yPlane.colSampling == 1
437                                     && uPlane.rowSampling == 2 && uPlane.colSampling == 2
438                                     && vPlane.rowSampling == 2 && vPlane.colSampling == 2
439                                     && yPlane.colInc == 2
440                                     && uPlane.colInc == 4
441                                     && vPlane.colInc == 4
442                                     && yPlane.rowInc == uPlane.rowInc
443                                     && yPlane.rowInc == vPlane.rowInc;
444                         }
445                         break;
446 
447                     default: {
448                         // default to fully planar format --- this will be overridden if wrapping
449                         // TODO: keep interleaved format
450                         int32_t colInc = divUp(mAllocatedDepth, 8u);
451                         int32_t rowInc = stride * colInc / yPlane.colSampling;
452                         mediaImage->mPlane[mediaImage->Y].mOffset = 0;
453                         mediaImage->mPlane[mediaImage->Y].mColInc = colInc;
454                         mediaImage->mPlane[mediaImage->Y].mRowInc = rowInc;
455                         mediaImage->mPlane[mediaImage->Y].mHorizSubsampling = yPlane.colSampling;
456                         mediaImage->mPlane[mediaImage->Y].mVertSubsampling = yPlane.rowSampling;
457                         int32_t offset = rowInc * vStride / yPlane.rowSampling;
458 
459                         rowInc = stride * colInc / uPlane.colSampling;
460                         mediaImage->mPlane[mediaImage->U].mOffset = offset;
461                         mediaImage->mPlane[mediaImage->U].mColInc = colInc;
462                         mediaImage->mPlane[mediaImage->U].mRowInc = rowInc;
463                         mediaImage->mPlane[mediaImage->U].mHorizSubsampling = uPlane.colSampling;
464                         mediaImage->mPlane[mediaImage->U].mVertSubsampling = uPlane.rowSampling;
465                         offset += rowInc * vStride / uPlane.rowSampling;
466 
467                         rowInc = stride * colInc / vPlane.colSampling;
468                         mediaImage->mPlane[mediaImage->V].mOffset = offset;
469                         mediaImage->mPlane[mediaImage->V].mColInc = colInc;
470                         mediaImage->mPlane[mediaImage->V].mRowInc = rowInc;
471                         mediaImage->mPlane[mediaImage->V].mHorizSubsampling = vPlane.colSampling;
472                         mediaImage->mPlane[mediaImage->V].mVertSubsampling = vPlane.rowSampling;
473                         break;
474                     }
475                 }
476                 break;
477             }
478 
479             case C2PlanarLayout::TYPE_YUVA:
480                 ALOGD("Converter: unrecognized color format "
481                         "(client %d component %d) for YUVA layout",
482                         mClientColorFormat, mComponentColorFormat);
483                 mInitCheck = NO_INIT;
484                 return;
485             case C2PlanarLayout::TYPE_RGB:
486                 mediaImage->mType = MediaImage2::MEDIA_IMAGE_TYPE_RGB;
487                 // TODO: support MediaImage layout
488                 switch (mClientColorFormat) {
489                     case COLOR_FormatSurface:
490                     case COLOR_FormatRGBFlexible:
491                     case COLOR_Format24bitBGR888:
492                     case COLOR_Format24bitRGB888:
493                         ALOGD("Converter: accept color format "
494                                 "(client %d component %d) for RGB layout",
495                                 mClientColorFormat, mComponentColorFormat);
496                         break;
497                     default:
498                         ALOGD("Converter: unrecognized color format "
499                                 "(client %d component %d) for RGB layout",
500                                 mClientColorFormat, mComponentColorFormat);
501                         mInitCheck = BAD_VALUE;
502                         return;
503                 }
504                 if (layout.numPlanes != 3) {
505                     ALOGD("Converter: %d planes for RGB layout", layout.numPlanes);
506                     mInitCheck = BAD_VALUE;
507                     return;
508                 }
509                 break;
510             case C2PlanarLayout::TYPE_RGBA:
511                 mediaImage->mType = MediaImage2::MEDIA_IMAGE_TYPE_RGBA;
512                 // TODO: support MediaImage layout
513                 switch (mClientColorFormat) {
514                     case COLOR_FormatSurface:
515                     case COLOR_FormatRGBAFlexible:
516                     case COLOR_Format32bitABGR8888:
517                     case COLOR_Format32bitARGB8888:
518                     case COLOR_Format32bitBGRA8888:
519                         ALOGD("Converter: accept color format "
520                                 "(client %d component %d) for RGBA layout",
521                                 mClientColorFormat, mComponentColorFormat);
522                         break;
523                     default:
524                         ALOGD("Converter: unrecognized color format "
525                                 "(client %d component %d) for RGBA layout",
526                                 mClientColorFormat, mComponentColorFormat);
527                         mInitCheck = BAD_VALUE;
528                         return;
529                 }
530                 if (layout.numPlanes != 4) {
531                     ALOGD("Converter: %d planes for RGBA layout", layout.numPlanes);
532                     mInitCheck = BAD_VALUE;
533                     return;
534                 }
535                 break;
536             default:
537                 mediaImage->mType = MediaImage2::MEDIA_IMAGE_TYPE_UNKNOWN;
538                 if (layout.numPlanes == 1) {
539                     const C2PlaneInfo &plane = layout.planes[0];
540                     if (plane.colInc < 0 || plane.rowInc < 0) {
541                         // Copy-only if we have negative colInc/rowInc
542                         tryWrapping = false;
543                     }
544                     mediaImage->mPlane[0].mOffset = 0;
545                     mediaImage->mPlane[0].mColInc = std::abs(plane.colInc);
546                     mediaImage->mPlane[0].mRowInc = std::abs(plane.rowInc);
547                     mediaImage->mPlane[0].mHorizSubsampling = plane.colSampling;
548                     mediaImage->mPlane[0].mVertSubsampling = plane.rowSampling;
549                 } else {
550                     ALOGD("Converter: unrecognized layout: color format (client %d component %d)",
551                             mClientColorFormat, mComponentColorFormat);
552                     mInitCheck = NO_INIT;
553                     return;
554                 }
555                 break;
556         }
557         if (tryWrapping) {
558             // try to map directly. check if the planes are near one another
559             const uint8_t *minPtr = mView.data()[0];
560             const uint8_t *maxPtr = mView.data()[0];
561             int32_t planeSize = 0;
562             for (uint32_t i = 0; i < layout.numPlanes; ++i) {
563                 const C2PlaneInfo &plane = layout.planes[i];
564                 int64_t planeStride = std::abs(plane.rowInc / plane.colInc);
565                 ssize_t minOffset = plane.minOffset(
566                         mWidth / plane.colSampling, mHeight / plane.rowSampling);
567                 ssize_t maxOffset = plane.maxOffset(
568                         mWidth / plane.colSampling, mHeight / plane.rowSampling);
569                 if (minPtr > mView.data()[i] + minOffset) {
570                     minPtr = mView.data()[i] + minOffset;
571                 }
572                 if (maxPtr < mView.data()[i] + maxOffset) {
573                     maxPtr = mView.data()[i] + maxOffset;
574                 }
575                 planeSize += planeStride * divUp(mAllocatedDepth, 8u)
576                         * align(mHeight, 64) / plane.rowSampling;
577             }
578 
579             if (minPtr == mView.data()[0] && (maxPtr - minPtr) <= planeSize) {
580                 // FIXME: this is risky as reading/writing data out of bound results
581                 //        in an undefined behavior, but gralloc does assume a
582                 //        contiguous mapping
583                 for (uint32_t i = 0; i < layout.numPlanes; ++i) {
584                     const C2PlaneInfo &plane = layout.planes[i];
585                     mediaImage->mPlane[i].mOffset = mView.data()[i] - minPtr;
586                     mediaImage->mPlane[i].mColInc = plane.colInc;
587                     mediaImage->mPlane[i].mRowInc = plane.rowInc;
588                     mediaImage->mPlane[i].mHorizSubsampling = plane.colSampling;
589                     mediaImage->mPlane[i].mVertSubsampling = plane.rowSampling;
590                 }
591                 mWrapped = new ABuffer(const_cast<uint8_t *>(minPtr), maxPtr - minPtr);
592                 ALOGV("Converter: wrapped (capacity=%zu)", mWrapped->capacity());
593             }
594         }
595         mediaImage->mNumPlanes = layout.numPlanes;
596         mediaImage->mWidth = view.crop().width;
597         mediaImage->mHeight = view.crop().height;
598         mediaImage->mBitDepth = bitDepth;
599         mediaImage->mBitDepthAllocated = mAllocatedDepth;
600 
601         uint32_t bufferSize = 0;
602         for (uint32_t i = 0; i < layout.numPlanes; ++i) {
603             const C2PlaneInfo &plane = layout.planes[i];
604             if (plane.allocatedDepth < plane.bitDepth
605                     || plane.rightShift != plane.allocatedDepth - plane.bitDepth) {
606                 ALOGD("rightShift value of %u unsupported", plane.rightShift);
607                 mInitCheck = BAD_VALUE;
608                 return;
609             }
610             if (plane.allocatedDepth > 8 && plane.endianness != C2PlaneInfo::NATIVE) {
611                 ALOGD("endianness value of %u unsupported", plane.endianness);
612                 mInitCheck = BAD_VALUE;
613                 return;
614             }
615             if (plane.allocatedDepth != mAllocatedDepth || plane.bitDepth != bitDepth) {
616                 ALOGD("different allocatedDepth/bitDepth per plane unsupported");
617                 mInitCheck = BAD_VALUE;
618                 return;
619             }
620             // stride is in bytes
621             bufferSize += stride * vStride / plane.rowSampling / plane.colSampling;
622         }
623 
624         mBackBufferSize = bufferSize;
625         mInitCheck = OK;
626     }
627 
initCheck() const628     status_t initCheck() const { return mInitCheck; }
629 
backBufferSize() const630     uint32_t backBufferSize() const { return mBackBufferSize; }
631 
632     /**
633      * Wrap C2GraphicView using a MediaImage2. Note that if not wrapped, the content is not mapped
634      * in this function --- the caller should use CopyGraphicView2MediaImage() function to copy the
635      * data into a backing buffer explicitly.
636      *
637      * \return media buffer. This is null if wrapping failed.
638      */
wrap() const639     sp<ABuffer> wrap() const {
640         if (mBackBuffer == nullptr) {
641             return mWrapped;
642         }
643         return nullptr;
644     }
645 
setBackBuffer(const sp<ABuffer> & backBuffer)646     bool setBackBuffer(const sp<ABuffer> &backBuffer) {
647         if (backBuffer == nullptr) {
648             return false;
649         }
650         if (backBuffer->capacity() < mBackBufferSize) {
651             return false;
652         }
653         backBuffer->setRange(0, mBackBufferSize);
654         mBackBuffer = backBuffer;
655         return true;
656     }
657 
658     /**
659      * Copy C2GraphicView to MediaImage2.
660      */
copyToMediaImage()661     status_t copyToMediaImage() {
662         ATRACE_CALL();
663         if (mInitCheck != OK) {
664             return mInitCheck;
665         }
666         return ImageCopy(mBackBuffer->base(), getMediaImage(), mView);
667     }
668 
imageData() const669     const sp<ABuffer> &imageData() const { return mMediaImage; }
670 
671 private:
672     status_t mInitCheck;
673 
674     const C2GraphicView mView;
675     uint32_t mWidth;
676     uint32_t mHeight;
677     int32_t mClientColorFormat;  ///< SDK color format for MediaImage
678     int32_t mComponentColorFormat;  ///< SDK color format from component
679     sp<ABuffer> mWrapped;  ///< wrapped buffer (if we can map C2Buffer to an ABuffer)
680     uint32_t mAllocatedDepth;
681     uint32_t mBackBufferSize;
682     sp<ABuffer> mMediaImage;
683     std::function<sp<ABuffer>(size_t)> mAlloc;
684 
685     sp<ABuffer> mBackBuffer;    ///< backing buffer if we have to copy C2Buffer <=> ABuffer
686 
getMediaImage()687     MediaImage2 *getMediaImage() {
688         return (MediaImage2 *)mMediaImage->base();
689     }
690 };
691 
692 }  // namespace
693 
694 // GraphicBlockBuffer
695 
696 // static
Allocate(const sp<AMessage> & format,const std::shared_ptr<C2GraphicBlock> & block,std::function<sp<ABuffer> (size_t)> alloc)697 sp<GraphicBlockBuffer> GraphicBlockBuffer::Allocate(
698         const sp<AMessage> &format,
699         const std::shared_ptr<C2GraphicBlock> &block,
700         std::function<sp<ABuffer>(size_t)> alloc) {
701     ATRACE_BEGIN("GraphicBlockBuffer::Allocate block->map()");
702     C2GraphicView view(block->map().get());
703     ATRACE_END();
704     if (view.error() != C2_OK) {
705         ALOGD("C2GraphicBlock::map failed: %d", view.error());
706         return nullptr;
707     }
708 
709     GraphicView2MediaImageConverter converter(view, format, false /* copy */);
710     if (converter.initCheck() != OK) {
711         ALOGD("Converter init failed: %d", converter.initCheck());
712         return nullptr;
713     }
714     bool wrapped = true;
715     sp<ABuffer> buffer = converter.wrap();
716     if (buffer == nullptr) {
717         buffer = alloc(converter.backBufferSize());
718         if (!converter.setBackBuffer(buffer)) {
719             ALOGD("Converter failed to set back buffer");
720             return nullptr;
721         }
722         wrapped = false;
723     }
724     return new GraphicBlockBuffer(
725             format,
726             buffer,
727             std::move(view),
728             block,
729             converter.imageData(),
730             wrapped);
731 }
732 
GraphicBlockBuffer(const sp<AMessage> & format,const sp<ABuffer> & buffer,C2GraphicView && view,const std::shared_ptr<C2GraphicBlock> & block,const sp<ABuffer> & imageData,bool wrapped)733 GraphicBlockBuffer::GraphicBlockBuffer(
734         const sp<AMessage> &format,
735         const sp<ABuffer> &buffer,
736         C2GraphicView &&view,
737         const std::shared_ptr<C2GraphicBlock> &block,
738         const sp<ABuffer> &imageData,
739         bool wrapped)
740     : Codec2Buffer(format, buffer),
741       mView(view),
742       mBlock(block),
743       mWrapped(wrapped) {
744     setImageData(imageData);
745 }
746 
asC2Buffer()747 std::shared_ptr<C2Buffer> GraphicBlockBuffer::asC2Buffer() {
748     ATRACE_CALL();
749     uint32_t width = mView.width();
750     uint32_t height = mView.height();
751     if (!mWrapped) {
752         (void)ImageCopy(mView, base(), imageData());
753     }
754     return C2Buffer::CreateGraphicBuffer(
755             mBlock->share(C2Rect(width, height), C2Fence()));
756 }
757 
758 // GraphicMetadataBuffer
GraphicMetadataBuffer(const sp<AMessage> & format,const std::shared_ptr<C2Allocator> & alloc)759 GraphicMetadataBuffer::GraphicMetadataBuffer(
760         const sp<AMessage> &format,
761         const std::shared_ptr<C2Allocator> &alloc)
762     : Codec2Buffer(format, new ABuffer(sizeof(VideoNativeMetadata))),
763       mAlloc(alloc) {
764     ((VideoNativeMetadata *)base())->pBuffer = nullptr;
765 }
766 
asC2Buffer()767 std::shared_ptr<C2Buffer> GraphicMetadataBuffer::asC2Buffer() {
768 #ifdef __LP64__
769     static std::once_flag s_checkOnce;
770     static bool s_is64bitOk {true};
771     std::call_once(s_checkOnce, [&](){
772         const std::string abi32list =
773         ::android::base::GetProperty("ro.product.cpu.abilist32", "");
774         if (!abi32list.empty()) {
775             int32_t inputSurfaceSetting =
776             ::android::base::GetIntProperty("debug.stagefright.c2inputsurface", int32_t(0));
777             s_is64bitOk = inputSurfaceSetting != 0;
778         }
779     });
780 
781     if (!s_is64bitOk) {
782         ALOGE("GraphicMetadataBuffer does not work in 32+64 system if compiled as 64-bit object"\
783               "when debug.stagefright.c2inputsurface is set to 0");
784         return nullptr;
785     }
786 #endif
787 
788     VideoNativeMetadata *meta = (VideoNativeMetadata *)base();
789     ANativeWindowBuffer *buffer = (ANativeWindowBuffer *)meta->pBuffer;
790     if (buffer == nullptr) {
791         ALOGD("VideoNativeMetadata contains null buffer");
792         return nullptr;
793     }
794 
795     ALOGV("VideoNativeMetadata: %dx%d", buffer->width, buffer->height);
796     C2Handle *handle = WrapNativeCodec2GrallocHandle(
797             buffer->handle,
798             buffer->width,
799             buffer->height,
800             buffer->format,
801             buffer->usage,
802             buffer->stride);
803     std::shared_ptr<C2GraphicAllocation> alloc;
804     c2_status_t err = mAlloc->priorGraphicAllocation(handle, &alloc);
805     if (err != C2_OK) {
806         ALOGD("Failed to wrap VideoNativeMetadata into C2GraphicAllocation");
807         native_handle_close(handle);
808         native_handle_delete(handle);
809         return nullptr;
810     }
811     std::shared_ptr<C2GraphicBlock> block = _C2BlockFactory::CreateGraphicBlock(alloc);
812 
813     meta->pBuffer = 0;
814     // TODO: wrap this in C2Fence so that the component can wait when it
815     //       actually starts processing.
816     if (meta->nFenceFd >= 0) {
817         sp<Fence> fence(new Fence(meta->nFenceFd));
818         fence->waitForever(LOG_TAG);
819     }
820     return C2Buffer::CreateGraphicBuffer(
821             block->share(C2Rect(buffer->width, buffer->height), C2Fence()));
822 }
823 
824 // ConstGraphicBlockBuffer
825 
826 // static
Allocate(const sp<AMessage> & format,const std::shared_ptr<C2Buffer> & buffer,std::function<sp<ABuffer> (size_t)> alloc)827 sp<ConstGraphicBlockBuffer> ConstGraphicBlockBuffer::Allocate(
828         const sp<AMessage> &format,
829         const std::shared_ptr<C2Buffer> &buffer,
830         std::function<sp<ABuffer>(size_t)> alloc) {
831     if (!buffer
832             || buffer->data().type() != C2BufferData::GRAPHIC
833             || buffer->data().graphicBlocks().size() != 1u) {
834         ALOGD("C2Buffer precond fail");
835         return nullptr;
836     }
837     ATRACE_BEGIN("ConstGraphicBlockBuffer::Allocate block->map()");
838     std::unique_ptr<const C2GraphicView> view(std::make_unique<const C2GraphicView>(
839             buffer->data().graphicBlocks()[0].map().get()));
840     ATRACE_END();
841     std::unique_ptr<const C2GraphicView> holder;
842 
843     GraphicView2MediaImageConverter converter(*view, format, false /* copy */);
844     if (converter.initCheck() != OK) {
845         ALOGD("Converter init failed: %d", converter.initCheck());
846         return nullptr;
847     }
848     bool wrapped = true;
849     sp<ABuffer> aBuffer = converter.wrap();
850     if (aBuffer == nullptr) {
851         aBuffer = alloc(converter.backBufferSize());
852         if (!converter.setBackBuffer(aBuffer)) {
853             ALOGD("Converter failed to set back buffer");
854             return nullptr;
855         }
856         wrapped = false;
857         converter.copyToMediaImage();
858         // We don't need the view.
859         holder = std::move(view);
860     }
861     return new ConstGraphicBlockBuffer(
862             format,
863             aBuffer,
864             std::move(view),
865             buffer,
866             converter.imageData(),
867             wrapped);
868 }
869 
870 // static
AllocateEmpty(const sp<AMessage> & format,std::function<sp<ABuffer> (size_t)> alloc)871 sp<ConstGraphicBlockBuffer> ConstGraphicBlockBuffer::AllocateEmpty(
872         const sp<AMessage> &format,
873         std::function<sp<ABuffer>(size_t)> alloc) {
874     int32_t width, height;
875     if (!format->findInt32("width", &width)
876             || !format->findInt32("height", &height)) {
877         ALOGD("format had no width / height");
878         return nullptr;
879     }
880     int32_t colorFormat = COLOR_FormatYUV420Flexible;
881     int32_t bpp = 12;  // 8(Y) + 2(U) + 2(V)
882     if (format->findInt32(KEY_COLOR_FORMAT, &colorFormat)) {
883         if (colorFormat == COLOR_FormatYUVP010) {
884             bpp = 24;  // 16(Y) + 4(U) + 4(V)
885         }
886     }
887     sp<ABuffer> aBuffer(alloc(align(width, 16) * align(height, 16) * bpp / 8));
888     if (aBuffer == nullptr) {
889         ALOGD("%s: failed to allocate buffer", __func__);
890         return nullptr;
891     }
892     return new ConstGraphicBlockBuffer(
893             format,
894             aBuffer,
895             nullptr,
896             nullptr,
897             nullptr,
898             false);
899 }
900 
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)901 ConstGraphicBlockBuffer::ConstGraphicBlockBuffer(
902         const sp<AMessage> &format,
903         const sp<ABuffer> &aBuffer,
904         std::unique_ptr<const C2GraphicView> &&view,
905         const std::shared_ptr<C2Buffer> &buffer,
906         const sp<ABuffer> &imageData,
907         bool wrapped)
908     : Codec2Buffer(format, aBuffer),
909       mView(std::move(view)),
910       mBufferRef(buffer),
911       mWrapped(wrapped) {
912     setImageData(imageData);
913 }
914 
asC2Buffer()915 std::shared_ptr<C2Buffer> ConstGraphicBlockBuffer::asC2Buffer() {
916     return mBufferRef;
917 }
918 
clearC2BufferRefs()919 void ConstGraphicBlockBuffer::clearC2BufferRefs() {
920     mView.reset();
921     mBufferRef.reset();
922 }
923 
canCopy(const std::shared_ptr<C2Buffer> & buffer) const924 bool ConstGraphicBlockBuffer::canCopy(const std::shared_ptr<C2Buffer> &buffer) const {
925     if (mWrapped || mBufferRef) {
926         ALOGD("ConstGraphicBlockBuffer::canCopy: %swrapped ; buffer ref %s",
927                 mWrapped ? "" : "not ", mBufferRef ? "exists" : "doesn't exist");
928         return false;
929     }
930     if (!buffer) {
931         // Nothing to copy, so we can copy by doing nothing.
932         return true;
933     }
934     if (buffer->data().type() != C2BufferData::GRAPHIC) {
935         ALOGD("ConstGraphicBlockBuffer::canCopy: buffer precondition unsatisfied");
936         return false;
937     }
938     if (buffer->data().graphicBlocks().size() == 0) {
939         return true;
940     } else if (buffer->data().graphicBlocks().size() != 1u) {
941         ALOGD("ConstGraphicBlockBuffer::canCopy: too many blocks");
942         return false;
943     }
944 
945     ATRACE_BEGIN("ConstGraphicBlockBuffer::canCopy block->map()");
946     GraphicView2MediaImageConverter converter(
947             buffer->data().graphicBlocks()[0].map().get(),
948             // FIXME: format() is not const, but we cannot change it, so do a const cast here
949             const_cast<ConstGraphicBlockBuffer *>(this)->format(),
950             true /* copy */);
951     ATRACE_END();
952     if (converter.initCheck() != OK) {
953         ALOGD("ConstGraphicBlockBuffer::canCopy: converter init failed: %d", converter.initCheck());
954         return false;
955     }
956     if (converter.backBufferSize() > capacity()) {
957         ALOGD("ConstGraphicBlockBuffer::canCopy: insufficient capacity: req %u has %zu",
958                 converter.backBufferSize(), capacity());
959         return false;
960     }
961     return true;
962 }
963 
copy(const std::shared_ptr<C2Buffer> & buffer)964 bool ConstGraphicBlockBuffer::copy(const std::shared_ptr<C2Buffer> &buffer) {
965     if (!buffer || buffer->data().graphicBlocks().size() == 0) {
966         setRange(0, 0);
967         return true;
968     }
969 
970     GraphicView2MediaImageConverter converter(
971             buffer->data().graphicBlocks()[0].map().get(), format(), true /* copy */);
972     if (converter.initCheck() != OK) {
973         ALOGD("ConstGraphicBlockBuffer::copy: converter init failed: %d", converter.initCheck());
974         return false;
975     }
976     sp<ABuffer> aBuffer = new ABuffer(base(), capacity());
977     if (!converter.setBackBuffer(aBuffer)) {
978         ALOGD("ConstGraphicBlockBuffer::copy: set back buffer failed");
979         return false;
980     }
981     setRange(0, aBuffer->size());  // align size info
982     converter.copyToMediaImage();
983     setImageData(converter.imageData());
984     mBufferRef = buffer;
985     return true;
986 }
987 
988 // EncryptedLinearBlockBuffer
989 
EncryptedLinearBlockBuffer(const sp<AMessage> & format,const std::shared_ptr<C2LinearBlock> & block,const sp<IMemory> & memory,int32_t heapSeqNum)990 EncryptedLinearBlockBuffer::EncryptedLinearBlockBuffer(
991         const sp<AMessage> &format,
992         const std::shared_ptr<C2LinearBlock> &block,
993         const sp<IMemory> &memory,
994         int32_t heapSeqNum)
995     // TODO: Using unsecurePointer() has some associated security pitfalls
996     //       (see declaration for details).
997     //       Either document why it is safe in this case or address the
998     //       issue (e.g. by copying).
999     : Codec2Buffer(format, new ABuffer(memory->unsecurePointer(), memory->size())),
1000       mBlock(block),
1001       mMemory(memory),
1002       mHeapSeqNum(heapSeqNum) {
1003 }
1004 
asC2Buffer()1005 std::shared_ptr<C2Buffer> EncryptedLinearBlockBuffer::asC2Buffer() {
1006     return C2Buffer::CreateLinearBuffer(mBlock->share(offset(), size(), C2Fence()));
1007 }
1008 
fillSourceBuffer(hardware::drm::V1_0::SharedBuffer * source)1009 void EncryptedLinearBlockBuffer::fillSourceBuffer(
1010         hardware::drm::V1_0::SharedBuffer *source) {
1011     BufferChannelBase::IMemoryToSharedBuffer(mMemory, mHeapSeqNum, source);
1012 }
1013 
fillSourceBuffer(hardware::cas::native::V1_0::SharedBuffer * source)1014 void EncryptedLinearBlockBuffer::fillSourceBuffer(
1015         hardware::cas::native::V1_0::SharedBuffer *source) {
1016     ssize_t offset;
1017     size_t size;
1018 
1019     mHidlMemory = hardware::fromHeap(mMemory->getMemory(&offset, &size));
1020     source->heapBase = *mHidlMemory;
1021     source->offset = offset;
1022     source->size = size;
1023 }
1024 
copyDecryptedContent(const sp<IMemory> & decrypted,size_t length)1025 bool EncryptedLinearBlockBuffer::copyDecryptedContent(
1026         const sp<IMemory> &decrypted, size_t length) {
1027     C2WriteView view = mBlock->map().get();
1028     if (view.error() != C2_OK) {
1029         return false;
1030     }
1031     if (view.size() < length) {
1032         return false;
1033     }
1034     memcpy(view.data(), decrypted->unsecurePointer(), length);
1035     return true;
1036 }
1037 
copyDecryptedContentFromMemory(size_t length)1038 bool EncryptedLinearBlockBuffer::copyDecryptedContentFromMemory(size_t length) {
1039     return copyDecryptedContent(mMemory, length);
1040 }
1041 
handle() const1042 native_handle_t *EncryptedLinearBlockBuffer::handle() const {
1043     return const_cast<native_handle_t *>(mBlock->handle());
1044 }
1045 
getMappedBlock(std::unique_ptr<MappedBlock> * const mappedBlock) const1046 void EncryptedLinearBlockBuffer::getMappedBlock(
1047         std::unique_ptr<MappedBlock> * const mappedBlock) const {
1048     if (mappedBlock) {
1049         mappedBlock->reset(new EncryptedLinearBlockBuffer::MappedBlock(mBlock));
1050     }
1051     return;
1052 }
1053 
MappedBlock(const std::shared_ptr<C2LinearBlock> & block)1054 EncryptedLinearBlockBuffer::MappedBlock::MappedBlock(
1055         const std::shared_ptr<C2LinearBlock> &block) : mView(block->map().get()) {
1056 }
1057 
copyDecryptedContent(const sp<IMemory> & decrypted,size_t length)1058 bool EncryptedLinearBlockBuffer::MappedBlock::copyDecryptedContent(
1059         const sp<IMemory> &decrypted, size_t length) {
1060     if (mView.error() != C2_OK) {
1061         return false;
1062     }
1063     if (mView.size() < length) {
1064         ALOGE("View size(%d) less than decrypted length(%zu)",
1065                 mView.size(), length);
1066         return false;
1067     }
1068     memcpy(mView.data(), decrypted->unsecurePointer(), length);
1069     mView.setOffset(mView.offset() + length);
1070     return true;
1071 }
1072 
~MappedBlock()1073 EncryptedLinearBlockBuffer::MappedBlock::~MappedBlock() {
1074     mView.setOffset(0);
1075 }
1076 
1077 using ::aidl::android::hardware::graphics::common::Cta861_3;
1078 using ::aidl::android::hardware::graphics::common::Smpte2086;
1079 
1080 namespace {
1081 
1082 class GrallocBuffer {
1083 public:
GrallocBuffer(const C2Handle * const handle)1084     GrallocBuffer(const C2Handle *const handle) : mBuffer(nullptr) {
1085         GraphicBufferMapper& mapper = GraphicBufferMapper::get();
1086 
1087         // Unwrap raw buffer handle from the C2Handle
1088         native_handle_t *nh = UnwrapNativeCodec2GrallocHandle(handle);
1089         if (!nh) {
1090             ALOGE("handle is not compatible to any gralloc C2Handle types");
1091             return;
1092         }
1093         // Import the raw handle so IMapper can use the buffer. The imported
1094         // handle must be freed when the client is done with the buffer.
1095         status_t status = mapper.importBufferNoValidate(
1096                 nh,
1097                 &mBuffer);
1098 
1099         if (status != OK) {
1100             ALOGE("Failed to import buffer. Status: %d.", status);
1101             return;
1102         }
1103 
1104         // TRICKY: UnwrapNativeCodec2GrallocHandle creates a new handle but
1105         //         does not clone the fds. Thus we need to delete the handle
1106         //         without closing it.
1107         native_handle_delete(nh);
1108     }
1109 
~GrallocBuffer()1110     ~GrallocBuffer() {
1111         GraphicBufferMapper& mapper = GraphicBufferMapper::get();
1112         if (mBuffer) {
1113             // Free the imported buffer handle. This does not release the
1114             // underlying buffer itself.
1115             mapper.freeBuffer(mBuffer);
1116         }
1117     }
1118 
get() const1119     buffer_handle_t get() const { return mBuffer; }
operator bool() const1120     operator bool() const { return (mBuffer != nullptr); }
1121 private:
1122     buffer_handle_t mBuffer;
1123 };
1124 
1125 }  // namspace
1126 
GetHdrMetadataFromGralloc4Handle(const C2Handle * const handle,std::shared_ptr<C2StreamHdrStaticMetadataInfo::input> * staticInfo,std::shared_ptr<C2StreamHdrDynamicMetadataInfo::input> * dynamicInfo)1127 c2_status_t GetHdrMetadataFromGralloc4Handle(
1128         const C2Handle *const handle,
1129         std::shared_ptr<C2StreamHdrStaticMetadataInfo::input> *staticInfo,
1130         std::shared_ptr<C2StreamHdrDynamicMetadataInfo::input> *dynamicInfo) {
1131     c2_status_t err = C2_OK;
1132     GraphicBufferMapper& mapper = GraphicBufferMapper::get();
1133     GrallocBuffer buffer(handle);
1134     if (!buffer) {
1135         // Gralloc4 not supported; nothing to do
1136         return err;
1137     }
1138     if (staticInfo) {
1139         ALOGV("Grabbing static HDR info from gralloc metadata");
1140         staticInfo->reset(new C2StreamHdrStaticMetadataInfo::input(0u));
1141         memset(&(*staticInfo)->mastering, 0, sizeof((*staticInfo)->mastering));
1142         (*staticInfo)->maxCll = 0;
1143         (*staticInfo)->maxFall = 0;
1144 
1145         std::optional<Smpte2086> smpte2086;
1146         status_t status = mapper.getSmpte2086(buffer.get(), &smpte2086);
1147         if (status != OK || !smpte2086) {
1148             err = C2_CORRUPTED;
1149         } else {
1150             if (smpte2086) {
1151                   (*staticInfo)->mastering.red.x    = smpte2086->primaryRed.x;
1152                   (*staticInfo)->mastering.red.y    = smpte2086->primaryRed.y;
1153                   (*staticInfo)->mastering.green.x  = smpte2086->primaryGreen.x;
1154                   (*staticInfo)->mastering.green.y  = smpte2086->primaryGreen.y;
1155                   (*staticInfo)->mastering.blue.x   = smpte2086->primaryBlue.x;
1156                   (*staticInfo)->mastering.blue.y   = smpte2086->primaryBlue.y;
1157                   (*staticInfo)->mastering.white.x  = smpte2086->whitePoint.x;
1158                   (*staticInfo)->mastering.white.y  = smpte2086->whitePoint.y;
1159 
1160                   (*staticInfo)->mastering.maxLuminance = smpte2086->maxLuminance;
1161                   (*staticInfo)->mastering.minLuminance = smpte2086->minLuminance;
1162             }
1163         }
1164 
1165         std::optional<Cta861_3> cta861_3;
1166         status = mapper.getCta861_3(buffer.get(), &cta861_3);
1167         if (status != OK || !cta861_3) {
1168             err = C2_CORRUPTED;
1169         } else {
1170             if (cta861_3) {
1171                   (*staticInfo)->maxCll   = cta861_3->maxContentLightLevel;
1172                   (*staticInfo)->maxFall  = cta861_3->maxFrameAverageLightLevel;
1173             }
1174         }
1175     }
1176 
1177     if (err != C2_OK) {
1178         staticInfo->reset();
1179     }
1180 
1181     if (dynamicInfo) {
1182         ALOGV("Grabbing dynamic HDR info from gralloc metadata");
1183         dynamicInfo->reset();
1184         std::optional<std::vector<uint8_t>> vec;
1185         status_t status = mapper.getSmpte2094_40(buffer.get(), &vec);
1186         if (status != OK || !vec) {
1187             dynamicInfo->reset();
1188             err = C2_CORRUPTED;
1189         } else {
1190             if (vec) {
1191                 *dynamicInfo = C2StreamHdrDynamicMetadataInfo::input::AllocShared(
1192                       vec->size(), 0u, C2Config::HDR_DYNAMIC_METADATA_TYPE_SMPTE_2094_40);
1193                 memcpy((*dynamicInfo)->m.data, vec->data(), vec->size());
1194             }
1195         }
1196     }
1197 
1198     return err;
1199 }
1200 
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)1201 c2_status_t SetMetadataToGralloc4Handle(
1202         android_dataspace_t dataSpace,
1203         const std::shared_ptr<const C2StreamHdrStaticMetadataInfo::output> &staticInfo,
1204         const std::shared_ptr<const C2StreamHdrDynamicMetadataInfo::output> &dynamicInfo,
1205         const C2Handle *const handle) {
1206     c2_status_t err = C2_OK;
1207     GraphicBufferMapper& mapper = GraphicBufferMapper::get();
1208     GrallocBuffer buffer(handle);
1209     if (!buffer) {
1210         // Gralloc4 not supported; nothing to do
1211         return err;
1212     }
1213     status_t status = mapper.setDataspace(buffer.get(), static_cast<ui::Dataspace>(dataSpace));
1214     if (status != OK) {
1215        err = C2_CORRUPTED;
1216     }
1217     if (staticInfo && *staticInfo) {
1218         ALOGV("Setting static HDR info as gralloc metadata");
1219         std::optional<Smpte2086> smpte2086 = Smpte2086{
1220             {staticInfo->mastering.red.x, staticInfo->mastering.red.y},
1221             {staticInfo->mastering.green.x, staticInfo->mastering.green.y},
1222             {staticInfo->mastering.blue.x, staticInfo->mastering.blue.y},
1223             {staticInfo->mastering.white.x, staticInfo->mastering.white.y},
1224             staticInfo->mastering.maxLuminance,
1225             staticInfo->mastering.minLuminance,
1226         };
1227         if (0.0 <= smpte2086->primaryRed.x && smpte2086->primaryRed.x <= 1.0
1228                 && 0.0 <= smpte2086->primaryRed.y && smpte2086->primaryRed.y <= 1.0
1229                 && 0.0 <= smpte2086->primaryGreen.x && smpte2086->primaryGreen.x <= 1.0
1230                 && 0.0 <= smpte2086->primaryGreen.y && smpte2086->primaryGreen.y <= 1.0
1231                 && 0.0 <= smpte2086->primaryBlue.x && smpte2086->primaryBlue.x <= 1.0
1232                 && 0.0 <= smpte2086->primaryBlue.y && smpte2086->primaryBlue.y <= 1.0
1233                 && 0.0 <= smpte2086->whitePoint.x && smpte2086->whitePoint.x <= 1.0
1234                 && 0.0 <= smpte2086->whitePoint.y && smpte2086->whitePoint.y <= 1.0
1235                 && 0.0 <= smpte2086->maxLuminance && 0.0 <= smpte2086->minLuminance) {
1236             status = mapper.setSmpte2086(buffer.get(), smpte2086);
1237             if (status != OK) {
1238                 err = C2_CORRUPTED;
1239             }
1240         }
1241         std::optional<Cta861_3> cta861_3 = Cta861_3{
1242             staticInfo->maxCll,
1243             staticInfo->maxFall,
1244         };
1245         if (0.0 <= cta861_3->maxContentLightLevel && 0.0 <= cta861_3->maxFrameAverageLightLevel) {
1246             status = mapper.setCta861_3(buffer.get(), cta861_3);
1247             if (status != OK) {
1248                 err = C2_CORRUPTED;
1249             }
1250         }
1251     }
1252     if (dynamicInfo && *dynamicInfo && dynamicInfo->flexCount() > 0) {
1253         ALOGV("Setting dynamic HDR info as gralloc metadata");
1254         if (dynamicInfo->m.type_ == C2Config::HDR_DYNAMIC_METADATA_TYPE_SMPTE_2094_40) {
1255             std::optional<std::vector<uint8_t>> smpte2094_40 = std::vector<uint8_t>();
1256             smpte2094_40->resize(dynamicInfo->flexCount());
1257             memcpy(smpte2094_40->data(), dynamicInfo->m.data, dynamicInfo->flexCount());
1258 
1259             status = mapper.setSmpte2094_40(buffer.get(), smpte2094_40);
1260             if (status != OK) {
1261                 err = C2_CORRUPTED;
1262             }
1263         } else {
1264             err = C2_BAD_VALUE;
1265         }
1266     }
1267 
1268     return err;
1269 }
1270 
1271 }  // namespace android
1272