blob: 507232385a024b95416f5e60a188fa9d544e824c [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
356 default:
357 ALOGD("Converter: incompactible color format (%d) for YUV layout", mColorFormat);
358 mInitCheck = BAD_VALUE;
359 return;
360 }
361 break;
362 case C2PlanarLayout::TYPE_YUVA:
363 mediaImage->mType = MediaImage2::MEDIA_IMAGE_TYPE_YUVA;
364 // We don't have an SDK YUVA format
365 ALOGD("Converter: incompactible color format (%d) for YUVA layout", mColorFormat);
366 mInitCheck = BAD_VALUE;
367 return;
368 case C2PlanarLayout::TYPE_RGB:
369 mediaImage->mType = MediaImage2::MEDIA_IMAGE_TYPE_RGB;
370 switch (mColorFormat) {
371 // TODO media image
372 case COLOR_FormatRGBFlexible:
373 case COLOR_Format24bitBGR888:
374 case COLOR_Format24bitRGB888:
375 break;
376 default:
377 ALOGD("Converter: incompactible color format (%d) for RGB layout", mColorFormat);
378 mInitCheck = BAD_VALUE;
379 return;
380 }
381 if (layout.numPlanes != 3) {
382 ALOGD("Converter: %d planes for RGB layout", layout.numPlanes);
383 mInitCheck = BAD_VALUE;
384 return;
385 }
386 break;
387 case C2PlanarLayout::TYPE_RGBA:
388 mediaImage->mType = MediaImage2::MEDIA_IMAGE_TYPE_RGBA;
389 switch (mColorFormat) {
390 // TODO media image
391 case COLOR_FormatRGBAFlexible:
392 case COLOR_Format32bitABGR8888:
393 case COLOR_Format32bitARGB8888:
394 case COLOR_Format32bitBGRA8888:
395 break;
396 default:
397 ALOGD("Incompactible color format (%d) for RGBA layout", mColorFormat);
398 mInitCheck = BAD_VALUE;
399 return;
400 }
401 if (layout.numPlanes != 4) {
402 ALOGD("Converter: %d planes for RGBA layout", layout.numPlanes);
403 mInitCheck = BAD_VALUE;
404 return;
405 }
406 break;
407 default:
408 mediaImage->mType = MediaImage2::MEDIA_IMAGE_TYPE_UNKNOWN;
409 ALOGD("Unknown layout");
410 mInitCheck = BAD_VALUE;
411 return;
412 }
413 mediaImage->mNumPlanes = layout.numPlanes;
Harish Mahendrakarf7c49e22019-05-24 14:19:16 -0700414 mediaImage->mWidth = view.crop().width;
415 mediaImage->mHeight = view.crop().height;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800416 mediaImage->mBitDepth = bitDepth;
417 mediaImage->mBitDepthAllocated = mAllocatedDepth;
418
419 uint32_t bufferSize = 0;
420 for (uint32_t i = 0; i < layout.numPlanes; ++i) {
421 const C2PlaneInfo &plane = layout.planes[i];
422 if (plane.allocatedDepth < plane.bitDepth
423 || plane.rightShift != plane.allocatedDepth - plane.bitDepth) {
424 ALOGD("rightShift value of %u unsupported", plane.rightShift);
425 mInitCheck = BAD_VALUE;
426 return;
427 }
428 if (plane.allocatedDepth > 8 && plane.endianness != C2PlaneInfo::NATIVE) {
429 ALOGD("endianness value of %u unsupported", plane.endianness);
430 mInitCheck = BAD_VALUE;
431 return;
432 }
433 if (plane.allocatedDepth != mAllocatedDepth || plane.bitDepth != bitDepth) {
434 ALOGV("different allocatedDepth/bitDepth per plane unsupported");
435 mInitCheck = BAD_VALUE;
436 return;
437 }
Wonsik Kim8bfa17a2019-05-30 22:12:30 -0700438 bufferSize += stride * vStride
Pawin Vongmasa36653902018-11-15 00:10:25 -0800439 / plane.rowSampling / plane.colSampling;
440 }
441
442 mBackBufferSize = bufferSize;
443 mInitCheck = OK;
444 }
445
446 status_t initCheck() const { return mInitCheck; }
447
448 uint32_t backBufferSize() const { return mBackBufferSize; }
449
450 /**
451 * Wrap C2GraphicView using a MediaImage2. Note that if not wrapped, the content is not mapped
452 * in this function --- the caller should use CopyGraphicView2MediaImage() function to copy the
453 * data into a backing buffer explicitly.
454 *
455 * \return media buffer. This is null if wrapping failed.
456 */
457 sp<ABuffer> wrap() const {
458 if (mBackBuffer == nullptr) {
459 return mWrapped;
460 }
461 return nullptr;
462 }
463
464 bool setBackBuffer(const sp<ABuffer> &backBuffer) {
Wonsik Kim186fdbf2019-01-29 13:30:01 -0800465 if (backBuffer == nullptr) {
466 return false;
467 }
Pawin Vongmasa36653902018-11-15 00:10:25 -0800468 if (backBuffer->capacity() < mBackBufferSize) {
469 return false;
470 }
471 backBuffer->setRange(0, mBackBufferSize);
472 mBackBuffer = backBuffer;
473 return true;
474 }
475
476 /**
477 * Copy C2GraphicView to MediaImage2.
478 */
479 status_t copyToMediaImage() {
480 if (mInitCheck != OK) {
481 return mInitCheck;
482 }
483 return ImageCopy(mBackBuffer->base(), getMediaImage(), mView);
484 }
485
486 const sp<ABuffer> &imageData() const { return mMediaImage; }
487
488private:
489 status_t mInitCheck;
490
491 const C2GraphicView mView;
492 uint32_t mWidth;
493 uint32_t mHeight;
494 int32_t mColorFormat; ///< SDK color format for MediaImage
495 sp<ABuffer> mWrapped; ///< wrapped buffer (if we can map C2Buffer to an ABuffer)
496 uint32_t mAllocatedDepth;
497 uint32_t mBackBufferSize;
498 sp<ABuffer> mMediaImage;
499 std::function<sp<ABuffer>(size_t)> mAlloc;
500
501 sp<ABuffer> mBackBuffer; ///< backing buffer if we have to copy C2Buffer <=> ABuffer
502
503 MediaImage2 *getMediaImage() {
504 return (MediaImage2 *)mMediaImage->base();
505 }
506};
507
508} // namespace
509
510// GraphicBlockBuffer
511
512// static
513sp<GraphicBlockBuffer> GraphicBlockBuffer::Allocate(
514 const sp<AMessage> &format,
515 const std::shared_ptr<C2GraphicBlock> &block,
516 std::function<sp<ABuffer>(size_t)> alloc) {
517 C2GraphicView view(block->map().get());
518 if (view.error() != C2_OK) {
519 ALOGD("C2GraphicBlock::map failed: %d", view.error());
520 return nullptr;
521 }
522
523 int32_t colorFormat = COLOR_FormatYUV420Flexible;
524 (void)format->findInt32("color-format", &colorFormat);
525
Wonsik Kim7d966312019-06-04 14:00:49 -0700526 GraphicView2MediaImageConverter converter(view, colorFormat, false /* copy */);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800527 if (converter.initCheck() != OK) {
528 ALOGD("Converter init failed: %d", converter.initCheck());
529 return nullptr;
530 }
531 bool wrapped = true;
532 sp<ABuffer> buffer = converter.wrap();
533 if (buffer == nullptr) {
534 buffer = alloc(converter.backBufferSize());
535 if (!converter.setBackBuffer(buffer)) {
536 ALOGD("Converter failed to set back buffer");
537 return nullptr;
538 }
539 wrapped = false;
540 }
541 return new GraphicBlockBuffer(
542 format,
543 buffer,
544 std::move(view),
545 block,
546 converter.imageData(),
547 wrapped);
548}
549
550GraphicBlockBuffer::GraphicBlockBuffer(
551 const sp<AMessage> &format,
552 const sp<ABuffer> &buffer,
553 C2GraphicView &&view,
554 const std::shared_ptr<C2GraphicBlock> &block,
555 const sp<ABuffer> &imageData,
556 bool wrapped)
557 : Codec2Buffer(format, buffer),
558 mView(view),
559 mBlock(block),
Pawin Vongmasa36653902018-11-15 00:10:25 -0800560 mWrapped(wrapped) {
561 setImageData(imageData);
562}
563
564std::shared_ptr<C2Buffer> GraphicBlockBuffer::asC2Buffer() {
565 uint32_t width = mView.width();
566 uint32_t height = mView.height();
567 if (!mWrapped) {
568 (void)ImageCopy(mView, base(), imageData());
569 }
570 return C2Buffer::CreateGraphicBuffer(
571 mBlock->share(C2Rect(width, height), C2Fence()));
572}
573
574// GraphicMetadataBuffer
575GraphicMetadataBuffer::GraphicMetadataBuffer(
576 const sp<AMessage> &format,
577 const std::shared_ptr<C2Allocator> &alloc)
578 : Codec2Buffer(format, new ABuffer(sizeof(VideoNativeMetadata))),
579 mAlloc(alloc) {
580 ((VideoNativeMetadata *)base())->pBuffer = nullptr;
581}
582
583std::shared_ptr<C2Buffer> GraphicMetadataBuffer::asC2Buffer() {
bohua222c0b2021-01-12 18:54:53 -0800584#ifdef __LP64__
585 static std::once_flag s_checkOnce;
586 static bool s_64bitonly {false};
587 std::call_once(s_checkOnce, [&](){
588 const std::string abi32list =
589 ::android::base::GetProperty("ro.product.cpu.abilist32", "");
590 if (abi32list.empty()) {
591 s_64bitonly = true;
592 }
593 });
594
595 if (!s_64bitonly) {
596 ALOGE("GraphicMetadataBuffer does not work in 32+64 system if compiled as 64-bit object");
597 return nullptr;
598 }
599#endif
600
Pawin Vongmasa36653902018-11-15 00:10:25 -0800601 VideoNativeMetadata *meta = (VideoNativeMetadata *)base();
602 ANativeWindowBuffer *buffer = (ANativeWindowBuffer *)meta->pBuffer;
603 if (buffer == nullptr) {
604 ALOGD("VideoNativeMetadata contains null buffer");
605 return nullptr;
606 }
607
608 ALOGV("VideoNativeMetadata: %dx%d", buffer->width, buffer->height);
609 C2Handle *handle = WrapNativeCodec2GrallocHandle(
Sungtak Leea4d13be2019-01-23 15:24:46 -0800610 buffer->handle,
Pawin Vongmasa36653902018-11-15 00:10:25 -0800611 buffer->width,
612 buffer->height,
613 buffer->format,
614 buffer->usage,
615 buffer->stride);
616 std::shared_ptr<C2GraphicAllocation> alloc;
617 c2_status_t err = mAlloc->priorGraphicAllocation(handle, &alloc);
618 if (err != C2_OK) {
619 ALOGD("Failed to wrap VideoNativeMetadata into C2GraphicAllocation");
620 return nullptr;
621 }
622 std::shared_ptr<C2GraphicBlock> block = _C2BlockFactory::CreateGraphicBlock(alloc);
623
624 meta->pBuffer = 0;
Wonsik Kimebe0f9e2019-07-03 11:06:51 -0700625 // TODO: wrap this in C2Fence so that the component can wait when it
626 // actually starts processing.
627 if (meta->nFenceFd >= 0) {
628 sp<Fence> fence(new Fence(meta->nFenceFd));
629 fence->waitForever(LOG_TAG);
630 }
Pawin Vongmasa36653902018-11-15 00:10:25 -0800631 return C2Buffer::CreateGraphicBuffer(
632 block->share(C2Rect(buffer->width, buffer->height), C2Fence()));
Pawin Vongmasa36653902018-11-15 00:10:25 -0800633}
634
635// ConstGraphicBlockBuffer
636
637// static
638sp<ConstGraphicBlockBuffer> ConstGraphicBlockBuffer::Allocate(
639 const sp<AMessage> &format,
640 const std::shared_ptr<C2Buffer> &buffer,
641 std::function<sp<ABuffer>(size_t)> alloc) {
642 if (!buffer
643 || buffer->data().type() != C2BufferData::GRAPHIC
644 || buffer->data().graphicBlocks().size() != 1u) {
645 ALOGD("C2Buffer precond fail");
646 return nullptr;
647 }
648 std::unique_ptr<const C2GraphicView> view(std::make_unique<const C2GraphicView>(
649 buffer->data().graphicBlocks()[0].map().get()));
650 std::unique_ptr<const C2GraphicView> holder;
651
652 int32_t colorFormat = COLOR_FormatYUV420Flexible;
653 (void)format->findInt32("color-format", &colorFormat);
654
Wonsik Kim7d966312019-06-04 14:00:49 -0700655 GraphicView2MediaImageConverter converter(*view, colorFormat, false /* copy */);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800656 if (converter.initCheck() != OK) {
657 ALOGD("Converter init failed: %d", converter.initCheck());
658 return nullptr;
659 }
660 bool wrapped = true;
661 sp<ABuffer> aBuffer = converter.wrap();
662 if (aBuffer == nullptr) {
663 aBuffer = alloc(converter.backBufferSize());
664 if (!converter.setBackBuffer(aBuffer)) {
665 ALOGD("Converter failed to set back buffer");
666 return nullptr;
667 }
668 wrapped = false;
669 converter.copyToMediaImage();
670 // We don't need the view.
671 holder = std::move(view);
672 }
673 return new ConstGraphicBlockBuffer(
674 format,
675 aBuffer,
676 std::move(view),
677 buffer,
678 converter.imageData(),
679 wrapped);
680}
681
682// static
683sp<ConstGraphicBlockBuffer> ConstGraphicBlockBuffer::AllocateEmpty(
684 const sp<AMessage> &format,
685 std::function<sp<ABuffer>(size_t)> alloc) {
686 int32_t width, height;
687 if (!format->findInt32("width", &width)
688 || !format->findInt32("height", &height)) {
689 ALOGD("format had no width / height");
690 return nullptr;
691 }
Wonsik Kim8bfa17a2019-05-30 22:12:30 -0700692 // NOTE: we currently only support YUV420 formats for byte-buffer mode.
693 sp<ABuffer> aBuffer(alloc(align(width, 16) * align(height, 16) * 3 / 2));
Pawin Vongmasa36653902018-11-15 00:10:25 -0800694 return new ConstGraphicBlockBuffer(
695 format,
696 aBuffer,
697 nullptr,
698 nullptr,
699 nullptr,
700 false);
701}
702
703ConstGraphicBlockBuffer::ConstGraphicBlockBuffer(
704 const sp<AMessage> &format,
705 const sp<ABuffer> &aBuffer,
706 std::unique_ptr<const C2GraphicView> &&view,
707 const std::shared_ptr<C2Buffer> &buffer,
708 const sp<ABuffer> &imageData,
709 bool wrapped)
710 : Codec2Buffer(format, aBuffer),
711 mView(std::move(view)),
712 mBufferRef(buffer),
713 mWrapped(wrapped) {
Wonsik Kimc48ddcf2019-02-11 16:16:57 -0800714 setImageData(imageData);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800715}
716
717std::shared_ptr<C2Buffer> ConstGraphicBlockBuffer::asC2Buffer() {
Wonsik Kimf9b32122020-04-02 11:30:17 -0700718 return mBufferRef;
719}
720
721void ConstGraphicBlockBuffer::clearC2BufferRefs() {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800722 mView.reset();
Wonsik Kimf9b32122020-04-02 11:30:17 -0700723 mBufferRef.reset();
Pawin Vongmasa36653902018-11-15 00:10:25 -0800724}
725
726bool ConstGraphicBlockBuffer::canCopy(const std::shared_ptr<C2Buffer> &buffer) const {
727 if (mWrapped || mBufferRef) {
728 ALOGD("ConstGraphicBlockBuffer::canCopy: %swrapped ; buffer ref %s",
729 mWrapped ? "" : "not ", mBufferRef ? "exists" : "doesn't exist");
730 return false;
731 }
732 if (!buffer) {
733 // Nothing to copy, so we can copy by doing nothing.
734 return true;
735 }
736 if (buffer->data().type() != C2BufferData::GRAPHIC) {
737 ALOGD("ConstGraphicBlockBuffer::canCopy: buffer precondition unsatisfied");
738 return false;
739 }
740 if (buffer->data().graphicBlocks().size() == 0) {
741 return true;
742 } else if (buffer->data().graphicBlocks().size() != 1u) {
743 ALOGD("ConstGraphicBlockBuffer::canCopy: too many blocks");
744 return false;
745 }
746
747 int32_t colorFormat = COLOR_FormatYUV420Flexible;
748 // FIXME: format() is not const, but we cannot change it, so do a const cast here
749 const_cast<ConstGraphicBlockBuffer *>(this)->format()->findInt32("color-format", &colorFormat);
750
751 GraphicView2MediaImageConverter converter(
Wonsik Kim7d966312019-06-04 14:00:49 -0700752 buffer->data().graphicBlocks()[0].map().get(), colorFormat, true /* copy */);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800753 if (converter.initCheck() != OK) {
754 ALOGD("ConstGraphicBlockBuffer::canCopy: converter init failed: %d", converter.initCheck());
755 return false;
756 }
757 if (converter.backBufferSize() > capacity()) {
758 ALOGD("ConstGraphicBlockBuffer::canCopy: insufficient capacity: req %u has %zu",
759 converter.backBufferSize(), capacity());
760 return false;
761 }
762 return true;
763}
764
765bool ConstGraphicBlockBuffer::copy(const std::shared_ptr<C2Buffer> &buffer) {
766 if (!buffer || buffer->data().graphicBlocks().size() == 0) {
767 setRange(0, 0);
768 return true;
769 }
770 int32_t colorFormat = COLOR_FormatYUV420Flexible;
771 format()->findInt32("color-format", &colorFormat);
772
773 GraphicView2MediaImageConverter converter(
Wonsik Kim7d966312019-06-04 14:00:49 -0700774 buffer->data().graphicBlocks()[0].map().get(), colorFormat, true /* copy */);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800775 if (converter.initCheck() != OK) {
776 ALOGD("ConstGraphicBlockBuffer::copy: converter init failed: %d", converter.initCheck());
777 return false;
778 }
779 sp<ABuffer> aBuffer = new ABuffer(base(), capacity());
780 if (!converter.setBackBuffer(aBuffer)) {
781 ALOGD("ConstGraphicBlockBuffer::copy: set back buffer failed");
782 return false;
783 }
Pin-chih Lin1971e2c2019-04-15 19:36:26 +0800784 setRange(0, aBuffer->size()); // align size info
Pawin Vongmasa36653902018-11-15 00:10:25 -0800785 converter.copyToMediaImage();
786 setImageData(converter.imageData());
787 mBufferRef = buffer;
788 return true;
789}
790
791// EncryptedLinearBlockBuffer
792
793EncryptedLinearBlockBuffer::EncryptedLinearBlockBuffer(
794 const sp<AMessage> &format,
795 const std::shared_ptr<C2LinearBlock> &block,
796 const sp<IMemory> &memory,
797 int32_t heapSeqNum)
Ytai Ben-Tsvi7dd39722019-09-05 15:14:30 -0700798 // TODO: Using unsecurePointer() has some associated security pitfalls
799 // (see declaration for details).
800 // Either document why it is safe in this case or address the
801 // issue (e.g. by copying).
802 : Codec2Buffer(format, new ABuffer(memory->unsecurePointer(), memory->size())),
Pawin Vongmasa36653902018-11-15 00:10:25 -0800803 mBlock(block),
804 mMemory(memory),
805 mHeapSeqNum(heapSeqNum) {
806}
807
808std::shared_ptr<C2Buffer> EncryptedLinearBlockBuffer::asC2Buffer() {
809 return C2Buffer::CreateLinearBuffer(mBlock->share(offset(), size(), C2Fence()));
810}
811
812void EncryptedLinearBlockBuffer::fillSourceBuffer(
Robert Shih895fba92019-07-16 16:29:44 -0700813 hardware::drm::V1_0::SharedBuffer *source) {
814 BufferChannelBase::IMemoryToSharedBuffer(mMemory, mHeapSeqNum, source);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800815}
816
817void EncryptedLinearBlockBuffer::fillSourceBuffer(
818 hardware::cas::native::V1_0::SharedBuffer *source) {
819 ssize_t offset;
820 size_t size;
821
822 mHidlMemory = hardware::fromHeap(mMemory->getMemory(&offset, &size));
823 source->heapBase = *mHidlMemory;
824 source->offset = offset;
825 source->size = size;
826}
827
828bool EncryptedLinearBlockBuffer::copyDecryptedContent(
829 const sp<IMemory> &decrypted, size_t length) {
830 C2WriteView view = mBlock->map().get();
831 if (view.error() != C2_OK) {
832 return false;
833 }
834 if (view.size() < length) {
835 return false;
836 }
Ytai Ben-Tsvi7dd39722019-09-05 15:14:30 -0700837 memcpy(view.data(), decrypted->unsecurePointer(), length);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800838 return true;
839}
840
841bool EncryptedLinearBlockBuffer::copyDecryptedContentFromMemory(size_t length) {
842 return copyDecryptedContent(mMemory, length);
843}
844
845native_handle_t *EncryptedLinearBlockBuffer::handle() const {
846 return const_cast<native_handle_t *>(mBlock->handle());
847}
848
849} // namespace android