blob: 5b3a62f37a1c6da1439c709c69b063a987759a80 [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
21#include <hidlmemory/FrameworkUtils.h>
22#include <media/hardware/HardwareAPI.h>
Robert Shih895fba92019-07-16 16:29:44 -070023#include <media/stagefright/CodecBase.h>
Pawin Vongmasa36653902018-11-15 00:10:25 -080024#include <media/stagefright/MediaCodecConstants.h>
25#include <media/stagefright/foundation/ABuffer.h>
26#include <media/stagefright/foundation/AMessage.h>
27#include <media/stagefright/foundation/AUtils.h>
28#include <nativebase/nativebase.h>
Wonsik Kimebe0f9e2019-07-03 11:06:51 -070029#include <ui/Fence.h>
Pawin Vongmasa36653902018-11-15 00:10:25 -080030
31#include <C2AllocatorGralloc.h>
32#include <C2BlockInternal.h>
33#include <C2Debug.h>
34
35#include "Codec2Buffer.h"
36
37namespace android {
38
39// Codec2Buffer
40
41bool Codec2Buffer::canCopyLinear(const std::shared_ptr<C2Buffer> &buffer) const {
42 if (const_cast<Codec2Buffer *>(this)->base() == nullptr) {
43 return false;
44 }
45 if (!buffer) {
46 // Nothing to copy, so we can copy by doing nothing.
47 return true;
48 }
49 if (buffer->data().type() != C2BufferData::LINEAR) {
50 return false;
51 }
52 if (buffer->data().linearBlocks().size() == 0u) {
53 // Nothing to copy, so we can copy by doing nothing.
54 return true;
55 } else if (buffer->data().linearBlocks().size() > 1u) {
56 // We don't know how to copy more than one blocks.
57 return false;
58 }
59 if (buffer->data().linearBlocks()[0].size() > capacity()) {
60 // It won't fit.
61 return false;
62 }
63 return true;
64}
65
66bool Codec2Buffer::copyLinear(const std::shared_ptr<C2Buffer> &buffer) {
67 // We assume that all canCopyLinear() checks passed.
68 if (!buffer || buffer->data().linearBlocks().size() == 0u
69 || buffer->data().linearBlocks()[0].size() == 0u) {
70 setRange(0, 0);
71 return true;
72 }
73 C2ReadView view = buffer->data().linearBlocks()[0].map().get();
74 if (view.error() != C2_OK) {
75 ALOGD("Error while mapping: %d", view.error());
76 return false;
77 }
78 if (view.capacity() > capacity()) {
79 ALOGD("C2ConstLinearBlock lied --- it actually doesn't fit: view(%u) > this(%zu)",
80 view.capacity(), capacity());
81 return false;
82 }
83 memcpy(base(), view.data(), view.capacity());
84 setRange(0, view.capacity());
85 return true;
86}
87
88void Codec2Buffer::setImageData(const sp<ABuffer> &imageData) {
Wonsik Kimc48ddcf2019-02-11 16:16:57 -080089 mImageData = imageData;
Pawin Vongmasa36653902018-11-15 00:10:25 -080090}
91
92// LocalLinearBuffer
93
94bool LocalLinearBuffer::canCopy(const std::shared_ptr<C2Buffer> &buffer) const {
95 return canCopyLinear(buffer);
96}
97
98bool LocalLinearBuffer::copy(const std::shared_ptr<C2Buffer> &buffer) {
99 return copyLinear(buffer);
100}
101
102// DummyContainerBuffer
103
Pawin Vongmasa8be93112018-12-11 14:01:42 -0800104static uint8_t sDummyByte[1] = { 0 };
105
Pawin Vongmasa36653902018-11-15 00:10:25 -0800106DummyContainerBuffer::DummyContainerBuffer(
107 const sp<AMessage> &format, const std::shared_ptr<C2Buffer> &buffer)
Pawin Vongmasa8be93112018-12-11 14:01:42 -0800108 : Codec2Buffer(format, new ABuffer(sDummyByte, 1)),
Pawin Vongmasa36653902018-11-15 00:10:25 -0800109 mBufferRef(buffer) {
110 setRange(0, buffer ? 1 : 0);
111}
112
113std::shared_ptr<C2Buffer> DummyContainerBuffer::asC2Buffer() {
Wonsik Kimf9b32122020-04-02 11:30:17 -0700114 return mBufferRef;
115}
116
117void DummyContainerBuffer::clearC2BufferRefs() {
118 mBufferRef.reset();
Pawin Vongmasa36653902018-11-15 00:10:25 -0800119}
120
121bool DummyContainerBuffer::canCopy(const std::shared_ptr<C2Buffer> &) const {
122 return !mBufferRef;
123}
124
125bool DummyContainerBuffer::copy(const std::shared_ptr<C2Buffer> &buffer) {
126 mBufferRef = buffer;
127 setRange(0, mBufferRef ? 1 : 0);
128 return true;
129}
130
131// LinearBlockBuffer
132
133// static
134sp<LinearBlockBuffer> LinearBlockBuffer::Allocate(
135 const sp<AMessage> &format, const std::shared_ptr<C2LinearBlock> &block) {
136 C2WriteView writeView(block->map().get());
137 if (writeView.error() != C2_OK) {
138 return nullptr;
139 }
140 return new LinearBlockBuffer(format, std::move(writeView), block);
141}
142
143std::shared_ptr<C2Buffer> LinearBlockBuffer::asC2Buffer() {
144 return C2Buffer::CreateLinearBuffer(mBlock->share(offset(), size(), C2Fence()));
145}
146
147bool LinearBlockBuffer::canCopy(const std::shared_ptr<C2Buffer> &buffer) const {
148 return canCopyLinear(buffer);
149}
150
151bool LinearBlockBuffer::copy(const std::shared_ptr<C2Buffer> &buffer) {
152 return copyLinear(buffer);
153}
154
155LinearBlockBuffer::LinearBlockBuffer(
156 const sp<AMessage> &format,
157 C2WriteView&& writeView,
158 const std::shared_ptr<C2LinearBlock> &block)
159 : Codec2Buffer(format, new ABuffer(writeView.data(), writeView.size())),
160 mWriteView(writeView),
161 mBlock(block) {
162}
163
164// ConstLinearBlockBuffer
165
166// static
167sp<ConstLinearBlockBuffer> ConstLinearBlockBuffer::Allocate(
168 const sp<AMessage> &format, const std::shared_ptr<C2Buffer> &buffer) {
169 if (!buffer
170 || buffer->data().type() != C2BufferData::LINEAR
171 || buffer->data().linearBlocks().size() != 1u) {
172 return nullptr;
173 }
174 C2ReadView readView(buffer->data().linearBlocks()[0].map().get());
175 if (readView.error() != C2_OK) {
176 return nullptr;
177 }
178 return new ConstLinearBlockBuffer(format, std::move(readView), buffer);
179}
180
181ConstLinearBlockBuffer::ConstLinearBlockBuffer(
182 const sp<AMessage> &format,
183 C2ReadView&& readView,
184 const std::shared_ptr<C2Buffer> &buffer)
185 : Codec2Buffer(format, new ABuffer(
186 // NOTE: ABuffer only takes non-const pointer but this data is
187 // supposed to be read-only.
188 const_cast<uint8_t *>(readView.data()), readView.capacity())),
189 mReadView(readView),
190 mBufferRef(buffer) {
191}
192
193std::shared_ptr<C2Buffer> ConstLinearBlockBuffer::asC2Buffer() {
Wonsik Kimf9b32122020-04-02 11:30:17 -0700194 return mBufferRef;
195}
196
197void ConstLinearBlockBuffer::clearC2BufferRefs() {
198 mBufferRef.reset();
Pawin Vongmasa36653902018-11-15 00:10:25 -0800199}
200
201// GraphicView2MediaImageConverter
202
203namespace {
204
205class GraphicView2MediaImageConverter {
206public:
207 /**
208 * Creates a C2GraphicView <=> MediaImage converter
209 *
210 * \param view C2GraphicView object
211 * \param colorFormat desired SDK color format for the MediaImage (if this is a flexible format,
212 * an attempt is made to simply represent the graphic view as a flexible SDK format
213 * without a memcpy)
Wonsik Kim7d966312019-06-04 14:00:49 -0700214 * \param copy whether the converter is used for copy or not
Pawin Vongmasa36653902018-11-15 00:10:25 -0800215 */
216 GraphicView2MediaImageConverter(
Wonsik Kim7d966312019-06-04 14:00:49 -0700217 const C2GraphicView &view, int32_t colorFormat, bool copy)
Pawin Vongmasa36653902018-11-15 00:10:25 -0800218 : mInitCheck(NO_INIT),
219 mView(view),
220 mWidth(view.width()),
221 mHeight(view.height()),
222 mColorFormat(colorFormat),
223 mAllocatedDepth(0),
224 mBackBufferSize(0),
225 mMediaImage(new ABuffer(sizeof(MediaImage2))) {
226 if (view.error() != C2_OK) {
227 ALOGD("Converter: view.error() = %d", view.error());
228 mInitCheck = BAD_VALUE;
229 return;
230 }
231 MediaImage2 *mediaImage = (MediaImage2 *)mMediaImage->base();
232 const C2PlanarLayout &layout = view.layout();
233 if (layout.numPlanes == 0) {
234 ALOGD("Converter: 0 planes");
235 mInitCheck = BAD_VALUE;
236 return;
237 }
Harish Mahendrakarcac53852019-02-20 10:59:10 -0800238 memset(mediaImage, 0, sizeof(*mediaImage));
Pawin Vongmasa36653902018-11-15 00:10:25 -0800239 mAllocatedDepth = layout.planes[0].allocatedDepth;
240 uint32_t bitDepth = layout.planes[0].bitDepth;
241
242 // align width and height to support subsampling cleanly
Wonsik Kim8bfa17a2019-05-30 22:12:30 -0700243 uint32_t stride = align(view.crop().width, 2) * divUp(layout.planes[0].allocatedDepth, 8u);
244 uint32_t vStride = align(view.crop().height, 2);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800245
246 switch (layout.type) {
247 case C2PlanarLayout::TYPE_YUV:
248 mediaImage->mType = MediaImage2::MEDIA_IMAGE_TYPE_YUV;
249 if (layout.numPlanes != 3) {
250 ALOGD("Converter: %d planes for YUV layout", layout.numPlanes);
251 mInitCheck = BAD_VALUE;
252 return;
253 }
254 if (layout.planes[0].channel != C2PlaneInfo::CHANNEL_Y
255 || layout.planes[1].channel != C2PlaneInfo::CHANNEL_CB
256 || layout.planes[2].channel != C2PlaneInfo::CHANNEL_CR
257 || layout.planes[0].colSampling != 1
258 || layout.planes[0].rowSampling != 1
259 || layout.planes[1].colSampling != 2
260 || layout.planes[1].rowSampling != 2
261 || layout.planes[2].colSampling != 2
262 || layout.planes[2].rowSampling != 2) {
263 ALOGD("Converter: not YUV420 for YUV layout");
264 mInitCheck = BAD_VALUE;
265 return;
266 }
267 switch (mColorFormat) {
268 case COLOR_FormatYUV420Flexible:
Wonsik Kim7d966312019-06-04 14:00:49 -0700269 if (!copy) {
270 // try to map directly. check if the planes are near one another
271 const uint8_t *minPtr = mView.data()[0];
272 const uint8_t *maxPtr = mView.data()[0];
273 int32_t planeSize = 0;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800274 for (uint32_t i = 0; i < layout.numPlanes; ++i) {
275 const C2PlaneInfo &plane = layout.planes[i];
Wonsik Kim7d966312019-06-04 14:00:49 -0700276 ssize_t minOffset = plane.minOffset(mWidth, mHeight);
277 ssize_t maxOffset = plane.maxOffset(mWidth, mHeight);
278 if (minPtr > mView.data()[i] + minOffset) {
279 minPtr = mView.data()[i] + minOffset;
280 }
281 if (maxPtr < mView.data()[i] + maxOffset) {
282 maxPtr = mView.data()[i] + maxOffset;
283 }
284 planeSize += std::abs(plane.rowInc) * align(mHeight, 64)
285 / plane.rowSampling / plane.colSampling
286 * divUp(mAllocatedDepth, 8u);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800287 }
Wonsik Kim7d966312019-06-04 14:00:49 -0700288
289 if ((maxPtr - minPtr + 1) <= planeSize) {
290 // FIXME: this is risky as reading/writing data out of bound results
291 // in an undefined behavior, but gralloc does assume a
292 // contiguous mapping
293 for (uint32_t i = 0; i < layout.numPlanes; ++i) {
294 const C2PlaneInfo &plane = layout.planes[i];
295 mediaImage->mPlane[i].mOffset = mView.data()[i] - minPtr;
296 mediaImage->mPlane[i].mColInc = plane.colInc;
297 mediaImage->mPlane[i].mRowInc = plane.rowInc;
298 mediaImage->mPlane[i].mHorizSubsampling = plane.colSampling;
299 mediaImage->mPlane[i].mVertSubsampling = plane.rowSampling;
300 }
301 mWrapped = new ABuffer(const_cast<uint8_t *>(minPtr),
302 maxPtr - minPtr + 1);
303 break;
304 }
Pawin Vongmasa36653902018-11-15 00:10:25 -0800305 }
Wonsik Kim7d966312019-06-04 14:00:49 -0700306 [[fallthrough]];
Pawin Vongmasa36653902018-11-15 00:10:25 -0800307
308 case COLOR_FormatYUV420Planar:
309 case COLOR_FormatYUV420PackedPlanar:
310 mediaImage->mPlane[mediaImage->Y].mOffset = 0;
311 mediaImage->mPlane[mediaImage->Y].mColInc = 1;
Wonsik Kim8bfa17a2019-05-30 22:12:30 -0700312 mediaImage->mPlane[mediaImage->Y].mRowInc = stride;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800313 mediaImage->mPlane[mediaImage->Y].mHorizSubsampling = 1;
314 mediaImage->mPlane[mediaImage->Y].mVertSubsampling = 1;
315
Wonsik Kim8bfa17a2019-05-30 22:12:30 -0700316 mediaImage->mPlane[mediaImage->U].mOffset = stride * vStride;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800317 mediaImage->mPlane[mediaImage->U].mColInc = 1;
Wonsik Kim8bfa17a2019-05-30 22:12:30 -0700318 mediaImage->mPlane[mediaImage->U].mRowInc = stride / 2;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800319 mediaImage->mPlane[mediaImage->U].mHorizSubsampling = 2;
320 mediaImage->mPlane[mediaImage->U].mVertSubsampling = 2;
321
Wonsik Kim8bfa17a2019-05-30 22:12:30 -0700322 mediaImage->mPlane[mediaImage->V].mOffset = stride * vStride * 5 / 4;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800323 mediaImage->mPlane[mediaImage->V].mColInc = 1;
Wonsik Kim8bfa17a2019-05-30 22:12:30 -0700324 mediaImage->mPlane[mediaImage->V].mRowInc = stride / 2;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800325 mediaImage->mPlane[mediaImage->V].mHorizSubsampling = 2;
326 mediaImage->mPlane[mediaImage->V].mVertSubsampling = 2;
327 break;
328
329 case COLOR_FormatYUV420SemiPlanar:
330 case COLOR_FormatYUV420PackedSemiPlanar:
331 mediaImage->mPlane[mediaImage->Y].mOffset = 0;
332 mediaImage->mPlane[mediaImage->Y].mColInc = 1;
Wonsik Kim8bfa17a2019-05-30 22:12:30 -0700333 mediaImage->mPlane[mediaImage->Y].mRowInc = stride;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800334 mediaImage->mPlane[mediaImage->Y].mHorizSubsampling = 1;
335 mediaImage->mPlane[mediaImage->Y].mVertSubsampling = 1;
336
Wonsik Kim8bfa17a2019-05-30 22:12:30 -0700337 mediaImage->mPlane[mediaImage->U].mOffset = stride * vStride;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800338 mediaImage->mPlane[mediaImage->U].mColInc = 2;
Wonsik Kim8bfa17a2019-05-30 22:12:30 -0700339 mediaImage->mPlane[mediaImage->U].mRowInc = stride;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800340 mediaImage->mPlane[mediaImage->U].mHorizSubsampling = 2;
341 mediaImage->mPlane[mediaImage->U].mVertSubsampling = 2;
342
Wonsik Kim8bfa17a2019-05-30 22:12:30 -0700343 mediaImage->mPlane[mediaImage->V].mOffset = stride * vStride + 1;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800344 mediaImage->mPlane[mediaImage->V].mColInc = 2;
Wonsik Kim8bfa17a2019-05-30 22:12:30 -0700345 mediaImage->mPlane[mediaImage->V].mRowInc = stride;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800346 mediaImage->mPlane[mediaImage->V].mHorizSubsampling = 2;
347 mediaImage->mPlane[mediaImage->V].mVertSubsampling = 2;
348 break;
349
350 default:
351 ALOGD("Converter: incompactible color format (%d) for YUV layout", mColorFormat);
352 mInitCheck = BAD_VALUE;
353 return;
354 }
355 break;
356 case C2PlanarLayout::TYPE_YUVA:
357 mediaImage->mType = MediaImage2::MEDIA_IMAGE_TYPE_YUVA;
358 // We don't have an SDK YUVA format
359 ALOGD("Converter: incompactible color format (%d) for YUVA layout", mColorFormat);
360 mInitCheck = BAD_VALUE;
361 return;
362 case C2PlanarLayout::TYPE_RGB:
363 mediaImage->mType = MediaImage2::MEDIA_IMAGE_TYPE_RGB;
364 switch (mColorFormat) {
365 // TODO media image
366 case COLOR_FormatRGBFlexible:
367 case COLOR_Format24bitBGR888:
368 case COLOR_Format24bitRGB888:
369 break;
370 default:
371 ALOGD("Converter: incompactible color format (%d) for RGB layout", mColorFormat);
372 mInitCheck = BAD_VALUE;
373 return;
374 }
375 if (layout.numPlanes != 3) {
376 ALOGD("Converter: %d planes for RGB layout", layout.numPlanes);
377 mInitCheck = BAD_VALUE;
378 return;
379 }
380 break;
381 case C2PlanarLayout::TYPE_RGBA:
382 mediaImage->mType = MediaImage2::MEDIA_IMAGE_TYPE_RGBA;
383 switch (mColorFormat) {
384 // TODO media image
385 case COLOR_FormatRGBAFlexible:
386 case COLOR_Format32bitABGR8888:
387 case COLOR_Format32bitARGB8888:
388 case COLOR_Format32bitBGRA8888:
389 break;
390 default:
391 ALOGD("Incompactible color format (%d) for RGBA layout", mColorFormat);
392 mInitCheck = BAD_VALUE;
393 return;
394 }
395 if (layout.numPlanes != 4) {
396 ALOGD("Converter: %d planes for RGBA layout", layout.numPlanes);
397 mInitCheck = BAD_VALUE;
398 return;
399 }
400 break;
401 default:
402 mediaImage->mType = MediaImage2::MEDIA_IMAGE_TYPE_UNKNOWN;
403 ALOGD("Unknown layout");
404 mInitCheck = BAD_VALUE;
405 return;
406 }
407 mediaImage->mNumPlanes = layout.numPlanes;
Harish Mahendrakarf7c49e22019-05-24 14:19:16 -0700408 mediaImage->mWidth = view.crop().width;
409 mediaImage->mHeight = view.crop().height;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800410 mediaImage->mBitDepth = bitDepth;
411 mediaImage->mBitDepthAllocated = mAllocatedDepth;
412
413 uint32_t bufferSize = 0;
414 for (uint32_t i = 0; i < layout.numPlanes; ++i) {
415 const C2PlaneInfo &plane = layout.planes[i];
416 if (plane.allocatedDepth < plane.bitDepth
417 || plane.rightShift != plane.allocatedDepth - plane.bitDepth) {
418 ALOGD("rightShift value of %u unsupported", plane.rightShift);
419 mInitCheck = BAD_VALUE;
420 return;
421 }
422 if (plane.allocatedDepth > 8 && plane.endianness != C2PlaneInfo::NATIVE) {
423 ALOGD("endianness value of %u unsupported", plane.endianness);
424 mInitCheck = BAD_VALUE;
425 return;
426 }
427 if (plane.allocatedDepth != mAllocatedDepth || plane.bitDepth != bitDepth) {
428 ALOGV("different allocatedDepth/bitDepth per plane unsupported");
429 mInitCheck = BAD_VALUE;
430 return;
431 }
Wonsik Kim8bfa17a2019-05-30 22:12:30 -0700432 bufferSize += stride * vStride
Pawin Vongmasa36653902018-11-15 00:10:25 -0800433 / plane.rowSampling / plane.colSampling;
434 }
435
436 mBackBufferSize = bufferSize;
437 mInitCheck = OK;
438 }
439
440 status_t initCheck() const { return mInitCheck; }
441
442 uint32_t backBufferSize() const { return mBackBufferSize; }
443
444 /**
445 * Wrap C2GraphicView using a MediaImage2. Note that if not wrapped, the content is not mapped
446 * in this function --- the caller should use CopyGraphicView2MediaImage() function to copy the
447 * data into a backing buffer explicitly.
448 *
449 * \return media buffer. This is null if wrapping failed.
450 */
451 sp<ABuffer> wrap() const {
452 if (mBackBuffer == nullptr) {
453 return mWrapped;
454 }
455 return nullptr;
456 }
457
458 bool setBackBuffer(const sp<ABuffer> &backBuffer) {
Wonsik Kim186fdbf2019-01-29 13:30:01 -0800459 if (backBuffer == nullptr) {
460 return false;
461 }
Pawin Vongmasa36653902018-11-15 00:10:25 -0800462 if (backBuffer->capacity() < mBackBufferSize) {
463 return false;
464 }
465 backBuffer->setRange(0, mBackBufferSize);
466 mBackBuffer = backBuffer;
467 return true;
468 }
469
470 /**
471 * Copy C2GraphicView to MediaImage2.
472 */
473 status_t copyToMediaImage() {
474 if (mInitCheck != OK) {
475 return mInitCheck;
476 }
477 return ImageCopy(mBackBuffer->base(), getMediaImage(), mView);
478 }
479
480 const sp<ABuffer> &imageData() const { return mMediaImage; }
481
482private:
483 status_t mInitCheck;
484
485 const C2GraphicView mView;
486 uint32_t mWidth;
487 uint32_t mHeight;
488 int32_t mColorFormat; ///< SDK color format for MediaImage
489 sp<ABuffer> mWrapped; ///< wrapped buffer (if we can map C2Buffer to an ABuffer)
490 uint32_t mAllocatedDepth;
491 uint32_t mBackBufferSize;
492 sp<ABuffer> mMediaImage;
493 std::function<sp<ABuffer>(size_t)> mAlloc;
494
495 sp<ABuffer> mBackBuffer; ///< backing buffer if we have to copy C2Buffer <=> ABuffer
496
497 MediaImage2 *getMediaImage() {
498 return (MediaImage2 *)mMediaImage->base();
499 }
500};
501
502} // namespace
503
504// GraphicBlockBuffer
505
506// static
507sp<GraphicBlockBuffer> GraphicBlockBuffer::Allocate(
508 const sp<AMessage> &format,
509 const std::shared_ptr<C2GraphicBlock> &block,
510 std::function<sp<ABuffer>(size_t)> alloc) {
511 C2GraphicView view(block->map().get());
512 if (view.error() != C2_OK) {
513 ALOGD("C2GraphicBlock::map failed: %d", view.error());
514 return nullptr;
515 }
516
517 int32_t colorFormat = COLOR_FormatYUV420Flexible;
518 (void)format->findInt32("color-format", &colorFormat);
519
Wonsik Kim7d966312019-06-04 14:00:49 -0700520 GraphicView2MediaImageConverter converter(view, colorFormat, false /* copy */);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800521 if (converter.initCheck() != OK) {
522 ALOGD("Converter init failed: %d", converter.initCheck());
523 return nullptr;
524 }
525 bool wrapped = true;
526 sp<ABuffer> buffer = converter.wrap();
527 if (buffer == nullptr) {
528 buffer = alloc(converter.backBufferSize());
529 if (!converter.setBackBuffer(buffer)) {
530 ALOGD("Converter failed to set back buffer");
531 return nullptr;
532 }
533 wrapped = false;
534 }
535 return new GraphicBlockBuffer(
536 format,
537 buffer,
538 std::move(view),
539 block,
540 converter.imageData(),
541 wrapped);
542}
543
544GraphicBlockBuffer::GraphicBlockBuffer(
545 const sp<AMessage> &format,
546 const sp<ABuffer> &buffer,
547 C2GraphicView &&view,
548 const std::shared_ptr<C2GraphicBlock> &block,
549 const sp<ABuffer> &imageData,
550 bool wrapped)
551 : Codec2Buffer(format, buffer),
552 mView(view),
553 mBlock(block),
Pawin Vongmasa36653902018-11-15 00:10:25 -0800554 mWrapped(wrapped) {
555 setImageData(imageData);
556}
557
558std::shared_ptr<C2Buffer> GraphicBlockBuffer::asC2Buffer() {
559 uint32_t width = mView.width();
560 uint32_t height = mView.height();
561 if (!mWrapped) {
562 (void)ImageCopy(mView, base(), imageData());
563 }
564 return C2Buffer::CreateGraphicBuffer(
565 mBlock->share(C2Rect(width, height), C2Fence()));
566}
567
568// GraphicMetadataBuffer
569GraphicMetadataBuffer::GraphicMetadataBuffer(
570 const sp<AMessage> &format,
571 const std::shared_ptr<C2Allocator> &alloc)
572 : Codec2Buffer(format, new ABuffer(sizeof(VideoNativeMetadata))),
573 mAlloc(alloc) {
574 ((VideoNativeMetadata *)base())->pBuffer = nullptr;
575}
576
577std::shared_ptr<C2Buffer> GraphicMetadataBuffer::asC2Buffer() {
578#ifndef __LP64__
579 VideoNativeMetadata *meta = (VideoNativeMetadata *)base();
580 ANativeWindowBuffer *buffer = (ANativeWindowBuffer *)meta->pBuffer;
581 if (buffer == nullptr) {
582 ALOGD("VideoNativeMetadata contains null buffer");
583 return nullptr;
584 }
585
586 ALOGV("VideoNativeMetadata: %dx%d", buffer->width, buffer->height);
587 C2Handle *handle = WrapNativeCodec2GrallocHandle(
Sungtak Leea4d13be2019-01-23 15:24:46 -0800588 buffer->handle,
Pawin Vongmasa36653902018-11-15 00:10:25 -0800589 buffer->width,
590 buffer->height,
591 buffer->format,
592 buffer->usage,
593 buffer->stride);
594 std::shared_ptr<C2GraphicAllocation> alloc;
595 c2_status_t err = mAlloc->priorGraphicAllocation(handle, &alloc);
596 if (err != C2_OK) {
597 ALOGD("Failed to wrap VideoNativeMetadata into C2GraphicAllocation");
598 return nullptr;
599 }
600 std::shared_ptr<C2GraphicBlock> block = _C2BlockFactory::CreateGraphicBlock(alloc);
601
602 meta->pBuffer = 0;
Wonsik Kimebe0f9e2019-07-03 11:06:51 -0700603 // TODO: wrap this in C2Fence so that the component can wait when it
604 // actually starts processing.
605 if (meta->nFenceFd >= 0) {
606 sp<Fence> fence(new Fence(meta->nFenceFd));
607 fence->waitForever(LOG_TAG);
608 }
Pawin Vongmasa36653902018-11-15 00:10:25 -0800609 return C2Buffer::CreateGraphicBuffer(
610 block->share(C2Rect(buffer->width, buffer->height), C2Fence()));
611#else
612 ALOGE("GraphicMetadataBuffer does not work on 64-bit arch");
613 return nullptr;
614#endif
615}
616
617// ConstGraphicBlockBuffer
618
619// static
620sp<ConstGraphicBlockBuffer> ConstGraphicBlockBuffer::Allocate(
621 const sp<AMessage> &format,
622 const std::shared_ptr<C2Buffer> &buffer,
623 std::function<sp<ABuffer>(size_t)> alloc) {
624 if (!buffer
625 || buffer->data().type() != C2BufferData::GRAPHIC
626 || buffer->data().graphicBlocks().size() != 1u) {
627 ALOGD("C2Buffer precond fail");
628 return nullptr;
629 }
630 std::unique_ptr<const C2GraphicView> view(std::make_unique<const C2GraphicView>(
631 buffer->data().graphicBlocks()[0].map().get()));
632 std::unique_ptr<const C2GraphicView> holder;
633
634 int32_t colorFormat = COLOR_FormatYUV420Flexible;
635 (void)format->findInt32("color-format", &colorFormat);
636
Wonsik Kim7d966312019-06-04 14:00:49 -0700637 GraphicView2MediaImageConverter converter(*view, colorFormat, false /* copy */);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800638 if (converter.initCheck() != OK) {
639 ALOGD("Converter init failed: %d", converter.initCheck());
640 return nullptr;
641 }
642 bool wrapped = true;
643 sp<ABuffer> aBuffer = converter.wrap();
644 if (aBuffer == nullptr) {
645 aBuffer = alloc(converter.backBufferSize());
646 if (!converter.setBackBuffer(aBuffer)) {
647 ALOGD("Converter failed to set back buffer");
648 return nullptr;
649 }
650 wrapped = false;
651 converter.copyToMediaImage();
652 // We don't need the view.
653 holder = std::move(view);
654 }
655 return new ConstGraphicBlockBuffer(
656 format,
657 aBuffer,
658 std::move(view),
659 buffer,
660 converter.imageData(),
661 wrapped);
662}
663
664// static
665sp<ConstGraphicBlockBuffer> ConstGraphicBlockBuffer::AllocateEmpty(
666 const sp<AMessage> &format,
667 std::function<sp<ABuffer>(size_t)> alloc) {
668 int32_t width, height;
669 if (!format->findInt32("width", &width)
670 || !format->findInt32("height", &height)) {
671 ALOGD("format had no width / height");
672 return nullptr;
673 }
Wonsik Kim8bfa17a2019-05-30 22:12:30 -0700674 // NOTE: we currently only support YUV420 formats for byte-buffer mode.
675 sp<ABuffer> aBuffer(alloc(align(width, 16) * align(height, 16) * 3 / 2));
Pawin Vongmasa36653902018-11-15 00:10:25 -0800676 return new ConstGraphicBlockBuffer(
677 format,
678 aBuffer,
679 nullptr,
680 nullptr,
681 nullptr,
682 false);
683}
684
685ConstGraphicBlockBuffer::ConstGraphicBlockBuffer(
686 const sp<AMessage> &format,
687 const sp<ABuffer> &aBuffer,
688 std::unique_ptr<const C2GraphicView> &&view,
689 const std::shared_ptr<C2Buffer> &buffer,
690 const sp<ABuffer> &imageData,
691 bool wrapped)
692 : Codec2Buffer(format, aBuffer),
693 mView(std::move(view)),
694 mBufferRef(buffer),
695 mWrapped(wrapped) {
Wonsik Kimc48ddcf2019-02-11 16:16:57 -0800696 setImageData(imageData);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800697}
698
699std::shared_ptr<C2Buffer> ConstGraphicBlockBuffer::asC2Buffer() {
Wonsik Kimf9b32122020-04-02 11:30:17 -0700700 return mBufferRef;
701}
702
703void ConstGraphicBlockBuffer::clearC2BufferRefs() {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800704 mView.reset();
Wonsik Kimf9b32122020-04-02 11:30:17 -0700705 mBufferRef.reset();
Pawin Vongmasa36653902018-11-15 00:10:25 -0800706}
707
708bool ConstGraphicBlockBuffer::canCopy(const std::shared_ptr<C2Buffer> &buffer) const {
709 if (mWrapped || mBufferRef) {
710 ALOGD("ConstGraphicBlockBuffer::canCopy: %swrapped ; buffer ref %s",
711 mWrapped ? "" : "not ", mBufferRef ? "exists" : "doesn't exist");
712 return false;
713 }
714 if (!buffer) {
715 // Nothing to copy, so we can copy by doing nothing.
716 return true;
717 }
718 if (buffer->data().type() != C2BufferData::GRAPHIC) {
719 ALOGD("ConstGraphicBlockBuffer::canCopy: buffer precondition unsatisfied");
720 return false;
721 }
722 if (buffer->data().graphicBlocks().size() == 0) {
723 return true;
724 } else if (buffer->data().graphicBlocks().size() != 1u) {
725 ALOGD("ConstGraphicBlockBuffer::canCopy: too many blocks");
726 return false;
727 }
728
729 int32_t colorFormat = COLOR_FormatYUV420Flexible;
730 // FIXME: format() is not const, but we cannot change it, so do a const cast here
731 const_cast<ConstGraphicBlockBuffer *>(this)->format()->findInt32("color-format", &colorFormat);
732
733 GraphicView2MediaImageConverter converter(
Wonsik Kim7d966312019-06-04 14:00:49 -0700734 buffer->data().graphicBlocks()[0].map().get(), colorFormat, true /* copy */);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800735 if (converter.initCheck() != OK) {
736 ALOGD("ConstGraphicBlockBuffer::canCopy: converter init failed: %d", converter.initCheck());
737 return false;
738 }
739 if (converter.backBufferSize() > capacity()) {
740 ALOGD("ConstGraphicBlockBuffer::canCopy: insufficient capacity: req %u has %zu",
741 converter.backBufferSize(), capacity());
742 return false;
743 }
744 return true;
745}
746
747bool ConstGraphicBlockBuffer::copy(const std::shared_ptr<C2Buffer> &buffer) {
748 if (!buffer || buffer->data().graphicBlocks().size() == 0) {
749 setRange(0, 0);
750 return true;
751 }
752 int32_t colorFormat = COLOR_FormatYUV420Flexible;
753 format()->findInt32("color-format", &colorFormat);
754
755 GraphicView2MediaImageConverter converter(
Wonsik Kim7d966312019-06-04 14:00:49 -0700756 buffer->data().graphicBlocks()[0].map().get(), colorFormat, true /* copy */);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800757 if (converter.initCheck() != OK) {
758 ALOGD("ConstGraphicBlockBuffer::copy: converter init failed: %d", converter.initCheck());
759 return false;
760 }
761 sp<ABuffer> aBuffer = new ABuffer(base(), capacity());
762 if (!converter.setBackBuffer(aBuffer)) {
763 ALOGD("ConstGraphicBlockBuffer::copy: set back buffer failed");
764 return false;
765 }
Pin-chih Lin1971e2c2019-04-15 19:36:26 +0800766 setRange(0, aBuffer->size()); // align size info
Pawin Vongmasa36653902018-11-15 00:10:25 -0800767 converter.copyToMediaImage();
768 setImageData(converter.imageData());
769 mBufferRef = buffer;
770 return true;
771}
772
773// EncryptedLinearBlockBuffer
774
775EncryptedLinearBlockBuffer::EncryptedLinearBlockBuffer(
776 const sp<AMessage> &format,
777 const std::shared_ptr<C2LinearBlock> &block,
778 const sp<IMemory> &memory,
779 int32_t heapSeqNum)
Ytai Ben-Tsvi7dd39722019-09-05 15:14:30 -0700780 // TODO: Using unsecurePointer() has some associated security pitfalls
781 // (see declaration for details).
782 // Either document why it is safe in this case or address the
783 // issue (e.g. by copying).
784 : Codec2Buffer(format, new ABuffer(memory->unsecurePointer(), memory->size())),
Pawin Vongmasa36653902018-11-15 00:10:25 -0800785 mBlock(block),
786 mMemory(memory),
787 mHeapSeqNum(heapSeqNum) {
788}
789
790std::shared_ptr<C2Buffer> EncryptedLinearBlockBuffer::asC2Buffer() {
791 return C2Buffer::CreateLinearBuffer(mBlock->share(offset(), size(), C2Fence()));
792}
793
794void EncryptedLinearBlockBuffer::fillSourceBuffer(
Robert Shih895fba92019-07-16 16:29:44 -0700795 hardware::drm::V1_0::SharedBuffer *source) {
796 BufferChannelBase::IMemoryToSharedBuffer(mMemory, mHeapSeqNum, source);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800797}
798
799void EncryptedLinearBlockBuffer::fillSourceBuffer(
800 hardware::cas::native::V1_0::SharedBuffer *source) {
801 ssize_t offset;
802 size_t size;
803
804 mHidlMemory = hardware::fromHeap(mMemory->getMemory(&offset, &size));
805 source->heapBase = *mHidlMemory;
806 source->offset = offset;
807 source->size = size;
808}
809
810bool EncryptedLinearBlockBuffer::copyDecryptedContent(
811 const sp<IMemory> &decrypted, size_t length) {
812 C2WriteView view = mBlock->map().get();
813 if (view.error() != C2_OK) {
814 return false;
815 }
816 if (view.size() < length) {
817 return false;
818 }
Ytai Ben-Tsvi7dd39722019-09-05 15:14:30 -0700819 memcpy(view.data(), decrypted->unsecurePointer(), length);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800820 return true;
821}
822
823bool EncryptedLinearBlockBuffer::copyDecryptedContentFromMemory(size_t length) {
824 return copyDecryptedContent(mMemory, length);
825}
826
827native_handle_t *EncryptedLinearBlockBuffer::handle() const {
828 return const_cast<native_handle_t *>(mBlock->handle());
829}
830
831} // namespace android