blob: 2d3c70a0cba888567c3b86e2aafd5edc68ba2d67 [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));
Pawin Vongmasa36653902018-11-15 00:10:25 -0800804 return new ConstGraphicBlockBuffer(
805 format,
806 aBuffer,
807 nullptr,
808 nullptr,
809 nullptr,
810 false);
811}
812
813ConstGraphicBlockBuffer::ConstGraphicBlockBuffer(
814 const sp<AMessage> &format,
815 const sp<ABuffer> &aBuffer,
816 std::unique_ptr<const C2GraphicView> &&view,
817 const std::shared_ptr<C2Buffer> &buffer,
818 const sp<ABuffer> &imageData,
819 bool wrapped)
820 : Codec2Buffer(format, aBuffer),
821 mView(std::move(view)),
822 mBufferRef(buffer),
823 mWrapped(wrapped) {
Wonsik Kimc48ddcf2019-02-11 16:16:57 -0800824 setImageData(imageData);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800825}
826
827std::shared_ptr<C2Buffer> ConstGraphicBlockBuffer::asC2Buffer() {
Wonsik Kimf9b32122020-04-02 11:30:17 -0700828 return mBufferRef;
829}
830
831void ConstGraphicBlockBuffer::clearC2BufferRefs() {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800832 mView.reset();
Wonsik Kimf9b32122020-04-02 11:30:17 -0700833 mBufferRef.reset();
Pawin Vongmasa36653902018-11-15 00:10:25 -0800834}
835
836bool ConstGraphicBlockBuffer::canCopy(const std::shared_ptr<C2Buffer> &buffer) const {
837 if (mWrapped || mBufferRef) {
838 ALOGD("ConstGraphicBlockBuffer::canCopy: %swrapped ; buffer ref %s",
839 mWrapped ? "" : "not ", mBufferRef ? "exists" : "doesn't exist");
840 return false;
841 }
842 if (!buffer) {
843 // Nothing to copy, so we can copy by doing nothing.
844 return true;
845 }
846 if (buffer->data().type() != C2BufferData::GRAPHIC) {
847 ALOGD("ConstGraphicBlockBuffer::canCopy: buffer precondition unsatisfied");
848 return false;
849 }
850 if (buffer->data().graphicBlocks().size() == 0) {
851 return true;
852 } else if (buffer->data().graphicBlocks().size() != 1u) {
853 ALOGD("ConstGraphicBlockBuffer::canCopy: too many blocks");
854 return false;
855 }
856
Pawin Vongmasa36653902018-11-15 00:10:25 -0800857 GraphicView2MediaImageConverter converter(
Wonsik Kimd79ee1f2020-08-27 17:41:56 -0700858 buffer->data().graphicBlocks()[0].map().get(),
859 // FIXME: format() is not const, but we cannot change it, so do a const cast here
860 const_cast<ConstGraphicBlockBuffer *>(this)->format(),
861 true /* copy */);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800862 if (converter.initCheck() != OK) {
863 ALOGD("ConstGraphicBlockBuffer::canCopy: converter init failed: %d", converter.initCheck());
864 return false;
865 }
866 if (converter.backBufferSize() > capacity()) {
867 ALOGD("ConstGraphicBlockBuffer::canCopy: insufficient capacity: req %u has %zu",
868 converter.backBufferSize(), capacity());
869 return false;
870 }
871 return true;
872}
873
874bool ConstGraphicBlockBuffer::copy(const std::shared_ptr<C2Buffer> &buffer) {
875 if (!buffer || buffer->data().graphicBlocks().size() == 0) {
876 setRange(0, 0);
877 return true;
878 }
Pawin Vongmasa36653902018-11-15 00:10:25 -0800879
880 GraphicView2MediaImageConverter converter(
Wonsik Kimd79ee1f2020-08-27 17:41:56 -0700881 buffer->data().graphicBlocks()[0].map().get(), format(), true /* copy */);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800882 if (converter.initCheck() != OK) {
883 ALOGD("ConstGraphicBlockBuffer::copy: converter init failed: %d", converter.initCheck());
884 return false;
885 }
886 sp<ABuffer> aBuffer = new ABuffer(base(), capacity());
887 if (!converter.setBackBuffer(aBuffer)) {
888 ALOGD("ConstGraphicBlockBuffer::copy: set back buffer failed");
889 return false;
890 }
Pin-chih Lin1971e2c2019-04-15 19:36:26 +0800891 setRange(0, aBuffer->size()); // align size info
Pawin Vongmasa36653902018-11-15 00:10:25 -0800892 converter.copyToMediaImage();
893 setImageData(converter.imageData());
894 mBufferRef = buffer;
895 return true;
896}
897
898// EncryptedLinearBlockBuffer
899
900EncryptedLinearBlockBuffer::EncryptedLinearBlockBuffer(
901 const sp<AMessage> &format,
902 const std::shared_ptr<C2LinearBlock> &block,
903 const sp<IMemory> &memory,
904 int32_t heapSeqNum)
Ytai Ben-Tsvi7dd39722019-09-05 15:14:30 -0700905 // TODO: Using unsecurePointer() has some associated security pitfalls
906 // (see declaration for details).
907 // Either document why it is safe in this case or address the
908 // issue (e.g. by copying).
909 : Codec2Buffer(format, new ABuffer(memory->unsecurePointer(), memory->size())),
Pawin Vongmasa36653902018-11-15 00:10:25 -0800910 mBlock(block),
911 mMemory(memory),
912 mHeapSeqNum(heapSeqNum) {
913}
914
915std::shared_ptr<C2Buffer> EncryptedLinearBlockBuffer::asC2Buffer() {
916 return C2Buffer::CreateLinearBuffer(mBlock->share(offset(), size(), C2Fence()));
917}
918
919void EncryptedLinearBlockBuffer::fillSourceBuffer(
Robert Shih895fba92019-07-16 16:29:44 -0700920 hardware::drm::V1_0::SharedBuffer *source) {
921 BufferChannelBase::IMemoryToSharedBuffer(mMemory, mHeapSeqNum, source);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800922}
923
924void EncryptedLinearBlockBuffer::fillSourceBuffer(
925 hardware::cas::native::V1_0::SharedBuffer *source) {
926 ssize_t offset;
927 size_t size;
928
929 mHidlMemory = hardware::fromHeap(mMemory->getMemory(&offset, &size));
930 source->heapBase = *mHidlMemory;
931 source->offset = offset;
932 source->size = size;
933}
934
935bool EncryptedLinearBlockBuffer::copyDecryptedContent(
936 const sp<IMemory> &decrypted, size_t length) {
937 C2WriteView view = mBlock->map().get();
938 if (view.error() != C2_OK) {
939 return false;
940 }
941 if (view.size() < length) {
942 return false;
943 }
Ytai Ben-Tsvi7dd39722019-09-05 15:14:30 -0700944 memcpy(view.data(), decrypted->unsecurePointer(), length);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800945 return true;
946}
947
948bool EncryptedLinearBlockBuffer::copyDecryptedContentFromMemory(size_t length) {
949 return copyDecryptedContent(mMemory, length);
950}
951
952native_handle_t *EncryptedLinearBlockBuffer::handle() const {
953 return const_cast<native_handle_t *>(mBlock->handle());
954}
955
Wonsik Kima79c5522022-01-18 16:29:24 -0800956using ::aidl::android::hardware::graphics::common::Cta861_3;
957using ::aidl::android::hardware::graphics::common::Smpte2086;
958
959using ::android::gralloc4::MetadataType_Cta861_3;
960using ::android::gralloc4::MetadataType_Smpte2086;
961using ::android::gralloc4::MetadataType_Smpte2094_40;
962
963using ::android::hardware::Return;
964using ::android::hardware::hidl_vec;
965
966using Error4 = ::android::hardware::graphics::mapper::V4_0::Error;
967using IMapper4 = ::android::hardware::graphics::mapper::V4_0::IMapper;
968
969namespace {
970
971sp<IMapper4> GetMapper4() {
972 static sp<IMapper4> sMapper = IMapper4::getService();
973 return sMapper;
974}
975
976class NativeHandleDeleter {
977public:
978 explicit NativeHandleDeleter(native_handle_t *handle) : mHandle(handle) {}
979 ~NativeHandleDeleter() {
980 if (mHandle) {
981 native_handle_delete(mHandle);
982 }
983 }
984private:
985 native_handle_t *mHandle;
986};
987
988} // namspace
989
990c2_status_t GetHdrMetadataFromGralloc4Handle(
991 const C2Handle *const handle,
992 std::shared_ptr<C2StreamHdrStaticMetadataInfo::input> *staticInfo,
993 std::shared_ptr<C2StreamHdrDynamicMetadataInfo::input> *dynamicInfo) {
994 c2_status_t err = C2_OK;
995 native_handle_t *nativeHandle = UnwrapNativeCodec2GrallocHandle(handle);
996 if (nativeHandle == nullptr) {
997 // Nothing to do
998 return err;
999 }
1000 // TRICKY: UnwrapNativeCodec2GrallocHandle creates a new handle but
1001 // does not clone the fds. Thus we need to delete the handle
1002 // without closing it when going out of scope.
1003 // NativeHandle cannot solve this problem, as it would close and
1004 // delete the handle, while we need delete only.
1005 NativeHandleDeleter nhd(nativeHandle);
1006 sp<IMapper4> mapper = GetMapper4();
1007 if (!mapper) {
1008 // Gralloc4 not supported; nothing to do
1009 return err;
1010 }
1011 Error4 mapperErr = Error4::NONE;
1012 if (staticInfo) {
1013 staticInfo->reset(new C2StreamHdrStaticMetadataInfo::input(0u));
1014 memset(&(*staticInfo)->mastering, 0, sizeof((*staticInfo)->mastering));
1015 (*staticInfo)->maxCll = 0;
1016 (*staticInfo)->maxFall = 0;
1017 IMapper4::get_cb cb = [&mapperErr, staticInfo](Error4 err, const hidl_vec<uint8_t> &vec) {
1018 mapperErr = err;
1019 if (err != Error4::NONE) {
1020 return;
1021 }
1022
1023 std::optional<Smpte2086> smpte2086;
1024 gralloc4::decodeSmpte2086(vec, &smpte2086);
1025 if (smpte2086) {
1026 (*staticInfo)->mastering.red.x = smpte2086->primaryRed.x;
1027 (*staticInfo)->mastering.red.y = smpte2086->primaryRed.y;
1028 (*staticInfo)->mastering.green.x = smpte2086->primaryGreen.x;
1029 (*staticInfo)->mastering.green.y = smpte2086->primaryGreen.y;
1030 (*staticInfo)->mastering.blue.x = smpte2086->primaryBlue.x;
1031 (*staticInfo)->mastering.blue.y = smpte2086->primaryBlue.y;
1032 (*staticInfo)->mastering.white.x = smpte2086->whitePoint.x;
1033 (*staticInfo)->mastering.white.y = smpte2086->whitePoint.y;
1034
1035 (*staticInfo)->mastering.maxLuminance = smpte2086->maxLuminance;
1036 (*staticInfo)->mastering.minLuminance = smpte2086->minLuminance;
1037 } else {
1038 mapperErr = Error4::BAD_VALUE;
1039 }
1040 };
1041 Return<void> ret = mapper->get(nativeHandle, MetadataType_Smpte2086, cb);
1042 if (!ret.isOk()) {
1043 err = C2_REFUSED;
1044 } else if (mapperErr != Error4::NONE) {
1045 err = C2_CORRUPTED;
1046 }
1047 cb = [&mapperErr, staticInfo](Error4 err, const hidl_vec<uint8_t> &vec) {
1048 mapperErr = err;
1049 if (err != Error4::NONE) {
1050 return;
1051 }
1052
1053 std::optional<Cta861_3> cta861_3;
1054 gralloc4::decodeCta861_3(vec, &cta861_3);
1055 if (cta861_3) {
1056 (*staticInfo)->maxCll = cta861_3->maxContentLightLevel;
1057 (*staticInfo)->maxFall = cta861_3->maxFrameAverageLightLevel;
1058 } else {
1059 mapperErr = Error4::BAD_VALUE;
1060 }
1061 };
1062 ret = mapper->get(nativeHandle, MetadataType_Cta861_3, cb);
1063 if (!ret.isOk()) {
1064 err = C2_REFUSED;
1065 } else if (mapperErr != Error4::NONE) {
1066 err = C2_CORRUPTED;
1067 }
1068 }
1069 if (dynamicInfo) {
1070 dynamicInfo->reset();
1071 IMapper4::get_cb cb = [&mapperErr, dynamicInfo](Error4 err, const hidl_vec<uint8_t> &vec) {
1072 mapperErr = err;
1073 if (err != Error4::NONE) {
1074 return;
1075 }
1076 if (!dynamicInfo) {
1077 return;
1078 }
1079 *dynamicInfo = C2StreamHdrDynamicMetadataInfo::input::AllocShared(
1080 vec.size(), 0u, C2Config::HDR_DYNAMIC_METADATA_TYPE_SMPTE_2094_40);
1081 memcpy((*dynamicInfo)->m.data, vec.data(), vec.size());
1082 };
1083 Return<void> ret = mapper->get(nativeHandle, MetadataType_Smpte2094_40, cb);
1084 if (!ret.isOk() || mapperErr != Error4::NONE) {
1085 dynamicInfo->reset();
1086 }
1087 }
1088
1089 return err;
1090}
1091
1092c2_status_t SetHdrMetadataToGralloc4Handle(
1093 const std::shared_ptr<const C2StreamHdrStaticMetadataInfo::output> &staticInfo,
1094 const std::shared_ptr<const C2StreamHdrDynamicMetadataInfo::output> &dynamicInfo,
1095 const C2Handle *const handle) {
1096 c2_status_t err = C2_OK;
1097 native_handle_t *nativeHandle = UnwrapNativeCodec2GrallocHandle(handle);
1098 if (nativeHandle == nullptr) {
1099 // Nothing to do
1100 return err;
1101 }
1102 // TRICKY: UnwrapNativeCodec2GrallocHandle creates a new handle but
1103 // does not clone the fds. Thus we need to delete the handle
1104 // without closing it when going out of scope.
1105 NativeHandleDeleter nhd(nativeHandle);
1106 sp<IMapper4> mapper = GetMapper4();
1107 if (!mapper) {
1108 // Gralloc4 not supported; nothing to do
1109 return err;
1110 }
1111 if (staticInfo && *staticInfo) {
1112 std::optional<Smpte2086> smpte2086 = Smpte2086{
1113 {staticInfo->mastering.red.x, staticInfo->mastering.red.y},
1114 {staticInfo->mastering.green.x, staticInfo->mastering.green.y},
1115 {staticInfo->mastering.blue.x, staticInfo->mastering.blue.y},
1116 {staticInfo->mastering.white.x, staticInfo->mastering.white.y},
1117 staticInfo->mastering.maxLuminance,
1118 staticInfo->mastering.minLuminance,
1119 };
1120 hidl_vec<uint8_t> vec;
1121 if (gralloc4::encodeSmpte2086(smpte2086, &vec) == OK) {
1122 Return<Error4> ret = mapper->set(nativeHandle, MetadataType_Smpte2086, vec);
1123 if (!ret.isOk()) {
1124 err = C2_REFUSED;
1125 } else if (ret != Error4::NONE) {
1126 err = C2_CORRUPTED;
1127 }
1128 }
1129 std::optional<Cta861_3> cta861_3 = Cta861_3{
1130 staticInfo->maxCll,
1131 staticInfo->maxFall,
1132 };
1133 if (gralloc4::encodeCta861_3(cta861_3, &vec) == OK) {
1134 Return<Error4> ret = mapper->set(nativeHandle, MetadataType_Cta861_3, vec);
1135 if (!ret.isOk()) {
1136 err = C2_REFUSED;
1137 } else if (ret != Error4::NONE) {
1138 err = C2_CORRUPTED;
1139 }
1140 }
1141 }
1142 if (dynamicInfo && *dynamicInfo) {
1143 hidl_vec<uint8_t> vec;
1144 vec.resize(dynamicInfo->flexCount());
1145 memcpy(vec.data(), dynamicInfo->m.data, dynamicInfo->flexCount());
1146 std::optional<IMapper4::MetadataType> metadataType;
1147 switch (dynamicInfo->m.type_) {
1148 case C2Config::HDR_DYNAMIC_METADATA_TYPE_SMPTE_2094_10:
1149 // TODO
1150 break;
1151 case C2Config::HDR_DYNAMIC_METADATA_TYPE_SMPTE_2094_40:
1152 metadataType = MetadataType_Smpte2094_40;
1153 break;
1154 }
1155 if (metadataType) {
1156 Return<Error4> ret = mapper->set(nativeHandle, *metadataType, vec);
1157 if (!ret.isOk()) {
1158 err = C2_REFUSED;
1159 } else if (ret != Error4::NONE) {
1160 err = C2_CORRUPTED;
1161 }
1162 } else {
1163 err = C2_BAD_VALUE;
1164 }
1165 }
1166
1167 return err;
1168}
1169
Pawin Vongmasa36653902018-11-15 00:10:25 -08001170} // namespace android