blob: 3bbdcfc757421cb14467319fdda9ae2f2acebb5a [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 Kim08a8a2b2021-05-10 19:03:47 -0700366 // stride is in bytes
Wonsik Kim29e3c4d2020-09-02 12:19:44 -0700367 mediaImage->mPlane[mediaImage->Y].mOffset = 0;
368 mediaImage->mPlane[mediaImage->Y].mColInc = 2;
Wonsik Kim08a8a2b2021-05-10 19:03:47 -0700369 mediaImage->mPlane[mediaImage->Y].mRowInc = stride;
Wonsik Kim29e3c4d2020-09-02 12:19:44 -0700370 mediaImage->mPlane[mediaImage->Y].mHorizSubsampling = 1;
371 mediaImage->mPlane[mediaImage->Y].mVertSubsampling = 1;
372
Wonsik Kim08a8a2b2021-05-10 19:03:47 -0700373 mediaImage->mPlane[mediaImage->U].mOffset = stride * vStride;
Wonsik Kim29e3c4d2020-09-02 12:19:44 -0700374 mediaImage->mPlane[mediaImage->U].mColInc = 4;
Wonsik Kim08a8a2b2021-05-10 19:03:47 -0700375 mediaImage->mPlane[mediaImage->U].mRowInc = stride;
Wonsik Kim29e3c4d2020-09-02 12:19:44 -0700376 mediaImage->mPlane[mediaImage->U].mHorizSubsampling = 2;
377 mediaImage->mPlane[mediaImage->U].mVertSubsampling = 2;
378
Wonsik Kim08a8a2b2021-05-10 19:03:47 -0700379 mediaImage->mPlane[mediaImage->V].mOffset = stride * vStride + 2;
Wonsik Kim29e3c4d2020-09-02 12:19:44 -0700380 mediaImage->mPlane[mediaImage->V].mColInc = 4;
Wonsik Kim08a8a2b2021-05-10 19:03:47 -0700381 mediaImage->mPlane[mediaImage->V].mRowInc = stride;
Wonsik Kim29e3c4d2020-09-02 12:19:44 -0700382 mediaImage->mPlane[mediaImage->V].mHorizSubsampling = 2;
383 mediaImage->mPlane[mediaImage->V].mVertSubsampling = 2;
Wonsik Kimd79ee1f2020-08-27 17:41:56 -0700384 if (tryWrapping) {
385 tryWrapping = yPlane.allocatedDepth == 16
386 && uPlane.allocatedDepth == 16
387 && vPlane.allocatedDepth == 16
388 && yPlane.bitDepth == 10
389 && uPlane.bitDepth == 10
390 && vPlane.bitDepth == 10
391 && yPlane.rightShift == 6
392 && uPlane.rightShift == 6
393 && vPlane.rightShift == 6
394 && yPlane.rowSampling == 1 && yPlane.colSampling == 1
395 && uPlane.rowSampling == 2 && uPlane.colSampling == 2
396 && vPlane.rowSampling == 2 && vPlane.colSampling == 2
397 && yPlane.colInc == 2
398 && uPlane.colInc == 4
399 && vPlane.colInc == 4
400 && yPlane.rowInc == uPlane.rowInc
401 && yPlane.rowInc == vPlane.rowInc;
402 }
Wonsik Kim29e3c4d2020-09-02 12:19:44 -0700403 break;
404
Wonsik Kimd79ee1f2020-08-27 17:41:56 -0700405 default: {
406 // default to fully planar format --- this will be overridden if wrapping
407 // TODO: keep interleaved format
408 int32_t colInc = divUp(mAllocatedDepth, 8u);
409 int32_t rowInc = stride * colInc / yPlane.colSampling;
410 mediaImage->mPlane[mediaImage->Y].mOffset = 0;
411 mediaImage->mPlane[mediaImage->Y].mColInc = colInc;
412 mediaImage->mPlane[mediaImage->Y].mRowInc = rowInc;
413 mediaImage->mPlane[mediaImage->Y].mHorizSubsampling = yPlane.colSampling;
414 mediaImage->mPlane[mediaImage->Y].mVertSubsampling = yPlane.rowSampling;
415 int32_t offset = rowInc * vStride / yPlane.rowSampling;
416
417 rowInc = stride * colInc / uPlane.colSampling;
418 mediaImage->mPlane[mediaImage->U].mOffset = offset;
419 mediaImage->mPlane[mediaImage->U].mColInc = colInc;
420 mediaImage->mPlane[mediaImage->U].mRowInc = rowInc;
421 mediaImage->mPlane[mediaImage->U].mHorizSubsampling = uPlane.colSampling;
422 mediaImage->mPlane[mediaImage->U].mVertSubsampling = uPlane.rowSampling;
423 offset += rowInc * vStride / uPlane.rowSampling;
424
425 rowInc = stride * colInc / vPlane.colSampling;
426 mediaImage->mPlane[mediaImage->V].mOffset = offset;
427 mediaImage->mPlane[mediaImage->V].mColInc = colInc;
428 mediaImage->mPlane[mediaImage->V].mRowInc = rowInc;
429 mediaImage->mPlane[mediaImage->V].mHorizSubsampling = vPlane.colSampling;
430 mediaImage->mPlane[mediaImage->V].mVertSubsampling = vPlane.rowSampling;
431 break;
432 }
Pawin Vongmasa36653902018-11-15 00:10:25 -0800433 }
434 break;
Wonsik Kimd79ee1f2020-08-27 17:41:56 -0700435 }
436
Pawin Vongmasa36653902018-11-15 00:10:25 -0800437 case C2PlanarLayout::TYPE_YUVA:
Wonsik Kimd79ee1f2020-08-27 17:41:56 -0700438 ALOGD("Converter: unrecognized color format "
439 "(client %d component %d) for YUVA layout",
440 mClientColorFormat, mComponentColorFormat);
441 mInitCheck = NO_INIT;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800442 return;
443 case C2PlanarLayout::TYPE_RGB:
Wonsik Kimd79ee1f2020-08-27 17:41:56 -0700444 ALOGD("Converter: unrecognized color format "
445 "(client %d component %d) for RGB layout",
446 mClientColorFormat, mComponentColorFormat);
447 mInitCheck = NO_INIT;
448 // TODO: support MediaImage layout
449 return;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800450 case C2PlanarLayout::TYPE_RGBA:
Wonsik Kimd79ee1f2020-08-27 17:41:56 -0700451 ALOGD("Converter: unrecognized color format "
452 "(client %d component %d) for RGBA layout",
453 mClientColorFormat, mComponentColorFormat);
454 mInitCheck = NO_INIT;
455 // TODO: support MediaImage layout
456 return;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800457 default:
458 mediaImage->mType = MediaImage2::MEDIA_IMAGE_TYPE_UNKNOWN;
Wonsik Kimd79ee1f2020-08-27 17:41:56 -0700459 if (layout.numPlanes == 1) {
460 const C2PlaneInfo &plane = layout.planes[0];
461 if (plane.colInc < 0 || plane.rowInc < 0) {
462 // Copy-only if we have negative colInc/rowInc
463 tryWrapping = false;
464 }
465 mediaImage->mPlane[0].mOffset = 0;
466 mediaImage->mPlane[0].mColInc = std::abs(plane.colInc);
467 mediaImage->mPlane[0].mRowInc = std::abs(plane.rowInc);
468 mediaImage->mPlane[0].mHorizSubsampling = plane.colSampling;
469 mediaImage->mPlane[0].mVertSubsampling = plane.rowSampling;
470 } else {
471 ALOGD("Converter: unrecognized layout: color format (client %d component %d)",
472 mClientColorFormat, mComponentColorFormat);
473 mInitCheck = NO_INIT;
474 return;
475 }
476 break;
477 }
478 if (tryWrapping) {
479 // try to map directly. check if the planes are near one another
480 const uint8_t *minPtr = mView.data()[0];
481 const uint8_t *maxPtr = mView.data()[0];
482 int32_t planeSize = 0;
483 for (uint32_t i = 0; i < layout.numPlanes; ++i) {
484 const C2PlaneInfo &plane = layout.planes[i];
485 int64_t planeStride = std::abs(plane.rowInc / plane.colInc);
486 ssize_t minOffset = plane.minOffset(
487 mWidth / plane.colSampling, mHeight / plane.rowSampling);
488 ssize_t maxOffset = plane.maxOffset(
489 mWidth / plane.colSampling, mHeight / plane.rowSampling);
490 if (minPtr > mView.data()[i] + minOffset) {
491 minPtr = mView.data()[i] + minOffset;
492 }
493 if (maxPtr < mView.data()[i] + maxOffset) {
494 maxPtr = mView.data()[i] + maxOffset;
495 }
496 planeSize += planeStride * divUp(mAllocatedDepth, 8u)
497 * align(mHeight, 64) / plane.rowSampling;
498 }
499
Wonsik Kimdc173402021-07-22 19:38:17 -0700500 if (minPtr == mView.data()[0] && (maxPtr - minPtr + 1) <= planeSize) {
Wonsik Kimd79ee1f2020-08-27 17:41:56 -0700501 // FIXME: this is risky as reading/writing data out of bound results
502 // in an undefined behavior, but gralloc does assume a
503 // contiguous mapping
504 for (uint32_t i = 0; i < layout.numPlanes; ++i) {
505 const C2PlaneInfo &plane = layout.planes[i];
506 mediaImage->mPlane[i].mOffset = mView.data()[i] - minPtr;
507 mediaImage->mPlane[i].mColInc = plane.colInc;
508 mediaImage->mPlane[i].mRowInc = plane.rowInc;
509 mediaImage->mPlane[i].mHorizSubsampling = plane.colSampling;
510 mediaImage->mPlane[i].mVertSubsampling = plane.rowSampling;
511 }
512 mWrapped = new ABuffer(const_cast<uint8_t *>(minPtr),
513 maxPtr - minPtr + 1);
514 ALOGV("Converter: wrapped (capacity=%zu)", mWrapped->capacity());
515 }
Pawin Vongmasa36653902018-11-15 00:10:25 -0800516 }
517 mediaImage->mNumPlanes = layout.numPlanes;
Harish Mahendrakarf7c49e22019-05-24 14:19:16 -0700518 mediaImage->mWidth = view.crop().width;
519 mediaImage->mHeight = view.crop().height;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800520 mediaImage->mBitDepth = bitDepth;
521 mediaImage->mBitDepthAllocated = mAllocatedDepth;
522
523 uint32_t bufferSize = 0;
524 for (uint32_t i = 0; i < layout.numPlanes; ++i) {
525 const C2PlaneInfo &plane = layout.planes[i];
526 if (plane.allocatedDepth < plane.bitDepth
527 || plane.rightShift != plane.allocatedDepth - plane.bitDepth) {
528 ALOGD("rightShift value of %u unsupported", plane.rightShift);
529 mInitCheck = BAD_VALUE;
530 return;
531 }
532 if (plane.allocatedDepth > 8 && plane.endianness != C2PlaneInfo::NATIVE) {
533 ALOGD("endianness value of %u unsupported", plane.endianness);
534 mInitCheck = BAD_VALUE;
535 return;
536 }
537 if (plane.allocatedDepth != mAllocatedDepth || plane.bitDepth != bitDepth) {
Wonsik Kimd79ee1f2020-08-27 17:41:56 -0700538 ALOGD("different allocatedDepth/bitDepth per plane unsupported");
Pawin Vongmasa36653902018-11-15 00:10:25 -0800539 mInitCheck = BAD_VALUE;
540 return;
541 }
Wonsik Kim08a8a2b2021-05-10 19:03:47 -0700542 // stride is in bytes
543 bufferSize += stride * vStride / plane.rowSampling / plane.colSampling;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800544 }
545
546 mBackBufferSize = bufferSize;
547 mInitCheck = OK;
548 }
549
550 status_t initCheck() const { return mInitCheck; }
551
552 uint32_t backBufferSize() const { return mBackBufferSize; }
553
554 /**
555 * Wrap C2GraphicView using a MediaImage2. Note that if not wrapped, the content is not mapped
556 * in this function --- the caller should use CopyGraphicView2MediaImage() function to copy the
557 * data into a backing buffer explicitly.
558 *
559 * \return media buffer. This is null if wrapping failed.
560 */
561 sp<ABuffer> wrap() const {
562 if (mBackBuffer == nullptr) {
563 return mWrapped;
564 }
565 return nullptr;
566 }
567
568 bool setBackBuffer(const sp<ABuffer> &backBuffer) {
Wonsik Kim186fdbf2019-01-29 13:30:01 -0800569 if (backBuffer == nullptr) {
570 return false;
571 }
Pawin Vongmasa36653902018-11-15 00:10:25 -0800572 if (backBuffer->capacity() < mBackBufferSize) {
573 return false;
574 }
575 backBuffer->setRange(0, mBackBufferSize);
576 mBackBuffer = backBuffer;
577 return true;
578 }
579
580 /**
581 * Copy C2GraphicView to MediaImage2.
582 */
583 status_t copyToMediaImage() {
584 if (mInitCheck != OK) {
585 return mInitCheck;
586 }
587 return ImageCopy(mBackBuffer->base(), getMediaImage(), mView);
588 }
589
590 const sp<ABuffer> &imageData() const { return mMediaImage; }
591
592private:
593 status_t mInitCheck;
594
595 const C2GraphicView mView;
596 uint32_t mWidth;
597 uint32_t mHeight;
Wonsik Kimd79ee1f2020-08-27 17:41:56 -0700598 int32_t mClientColorFormat; ///< SDK color format for MediaImage
599 int32_t mComponentColorFormat; ///< SDK color format from component
Pawin Vongmasa36653902018-11-15 00:10:25 -0800600 sp<ABuffer> mWrapped; ///< wrapped buffer (if we can map C2Buffer to an ABuffer)
601 uint32_t mAllocatedDepth;
602 uint32_t mBackBufferSize;
603 sp<ABuffer> mMediaImage;
604 std::function<sp<ABuffer>(size_t)> mAlloc;
605
606 sp<ABuffer> mBackBuffer; ///< backing buffer if we have to copy C2Buffer <=> ABuffer
607
608 MediaImage2 *getMediaImage() {
609 return (MediaImage2 *)mMediaImage->base();
610 }
611};
612
613} // namespace
614
615// GraphicBlockBuffer
616
617// static
618sp<GraphicBlockBuffer> GraphicBlockBuffer::Allocate(
619 const sp<AMessage> &format,
620 const std::shared_ptr<C2GraphicBlock> &block,
621 std::function<sp<ABuffer>(size_t)> alloc) {
622 C2GraphicView view(block->map().get());
623 if (view.error() != C2_OK) {
624 ALOGD("C2GraphicBlock::map failed: %d", view.error());
625 return nullptr;
626 }
627
Wonsik Kimd79ee1f2020-08-27 17:41:56 -0700628 GraphicView2MediaImageConverter converter(view, format, false /* copy */);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800629 if (converter.initCheck() != OK) {
630 ALOGD("Converter init failed: %d", converter.initCheck());
631 return nullptr;
632 }
633 bool wrapped = true;
634 sp<ABuffer> buffer = converter.wrap();
635 if (buffer == nullptr) {
636 buffer = alloc(converter.backBufferSize());
637 if (!converter.setBackBuffer(buffer)) {
638 ALOGD("Converter failed to set back buffer");
639 return nullptr;
640 }
641 wrapped = false;
642 }
643 return new GraphicBlockBuffer(
644 format,
645 buffer,
646 std::move(view),
647 block,
648 converter.imageData(),
649 wrapped);
650}
651
652GraphicBlockBuffer::GraphicBlockBuffer(
653 const sp<AMessage> &format,
654 const sp<ABuffer> &buffer,
655 C2GraphicView &&view,
656 const std::shared_ptr<C2GraphicBlock> &block,
657 const sp<ABuffer> &imageData,
658 bool wrapped)
659 : Codec2Buffer(format, buffer),
660 mView(view),
661 mBlock(block),
Pawin Vongmasa36653902018-11-15 00:10:25 -0800662 mWrapped(wrapped) {
663 setImageData(imageData);
664}
665
666std::shared_ptr<C2Buffer> GraphicBlockBuffer::asC2Buffer() {
667 uint32_t width = mView.width();
668 uint32_t height = mView.height();
669 if (!mWrapped) {
670 (void)ImageCopy(mView, base(), imageData());
671 }
672 return C2Buffer::CreateGraphicBuffer(
673 mBlock->share(C2Rect(width, height), C2Fence()));
674}
675
676// GraphicMetadataBuffer
677GraphicMetadataBuffer::GraphicMetadataBuffer(
678 const sp<AMessage> &format,
679 const std::shared_ptr<C2Allocator> &alloc)
680 : Codec2Buffer(format, new ABuffer(sizeof(VideoNativeMetadata))),
681 mAlloc(alloc) {
682 ((VideoNativeMetadata *)base())->pBuffer = nullptr;
683}
684
685std::shared_ptr<C2Buffer> GraphicMetadataBuffer::asC2Buffer() {
bohua222c0b2021-01-12 18:54:53 -0800686#ifdef __LP64__
687 static std::once_flag s_checkOnce;
Harish Mahendrakar731e9142021-04-21 17:20:39 -0700688 static bool s_is64bitOk {true};
bohua222c0b2021-01-12 18:54:53 -0800689 std::call_once(s_checkOnce, [&](){
690 const std::string abi32list =
691 ::android::base::GetProperty("ro.product.cpu.abilist32", "");
Harish Mahendrakar731e9142021-04-21 17:20:39 -0700692 if (!abi32list.empty()) {
693 int32_t inputSurfaceSetting =
694 ::android::base::GetIntProperty("debug.stagefright.c2inputsurface", int32_t(0));
695 s_is64bitOk = inputSurfaceSetting != 0;
bohua222c0b2021-01-12 18:54:53 -0800696 }
697 });
698
Harish Mahendrakar731e9142021-04-21 17:20:39 -0700699 if (!s_is64bitOk) {
700 ALOGE("GraphicMetadataBuffer does not work in 32+64 system if compiled as 64-bit object"\
701 "when debug.stagefright.c2inputsurface is set to 0");
bohua222c0b2021-01-12 18:54:53 -0800702 return nullptr;
703 }
704#endif
705
Pawin Vongmasa36653902018-11-15 00:10:25 -0800706 VideoNativeMetadata *meta = (VideoNativeMetadata *)base();
707 ANativeWindowBuffer *buffer = (ANativeWindowBuffer *)meta->pBuffer;
708 if (buffer == nullptr) {
709 ALOGD("VideoNativeMetadata contains null buffer");
710 return nullptr;
711 }
712
713 ALOGV("VideoNativeMetadata: %dx%d", buffer->width, buffer->height);
714 C2Handle *handle = WrapNativeCodec2GrallocHandle(
Sungtak Leea4d13be2019-01-23 15:24:46 -0800715 buffer->handle,
Pawin Vongmasa36653902018-11-15 00:10:25 -0800716 buffer->width,
717 buffer->height,
718 buffer->format,
719 buffer->usage,
720 buffer->stride);
721 std::shared_ptr<C2GraphicAllocation> alloc;
722 c2_status_t err = mAlloc->priorGraphicAllocation(handle, &alloc);
723 if (err != C2_OK) {
724 ALOGD("Failed to wrap VideoNativeMetadata into C2GraphicAllocation");
Chih-Yu Huangc0ac3552021-03-11 14:37:10 +0900725 native_handle_close(handle);
726 native_handle_delete(handle);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800727 return nullptr;
728 }
729 std::shared_ptr<C2GraphicBlock> block = _C2BlockFactory::CreateGraphicBlock(alloc);
730
731 meta->pBuffer = 0;
Wonsik Kimebe0f9e2019-07-03 11:06:51 -0700732 // TODO: wrap this in C2Fence so that the component can wait when it
733 // actually starts processing.
734 if (meta->nFenceFd >= 0) {
735 sp<Fence> fence(new Fence(meta->nFenceFd));
736 fence->waitForever(LOG_TAG);
737 }
Pawin Vongmasa36653902018-11-15 00:10:25 -0800738 return C2Buffer::CreateGraphicBuffer(
739 block->share(C2Rect(buffer->width, buffer->height), C2Fence()));
Pawin Vongmasa36653902018-11-15 00:10:25 -0800740}
741
742// ConstGraphicBlockBuffer
743
744// static
745sp<ConstGraphicBlockBuffer> ConstGraphicBlockBuffer::Allocate(
746 const sp<AMessage> &format,
747 const std::shared_ptr<C2Buffer> &buffer,
748 std::function<sp<ABuffer>(size_t)> alloc) {
749 if (!buffer
750 || buffer->data().type() != C2BufferData::GRAPHIC
751 || buffer->data().graphicBlocks().size() != 1u) {
752 ALOGD("C2Buffer precond fail");
753 return nullptr;
754 }
755 std::unique_ptr<const C2GraphicView> view(std::make_unique<const C2GraphicView>(
756 buffer->data().graphicBlocks()[0].map().get()));
757 std::unique_ptr<const C2GraphicView> holder;
758
Wonsik Kimd79ee1f2020-08-27 17:41:56 -0700759 GraphicView2MediaImageConverter converter(*view, format, false /* copy */);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800760 if (converter.initCheck() != OK) {
761 ALOGD("Converter init failed: %d", converter.initCheck());
762 return nullptr;
763 }
764 bool wrapped = true;
765 sp<ABuffer> aBuffer = converter.wrap();
766 if (aBuffer == nullptr) {
767 aBuffer = alloc(converter.backBufferSize());
768 if (!converter.setBackBuffer(aBuffer)) {
769 ALOGD("Converter failed to set back buffer");
770 return nullptr;
771 }
772 wrapped = false;
773 converter.copyToMediaImage();
774 // We don't need the view.
775 holder = std::move(view);
776 }
777 return new ConstGraphicBlockBuffer(
778 format,
779 aBuffer,
780 std::move(view),
781 buffer,
782 converter.imageData(),
783 wrapped);
784}
785
786// static
787sp<ConstGraphicBlockBuffer> ConstGraphicBlockBuffer::AllocateEmpty(
788 const sp<AMessage> &format,
789 std::function<sp<ABuffer>(size_t)> alloc) {
790 int32_t width, height;
791 if (!format->findInt32("width", &width)
792 || !format->findInt32("height", &height)) {
793 ALOGD("format had no width / height");
794 return nullptr;
795 }
Wonsik Kim08a8a2b2021-05-10 19:03:47 -0700796 int32_t colorFormat = COLOR_FormatYUV420Flexible;
797 int32_t bpp = 12; // 8(Y) + 2(U) + 2(V)
798 if (format->findInt32(KEY_COLOR_FORMAT, &colorFormat)) {
799 if (colorFormat == COLOR_FormatYUVP010) {
800 bpp = 24; // 16(Y) + 4(U) + 4(V)
801 }
802 }
803 sp<ABuffer> aBuffer(alloc(align(width, 16) * align(height, 16) * bpp / 8));
Jiajia Cong9ed0ab22020-12-02 12:00:49 +0800804 if (aBuffer == nullptr) {
805 ALOGD("%s: failed to allocate buffer", __func__);
806 return nullptr;
807 }
Pawin Vongmasa36653902018-11-15 00:10:25 -0800808 return new ConstGraphicBlockBuffer(
809 format,
810 aBuffer,
811 nullptr,
812 nullptr,
813 nullptr,
814 false);
815}
816
817ConstGraphicBlockBuffer::ConstGraphicBlockBuffer(
818 const sp<AMessage> &format,
819 const sp<ABuffer> &aBuffer,
820 std::unique_ptr<const C2GraphicView> &&view,
821 const std::shared_ptr<C2Buffer> &buffer,
822 const sp<ABuffer> &imageData,
823 bool wrapped)
824 : Codec2Buffer(format, aBuffer),
825 mView(std::move(view)),
826 mBufferRef(buffer),
827 mWrapped(wrapped) {
Wonsik Kimc48ddcf2019-02-11 16:16:57 -0800828 setImageData(imageData);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800829}
830
831std::shared_ptr<C2Buffer> ConstGraphicBlockBuffer::asC2Buffer() {
Wonsik Kimf9b32122020-04-02 11:30:17 -0700832 return mBufferRef;
833}
834
835void ConstGraphicBlockBuffer::clearC2BufferRefs() {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800836 mView.reset();
Wonsik Kimf9b32122020-04-02 11:30:17 -0700837 mBufferRef.reset();
Pawin Vongmasa36653902018-11-15 00:10:25 -0800838}
839
840bool ConstGraphicBlockBuffer::canCopy(const std::shared_ptr<C2Buffer> &buffer) const {
841 if (mWrapped || mBufferRef) {
842 ALOGD("ConstGraphicBlockBuffer::canCopy: %swrapped ; buffer ref %s",
843 mWrapped ? "" : "not ", mBufferRef ? "exists" : "doesn't exist");
844 return false;
845 }
846 if (!buffer) {
847 // Nothing to copy, so we can copy by doing nothing.
848 return true;
849 }
850 if (buffer->data().type() != C2BufferData::GRAPHIC) {
851 ALOGD("ConstGraphicBlockBuffer::canCopy: buffer precondition unsatisfied");
852 return false;
853 }
854 if (buffer->data().graphicBlocks().size() == 0) {
855 return true;
856 } else if (buffer->data().graphicBlocks().size() != 1u) {
857 ALOGD("ConstGraphicBlockBuffer::canCopy: too many blocks");
858 return false;
859 }
860
Pawin Vongmasa36653902018-11-15 00:10:25 -0800861 GraphicView2MediaImageConverter converter(
Wonsik Kimd79ee1f2020-08-27 17:41:56 -0700862 buffer->data().graphicBlocks()[0].map().get(),
863 // FIXME: format() is not const, but we cannot change it, so do a const cast here
864 const_cast<ConstGraphicBlockBuffer *>(this)->format(),
865 true /* copy */);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800866 if (converter.initCheck() != OK) {
867 ALOGD("ConstGraphicBlockBuffer::canCopy: converter init failed: %d", converter.initCheck());
868 return false;
869 }
870 if (converter.backBufferSize() > capacity()) {
871 ALOGD("ConstGraphicBlockBuffer::canCopy: insufficient capacity: req %u has %zu",
872 converter.backBufferSize(), capacity());
873 return false;
874 }
875 return true;
876}
877
878bool ConstGraphicBlockBuffer::copy(const std::shared_ptr<C2Buffer> &buffer) {
879 if (!buffer || buffer->data().graphicBlocks().size() == 0) {
880 setRange(0, 0);
881 return true;
882 }
Pawin Vongmasa36653902018-11-15 00:10:25 -0800883
884 GraphicView2MediaImageConverter converter(
Wonsik Kimd79ee1f2020-08-27 17:41:56 -0700885 buffer->data().graphicBlocks()[0].map().get(), format(), true /* copy */);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800886 if (converter.initCheck() != OK) {
887 ALOGD("ConstGraphicBlockBuffer::copy: converter init failed: %d", converter.initCheck());
888 return false;
889 }
890 sp<ABuffer> aBuffer = new ABuffer(base(), capacity());
891 if (!converter.setBackBuffer(aBuffer)) {
892 ALOGD("ConstGraphicBlockBuffer::copy: set back buffer failed");
893 return false;
894 }
Pin-chih Lin1971e2c2019-04-15 19:36:26 +0800895 setRange(0, aBuffer->size()); // align size info
Pawin Vongmasa36653902018-11-15 00:10:25 -0800896 converter.copyToMediaImage();
897 setImageData(converter.imageData());
898 mBufferRef = buffer;
899 return true;
900}
901
902// EncryptedLinearBlockBuffer
903
904EncryptedLinearBlockBuffer::EncryptedLinearBlockBuffer(
905 const sp<AMessage> &format,
906 const std::shared_ptr<C2LinearBlock> &block,
907 const sp<IMemory> &memory,
908 int32_t heapSeqNum)
Ytai Ben-Tsvi7dd39722019-09-05 15:14:30 -0700909 // TODO: Using unsecurePointer() has some associated security pitfalls
910 // (see declaration for details).
911 // Either document why it is safe in this case or address the
912 // issue (e.g. by copying).
913 : Codec2Buffer(format, new ABuffer(memory->unsecurePointer(), memory->size())),
Pawin Vongmasa36653902018-11-15 00:10:25 -0800914 mBlock(block),
915 mMemory(memory),
916 mHeapSeqNum(heapSeqNum) {
917}
918
919std::shared_ptr<C2Buffer> EncryptedLinearBlockBuffer::asC2Buffer() {
920 return C2Buffer::CreateLinearBuffer(mBlock->share(offset(), size(), C2Fence()));
921}
922
923void EncryptedLinearBlockBuffer::fillSourceBuffer(
Robert Shih895fba92019-07-16 16:29:44 -0700924 hardware::drm::V1_0::SharedBuffer *source) {
925 BufferChannelBase::IMemoryToSharedBuffer(mMemory, mHeapSeqNum, source);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800926}
927
928void EncryptedLinearBlockBuffer::fillSourceBuffer(
929 hardware::cas::native::V1_0::SharedBuffer *source) {
930 ssize_t offset;
931 size_t size;
932
933 mHidlMemory = hardware::fromHeap(mMemory->getMemory(&offset, &size));
934 source->heapBase = *mHidlMemory;
935 source->offset = offset;
936 source->size = size;
937}
938
939bool EncryptedLinearBlockBuffer::copyDecryptedContent(
940 const sp<IMemory> &decrypted, size_t length) {
941 C2WriteView view = mBlock->map().get();
942 if (view.error() != C2_OK) {
943 return false;
944 }
945 if (view.size() < length) {
946 return false;
947 }
Ytai Ben-Tsvi7dd39722019-09-05 15:14:30 -0700948 memcpy(view.data(), decrypted->unsecurePointer(), length);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800949 return true;
950}
951
952bool EncryptedLinearBlockBuffer::copyDecryptedContentFromMemory(size_t length) {
953 return copyDecryptedContent(mMemory, length);
954}
955
956native_handle_t *EncryptedLinearBlockBuffer::handle() const {
957 return const_cast<native_handle_t *>(mBlock->handle());
958}
959
Wonsik Kima79c5522022-01-18 16:29:24 -0800960using ::aidl::android::hardware::graphics::common::Cta861_3;
961using ::aidl::android::hardware::graphics::common::Smpte2086;
962
963using ::android::gralloc4::MetadataType_Cta861_3;
964using ::android::gralloc4::MetadataType_Smpte2086;
965using ::android::gralloc4::MetadataType_Smpte2094_40;
966
967using ::android::hardware::Return;
968using ::android::hardware::hidl_vec;
969
970using Error4 = ::android::hardware::graphics::mapper::V4_0::Error;
971using IMapper4 = ::android::hardware::graphics::mapper::V4_0::IMapper;
972
973namespace {
974
975sp<IMapper4> GetMapper4() {
976 static sp<IMapper4> sMapper = IMapper4::getService();
977 return sMapper;
978}
979
980class NativeHandleDeleter {
981public:
982 explicit NativeHandleDeleter(native_handle_t *handle) : mHandle(handle) {}
983 ~NativeHandleDeleter() {
984 if (mHandle) {
985 native_handle_delete(mHandle);
986 }
987 }
988private:
989 native_handle_t *mHandle;
990};
991
992} // namspace
993
994c2_status_t GetHdrMetadataFromGralloc4Handle(
995 const C2Handle *const handle,
996 std::shared_ptr<C2StreamHdrStaticMetadataInfo::input> *staticInfo,
997 std::shared_ptr<C2StreamHdrDynamicMetadataInfo::input> *dynamicInfo) {
998 c2_status_t err = C2_OK;
999 native_handle_t *nativeHandle = UnwrapNativeCodec2GrallocHandle(handle);
1000 if (nativeHandle == nullptr) {
1001 // Nothing to do
1002 return err;
1003 }
1004 // TRICKY: UnwrapNativeCodec2GrallocHandle creates a new handle but
1005 // does not clone the fds. Thus we need to delete the handle
1006 // without closing it when going out of scope.
1007 // NativeHandle cannot solve this problem, as it would close and
1008 // delete the handle, while we need delete only.
1009 NativeHandleDeleter nhd(nativeHandle);
1010 sp<IMapper4> mapper = GetMapper4();
1011 if (!mapper) {
1012 // Gralloc4 not supported; nothing to do
1013 return err;
1014 }
1015 Error4 mapperErr = Error4::NONE;
1016 if (staticInfo) {
1017 staticInfo->reset(new C2StreamHdrStaticMetadataInfo::input(0u));
1018 memset(&(*staticInfo)->mastering, 0, sizeof((*staticInfo)->mastering));
1019 (*staticInfo)->maxCll = 0;
1020 (*staticInfo)->maxFall = 0;
1021 IMapper4::get_cb cb = [&mapperErr, staticInfo](Error4 err, const hidl_vec<uint8_t> &vec) {
1022 mapperErr = err;
1023 if (err != Error4::NONE) {
1024 return;
1025 }
1026
1027 std::optional<Smpte2086> smpte2086;
1028 gralloc4::decodeSmpte2086(vec, &smpte2086);
1029 if (smpte2086) {
1030 (*staticInfo)->mastering.red.x = smpte2086->primaryRed.x;
1031 (*staticInfo)->mastering.red.y = smpte2086->primaryRed.y;
1032 (*staticInfo)->mastering.green.x = smpte2086->primaryGreen.x;
1033 (*staticInfo)->mastering.green.y = smpte2086->primaryGreen.y;
1034 (*staticInfo)->mastering.blue.x = smpte2086->primaryBlue.x;
1035 (*staticInfo)->mastering.blue.y = smpte2086->primaryBlue.y;
1036 (*staticInfo)->mastering.white.x = smpte2086->whitePoint.x;
1037 (*staticInfo)->mastering.white.y = smpte2086->whitePoint.y;
1038
1039 (*staticInfo)->mastering.maxLuminance = smpte2086->maxLuminance;
1040 (*staticInfo)->mastering.minLuminance = smpte2086->minLuminance;
1041 } else {
1042 mapperErr = Error4::BAD_VALUE;
1043 }
1044 };
1045 Return<void> ret = mapper->get(nativeHandle, MetadataType_Smpte2086, cb);
1046 if (!ret.isOk()) {
1047 err = C2_REFUSED;
1048 } else if (mapperErr != Error4::NONE) {
1049 err = C2_CORRUPTED;
1050 }
1051 cb = [&mapperErr, staticInfo](Error4 err, const hidl_vec<uint8_t> &vec) {
1052 mapperErr = err;
1053 if (err != Error4::NONE) {
1054 return;
1055 }
1056
1057 std::optional<Cta861_3> cta861_3;
1058 gralloc4::decodeCta861_3(vec, &cta861_3);
1059 if (cta861_3) {
1060 (*staticInfo)->maxCll = cta861_3->maxContentLightLevel;
1061 (*staticInfo)->maxFall = cta861_3->maxFrameAverageLightLevel;
1062 } else {
1063 mapperErr = Error4::BAD_VALUE;
1064 }
1065 };
1066 ret = mapper->get(nativeHandle, MetadataType_Cta861_3, cb);
1067 if (!ret.isOk()) {
1068 err = C2_REFUSED;
1069 } else if (mapperErr != Error4::NONE) {
1070 err = C2_CORRUPTED;
1071 }
1072 }
1073 if (dynamicInfo) {
1074 dynamicInfo->reset();
1075 IMapper4::get_cb cb = [&mapperErr, dynamicInfo](Error4 err, const hidl_vec<uint8_t> &vec) {
1076 mapperErr = err;
1077 if (err != Error4::NONE) {
1078 return;
1079 }
1080 if (!dynamicInfo) {
1081 return;
1082 }
1083 *dynamicInfo = C2StreamHdrDynamicMetadataInfo::input::AllocShared(
1084 vec.size(), 0u, C2Config::HDR_DYNAMIC_METADATA_TYPE_SMPTE_2094_40);
1085 memcpy((*dynamicInfo)->m.data, vec.data(), vec.size());
1086 };
1087 Return<void> ret = mapper->get(nativeHandle, MetadataType_Smpte2094_40, cb);
1088 if (!ret.isOk() || mapperErr != Error4::NONE) {
1089 dynamicInfo->reset();
1090 }
1091 }
1092
1093 return err;
1094}
1095
1096c2_status_t SetHdrMetadataToGralloc4Handle(
1097 const std::shared_ptr<const C2StreamHdrStaticMetadataInfo::output> &staticInfo,
1098 const std::shared_ptr<const C2StreamHdrDynamicMetadataInfo::output> &dynamicInfo,
1099 const C2Handle *const handle) {
1100 c2_status_t err = C2_OK;
1101 native_handle_t *nativeHandle = UnwrapNativeCodec2GrallocHandle(handle);
1102 if (nativeHandle == nullptr) {
1103 // Nothing to do
1104 return err;
1105 }
1106 // TRICKY: UnwrapNativeCodec2GrallocHandle creates a new handle but
1107 // does not clone the fds. Thus we need to delete the handle
1108 // without closing it when going out of scope.
1109 NativeHandleDeleter nhd(nativeHandle);
1110 sp<IMapper4> mapper = GetMapper4();
1111 if (!mapper) {
1112 // Gralloc4 not supported; nothing to do
1113 return err;
1114 }
1115 if (staticInfo && *staticInfo) {
1116 std::optional<Smpte2086> smpte2086 = Smpte2086{
1117 {staticInfo->mastering.red.x, staticInfo->mastering.red.y},
1118 {staticInfo->mastering.green.x, staticInfo->mastering.green.y},
1119 {staticInfo->mastering.blue.x, staticInfo->mastering.blue.y},
1120 {staticInfo->mastering.white.x, staticInfo->mastering.white.y},
1121 staticInfo->mastering.maxLuminance,
1122 staticInfo->mastering.minLuminance,
1123 };
1124 hidl_vec<uint8_t> vec;
1125 if (gralloc4::encodeSmpte2086(smpte2086, &vec) == OK) {
1126 Return<Error4> ret = mapper->set(nativeHandle, MetadataType_Smpte2086, vec);
1127 if (!ret.isOk()) {
1128 err = C2_REFUSED;
1129 } else if (ret != Error4::NONE) {
1130 err = C2_CORRUPTED;
1131 }
1132 }
1133 std::optional<Cta861_3> cta861_3 = Cta861_3{
1134 staticInfo->maxCll,
1135 staticInfo->maxFall,
1136 };
1137 if (gralloc4::encodeCta861_3(cta861_3, &vec) == OK) {
1138 Return<Error4> ret = mapper->set(nativeHandle, MetadataType_Cta861_3, vec);
1139 if (!ret.isOk()) {
1140 err = C2_REFUSED;
1141 } else if (ret != Error4::NONE) {
1142 err = C2_CORRUPTED;
1143 }
1144 }
1145 }
1146 if (dynamicInfo && *dynamicInfo) {
1147 hidl_vec<uint8_t> vec;
1148 vec.resize(dynamicInfo->flexCount());
1149 memcpy(vec.data(), dynamicInfo->m.data, dynamicInfo->flexCount());
1150 std::optional<IMapper4::MetadataType> metadataType;
1151 switch (dynamicInfo->m.type_) {
1152 case C2Config::HDR_DYNAMIC_METADATA_TYPE_SMPTE_2094_10:
1153 // TODO
1154 break;
1155 case C2Config::HDR_DYNAMIC_METADATA_TYPE_SMPTE_2094_40:
1156 metadataType = MetadataType_Smpte2094_40;
1157 break;
1158 }
1159 if (metadataType) {
1160 Return<Error4> ret = mapper->set(nativeHandle, *metadataType, vec);
1161 if (!ret.isOk()) {
1162 err = C2_REFUSED;
1163 } else if (ret != Error4::NONE) {
1164 err = C2_CORRUPTED;
1165 }
1166 } else {
1167 err = C2_BAD_VALUE;
1168 }
1169 }
1170
1171 return err;
1172}
1173
Pawin Vongmasa36653902018-11-15 00:10:25 -08001174} // namespace android