blob: b9270dec5b4de2f56d09c9482af21bde17793863 [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"
My Name6bd9a7d2022-03-25 12:37:58 -070019#define ATRACE_TAG ATRACE_TAG_VIDEO
Pawin Vongmasa36653902018-11-15 00:10:25 -080020#include <utils/Log.h>
My Name6bd9a7d2022-03-25 12:37:58 -070021#include <utils/Trace.h>
Pawin Vongmasa36653902018-11-15 00:10:25 -080022
Wonsik Kima79c5522022-01-18 16:29:24 -080023#include <aidl/android/hardware/graphics/common/Cta861_3.h>
24#include <aidl/android/hardware/graphics/common/Smpte2086.h>
bohua222c0b2021-01-12 18:54:53 -080025#include <android-base/properties.h>
Wonsik Kim41d83432020-04-27 16:40:49 -070026#include <android/hardware/cas/native/1.0/types.h>
27#include <android/hardware/drm/1.0/types.h>
Wonsik Kima79c5522022-01-18 16:29:24 -080028#include <android/hardware/graphics/common/1.2/types.h>
29#include <android/hardware/graphics/mapper/4.0/IMapper.h>
30#include <gralloctypes/Gralloc4.h>
Pawin Vongmasa36653902018-11-15 00:10:25 -080031#include <hidlmemory/FrameworkUtils.h>
32#include <media/hardware/HardwareAPI.h>
Robert Shih895fba92019-07-16 16:29:44 -070033#include <media/stagefright/CodecBase.h>
Pawin Vongmasa36653902018-11-15 00:10:25 -080034#include <media/stagefright/MediaCodecConstants.h>
35#include <media/stagefright/foundation/ABuffer.h>
36#include <media/stagefright/foundation/AMessage.h>
37#include <media/stagefright/foundation/AUtils.h>
Wonsik Kim41d83432020-04-27 16:40:49 -070038#include <mediadrm/ICrypto.h>
Pawin Vongmasa36653902018-11-15 00:10:25 -080039#include <nativebase/nativebase.h>
Wonsik Kimebe0f9e2019-07-03 11:06:51 -070040#include <ui/Fence.h>
Pawin Vongmasa36653902018-11-15 00:10:25 -080041
42#include <C2AllocatorGralloc.h>
43#include <C2BlockInternal.h>
44#include <C2Debug.h>
45
46#include "Codec2Buffer.h"
47
48namespace android {
49
50// Codec2Buffer
51
52bool Codec2Buffer::canCopyLinear(const std::shared_ptr<C2Buffer> &buffer) const {
53 if (const_cast<Codec2Buffer *>(this)->base() == nullptr) {
54 return false;
55 }
56 if (!buffer) {
57 // Nothing to copy, so we can copy by doing nothing.
58 return true;
59 }
60 if (buffer->data().type() != C2BufferData::LINEAR) {
61 return false;
62 }
63 if (buffer->data().linearBlocks().size() == 0u) {
64 // Nothing to copy, so we can copy by doing nothing.
65 return true;
66 } else if (buffer->data().linearBlocks().size() > 1u) {
67 // We don't know how to copy more than one blocks.
68 return false;
69 }
70 if (buffer->data().linearBlocks()[0].size() > capacity()) {
71 // It won't fit.
72 return false;
73 }
74 return true;
75}
76
77bool Codec2Buffer::copyLinear(const std::shared_ptr<C2Buffer> &buffer) {
78 // We assume that all canCopyLinear() checks passed.
79 if (!buffer || buffer->data().linearBlocks().size() == 0u
80 || buffer->data().linearBlocks()[0].size() == 0u) {
81 setRange(0, 0);
82 return true;
83 }
84 C2ReadView view = buffer->data().linearBlocks()[0].map().get();
85 if (view.error() != C2_OK) {
86 ALOGD("Error while mapping: %d", view.error());
87 return false;
88 }
89 if (view.capacity() > capacity()) {
90 ALOGD("C2ConstLinearBlock lied --- it actually doesn't fit: view(%u) > this(%zu)",
91 view.capacity(), capacity());
92 return false;
93 }
94 memcpy(base(), view.data(), view.capacity());
95 setRange(0, view.capacity());
96 return true;
97}
98
99void Codec2Buffer::setImageData(const sp<ABuffer> &imageData) {
Wonsik Kimc48ddcf2019-02-11 16:16:57 -0800100 mImageData = imageData;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800101}
102
103// LocalLinearBuffer
104
105bool LocalLinearBuffer::canCopy(const std::shared_ptr<C2Buffer> &buffer) const {
106 return canCopyLinear(buffer);
107}
108
109bool LocalLinearBuffer::copy(const std::shared_ptr<C2Buffer> &buffer) {
110 return copyLinear(buffer);
111}
112
113// DummyContainerBuffer
114
Pawin Vongmasa8be93112018-12-11 14:01:42 -0800115static uint8_t sDummyByte[1] = { 0 };
116
Pawin Vongmasa36653902018-11-15 00:10:25 -0800117DummyContainerBuffer::DummyContainerBuffer(
118 const sp<AMessage> &format, const std::shared_ptr<C2Buffer> &buffer)
Pawin Vongmasa8be93112018-12-11 14:01:42 -0800119 : Codec2Buffer(format, new ABuffer(sDummyByte, 1)),
Pawin Vongmasa36653902018-11-15 00:10:25 -0800120 mBufferRef(buffer) {
121 setRange(0, buffer ? 1 : 0);
122}
123
124std::shared_ptr<C2Buffer> DummyContainerBuffer::asC2Buffer() {
Wonsik Kimf9b32122020-04-02 11:30:17 -0700125 return mBufferRef;
126}
127
128void DummyContainerBuffer::clearC2BufferRefs() {
129 mBufferRef.reset();
Pawin Vongmasa36653902018-11-15 00:10:25 -0800130}
131
132bool DummyContainerBuffer::canCopy(const std::shared_ptr<C2Buffer> &) const {
133 return !mBufferRef;
134}
135
136bool DummyContainerBuffer::copy(const std::shared_ptr<C2Buffer> &buffer) {
137 mBufferRef = buffer;
138 setRange(0, mBufferRef ? 1 : 0);
139 return true;
140}
141
142// LinearBlockBuffer
143
144// static
145sp<LinearBlockBuffer> LinearBlockBuffer::Allocate(
146 const sp<AMessage> &format, const std::shared_ptr<C2LinearBlock> &block) {
147 C2WriteView writeView(block->map().get());
148 if (writeView.error() != C2_OK) {
149 return nullptr;
150 }
151 return new LinearBlockBuffer(format, std::move(writeView), block);
152}
153
154std::shared_ptr<C2Buffer> LinearBlockBuffer::asC2Buffer() {
155 return C2Buffer::CreateLinearBuffer(mBlock->share(offset(), size(), C2Fence()));
156}
157
158bool LinearBlockBuffer::canCopy(const std::shared_ptr<C2Buffer> &buffer) const {
159 return canCopyLinear(buffer);
160}
161
162bool LinearBlockBuffer::copy(const std::shared_ptr<C2Buffer> &buffer) {
163 return copyLinear(buffer);
164}
165
166LinearBlockBuffer::LinearBlockBuffer(
167 const sp<AMessage> &format,
168 C2WriteView&& writeView,
169 const std::shared_ptr<C2LinearBlock> &block)
170 : Codec2Buffer(format, new ABuffer(writeView.data(), writeView.size())),
171 mWriteView(writeView),
172 mBlock(block) {
173}
174
175// ConstLinearBlockBuffer
176
177// static
178sp<ConstLinearBlockBuffer> ConstLinearBlockBuffer::Allocate(
179 const sp<AMessage> &format, const std::shared_ptr<C2Buffer> &buffer) {
180 if (!buffer
181 || buffer->data().type() != C2BufferData::LINEAR
182 || buffer->data().linearBlocks().size() != 1u) {
183 return nullptr;
184 }
185 C2ReadView readView(buffer->data().linearBlocks()[0].map().get());
186 if (readView.error() != C2_OK) {
187 return nullptr;
188 }
189 return new ConstLinearBlockBuffer(format, std::move(readView), buffer);
190}
191
192ConstLinearBlockBuffer::ConstLinearBlockBuffer(
193 const sp<AMessage> &format,
194 C2ReadView&& readView,
195 const std::shared_ptr<C2Buffer> &buffer)
196 : Codec2Buffer(format, new ABuffer(
197 // NOTE: ABuffer only takes non-const pointer but this data is
198 // supposed to be read-only.
199 const_cast<uint8_t *>(readView.data()), readView.capacity())),
200 mReadView(readView),
201 mBufferRef(buffer) {
202}
203
204std::shared_ptr<C2Buffer> ConstLinearBlockBuffer::asC2Buffer() {
Wonsik Kimf9b32122020-04-02 11:30:17 -0700205 return mBufferRef;
206}
207
208void ConstLinearBlockBuffer::clearC2BufferRefs() {
209 mBufferRef.reset();
Pawin Vongmasa36653902018-11-15 00:10:25 -0800210}
211
212// GraphicView2MediaImageConverter
213
214namespace {
215
216class GraphicView2MediaImageConverter {
217public:
218 /**
219 * Creates a C2GraphicView <=> MediaImage converter
220 *
221 * \param view C2GraphicView object
Wonsik Kimd79ee1f2020-08-27 17:41:56 -0700222 * \param format buffer format
Wonsik Kim7d966312019-06-04 14:00:49 -0700223 * \param copy whether the converter is used for copy or not
Pawin Vongmasa36653902018-11-15 00:10:25 -0800224 */
225 GraphicView2MediaImageConverter(
Wonsik Kimd79ee1f2020-08-27 17:41:56 -0700226 const C2GraphicView &view, const sp<AMessage> &format, bool copy)
Pawin Vongmasa36653902018-11-15 00:10:25 -0800227 : mInitCheck(NO_INIT),
228 mView(view),
229 mWidth(view.width()),
230 mHeight(view.height()),
Pawin Vongmasa36653902018-11-15 00:10:25 -0800231 mAllocatedDepth(0),
232 mBackBufferSize(0),
233 mMediaImage(new ABuffer(sizeof(MediaImage2))) {
My Name6bd9a7d2022-03-25 12:37:58 -0700234 ATRACE_CALL();
Wonsik Kimd79ee1f2020-08-27 17:41:56 -0700235 if (!format->findInt32(KEY_COLOR_FORMAT, &mClientColorFormat)) {
236 mClientColorFormat = COLOR_FormatYUV420Flexible;
237 }
238 if (!format->findInt32("android._color-format", &mComponentColorFormat)) {
239 mComponentColorFormat = COLOR_FormatYUV420Flexible;
240 }
Pawin Vongmasa36653902018-11-15 00:10:25 -0800241 if (view.error() != C2_OK) {
242 ALOGD("Converter: view.error() = %d", view.error());
243 mInitCheck = BAD_VALUE;
244 return;
245 }
246 MediaImage2 *mediaImage = (MediaImage2 *)mMediaImage->base();
247 const C2PlanarLayout &layout = view.layout();
248 if (layout.numPlanes == 0) {
249 ALOGD("Converter: 0 planes");
250 mInitCheck = BAD_VALUE;
251 return;
252 }
Harish Mahendrakarcac53852019-02-20 10:59:10 -0800253 memset(mediaImage, 0, sizeof(*mediaImage));
Pawin Vongmasa36653902018-11-15 00:10:25 -0800254 mAllocatedDepth = layout.planes[0].allocatedDepth;
255 uint32_t bitDepth = layout.planes[0].bitDepth;
256
257 // align width and height to support subsampling cleanly
Wonsik Kim8bfa17a2019-05-30 22:12:30 -0700258 uint32_t stride = align(view.crop().width, 2) * divUp(layout.planes[0].allocatedDepth, 8u);
259 uint32_t vStride = align(view.crop().height, 2);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800260
Wonsik Kimd79ee1f2020-08-27 17:41:56 -0700261 bool tryWrapping = !copy;
262
Pawin Vongmasa36653902018-11-15 00:10:25 -0800263 switch (layout.type) {
Wonsik Kimd79ee1f2020-08-27 17:41:56 -0700264 case C2PlanarLayout::TYPE_YUV: {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800265 mediaImage->mType = MediaImage2::MEDIA_IMAGE_TYPE_YUV;
266 if (layout.numPlanes != 3) {
267 ALOGD("Converter: %d planes for YUV layout", layout.numPlanes);
268 mInitCheck = BAD_VALUE;
269 return;
270 }
Arun Johnson3ab32cd2022-06-10 18:58:01 +0000271 std::optional<int> clientBitDepth = {};
272 switch (mClientColorFormat) {
273 case COLOR_FormatYUVP010:
274 clientBitDepth = 10;
275 break;
276 case COLOR_FormatYUV411PackedPlanar:
277 case COLOR_FormatYUV411Planar:
278 case COLOR_FormatYUV420Flexible:
279 case COLOR_FormatYUV420PackedPlanar:
280 case COLOR_FormatYUV420PackedSemiPlanar:
281 case COLOR_FormatYUV420Planar:
282 case COLOR_FormatYUV420SemiPlanar:
283 case COLOR_FormatYUV422Flexible:
284 case COLOR_FormatYUV422PackedPlanar:
285 case COLOR_FormatYUV422PackedSemiPlanar:
286 case COLOR_FormatYUV422Planar:
287 case COLOR_FormatYUV422SemiPlanar:
288 case COLOR_FormatYUV444Flexible:
289 case COLOR_FormatYUV444Interleaved:
290 clientBitDepth = 8;
291 break;
292 default:
293 // no-op; used with optional
294 break;
295
296 }
297 // conversion fails if client bit-depth and the component bit-depth differs
298 if ((clientBitDepth) && (bitDepth != clientBitDepth.value())) {
299 ALOGD("Bit depth of client: %d and component: %d differs",
300 *clientBitDepth, bitDepth);
301 mInitCheck = BAD_VALUE;
302 return;
303 }
Wonsik Kimd79ee1f2020-08-27 17:41:56 -0700304 C2PlaneInfo yPlane = layout.planes[C2PlanarLayout::PLANE_Y];
305 C2PlaneInfo uPlane = layout.planes[C2PlanarLayout::PLANE_U];
306 C2PlaneInfo vPlane = layout.planes[C2PlanarLayout::PLANE_V];
307 if (yPlane.channel != C2PlaneInfo::CHANNEL_Y
308 || uPlane.channel != C2PlaneInfo::CHANNEL_CB
309 || vPlane.channel != C2PlaneInfo::CHANNEL_CR) {
310 ALOGD("Converter: not YUV layout");
Pawin Vongmasa36653902018-11-15 00:10:25 -0800311 mInitCheck = BAD_VALUE;
312 return;
313 }
Wonsik Kimd79ee1f2020-08-27 17:41:56 -0700314 bool yuv420888 = yPlane.rowSampling == 1 && yPlane.colSampling == 1
315 && uPlane.rowSampling == 2 && uPlane.colSampling == 2
316 && vPlane.rowSampling == 2 && vPlane.colSampling == 2;
317 if (yuv420888) {
318 for (uint32_t i = 0; i < 3; ++i) {
319 const C2PlaneInfo &plane = layout.planes[i];
320 if (plane.allocatedDepth != 8 || plane.bitDepth != 8) {
321 yuv420888 = false;
322 break;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800323 }
Wonsik Kimd79ee1f2020-08-27 17:41:56 -0700324 }
325 yuv420888 = yuv420888 && yPlane.colInc == 1 && uPlane.rowInc == vPlane.rowInc;
326 }
327 int32_t copyFormat = mClientColorFormat;
328 if (yuv420888 && mClientColorFormat == COLOR_FormatYUV420Flexible) {
329 if (uPlane.colInc == 2 && vPlane.colInc == 2
330 && yPlane.rowInc == uPlane.rowInc) {
331 copyFormat = COLOR_FormatYUV420PackedSemiPlanar;
332 } else if (uPlane.colInc == 1 && vPlane.colInc == 1
333 && yPlane.rowInc == uPlane.rowInc * 2) {
334 copyFormat = COLOR_FormatYUV420PackedPlanar;
335 }
336 }
337 ALOGV("client_fmt=0x%x y:{colInc=%d rowInc=%d} u:{colInc=%d rowInc=%d} "
338 "v:{colInc=%d rowInc=%d}",
339 mClientColorFormat,
340 yPlane.colInc, yPlane.rowInc,
341 uPlane.colInc, uPlane.rowInc,
342 vPlane.colInc, vPlane.rowInc);
343 switch (copyFormat) {
344 case COLOR_FormatYUV420Flexible:
Pawin Vongmasa36653902018-11-15 00:10:25 -0800345 case COLOR_FormatYUV420Planar:
346 case COLOR_FormatYUV420PackedPlanar:
347 mediaImage->mPlane[mediaImage->Y].mOffset = 0;
348 mediaImage->mPlane[mediaImage->Y].mColInc = 1;
Wonsik Kim8bfa17a2019-05-30 22:12:30 -0700349 mediaImage->mPlane[mediaImage->Y].mRowInc = stride;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800350 mediaImage->mPlane[mediaImage->Y].mHorizSubsampling = 1;
351 mediaImage->mPlane[mediaImage->Y].mVertSubsampling = 1;
352
Wonsik Kim8bfa17a2019-05-30 22:12:30 -0700353 mediaImage->mPlane[mediaImage->U].mOffset = stride * vStride;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800354 mediaImage->mPlane[mediaImage->U].mColInc = 1;
Wonsik Kim8bfa17a2019-05-30 22:12:30 -0700355 mediaImage->mPlane[mediaImage->U].mRowInc = stride / 2;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800356 mediaImage->mPlane[mediaImage->U].mHorizSubsampling = 2;
357 mediaImage->mPlane[mediaImage->U].mVertSubsampling = 2;
358
Wonsik Kim8bfa17a2019-05-30 22:12:30 -0700359 mediaImage->mPlane[mediaImage->V].mOffset = stride * vStride * 5 / 4;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800360 mediaImage->mPlane[mediaImage->V].mColInc = 1;
Wonsik Kim8bfa17a2019-05-30 22:12:30 -0700361 mediaImage->mPlane[mediaImage->V].mRowInc = stride / 2;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800362 mediaImage->mPlane[mediaImage->V].mHorizSubsampling = 2;
363 mediaImage->mPlane[mediaImage->V].mVertSubsampling = 2;
Wonsik Kimd79ee1f2020-08-27 17:41:56 -0700364
365 if (tryWrapping && mClientColorFormat != COLOR_FormatYUV420Flexible) {
366 tryWrapping = yuv420888 && uPlane.colInc == 1 && vPlane.colInc == 1
367 && yPlane.rowInc == uPlane.rowInc * 2
368 && view.data()[0] < view.data()[1]
369 && view.data()[1] < view.data()[2];
370 }
Pawin Vongmasa36653902018-11-15 00:10:25 -0800371 break;
372
373 case COLOR_FormatYUV420SemiPlanar:
374 case COLOR_FormatYUV420PackedSemiPlanar:
375 mediaImage->mPlane[mediaImage->Y].mOffset = 0;
376 mediaImage->mPlane[mediaImage->Y].mColInc = 1;
Wonsik Kim8bfa17a2019-05-30 22:12:30 -0700377 mediaImage->mPlane[mediaImage->Y].mRowInc = stride;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800378 mediaImage->mPlane[mediaImage->Y].mHorizSubsampling = 1;
379 mediaImage->mPlane[mediaImage->Y].mVertSubsampling = 1;
380
Wonsik Kim8bfa17a2019-05-30 22:12:30 -0700381 mediaImage->mPlane[mediaImage->U].mOffset = stride * vStride;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800382 mediaImage->mPlane[mediaImage->U].mColInc = 2;
Wonsik Kim8bfa17a2019-05-30 22:12:30 -0700383 mediaImage->mPlane[mediaImage->U].mRowInc = stride;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800384 mediaImage->mPlane[mediaImage->U].mHorizSubsampling = 2;
385 mediaImage->mPlane[mediaImage->U].mVertSubsampling = 2;
386
Wonsik Kim8bfa17a2019-05-30 22:12:30 -0700387 mediaImage->mPlane[mediaImage->V].mOffset = stride * vStride + 1;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800388 mediaImage->mPlane[mediaImage->V].mColInc = 2;
Wonsik Kim8bfa17a2019-05-30 22:12:30 -0700389 mediaImage->mPlane[mediaImage->V].mRowInc = stride;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800390 mediaImage->mPlane[mediaImage->V].mHorizSubsampling = 2;
391 mediaImage->mPlane[mediaImage->V].mVertSubsampling = 2;
Wonsik Kimd79ee1f2020-08-27 17:41:56 -0700392
393 if (tryWrapping && mClientColorFormat != COLOR_FormatYUV420Flexible) {
394 tryWrapping = yuv420888 && uPlane.colInc == 2 && vPlane.colInc == 2
395 && yPlane.rowInc == uPlane.rowInc
396 && view.data()[0] < view.data()[1]
397 && view.data()[1] < view.data()[2];
398 }
Pawin Vongmasa36653902018-11-15 00:10:25 -0800399 break;
400
Wonsik Kim29e3c4d2020-09-02 12:19:44 -0700401 case COLOR_FormatYUVP010:
Wonsik Kim08a8a2b2021-05-10 19:03:47 -0700402 // stride is in bytes
Wonsik Kim29e3c4d2020-09-02 12:19:44 -0700403 mediaImage->mPlane[mediaImage->Y].mOffset = 0;
404 mediaImage->mPlane[mediaImage->Y].mColInc = 2;
Wonsik Kim08a8a2b2021-05-10 19:03:47 -0700405 mediaImage->mPlane[mediaImage->Y].mRowInc = stride;
Wonsik Kim29e3c4d2020-09-02 12:19:44 -0700406 mediaImage->mPlane[mediaImage->Y].mHorizSubsampling = 1;
407 mediaImage->mPlane[mediaImage->Y].mVertSubsampling = 1;
408
Wonsik Kim08a8a2b2021-05-10 19:03:47 -0700409 mediaImage->mPlane[mediaImage->U].mOffset = stride * vStride;
Wonsik Kim29e3c4d2020-09-02 12:19:44 -0700410 mediaImage->mPlane[mediaImage->U].mColInc = 4;
Wonsik Kim08a8a2b2021-05-10 19:03:47 -0700411 mediaImage->mPlane[mediaImage->U].mRowInc = stride;
Wonsik Kim29e3c4d2020-09-02 12:19:44 -0700412 mediaImage->mPlane[mediaImage->U].mHorizSubsampling = 2;
413 mediaImage->mPlane[mediaImage->U].mVertSubsampling = 2;
414
Wonsik Kim08a8a2b2021-05-10 19:03:47 -0700415 mediaImage->mPlane[mediaImage->V].mOffset = stride * vStride + 2;
Wonsik Kim29e3c4d2020-09-02 12:19:44 -0700416 mediaImage->mPlane[mediaImage->V].mColInc = 4;
Wonsik Kim08a8a2b2021-05-10 19:03:47 -0700417 mediaImage->mPlane[mediaImage->V].mRowInc = stride;
Wonsik Kim29e3c4d2020-09-02 12:19:44 -0700418 mediaImage->mPlane[mediaImage->V].mHorizSubsampling = 2;
419 mediaImage->mPlane[mediaImage->V].mVertSubsampling = 2;
Wonsik Kimd79ee1f2020-08-27 17:41:56 -0700420 if (tryWrapping) {
421 tryWrapping = yPlane.allocatedDepth == 16
422 && uPlane.allocatedDepth == 16
423 && vPlane.allocatedDepth == 16
424 && yPlane.bitDepth == 10
425 && uPlane.bitDepth == 10
426 && vPlane.bitDepth == 10
427 && yPlane.rightShift == 6
428 && uPlane.rightShift == 6
429 && vPlane.rightShift == 6
430 && yPlane.rowSampling == 1 && yPlane.colSampling == 1
431 && uPlane.rowSampling == 2 && uPlane.colSampling == 2
432 && vPlane.rowSampling == 2 && vPlane.colSampling == 2
433 && yPlane.colInc == 2
434 && uPlane.colInc == 4
435 && vPlane.colInc == 4
436 && yPlane.rowInc == uPlane.rowInc
437 && yPlane.rowInc == vPlane.rowInc;
438 }
Wonsik Kim29e3c4d2020-09-02 12:19:44 -0700439 break;
440
Wonsik Kimd79ee1f2020-08-27 17:41:56 -0700441 default: {
442 // default to fully planar format --- this will be overridden if wrapping
443 // TODO: keep interleaved format
444 int32_t colInc = divUp(mAllocatedDepth, 8u);
445 int32_t rowInc = stride * colInc / yPlane.colSampling;
446 mediaImage->mPlane[mediaImage->Y].mOffset = 0;
447 mediaImage->mPlane[mediaImage->Y].mColInc = colInc;
448 mediaImage->mPlane[mediaImage->Y].mRowInc = rowInc;
449 mediaImage->mPlane[mediaImage->Y].mHorizSubsampling = yPlane.colSampling;
450 mediaImage->mPlane[mediaImage->Y].mVertSubsampling = yPlane.rowSampling;
451 int32_t offset = rowInc * vStride / yPlane.rowSampling;
452
453 rowInc = stride * colInc / uPlane.colSampling;
454 mediaImage->mPlane[mediaImage->U].mOffset = offset;
455 mediaImage->mPlane[mediaImage->U].mColInc = colInc;
456 mediaImage->mPlane[mediaImage->U].mRowInc = rowInc;
457 mediaImage->mPlane[mediaImage->U].mHorizSubsampling = uPlane.colSampling;
458 mediaImage->mPlane[mediaImage->U].mVertSubsampling = uPlane.rowSampling;
459 offset += rowInc * vStride / uPlane.rowSampling;
460
461 rowInc = stride * colInc / vPlane.colSampling;
462 mediaImage->mPlane[mediaImage->V].mOffset = offset;
463 mediaImage->mPlane[mediaImage->V].mColInc = colInc;
464 mediaImage->mPlane[mediaImage->V].mRowInc = rowInc;
465 mediaImage->mPlane[mediaImage->V].mHorizSubsampling = vPlane.colSampling;
466 mediaImage->mPlane[mediaImage->V].mVertSubsampling = vPlane.rowSampling;
467 break;
468 }
Pawin Vongmasa36653902018-11-15 00:10:25 -0800469 }
470 break;
Wonsik Kimd79ee1f2020-08-27 17:41:56 -0700471 }
472
Pawin Vongmasa36653902018-11-15 00:10:25 -0800473 case C2PlanarLayout::TYPE_YUVA:
Wonsik Kimd79ee1f2020-08-27 17:41:56 -0700474 ALOGD("Converter: unrecognized color format "
475 "(client %d component %d) for YUVA layout",
476 mClientColorFormat, mComponentColorFormat);
477 mInitCheck = NO_INIT;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800478 return;
479 case C2PlanarLayout::TYPE_RGB:
Wonsik Kimd79ee1f2020-08-27 17:41:56 -0700480 ALOGD("Converter: unrecognized color format "
481 "(client %d component %d) for RGB layout",
482 mClientColorFormat, mComponentColorFormat);
483 mInitCheck = NO_INIT;
484 // TODO: support MediaImage layout
485 return;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800486 case C2PlanarLayout::TYPE_RGBA:
Wonsik Kimd79ee1f2020-08-27 17:41:56 -0700487 ALOGD("Converter: unrecognized color format "
488 "(client %d component %d) for RGBA layout",
489 mClientColorFormat, mComponentColorFormat);
490 mInitCheck = NO_INIT;
491 // TODO: support MediaImage layout
492 return;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800493 default:
494 mediaImage->mType = MediaImage2::MEDIA_IMAGE_TYPE_UNKNOWN;
Wonsik Kimd79ee1f2020-08-27 17:41:56 -0700495 if (layout.numPlanes == 1) {
496 const C2PlaneInfo &plane = layout.planes[0];
497 if (plane.colInc < 0 || plane.rowInc < 0) {
498 // Copy-only if we have negative colInc/rowInc
499 tryWrapping = false;
500 }
501 mediaImage->mPlane[0].mOffset = 0;
502 mediaImage->mPlane[0].mColInc = std::abs(plane.colInc);
503 mediaImage->mPlane[0].mRowInc = std::abs(plane.rowInc);
504 mediaImage->mPlane[0].mHorizSubsampling = plane.colSampling;
505 mediaImage->mPlane[0].mVertSubsampling = plane.rowSampling;
506 } else {
507 ALOGD("Converter: unrecognized layout: color format (client %d component %d)",
508 mClientColorFormat, mComponentColorFormat);
509 mInitCheck = NO_INIT;
510 return;
511 }
512 break;
513 }
514 if (tryWrapping) {
515 // try to map directly. check if the planes are near one another
516 const uint8_t *minPtr = mView.data()[0];
517 const uint8_t *maxPtr = mView.data()[0];
518 int32_t planeSize = 0;
519 for (uint32_t i = 0; i < layout.numPlanes; ++i) {
520 const C2PlaneInfo &plane = layout.planes[i];
521 int64_t planeStride = std::abs(plane.rowInc / plane.colInc);
522 ssize_t minOffset = plane.minOffset(
523 mWidth / plane.colSampling, mHeight / plane.rowSampling);
524 ssize_t maxOffset = plane.maxOffset(
525 mWidth / plane.colSampling, mHeight / plane.rowSampling);
526 if (minPtr > mView.data()[i] + minOffset) {
527 minPtr = mView.data()[i] + minOffset;
528 }
529 if (maxPtr < mView.data()[i] + maxOffset) {
530 maxPtr = mView.data()[i] + maxOffset;
531 }
532 planeSize += planeStride * divUp(mAllocatedDepth, 8u)
533 * align(mHeight, 64) / plane.rowSampling;
534 }
535
Wonsik Kim1bf84162022-09-20 11:00:42 -0700536 if (minPtr == mView.data()[0] && (maxPtr - minPtr) <= planeSize) {
Wonsik Kimd79ee1f2020-08-27 17:41:56 -0700537 // FIXME: this is risky as reading/writing data out of bound results
538 // in an undefined behavior, but gralloc does assume a
539 // contiguous mapping
540 for (uint32_t i = 0; i < layout.numPlanes; ++i) {
541 const C2PlaneInfo &plane = layout.planes[i];
542 mediaImage->mPlane[i].mOffset = mView.data()[i] - minPtr;
543 mediaImage->mPlane[i].mColInc = plane.colInc;
544 mediaImage->mPlane[i].mRowInc = plane.rowInc;
545 mediaImage->mPlane[i].mHorizSubsampling = plane.colSampling;
546 mediaImage->mPlane[i].mVertSubsampling = plane.rowSampling;
547 }
Wonsik Kim1bf84162022-09-20 11:00:42 -0700548 mWrapped = new ABuffer(const_cast<uint8_t *>(minPtr), maxPtr - minPtr);
Wonsik Kimd79ee1f2020-08-27 17:41:56 -0700549 ALOGV("Converter: wrapped (capacity=%zu)", mWrapped->capacity());
550 }
Pawin Vongmasa36653902018-11-15 00:10:25 -0800551 }
552 mediaImage->mNumPlanes = layout.numPlanes;
Harish Mahendrakarf7c49e22019-05-24 14:19:16 -0700553 mediaImage->mWidth = view.crop().width;
554 mediaImage->mHeight = view.crop().height;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800555 mediaImage->mBitDepth = bitDepth;
556 mediaImage->mBitDepthAllocated = mAllocatedDepth;
557
558 uint32_t bufferSize = 0;
559 for (uint32_t i = 0; i < layout.numPlanes; ++i) {
560 const C2PlaneInfo &plane = layout.planes[i];
561 if (plane.allocatedDepth < plane.bitDepth
562 || plane.rightShift != plane.allocatedDepth - plane.bitDepth) {
563 ALOGD("rightShift value of %u unsupported", plane.rightShift);
564 mInitCheck = BAD_VALUE;
565 return;
566 }
567 if (plane.allocatedDepth > 8 && plane.endianness != C2PlaneInfo::NATIVE) {
568 ALOGD("endianness value of %u unsupported", plane.endianness);
569 mInitCheck = BAD_VALUE;
570 return;
571 }
572 if (plane.allocatedDepth != mAllocatedDepth || plane.bitDepth != bitDepth) {
Wonsik Kimd79ee1f2020-08-27 17:41:56 -0700573 ALOGD("different allocatedDepth/bitDepth per plane unsupported");
Pawin Vongmasa36653902018-11-15 00:10:25 -0800574 mInitCheck = BAD_VALUE;
575 return;
576 }
Wonsik Kim08a8a2b2021-05-10 19:03:47 -0700577 // stride is in bytes
578 bufferSize += stride * vStride / plane.rowSampling / plane.colSampling;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800579 }
580
581 mBackBufferSize = bufferSize;
582 mInitCheck = OK;
583 }
584
585 status_t initCheck() const { return mInitCheck; }
586
587 uint32_t backBufferSize() const { return mBackBufferSize; }
588
589 /**
590 * Wrap C2GraphicView using a MediaImage2. Note that if not wrapped, the content is not mapped
591 * in this function --- the caller should use CopyGraphicView2MediaImage() function to copy the
592 * data into a backing buffer explicitly.
593 *
594 * \return media buffer. This is null if wrapping failed.
595 */
596 sp<ABuffer> wrap() const {
597 if (mBackBuffer == nullptr) {
598 return mWrapped;
599 }
600 return nullptr;
601 }
602
603 bool setBackBuffer(const sp<ABuffer> &backBuffer) {
Wonsik Kim186fdbf2019-01-29 13:30:01 -0800604 if (backBuffer == nullptr) {
605 return false;
606 }
Pawin Vongmasa36653902018-11-15 00:10:25 -0800607 if (backBuffer->capacity() < mBackBufferSize) {
608 return false;
609 }
610 backBuffer->setRange(0, mBackBufferSize);
611 mBackBuffer = backBuffer;
612 return true;
613 }
614
615 /**
616 * Copy C2GraphicView to MediaImage2.
617 */
618 status_t copyToMediaImage() {
My Name6bd9a7d2022-03-25 12:37:58 -0700619 ATRACE_CALL();
Pawin Vongmasa36653902018-11-15 00:10:25 -0800620 if (mInitCheck != OK) {
621 return mInitCheck;
622 }
623 return ImageCopy(mBackBuffer->base(), getMediaImage(), mView);
624 }
625
626 const sp<ABuffer> &imageData() const { return mMediaImage; }
627
628private:
629 status_t mInitCheck;
630
631 const C2GraphicView mView;
632 uint32_t mWidth;
633 uint32_t mHeight;
Wonsik Kimd79ee1f2020-08-27 17:41:56 -0700634 int32_t mClientColorFormat; ///< SDK color format for MediaImage
635 int32_t mComponentColorFormat; ///< SDK color format from component
Pawin Vongmasa36653902018-11-15 00:10:25 -0800636 sp<ABuffer> mWrapped; ///< wrapped buffer (if we can map C2Buffer to an ABuffer)
637 uint32_t mAllocatedDepth;
638 uint32_t mBackBufferSize;
639 sp<ABuffer> mMediaImage;
640 std::function<sp<ABuffer>(size_t)> mAlloc;
641
642 sp<ABuffer> mBackBuffer; ///< backing buffer if we have to copy C2Buffer <=> ABuffer
643
644 MediaImage2 *getMediaImage() {
645 return (MediaImage2 *)mMediaImage->base();
646 }
647};
648
649} // namespace
650
651// GraphicBlockBuffer
652
653// static
654sp<GraphicBlockBuffer> GraphicBlockBuffer::Allocate(
655 const sp<AMessage> &format,
656 const std::shared_ptr<C2GraphicBlock> &block,
657 std::function<sp<ABuffer>(size_t)> alloc) {
My Name6bd9a7d2022-03-25 12:37:58 -0700658 ATRACE_BEGIN("GraphicBlockBuffer::Allocate block->map()");
Pawin Vongmasa36653902018-11-15 00:10:25 -0800659 C2GraphicView view(block->map().get());
My Name6bd9a7d2022-03-25 12:37:58 -0700660 ATRACE_END();
Pawin Vongmasa36653902018-11-15 00:10:25 -0800661 if (view.error() != C2_OK) {
662 ALOGD("C2GraphicBlock::map failed: %d", view.error());
663 return nullptr;
664 }
665
Wonsik Kimd79ee1f2020-08-27 17:41:56 -0700666 GraphicView2MediaImageConverter converter(view, format, false /* copy */);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800667 if (converter.initCheck() != OK) {
668 ALOGD("Converter init failed: %d", converter.initCheck());
669 return nullptr;
670 }
671 bool wrapped = true;
672 sp<ABuffer> buffer = converter.wrap();
673 if (buffer == nullptr) {
674 buffer = alloc(converter.backBufferSize());
675 if (!converter.setBackBuffer(buffer)) {
676 ALOGD("Converter failed to set back buffer");
677 return nullptr;
678 }
679 wrapped = false;
680 }
681 return new GraphicBlockBuffer(
682 format,
683 buffer,
684 std::move(view),
685 block,
686 converter.imageData(),
687 wrapped);
688}
689
690GraphicBlockBuffer::GraphicBlockBuffer(
691 const sp<AMessage> &format,
692 const sp<ABuffer> &buffer,
693 C2GraphicView &&view,
694 const std::shared_ptr<C2GraphicBlock> &block,
695 const sp<ABuffer> &imageData,
696 bool wrapped)
697 : Codec2Buffer(format, buffer),
698 mView(view),
699 mBlock(block),
Pawin Vongmasa36653902018-11-15 00:10:25 -0800700 mWrapped(wrapped) {
701 setImageData(imageData);
702}
703
704std::shared_ptr<C2Buffer> GraphicBlockBuffer::asC2Buffer() {
My Name6bd9a7d2022-03-25 12:37:58 -0700705 ATRACE_CALL();
Pawin Vongmasa36653902018-11-15 00:10:25 -0800706 uint32_t width = mView.width();
707 uint32_t height = mView.height();
708 if (!mWrapped) {
709 (void)ImageCopy(mView, base(), imageData());
710 }
711 return C2Buffer::CreateGraphicBuffer(
712 mBlock->share(C2Rect(width, height), C2Fence()));
713}
714
715// GraphicMetadataBuffer
716GraphicMetadataBuffer::GraphicMetadataBuffer(
717 const sp<AMessage> &format,
718 const std::shared_ptr<C2Allocator> &alloc)
719 : Codec2Buffer(format, new ABuffer(sizeof(VideoNativeMetadata))),
720 mAlloc(alloc) {
721 ((VideoNativeMetadata *)base())->pBuffer = nullptr;
722}
723
724std::shared_ptr<C2Buffer> GraphicMetadataBuffer::asC2Buffer() {
bohua222c0b2021-01-12 18:54:53 -0800725#ifdef __LP64__
726 static std::once_flag s_checkOnce;
Harish Mahendrakar731e9142021-04-21 17:20:39 -0700727 static bool s_is64bitOk {true};
bohua222c0b2021-01-12 18:54:53 -0800728 std::call_once(s_checkOnce, [&](){
729 const std::string abi32list =
730 ::android::base::GetProperty("ro.product.cpu.abilist32", "");
Harish Mahendrakar731e9142021-04-21 17:20:39 -0700731 if (!abi32list.empty()) {
732 int32_t inputSurfaceSetting =
733 ::android::base::GetIntProperty("debug.stagefright.c2inputsurface", int32_t(0));
734 s_is64bitOk = inputSurfaceSetting != 0;
bohua222c0b2021-01-12 18:54:53 -0800735 }
736 });
737
Harish Mahendrakar731e9142021-04-21 17:20:39 -0700738 if (!s_is64bitOk) {
739 ALOGE("GraphicMetadataBuffer does not work in 32+64 system if compiled as 64-bit object"\
740 "when debug.stagefright.c2inputsurface is set to 0");
bohua222c0b2021-01-12 18:54:53 -0800741 return nullptr;
742 }
743#endif
744
Pawin Vongmasa36653902018-11-15 00:10:25 -0800745 VideoNativeMetadata *meta = (VideoNativeMetadata *)base();
746 ANativeWindowBuffer *buffer = (ANativeWindowBuffer *)meta->pBuffer;
747 if (buffer == nullptr) {
748 ALOGD("VideoNativeMetadata contains null buffer");
749 return nullptr;
750 }
751
752 ALOGV("VideoNativeMetadata: %dx%d", buffer->width, buffer->height);
753 C2Handle *handle = WrapNativeCodec2GrallocHandle(
Sungtak Leea4d13be2019-01-23 15:24:46 -0800754 buffer->handle,
Pawin Vongmasa36653902018-11-15 00:10:25 -0800755 buffer->width,
756 buffer->height,
757 buffer->format,
758 buffer->usage,
759 buffer->stride);
760 std::shared_ptr<C2GraphicAllocation> alloc;
761 c2_status_t err = mAlloc->priorGraphicAllocation(handle, &alloc);
762 if (err != C2_OK) {
763 ALOGD("Failed to wrap VideoNativeMetadata into C2GraphicAllocation");
Chih-Yu Huangc0ac3552021-03-11 14:37:10 +0900764 native_handle_close(handle);
765 native_handle_delete(handle);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800766 return nullptr;
767 }
768 std::shared_ptr<C2GraphicBlock> block = _C2BlockFactory::CreateGraphicBlock(alloc);
769
770 meta->pBuffer = 0;
Wonsik Kimebe0f9e2019-07-03 11:06:51 -0700771 // TODO: wrap this in C2Fence so that the component can wait when it
772 // actually starts processing.
773 if (meta->nFenceFd >= 0) {
774 sp<Fence> fence(new Fence(meta->nFenceFd));
775 fence->waitForever(LOG_TAG);
776 }
Pawin Vongmasa36653902018-11-15 00:10:25 -0800777 return C2Buffer::CreateGraphicBuffer(
778 block->share(C2Rect(buffer->width, buffer->height), C2Fence()));
Pawin Vongmasa36653902018-11-15 00:10:25 -0800779}
780
781// ConstGraphicBlockBuffer
782
783// static
784sp<ConstGraphicBlockBuffer> ConstGraphicBlockBuffer::Allocate(
785 const sp<AMessage> &format,
786 const std::shared_ptr<C2Buffer> &buffer,
787 std::function<sp<ABuffer>(size_t)> alloc) {
788 if (!buffer
789 || buffer->data().type() != C2BufferData::GRAPHIC
790 || buffer->data().graphicBlocks().size() != 1u) {
791 ALOGD("C2Buffer precond fail");
792 return nullptr;
793 }
My Name6bd9a7d2022-03-25 12:37:58 -0700794 ATRACE_BEGIN("ConstGraphicBlockBuffer::Allocate block->map()");
Pawin Vongmasa36653902018-11-15 00:10:25 -0800795 std::unique_ptr<const C2GraphicView> view(std::make_unique<const C2GraphicView>(
796 buffer->data().graphicBlocks()[0].map().get()));
My Name6bd9a7d2022-03-25 12:37:58 -0700797 ATRACE_END();
Pawin Vongmasa36653902018-11-15 00:10:25 -0800798 std::unique_ptr<const C2GraphicView> holder;
799
Wonsik Kimd79ee1f2020-08-27 17:41:56 -0700800 GraphicView2MediaImageConverter converter(*view, format, false /* copy */);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800801 if (converter.initCheck() != OK) {
802 ALOGD("Converter init failed: %d", converter.initCheck());
803 return nullptr;
804 }
805 bool wrapped = true;
806 sp<ABuffer> aBuffer = converter.wrap();
807 if (aBuffer == nullptr) {
808 aBuffer = alloc(converter.backBufferSize());
809 if (!converter.setBackBuffer(aBuffer)) {
810 ALOGD("Converter failed to set back buffer");
811 return nullptr;
812 }
813 wrapped = false;
814 converter.copyToMediaImage();
815 // We don't need the view.
816 holder = std::move(view);
817 }
818 return new ConstGraphicBlockBuffer(
819 format,
820 aBuffer,
821 std::move(view),
822 buffer,
823 converter.imageData(),
824 wrapped);
825}
826
827// static
828sp<ConstGraphicBlockBuffer> ConstGraphicBlockBuffer::AllocateEmpty(
829 const sp<AMessage> &format,
830 std::function<sp<ABuffer>(size_t)> alloc) {
831 int32_t width, height;
832 if (!format->findInt32("width", &width)
833 || !format->findInt32("height", &height)) {
834 ALOGD("format had no width / height");
835 return nullptr;
836 }
Wonsik Kim08a8a2b2021-05-10 19:03:47 -0700837 int32_t colorFormat = COLOR_FormatYUV420Flexible;
838 int32_t bpp = 12; // 8(Y) + 2(U) + 2(V)
839 if (format->findInt32(KEY_COLOR_FORMAT, &colorFormat)) {
840 if (colorFormat == COLOR_FormatYUVP010) {
841 bpp = 24; // 16(Y) + 4(U) + 4(V)
842 }
843 }
844 sp<ABuffer> aBuffer(alloc(align(width, 16) * align(height, 16) * bpp / 8));
Jiajia Cong9ed0ab22020-12-02 12:00:49 +0800845 if (aBuffer == nullptr) {
846 ALOGD("%s: failed to allocate buffer", __func__);
847 return nullptr;
848 }
Pawin Vongmasa36653902018-11-15 00:10:25 -0800849 return new ConstGraphicBlockBuffer(
850 format,
851 aBuffer,
852 nullptr,
853 nullptr,
854 nullptr,
855 false);
856}
857
858ConstGraphicBlockBuffer::ConstGraphicBlockBuffer(
859 const sp<AMessage> &format,
860 const sp<ABuffer> &aBuffer,
861 std::unique_ptr<const C2GraphicView> &&view,
862 const std::shared_ptr<C2Buffer> &buffer,
863 const sp<ABuffer> &imageData,
864 bool wrapped)
865 : Codec2Buffer(format, aBuffer),
866 mView(std::move(view)),
867 mBufferRef(buffer),
868 mWrapped(wrapped) {
Wonsik Kimc48ddcf2019-02-11 16:16:57 -0800869 setImageData(imageData);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800870}
871
872std::shared_ptr<C2Buffer> ConstGraphicBlockBuffer::asC2Buffer() {
Wonsik Kimf9b32122020-04-02 11:30:17 -0700873 return mBufferRef;
874}
875
876void ConstGraphicBlockBuffer::clearC2BufferRefs() {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800877 mView.reset();
Wonsik Kimf9b32122020-04-02 11:30:17 -0700878 mBufferRef.reset();
Pawin Vongmasa36653902018-11-15 00:10:25 -0800879}
880
881bool ConstGraphicBlockBuffer::canCopy(const std::shared_ptr<C2Buffer> &buffer) const {
882 if (mWrapped || mBufferRef) {
883 ALOGD("ConstGraphicBlockBuffer::canCopy: %swrapped ; buffer ref %s",
884 mWrapped ? "" : "not ", mBufferRef ? "exists" : "doesn't exist");
885 return false;
886 }
887 if (!buffer) {
888 // Nothing to copy, so we can copy by doing nothing.
889 return true;
890 }
891 if (buffer->data().type() != C2BufferData::GRAPHIC) {
892 ALOGD("ConstGraphicBlockBuffer::canCopy: buffer precondition unsatisfied");
893 return false;
894 }
895 if (buffer->data().graphicBlocks().size() == 0) {
896 return true;
897 } else if (buffer->data().graphicBlocks().size() != 1u) {
898 ALOGD("ConstGraphicBlockBuffer::canCopy: too many blocks");
899 return false;
900 }
901
My Name6bd9a7d2022-03-25 12:37:58 -0700902 ATRACE_BEGIN("ConstGraphicBlockBuffer::canCopy block->map()");
Pawin Vongmasa36653902018-11-15 00:10:25 -0800903 GraphicView2MediaImageConverter converter(
Wonsik Kimd79ee1f2020-08-27 17:41:56 -0700904 buffer->data().graphicBlocks()[0].map().get(),
905 // FIXME: format() is not const, but we cannot change it, so do a const cast here
906 const_cast<ConstGraphicBlockBuffer *>(this)->format(),
907 true /* copy */);
My Name6bd9a7d2022-03-25 12:37:58 -0700908 ATRACE_END();
Pawin Vongmasa36653902018-11-15 00:10:25 -0800909 if (converter.initCheck() != OK) {
910 ALOGD("ConstGraphicBlockBuffer::canCopy: converter init failed: %d", converter.initCheck());
911 return false;
912 }
913 if (converter.backBufferSize() > capacity()) {
914 ALOGD("ConstGraphicBlockBuffer::canCopy: insufficient capacity: req %u has %zu",
915 converter.backBufferSize(), capacity());
916 return false;
917 }
918 return true;
919}
920
921bool ConstGraphicBlockBuffer::copy(const std::shared_ptr<C2Buffer> &buffer) {
922 if (!buffer || buffer->data().graphicBlocks().size() == 0) {
923 setRange(0, 0);
924 return true;
925 }
Pawin Vongmasa36653902018-11-15 00:10:25 -0800926
927 GraphicView2MediaImageConverter converter(
Wonsik Kimd79ee1f2020-08-27 17:41:56 -0700928 buffer->data().graphicBlocks()[0].map().get(), format(), true /* copy */);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800929 if (converter.initCheck() != OK) {
930 ALOGD("ConstGraphicBlockBuffer::copy: converter init failed: %d", converter.initCheck());
931 return false;
932 }
933 sp<ABuffer> aBuffer = new ABuffer(base(), capacity());
934 if (!converter.setBackBuffer(aBuffer)) {
935 ALOGD("ConstGraphicBlockBuffer::copy: set back buffer failed");
936 return false;
937 }
Pin-chih Lin1971e2c2019-04-15 19:36:26 +0800938 setRange(0, aBuffer->size()); // align size info
Pawin Vongmasa36653902018-11-15 00:10:25 -0800939 converter.copyToMediaImage();
940 setImageData(converter.imageData());
941 mBufferRef = buffer;
942 return true;
943}
944
945// EncryptedLinearBlockBuffer
946
947EncryptedLinearBlockBuffer::EncryptedLinearBlockBuffer(
948 const sp<AMessage> &format,
949 const std::shared_ptr<C2LinearBlock> &block,
950 const sp<IMemory> &memory,
951 int32_t heapSeqNum)
Ytai Ben-Tsvi7dd39722019-09-05 15:14:30 -0700952 // TODO: Using unsecurePointer() has some associated security pitfalls
953 // (see declaration for details).
954 // Either document why it is safe in this case or address the
955 // issue (e.g. by copying).
956 : Codec2Buffer(format, new ABuffer(memory->unsecurePointer(), memory->size())),
Pawin Vongmasa36653902018-11-15 00:10:25 -0800957 mBlock(block),
958 mMemory(memory),
959 mHeapSeqNum(heapSeqNum) {
960}
961
962std::shared_ptr<C2Buffer> EncryptedLinearBlockBuffer::asC2Buffer() {
963 return C2Buffer::CreateLinearBuffer(mBlock->share(offset(), size(), C2Fence()));
964}
965
966void EncryptedLinearBlockBuffer::fillSourceBuffer(
Robert Shih895fba92019-07-16 16:29:44 -0700967 hardware::drm::V1_0::SharedBuffer *source) {
968 BufferChannelBase::IMemoryToSharedBuffer(mMemory, mHeapSeqNum, source);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800969}
970
971void EncryptedLinearBlockBuffer::fillSourceBuffer(
972 hardware::cas::native::V1_0::SharedBuffer *source) {
973 ssize_t offset;
974 size_t size;
975
976 mHidlMemory = hardware::fromHeap(mMemory->getMemory(&offset, &size));
977 source->heapBase = *mHidlMemory;
978 source->offset = offset;
979 source->size = size;
980}
981
982bool EncryptedLinearBlockBuffer::copyDecryptedContent(
983 const sp<IMemory> &decrypted, size_t length) {
984 C2WriteView view = mBlock->map().get();
985 if (view.error() != C2_OK) {
986 return false;
987 }
988 if (view.size() < length) {
989 return false;
990 }
Ytai Ben-Tsvi7dd39722019-09-05 15:14:30 -0700991 memcpy(view.data(), decrypted->unsecurePointer(), length);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800992 return true;
993}
994
995bool EncryptedLinearBlockBuffer::copyDecryptedContentFromMemory(size_t length) {
996 return copyDecryptedContent(mMemory, length);
997}
998
999native_handle_t *EncryptedLinearBlockBuffer::handle() const {
1000 return const_cast<native_handle_t *>(mBlock->handle());
1001}
1002
Wonsik Kima79c5522022-01-18 16:29:24 -08001003using ::aidl::android::hardware::graphics::common::Cta861_3;
Hongguangfc1478a2022-07-20 22:56:06 -07001004using ::aidl::android::hardware::graphics::common::Dataspace;
Wonsik Kima79c5522022-01-18 16:29:24 -08001005using ::aidl::android::hardware::graphics::common::Smpte2086;
1006
1007using ::android::gralloc4::MetadataType_Cta861_3;
Hongguangfc1478a2022-07-20 22:56:06 -07001008using ::android::gralloc4::MetadataType_Dataspace;
Wonsik Kima79c5522022-01-18 16:29:24 -08001009using ::android::gralloc4::MetadataType_Smpte2086;
1010using ::android::gralloc4::MetadataType_Smpte2094_40;
1011
1012using ::android::hardware::Return;
1013using ::android::hardware::hidl_vec;
1014
1015using Error4 = ::android::hardware::graphics::mapper::V4_0::Error;
1016using IMapper4 = ::android::hardware::graphics::mapper::V4_0::IMapper;
1017
1018namespace {
1019
1020sp<IMapper4> GetMapper4() {
1021 static sp<IMapper4> sMapper = IMapper4::getService();
1022 return sMapper;
1023}
1024
Wonsik Kime2aa2402022-04-08 14:07:14 -07001025class Gralloc4Buffer {
Wonsik Kima79c5522022-01-18 16:29:24 -08001026public:
Wonsik Kime2aa2402022-04-08 14:07:14 -07001027 Gralloc4Buffer(const C2Handle *const handle) : mBuffer(nullptr) {
1028 sp<IMapper4> mapper = GetMapper4();
1029 if (!mapper) {
1030 return;
1031 }
1032 // Unwrap raw buffer handle from the C2Handle
1033 native_handle_t *nh = UnwrapNativeCodec2GrallocHandle(handle);
1034 if (!nh) {
1035 return;
1036 }
1037 // Import the raw handle so IMapper can use the buffer. The imported
1038 // handle must be freed when the client is done with the buffer.
1039 mapper->importBuffer(
1040 hardware::hidl_handle(nh),
1041 [&](const Error4 &error, void *buffer) {
1042 if (error == Error4::NONE) {
1043 mBuffer = buffer;
1044 }
1045 });
1046
1047 // TRICKY: UnwrapNativeCodec2GrallocHandle creates a new handle but
1048 // does not clone the fds. Thus we need to delete the handle
1049 // without closing it.
1050 native_handle_delete(nh);
1051 }
1052
1053 ~Gralloc4Buffer() {
1054 sp<IMapper4> mapper = GetMapper4();
1055 if (mapper && mBuffer) {
1056 // Free the imported buffer handle. This does not release the
1057 // underlying buffer itself.
1058 mapper->freeBuffer(mBuffer);
Wonsik Kima79c5522022-01-18 16:29:24 -08001059 }
1060 }
Wonsik Kime2aa2402022-04-08 14:07:14 -07001061
1062 void *get() const { return mBuffer; }
1063 operator bool() const { return (mBuffer != nullptr); }
Wonsik Kima79c5522022-01-18 16:29:24 -08001064private:
Wonsik Kime2aa2402022-04-08 14:07:14 -07001065 void *mBuffer;
Wonsik Kima79c5522022-01-18 16:29:24 -08001066};
1067
1068} // namspace
1069
1070c2_status_t GetHdrMetadataFromGralloc4Handle(
1071 const C2Handle *const handle,
1072 std::shared_ptr<C2StreamHdrStaticMetadataInfo::input> *staticInfo,
1073 std::shared_ptr<C2StreamHdrDynamicMetadataInfo::input> *dynamicInfo) {
1074 c2_status_t err = C2_OK;
Wonsik Kima79c5522022-01-18 16:29:24 -08001075 sp<IMapper4> mapper = GetMapper4();
Wonsik Kime2aa2402022-04-08 14:07:14 -07001076 Gralloc4Buffer buffer(handle);
1077 if (!mapper || !buffer) {
Wonsik Kima79c5522022-01-18 16:29:24 -08001078 // Gralloc4 not supported; nothing to do
1079 return err;
1080 }
1081 Error4 mapperErr = Error4::NONE;
1082 if (staticInfo) {
Wonsik Kime2aa2402022-04-08 14:07:14 -07001083 ALOGV("Grabbing static HDR info from gralloc4 metadata");
Wonsik Kima79c5522022-01-18 16:29:24 -08001084 staticInfo->reset(new C2StreamHdrStaticMetadataInfo::input(0u));
1085 memset(&(*staticInfo)->mastering, 0, sizeof((*staticInfo)->mastering));
1086 (*staticInfo)->maxCll = 0;
1087 (*staticInfo)->maxFall = 0;
1088 IMapper4::get_cb cb = [&mapperErr, staticInfo](Error4 err, const hidl_vec<uint8_t> &vec) {
1089 mapperErr = err;
1090 if (err != Error4::NONE) {
1091 return;
1092 }
1093
1094 std::optional<Smpte2086> smpte2086;
1095 gralloc4::decodeSmpte2086(vec, &smpte2086);
1096 if (smpte2086) {
1097 (*staticInfo)->mastering.red.x = smpte2086->primaryRed.x;
1098 (*staticInfo)->mastering.red.y = smpte2086->primaryRed.y;
1099 (*staticInfo)->mastering.green.x = smpte2086->primaryGreen.x;
1100 (*staticInfo)->mastering.green.y = smpte2086->primaryGreen.y;
1101 (*staticInfo)->mastering.blue.x = smpte2086->primaryBlue.x;
1102 (*staticInfo)->mastering.blue.y = smpte2086->primaryBlue.y;
1103 (*staticInfo)->mastering.white.x = smpte2086->whitePoint.x;
1104 (*staticInfo)->mastering.white.y = smpte2086->whitePoint.y;
1105
1106 (*staticInfo)->mastering.maxLuminance = smpte2086->maxLuminance;
1107 (*staticInfo)->mastering.minLuminance = smpte2086->minLuminance;
1108 } else {
1109 mapperErr = Error4::BAD_VALUE;
1110 }
1111 };
Wonsik Kime2aa2402022-04-08 14:07:14 -07001112 Return<void> ret = mapper->get(buffer.get(), MetadataType_Smpte2086, cb);
Wonsik Kima79c5522022-01-18 16:29:24 -08001113 if (!ret.isOk()) {
1114 err = C2_REFUSED;
1115 } else if (mapperErr != Error4::NONE) {
1116 err = C2_CORRUPTED;
1117 }
1118 cb = [&mapperErr, staticInfo](Error4 err, const hidl_vec<uint8_t> &vec) {
1119 mapperErr = err;
1120 if (err != Error4::NONE) {
1121 return;
1122 }
1123
1124 std::optional<Cta861_3> cta861_3;
1125 gralloc4::decodeCta861_3(vec, &cta861_3);
1126 if (cta861_3) {
1127 (*staticInfo)->maxCll = cta861_3->maxContentLightLevel;
1128 (*staticInfo)->maxFall = cta861_3->maxFrameAverageLightLevel;
1129 } else {
1130 mapperErr = Error4::BAD_VALUE;
1131 }
1132 };
Wonsik Kime2aa2402022-04-08 14:07:14 -07001133 ret = mapper->get(buffer.get(), MetadataType_Cta861_3, cb);
Wonsik Kima79c5522022-01-18 16:29:24 -08001134 if (!ret.isOk()) {
1135 err = C2_REFUSED;
1136 } else if (mapperErr != Error4::NONE) {
1137 err = C2_CORRUPTED;
1138 }
1139 }
1140 if (dynamicInfo) {
Wonsik Kime2aa2402022-04-08 14:07:14 -07001141 ALOGV("Grabbing dynamic HDR info from gralloc4 metadata");
Wonsik Kima79c5522022-01-18 16:29:24 -08001142 dynamicInfo->reset();
1143 IMapper4::get_cb cb = [&mapperErr, dynamicInfo](Error4 err, const hidl_vec<uint8_t> &vec) {
1144 mapperErr = err;
1145 if (err != Error4::NONE) {
1146 return;
1147 }
1148 if (!dynamicInfo) {
1149 return;
1150 }
1151 *dynamicInfo = C2StreamHdrDynamicMetadataInfo::input::AllocShared(
1152 vec.size(), 0u, C2Config::HDR_DYNAMIC_METADATA_TYPE_SMPTE_2094_40);
1153 memcpy((*dynamicInfo)->m.data, vec.data(), vec.size());
1154 };
Wonsik Kime2aa2402022-04-08 14:07:14 -07001155 Return<void> ret = mapper->get(buffer.get(), MetadataType_Smpte2094_40, cb);
Wonsik Kima79c5522022-01-18 16:29:24 -08001156 if (!ret.isOk() || mapperErr != Error4::NONE) {
1157 dynamicInfo->reset();
1158 }
1159 }
1160
1161 return err;
1162}
1163
Hongguangfc1478a2022-07-20 22:56:06 -07001164c2_status_t SetMetadataToGralloc4Handle(
1165 android_dataspace_t dataSpace,
Wonsik Kima79c5522022-01-18 16:29:24 -08001166 const std::shared_ptr<const C2StreamHdrStaticMetadataInfo::output> &staticInfo,
1167 const std::shared_ptr<const C2StreamHdrDynamicMetadataInfo::output> &dynamicInfo,
1168 const C2Handle *const handle) {
1169 c2_status_t err = C2_OK;
Wonsik Kima79c5522022-01-18 16:29:24 -08001170 sp<IMapper4> mapper = GetMapper4();
Wonsik Kime2aa2402022-04-08 14:07:14 -07001171 Gralloc4Buffer buffer(handle);
1172 if (!mapper || !buffer) {
Wonsik Kima79c5522022-01-18 16:29:24 -08001173 // Gralloc4 not supported; nothing to do
1174 return err;
1175 }
Hongguangfc1478a2022-07-20 22:56:06 -07001176 {
1177 hidl_vec<uint8_t> metadata;
1178 if (gralloc4::encodeDataspace(static_cast<Dataspace>(dataSpace), &metadata) == OK) {
1179 Return<Error4> ret = mapper->set(buffer.get(), MetadataType_Dataspace, metadata);
1180 if (!ret.isOk()) {
1181 err = C2_REFUSED;
1182 } else if (ret != Error4::NONE) {
1183 err = C2_CORRUPTED;
1184 }
1185 }
1186 }
Wonsik Kima79c5522022-01-18 16:29:24 -08001187 if (staticInfo && *staticInfo) {
Wonsik Kime2aa2402022-04-08 14:07:14 -07001188 ALOGV("Setting static HDR info as gralloc4 metadata");
Wonsik Kima79c5522022-01-18 16:29:24 -08001189 std::optional<Smpte2086> smpte2086 = Smpte2086{
1190 {staticInfo->mastering.red.x, staticInfo->mastering.red.y},
1191 {staticInfo->mastering.green.x, staticInfo->mastering.green.y},
1192 {staticInfo->mastering.blue.x, staticInfo->mastering.blue.y},
1193 {staticInfo->mastering.white.x, staticInfo->mastering.white.y},
1194 staticInfo->mastering.maxLuminance,
1195 staticInfo->mastering.minLuminance,
1196 };
1197 hidl_vec<uint8_t> vec;
Wonsik Kime2aa2402022-04-08 14:07:14 -07001198 if (0.0 <= smpte2086->primaryRed.x && smpte2086->primaryRed.x <= 1.0
1199 && 0.0 <= smpte2086->primaryRed.y && smpte2086->primaryRed.y <= 1.0
1200 && 0.0 <= smpte2086->primaryGreen.x && smpte2086->primaryGreen.x <= 1.0
1201 && 0.0 <= smpte2086->primaryGreen.y && smpte2086->primaryGreen.y <= 1.0
1202 && 0.0 <= smpte2086->primaryBlue.x && smpte2086->primaryBlue.x <= 1.0
1203 && 0.0 <= smpte2086->primaryBlue.y && smpte2086->primaryBlue.y <= 1.0
1204 && 0.0 <= smpte2086->whitePoint.x && smpte2086->whitePoint.x <= 1.0
1205 && 0.0 <= smpte2086->whitePoint.y && smpte2086->whitePoint.y <= 1.0
1206 && 0.0 <= smpte2086->maxLuminance && 0.0 <= smpte2086->minLuminance
1207 && gralloc4::encodeSmpte2086(smpte2086, &vec) == OK) {
1208 Return<Error4> ret = mapper->set(buffer.get(), MetadataType_Smpte2086, vec);
Wonsik Kima79c5522022-01-18 16:29:24 -08001209 if (!ret.isOk()) {
1210 err = C2_REFUSED;
1211 } else if (ret != Error4::NONE) {
1212 err = C2_CORRUPTED;
1213 }
1214 }
1215 std::optional<Cta861_3> cta861_3 = Cta861_3{
1216 staticInfo->maxCll,
1217 staticInfo->maxFall,
1218 };
Wonsik Kime2aa2402022-04-08 14:07:14 -07001219 if (0.0 <= cta861_3->maxContentLightLevel && 0.0 <= cta861_3->maxFrameAverageLightLevel
1220 && gralloc4::encodeCta861_3(cta861_3, &vec) == OK) {
1221 Return<Error4> ret = mapper->set(buffer.get(), MetadataType_Cta861_3, vec);
Wonsik Kima79c5522022-01-18 16:29:24 -08001222 if (!ret.isOk()) {
1223 err = C2_REFUSED;
1224 } else if (ret != Error4::NONE) {
1225 err = C2_CORRUPTED;
1226 }
1227 }
1228 }
Wonsik Kime2aa2402022-04-08 14:07:14 -07001229 if (dynamicInfo && *dynamicInfo && dynamicInfo->flexCount() > 0) {
1230 ALOGV("Setting dynamic HDR info as gralloc4 metadata");
Wonsik Kima79c5522022-01-18 16:29:24 -08001231 std::optional<IMapper4::MetadataType> metadataType;
1232 switch (dynamicInfo->m.type_) {
1233 case C2Config::HDR_DYNAMIC_METADATA_TYPE_SMPTE_2094_10:
1234 // TODO
1235 break;
1236 case C2Config::HDR_DYNAMIC_METADATA_TYPE_SMPTE_2094_40:
1237 metadataType = MetadataType_Smpte2094_40;
1238 break;
1239 }
Taehwan Kim3f3d1ac2022-05-12 10:40:29 +09001240
Wonsik Kima79c5522022-01-18 16:29:24 -08001241 if (metadataType) {
Taehwan Kim3f3d1ac2022-05-12 10:40:29 +09001242 std::vector<uint8_t> smpte2094_40;
1243 smpte2094_40.resize(dynamicInfo->flexCount());
1244 memcpy(smpte2094_40.data(), dynamicInfo->m.data, dynamicInfo->flexCount());
1245
1246 hidl_vec<uint8_t> vec;
1247 if (gralloc4::encodeSmpte2094_40({ smpte2094_40 }, &vec) == OK) {
1248 Return<Error4> ret = mapper->set(buffer.get(), *metadataType, vec);
1249 if (!ret.isOk()) {
1250 err = C2_REFUSED;
1251 } else if (ret != Error4::NONE) {
1252 err = C2_CORRUPTED;
1253 }
Wonsik Kima79c5522022-01-18 16:29:24 -08001254 }
1255 } else {
1256 err = C2_BAD_VALUE;
1257 }
1258 }
1259
1260 return err;
1261}
1262
Pawin Vongmasa36653902018-11-15 00:10:25 -08001263} // namespace android