blob: 7f9de219cab248f8a660caba97735791b804f027 [file] [log] [blame]
Pawin Vongmasa36653902018-11-15 00:10:25 -08001/*
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#include <utils/Log.h>
20
Wonsik Kima79c5522022-01-18 16:29:24 -080021#include <aidl/android/hardware/graphics/common/Cta861_3.h>
22#include <aidl/android/hardware/graphics/common/Smpte2086.h>
bohua222c0b2021-01-12 18:54:53 -080023#include <android-base/properties.h>
Wonsik Kim41d83432020-04-27 16:40:49 -070024#include <android/hardware/cas/native/1.0/types.h>
25#include <android/hardware/drm/1.0/types.h>
Wonsik Kima79c5522022-01-18 16:29:24 -080026#include <android/hardware/graphics/common/1.2/types.h>
27#include <android/hardware/graphics/mapper/4.0/IMapper.h>
28#include <gralloctypes/Gralloc4.h>
Pawin Vongmasa36653902018-11-15 00:10:25 -080029#include <hidlmemory/FrameworkUtils.h>
30#include <media/hardware/HardwareAPI.h>
Robert Shih895fba92019-07-16 16:29:44 -070031#include <media/stagefright/CodecBase.h>
Pawin Vongmasa36653902018-11-15 00:10:25 -080032#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>
Wonsik Kim41d83432020-04-27 16:40:49 -070036#include <mediadrm/ICrypto.h>
Pawin Vongmasa36653902018-11-15 00:10:25 -080037#include <nativebase/nativebase.h>
Wonsik Kimebe0f9e2019-07-03 11:06:51 -070038#include <ui/Fence.h>
Pawin Vongmasa36653902018-11-15 00:10:25 -080039
40#include <C2AllocatorGralloc.h>
41#include <C2BlockInternal.h>
42#include <C2Debug.h>
43
44#include "Codec2Buffer.h"
45
46namespace android {
47
48// Codec2Buffer
49
50bool Codec2Buffer::canCopyLinear(const std::shared_ptr<C2Buffer> &buffer) const {
51 if (const_cast<Codec2Buffer *>(this)->base() == nullptr) {
52 return false;
53 }
54 if (!buffer) {
55 // Nothing to copy, so we can copy by doing nothing.
56 return true;
57 }
58 if (buffer->data().type() != C2BufferData::LINEAR) {
59 return false;
60 }
61 if (buffer->data().linearBlocks().size() == 0u) {
62 // Nothing to copy, so we can copy by doing nothing.
63 return true;
64 } else if (buffer->data().linearBlocks().size() > 1u) {
65 // We don't know how to copy more than one blocks.
66 return false;
67 }
68 if (buffer->data().linearBlocks()[0].size() > capacity()) {
69 // It won't fit.
70 return false;
71 }
72 return true;
73}
74
75bool Codec2Buffer::copyLinear(const std::shared_ptr<C2Buffer> &buffer) {
76 // We assume that all canCopyLinear() checks passed.
77 if (!buffer || buffer->data().linearBlocks().size() == 0u
78 || buffer->data().linearBlocks()[0].size() == 0u) {
79 setRange(0, 0);
80 return true;
81 }
82 C2ReadView view = buffer->data().linearBlocks()[0].map().get();
83 if (view.error() != C2_OK) {
84 ALOGD("Error while mapping: %d", view.error());
85 return false;
86 }
87 if (view.capacity() > capacity()) {
88 ALOGD("C2ConstLinearBlock lied --- it actually doesn't fit: view(%u) > this(%zu)",
89 view.capacity(), capacity());
90 return false;
91 }
92 memcpy(base(), view.data(), view.capacity());
93 setRange(0, view.capacity());
94 return true;
95}
96
97void Codec2Buffer::setImageData(const sp<ABuffer> &imageData) {
Wonsik Kimc48ddcf2019-02-11 16:16:57 -080098 mImageData = imageData;
Pawin Vongmasa36653902018-11-15 00:10:25 -080099}
100
101// LocalLinearBuffer
102
103bool LocalLinearBuffer::canCopy(const std::shared_ptr<C2Buffer> &buffer) const {
104 return canCopyLinear(buffer);
105}
106
107bool LocalLinearBuffer::copy(const std::shared_ptr<C2Buffer> &buffer) {
108 return copyLinear(buffer);
109}
110
111// DummyContainerBuffer
112
Pawin Vongmasa8be93112018-12-11 14:01:42 -0800113static uint8_t sDummyByte[1] = { 0 };
114
Pawin Vongmasa36653902018-11-15 00:10:25 -0800115DummyContainerBuffer::DummyContainerBuffer(
116 const sp<AMessage> &format, const std::shared_ptr<C2Buffer> &buffer)
Pawin Vongmasa8be93112018-12-11 14:01:42 -0800117 : Codec2Buffer(format, new ABuffer(sDummyByte, 1)),
Pawin Vongmasa36653902018-11-15 00:10:25 -0800118 mBufferRef(buffer) {
119 setRange(0, buffer ? 1 : 0);
120}
121
122std::shared_ptr<C2Buffer> DummyContainerBuffer::asC2Buffer() {
Wonsik Kimf9b32122020-04-02 11:30:17 -0700123 return mBufferRef;
124}
125
126void DummyContainerBuffer::clearC2BufferRefs() {
127 mBufferRef.reset();
Pawin Vongmasa36653902018-11-15 00:10:25 -0800128}
129
130bool DummyContainerBuffer::canCopy(const std::shared_ptr<C2Buffer> &) const {
131 return !mBufferRef;
132}
133
134bool DummyContainerBuffer::copy(const std::shared_ptr<C2Buffer> &buffer) {
135 mBufferRef = buffer;
136 setRange(0, mBufferRef ? 1 : 0);
137 return true;
138}
139
140// LinearBlockBuffer
141
142// static
143sp<LinearBlockBuffer> LinearBlockBuffer::Allocate(
144 const sp<AMessage> &format, const std::shared_ptr<C2LinearBlock> &block) {
145 C2WriteView writeView(block->map().get());
146 if (writeView.error() != C2_OK) {
147 return nullptr;
148 }
149 return new LinearBlockBuffer(format, std::move(writeView), block);
150}
151
152std::shared_ptr<C2Buffer> LinearBlockBuffer::asC2Buffer() {
153 return C2Buffer::CreateLinearBuffer(mBlock->share(offset(), size(), C2Fence()));
154}
155
156bool LinearBlockBuffer::canCopy(const std::shared_ptr<C2Buffer> &buffer) const {
157 return canCopyLinear(buffer);
158}
159
160bool LinearBlockBuffer::copy(const std::shared_ptr<C2Buffer> &buffer) {
161 return copyLinear(buffer);
162}
163
164LinearBlockBuffer::LinearBlockBuffer(
165 const sp<AMessage> &format,
166 C2WriteView&& writeView,
167 const std::shared_ptr<C2LinearBlock> &block)
168 : Codec2Buffer(format, new ABuffer(writeView.data(), writeView.size())),
169 mWriteView(writeView),
170 mBlock(block) {
171}
172
173// ConstLinearBlockBuffer
174
175// static
176sp<ConstLinearBlockBuffer> ConstLinearBlockBuffer::Allocate(
177 const sp<AMessage> &format, const std::shared_ptr<C2Buffer> &buffer) {
178 if (!buffer
179 || buffer->data().type() != C2BufferData::LINEAR
180 || buffer->data().linearBlocks().size() != 1u) {
181 return nullptr;
182 }
183 C2ReadView readView(buffer->data().linearBlocks()[0].map().get());
184 if (readView.error() != C2_OK) {
185 return nullptr;
186 }
187 return new ConstLinearBlockBuffer(format, std::move(readView), buffer);
188}
189
190ConstLinearBlockBuffer::ConstLinearBlockBuffer(
191 const sp<AMessage> &format,
192 C2ReadView&& readView,
193 const std::shared_ptr<C2Buffer> &buffer)
194 : Codec2Buffer(format, new ABuffer(
195 // NOTE: ABuffer only takes non-const pointer but this data is
196 // supposed to be read-only.
197 const_cast<uint8_t *>(readView.data()), readView.capacity())),
198 mReadView(readView),
199 mBufferRef(buffer) {
200}
201
202std::shared_ptr<C2Buffer> ConstLinearBlockBuffer::asC2Buffer() {
Wonsik Kimf9b32122020-04-02 11:30:17 -0700203 return mBufferRef;
204}
205
206void ConstLinearBlockBuffer::clearC2BufferRefs() {
207 mBufferRef.reset();
Pawin Vongmasa36653902018-11-15 00:10:25 -0800208}
209
210// GraphicView2MediaImageConverter
211
212namespace {
213
214class GraphicView2MediaImageConverter {
215public:
216 /**
217 * Creates a C2GraphicView <=> MediaImage converter
218 *
219 * \param view C2GraphicView object
Wonsik Kimd79ee1f2020-08-27 17:41:56 -0700220 * \param format buffer format
Wonsik Kim7d966312019-06-04 14:00:49 -0700221 * \param copy whether the converter is used for copy or not
Pawin Vongmasa36653902018-11-15 00:10:25 -0800222 */
223 GraphicView2MediaImageConverter(
Wonsik Kimd79ee1f2020-08-27 17:41:56 -0700224 const C2GraphicView &view, const sp<AMessage> &format, bool copy)
Pawin Vongmasa36653902018-11-15 00:10:25 -0800225 : mInitCheck(NO_INIT),
226 mView(view),
227 mWidth(view.width()),
228 mHeight(view.height()),
Pawin Vongmasa36653902018-11-15 00:10:25 -0800229 mAllocatedDepth(0),
230 mBackBufferSize(0),
231 mMediaImage(new ABuffer(sizeof(MediaImage2))) {
Wonsik Kimd79ee1f2020-08-27 17:41:56 -0700232 if (!format->findInt32(KEY_COLOR_FORMAT, &mClientColorFormat)) {
233 mClientColorFormat = COLOR_FormatYUV420Flexible;
234 }
235 if (!format->findInt32("android._color-format", &mComponentColorFormat)) {
236 mComponentColorFormat = COLOR_FormatYUV420Flexible;
237 }
Pawin Vongmasa36653902018-11-15 00:10:25 -0800238 if (view.error() != C2_OK) {
239 ALOGD("Converter: view.error() = %d", view.error());
240 mInitCheck = BAD_VALUE;
241 return;
242 }
243 MediaImage2 *mediaImage = (MediaImage2 *)mMediaImage->base();
244 const C2PlanarLayout &layout = view.layout();
245 if (layout.numPlanes == 0) {
246 ALOGD("Converter: 0 planes");
247 mInitCheck = BAD_VALUE;
248 return;
249 }
Harish Mahendrakarcac53852019-02-20 10:59:10 -0800250 memset(mediaImage, 0, sizeof(*mediaImage));
Pawin Vongmasa36653902018-11-15 00:10:25 -0800251 mAllocatedDepth = layout.planes[0].allocatedDepth;
252 uint32_t bitDepth = layout.planes[0].bitDepth;
253
254 // align width and height to support subsampling cleanly
Wonsik Kim8bfa17a2019-05-30 22:12:30 -0700255 uint32_t stride = align(view.crop().width, 2) * divUp(layout.planes[0].allocatedDepth, 8u);
256 uint32_t vStride = align(view.crop().height, 2);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800257
Wonsik Kimd79ee1f2020-08-27 17:41:56 -0700258 bool tryWrapping = !copy;
259
Pawin Vongmasa36653902018-11-15 00:10:25 -0800260 switch (layout.type) {
Wonsik Kimd79ee1f2020-08-27 17:41:56 -0700261 case C2PlanarLayout::TYPE_YUV: {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800262 mediaImage->mType = MediaImage2::MEDIA_IMAGE_TYPE_YUV;
263 if (layout.numPlanes != 3) {
264 ALOGD("Converter: %d planes for YUV layout", layout.numPlanes);
265 mInitCheck = BAD_VALUE;
266 return;
267 }
Wonsik Kimd79ee1f2020-08-27 17:41:56 -0700268 C2PlaneInfo yPlane = layout.planes[C2PlanarLayout::PLANE_Y];
269 C2PlaneInfo uPlane = layout.planes[C2PlanarLayout::PLANE_U];
270 C2PlaneInfo vPlane = layout.planes[C2PlanarLayout::PLANE_V];
271 if (yPlane.channel != C2PlaneInfo::CHANNEL_Y
272 || uPlane.channel != C2PlaneInfo::CHANNEL_CB
273 || vPlane.channel != C2PlaneInfo::CHANNEL_CR) {
274 ALOGD("Converter: not YUV layout");
Pawin Vongmasa36653902018-11-15 00:10:25 -0800275 mInitCheck = BAD_VALUE;
276 return;
277 }
Wonsik Kimd79ee1f2020-08-27 17:41:56 -0700278 bool yuv420888 = yPlane.rowSampling == 1 && yPlane.colSampling == 1
279 && uPlane.rowSampling == 2 && uPlane.colSampling == 2
280 && vPlane.rowSampling == 2 && vPlane.colSampling == 2;
281 if (yuv420888) {
282 for (uint32_t i = 0; i < 3; ++i) {
283 const C2PlaneInfo &plane = layout.planes[i];
284 if (plane.allocatedDepth != 8 || plane.bitDepth != 8) {
285 yuv420888 = false;
286 break;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800287 }
Wonsik Kimd79ee1f2020-08-27 17:41:56 -0700288 }
289 yuv420888 = yuv420888 && yPlane.colInc == 1 && uPlane.rowInc == vPlane.rowInc;
290 }
291 int32_t copyFormat = mClientColorFormat;
292 if (yuv420888 && mClientColorFormat == COLOR_FormatYUV420Flexible) {
293 if (uPlane.colInc == 2 && vPlane.colInc == 2
294 && yPlane.rowInc == uPlane.rowInc) {
295 copyFormat = COLOR_FormatYUV420PackedSemiPlanar;
296 } else if (uPlane.colInc == 1 && vPlane.colInc == 1
297 && yPlane.rowInc == uPlane.rowInc * 2) {
298 copyFormat = COLOR_FormatYUV420PackedPlanar;
299 }
300 }
301 ALOGV("client_fmt=0x%x y:{colInc=%d rowInc=%d} u:{colInc=%d rowInc=%d} "
302 "v:{colInc=%d rowInc=%d}",
303 mClientColorFormat,
304 yPlane.colInc, yPlane.rowInc,
305 uPlane.colInc, uPlane.rowInc,
306 vPlane.colInc, vPlane.rowInc);
307 switch (copyFormat) {
308 case COLOR_FormatYUV420Flexible:
Pawin Vongmasa36653902018-11-15 00:10:25 -0800309 case COLOR_FormatYUV420Planar:
310 case COLOR_FormatYUV420PackedPlanar:
311 mediaImage->mPlane[mediaImage->Y].mOffset = 0;
312 mediaImage->mPlane[mediaImage->Y].mColInc = 1;
Wonsik Kim8bfa17a2019-05-30 22:12:30 -0700313 mediaImage->mPlane[mediaImage->Y].mRowInc = stride;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800314 mediaImage->mPlane[mediaImage->Y].mHorizSubsampling = 1;
315 mediaImage->mPlane[mediaImage->Y].mVertSubsampling = 1;
316
Wonsik Kim8bfa17a2019-05-30 22:12:30 -0700317 mediaImage->mPlane[mediaImage->U].mOffset = stride * vStride;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800318 mediaImage->mPlane[mediaImage->U].mColInc = 1;
Wonsik Kim8bfa17a2019-05-30 22:12:30 -0700319 mediaImage->mPlane[mediaImage->U].mRowInc = stride / 2;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800320 mediaImage->mPlane[mediaImage->U].mHorizSubsampling = 2;
321 mediaImage->mPlane[mediaImage->U].mVertSubsampling = 2;
322
Wonsik Kim8bfa17a2019-05-30 22:12:30 -0700323 mediaImage->mPlane[mediaImage->V].mOffset = stride * vStride * 5 / 4;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800324 mediaImage->mPlane[mediaImage->V].mColInc = 1;
Wonsik Kim8bfa17a2019-05-30 22:12:30 -0700325 mediaImage->mPlane[mediaImage->V].mRowInc = stride / 2;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800326 mediaImage->mPlane[mediaImage->V].mHorizSubsampling = 2;
327 mediaImage->mPlane[mediaImage->V].mVertSubsampling = 2;
Wonsik Kimd79ee1f2020-08-27 17:41:56 -0700328
329 if (tryWrapping && mClientColorFormat != COLOR_FormatYUV420Flexible) {
330 tryWrapping = yuv420888 && uPlane.colInc == 1 && vPlane.colInc == 1
331 && yPlane.rowInc == uPlane.rowInc * 2
332 && view.data()[0] < view.data()[1]
333 && view.data()[1] < view.data()[2];
334 }
Pawin Vongmasa36653902018-11-15 00:10:25 -0800335 break;
336
337 case COLOR_FormatYUV420SemiPlanar:
338 case COLOR_FormatYUV420PackedSemiPlanar:
339 mediaImage->mPlane[mediaImage->Y].mOffset = 0;
340 mediaImage->mPlane[mediaImage->Y].mColInc = 1;
Wonsik Kim8bfa17a2019-05-30 22:12:30 -0700341 mediaImage->mPlane[mediaImage->Y].mRowInc = stride;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800342 mediaImage->mPlane[mediaImage->Y].mHorizSubsampling = 1;
343 mediaImage->mPlane[mediaImage->Y].mVertSubsampling = 1;
344
Wonsik Kim8bfa17a2019-05-30 22:12:30 -0700345 mediaImage->mPlane[mediaImage->U].mOffset = stride * vStride;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800346 mediaImage->mPlane[mediaImage->U].mColInc = 2;
Wonsik Kim8bfa17a2019-05-30 22:12:30 -0700347 mediaImage->mPlane[mediaImage->U].mRowInc = stride;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800348 mediaImage->mPlane[mediaImage->U].mHorizSubsampling = 2;
349 mediaImage->mPlane[mediaImage->U].mVertSubsampling = 2;
350
Wonsik Kim8bfa17a2019-05-30 22:12:30 -0700351 mediaImage->mPlane[mediaImage->V].mOffset = stride * vStride + 1;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800352 mediaImage->mPlane[mediaImage->V].mColInc = 2;
Wonsik Kim8bfa17a2019-05-30 22:12:30 -0700353 mediaImage->mPlane[mediaImage->V].mRowInc = stride;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800354 mediaImage->mPlane[mediaImage->V].mHorizSubsampling = 2;
355 mediaImage->mPlane[mediaImage->V].mVertSubsampling = 2;
Wonsik Kimd79ee1f2020-08-27 17:41:56 -0700356
357 if (tryWrapping && mClientColorFormat != COLOR_FormatYUV420Flexible) {
358 tryWrapping = yuv420888 && uPlane.colInc == 2 && vPlane.colInc == 2
359 && yPlane.rowInc == uPlane.rowInc
360 && view.data()[0] < view.data()[1]
361 && view.data()[1] < view.data()[2];
362 }
Pawin Vongmasa36653902018-11-15 00:10:25 -0800363 break;
364
Wonsik Kim29e3c4d2020-09-02 12:19:44 -0700365 case COLOR_FormatYUVP010:
Wonsik Kim29e3c4d2020-09-02 12:19:44 -0700366 mediaImage->mPlane[mediaImage->Y].mOffset = 0;
367 mediaImage->mPlane[mediaImage->Y].mColInc = 2;
368 mediaImage->mPlane[mediaImage->Y].mRowInc = stride * 2;
369 mediaImage->mPlane[mediaImage->Y].mHorizSubsampling = 1;
370 mediaImage->mPlane[mediaImage->Y].mVertSubsampling = 1;
371
372 mediaImage->mPlane[mediaImage->U].mOffset = stride * vStride * 2;
373 mediaImage->mPlane[mediaImage->U].mColInc = 4;
374 mediaImage->mPlane[mediaImage->U].mRowInc = stride * 2;
375 mediaImage->mPlane[mediaImage->U].mHorizSubsampling = 2;
376 mediaImage->mPlane[mediaImage->U].mVertSubsampling = 2;
377
378 mediaImage->mPlane[mediaImage->V].mOffset = stride * vStride * 2 + 2;
379 mediaImage->mPlane[mediaImage->V].mColInc = 4;
380 mediaImage->mPlane[mediaImage->V].mRowInc = stride * 2;
381 mediaImage->mPlane[mediaImage->V].mHorizSubsampling = 2;
382 mediaImage->mPlane[mediaImage->V].mVertSubsampling = 2;
Wonsik Kimd79ee1f2020-08-27 17:41:56 -0700383 if (tryWrapping) {
384 tryWrapping = yPlane.allocatedDepth == 16
385 && uPlane.allocatedDepth == 16
386 && vPlane.allocatedDepth == 16
387 && yPlane.bitDepth == 10
388 && uPlane.bitDepth == 10
389 && vPlane.bitDepth == 10
390 && yPlane.rightShift == 6
391 && uPlane.rightShift == 6
392 && vPlane.rightShift == 6
393 && yPlane.rowSampling == 1 && yPlane.colSampling == 1
394 && uPlane.rowSampling == 2 && uPlane.colSampling == 2
395 && vPlane.rowSampling == 2 && vPlane.colSampling == 2
396 && yPlane.colInc == 2
397 && uPlane.colInc == 4
398 && vPlane.colInc == 4
399 && yPlane.rowInc == uPlane.rowInc
400 && yPlane.rowInc == vPlane.rowInc;
401 }
Wonsik Kim29e3c4d2020-09-02 12:19:44 -0700402 break;
403
Wonsik Kimd79ee1f2020-08-27 17:41:56 -0700404 default: {
405 // default to fully planar format --- this will be overridden if wrapping
406 // TODO: keep interleaved format
407 int32_t colInc = divUp(mAllocatedDepth, 8u);
408 int32_t rowInc = stride * colInc / yPlane.colSampling;
409 mediaImage->mPlane[mediaImage->Y].mOffset = 0;
410 mediaImage->mPlane[mediaImage->Y].mColInc = colInc;
411 mediaImage->mPlane[mediaImage->Y].mRowInc = rowInc;
412 mediaImage->mPlane[mediaImage->Y].mHorizSubsampling = yPlane.colSampling;
413 mediaImage->mPlane[mediaImage->Y].mVertSubsampling = yPlane.rowSampling;
414 int32_t offset = rowInc * vStride / yPlane.rowSampling;
415
416 rowInc = stride * colInc / uPlane.colSampling;
417 mediaImage->mPlane[mediaImage->U].mOffset = offset;
418 mediaImage->mPlane[mediaImage->U].mColInc = colInc;
419 mediaImage->mPlane[mediaImage->U].mRowInc = rowInc;
420 mediaImage->mPlane[mediaImage->U].mHorizSubsampling = uPlane.colSampling;
421 mediaImage->mPlane[mediaImage->U].mVertSubsampling = uPlane.rowSampling;
422 offset += rowInc * vStride / uPlane.rowSampling;
423
424 rowInc = stride * colInc / vPlane.colSampling;
425 mediaImage->mPlane[mediaImage->V].mOffset = offset;
426 mediaImage->mPlane[mediaImage->V].mColInc = colInc;
427 mediaImage->mPlane[mediaImage->V].mRowInc = rowInc;
428 mediaImage->mPlane[mediaImage->V].mHorizSubsampling = vPlane.colSampling;
429 mediaImage->mPlane[mediaImage->V].mVertSubsampling = vPlane.rowSampling;
430 break;
431 }
Pawin Vongmasa36653902018-11-15 00:10:25 -0800432 }
433 break;
Wonsik Kimd79ee1f2020-08-27 17:41:56 -0700434 }
435
Pawin Vongmasa36653902018-11-15 00:10:25 -0800436 case C2PlanarLayout::TYPE_YUVA:
Wonsik Kimd79ee1f2020-08-27 17:41:56 -0700437 ALOGD("Converter: unrecognized color format "
438 "(client %d component %d) for YUVA layout",
439 mClientColorFormat, mComponentColorFormat);
440 mInitCheck = NO_INIT;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800441 return;
442 case C2PlanarLayout::TYPE_RGB:
Wonsik Kimd79ee1f2020-08-27 17:41:56 -0700443 ALOGD("Converter: unrecognized color format "
444 "(client %d component %d) for RGB layout",
445 mClientColorFormat, mComponentColorFormat);
446 mInitCheck = NO_INIT;
447 // TODO: support MediaImage layout
448 return;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800449 case C2PlanarLayout::TYPE_RGBA:
Wonsik Kimd79ee1f2020-08-27 17:41:56 -0700450 ALOGD("Converter: unrecognized color format "
451 "(client %d component %d) for RGBA layout",
452 mClientColorFormat, mComponentColorFormat);
453 mInitCheck = NO_INIT;
454 // TODO: support MediaImage layout
455 return;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800456 default:
457 mediaImage->mType = MediaImage2::MEDIA_IMAGE_TYPE_UNKNOWN;
Wonsik Kimd79ee1f2020-08-27 17:41:56 -0700458 if (layout.numPlanes == 1) {
459 const C2PlaneInfo &plane = layout.planes[0];
460 if (plane.colInc < 0 || plane.rowInc < 0) {
461 // Copy-only if we have negative colInc/rowInc
462 tryWrapping = false;
463 }
464 mediaImage->mPlane[0].mOffset = 0;
465 mediaImage->mPlane[0].mColInc = std::abs(plane.colInc);
466 mediaImage->mPlane[0].mRowInc = std::abs(plane.rowInc);
467 mediaImage->mPlane[0].mHorizSubsampling = plane.colSampling;
468 mediaImage->mPlane[0].mVertSubsampling = plane.rowSampling;
469 } else {
470 ALOGD("Converter: unrecognized layout: color format (client %d component %d)",
471 mClientColorFormat, mComponentColorFormat);
472 mInitCheck = NO_INIT;
473 return;
474 }
475 break;
476 }
477 if (tryWrapping) {
478 // try to map directly. check if the planes are near one another
479 const uint8_t *minPtr = mView.data()[0];
480 const uint8_t *maxPtr = mView.data()[0];
481 int32_t planeSize = 0;
482 for (uint32_t i = 0; i < layout.numPlanes; ++i) {
483 const C2PlaneInfo &plane = layout.planes[i];
484 int64_t planeStride = std::abs(plane.rowInc / plane.colInc);
485 ssize_t minOffset = plane.minOffset(
486 mWidth / plane.colSampling, mHeight / plane.rowSampling);
487 ssize_t maxOffset = plane.maxOffset(
488 mWidth / plane.colSampling, mHeight / plane.rowSampling);
489 if (minPtr > mView.data()[i] + minOffset) {
490 minPtr = mView.data()[i] + minOffset;
491 }
492 if (maxPtr < mView.data()[i] + maxOffset) {
493 maxPtr = mView.data()[i] + maxOffset;
494 }
495 planeSize += planeStride * divUp(mAllocatedDepth, 8u)
496 * align(mHeight, 64) / plane.rowSampling;
497 }
498
Wonsik Kimdc173402021-07-22 19:38:17 -0700499 if (minPtr == mView.data()[0] && (maxPtr - minPtr + 1) <= planeSize) {
Wonsik Kimd79ee1f2020-08-27 17:41:56 -0700500 // FIXME: this is risky as reading/writing data out of bound results
501 // in an undefined behavior, but gralloc does assume a
502 // contiguous mapping
503 for (uint32_t i = 0; i < layout.numPlanes; ++i) {
504 const C2PlaneInfo &plane = layout.planes[i];
505 mediaImage->mPlane[i].mOffset = mView.data()[i] - minPtr;
506 mediaImage->mPlane[i].mColInc = plane.colInc;
507 mediaImage->mPlane[i].mRowInc = plane.rowInc;
508 mediaImage->mPlane[i].mHorizSubsampling = plane.colSampling;
509 mediaImage->mPlane[i].mVertSubsampling = plane.rowSampling;
510 }
511 mWrapped = new ABuffer(const_cast<uint8_t *>(minPtr),
512 maxPtr - minPtr + 1);
513 ALOGV("Converter: wrapped (capacity=%zu)", mWrapped->capacity());
514 }
Pawin Vongmasa36653902018-11-15 00:10:25 -0800515 }
516 mediaImage->mNumPlanes = layout.numPlanes;
Harish Mahendrakarf7c49e22019-05-24 14:19:16 -0700517 mediaImage->mWidth = view.crop().width;
518 mediaImage->mHeight = view.crop().height;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800519 mediaImage->mBitDepth = bitDepth;
520 mediaImage->mBitDepthAllocated = mAllocatedDepth;
521
522 uint32_t bufferSize = 0;
523 for (uint32_t i = 0; i < layout.numPlanes; ++i) {
524 const C2PlaneInfo &plane = layout.planes[i];
525 if (plane.allocatedDepth < plane.bitDepth
526 || plane.rightShift != plane.allocatedDepth - plane.bitDepth) {
527 ALOGD("rightShift value of %u unsupported", plane.rightShift);
528 mInitCheck = BAD_VALUE;
529 return;
530 }
531 if (plane.allocatedDepth > 8 && plane.endianness != C2PlaneInfo::NATIVE) {
532 ALOGD("endianness value of %u unsupported", plane.endianness);
533 mInitCheck = BAD_VALUE;
534 return;
535 }
536 if (plane.allocatedDepth != mAllocatedDepth || plane.bitDepth != bitDepth) {
Wonsik Kimd79ee1f2020-08-27 17:41:56 -0700537 ALOGD("different allocatedDepth/bitDepth per plane unsupported");
Pawin Vongmasa36653902018-11-15 00:10:25 -0800538 mInitCheck = BAD_VALUE;
539 return;
540 }
Wonsik Kim8bfa17a2019-05-30 22:12:30 -0700541 bufferSize += stride * vStride
Wonsik Kimd79ee1f2020-08-27 17:41:56 -0700542 / plane.rowSampling / plane.colSampling * divUp(mAllocatedDepth, 8u);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800543 }
544
545 mBackBufferSize = bufferSize;
546 mInitCheck = OK;
547 }
548
549 status_t initCheck() const { return mInitCheck; }
550
551 uint32_t backBufferSize() const { return mBackBufferSize; }
552
553 /**
554 * Wrap C2GraphicView using a MediaImage2. Note that if not wrapped, the content is not mapped
555 * in this function --- the caller should use CopyGraphicView2MediaImage() function to copy the
556 * data into a backing buffer explicitly.
557 *
558 * \return media buffer. This is null if wrapping failed.
559 */
560 sp<ABuffer> wrap() const {
561 if (mBackBuffer == nullptr) {
562 return mWrapped;
563 }
564 return nullptr;
565 }
566
567 bool setBackBuffer(const sp<ABuffer> &backBuffer) {
Wonsik Kim186fdbf2019-01-29 13:30:01 -0800568 if (backBuffer == nullptr) {
569 return false;
570 }
Pawin Vongmasa36653902018-11-15 00:10:25 -0800571 if (backBuffer->capacity() < mBackBufferSize) {
572 return false;
573 }
574 backBuffer->setRange(0, mBackBufferSize);
575 mBackBuffer = backBuffer;
576 return true;
577 }
578
579 /**
580 * Copy C2GraphicView to MediaImage2.
581 */
582 status_t copyToMediaImage() {
583 if (mInitCheck != OK) {
584 return mInitCheck;
585 }
586 return ImageCopy(mBackBuffer->base(), getMediaImage(), mView);
587 }
588
589 const sp<ABuffer> &imageData() const { return mMediaImage; }
590
591private:
592 status_t mInitCheck;
593
594 const C2GraphicView mView;
595 uint32_t mWidth;
596 uint32_t mHeight;
Wonsik Kimd79ee1f2020-08-27 17:41:56 -0700597 int32_t mClientColorFormat; ///< SDK color format for MediaImage
598 int32_t mComponentColorFormat; ///< SDK color format from component
Pawin Vongmasa36653902018-11-15 00:10:25 -0800599 sp<ABuffer> mWrapped; ///< wrapped buffer (if we can map C2Buffer to an ABuffer)
600 uint32_t mAllocatedDepth;
601 uint32_t mBackBufferSize;
602 sp<ABuffer> mMediaImage;
603 std::function<sp<ABuffer>(size_t)> mAlloc;
604
605 sp<ABuffer> mBackBuffer; ///< backing buffer if we have to copy C2Buffer <=> ABuffer
606
607 MediaImage2 *getMediaImage() {
608 return (MediaImage2 *)mMediaImage->base();
609 }
610};
611
612} // namespace
613
614// GraphicBlockBuffer
615
616// static
617sp<GraphicBlockBuffer> GraphicBlockBuffer::Allocate(
618 const sp<AMessage> &format,
619 const std::shared_ptr<C2GraphicBlock> &block,
620 std::function<sp<ABuffer>(size_t)> alloc) {
621 C2GraphicView view(block->map().get());
622 if (view.error() != C2_OK) {
623 ALOGD("C2GraphicBlock::map failed: %d", view.error());
624 return nullptr;
625 }
626
Wonsik Kimd79ee1f2020-08-27 17:41:56 -0700627 GraphicView2MediaImageConverter converter(view, format, false /* copy */);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800628 if (converter.initCheck() != OK) {
629 ALOGD("Converter init failed: %d", converter.initCheck());
630 return nullptr;
631 }
632 bool wrapped = true;
633 sp<ABuffer> buffer = converter.wrap();
634 if (buffer == nullptr) {
635 buffer = alloc(converter.backBufferSize());
636 if (!converter.setBackBuffer(buffer)) {
637 ALOGD("Converter failed to set back buffer");
638 return nullptr;
639 }
640 wrapped = false;
641 }
642 return new GraphicBlockBuffer(
643 format,
644 buffer,
645 std::move(view),
646 block,
647 converter.imageData(),
648 wrapped);
649}
650
651GraphicBlockBuffer::GraphicBlockBuffer(
652 const sp<AMessage> &format,
653 const sp<ABuffer> &buffer,
654 C2GraphicView &&view,
655 const std::shared_ptr<C2GraphicBlock> &block,
656 const sp<ABuffer> &imageData,
657 bool wrapped)
658 : Codec2Buffer(format, buffer),
659 mView(view),
660 mBlock(block),
Pawin Vongmasa36653902018-11-15 00:10:25 -0800661 mWrapped(wrapped) {
662 setImageData(imageData);
663}
664
665std::shared_ptr<C2Buffer> GraphicBlockBuffer::asC2Buffer() {
666 uint32_t width = mView.width();
667 uint32_t height = mView.height();
668 if (!mWrapped) {
669 (void)ImageCopy(mView, base(), imageData());
670 }
671 return C2Buffer::CreateGraphicBuffer(
672 mBlock->share(C2Rect(width, height), C2Fence()));
673}
674
675// GraphicMetadataBuffer
676GraphicMetadataBuffer::GraphicMetadataBuffer(
677 const sp<AMessage> &format,
678 const std::shared_ptr<C2Allocator> &alloc)
679 : Codec2Buffer(format, new ABuffer(sizeof(VideoNativeMetadata))),
680 mAlloc(alloc) {
681 ((VideoNativeMetadata *)base())->pBuffer = nullptr;
682}
683
684std::shared_ptr<C2Buffer> GraphicMetadataBuffer::asC2Buffer() {
bohua222c0b2021-01-12 18:54:53 -0800685#ifdef __LP64__
686 static std::once_flag s_checkOnce;
Harish Mahendrakar731e9142021-04-21 17:20:39 -0700687 static bool s_is64bitOk {true};
bohua222c0b2021-01-12 18:54:53 -0800688 std::call_once(s_checkOnce, [&](){
689 const std::string abi32list =
690 ::android::base::GetProperty("ro.product.cpu.abilist32", "");
Harish Mahendrakar731e9142021-04-21 17:20:39 -0700691 if (!abi32list.empty()) {
692 int32_t inputSurfaceSetting =
693 ::android::base::GetIntProperty("debug.stagefright.c2inputsurface", int32_t(0));
694 s_is64bitOk = inputSurfaceSetting != 0;
bohua222c0b2021-01-12 18:54:53 -0800695 }
696 });
697
Harish Mahendrakar731e9142021-04-21 17:20:39 -0700698 if (!s_is64bitOk) {
699 ALOGE("GraphicMetadataBuffer does not work in 32+64 system if compiled as 64-bit object"\
700 "when debug.stagefright.c2inputsurface is set to 0");
bohua222c0b2021-01-12 18:54:53 -0800701 return nullptr;
702 }
703#endif
704
Pawin Vongmasa36653902018-11-15 00:10:25 -0800705 VideoNativeMetadata *meta = (VideoNativeMetadata *)base();
706 ANativeWindowBuffer *buffer = (ANativeWindowBuffer *)meta->pBuffer;
707 if (buffer == nullptr) {
708 ALOGD("VideoNativeMetadata contains null buffer");
709 return nullptr;
710 }
711
712 ALOGV("VideoNativeMetadata: %dx%d", buffer->width, buffer->height);
713 C2Handle *handle = WrapNativeCodec2GrallocHandle(
Sungtak Leea4d13be2019-01-23 15:24:46 -0800714 buffer->handle,
Pawin Vongmasa36653902018-11-15 00:10:25 -0800715 buffer->width,
716 buffer->height,
717 buffer->format,
718 buffer->usage,
719 buffer->stride);
720 std::shared_ptr<C2GraphicAllocation> alloc;
721 c2_status_t err = mAlloc->priorGraphicAllocation(handle, &alloc);
722 if (err != C2_OK) {
723 ALOGD("Failed to wrap VideoNativeMetadata into C2GraphicAllocation");
Chih-Yu Huangc0ac3552021-03-11 14:37:10 +0900724 native_handle_close(handle);
725 native_handle_delete(handle);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800726 return nullptr;
727 }
728 std::shared_ptr<C2GraphicBlock> block = _C2BlockFactory::CreateGraphicBlock(alloc);
729
730 meta->pBuffer = 0;
Wonsik Kimebe0f9e2019-07-03 11:06:51 -0700731 // TODO: wrap this in C2Fence so that the component can wait when it
732 // actually starts processing.
733 if (meta->nFenceFd >= 0) {
734 sp<Fence> fence(new Fence(meta->nFenceFd));
735 fence->waitForever(LOG_TAG);
736 }
Pawin Vongmasa36653902018-11-15 00:10:25 -0800737 return C2Buffer::CreateGraphicBuffer(
738 block->share(C2Rect(buffer->width, buffer->height), C2Fence()));
Pawin Vongmasa36653902018-11-15 00:10:25 -0800739}
740
741// ConstGraphicBlockBuffer
742
743// static
744sp<ConstGraphicBlockBuffer> ConstGraphicBlockBuffer::Allocate(
745 const sp<AMessage> &format,
746 const std::shared_ptr<C2Buffer> &buffer,
747 std::function<sp<ABuffer>(size_t)> alloc) {
748 if (!buffer
749 || buffer->data().type() != C2BufferData::GRAPHIC
750 || buffer->data().graphicBlocks().size() != 1u) {
751 ALOGD("C2Buffer precond fail");
752 return nullptr;
753 }
754 std::unique_ptr<const C2GraphicView> view(std::make_unique<const C2GraphicView>(
755 buffer->data().graphicBlocks()[0].map().get()));
756 std::unique_ptr<const C2GraphicView> holder;
757
Wonsik Kimd79ee1f2020-08-27 17:41:56 -0700758 GraphicView2MediaImageConverter converter(*view, format, false /* copy */);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800759 if (converter.initCheck() != OK) {
760 ALOGD("Converter init failed: %d", converter.initCheck());
761 return nullptr;
762 }
763 bool wrapped = true;
764 sp<ABuffer> aBuffer = converter.wrap();
765 if (aBuffer == nullptr) {
766 aBuffer = alloc(converter.backBufferSize());
767 if (!converter.setBackBuffer(aBuffer)) {
768 ALOGD("Converter failed to set back buffer");
769 return nullptr;
770 }
771 wrapped = false;
772 converter.copyToMediaImage();
773 // We don't need the view.
774 holder = std::move(view);
775 }
776 return new ConstGraphicBlockBuffer(
777 format,
778 aBuffer,
779 std::move(view),
780 buffer,
781 converter.imageData(),
782 wrapped);
783}
784
785// static
786sp<ConstGraphicBlockBuffer> ConstGraphicBlockBuffer::AllocateEmpty(
787 const sp<AMessage> &format,
788 std::function<sp<ABuffer>(size_t)> alloc) {
789 int32_t width, height;
790 if (!format->findInt32("width", &width)
791 || !format->findInt32("height", &height)) {
792 ALOGD("format had no width / height");
793 return nullptr;
794 }
Wonsik Kim8bfa17a2019-05-30 22:12:30 -0700795 // NOTE: we currently only support YUV420 formats for byte-buffer mode.
796 sp<ABuffer> aBuffer(alloc(align(width, 16) * align(height, 16) * 3 / 2));
Pawin Vongmasa36653902018-11-15 00:10:25 -0800797 return new ConstGraphicBlockBuffer(
798 format,
799 aBuffer,
800 nullptr,
801 nullptr,
802 nullptr,
803 false);
804}
805
806ConstGraphicBlockBuffer::ConstGraphicBlockBuffer(
807 const sp<AMessage> &format,
808 const sp<ABuffer> &aBuffer,
809 std::unique_ptr<const C2GraphicView> &&view,
810 const std::shared_ptr<C2Buffer> &buffer,
811 const sp<ABuffer> &imageData,
812 bool wrapped)
813 : Codec2Buffer(format, aBuffer),
814 mView(std::move(view)),
815 mBufferRef(buffer),
816 mWrapped(wrapped) {
Wonsik Kimc48ddcf2019-02-11 16:16:57 -0800817 setImageData(imageData);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800818}
819
820std::shared_ptr<C2Buffer> ConstGraphicBlockBuffer::asC2Buffer() {
Wonsik Kimf9b32122020-04-02 11:30:17 -0700821 return mBufferRef;
822}
823
824void ConstGraphicBlockBuffer::clearC2BufferRefs() {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800825 mView.reset();
Wonsik Kimf9b32122020-04-02 11:30:17 -0700826 mBufferRef.reset();
Pawin Vongmasa36653902018-11-15 00:10:25 -0800827}
828
829bool ConstGraphicBlockBuffer::canCopy(const std::shared_ptr<C2Buffer> &buffer) const {
830 if (mWrapped || mBufferRef) {
831 ALOGD("ConstGraphicBlockBuffer::canCopy: %swrapped ; buffer ref %s",
832 mWrapped ? "" : "not ", mBufferRef ? "exists" : "doesn't exist");
833 return false;
834 }
835 if (!buffer) {
836 // Nothing to copy, so we can copy by doing nothing.
837 return true;
838 }
839 if (buffer->data().type() != C2BufferData::GRAPHIC) {
840 ALOGD("ConstGraphicBlockBuffer::canCopy: buffer precondition unsatisfied");
841 return false;
842 }
843 if (buffer->data().graphicBlocks().size() == 0) {
844 return true;
845 } else if (buffer->data().graphicBlocks().size() != 1u) {
846 ALOGD("ConstGraphicBlockBuffer::canCopy: too many blocks");
847 return false;
848 }
849
Pawin Vongmasa36653902018-11-15 00:10:25 -0800850 GraphicView2MediaImageConverter converter(
Wonsik Kimd79ee1f2020-08-27 17:41:56 -0700851 buffer->data().graphicBlocks()[0].map().get(),
852 // FIXME: format() is not const, but we cannot change it, so do a const cast here
853 const_cast<ConstGraphicBlockBuffer *>(this)->format(),
854 true /* copy */);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800855 if (converter.initCheck() != OK) {
856 ALOGD("ConstGraphicBlockBuffer::canCopy: converter init failed: %d", converter.initCheck());
857 return false;
858 }
859 if (converter.backBufferSize() > capacity()) {
860 ALOGD("ConstGraphicBlockBuffer::canCopy: insufficient capacity: req %u has %zu",
861 converter.backBufferSize(), capacity());
862 return false;
863 }
864 return true;
865}
866
867bool ConstGraphicBlockBuffer::copy(const std::shared_ptr<C2Buffer> &buffer) {
868 if (!buffer || buffer->data().graphicBlocks().size() == 0) {
869 setRange(0, 0);
870 return true;
871 }
Pawin Vongmasa36653902018-11-15 00:10:25 -0800872
873 GraphicView2MediaImageConverter converter(
Wonsik Kimd79ee1f2020-08-27 17:41:56 -0700874 buffer->data().graphicBlocks()[0].map().get(), format(), true /* copy */);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800875 if (converter.initCheck() != OK) {
876 ALOGD("ConstGraphicBlockBuffer::copy: converter init failed: %d", converter.initCheck());
877 return false;
878 }
879 sp<ABuffer> aBuffer = new ABuffer(base(), capacity());
880 if (!converter.setBackBuffer(aBuffer)) {
881 ALOGD("ConstGraphicBlockBuffer::copy: set back buffer failed");
882 return false;
883 }
Pin-chih Lin1971e2c2019-04-15 19:36:26 +0800884 setRange(0, aBuffer->size()); // align size info
Pawin Vongmasa36653902018-11-15 00:10:25 -0800885 converter.copyToMediaImage();
886 setImageData(converter.imageData());
887 mBufferRef = buffer;
888 return true;
889}
890
891// EncryptedLinearBlockBuffer
892
893EncryptedLinearBlockBuffer::EncryptedLinearBlockBuffer(
894 const sp<AMessage> &format,
895 const std::shared_ptr<C2LinearBlock> &block,
896 const sp<IMemory> &memory,
897 int32_t heapSeqNum)
Ytai Ben-Tsvi7dd39722019-09-05 15:14:30 -0700898 // TODO: Using unsecurePointer() has some associated security pitfalls
899 // (see declaration for details).
900 // Either document why it is safe in this case or address the
901 // issue (e.g. by copying).
902 : Codec2Buffer(format, new ABuffer(memory->unsecurePointer(), memory->size())),
Pawin Vongmasa36653902018-11-15 00:10:25 -0800903 mBlock(block),
904 mMemory(memory),
905 mHeapSeqNum(heapSeqNum) {
906}
907
908std::shared_ptr<C2Buffer> EncryptedLinearBlockBuffer::asC2Buffer() {
909 return C2Buffer::CreateLinearBuffer(mBlock->share(offset(), size(), C2Fence()));
910}
911
912void EncryptedLinearBlockBuffer::fillSourceBuffer(
Robert Shih895fba92019-07-16 16:29:44 -0700913 hardware::drm::V1_0::SharedBuffer *source) {
914 BufferChannelBase::IMemoryToSharedBuffer(mMemory, mHeapSeqNum, source);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800915}
916
917void EncryptedLinearBlockBuffer::fillSourceBuffer(
918 hardware::cas::native::V1_0::SharedBuffer *source) {
919 ssize_t offset;
920 size_t size;
921
922 mHidlMemory = hardware::fromHeap(mMemory->getMemory(&offset, &size));
923 source->heapBase = *mHidlMemory;
924 source->offset = offset;
925 source->size = size;
926}
927
928bool EncryptedLinearBlockBuffer::copyDecryptedContent(
929 const sp<IMemory> &decrypted, size_t length) {
930 C2WriteView view = mBlock->map().get();
931 if (view.error() != C2_OK) {
932 return false;
933 }
934 if (view.size() < length) {
935 return false;
936 }
Ytai Ben-Tsvi7dd39722019-09-05 15:14:30 -0700937 memcpy(view.data(), decrypted->unsecurePointer(), length);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800938 return true;
939}
940
941bool EncryptedLinearBlockBuffer::copyDecryptedContentFromMemory(size_t length) {
942 return copyDecryptedContent(mMemory, length);
943}
944
945native_handle_t *EncryptedLinearBlockBuffer::handle() const {
946 return const_cast<native_handle_t *>(mBlock->handle());
947}
948
Wonsik Kima79c5522022-01-18 16:29:24 -0800949using ::aidl::android::hardware::graphics::common::Cta861_3;
950using ::aidl::android::hardware::graphics::common::Smpte2086;
951
952using ::android::gralloc4::MetadataType_Cta861_3;
953using ::android::gralloc4::MetadataType_Smpte2086;
954using ::android::gralloc4::MetadataType_Smpte2094_40;
955
956using ::android::hardware::Return;
957using ::android::hardware::hidl_vec;
958
959using Error4 = ::android::hardware::graphics::mapper::V4_0::Error;
960using IMapper4 = ::android::hardware::graphics::mapper::V4_0::IMapper;
961
962namespace {
963
964sp<IMapper4> GetMapper4() {
965 static sp<IMapper4> sMapper = IMapper4::getService();
966 return sMapper;
967}
968
969class NativeHandleDeleter {
970public:
971 explicit NativeHandleDeleter(native_handle_t *handle) : mHandle(handle) {}
972 ~NativeHandleDeleter() {
973 if (mHandle) {
974 native_handle_delete(mHandle);
975 }
976 }
977private:
978 native_handle_t *mHandle;
979};
980
981} // namspace
982
983c2_status_t GetHdrMetadataFromGralloc4Handle(
984 const C2Handle *const handle,
985 std::shared_ptr<C2StreamHdrStaticMetadataInfo::input> *staticInfo,
986 std::shared_ptr<C2StreamHdrDynamicMetadataInfo::input> *dynamicInfo) {
987 c2_status_t err = C2_OK;
988 native_handle_t *nativeHandle = UnwrapNativeCodec2GrallocHandle(handle);
989 if (nativeHandle == nullptr) {
990 // Nothing to do
991 return err;
992 }
993 // TRICKY: UnwrapNativeCodec2GrallocHandle creates a new handle but
994 // does not clone the fds. Thus we need to delete the handle
995 // without closing it when going out of scope.
996 // NativeHandle cannot solve this problem, as it would close and
997 // delete the handle, while we need delete only.
998 NativeHandleDeleter nhd(nativeHandle);
999 sp<IMapper4> mapper = GetMapper4();
1000 if (!mapper) {
1001 // Gralloc4 not supported; nothing to do
1002 return err;
1003 }
1004 Error4 mapperErr = Error4::NONE;
1005 if (staticInfo) {
1006 staticInfo->reset(new C2StreamHdrStaticMetadataInfo::input(0u));
1007 memset(&(*staticInfo)->mastering, 0, sizeof((*staticInfo)->mastering));
1008 (*staticInfo)->maxCll = 0;
1009 (*staticInfo)->maxFall = 0;
1010 IMapper4::get_cb cb = [&mapperErr, staticInfo](Error4 err, const hidl_vec<uint8_t> &vec) {
1011 mapperErr = err;
1012 if (err != Error4::NONE) {
1013 return;
1014 }
1015
1016 std::optional<Smpte2086> smpte2086;
1017 gralloc4::decodeSmpte2086(vec, &smpte2086);
1018 if (smpte2086) {
1019 (*staticInfo)->mastering.red.x = smpte2086->primaryRed.x;
1020 (*staticInfo)->mastering.red.y = smpte2086->primaryRed.y;
1021 (*staticInfo)->mastering.green.x = smpte2086->primaryGreen.x;
1022 (*staticInfo)->mastering.green.y = smpte2086->primaryGreen.y;
1023 (*staticInfo)->mastering.blue.x = smpte2086->primaryBlue.x;
1024 (*staticInfo)->mastering.blue.y = smpte2086->primaryBlue.y;
1025 (*staticInfo)->mastering.white.x = smpte2086->whitePoint.x;
1026 (*staticInfo)->mastering.white.y = smpte2086->whitePoint.y;
1027
1028 (*staticInfo)->mastering.maxLuminance = smpte2086->maxLuminance;
1029 (*staticInfo)->mastering.minLuminance = smpte2086->minLuminance;
1030 } else {
1031 mapperErr = Error4::BAD_VALUE;
1032 }
1033 };
1034 Return<void> ret = mapper->get(nativeHandle, MetadataType_Smpte2086, cb);
1035 if (!ret.isOk()) {
1036 err = C2_REFUSED;
1037 } else if (mapperErr != Error4::NONE) {
1038 err = C2_CORRUPTED;
1039 }
1040 cb = [&mapperErr, staticInfo](Error4 err, const hidl_vec<uint8_t> &vec) {
1041 mapperErr = err;
1042 if (err != Error4::NONE) {
1043 return;
1044 }
1045
1046 std::optional<Cta861_3> cta861_3;
1047 gralloc4::decodeCta861_3(vec, &cta861_3);
1048 if (cta861_3) {
1049 (*staticInfo)->maxCll = cta861_3->maxContentLightLevel;
1050 (*staticInfo)->maxFall = cta861_3->maxFrameAverageLightLevel;
1051 } else {
1052 mapperErr = Error4::BAD_VALUE;
1053 }
1054 };
1055 ret = mapper->get(nativeHandle, MetadataType_Cta861_3, cb);
1056 if (!ret.isOk()) {
1057 err = C2_REFUSED;
1058 } else if (mapperErr != Error4::NONE) {
1059 err = C2_CORRUPTED;
1060 }
1061 }
1062 if (dynamicInfo) {
1063 dynamicInfo->reset();
1064 IMapper4::get_cb cb = [&mapperErr, dynamicInfo](Error4 err, const hidl_vec<uint8_t> &vec) {
1065 mapperErr = err;
1066 if (err != Error4::NONE) {
1067 return;
1068 }
1069 if (!dynamicInfo) {
1070 return;
1071 }
1072 *dynamicInfo = C2StreamHdrDynamicMetadataInfo::input::AllocShared(
1073 vec.size(), 0u, C2Config::HDR_DYNAMIC_METADATA_TYPE_SMPTE_2094_40);
1074 memcpy((*dynamicInfo)->m.data, vec.data(), vec.size());
1075 };
1076 Return<void> ret = mapper->get(nativeHandle, MetadataType_Smpte2094_40, cb);
1077 if (!ret.isOk() || mapperErr != Error4::NONE) {
1078 dynamicInfo->reset();
1079 }
1080 }
1081
1082 return err;
1083}
1084
1085c2_status_t SetHdrMetadataToGralloc4Handle(
1086 const std::shared_ptr<const C2StreamHdrStaticMetadataInfo::output> &staticInfo,
1087 const std::shared_ptr<const C2StreamHdrDynamicMetadataInfo::output> &dynamicInfo,
1088 const C2Handle *const handle) {
1089 c2_status_t err = C2_OK;
1090 native_handle_t *nativeHandle = UnwrapNativeCodec2GrallocHandle(handle);
1091 if (nativeHandle == nullptr) {
1092 // Nothing to do
1093 return err;
1094 }
1095 // TRICKY: UnwrapNativeCodec2GrallocHandle creates a new handle but
1096 // does not clone the fds. Thus we need to delete the handle
1097 // without closing it when going out of scope.
1098 NativeHandleDeleter nhd(nativeHandle);
1099 sp<IMapper4> mapper = GetMapper4();
1100 if (!mapper) {
1101 // Gralloc4 not supported; nothing to do
1102 return err;
1103 }
1104 if (staticInfo && *staticInfo) {
1105 std::optional<Smpte2086> smpte2086 = Smpte2086{
1106 {staticInfo->mastering.red.x, staticInfo->mastering.red.y},
1107 {staticInfo->mastering.green.x, staticInfo->mastering.green.y},
1108 {staticInfo->mastering.blue.x, staticInfo->mastering.blue.y},
1109 {staticInfo->mastering.white.x, staticInfo->mastering.white.y},
1110 staticInfo->mastering.maxLuminance,
1111 staticInfo->mastering.minLuminance,
1112 };
1113 hidl_vec<uint8_t> vec;
1114 if (gralloc4::encodeSmpte2086(smpte2086, &vec) == OK) {
1115 Return<Error4> ret = mapper->set(nativeHandle, MetadataType_Smpte2086, vec);
1116 if (!ret.isOk()) {
1117 err = C2_REFUSED;
1118 } else if (ret != Error4::NONE) {
1119 err = C2_CORRUPTED;
1120 }
1121 }
1122 std::optional<Cta861_3> cta861_3 = Cta861_3{
1123 staticInfo->maxCll,
1124 staticInfo->maxFall,
1125 };
1126 if (gralloc4::encodeCta861_3(cta861_3, &vec) == OK) {
1127 Return<Error4> ret = mapper->set(nativeHandle, MetadataType_Cta861_3, vec);
1128 if (!ret.isOk()) {
1129 err = C2_REFUSED;
1130 } else if (ret != Error4::NONE) {
1131 err = C2_CORRUPTED;
1132 }
1133 }
1134 }
1135 if (dynamicInfo && *dynamicInfo) {
1136 hidl_vec<uint8_t> vec;
1137 vec.resize(dynamicInfo->flexCount());
1138 memcpy(vec.data(), dynamicInfo->m.data, dynamicInfo->flexCount());
1139 std::optional<IMapper4::MetadataType> metadataType;
1140 switch (dynamicInfo->m.type_) {
1141 case C2Config::HDR_DYNAMIC_METADATA_TYPE_SMPTE_2094_10:
1142 // TODO
1143 break;
1144 case C2Config::HDR_DYNAMIC_METADATA_TYPE_SMPTE_2094_40:
1145 metadataType = MetadataType_Smpte2094_40;
1146 break;
1147 }
1148 if (metadataType) {
1149 Return<Error4> ret = mapper->set(nativeHandle, *metadataType, vec);
1150 if (!ret.isOk()) {
1151 err = C2_REFUSED;
1152 } else if (ret != Error4::NONE) {
1153 err = C2_CORRUPTED;
1154 }
1155 } else {
1156 err = C2_BAD_VALUE;
1157 }
1158 }
1159
1160 return err;
1161}
1162
Pawin Vongmasa36653902018-11-15 00:10:25 -08001163} // namespace android