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