blob: e4442ba867d27bb2f250a3a9ad8dd33516ce89f0 [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
bohua222c0b2021-01-12 18:54:53 -080021#include <android-base/properties.h>
Wonsik Kim41d83432020-04-27 16:40:49 -070022#include <android/hardware/cas/native/1.0/types.h>
23#include <android/hardware/drm/1.0/types.h>
Pawin Vongmasa36653902018-11-15 00:10:25 -080024#include <hidlmemory/FrameworkUtils.h>
25#include <media/hardware/HardwareAPI.h>
Robert Shih895fba92019-07-16 16:29:44 -070026#include <media/stagefright/CodecBase.h>
Pawin Vongmasa36653902018-11-15 00:10:25 -080027#include <media/stagefright/MediaCodecConstants.h>
28#include <media/stagefright/foundation/ABuffer.h>
29#include <media/stagefright/foundation/AMessage.h>
30#include <media/stagefright/foundation/AUtils.h>
Wonsik Kim41d83432020-04-27 16:40:49 -070031#include <mediadrm/ICrypto.h>
Pawin Vongmasa36653902018-11-15 00:10:25 -080032#include <nativebase/nativebase.h>
Wonsik Kimebe0f9e2019-07-03 11:06:51 -070033#include <ui/Fence.h>
Pawin Vongmasa36653902018-11-15 00:10:25 -080034
35#include <C2AllocatorGralloc.h>
36#include <C2BlockInternal.h>
37#include <C2Debug.h>
38
39#include "Codec2Buffer.h"
40
41namespace android {
42
43// Codec2Buffer
44
45bool Codec2Buffer::canCopyLinear(const std::shared_ptr<C2Buffer> &buffer) const {
46 if (const_cast<Codec2Buffer *>(this)->base() == nullptr) {
47 return false;
48 }
49 if (!buffer) {
50 // Nothing to copy, so we can copy by doing nothing.
51 return true;
52 }
53 if (buffer->data().type() != C2BufferData::LINEAR) {
54 return false;
55 }
56 if (buffer->data().linearBlocks().size() == 0u) {
57 // Nothing to copy, so we can copy by doing nothing.
58 return true;
59 } else if (buffer->data().linearBlocks().size() > 1u) {
60 // We don't know how to copy more than one blocks.
61 return false;
62 }
63 if (buffer->data().linearBlocks()[0].size() > capacity()) {
64 // It won't fit.
65 return false;
66 }
67 return true;
68}
69
70bool Codec2Buffer::copyLinear(const std::shared_ptr<C2Buffer> &buffer) {
71 // We assume that all canCopyLinear() checks passed.
72 if (!buffer || buffer->data().linearBlocks().size() == 0u
73 || buffer->data().linearBlocks()[0].size() == 0u) {
74 setRange(0, 0);
75 return true;
76 }
77 C2ReadView view = buffer->data().linearBlocks()[0].map().get();
78 if (view.error() != C2_OK) {
79 ALOGD("Error while mapping: %d", view.error());
80 return false;
81 }
82 if (view.capacity() > capacity()) {
83 ALOGD("C2ConstLinearBlock lied --- it actually doesn't fit: view(%u) > this(%zu)",
84 view.capacity(), capacity());
85 return false;
86 }
87 memcpy(base(), view.data(), view.capacity());
88 setRange(0, view.capacity());
89 return true;
90}
91
92void Codec2Buffer::setImageData(const sp<ABuffer> &imageData) {
Wonsik Kimc48ddcf2019-02-11 16:16:57 -080093 mImageData = imageData;
Pawin Vongmasa36653902018-11-15 00:10:25 -080094}
95
96// LocalLinearBuffer
97
98bool LocalLinearBuffer::canCopy(const std::shared_ptr<C2Buffer> &buffer) const {
99 return canCopyLinear(buffer);
100}
101
102bool LocalLinearBuffer::copy(const std::shared_ptr<C2Buffer> &buffer) {
103 return copyLinear(buffer);
104}
105
106// DummyContainerBuffer
107
Pawin Vongmasa8be93112018-12-11 14:01:42 -0800108static uint8_t sDummyByte[1] = { 0 };
109
Pawin Vongmasa36653902018-11-15 00:10:25 -0800110DummyContainerBuffer::DummyContainerBuffer(
111 const sp<AMessage> &format, const std::shared_ptr<C2Buffer> &buffer)
Pawin Vongmasa8be93112018-12-11 14:01:42 -0800112 : Codec2Buffer(format, new ABuffer(sDummyByte, 1)),
Pawin Vongmasa36653902018-11-15 00:10:25 -0800113 mBufferRef(buffer) {
114 setRange(0, buffer ? 1 : 0);
115}
116
117std::shared_ptr<C2Buffer> DummyContainerBuffer::asC2Buffer() {
Wonsik Kimf9b32122020-04-02 11:30:17 -0700118 return mBufferRef;
119}
120
121void DummyContainerBuffer::clearC2BufferRefs() {
122 mBufferRef.reset();
Pawin Vongmasa36653902018-11-15 00:10:25 -0800123}
124
125bool DummyContainerBuffer::canCopy(const std::shared_ptr<C2Buffer> &) const {
126 return !mBufferRef;
127}
128
129bool DummyContainerBuffer::copy(const std::shared_ptr<C2Buffer> &buffer) {
130 mBufferRef = buffer;
131 setRange(0, mBufferRef ? 1 : 0);
132 return true;
133}
134
135// LinearBlockBuffer
136
137// static
138sp<LinearBlockBuffer> LinearBlockBuffer::Allocate(
139 const sp<AMessage> &format, const std::shared_ptr<C2LinearBlock> &block) {
140 C2WriteView writeView(block->map().get());
141 if (writeView.error() != C2_OK) {
142 return nullptr;
143 }
144 return new LinearBlockBuffer(format, std::move(writeView), block);
145}
146
147std::shared_ptr<C2Buffer> LinearBlockBuffer::asC2Buffer() {
148 return C2Buffer::CreateLinearBuffer(mBlock->share(offset(), size(), C2Fence()));
149}
150
151bool LinearBlockBuffer::canCopy(const std::shared_ptr<C2Buffer> &buffer) const {
152 return canCopyLinear(buffer);
153}
154
155bool LinearBlockBuffer::copy(const std::shared_ptr<C2Buffer> &buffer) {
156 return copyLinear(buffer);
157}
158
159LinearBlockBuffer::LinearBlockBuffer(
160 const sp<AMessage> &format,
161 C2WriteView&& writeView,
162 const std::shared_ptr<C2LinearBlock> &block)
163 : Codec2Buffer(format, new ABuffer(writeView.data(), writeView.size())),
164 mWriteView(writeView),
165 mBlock(block) {
166}
167
168// ConstLinearBlockBuffer
169
170// static
171sp<ConstLinearBlockBuffer> ConstLinearBlockBuffer::Allocate(
172 const sp<AMessage> &format, const std::shared_ptr<C2Buffer> &buffer) {
173 if (!buffer
174 || buffer->data().type() != C2BufferData::LINEAR
175 || buffer->data().linearBlocks().size() != 1u) {
176 return nullptr;
177 }
178 C2ReadView readView(buffer->data().linearBlocks()[0].map().get());
179 if (readView.error() != C2_OK) {
180 return nullptr;
181 }
182 return new ConstLinearBlockBuffer(format, std::move(readView), buffer);
183}
184
185ConstLinearBlockBuffer::ConstLinearBlockBuffer(
186 const sp<AMessage> &format,
187 C2ReadView&& readView,
188 const std::shared_ptr<C2Buffer> &buffer)
189 : Codec2Buffer(format, new ABuffer(
190 // NOTE: ABuffer only takes non-const pointer but this data is
191 // supposed to be read-only.
192 const_cast<uint8_t *>(readView.data()), readView.capacity())),
193 mReadView(readView),
194 mBufferRef(buffer) {
195}
196
197std::shared_ptr<C2Buffer> ConstLinearBlockBuffer::asC2Buffer() {
Wonsik Kimf9b32122020-04-02 11:30:17 -0700198 return mBufferRef;
199}
200
201void ConstLinearBlockBuffer::clearC2BufferRefs() {
202 mBufferRef.reset();
Pawin Vongmasa36653902018-11-15 00:10:25 -0800203}
204
205// GraphicView2MediaImageConverter
206
207namespace {
208
209class GraphicView2MediaImageConverter {
210public:
211 /**
212 * Creates a C2GraphicView <=> MediaImage converter
213 *
214 * \param view C2GraphicView object
Wonsik Kimd79ee1f2020-08-27 17:41:56 -0700215 * \param format buffer format
Wonsik Kim7d966312019-06-04 14:00:49 -0700216 * \param copy whether the converter is used for copy or not
Pawin Vongmasa36653902018-11-15 00:10:25 -0800217 */
218 GraphicView2MediaImageConverter(
Wonsik Kimd79ee1f2020-08-27 17:41:56 -0700219 const C2GraphicView &view, const sp<AMessage> &format, bool copy)
Pawin Vongmasa36653902018-11-15 00:10:25 -0800220 : mInitCheck(NO_INIT),
221 mView(view),
222 mWidth(view.width()),
223 mHeight(view.height()),
Pawin Vongmasa36653902018-11-15 00:10:25 -0800224 mAllocatedDepth(0),
225 mBackBufferSize(0),
226 mMediaImage(new ABuffer(sizeof(MediaImage2))) {
Wonsik Kimd79ee1f2020-08-27 17:41:56 -0700227 if (!format->findInt32(KEY_COLOR_FORMAT, &mClientColorFormat)) {
228 mClientColorFormat = COLOR_FormatYUV420Flexible;
229 }
230 if (!format->findInt32("android._color-format", &mComponentColorFormat)) {
231 mComponentColorFormat = COLOR_FormatYUV420Flexible;
232 }
Pawin Vongmasa36653902018-11-15 00:10:25 -0800233 if (view.error() != C2_OK) {
234 ALOGD("Converter: view.error() = %d", view.error());
235 mInitCheck = BAD_VALUE;
236 return;
237 }
238 MediaImage2 *mediaImage = (MediaImage2 *)mMediaImage->base();
239 const C2PlanarLayout &layout = view.layout();
240 if (layout.numPlanes == 0) {
241 ALOGD("Converter: 0 planes");
242 mInitCheck = BAD_VALUE;
243 return;
244 }
Harish Mahendrakarcac53852019-02-20 10:59:10 -0800245 memset(mediaImage, 0, sizeof(*mediaImage));
Pawin Vongmasa36653902018-11-15 00:10:25 -0800246 mAllocatedDepth = layout.planes[0].allocatedDepth;
247 uint32_t bitDepth = layout.planes[0].bitDepth;
248
249 // align width and height to support subsampling cleanly
Wonsik Kim8bfa17a2019-05-30 22:12:30 -0700250 uint32_t stride = align(view.crop().width, 2) * divUp(layout.planes[0].allocatedDepth, 8u);
251 uint32_t vStride = align(view.crop().height, 2);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800252
Wonsik Kimd79ee1f2020-08-27 17:41:56 -0700253 bool tryWrapping = !copy;
254
Pawin Vongmasa36653902018-11-15 00:10:25 -0800255 switch (layout.type) {
Wonsik Kimd79ee1f2020-08-27 17:41:56 -0700256 case C2PlanarLayout::TYPE_YUV: {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800257 mediaImage->mType = MediaImage2::MEDIA_IMAGE_TYPE_YUV;
258 if (layout.numPlanes != 3) {
259 ALOGD("Converter: %d planes for YUV layout", layout.numPlanes);
260 mInitCheck = BAD_VALUE;
261 return;
262 }
Wonsik Kimd79ee1f2020-08-27 17:41:56 -0700263 C2PlaneInfo yPlane = layout.planes[C2PlanarLayout::PLANE_Y];
264 C2PlaneInfo uPlane = layout.planes[C2PlanarLayout::PLANE_U];
265 C2PlaneInfo vPlane = layout.planes[C2PlanarLayout::PLANE_V];
266 if (yPlane.channel != C2PlaneInfo::CHANNEL_Y
267 || uPlane.channel != C2PlaneInfo::CHANNEL_CB
268 || vPlane.channel != C2PlaneInfo::CHANNEL_CR) {
269 ALOGD("Converter: not YUV layout");
Pawin Vongmasa36653902018-11-15 00:10:25 -0800270 mInitCheck = BAD_VALUE;
271 return;
272 }
Wonsik Kimd79ee1f2020-08-27 17:41:56 -0700273 bool yuv420888 = yPlane.rowSampling == 1 && yPlane.colSampling == 1
274 && uPlane.rowSampling == 2 && uPlane.colSampling == 2
275 && vPlane.rowSampling == 2 && vPlane.colSampling == 2;
276 if (yuv420888) {
277 for (uint32_t i = 0; i < 3; ++i) {
278 const C2PlaneInfo &plane = layout.planes[i];
279 if (plane.allocatedDepth != 8 || plane.bitDepth != 8) {
280 yuv420888 = false;
281 break;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800282 }
Wonsik Kimd79ee1f2020-08-27 17:41:56 -0700283 }
284 yuv420888 = yuv420888 && yPlane.colInc == 1 && uPlane.rowInc == vPlane.rowInc;
285 }
286 int32_t copyFormat = mClientColorFormat;
287 if (yuv420888 && mClientColorFormat == COLOR_FormatYUV420Flexible) {
288 if (uPlane.colInc == 2 && vPlane.colInc == 2
289 && yPlane.rowInc == uPlane.rowInc) {
290 copyFormat = COLOR_FormatYUV420PackedSemiPlanar;
291 } else if (uPlane.colInc == 1 && vPlane.colInc == 1
292 && yPlane.rowInc == uPlane.rowInc * 2) {
293 copyFormat = COLOR_FormatYUV420PackedPlanar;
294 }
295 }
296 ALOGV("client_fmt=0x%x y:{colInc=%d rowInc=%d} u:{colInc=%d rowInc=%d} "
297 "v:{colInc=%d rowInc=%d}",
298 mClientColorFormat,
299 yPlane.colInc, yPlane.rowInc,
300 uPlane.colInc, uPlane.rowInc,
301 vPlane.colInc, vPlane.rowInc);
302 switch (copyFormat) {
303 case COLOR_FormatYUV420Flexible:
Pawin Vongmasa36653902018-11-15 00:10:25 -0800304 case COLOR_FormatYUV420Planar:
305 case COLOR_FormatYUV420PackedPlanar:
306 mediaImage->mPlane[mediaImage->Y].mOffset = 0;
307 mediaImage->mPlane[mediaImage->Y].mColInc = 1;
Wonsik Kim8bfa17a2019-05-30 22:12:30 -0700308 mediaImage->mPlane[mediaImage->Y].mRowInc = stride;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800309 mediaImage->mPlane[mediaImage->Y].mHorizSubsampling = 1;
310 mediaImage->mPlane[mediaImage->Y].mVertSubsampling = 1;
311
Wonsik Kim8bfa17a2019-05-30 22:12:30 -0700312 mediaImage->mPlane[mediaImage->U].mOffset = stride * vStride;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800313 mediaImage->mPlane[mediaImage->U].mColInc = 1;
Wonsik Kim8bfa17a2019-05-30 22:12:30 -0700314 mediaImage->mPlane[mediaImage->U].mRowInc = stride / 2;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800315 mediaImage->mPlane[mediaImage->U].mHorizSubsampling = 2;
316 mediaImage->mPlane[mediaImage->U].mVertSubsampling = 2;
317
Wonsik Kim8bfa17a2019-05-30 22:12:30 -0700318 mediaImage->mPlane[mediaImage->V].mOffset = stride * vStride * 5 / 4;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800319 mediaImage->mPlane[mediaImage->V].mColInc = 1;
Wonsik Kim8bfa17a2019-05-30 22:12:30 -0700320 mediaImage->mPlane[mediaImage->V].mRowInc = stride / 2;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800321 mediaImage->mPlane[mediaImage->V].mHorizSubsampling = 2;
322 mediaImage->mPlane[mediaImage->V].mVertSubsampling = 2;
Wonsik Kimd79ee1f2020-08-27 17:41:56 -0700323
324 if (tryWrapping && mClientColorFormat != COLOR_FormatYUV420Flexible) {
325 tryWrapping = yuv420888 && uPlane.colInc == 1 && vPlane.colInc == 1
326 && yPlane.rowInc == uPlane.rowInc * 2
327 && view.data()[0] < view.data()[1]
328 && view.data()[1] < view.data()[2];
329 }
Pawin Vongmasa36653902018-11-15 00:10:25 -0800330 break;
331
332 case COLOR_FormatYUV420SemiPlanar:
333 case COLOR_FormatYUV420PackedSemiPlanar:
334 mediaImage->mPlane[mediaImage->Y].mOffset = 0;
335 mediaImage->mPlane[mediaImage->Y].mColInc = 1;
Wonsik Kim8bfa17a2019-05-30 22:12:30 -0700336 mediaImage->mPlane[mediaImage->Y].mRowInc = stride;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800337 mediaImage->mPlane[mediaImage->Y].mHorizSubsampling = 1;
338 mediaImage->mPlane[mediaImage->Y].mVertSubsampling = 1;
339
Wonsik Kim8bfa17a2019-05-30 22:12:30 -0700340 mediaImage->mPlane[mediaImage->U].mOffset = stride * vStride;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800341 mediaImage->mPlane[mediaImage->U].mColInc = 2;
Wonsik Kim8bfa17a2019-05-30 22:12:30 -0700342 mediaImage->mPlane[mediaImage->U].mRowInc = stride;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800343 mediaImage->mPlane[mediaImage->U].mHorizSubsampling = 2;
344 mediaImage->mPlane[mediaImage->U].mVertSubsampling = 2;
345
Wonsik Kim8bfa17a2019-05-30 22:12:30 -0700346 mediaImage->mPlane[mediaImage->V].mOffset = stride * vStride + 1;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800347 mediaImage->mPlane[mediaImage->V].mColInc = 2;
Wonsik Kim8bfa17a2019-05-30 22:12:30 -0700348 mediaImage->mPlane[mediaImage->V].mRowInc = stride;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800349 mediaImage->mPlane[mediaImage->V].mHorizSubsampling = 2;
350 mediaImage->mPlane[mediaImage->V].mVertSubsampling = 2;
Wonsik Kimd79ee1f2020-08-27 17:41:56 -0700351
352 if (tryWrapping && mClientColorFormat != COLOR_FormatYUV420Flexible) {
353 tryWrapping = yuv420888 && uPlane.colInc == 2 && vPlane.colInc == 2
354 && yPlane.rowInc == uPlane.rowInc
355 && view.data()[0] < view.data()[1]
356 && view.data()[1] < view.data()[2];
357 }
Pawin Vongmasa36653902018-11-15 00:10:25 -0800358 break;
359
Wonsik Kim29e3c4d2020-09-02 12:19:44 -0700360 case COLOR_FormatYUVP010:
Wonsik Kim08a8a2b2021-05-10 19:03:47 -0700361 // stride is in bytes
Wonsik Kim29e3c4d2020-09-02 12:19:44 -0700362 mediaImage->mPlane[mediaImage->Y].mOffset = 0;
363 mediaImage->mPlane[mediaImage->Y].mColInc = 2;
Wonsik Kim08a8a2b2021-05-10 19:03:47 -0700364 mediaImage->mPlane[mediaImage->Y].mRowInc = stride;
Wonsik Kim29e3c4d2020-09-02 12:19:44 -0700365 mediaImage->mPlane[mediaImage->Y].mHorizSubsampling = 1;
366 mediaImage->mPlane[mediaImage->Y].mVertSubsampling = 1;
367
Wonsik Kim08a8a2b2021-05-10 19:03:47 -0700368 mediaImage->mPlane[mediaImage->U].mOffset = stride * vStride;
Wonsik Kim29e3c4d2020-09-02 12:19:44 -0700369 mediaImage->mPlane[mediaImage->U].mColInc = 4;
Wonsik Kim08a8a2b2021-05-10 19:03:47 -0700370 mediaImage->mPlane[mediaImage->U].mRowInc = stride;
Wonsik Kim29e3c4d2020-09-02 12:19:44 -0700371 mediaImage->mPlane[mediaImage->U].mHorizSubsampling = 2;
372 mediaImage->mPlane[mediaImage->U].mVertSubsampling = 2;
373
Wonsik Kim08a8a2b2021-05-10 19:03:47 -0700374 mediaImage->mPlane[mediaImage->V].mOffset = stride * vStride + 2;
Wonsik Kim29e3c4d2020-09-02 12:19:44 -0700375 mediaImage->mPlane[mediaImage->V].mColInc = 4;
Wonsik Kim08a8a2b2021-05-10 19:03:47 -0700376 mediaImage->mPlane[mediaImage->V].mRowInc = stride;
Wonsik Kim29e3c4d2020-09-02 12:19:44 -0700377 mediaImage->mPlane[mediaImage->V].mHorizSubsampling = 2;
378 mediaImage->mPlane[mediaImage->V].mVertSubsampling = 2;
Wonsik Kimd79ee1f2020-08-27 17:41:56 -0700379 if (tryWrapping) {
380 tryWrapping = yPlane.allocatedDepth == 16
381 && uPlane.allocatedDepth == 16
382 && vPlane.allocatedDepth == 16
383 && yPlane.bitDepth == 10
384 && uPlane.bitDepth == 10
385 && vPlane.bitDepth == 10
386 && yPlane.rightShift == 6
387 && uPlane.rightShift == 6
388 && vPlane.rightShift == 6
389 && yPlane.rowSampling == 1 && yPlane.colSampling == 1
390 && uPlane.rowSampling == 2 && uPlane.colSampling == 2
391 && vPlane.rowSampling == 2 && vPlane.colSampling == 2
392 && yPlane.colInc == 2
393 && uPlane.colInc == 4
394 && vPlane.colInc == 4
395 && yPlane.rowInc == uPlane.rowInc
396 && yPlane.rowInc == vPlane.rowInc;
397 }
Wonsik Kim29e3c4d2020-09-02 12:19:44 -0700398 break;
399
Wonsik Kimd79ee1f2020-08-27 17:41:56 -0700400 default: {
401 // default to fully planar format --- this will be overridden if wrapping
402 // TODO: keep interleaved format
403 int32_t colInc = divUp(mAllocatedDepth, 8u);
404 int32_t rowInc = stride * colInc / yPlane.colSampling;
405 mediaImage->mPlane[mediaImage->Y].mOffset = 0;
406 mediaImage->mPlane[mediaImage->Y].mColInc = colInc;
407 mediaImage->mPlane[mediaImage->Y].mRowInc = rowInc;
408 mediaImage->mPlane[mediaImage->Y].mHorizSubsampling = yPlane.colSampling;
409 mediaImage->mPlane[mediaImage->Y].mVertSubsampling = yPlane.rowSampling;
410 int32_t offset = rowInc * vStride / yPlane.rowSampling;
411
412 rowInc = stride * colInc / uPlane.colSampling;
413 mediaImage->mPlane[mediaImage->U].mOffset = offset;
414 mediaImage->mPlane[mediaImage->U].mColInc = colInc;
415 mediaImage->mPlane[mediaImage->U].mRowInc = rowInc;
416 mediaImage->mPlane[mediaImage->U].mHorizSubsampling = uPlane.colSampling;
417 mediaImage->mPlane[mediaImage->U].mVertSubsampling = uPlane.rowSampling;
418 offset += rowInc * vStride / uPlane.rowSampling;
419
420 rowInc = stride * colInc / vPlane.colSampling;
421 mediaImage->mPlane[mediaImage->V].mOffset = offset;
422 mediaImage->mPlane[mediaImage->V].mColInc = colInc;
423 mediaImage->mPlane[mediaImage->V].mRowInc = rowInc;
424 mediaImage->mPlane[mediaImage->V].mHorizSubsampling = vPlane.colSampling;
425 mediaImage->mPlane[mediaImage->V].mVertSubsampling = vPlane.rowSampling;
426 break;
427 }
Pawin Vongmasa36653902018-11-15 00:10:25 -0800428 }
429 break;
Wonsik Kimd79ee1f2020-08-27 17:41:56 -0700430 }
431
Pawin Vongmasa36653902018-11-15 00:10:25 -0800432 case C2PlanarLayout::TYPE_YUVA:
Wonsik Kimd79ee1f2020-08-27 17:41:56 -0700433 ALOGD("Converter: unrecognized color format "
434 "(client %d component %d) for YUVA layout",
435 mClientColorFormat, mComponentColorFormat);
436 mInitCheck = NO_INIT;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800437 return;
438 case C2PlanarLayout::TYPE_RGB:
Wonsik Kimd79ee1f2020-08-27 17:41:56 -0700439 ALOGD("Converter: unrecognized color format "
440 "(client %d component %d) for RGB layout",
441 mClientColorFormat, mComponentColorFormat);
442 mInitCheck = NO_INIT;
443 // TODO: support MediaImage layout
444 return;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800445 case C2PlanarLayout::TYPE_RGBA:
Wonsik Kimd79ee1f2020-08-27 17:41:56 -0700446 ALOGD("Converter: unrecognized color format "
447 "(client %d component %d) for RGBA layout",
448 mClientColorFormat, mComponentColorFormat);
449 mInitCheck = NO_INIT;
450 // TODO: support MediaImage layout
451 return;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800452 default:
453 mediaImage->mType = MediaImage2::MEDIA_IMAGE_TYPE_UNKNOWN;
Wonsik Kimd79ee1f2020-08-27 17:41:56 -0700454 if (layout.numPlanes == 1) {
455 const C2PlaneInfo &plane = layout.planes[0];
456 if (plane.colInc < 0 || plane.rowInc < 0) {
457 // Copy-only if we have negative colInc/rowInc
458 tryWrapping = false;
459 }
460 mediaImage->mPlane[0].mOffset = 0;
461 mediaImage->mPlane[0].mColInc = std::abs(plane.colInc);
462 mediaImage->mPlane[0].mRowInc = std::abs(plane.rowInc);
463 mediaImage->mPlane[0].mHorizSubsampling = plane.colSampling;
464 mediaImage->mPlane[0].mVertSubsampling = plane.rowSampling;
465 } else {
466 ALOGD("Converter: unrecognized layout: color format (client %d component %d)",
467 mClientColorFormat, mComponentColorFormat);
468 mInitCheck = NO_INIT;
469 return;
470 }
471 break;
472 }
473 if (tryWrapping) {
474 // try to map directly. check if the planes are near one another
475 const uint8_t *minPtr = mView.data()[0];
476 const uint8_t *maxPtr = mView.data()[0];
477 int32_t planeSize = 0;
478 for (uint32_t i = 0; i < layout.numPlanes; ++i) {
479 const C2PlaneInfo &plane = layout.planes[i];
480 int64_t planeStride = std::abs(plane.rowInc / plane.colInc);
481 ssize_t minOffset = plane.minOffset(
482 mWidth / plane.colSampling, mHeight / plane.rowSampling);
483 ssize_t maxOffset = plane.maxOffset(
484 mWidth / plane.colSampling, mHeight / plane.rowSampling);
485 if (minPtr > mView.data()[i] + minOffset) {
486 minPtr = mView.data()[i] + minOffset;
487 }
488 if (maxPtr < mView.data()[i] + maxOffset) {
489 maxPtr = mView.data()[i] + maxOffset;
490 }
491 planeSize += planeStride * divUp(mAllocatedDepth, 8u)
492 * align(mHeight, 64) / plane.rowSampling;
493 }
494
Wonsik Kimdc173402021-07-22 19:38:17 -0700495 if (minPtr == mView.data()[0] && (maxPtr - minPtr + 1) <= planeSize) {
Wonsik Kimd79ee1f2020-08-27 17:41:56 -0700496 // FIXME: this is risky as reading/writing data out of bound results
497 // in an undefined behavior, but gralloc does assume a
498 // contiguous mapping
499 for (uint32_t i = 0; i < layout.numPlanes; ++i) {
500 const C2PlaneInfo &plane = layout.planes[i];
501 mediaImage->mPlane[i].mOffset = mView.data()[i] - minPtr;
502 mediaImage->mPlane[i].mColInc = plane.colInc;
503 mediaImage->mPlane[i].mRowInc = plane.rowInc;
504 mediaImage->mPlane[i].mHorizSubsampling = plane.colSampling;
505 mediaImage->mPlane[i].mVertSubsampling = plane.rowSampling;
506 }
507 mWrapped = new ABuffer(const_cast<uint8_t *>(minPtr),
508 maxPtr - minPtr + 1);
509 ALOGV("Converter: wrapped (capacity=%zu)", mWrapped->capacity());
510 }
Pawin Vongmasa36653902018-11-15 00:10:25 -0800511 }
512 mediaImage->mNumPlanes = layout.numPlanes;
Harish Mahendrakarf7c49e22019-05-24 14:19:16 -0700513 mediaImage->mWidth = view.crop().width;
514 mediaImage->mHeight = view.crop().height;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800515 mediaImage->mBitDepth = bitDepth;
516 mediaImage->mBitDepthAllocated = mAllocatedDepth;
517
518 uint32_t bufferSize = 0;
519 for (uint32_t i = 0; i < layout.numPlanes; ++i) {
520 const C2PlaneInfo &plane = layout.planes[i];
521 if (plane.allocatedDepth < plane.bitDepth
522 || plane.rightShift != plane.allocatedDepth - plane.bitDepth) {
523 ALOGD("rightShift value of %u unsupported", plane.rightShift);
524 mInitCheck = BAD_VALUE;
525 return;
526 }
527 if (plane.allocatedDepth > 8 && plane.endianness != C2PlaneInfo::NATIVE) {
528 ALOGD("endianness value of %u unsupported", plane.endianness);
529 mInitCheck = BAD_VALUE;
530 return;
531 }
532 if (plane.allocatedDepth != mAllocatedDepth || plane.bitDepth != bitDepth) {
Wonsik Kimd79ee1f2020-08-27 17:41:56 -0700533 ALOGD("different allocatedDepth/bitDepth per plane unsupported");
Pawin Vongmasa36653902018-11-15 00:10:25 -0800534 mInitCheck = BAD_VALUE;
535 return;
536 }
Wonsik Kim08a8a2b2021-05-10 19:03:47 -0700537 // stride is in bytes
538 bufferSize += stride * vStride / plane.rowSampling / plane.colSampling;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800539 }
540
541 mBackBufferSize = bufferSize;
542 mInitCheck = OK;
543 }
544
545 status_t initCheck() const { return mInitCheck; }
546
547 uint32_t backBufferSize() const { return mBackBufferSize; }
548
549 /**
550 * Wrap C2GraphicView using a MediaImage2. Note that if not wrapped, the content is not mapped
551 * in this function --- the caller should use CopyGraphicView2MediaImage() function to copy the
552 * data into a backing buffer explicitly.
553 *
554 * \return media buffer. This is null if wrapping failed.
555 */
556 sp<ABuffer> wrap() const {
557 if (mBackBuffer == nullptr) {
558 return mWrapped;
559 }
560 return nullptr;
561 }
562
563 bool setBackBuffer(const sp<ABuffer> &backBuffer) {
Wonsik Kim186fdbf2019-01-29 13:30:01 -0800564 if (backBuffer == nullptr) {
565 return false;
566 }
Pawin Vongmasa36653902018-11-15 00:10:25 -0800567 if (backBuffer->capacity() < mBackBufferSize) {
568 return false;
569 }
570 backBuffer->setRange(0, mBackBufferSize);
571 mBackBuffer = backBuffer;
572 return true;
573 }
574
575 /**
576 * Copy C2GraphicView to MediaImage2.
577 */
578 status_t copyToMediaImage() {
579 if (mInitCheck != OK) {
580 return mInitCheck;
581 }
582 return ImageCopy(mBackBuffer->base(), getMediaImage(), mView);
583 }
584
585 const sp<ABuffer> &imageData() const { return mMediaImage; }
586
587private:
588 status_t mInitCheck;
589
590 const C2GraphicView mView;
591 uint32_t mWidth;
592 uint32_t mHeight;
Wonsik Kimd79ee1f2020-08-27 17:41:56 -0700593 int32_t mClientColorFormat; ///< SDK color format for MediaImage
594 int32_t mComponentColorFormat; ///< SDK color format from component
Pawin Vongmasa36653902018-11-15 00:10:25 -0800595 sp<ABuffer> mWrapped; ///< wrapped buffer (if we can map C2Buffer to an ABuffer)
596 uint32_t mAllocatedDepth;
597 uint32_t mBackBufferSize;
598 sp<ABuffer> mMediaImage;
599 std::function<sp<ABuffer>(size_t)> mAlloc;
600
601 sp<ABuffer> mBackBuffer; ///< backing buffer if we have to copy C2Buffer <=> ABuffer
602
603 MediaImage2 *getMediaImage() {
604 return (MediaImage2 *)mMediaImage->base();
605 }
606};
607
608} // namespace
609
610// GraphicBlockBuffer
611
612// static
613sp<GraphicBlockBuffer> GraphicBlockBuffer::Allocate(
614 const sp<AMessage> &format,
615 const std::shared_ptr<C2GraphicBlock> &block,
616 std::function<sp<ABuffer>(size_t)> alloc) {
617 C2GraphicView view(block->map().get());
618 if (view.error() != C2_OK) {
619 ALOGD("C2GraphicBlock::map failed: %d", view.error());
620 return nullptr;
621 }
622
Wonsik Kimd79ee1f2020-08-27 17:41:56 -0700623 GraphicView2MediaImageConverter converter(view, format, false /* copy */);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800624 if (converter.initCheck() != OK) {
625 ALOGD("Converter init failed: %d", converter.initCheck());
626 return nullptr;
627 }
628 bool wrapped = true;
629 sp<ABuffer> buffer = converter.wrap();
630 if (buffer == nullptr) {
631 buffer = alloc(converter.backBufferSize());
632 if (!converter.setBackBuffer(buffer)) {
633 ALOGD("Converter failed to set back buffer");
634 return nullptr;
635 }
636 wrapped = false;
637 }
638 return new GraphicBlockBuffer(
639 format,
640 buffer,
641 std::move(view),
642 block,
643 converter.imageData(),
644 wrapped);
645}
646
647GraphicBlockBuffer::GraphicBlockBuffer(
648 const sp<AMessage> &format,
649 const sp<ABuffer> &buffer,
650 C2GraphicView &&view,
651 const std::shared_ptr<C2GraphicBlock> &block,
652 const sp<ABuffer> &imageData,
653 bool wrapped)
654 : Codec2Buffer(format, buffer),
655 mView(view),
656 mBlock(block),
Pawin Vongmasa36653902018-11-15 00:10:25 -0800657 mWrapped(wrapped) {
658 setImageData(imageData);
659}
660
661std::shared_ptr<C2Buffer> GraphicBlockBuffer::asC2Buffer() {
662 uint32_t width = mView.width();
663 uint32_t height = mView.height();
664 if (!mWrapped) {
665 (void)ImageCopy(mView, base(), imageData());
666 }
667 return C2Buffer::CreateGraphicBuffer(
668 mBlock->share(C2Rect(width, height), C2Fence()));
669}
670
671// GraphicMetadataBuffer
672GraphicMetadataBuffer::GraphicMetadataBuffer(
673 const sp<AMessage> &format,
674 const std::shared_ptr<C2Allocator> &alloc)
675 : Codec2Buffer(format, new ABuffer(sizeof(VideoNativeMetadata))),
676 mAlloc(alloc) {
677 ((VideoNativeMetadata *)base())->pBuffer = nullptr;
678}
679
680std::shared_ptr<C2Buffer> GraphicMetadataBuffer::asC2Buffer() {
bohua222c0b2021-01-12 18:54:53 -0800681#ifdef __LP64__
682 static std::once_flag s_checkOnce;
Harish Mahendrakar731e9142021-04-21 17:20:39 -0700683 static bool s_is64bitOk {true};
bohua222c0b2021-01-12 18:54:53 -0800684 std::call_once(s_checkOnce, [&](){
685 const std::string abi32list =
686 ::android::base::GetProperty("ro.product.cpu.abilist32", "");
Harish Mahendrakar731e9142021-04-21 17:20:39 -0700687 if (!abi32list.empty()) {
688 int32_t inputSurfaceSetting =
689 ::android::base::GetIntProperty("debug.stagefright.c2inputsurface", int32_t(0));
690 s_is64bitOk = inputSurfaceSetting != 0;
bohua222c0b2021-01-12 18:54:53 -0800691 }
692 });
693
Harish Mahendrakar731e9142021-04-21 17:20:39 -0700694 if (!s_is64bitOk) {
695 ALOGE("GraphicMetadataBuffer does not work in 32+64 system if compiled as 64-bit object"\
696 "when debug.stagefright.c2inputsurface is set to 0");
bohua222c0b2021-01-12 18:54:53 -0800697 return nullptr;
698 }
699#endif
700
Pawin Vongmasa36653902018-11-15 00:10:25 -0800701 VideoNativeMetadata *meta = (VideoNativeMetadata *)base();
702 ANativeWindowBuffer *buffer = (ANativeWindowBuffer *)meta->pBuffer;
703 if (buffer == nullptr) {
704 ALOGD("VideoNativeMetadata contains null buffer");
705 return nullptr;
706 }
707
708 ALOGV("VideoNativeMetadata: %dx%d", buffer->width, buffer->height);
709 C2Handle *handle = WrapNativeCodec2GrallocHandle(
Sungtak Leea4d13be2019-01-23 15:24:46 -0800710 buffer->handle,
Pawin Vongmasa36653902018-11-15 00:10:25 -0800711 buffer->width,
712 buffer->height,
713 buffer->format,
714 buffer->usage,
715 buffer->stride);
716 std::shared_ptr<C2GraphicAllocation> alloc;
717 c2_status_t err = mAlloc->priorGraphicAllocation(handle, &alloc);
718 if (err != C2_OK) {
719 ALOGD("Failed to wrap VideoNativeMetadata into C2GraphicAllocation");
Chih-Yu Huangc0ac3552021-03-11 14:37:10 +0900720 native_handle_close(handle);
721 native_handle_delete(handle);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800722 return nullptr;
723 }
724 std::shared_ptr<C2GraphicBlock> block = _C2BlockFactory::CreateGraphicBlock(alloc);
725
726 meta->pBuffer = 0;
Wonsik Kimebe0f9e2019-07-03 11:06:51 -0700727 // TODO: wrap this in C2Fence so that the component can wait when it
728 // actually starts processing.
729 if (meta->nFenceFd >= 0) {
730 sp<Fence> fence(new Fence(meta->nFenceFd));
731 fence->waitForever(LOG_TAG);
732 }
Pawin Vongmasa36653902018-11-15 00:10:25 -0800733 return C2Buffer::CreateGraphicBuffer(
734 block->share(C2Rect(buffer->width, buffer->height), C2Fence()));
Pawin Vongmasa36653902018-11-15 00:10:25 -0800735}
736
737// ConstGraphicBlockBuffer
738
739// static
740sp<ConstGraphicBlockBuffer> ConstGraphicBlockBuffer::Allocate(
741 const sp<AMessage> &format,
742 const std::shared_ptr<C2Buffer> &buffer,
743 std::function<sp<ABuffer>(size_t)> alloc) {
744 if (!buffer
745 || buffer->data().type() != C2BufferData::GRAPHIC
746 || buffer->data().graphicBlocks().size() != 1u) {
747 ALOGD("C2Buffer precond fail");
748 return nullptr;
749 }
750 std::unique_ptr<const C2GraphicView> view(std::make_unique<const C2GraphicView>(
751 buffer->data().graphicBlocks()[0].map().get()));
752 std::unique_ptr<const C2GraphicView> holder;
753
Wonsik Kimd79ee1f2020-08-27 17:41:56 -0700754 GraphicView2MediaImageConverter converter(*view, format, false /* copy */);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800755 if (converter.initCheck() != OK) {
756 ALOGD("Converter init failed: %d", converter.initCheck());
757 return nullptr;
758 }
759 bool wrapped = true;
760 sp<ABuffer> aBuffer = converter.wrap();
761 if (aBuffer == nullptr) {
762 aBuffer = alloc(converter.backBufferSize());
763 if (!converter.setBackBuffer(aBuffer)) {
764 ALOGD("Converter failed to set back buffer");
765 return nullptr;
766 }
767 wrapped = false;
768 converter.copyToMediaImage();
769 // We don't need the view.
770 holder = std::move(view);
771 }
772 return new ConstGraphicBlockBuffer(
773 format,
774 aBuffer,
775 std::move(view),
776 buffer,
777 converter.imageData(),
778 wrapped);
779}
780
781// static
782sp<ConstGraphicBlockBuffer> ConstGraphicBlockBuffer::AllocateEmpty(
783 const sp<AMessage> &format,
784 std::function<sp<ABuffer>(size_t)> alloc) {
785 int32_t width, height;
786 if (!format->findInt32("width", &width)
787 || !format->findInt32("height", &height)) {
788 ALOGD("format had no width / height");
789 return nullptr;
790 }
Wonsik Kim08a8a2b2021-05-10 19:03:47 -0700791 int32_t colorFormat = COLOR_FormatYUV420Flexible;
792 int32_t bpp = 12; // 8(Y) + 2(U) + 2(V)
793 if (format->findInt32(KEY_COLOR_FORMAT, &colorFormat)) {
794 if (colorFormat == COLOR_FormatYUVP010) {
795 bpp = 24; // 16(Y) + 4(U) + 4(V)
796 }
797 }
798 sp<ABuffer> aBuffer(alloc(align(width, 16) * align(height, 16) * bpp / 8));
Pawin Vongmasa36653902018-11-15 00:10:25 -0800799 return new ConstGraphicBlockBuffer(
800 format,
801 aBuffer,
802 nullptr,
803 nullptr,
804 nullptr,
805 false);
806}
807
808ConstGraphicBlockBuffer::ConstGraphicBlockBuffer(
809 const sp<AMessage> &format,
810 const sp<ABuffer> &aBuffer,
811 std::unique_ptr<const C2GraphicView> &&view,
812 const std::shared_ptr<C2Buffer> &buffer,
813 const sp<ABuffer> &imageData,
814 bool wrapped)
815 : Codec2Buffer(format, aBuffer),
816 mView(std::move(view)),
817 mBufferRef(buffer),
818 mWrapped(wrapped) {
Wonsik Kimc48ddcf2019-02-11 16:16:57 -0800819 setImageData(imageData);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800820}
821
822std::shared_ptr<C2Buffer> ConstGraphicBlockBuffer::asC2Buffer() {
Wonsik Kimf9b32122020-04-02 11:30:17 -0700823 return mBufferRef;
824}
825
826void ConstGraphicBlockBuffer::clearC2BufferRefs() {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800827 mView.reset();
Wonsik Kimf9b32122020-04-02 11:30:17 -0700828 mBufferRef.reset();
Pawin Vongmasa36653902018-11-15 00:10:25 -0800829}
830
831bool ConstGraphicBlockBuffer::canCopy(const std::shared_ptr<C2Buffer> &buffer) const {
832 if (mWrapped || mBufferRef) {
833 ALOGD("ConstGraphicBlockBuffer::canCopy: %swrapped ; buffer ref %s",
834 mWrapped ? "" : "not ", mBufferRef ? "exists" : "doesn't exist");
835 return false;
836 }
837 if (!buffer) {
838 // Nothing to copy, so we can copy by doing nothing.
839 return true;
840 }
841 if (buffer->data().type() != C2BufferData::GRAPHIC) {
842 ALOGD("ConstGraphicBlockBuffer::canCopy: buffer precondition unsatisfied");
843 return false;
844 }
845 if (buffer->data().graphicBlocks().size() == 0) {
846 return true;
847 } else if (buffer->data().graphicBlocks().size() != 1u) {
848 ALOGD("ConstGraphicBlockBuffer::canCopy: too many blocks");
849 return false;
850 }
851
Pawin Vongmasa36653902018-11-15 00:10:25 -0800852 GraphicView2MediaImageConverter converter(
Wonsik Kimd79ee1f2020-08-27 17:41:56 -0700853 buffer->data().graphicBlocks()[0].map().get(),
854 // FIXME: format() is not const, but we cannot change it, so do a const cast here
855 const_cast<ConstGraphicBlockBuffer *>(this)->format(),
856 true /* copy */);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800857 if (converter.initCheck() != OK) {
858 ALOGD("ConstGraphicBlockBuffer::canCopy: converter init failed: %d", converter.initCheck());
859 return false;
860 }
861 if (converter.backBufferSize() > capacity()) {
862 ALOGD("ConstGraphicBlockBuffer::canCopy: insufficient capacity: req %u has %zu",
863 converter.backBufferSize(), capacity());
864 return false;
865 }
866 return true;
867}
868
869bool ConstGraphicBlockBuffer::copy(const std::shared_ptr<C2Buffer> &buffer) {
870 if (!buffer || buffer->data().graphicBlocks().size() == 0) {
871 setRange(0, 0);
872 return true;
873 }
Pawin Vongmasa36653902018-11-15 00:10:25 -0800874
875 GraphicView2MediaImageConverter converter(
Wonsik Kimd79ee1f2020-08-27 17:41:56 -0700876 buffer->data().graphicBlocks()[0].map().get(), format(), true /* copy */);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800877 if (converter.initCheck() != OK) {
878 ALOGD("ConstGraphicBlockBuffer::copy: converter init failed: %d", converter.initCheck());
879 return false;
880 }
881 sp<ABuffer> aBuffer = new ABuffer(base(), capacity());
882 if (!converter.setBackBuffer(aBuffer)) {
883 ALOGD("ConstGraphicBlockBuffer::copy: set back buffer failed");
884 return false;
885 }
Pin-chih Lin1971e2c2019-04-15 19:36:26 +0800886 setRange(0, aBuffer->size()); // align size info
Pawin Vongmasa36653902018-11-15 00:10:25 -0800887 converter.copyToMediaImage();
888 setImageData(converter.imageData());
889 mBufferRef = buffer;
890 return true;
891}
892
893// EncryptedLinearBlockBuffer
894
895EncryptedLinearBlockBuffer::EncryptedLinearBlockBuffer(
896 const sp<AMessage> &format,
897 const std::shared_ptr<C2LinearBlock> &block,
898 const sp<IMemory> &memory,
899 int32_t heapSeqNum)
Ytai Ben-Tsvi7dd39722019-09-05 15:14:30 -0700900 // TODO: Using unsecurePointer() has some associated security pitfalls
901 // (see declaration for details).
902 // Either document why it is safe in this case or address the
903 // issue (e.g. by copying).
904 : Codec2Buffer(format, new ABuffer(memory->unsecurePointer(), memory->size())),
Pawin Vongmasa36653902018-11-15 00:10:25 -0800905 mBlock(block),
906 mMemory(memory),
907 mHeapSeqNum(heapSeqNum) {
908}
909
910std::shared_ptr<C2Buffer> EncryptedLinearBlockBuffer::asC2Buffer() {
911 return C2Buffer::CreateLinearBuffer(mBlock->share(offset(), size(), C2Fence()));
912}
913
914void EncryptedLinearBlockBuffer::fillSourceBuffer(
Robert Shih895fba92019-07-16 16:29:44 -0700915 hardware::drm::V1_0::SharedBuffer *source) {
916 BufferChannelBase::IMemoryToSharedBuffer(mMemory, mHeapSeqNum, source);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800917}
918
919void EncryptedLinearBlockBuffer::fillSourceBuffer(
920 hardware::cas::native::V1_0::SharedBuffer *source) {
921 ssize_t offset;
922 size_t size;
923
924 mHidlMemory = hardware::fromHeap(mMemory->getMemory(&offset, &size));
925 source->heapBase = *mHidlMemory;
926 source->offset = offset;
927 source->size = size;
928}
929
930bool EncryptedLinearBlockBuffer::copyDecryptedContent(
931 const sp<IMemory> &decrypted, size_t length) {
932 C2WriteView view = mBlock->map().get();
933 if (view.error() != C2_OK) {
934 return false;
935 }
936 if (view.size() < length) {
937 return false;
938 }
Ytai Ben-Tsvi7dd39722019-09-05 15:14:30 -0700939 memcpy(view.data(), decrypted->unsecurePointer(), length);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800940 return true;
941}
942
943bool EncryptedLinearBlockBuffer::copyDecryptedContentFromMemory(size_t length) {
944 return copyDecryptedContent(mMemory, length);
945}
946
947native_handle_t *EncryptedLinearBlockBuffer::handle() const {
948 return const_cast<native_handle_t *>(mBlock->handle());
949}
950
951} // namespace android