blob: 2dec42ed153463a4fc95e9608922a431e59843e7 [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>
23#include <media/stagefright/MediaCodecConstants.h>
24#include <media/stagefright/foundation/ABuffer.h>
25#include <media/stagefright/foundation/AMessage.h>
26#include <media/stagefright/foundation/AUtils.h>
27#include <nativebase/nativebase.h>
28
29#include <C2AllocatorGralloc.h>
30#include <C2BlockInternal.h>
31#include <C2Debug.h>
32
33#include "Codec2Buffer.h"
34
35namespace android {
36
37// Codec2Buffer
38
39bool Codec2Buffer::canCopyLinear(const std::shared_ptr<C2Buffer> &buffer) const {
40 if (const_cast<Codec2Buffer *>(this)->base() == nullptr) {
41 return false;
42 }
43 if (!buffer) {
44 // Nothing to copy, so we can copy by doing nothing.
45 return true;
46 }
47 if (buffer->data().type() != C2BufferData::LINEAR) {
48 return false;
49 }
50 if (buffer->data().linearBlocks().size() == 0u) {
51 // Nothing to copy, so we can copy by doing nothing.
52 return true;
53 } else if (buffer->data().linearBlocks().size() > 1u) {
54 // We don't know how to copy more than one blocks.
55 return false;
56 }
57 if (buffer->data().linearBlocks()[0].size() > capacity()) {
58 // It won't fit.
59 return false;
60 }
61 return true;
62}
63
64bool Codec2Buffer::copyLinear(const std::shared_ptr<C2Buffer> &buffer) {
65 // We assume that all canCopyLinear() checks passed.
66 if (!buffer || buffer->data().linearBlocks().size() == 0u
67 || buffer->data().linearBlocks()[0].size() == 0u) {
68 setRange(0, 0);
69 return true;
70 }
71 C2ReadView view = buffer->data().linearBlocks()[0].map().get();
72 if (view.error() != C2_OK) {
73 ALOGD("Error while mapping: %d", view.error());
74 return false;
75 }
76 if (view.capacity() > capacity()) {
77 ALOGD("C2ConstLinearBlock lied --- it actually doesn't fit: view(%u) > this(%zu)",
78 view.capacity(), capacity());
79 return false;
80 }
81 memcpy(base(), view.data(), view.capacity());
82 setRange(0, view.capacity());
83 return true;
84}
85
86void Codec2Buffer::setImageData(const sp<ABuffer> &imageData) {
87 meta()->setBuffer("image-data", imageData);
88 format()->setBuffer("image-data", imageData);
89 MediaImage2 *img = (MediaImage2*)imageData->data();
90 if (img->mNumPlanes > 0 && img->mType != img->MEDIA_IMAGE_TYPE_UNKNOWN) {
91 int32_t stride = img->mPlane[0].mRowInc;
92 format()->setInt32(KEY_STRIDE, stride);
93 if (img->mNumPlanes > 1 && stride > 0) {
94 int32_t vstride = (img->mPlane[1].mOffset - img->mPlane[0].mOffset) / stride;
95 format()->setInt32(KEY_SLICE_HEIGHT, vstride);
96 }
97 }
98}
99
100// LocalLinearBuffer
101
102bool LocalLinearBuffer::canCopy(const std::shared_ptr<C2Buffer> &buffer) const {
103 return canCopyLinear(buffer);
104}
105
106bool LocalLinearBuffer::copy(const std::shared_ptr<C2Buffer> &buffer) {
107 return copyLinear(buffer);
108}
109
110// DummyContainerBuffer
111
Pawin Vongmasa8be93112018-12-11 14:01:42 -0800112static uint8_t sDummyByte[1] = { 0 };
113
Pawin Vongmasa36653902018-11-15 00:10:25 -0800114DummyContainerBuffer::DummyContainerBuffer(
115 const sp<AMessage> &format, const std::shared_ptr<C2Buffer> &buffer)
Pawin Vongmasa8be93112018-12-11 14:01:42 -0800116 : Codec2Buffer(format, new ABuffer(sDummyByte, 1)),
Pawin Vongmasa36653902018-11-15 00:10:25 -0800117 mBufferRef(buffer) {
118 setRange(0, buffer ? 1 : 0);
119}
120
121std::shared_ptr<C2Buffer> DummyContainerBuffer::asC2Buffer() {
122 return std::move(mBufferRef);
123}
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() {
198 return std::move(mBufferRef);
199}
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)
214 */
215 GraphicView2MediaImageConverter(
216 const C2GraphicView &view, int32_t colorFormat)
217 : mInitCheck(NO_INIT),
218 mView(view),
219 mWidth(view.width()),
220 mHeight(view.height()),
221 mColorFormat(colorFormat),
222 mAllocatedDepth(0),
223 mBackBufferSize(0),
224 mMediaImage(new ABuffer(sizeof(MediaImage2))) {
225 if (view.error() != C2_OK) {
226 ALOGD("Converter: view.error() = %d", view.error());
227 mInitCheck = BAD_VALUE;
228 return;
229 }
230 MediaImage2 *mediaImage = (MediaImage2 *)mMediaImage->base();
231 const C2PlanarLayout &layout = view.layout();
232 if (layout.numPlanes == 0) {
233 ALOGD("Converter: 0 planes");
234 mInitCheck = BAD_VALUE;
235 return;
236 }
237 mAllocatedDepth = layout.planes[0].allocatedDepth;
238 uint32_t bitDepth = layout.planes[0].bitDepth;
239
240 // align width and height to support subsampling cleanly
241 uint32_t mStride = align(mWidth, 2) * divUp(layout.planes[0].allocatedDepth, 8u);
242 uint32_t mVStride = align(mHeight, 2);
243
244 switch (layout.type) {
245 case C2PlanarLayout::TYPE_YUV:
246 mediaImage->mType = MediaImage2::MEDIA_IMAGE_TYPE_YUV;
247 if (layout.numPlanes != 3) {
248 ALOGD("Converter: %d planes for YUV layout", layout.numPlanes);
249 mInitCheck = BAD_VALUE;
250 return;
251 }
252 if (layout.planes[0].channel != C2PlaneInfo::CHANNEL_Y
253 || layout.planes[1].channel != C2PlaneInfo::CHANNEL_CB
254 || layout.planes[2].channel != C2PlaneInfo::CHANNEL_CR
255 || layout.planes[0].colSampling != 1
256 || layout.planes[0].rowSampling != 1
257 || layout.planes[1].colSampling != 2
258 || layout.planes[1].rowSampling != 2
259 || layout.planes[2].colSampling != 2
260 || layout.planes[2].rowSampling != 2) {
261 ALOGD("Converter: not YUV420 for YUV layout");
262 mInitCheck = BAD_VALUE;
263 return;
264 }
265 switch (mColorFormat) {
266 case COLOR_FormatYUV420Flexible:
267 { // try to map directly. check if the planes are near one another
268 const uint8_t *minPtr = mView.data()[0];
269 const uint8_t *maxPtr = mView.data()[0];
270 int32_t planeSize = 0;
271 for (uint32_t i = 0; i < layout.numPlanes; ++i) {
272 const C2PlaneInfo &plane = layout.planes[i];
273 ssize_t minOffset = plane.minOffset(mWidth, mHeight);
274 ssize_t maxOffset = plane.maxOffset(mWidth, mHeight);
275 if (minPtr > mView.data()[i] + minOffset) {
276 minPtr = mView.data()[i] + minOffset;
277 }
278 if (maxPtr < mView.data()[i] + maxOffset) {
279 maxPtr = mView.data()[i] + maxOffset;
280 }
281 planeSize += std::abs(plane.rowInc) * align(mHeight, 64)
282 / plane.rowSampling / plane.colSampling * divUp(mAllocatedDepth, 8u);
283 }
284
285 if ((maxPtr - minPtr + 1) <= planeSize) {
286 // FIXME: this is risky as reading/writing data out of bound results in
287 // an undefined behavior, but gralloc does assume a contiguous
288 // mapping
289 for (uint32_t i = 0; i < layout.numPlanes; ++i) {
290 const C2PlaneInfo &plane = layout.planes[i];
291 mediaImage->mPlane[i].mOffset = mView.data()[i] - minPtr;
292 mediaImage->mPlane[i].mColInc = plane.colInc;
293 mediaImage->mPlane[i].mRowInc = plane.rowInc;
294 mediaImage->mPlane[i].mHorizSubsampling = plane.colSampling;
295 mediaImage->mPlane[i].mVertSubsampling = plane.rowSampling;
296 }
297 mWrapped = new ABuffer(const_cast<uint8_t *>(minPtr), maxPtr - minPtr + 1);
298 break;
299 }
300 }
301 [[fallthrough]];
302
303 case COLOR_FormatYUV420Planar:
304 case COLOR_FormatYUV420PackedPlanar:
305 mediaImage->mPlane[mediaImage->Y].mOffset = 0;
306 mediaImage->mPlane[mediaImage->Y].mColInc = 1;
307 mediaImage->mPlane[mediaImage->Y].mRowInc = mStride;
308 mediaImage->mPlane[mediaImage->Y].mHorizSubsampling = 1;
309 mediaImage->mPlane[mediaImage->Y].mVertSubsampling = 1;
310
311 mediaImage->mPlane[mediaImage->U].mOffset = mStride * mVStride;
312 mediaImage->mPlane[mediaImage->U].mColInc = 1;
313 mediaImage->mPlane[mediaImage->U].mRowInc = mStride / 2;
314 mediaImage->mPlane[mediaImage->U].mHorizSubsampling = 2;
315 mediaImage->mPlane[mediaImage->U].mVertSubsampling = 2;
316
317 mediaImage->mPlane[mediaImage->V].mOffset = mStride * mVStride * 5 / 4;
318 mediaImage->mPlane[mediaImage->V].mColInc = 1;
319 mediaImage->mPlane[mediaImage->V].mRowInc = mStride / 2;
320 mediaImage->mPlane[mediaImage->V].mHorizSubsampling = 2;
321 mediaImage->mPlane[mediaImage->V].mVertSubsampling = 2;
322 break;
323
324 case COLOR_FormatYUV420SemiPlanar:
325 case COLOR_FormatYUV420PackedSemiPlanar:
326 mediaImage->mPlane[mediaImage->Y].mOffset = 0;
327 mediaImage->mPlane[mediaImage->Y].mColInc = 1;
328 mediaImage->mPlane[mediaImage->Y].mRowInc = mStride;
329 mediaImage->mPlane[mediaImage->Y].mHorizSubsampling = 1;
330 mediaImage->mPlane[mediaImage->Y].mVertSubsampling = 1;
331
332 mediaImage->mPlane[mediaImage->U].mOffset = mStride * mVStride;
333 mediaImage->mPlane[mediaImage->U].mColInc = 2;
334 mediaImage->mPlane[mediaImage->U].mRowInc = mStride;
335 mediaImage->mPlane[mediaImage->U].mHorizSubsampling = 2;
336 mediaImage->mPlane[mediaImage->U].mVertSubsampling = 2;
337
338 mediaImage->mPlane[mediaImage->V].mOffset = mStride * mVStride + 1;
339 mediaImage->mPlane[mediaImage->V].mColInc = 2;
340 mediaImage->mPlane[mediaImage->V].mRowInc = mStride;
341 mediaImage->mPlane[mediaImage->V].mHorizSubsampling = 2;
342 mediaImage->mPlane[mediaImage->V].mVertSubsampling = 2;
343 break;
344
345 default:
346 ALOGD("Converter: incompactible color format (%d) for YUV layout", mColorFormat);
347 mInitCheck = BAD_VALUE;
348 return;
349 }
350 break;
351 case C2PlanarLayout::TYPE_YUVA:
352 mediaImage->mType = MediaImage2::MEDIA_IMAGE_TYPE_YUVA;
353 // We don't have an SDK YUVA format
354 ALOGD("Converter: incompactible color format (%d) for YUVA layout", mColorFormat);
355 mInitCheck = BAD_VALUE;
356 return;
357 case C2PlanarLayout::TYPE_RGB:
358 mediaImage->mType = MediaImage2::MEDIA_IMAGE_TYPE_RGB;
359 switch (mColorFormat) {
360 // TODO media image
361 case COLOR_FormatRGBFlexible:
362 case COLOR_Format24bitBGR888:
363 case COLOR_Format24bitRGB888:
364 break;
365 default:
366 ALOGD("Converter: incompactible color format (%d) for RGB layout", mColorFormat);
367 mInitCheck = BAD_VALUE;
368 return;
369 }
370 if (layout.numPlanes != 3) {
371 ALOGD("Converter: %d planes for RGB layout", layout.numPlanes);
372 mInitCheck = BAD_VALUE;
373 return;
374 }
375 break;
376 case C2PlanarLayout::TYPE_RGBA:
377 mediaImage->mType = MediaImage2::MEDIA_IMAGE_TYPE_RGBA;
378 switch (mColorFormat) {
379 // TODO media image
380 case COLOR_FormatRGBAFlexible:
381 case COLOR_Format32bitABGR8888:
382 case COLOR_Format32bitARGB8888:
383 case COLOR_Format32bitBGRA8888:
384 break;
385 default:
386 ALOGD("Incompactible color format (%d) for RGBA layout", mColorFormat);
387 mInitCheck = BAD_VALUE;
388 return;
389 }
390 if (layout.numPlanes != 4) {
391 ALOGD("Converter: %d planes for RGBA layout", layout.numPlanes);
392 mInitCheck = BAD_VALUE;
393 return;
394 }
395 break;
396 default:
397 mediaImage->mType = MediaImage2::MEDIA_IMAGE_TYPE_UNKNOWN;
398 ALOGD("Unknown layout");
399 mInitCheck = BAD_VALUE;
400 return;
401 }
402 mediaImage->mNumPlanes = layout.numPlanes;
403 mediaImage->mWidth = mWidth;
404 mediaImage->mHeight = mHeight;
405 mediaImage->mBitDepth = bitDepth;
406 mediaImage->mBitDepthAllocated = mAllocatedDepth;
407
408 uint32_t bufferSize = 0;
409 for (uint32_t i = 0; i < layout.numPlanes; ++i) {
410 const C2PlaneInfo &plane = layout.planes[i];
411 if (plane.allocatedDepth < plane.bitDepth
412 || plane.rightShift != plane.allocatedDepth - plane.bitDepth) {
413 ALOGD("rightShift value of %u unsupported", plane.rightShift);
414 mInitCheck = BAD_VALUE;
415 return;
416 }
417 if (plane.allocatedDepth > 8 && plane.endianness != C2PlaneInfo::NATIVE) {
418 ALOGD("endianness value of %u unsupported", plane.endianness);
419 mInitCheck = BAD_VALUE;
420 return;
421 }
422 if (plane.allocatedDepth != mAllocatedDepth || plane.bitDepth != bitDepth) {
423 ALOGV("different allocatedDepth/bitDepth per plane unsupported");
424 mInitCheck = BAD_VALUE;
425 return;
426 }
427 bufferSize += mStride * mVStride
428 / plane.rowSampling / plane.colSampling;
429 }
430
431 mBackBufferSize = bufferSize;
432 mInitCheck = OK;
433 }
434
435 status_t initCheck() const { return mInitCheck; }
436
437 uint32_t backBufferSize() const { return mBackBufferSize; }
438
439 /**
440 * Wrap C2GraphicView using a MediaImage2. Note that if not wrapped, the content is not mapped
441 * in this function --- the caller should use CopyGraphicView2MediaImage() function to copy the
442 * data into a backing buffer explicitly.
443 *
444 * \return media buffer. This is null if wrapping failed.
445 */
446 sp<ABuffer> wrap() const {
447 if (mBackBuffer == nullptr) {
448 return mWrapped;
449 }
450 return nullptr;
451 }
452
453 bool setBackBuffer(const sp<ABuffer> &backBuffer) {
Wonsik Kim186fdbf2019-01-29 13:30:01 -0800454 if (backBuffer == nullptr) {
455 return false;
456 }
Pawin Vongmasa36653902018-11-15 00:10:25 -0800457 if (backBuffer->capacity() < mBackBufferSize) {
458 return false;
459 }
460 backBuffer->setRange(0, mBackBufferSize);
461 mBackBuffer = backBuffer;
462 return true;
463 }
464
465 /**
466 * Copy C2GraphicView to MediaImage2.
467 */
468 status_t copyToMediaImage() {
469 if (mInitCheck != OK) {
470 return mInitCheck;
471 }
472 return ImageCopy(mBackBuffer->base(), getMediaImage(), mView);
473 }
474
475 const sp<ABuffer> &imageData() const { return mMediaImage; }
476
477private:
478 status_t mInitCheck;
479
480 const C2GraphicView mView;
481 uint32_t mWidth;
482 uint32_t mHeight;
483 int32_t mColorFormat; ///< SDK color format for MediaImage
484 sp<ABuffer> mWrapped; ///< wrapped buffer (if we can map C2Buffer to an ABuffer)
485 uint32_t mAllocatedDepth;
486 uint32_t mBackBufferSize;
487 sp<ABuffer> mMediaImage;
488 std::function<sp<ABuffer>(size_t)> mAlloc;
489
490 sp<ABuffer> mBackBuffer; ///< backing buffer if we have to copy C2Buffer <=> ABuffer
491
492 MediaImage2 *getMediaImage() {
493 return (MediaImage2 *)mMediaImage->base();
494 }
495};
496
497} // namespace
498
499// GraphicBlockBuffer
500
501// static
502sp<GraphicBlockBuffer> GraphicBlockBuffer::Allocate(
503 const sp<AMessage> &format,
504 const std::shared_ptr<C2GraphicBlock> &block,
505 std::function<sp<ABuffer>(size_t)> alloc) {
506 C2GraphicView view(block->map().get());
507 if (view.error() != C2_OK) {
508 ALOGD("C2GraphicBlock::map failed: %d", view.error());
509 return nullptr;
510 }
511
512 int32_t colorFormat = COLOR_FormatYUV420Flexible;
513 (void)format->findInt32("color-format", &colorFormat);
514
515 GraphicView2MediaImageConverter converter(view, colorFormat);
516 if (converter.initCheck() != OK) {
517 ALOGD("Converter init failed: %d", converter.initCheck());
518 return nullptr;
519 }
520 bool wrapped = true;
521 sp<ABuffer> buffer = converter.wrap();
522 if (buffer == nullptr) {
523 buffer = alloc(converter.backBufferSize());
524 if (!converter.setBackBuffer(buffer)) {
525 ALOGD("Converter failed to set back buffer");
526 return nullptr;
527 }
528 wrapped = false;
529 }
530 return new GraphicBlockBuffer(
531 format,
532 buffer,
533 std::move(view),
534 block,
535 converter.imageData(),
536 wrapped);
537}
538
539GraphicBlockBuffer::GraphicBlockBuffer(
540 const sp<AMessage> &format,
541 const sp<ABuffer> &buffer,
542 C2GraphicView &&view,
543 const std::shared_ptr<C2GraphicBlock> &block,
544 const sp<ABuffer> &imageData,
545 bool wrapped)
546 : Codec2Buffer(format, buffer),
547 mView(view),
548 mBlock(block),
549 mImageData(imageData),
550 mWrapped(wrapped) {
551 setImageData(imageData);
552}
553
554std::shared_ptr<C2Buffer> GraphicBlockBuffer::asC2Buffer() {
555 uint32_t width = mView.width();
556 uint32_t height = mView.height();
557 if (!mWrapped) {
558 (void)ImageCopy(mView, base(), imageData());
559 }
560 return C2Buffer::CreateGraphicBuffer(
561 mBlock->share(C2Rect(width, height), C2Fence()));
562}
563
564// GraphicMetadataBuffer
565GraphicMetadataBuffer::GraphicMetadataBuffer(
566 const sp<AMessage> &format,
567 const std::shared_ptr<C2Allocator> &alloc)
568 : Codec2Buffer(format, new ABuffer(sizeof(VideoNativeMetadata))),
569 mAlloc(alloc) {
570 ((VideoNativeMetadata *)base())->pBuffer = nullptr;
571}
572
573std::shared_ptr<C2Buffer> GraphicMetadataBuffer::asC2Buffer() {
574#ifndef __LP64__
575 VideoNativeMetadata *meta = (VideoNativeMetadata *)base();
576 ANativeWindowBuffer *buffer = (ANativeWindowBuffer *)meta->pBuffer;
577 if (buffer == nullptr) {
578 ALOGD("VideoNativeMetadata contains null buffer");
579 return nullptr;
580 }
581
582 ALOGV("VideoNativeMetadata: %dx%d", buffer->width, buffer->height);
583 C2Handle *handle = WrapNativeCodec2GrallocHandle(
Sungtak Leea4d13be2019-01-23 15:24:46 -0800584 buffer->handle,
Pawin Vongmasa36653902018-11-15 00:10:25 -0800585 buffer->width,
586 buffer->height,
587 buffer->format,
588 buffer->usage,
589 buffer->stride);
590 std::shared_ptr<C2GraphicAllocation> alloc;
591 c2_status_t err = mAlloc->priorGraphicAllocation(handle, &alloc);
592 if (err != C2_OK) {
593 ALOGD("Failed to wrap VideoNativeMetadata into C2GraphicAllocation");
594 return nullptr;
595 }
596 std::shared_ptr<C2GraphicBlock> block = _C2BlockFactory::CreateGraphicBlock(alloc);
597
598 meta->pBuffer = 0;
599 // TODO: fence
600 return C2Buffer::CreateGraphicBuffer(
601 block->share(C2Rect(buffer->width, buffer->height), C2Fence()));
602#else
603 ALOGE("GraphicMetadataBuffer does not work on 64-bit arch");
604 return nullptr;
605#endif
606}
607
608// ConstGraphicBlockBuffer
609
610// static
611sp<ConstGraphicBlockBuffer> ConstGraphicBlockBuffer::Allocate(
612 const sp<AMessage> &format,
613 const std::shared_ptr<C2Buffer> &buffer,
614 std::function<sp<ABuffer>(size_t)> alloc) {
615 if (!buffer
616 || buffer->data().type() != C2BufferData::GRAPHIC
617 || buffer->data().graphicBlocks().size() != 1u) {
618 ALOGD("C2Buffer precond fail");
619 return nullptr;
620 }
621 std::unique_ptr<const C2GraphicView> view(std::make_unique<const C2GraphicView>(
622 buffer->data().graphicBlocks()[0].map().get()));
623 std::unique_ptr<const C2GraphicView> holder;
624
625 int32_t colorFormat = COLOR_FormatYUV420Flexible;
626 (void)format->findInt32("color-format", &colorFormat);
627
628 GraphicView2MediaImageConverter converter(*view, colorFormat);
629 if (converter.initCheck() != OK) {
630 ALOGD("Converter init failed: %d", converter.initCheck());
631 return nullptr;
632 }
633 bool wrapped = true;
634 sp<ABuffer> aBuffer = converter.wrap();
635 if (aBuffer == nullptr) {
636 aBuffer = alloc(converter.backBufferSize());
637 if (!converter.setBackBuffer(aBuffer)) {
638 ALOGD("Converter failed to set back buffer");
639 return nullptr;
640 }
641 wrapped = false;
642 converter.copyToMediaImage();
643 // We don't need the view.
644 holder = std::move(view);
645 }
646 return new ConstGraphicBlockBuffer(
647 format,
648 aBuffer,
649 std::move(view),
650 buffer,
651 converter.imageData(),
652 wrapped);
653}
654
655// static
656sp<ConstGraphicBlockBuffer> ConstGraphicBlockBuffer::AllocateEmpty(
657 const sp<AMessage> &format,
658 std::function<sp<ABuffer>(size_t)> alloc) {
659 int32_t width, height;
660 if (!format->findInt32("width", &width)
661 || !format->findInt32("height", &height)) {
662 ALOGD("format had no width / height");
663 return nullptr;
664 }
665 sp<ABuffer> aBuffer(alloc(width * height * 4));
666 return new ConstGraphicBlockBuffer(
667 format,
668 aBuffer,
669 nullptr,
670 nullptr,
671 nullptr,
672 false);
673}
674
675ConstGraphicBlockBuffer::ConstGraphicBlockBuffer(
676 const sp<AMessage> &format,
677 const sp<ABuffer> &aBuffer,
678 std::unique_ptr<const C2GraphicView> &&view,
679 const std::shared_ptr<C2Buffer> &buffer,
680 const sp<ABuffer> &imageData,
681 bool wrapped)
682 : Codec2Buffer(format, aBuffer),
683 mView(std::move(view)),
684 mBufferRef(buffer),
685 mWrapped(wrapped) {
686 if (imageData != nullptr) {
687 setImageData(imageData);
688 }
689}
690
691std::shared_ptr<C2Buffer> ConstGraphicBlockBuffer::asC2Buffer() {
692 mView.reset();
693 return std::move(mBufferRef);
694}
695
696bool ConstGraphicBlockBuffer::canCopy(const std::shared_ptr<C2Buffer> &buffer) const {
697 if (mWrapped || mBufferRef) {
698 ALOGD("ConstGraphicBlockBuffer::canCopy: %swrapped ; buffer ref %s",
699 mWrapped ? "" : "not ", mBufferRef ? "exists" : "doesn't exist");
700 return false;
701 }
702 if (!buffer) {
703 // Nothing to copy, so we can copy by doing nothing.
704 return true;
705 }
706 if (buffer->data().type() != C2BufferData::GRAPHIC) {
707 ALOGD("ConstGraphicBlockBuffer::canCopy: buffer precondition unsatisfied");
708 return false;
709 }
710 if (buffer->data().graphicBlocks().size() == 0) {
711 return true;
712 } else if (buffer->data().graphicBlocks().size() != 1u) {
713 ALOGD("ConstGraphicBlockBuffer::canCopy: too many blocks");
714 return false;
715 }
716
717 int32_t colorFormat = COLOR_FormatYUV420Flexible;
718 // FIXME: format() is not const, but we cannot change it, so do a const cast here
719 const_cast<ConstGraphicBlockBuffer *>(this)->format()->findInt32("color-format", &colorFormat);
720
721 GraphicView2MediaImageConverter converter(
722 buffer->data().graphicBlocks()[0].map().get(), colorFormat);
723 if (converter.initCheck() != OK) {
724 ALOGD("ConstGraphicBlockBuffer::canCopy: converter init failed: %d", converter.initCheck());
725 return false;
726 }
727 if (converter.backBufferSize() > capacity()) {
728 ALOGD("ConstGraphicBlockBuffer::canCopy: insufficient capacity: req %u has %zu",
729 converter.backBufferSize(), capacity());
730 return false;
731 }
732 return true;
733}
734
735bool ConstGraphicBlockBuffer::copy(const std::shared_ptr<C2Buffer> &buffer) {
736 if (!buffer || buffer->data().graphicBlocks().size() == 0) {
737 setRange(0, 0);
738 return true;
739 }
740 int32_t colorFormat = COLOR_FormatYUV420Flexible;
741 format()->findInt32("color-format", &colorFormat);
742
743 GraphicView2MediaImageConverter converter(
744 buffer->data().graphicBlocks()[0].map().get(), colorFormat);
745 if (converter.initCheck() != OK) {
746 ALOGD("ConstGraphicBlockBuffer::copy: converter init failed: %d", converter.initCheck());
747 return false;
748 }
749 sp<ABuffer> aBuffer = new ABuffer(base(), capacity());
750 if (!converter.setBackBuffer(aBuffer)) {
751 ALOGD("ConstGraphicBlockBuffer::copy: set back buffer failed");
752 return false;
753 }
754 converter.copyToMediaImage();
755 setImageData(converter.imageData());
756 mBufferRef = buffer;
757 return true;
758}
759
760// EncryptedLinearBlockBuffer
761
762EncryptedLinearBlockBuffer::EncryptedLinearBlockBuffer(
763 const sp<AMessage> &format,
764 const std::shared_ptr<C2LinearBlock> &block,
765 const sp<IMemory> &memory,
766 int32_t heapSeqNum)
767 : Codec2Buffer(format, new ABuffer(memory->pointer(), memory->size())),
768 mBlock(block),
769 mMemory(memory),
770 mHeapSeqNum(heapSeqNum) {
771}
772
773std::shared_ptr<C2Buffer> EncryptedLinearBlockBuffer::asC2Buffer() {
774 return C2Buffer::CreateLinearBuffer(mBlock->share(offset(), size(), C2Fence()));
775}
776
777void EncryptedLinearBlockBuffer::fillSourceBuffer(
778 ICrypto::SourceBuffer *source) {
779 source->mSharedMemory = mMemory;
780 source->mHeapSeqNum = mHeapSeqNum;
781}
782
783void EncryptedLinearBlockBuffer::fillSourceBuffer(
784 hardware::cas::native::V1_0::SharedBuffer *source) {
785 ssize_t offset;
786 size_t size;
787
788 mHidlMemory = hardware::fromHeap(mMemory->getMemory(&offset, &size));
789 source->heapBase = *mHidlMemory;
790 source->offset = offset;
791 source->size = size;
792}
793
794bool EncryptedLinearBlockBuffer::copyDecryptedContent(
795 const sp<IMemory> &decrypted, size_t length) {
796 C2WriteView view = mBlock->map().get();
797 if (view.error() != C2_OK) {
798 return false;
799 }
800 if (view.size() < length) {
801 return false;
802 }
803 memcpy(view.data(), decrypted->pointer(), length);
804 return true;
805}
806
807bool EncryptedLinearBlockBuffer::copyDecryptedContentFromMemory(size_t length) {
808 return copyDecryptedContent(mMemory, length);
809}
810
811native_handle_t *EncryptedLinearBlockBuffer::handle() const {
812 return const_cast<native_handle_t *>(mBlock->handle());
813}
814
815} // namespace android