blob: fa0d4ac3f88dfe5b0e101ed40f39899c48e8c6bf [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
215 * \param colorFormat desired SDK color format for the MediaImage (if this is a flexible format,
216 * an attempt is made to simply represent the graphic view as a flexible SDK format
217 * without a memcpy)
Wonsik Kim7d966312019-06-04 14:00:49 -0700218 * \param copy whether the converter is used for copy or not
Pawin Vongmasa36653902018-11-15 00:10:25 -0800219 */
220 GraphicView2MediaImageConverter(
Wonsik Kim7d966312019-06-04 14:00:49 -0700221 const C2GraphicView &view, int32_t colorFormat, bool copy)
Pawin Vongmasa36653902018-11-15 00:10:25 -0800222 : mInitCheck(NO_INIT),
223 mView(view),
224 mWidth(view.width()),
225 mHeight(view.height()),
226 mColorFormat(colorFormat),
227 mAllocatedDepth(0),
228 mBackBufferSize(0),
229 mMediaImage(new ABuffer(sizeof(MediaImage2))) {
230 if (view.error() != C2_OK) {
231 ALOGD("Converter: view.error() = %d", view.error());
232 mInitCheck = BAD_VALUE;
233 return;
234 }
235 MediaImage2 *mediaImage = (MediaImage2 *)mMediaImage->base();
236 const C2PlanarLayout &layout = view.layout();
237 if (layout.numPlanes == 0) {
238 ALOGD("Converter: 0 planes");
239 mInitCheck = BAD_VALUE;
240 return;
241 }
Harish Mahendrakarcac53852019-02-20 10:59:10 -0800242 memset(mediaImage, 0, sizeof(*mediaImage));
Pawin Vongmasa36653902018-11-15 00:10:25 -0800243 mAllocatedDepth = layout.planes[0].allocatedDepth;
244 uint32_t bitDepth = layout.planes[0].bitDepth;
245
246 // align width and height to support subsampling cleanly
Wonsik Kim8bfa17a2019-05-30 22:12:30 -0700247 uint32_t stride = align(view.crop().width, 2) * divUp(layout.planes[0].allocatedDepth, 8u);
248 uint32_t vStride = align(view.crop().height, 2);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800249
250 switch (layout.type) {
251 case C2PlanarLayout::TYPE_YUV:
252 mediaImage->mType = MediaImage2::MEDIA_IMAGE_TYPE_YUV;
253 if (layout.numPlanes != 3) {
254 ALOGD("Converter: %d planes for YUV layout", layout.numPlanes);
255 mInitCheck = BAD_VALUE;
256 return;
257 }
258 if (layout.planes[0].channel != C2PlaneInfo::CHANNEL_Y
259 || layout.planes[1].channel != C2PlaneInfo::CHANNEL_CB
260 || layout.planes[2].channel != C2PlaneInfo::CHANNEL_CR
261 || layout.planes[0].colSampling != 1
262 || layout.planes[0].rowSampling != 1
263 || layout.planes[1].colSampling != 2
264 || layout.planes[1].rowSampling != 2
265 || layout.planes[2].colSampling != 2
266 || layout.planes[2].rowSampling != 2) {
267 ALOGD("Converter: not YUV420 for YUV layout");
268 mInitCheck = BAD_VALUE;
269 return;
270 }
271 switch (mColorFormat) {
272 case COLOR_FormatYUV420Flexible:
Wonsik Kim7d966312019-06-04 14:00:49 -0700273 if (!copy) {
274 // try to map directly. check if the planes are near one another
275 const uint8_t *minPtr = mView.data()[0];
276 const uint8_t *maxPtr = mView.data()[0];
277 int32_t planeSize = 0;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800278 for (uint32_t i = 0; i < layout.numPlanes; ++i) {
279 const C2PlaneInfo &plane = layout.planes[i];
Wonsik Kim2eb06312020-12-03 11:07:58 -0800280 int64_t planeStride = std::abs(plane.rowInc / plane.colInc);
281 ssize_t minOffset = plane.minOffset(
282 mWidth / plane.colSampling, mHeight / plane.rowSampling);
283 ssize_t maxOffset = plane.maxOffset(
284 mWidth / plane.colSampling, mHeight / plane.rowSampling);
Wonsik Kim7d966312019-06-04 14:00:49 -0700285 if (minPtr > mView.data()[i] + minOffset) {
286 minPtr = mView.data()[i] + minOffset;
287 }
288 if (maxPtr < mView.data()[i] + maxOffset) {
289 maxPtr = mView.data()[i] + maxOffset;
290 }
Wonsik Kim2eb06312020-12-03 11:07:58 -0800291 planeSize += planeStride * divUp(mAllocatedDepth, 8u)
292 * align(mHeight, 64) / plane.rowSampling;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800293 }
Wonsik Kim7d966312019-06-04 14:00:49 -0700294
Wonsik Kim2eb06312020-12-03 11:07:58 -0800295 if (minPtr == mView.data()[0] && (maxPtr - minPtr + 1) <= planeSize) {
Wonsik Kim7d966312019-06-04 14:00:49 -0700296 // FIXME: this is risky as reading/writing data out of bound results
297 // in an undefined behavior, but gralloc does assume a
298 // contiguous mapping
299 for (uint32_t i = 0; i < layout.numPlanes; ++i) {
300 const C2PlaneInfo &plane = layout.planes[i];
301 mediaImage->mPlane[i].mOffset = mView.data()[i] - minPtr;
302 mediaImage->mPlane[i].mColInc = plane.colInc;
303 mediaImage->mPlane[i].mRowInc = plane.rowInc;
304 mediaImage->mPlane[i].mHorizSubsampling = plane.colSampling;
305 mediaImage->mPlane[i].mVertSubsampling = plane.rowSampling;
306 }
307 mWrapped = new ABuffer(const_cast<uint8_t *>(minPtr),
308 maxPtr - minPtr + 1);
309 break;
310 }
Pawin Vongmasa36653902018-11-15 00:10:25 -0800311 }
Wonsik Kim7d966312019-06-04 14:00:49 -0700312 [[fallthrough]];
Pawin Vongmasa36653902018-11-15 00:10:25 -0800313
314 case COLOR_FormatYUV420Planar:
315 case COLOR_FormatYUV420PackedPlanar:
316 mediaImage->mPlane[mediaImage->Y].mOffset = 0;
317 mediaImage->mPlane[mediaImage->Y].mColInc = 1;
Wonsik Kim8bfa17a2019-05-30 22:12:30 -0700318 mediaImage->mPlane[mediaImage->Y].mRowInc = stride;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800319 mediaImage->mPlane[mediaImage->Y].mHorizSubsampling = 1;
320 mediaImage->mPlane[mediaImage->Y].mVertSubsampling = 1;
321
Wonsik Kim8bfa17a2019-05-30 22:12:30 -0700322 mediaImage->mPlane[mediaImage->U].mOffset = stride * vStride;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800323 mediaImage->mPlane[mediaImage->U].mColInc = 1;
Wonsik Kim8bfa17a2019-05-30 22:12:30 -0700324 mediaImage->mPlane[mediaImage->U].mRowInc = stride / 2;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800325 mediaImage->mPlane[mediaImage->U].mHorizSubsampling = 2;
326 mediaImage->mPlane[mediaImage->U].mVertSubsampling = 2;
327
Wonsik Kim8bfa17a2019-05-30 22:12:30 -0700328 mediaImage->mPlane[mediaImage->V].mOffset = stride * vStride * 5 / 4;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800329 mediaImage->mPlane[mediaImage->V].mColInc = 1;
Wonsik Kim8bfa17a2019-05-30 22:12:30 -0700330 mediaImage->mPlane[mediaImage->V].mRowInc = stride / 2;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800331 mediaImage->mPlane[mediaImage->V].mHorizSubsampling = 2;
332 mediaImage->mPlane[mediaImage->V].mVertSubsampling = 2;
333 break;
334
335 case COLOR_FormatYUV420SemiPlanar:
336 case COLOR_FormatYUV420PackedSemiPlanar:
337 mediaImage->mPlane[mediaImage->Y].mOffset = 0;
338 mediaImage->mPlane[mediaImage->Y].mColInc = 1;
Wonsik Kim8bfa17a2019-05-30 22:12:30 -0700339 mediaImage->mPlane[mediaImage->Y].mRowInc = stride;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800340 mediaImage->mPlane[mediaImage->Y].mHorizSubsampling = 1;
341 mediaImage->mPlane[mediaImage->Y].mVertSubsampling = 1;
342
Wonsik Kim8bfa17a2019-05-30 22:12:30 -0700343 mediaImage->mPlane[mediaImage->U].mOffset = stride * vStride;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800344 mediaImage->mPlane[mediaImage->U].mColInc = 2;
Wonsik Kim8bfa17a2019-05-30 22:12:30 -0700345 mediaImage->mPlane[mediaImage->U].mRowInc = stride;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800346 mediaImage->mPlane[mediaImage->U].mHorizSubsampling = 2;
347 mediaImage->mPlane[mediaImage->U].mVertSubsampling = 2;
348
Wonsik Kim8bfa17a2019-05-30 22:12:30 -0700349 mediaImage->mPlane[mediaImage->V].mOffset = stride * vStride + 1;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800350 mediaImage->mPlane[mediaImage->V].mColInc = 2;
Wonsik Kim8bfa17a2019-05-30 22:12:30 -0700351 mediaImage->mPlane[mediaImage->V].mRowInc = stride;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800352 mediaImage->mPlane[mediaImage->V].mHorizSubsampling = 2;
353 mediaImage->mPlane[mediaImage->V].mVertSubsampling = 2;
354 break;
355
Wonsik Kim29e3c4d2020-09-02 12:19:44 -0700356 case COLOR_FormatYUVP010:
357 if (!copy) {
358 // try to map directly. check if the planes are near one another
359 const uint8_t *minPtr = mView.data()[0];
360 const uint8_t *maxPtr = mView.data()[0];
361 int32_t planeSize = 0;
362 for (uint32_t i = 0; i < layout.numPlanes; ++i) {
363 const C2PlaneInfo &plane = layout.planes[i];
364 ssize_t minOffset = plane.minOffset(
365 mWidth / plane.colSampling, mHeight / plane.rowSampling);
366 ssize_t maxOffset = plane.maxOffset(
367 mWidth / plane.colSampling, mHeight / plane.rowSampling);
368 if (minPtr > mView.data()[i] + minOffset) {
369 minPtr = mView.data()[i] + minOffset;
370 }
371 if (maxPtr < mView.data()[i] + maxOffset) {
372 maxPtr = mView.data()[i] + maxOffset;
373 }
374 planeSize += std::abs(plane.rowInc) * align(mHeight, 64)
375 / plane.rowSampling / plane.colSampling
376 * divUp(mAllocatedDepth, 8u);
377 }
378
379 if ((maxPtr - minPtr + 1) <= planeSize) {
380 // FIXME: this is risky as reading/writing data out of bound results
381 // in an undefined behavior, but gralloc does assume a
382 // contiguous mapping
383 for (uint32_t i = 0; i < layout.numPlanes; ++i) {
384 const C2PlaneInfo &plane = layout.planes[i];
385 mediaImage->mPlane[i].mOffset = mView.data()[i] - minPtr;
386 mediaImage->mPlane[i].mColInc = plane.colInc;
387 mediaImage->mPlane[i].mRowInc = plane.rowInc;
388 mediaImage->mPlane[i].mHorizSubsampling = plane.colSampling;
389 mediaImage->mPlane[i].mVertSubsampling = plane.rowSampling;
390 }
391 mWrapped = new ABuffer(
392 const_cast<uint8_t *>(minPtr),
393 maxPtr - minPtr + divUp(mAllocatedDepth, 8u));
394 break;
395 }
396 }
397 mediaImage->mPlane[mediaImage->Y].mOffset = 0;
398 mediaImage->mPlane[mediaImage->Y].mColInc = 2;
399 mediaImage->mPlane[mediaImage->Y].mRowInc = stride * 2;
400 mediaImage->mPlane[mediaImage->Y].mHorizSubsampling = 1;
401 mediaImage->mPlane[mediaImage->Y].mVertSubsampling = 1;
402
403 mediaImage->mPlane[mediaImage->U].mOffset = stride * vStride * 2;
404 mediaImage->mPlane[mediaImage->U].mColInc = 4;
405 mediaImage->mPlane[mediaImage->U].mRowInc = stride * 2;
406 mediaImage->mPlane[mediaImage->U].mHorizSubsampling = 2;
407 mediaImage->mPlane[mediaImage->U].mVertSubsampling = 2;
408
409 mediaImage->mPlane[mediaImage->V].mOffset = stride * vStride * 2 + 2;
410 mediaImage->mPlane[mediaImage->V].mColInc = 4;
411 mediaImage->mPlane[mediaImage->V].mRowInc = stride * 2;
412 mediaImage->mPlane[mediaImage->V].mHorizSubsampling = 2;
413 mediaImage->mPlane[mediaImage->V].mVertSubsampling = 2;
414 break;
415
Pawin Vongmasa36653902018-11-15 00:10:25 -0800416 default:
417 ALOGD("Converter: incompactible color format (%d) for YUV layout", mColorFormat);
418 mInitCheck = BAD_VALUE;
419 return;
420 }
421 break;
422 case C2PlanarLayout::TYPE_YUVA:
423 mediaImage->mType = MediaImage2::MEDIA_IMAGE_TYPE_YUVA;
424 // We don't have an SDK YUVA format
425 ALOGD("Converter: incompactible color format (%d) for YUVA layout", mColorFormat);
426 mInitCheck = BAD_VALUE;
427 return;
428 case C2PlanarLayout::TYPE_RGB:
429 mediaImage->mType = MediaImage2::MEDIA_IMAGE_TYPE_RGB;
430 switch (mColorFormat) {
431 // TODO media image
432 case COLOR_FormatRGBFlexible:
433 case COLOR_Format24bitBGR888:
434 case COLOR_Format24bitRGB888:
435 break;
436 default:
437 ALOGD("Converter: incompactible color format (%d) for RGB layout", mColorFormat);
438 mInitCheck = BAD_VALUE;
439 return;
440 }
441 if (layout.numPlanes != 3) {
442 ALOGD("Converter: %d planes for RGB layout", layout.numPlanes);
443 mInitCheck = BAD_VALUE;
444 return;
445 }
446 break;
447 case C2PlanarLayout::TYPE_RGBA:
448 mediaImage->mType = MediaImage2::MEDIA_IMAGE_TYPE_RGBA;
449 switch (mColorFormat) {
450 // TODO media image
451 case COLOR_FormatRGBAFlexible:
452 case COLOR_Format32bitABGR8888:
453 case COLOR_Format32bitARGB8888:
454 case COLOR_Format32bitBGRA8888:
455 break;
456 default:
457 ALOGD("Incompactible color format (%d) for RGBA layout", mColorFormat);
458 mInitCheck = BAD_VALUE;
459 return;
460 }
461 if (layout.numPlanes != 4) {
462 ALOGD("Converter: %d planes for RGBA layout", layout.numPlanes);
463 mInitCheck = BAD_VALUE;
464 return;
465 }
466 break;
467 default:
468 mediaImage->mType = MediaImage2::MEDIA_IMAGE_TYPE_UNKNOWN;
469 ALOGD("Unknown layout");
470 mInitCheck = BAD_VALUE;
471 return;
472 }
473 mediaImage->mNumPlanes = layout.numPlanes;
Harish Mahendrakarf7c49e22019-05-24 14:19:16 -0700474 mediaImage->mWidth = view.crop().width;
475 mediaImage->mHeight = view.crop().height;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800476 mediaImage->mBitDepth = bitDepth;
477 mediaImage->mBitDepthAllocated = mAllocatedDepth;
478
479 uint32_t bufferSize = 0;
480 for (uint32_t i = 0; i < layout.numPlanes; ++i) {
481 const C2PlaneInfo &plane = layout.planes[i];
482 if (plane.allocatedDepth < plane.bitDepth
483 || plane.rightShift != plane.allocatedDepth - plane.bitDepth) {
484 ALOGD("rightShift value of %u unsupported", plane.rightShift);
485 mInitCheck = BAD_VALUE;
486 return;
487 }
488 if (plane.allocatedDepth > 8 && plane.endianness != C2PlaneInfo::NATIVE) {
489 ALOGD("endianness value of %u unsupported", plane.endianness);
490 mInitCheck = BAD_VALUE;
491 return;
492 }
493 if (plane.allocatedDepth != mAllocatedDepth || plane.bitDepth != bitDepth) {
494 ALOGV("different allocatedDepth/bitDepth per plane unsupported");
495 mInitCheck = BAD_VALUE;
496 return;
497 }
Wonsik Kim8bfa17a2019-05-30 22:12:30 -0700498 bufferSize += stride * vStride
Pawin Vongmasa36653902018-11-15 00:10:25 -0800499 / plane.rowSampling / plane.colSampling;
500 }
501
502 mBackBufferSize = bufferSize;
503 mInitCheck = OK;
504 }
505
506 status_t initCheck() const { return mInitCheck; }
507
508 uint32_t backBufferSize() const { return mBackBufferSize; }
509
510 /**
511 * Wrap C2GraphicView using a MediaImage2. Note that if not wrapped, the content is not mapped
512 * in this function --- the caller should use CopyGraphicView2MediaImage() function to copy the
513 * data into a backing buffer explicitly.
514 *
515 * \return media buffer. This is null if wrapping failed.
516 */
517 sp<ABuffer> wrap() const {
518 if (mBackBuffer == nullptr) {
519 return mWrapped;
520 }
521 return nullptr;
522 }
523
524 bool setBackBuffer(const sp<ABuffer> &backBuffer) {
Wonsik Kim186fdbf2019-01-29 13:30:01 -0800525 if (backBuffer == nullptr) {
526 return false;
527 }
Pawin Vongmasa36653902018-11-15 00:10:25 -0800528 if (backBuffer->capacity() < mBackBufferSize) {
529 return false;
530 }
531 backBuffer->setRange(0, mBackBufferSize);
532 mBackBuffer = backBuffer;
533 return true;
534 }
535
536 /**
537 * Copy C2GraphicView to MediaImage2.
538 */
539 status_t copyToMediaImage() {
540 if (mInitCheck != OK) {
541 return mInitCheck;
542 }
543 return ImageCopy(mBackBuffer->base(), getMediaImage(), mView);
544 }
545
546 const sp<ABuffer> &imageData() const { return mMediaImage; }
547
548private:
549 status_t mInitCheck;
550
551 const C2GraphicView mView;
552 uint32_t mWidth;
553 uint32_t mHeight;
554 int32_t mColorFormat; ///< SDK color format for MediaImage
555 sp<ABuffer> mWrapped; ///< wrapped buffer (if we can map C2Buffer to an ABuffer)
556 uint32_t mAllocatedDepth;
557 uint32_t mBackBufferSize;
558 sp<ABuffer> mMediaImage;
559 std::function<sp<ABuffer>(size_t)> mAlloc;
560
561 sp<ABuffer> mBackBuffer; ///< backing buffer if we have to copy C2Buffer <=> ABuffer
562
563 MediaImage2 *getMediaImage() {
564 return (MediaImage2 *)mMediaImage->base();
565 }
566};
567
568} // namespace
569
570// GraphicBlockBuffer
571
572// static
573sp<GraphicBlockBuffer> GraphicBlockBuffer::Allocate(
574 const sp<AMessage> &format,
575 const std::shared_ptr<C2GraphicBlock> &block,
576 std::function<sp<ABuffer>(size_t)> alloc) {
577 C2GraphicView view(block->map().get());
578 if (view.error() != C2_OK) {
579 ALOGD("C2GraphicBlock::map failed: %d", view.error());
580 return nullptr;
581 }
582
583 int32_t colorFormat = COLOR_FormatYUV420Flexible;
584 (void)format->findInt32("color-format", &colorFormat);
585
Wonsik Kim7d966312019-06-04 14:00:49 -0700586 GraphicView2MediaImageConverter converter(view, colorFormat, false /* copy */);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800587 if (converter.initCheck() != OK) {
588 ALOGD("Converter init failed: %d", converter.initCheck());
589 return nullptr;
590 }
591 bool wrapped = true;
592 sp<ABuffer> buffer = converter.wrap();
593 if (buffer == nullptr) {
594 buffer = alloc(converter.backBufferSize());
595 if (!converter.setBackBuffer(buffer)) {
596 ALOGD("Converter failed to set back buffer");
597 return nullptr;
598 }
599 wrapped = false;
600 }
601 return new GraphicBlockBuffer(
602 format,
603 buffer,
604 std::move(view),
605 block,
606 converter.imageData(),
607 wrapped);
608}
609
610GraphicBlockBuffer::GraphicBlockBuffer(
611 const sp<AMessage> &format,
612 const sp<ABuffer> &buffer,
613 C2GraphicView &&view,
614 const std::shared_ptr<C2GraphicBlock> &block,
615 const sp<ABuffer> &imageData,
616 bool wrapped)
617 : Codec2Buffer(format, buffer),
618 mView(view),
619 mBlock(block),
Pawin Vongmasa36653902018-11-15 00:10:25 -0800620 mWrapped(wrapped) {
621 setImageData(imageData);
622}
623
624std::shared_ptr<C2Buffer> GraphicBlockBuffer::asC2Buffer() {
625 uint32_t width = mView.width();
626 uint32_t height = mView.height();
627 if (!mWrapped) {
628 (void)ImageCopy(mView, base(), imageData());
629 }
630 return C2Buffer::CreateGraphicBuffer(
631 mBlock->share(C2Rect(width, height), C2Fence()));
632}
633
634// GraphicMetadataBuffer
635GraphicMetadataBuffer::GraphicMetadataBuffer(
636 const sp<AMessage> &format,
637 const std::shared_ptr<C2Allocator> &alloc)
638 : Codec2Buffer(format, new ABuffer(sizeof(VideoNativeMetadata))),
639 mAlloc(alloc) {
640 ((VideoNativeMetadata *)base())->pBuffer = nullptr;
641}
642
643std::shared_ptr<C2Buffer> GraphicMetadataBuffer::asC2Buffer() {
bohua222c0b2021-01-12 18:54:53 -0800644#ifdef __LP64__
645 static std::once_flag s_checkOnce;
646 static bool s_64bitonly {false};
647 std::call_once(s_checkOnce, [&](){
648 const std::string abi32list =
649 ::android::base::GetProperty("ro.product.cpu.abilist32", "");
650 if (abi32list.empty()) {
651 s_64bitonly = true;
652 }
653 });
654
655 if (!s_64bitonly) {
656 ALOGE("GraphicMetadataBuffer does not work in 32+64 system if compiled as 64-bit object");
657 return nullptr;
658 }
659#endif
660
Pawin Vongmasa36653902018-11-15 00:10:25 -0800661 VideoNativeMetadata *meta = (VideoNativeMetadata *)base();
662 ANativeWindowBuffer *buffer = (ANativeWindowBuffer *)meta->pBuffer;
663 if (buffer == nullptr) {
664 ALOGD("VideoNativeMetadata contains null buffer");
665 return nullptr;
666 }
667
668 ALOGV("VideoNativeMetadata: %dx%d", buffer->width, buffer->height);
669 C2Handle *handle = WrapNativeCodec2GrallocHandle(
Sungtak Leea4d13be2019-01-23 15:24:46 -0800670 buffer->handle,
Pawin Vongmasa36653902018-11-15 00:10:25 -0800671 buffer->width,
672 buffer->height,
673 buffer->format,
674 buffer->usage,
675 buffer->stride);
676 std::shared_ptr<C2GraphicAllocation> alloc;
677 c2_status_t err = mAlloc->priorGraphicAllocation(handle, &alloc);
678 if (err != C2_OK) {
679 ALOGD("Failed to wrap VideoNativeMetadata into C2GraphicAllocation");
680 return nullptr;
681 }
682 std::shared_ptr<C2GraphicBlock> block = _C2BlockFactory::CreateGraphicBlock(alloc);
683
684 meta->pBuffer = 0;
Wonsik Kimebe0f9e2019-07-03 11:06:51 -0700685 // TODO: wrap this in C2Fence so that the component can wait when it
686 // actually starts processing.
687 if (meta->nFenceFd >= 0) {
688 sp<Fence> fence(new Fence(meta->nFenceFd));
689 fence->waitForever(LOG_TAG);
690 }
Pawin Vongmasa36653902018-11-15 00:10:25 -0800691 return C2Buffer::CreateGraphicBuffer(
692 block->share(C2Rect(buffer->width, buffer->height), C2Fence()));
Pawin Vongmasa36653902018-11-15 00:10:25 -0800693}
694
695// ConstGraphicBlockBuffer
696
697// static
698sp<ConstGraphicBlockBuffer> ConstGraphicBlockBuffer::Allocate(
699 const sp<AMessage> &format,
700 const std::shared_ptr<C2Buffer> &buffer,
701 std::function<sp<ABuffer>(size_t)> alloc) {
702 if (!buffer
703 || buffer->data().type() != C2BufferData::GRAPHIC
704 || buffer->data().graphicBlocks().size() != 1u) {
705 ALOGD("C2Buffer precond fail");
706 return nullptr;
707 }
708 std::unique_ptr<const C2GraphicView> view(std::make_unique<const C2GraphicView>(
709 buffer->data().graphicBlocks()[0].map().get()));
710 std::unique_ptr<const C2GraphicView> holder;
711
712 int32_t colorFormat = COLOR_FormatYUV420Flexible;
713 (void)format->findInt32("color-format", &colorFormat);
714
Wonsik Kim7d966312019-06-04 14:00:49 -0700715 GraphicView2MediaImageConverter converter(*view, colorFormat, false /* copy */);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800716 if (converter.initCheck() != OK) {
717 ALOGD("Converter init failed: %d", converter.initCheck());
718 return nullptr;
719 }
720 bool wrapped = true;
721 sp<ABuffer> aBuffer = converter.wrap();
722 if (aBuffer == nullptr) {
723 aBuffer = alloc(converter.backBufferSize());
724 if (!converter.setBackBuffer(aBuffer)) {
725 ALOGD("Converter failed to set back buffer");
726 return nullptr;
727 }
728 wrapped = false;
729 converter.copyToMediaImage();
730 // We don't need the view.
731 holder = std::move(view);
732 }
733 return new ConstGraphicBlockBuffer(
734 format,
735 aBuffer,
736 std::move(view),
737 buffer,
738 converter.imageData(),
739 wrapped);
740}
741
742// static
743sp<ConstGraphicBlockBuffer> ConstGraphicBlockBuffer::AllocateEmpty(
744 const sp<AMessage> &format,
745 std::function<sp<ABuffer>(size_t)> alloc) {
746 int32_t width, height;
747 if (!format->findInt32("width", &width)
748 || !format->findInt32("height", &height)) {
749 ALOGD("format had no width / height");
750 return nullptr;
751 }
Wonsik Kim8bfa17a2019-05-30 22:12:30 -0700752 // NOTE: we currently only support YUV420 formats for byte-buffer mode.
753 sp<ABuffer> aBuffer(alloc(align(width, 16) * align(height, 16) * 3 / 2));
Pawin Vongmasa36653902018-11-15 00:10:25 -0800754 return new ConstGraphicBlockBuffer(
755 format,
756 aBuffer,
757 nullptr,
758 nullptr,
759 nullptr,
760 false);
761}
762
763ConstGraphicBlockBuffer::ConstGraphicBlockBuffer(
764 const sp<AMessage> &format,
765 const sp<ABuffer> &aBuffer,
766 std::unique_ptr<const C2GraphicView> &&view,
767 const std::shared_ptr<C2Buffer> &buffer,
768 const sp<ABuffer> &imageData,
769 bool wrapped)
770 : Codec2Buffer(format, aBuffer),
771 mView(std::move(view)),
772 mBufferRef(buffer),
773 mWrapped(wrapped) {
Wonsik Kimc48ddcf2019-02-11 16:16:57 -0800774 setImageData(imageData);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800775}
776
777std::shared_ptr<C2Buffer> ConstGraphicBlockBuffer::asC2Buffer() {
Wonsik Kimf9b32122020-04-02 11:30:17 -0700778 return mBufferRef;
779}
780
781void ConstGraphicBlockBuffer::clearC2BufferRefs() {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800782 mView.reset();
Wonsik Kimf9b32122020-04-02 11:30:17 -0700783 mBufferRef.reset();
Pawin Vongmasa36653902018-11-15 00:10:25 -0800784}
785
786bool ConstGraphicBlockBuffer::canCopy(const std::shared_ptr<C2Buffer> &buffer) const {
787 if (mWrapped || mBufferRef) {
788 ALOGD("ConstGraphicBlockBuffer::canCopy: %swrapped ; buffer ref %s",
789 mWrapped ? "" : "not ", mBufferRef ? "exists" : "doesn't exist");
790 return false;
791 }
792 if (!buffer) {
793 // Nothing to copy, so we can copy by doing nothing.
794 return true;
795 }
796 if (buffer->data().type() != C2BufferData::GRAPHIC) {
797 ALOGD("ConstGraphicBlockBuffer::canCopy: buffer precondition unsatisfied");
798 return false;
799 }
800 if (buffer->data().graphicBlocks().size() == 0) {
801 return true;
802 } else if (buffer->data().graphicBlocks().size() != 1u) {
803 ALOGD("ConstGraphicBlockBuffer::canCopy: too many blocks");
804 return false;
805 }
806
807 int32_t colorFormat = COLOR_FormatYUV420Flexible;
808 // FIXME: format() is not const, but we cannot change it, so do a const cast here
809 const_cast<ConstGraphicBlockBuffer *>(this)->format()->findInt32("color-format", &colorFormat);
810
811 GraphicView2MediaImageConverter converter(
Wonsik Kim7d966312019-06-04 14:00:49 -0700812 buffer->data().graphicBlocks()[0].map().get(), colorFormat, true /* copy */);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800813 if (converter.initCheck() != OK) {
814 ALOGD("ConstGraphicBlockBuffer::canCopy: converter init failed: %d", converter.initCheck());
815 return false;
816 }
817 if (converter.backBufferSize() > capacity()) {
818 ALOGD("ConstGraphicBlockBuffer::canCopy: insufficient capacity: req %u has %zu",
819 converter.backBufferSize(), capacity());
820 return false;
821 }
822 return true;
823}
824
825bool ConstGraphicBlockBuffer::copy(const std::shared_ptr<C2Buffer> &buffer) {
826 if (!buffer || buffer->data().graphicBlocks().size() == 0) {
827 setRange(0, 0);
828 return true;
829 }
830 int32_t colorFormat = COLOR_FormatYUV420Flexible;
831 format()->findInt32("color-format", &colorFormat);
832
833 GraphicView2MediaImageConverter converter(
Wonsik Kim7d966312019-06-04 14:00:49 -0700834 buffer->data().graphicBlocks()[0].map().get(), colorFormat, true /* copy */);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800835 if (converter.initCheck() != OK) {
836 ALOGD("ConstGraphicBlockBuffer::copy: converter init failed: %d", converter.initCheck());
837 return false;
838 }
839 sp<ABuffer> aBuffer = new ABuffer(base(), capacity());
840 if (!converter.setBackBuffer(aBuffer)) {
841 ALOGD("ConstGraphicBlockBuffer::copy: set back buffer failed");
842 return false;
843 }
Pin-chih Lin1971e2c2019-04-15 19:36:26 +0800844 setRange(0, aBuffer->size()); // align size info
Pawin Vongmasa36653902018-11-15 00:10:25 -0800845 converter.copyToMediaImage();
846 setImageData(converter.imageData());
847 mBufferRef = buffer;
848 return true;
849}
850
851// EncryptedLinearBlockBuffer
852
853EncryptedLinearBlockBuffer::EncryptedLinearBlockBuffer(
854 const sp<AMessage> &format,
855 const std::shared_ptr<C2LinearBlock> &block,
856 const sp<IMemory> &memory,
857 int32_t heapSeqNum)
Ytai Ben-Tsvi7dd39722019-09-05 15:14:30 -0700858 // TODO: Using unsecurePointer() has some associated security pitfalls
859 // (see declaration for details).
860 // Either document why it is safe in this case or address the
861 // issue (e.g. by copying).
862 : Codec2Buffer(format, new ABuffer(memory->unsecurePointer(), memory->size())),
Pawin Vongmasa36653902018-11-15 00:10:25 -0800863 mBlock(block),
864 mMemory(memory),
865 mHeapSeqNum(heapSeqNum) {
866}
867
868std::shared_ptr<C2Buffer> EncryptedLinearBlockBuffer::asC2Buffer() {
869 return C2Buffer::CreateLinearBuffer(mBlock->share(offset(), size(), C2Fence()));
870}
871
872void EncryptedLinearBlockBuffer::fillSourceBuffer(
Robert Shih895fba92019-07-16 16:29:44 -0700873 hardware::drm::V1_0::SharedBuffer *source) {
874 BufferChannelBase::IMemoryToSharedBuffer(mMemory, mHeapSeqNum, source);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800875}
876
877void EncryptedLinearBlockBuffer::fillSourceBuffer(
878 hardware::cas::native::V1_0::SharedBuffer *source) {
879 ssize_t offset;
880 size_t size;
881
882 mHidlMemory = hardware::fromHeap(mMemory->getMemory(&offset, &size));
883 source->heapBase = *mHidlMemory;
884 source->offset = offset;
885 source->size = size;
886}
887
888bool EncryptedLinearBlockBuffer::copyDecryptedContent(
889 const sp<IMemory> &decrypted, size_t length) {
890 C2WriteView view = mBlock->map().get();
891 if (view.error() != C2_OK) {
892 return false;
893 }
894 if (view.size() < length) {
895 return false;
896 }
Ytai Ben-Tsvi7dd39722019-09-05 15:14:30 -0700897 memcpy(view.data(), decrypted->unsecurePointer(), length);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800898 return true;
899}
900
901bool EncryptedLinearBlockBuffer::copyDecryptedContentFromMemory(size_t length) {
902 return copyDecryptedContent(mMemory, length);
903}
904
905native_handle_t *EncryptedLinearBlockBuffer::handle() const {
906 return const_cast<native_handle_t *>(mBlock->handle());
907}
908
909} // namespace android