1/* 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 112DummyContainerBuffer::DummyContainerBuffer( 113 const sp<AMessage> &format, const std::shared_ptr<C2Buffer> &buffer) 114 : Codec2Buffer(format, new ABuffer(nullptr, 1)), 115 mBufferRef(buffer) { 116 setRange(0, buffer ? 1 : 0); 117} 118 119std::shared_ptr<C2Buffer> DummyContainerBuffer::asC2Buffer() { 120 return std::move(mBufferRef); 121} 122 123bool DummyContainerBuffer::canCopy(const std::shared_ptr<C2Buffer> &) const { 124 return !mBufferRef; 125} 126 127bool DummyContainerBuffer::copy(const std::shared_ptr<C2Buffer> &buffer) { 128 mBufferRef = buffer; 129 setRange(0, mBufferRef ? 1 : 0); 130 return true; 131} 132 133// LinearBlockBuffer 134 135// static 136sp<LinearBlockBuffer> LinearBlockBuffer::Allocate( 137 const sp<AMessage> &format, const std::shared_ptr<C2LinearBlock> &block) { 138 C2WriteView writeView(block->map().get()); 139 if (writeView.error() != C2_OK) { 140 return nullptr; 141 } 142 return new LinearBlockBuffer(format, std::move(writeView), block); 143} 144 145std::shared_ptr<C2Buffer> LinearBlockBuffer::asC2Buffer() { 146 return C2Buffer::CreateLinearBuffer(mBlock->share(offset(), size(), C2Fence())); 147} 148 149bool LinearBlockBuffer::canCopy(const std::shared_ptr<C2Buffer> &buffer) const { 150 return canCopyLinear(buffer); 151} 152 153bool LinearBlockBuffer::copy(const std::shared_ptr<C2Buffer> &buffer) { 154 return copyLinear(buffer); 155} 156 157LinearBlockBuffer::LinearBlockBuffer( 158 const sp<AMessage> &format, 159 C2WriteView&& writeView, 160 const std::shared_ptr<C2LinearBlock> &block) 161 : Codec2Buffer(format, new ABuffer(writeView.data(), writeView.size())), 162 mWriteView(writeView), 163 mBlock(block) { 164} 165 166// ConstLinearBlockBuffer 167 168// static 169sp<ConstLinearBlockBuffer> ConstLinearBlockBuffer::Allocate( 170 const sp<AMessage> &format, const std::shared_ptr<C2Buffer> &buffer) { 171 if (!buffer 172 || buffer->data().type() != C2BufferData::LINEAR 173 || buffer->data().linearBlocks().size() != 1u) { 174 return nullptr; 175 } 176 C2ReadView readView(buffer->data().linearBlocks()[0].map().get()); 177 if (readView.error() != C2_OK) { 178 return nullptr; 179 } 180 return new ConstLinearBlockBuffer(format, std::move(readView), buffer); 181} 182 183ConstLinearBlockBuffer::ConstLinearBlockBuffer( 184 const sp<AMessage> &format, 185 C2ReadView&& readView, 186 const std::shared_ptr<C2Buffer> &buffer) 187 : Codec2Buffer(format, new ABuffer( 188 // NOTE: ABuffer only takes non-const pointer but this data is 189 // supposed to be read-only. 190 const_cast<uint8_t *>(readView.data()), readView.capacity())), 191 mReadView(readView), 192 mBufferRef(buffer) { 193} 194 195std::shared_ptr<C2Buffer> ConstLinearBlockBuffer::asC2Buffer() { 196 return std::move(mBufferRef); 197} 198 199// GraphicView2MediaImageConverter 200 201namespace { 202 203class GraphicView2MediaImageConverter { 204public: 205 /** 206 * Creates a C2GraphicView <=> MediaImage converter 207 * 208 * \param view C2GraphicView object 209 * \param colorFormat desired SDK color format for the MediaImage (if this is a flexible format, 210 * an attempt is made to simply represent the graphic view as a flexible SDK format 211 * without a memcpy) 212 */ 213 GraphicView2MediaImageConverter( 214 const C2GraphicView &view, int32_t colorFormat) 215 : mInitCheck(NO_INIT), 216 mView(view), 217 mWidth(view.width()), 218 mHeight(view.height()), 219 mColorFormat(colorFormat), 220 mAllocatedDepth(0), 221 mBackBufferSize(0), 222 mMediaImage(new ABuffer(sizeof(MediaImage2))) { 223 if (view.error() != C2_OK) { 224 ALOGD("Converter: view.error() = %d", view.error()); 225 mInitCheck = BAD_VALUE; 226 return; 227 } 228 MediaImage2 *mediaImage = (MediaImage2 *)mMediaImage->base(); 229 const C2PlanarLayout &layout = view.layout(); 230 if (layout.numPlanes == 0) { 231 ALOGD("Converter: 0 planes"); 232 mInitCheck = BAD_VALUE; 233 return; 234 } 235 mAllocatedDepth = layout.planes[0].allocatedDepth; 236 uint32_t bitDepth = layout.planes[0].bitDepth; 237 238 // align width and height to support subsampling cleanly 239 uint32_t mStride = align(mWidth, 2) * divUp(layout.planes[0].allocatedDepth, 8u); 240 uint32_t mVStride = align(mHeight, 2); 241 242 switch (layout.type) { 243 case C2PlanarLayout::TYPE_YUV: 244 mediaImage->mType = MediaImage2::MEDIA_IMAGE_TYPE_YUV; 245 if (layout.numPlanes != 3) { 246 ALOGD("Converter: %d planes for YUV layout", layout.numPlanes); 247 mInitCheck = BAD_VALUE; 248 return; 249 } 250 if (layout.planes[0].channel != C2PlaneInfo::CHANNEL_Y 251 || layout.planes[1].channel != C2PlaneInfo::CHANNEL_CB 252 || layout.planes[2].channel != C2PlaneInfo::CHANNEL_CR 253 || layout.planes[0].colSampling != 1 254 || layout.planes[0].rowSampling != 1 255 || layout.planes[1].colSampling != 2 256 || layout.planes[1].rowSampling != 2 257 || layout.planes[2].colSampling != 2 258 || layout.planes[2].rowSampling != 2) { 259 ALOGD("Converter: not YUV420 for YUV layout"); 260 mInitCheck = BAD_VALUE; 261 return; 262 } 263 switch (mColorFormat) { 264 case COLOR_FormatYUV420Flexible: 265 { // try to map directly. check if the planes are near one another 266 const uint8_t *minPtr = mView.data()[0]; 267 const uint8_t *maxPtr = mView.data()[0]; 268 int32_t planeSize = 0; 269 for (uint32_t i = 0; i < layout.numPlanes; ++i) { 270 const C2PlaneInfo &plane = layout.planes[i]; 271 ssize_t minOffset = plane.minOffset(mWidth, mHeight); 272 ssize_t maxOffset = plane.maxOffset(mWidth, mHeight); 273 if (minPtr > mView.data()[i] + minOffset) { 274 minPtr = mView.data()[i] + minOffset; 275 } 276 if (maxPtr < mView.data()[i] + maxOffset) { 277 maxPtr = mView.data()[i] + maxOffset; 278 } 279 planeSize += std::abs(plane.rowInc) * align(mHeight, 64) 280 / plane.rowSampling / plane.colSampling * divUp(mAllocatedDepth, 8u); 281 } 282 283 if ((maxPtr - minPtr + 1) <= planeSize) { 284 // FIXME: this is risky as reading/writing data out of bound results in 285 // an undefined behavior, but gralloc does assume a contiguous 286 // mapping 287 for (uint32_t i = 0; i < layout.numPlanes; ++i) { 288 const C2PlaneInfo &plane = layout.planes[i]; 289 mediaImage->mPlane[i].mOffset = mView.data()[i] - minPtr; 290 mediaImage->mPlane[i].mColInc = plane.colInc; 291 mediaImage->mPlane[i].mRowInc = plane.rowInc; 292 mediaImage->mPlane[i].mHorizSubsampling = plane.colSampling; 293 mediaImage->mPlane[i].mVertSubsampling = plane.rowSampling; 294 } 295 mWrapped = new ABuffer(const_cast<uint8_t *>(minPtr), maxPtr - minPtr + 1); 296 break; 297 } 298 } 299 // fall through if we could not wrap 300 301 case COLOR_FormatYUV420Planar: 302 case COLOR_FormatYUV420PackedPlanar: 303 mediaImage->mPlane[mediaImage->Y].mOffset = 0; 304 mediaImage->mPlane[mediaImage->Y].mColInc = 1; 305 mediaImage->mPlane[mediaImage->Y].mRowInc = mStride; 306 mediaImage->mPlane[mediaImage->Y].mHorizSubsampling = 1; 307 mediaImage->mPlane[mediaImage->Y].mVertSubsampling = 1; 308 309 mediaImage->mPlane[mediaImage->U].mOffset = mStride * mVStride; 310 mediaImage->mPlane[mediaImage->U].mColInc = 1; 311 mediaImage->mPlane[mediaImage->U].mRowInc = mStride / 2; 312 mediaImage->mPlane[mediaImage->U].mHorizSubsampling = 2; 313 mediaImage->mPlane[mediaImage->U].mVertSubsampling = 2; 314 315 mediaImage->mPlane[mediaImage->V].mOffset = mStride * mVStride * 5 / 4; 316 mediaImage->mPlane[mediaImage->V].mColInc = 1; 317 mediaImage->mPlane[mediaImage->V].mRowInc = mStride / 2; 318 mediaImage->mPlane[mediaImage->V].mHorizSubsampling = 2; 319 mediaImage->mPlane[mediaImage->V].mVertSubsampling = 2; 320 break; 321 322 case COLOR_FormatYUV420SemiPlanar: 323 case COLOR_FormatYUV420PackedSemiPlanar: 324 mediaImage->mPlane[mediaImage->Y].mOffset = 0; 325 mediaImage->mPlane[mediaImage->Y].mColInc = 1; 326 mediaImage->mPlane[mediaImage->Y].mRowInc = mStride; 327 mediaImage->mPlane[mediaImage->Y].mHorizSubsampling = 1; 328 mediaImage->mPlane[mediaImage->Y].mVertSubsampling = 1; 329 330 mediaImage->mPlane[mediaImage->U].mOffset = mStride * mVStride; 331 mediaImage->mPlane[mediaImage->U].mColInc = 2; 332 mediaImage->mPlane[mediaImage->U].mRowInc = mStride; 333 mediaImage->mPlane[mediaImage->U].mHorizSubsampling = 2; 334 mediaImage->mPlane[mediaImage->U].mVertSubsampling = 2; 335 336 mediaImage->mPlane[mediaImage->V].mOffset = mStride * mVStride + 1; 337 mediaImage->mPlane[mediaImage->V].mColInc = 2; 338 mediaImage->mPlane[mediaImage->V].mRowInc = mStride; 339 mediaImage->mPlane[mediaImage->V].mHorizSubsampling = 2; 340 mediaImage->mPlane[mediaImage->V].mVertSubsampling = 2; 341 break; 342 343 default: 344 ALOGD("Converter: incompactible color format (%d) for YUV layout", mColorFormat); 345 mInitCheck = BAD_VALUE; 346 return; 347 } 348 break; 349 case C2PlanarLayout::TYPE_YUVA: 350 mediaImage->mType = MediaImage2::MEDIA_IMAGE_TYPE_YUVA; 351 // We don't have an SDK YUVA format 352 ALOGD("Converter: incompactible color format (%d) for YUVA layout", mColorFormat); 353 mInitCheck = BAD_VALUE; 354 return; 355 case C2PlanarLayout::TYPE_RGB: 356 mediaImage->mType = MediaImage2::MEDIA_IMAGE_TYPE_RGB; 357 switch (mColorFormat) { 358 // TODO media image 359 case COLOR_FormatRGBFlexible: 360 case COLOR_Format24bitBGR888: 361 case COLOR_Format24bitRGB888: 362 break; 363 default: 364 ALOGD("Converter: incompactible color format (%d) for RGB layout", mColorFormat); 365 mInitCheck = BAD_VALUE; 366 return; 367 } 368 if (layout.numPlanes != 3) { 369 ALOGD("Converter: %d planes for RGB layout", layout.numPlanes); 370 mInitCheck = BAD_VALUE; 371 return; 372 } 373 break; 374 case C2PlanarLayout::TYPE_RGBA: 375 mediaImage->mType = MediaImage2::MEDIA_IMAGE_TYPE_RGBA; 376 switch (mColorFormat) { 377 // TODO media image 378 case COLOR_FormatRGBAFlexible: 379 case COLOR_Format32bitABGR8888: 380 case COLOR_Format32bitARGB8888: 381 case COLOR_Format32bitBGRA8888: 382 break; 383 default: 384 ALOGD("Incompactible color format (%d) for RGBA layout", mColorFormat); 385 mInitCheck = BAD_VALUE; 386 return; 387 } 388 if (layout.numPlanes != 4) { 389 ALOGD("Converter: %d planes for RGBA layout", layout.numPlanes); 390 mInitCheck = BAD_VALUE; 391 return; 392 } 393 break; 394 default: 395 mediaImage->mType = MediaImage2::MEDIA_IMAGE_TYPE_UNKNOWN; 396 ALOGD("Unknown layout"); 397 mInitCheck = BAD_VALUE; 398 return; 399 } 400 mediaImage->mNumPlanes = layout.numPlanes; 401 mediaImage->mWidth = mWidth; 402 mediaImage->mHeight = mHeight; 403 mediaImage->mBitDepth = bitDepth; 404 mediaImage->mBitDepthAllocated = mAllocatedDepth; 405 406 uint32_t bufferSize = 0; 407 for (uint32_t i = 0; i < layout.numPlanes; ++i) { 408 const C2PlaneInfo &plane = layout.planes[i]; 409 if (plane.allocatedDepth < plane.bitDepth 410 || plane.rightShift != plane.allocatedDepth - plane.bitDepth) { 411 ALOGD("rightShift value of %u unsupported", plane.rightShift); 412 mInitCheck = BAD_VALUE; 413 return; 414 } 415 if (plane.allocatedDepth > 8 && plane.endianness != C2PlaneInfo::NATIVE) { 416 ALOGD("endianness value of %u unsupported", plane.endianness); 417 mInitCheck = BAD_VALUE; 418 return; 419 } 420 if (plane.allocatedDepth != mAllocatedDepth || plane.bitDepth != bitDepth) { 421 ALOGV("different allocatedDepth/bitDepth per plane unsupported"); 422 mInitCheck = BAD_VALUE; 423 return; 424 } 425 bufferSize += mStride * mVStride 426 / plane.rowSampling / plane.colSampling; 427 } 428 429 mBackBufferSize = bufferSize; 430 mInitCheck = OK; 431 } 432 433 status_t initCheck() const { return mInitCheck; } 434 435 uint32_t backBufferSize() const { return mBackBufferSize; } 436 437 /** 438 * Wrap C2GraphicView using a MediaImage2. Note that if not wrapped, the content is not mapped 439 * in this function --- the caller should use CopyGraphicView2MediaImage() function to copy the 440 * data into a backing buffer explicitly. 441 * 442 * \return media buffer. This is null if wrapping failed. 443 */ 444 sp<ABuffer> wrap() const { 445 if (mBackBuffer == nullptr) { 446 return mWrapped; 447 } 448 return nullptr; 449 } 450 451 bool setBackBuffer(const sp<ABuffer> &backBuffer) { 452 if (backBuffer->capacity() < mBackBufferSize) { 453 return false; 454 } 455 backBuffer->setRange(0, mBackBufferSize); 456 mBackBuffer = backBuffer; 457 return true; 458 } 459 460 /** 461 * Copy C2GraphicView to MediaImage2. 462 */ 463 status_t copyToMediaImage() { 464 if (mInitCheck != OK) { 465 return mInitCheck; 466 } 467 return ImageCopy(mBackBuffer->base(), getMediaImage(), mView); 468 } 469 470 const sp<ABuffer> &imageData() const { return mMediaImage; } 471 472private: 473 status_t mInitCheck; 474 475 const C2GraphicView mView; 476 uint32_t mWidth; 477 uint32_t mHeight; 478 int32_t mColorFormat; ///< SDK color format for MediaImage 479 sp<ABuffer> mWrapped; ///< wrapped buffer (if we can map C2Buffer to an ABuffer) 480 uint32_t mAllocatedDepth; 481 uint32_t mBackBufferSize; 482 sp<ABuffer> mMediaImage; 483 std::function<sp<ABuffer>(size_t)> mAlloc; 484 485 sp<ABuffer> mBackBuffer; ///< backing buffer if we have to copy C2Buffer <=> ABuffer 486 487 MediaImage2 *getMediaImage() { 488 return (MediaImage2 *)mMediaImage->base(); 489 } 490}; 491 492} // namespace 493 494// GraphicBlockBuffer 495 496// static 497sp<GraphicBlockBuffer> GraphicBlockBuffer::Allocate( 498 const sp<AMessage> &format, 499 const std::shared_ptr<C2GraphicBlock> &block, 500 std::function<sp<ABuffer>(size_t)> alloc) { 501 C2GraphicView view(block->map().get()); 502 if (view.error() != C2_OK) { 503 ALOGD("C2GraphicBlock::map failed: %d", view.error()); 504 return nullptr; 505 } 506 507 int32_t colorFormat = COLOR_FormatYUV420Flexible; 508 (void)format->findInt32("color-format", &colorFormat); 509 510 GraphicView2MediaImageConverter converter(view, colorFormat); 511 if (converter.initCheck() != OK) { 512 ALOGD("Converter init failed: %d", converter.initCheck()); 513 return nullptr; 514 } 515 bool wrapped = true; 516 sp<ABuffer> buffer = converter.wrap(); 517 if (buffer == nullptr) { 518 buffer = alloc(converter.backBufferSize()); 519 if (!converter.setBackBuffer(buffer)) { 520 ALOGD("Converter failed to set back buffer"); 521 return nullptr; 522 } 523 wrapped = false; 524 } 525 return new GraphicBlockBuffer( 526 format, 527 buffer, 528 std::move(view), 529 block, 530 converter.imageData(), 531 wrapped); 532} 533 534GraphicBlockBuffer::GraphicBlockBuffer( 535 const sp<AMessage> &format, 536 const sp<ABuffer> &buffer, 537 C2GraphicView &&view, 538 const std::shared_ptr<C2GraphicBlock> &block, 539 const sp<ABuffer> &imageData, 540 bool wrapped) 541 : Codec2Buffer(format, buffer), 542 mView(view), 543 mBlock(block), 544 mImageData(imageData), 545 mWrapped(wrapped) { 546 setImageData(imageData); 547} 548 549std::shared_ptr<C2Buffer> GraphicBlockBuffer::asC2Buffer() { 550 uint32_t width = mView.width(); 551 uint32_t height = mView.height(); 552 if (!mWrapped) { 553 (void)ImageCopy(mView, base(), imageData()); 554 } 555 return C2Buffer::CreateGraphicBuffer( 556 mBlock->share(C2Rect(width, height), C2Fence())); 557} 558 559// GraphicMetadataBuffer 560GraphicMetadataBuffer::GraphicMetadataBuffer( 561 const sp<AMessage> &format, 562 const std::shared_ptr<C2Allocator> &alloc) 563 : Codec2Buffer(format, new ABuffer(sizeof(VideoNativeMetadata))), 564 mAlloc(alloc) { 565 ((VideoNativeMetadata *)base())->pBuffer = 0; 566} 567 568std::shared_ptr<C2Buffer> GraphicMetadataBuffer::asC2Buffer() { 569#ifndef __LP64__ 570 VideoNativeMetadata *meta = (VideoNativeMetadata *)base(); 571 ANativeWindowBuffer *buffer = (ANativeWindowBuffer *)meta->pBuffer; 572 if (buffer == nullptr) { 573 ALOGD("VideoNativeMetadata contains null buffer"); 574 return nullptr; 575 } 576 577 ALOGV("VideoNativeMetadata: %dx%d", buffer->width, buffer->height); 578 C2Handle *handle = WrapNativeCodec2GrallocHandle( 579 native_handle_clone(buffer->handle), 580 buffer->width, 581 buffer->height, 582 buffer->format, 583 buffer->usage, 584 buffer->stride); 585 std::shared_ptr<C2GraphicAllocation> alloc; 586 c2_status_t err = mAlloc->priorGraphicAllocation(handle, &alloc); 587 if (err != C2_OK) { 588 ALOGD("Failed to wrap VideoNativeMetadata into C2GraphicAllocation"); 589 return nullptr; 590 } 591 std::shared_ptr<C2GraphicBlock> block = _C2BlockFactory::CreateGraphicBlock(alloc); 592 593 meta->pBuffer = 0; 594 // TODO: fence 595 return C2Buffer::CreateGraphicBuffer( 596 block->share(C2Rect(buffer->width, buffer->height), C2Fence())); 597#else 598 ALOGE("GraphicMetadataBuffer does not work on 64-bit arch"); 599 return nullptr; 600#endif 601} 602 603// ConstGraphicBlockBuffer 604 605// static 606sp<ConstGraphicBlockBuffer> ConstGraphicBlockBuffer::Allocate( 607 const sp<AMessage> &format, 608 const std::shared_ptr<C2Buffer> &buffer, 609 std::function<sp<ABuffer>(size_t)> alloc) { 610 if (!buffer 611 || buffer->data().type() != C2BufferData::GRAPHIC 612 || buffer->data().graphicBlocks().size() != 1u) { 613 ALOGD("C2Buffer precond fail"); 614 return nullptr; 615 } 616 std::unique_ptr<const C2GraphicView> view(std::make_unique<const C2GraphicView>( 617 buffer->data().graphicBlocks()[0].map().get())); 618 std::unique_ptr<const C2GraphicView> holder; 619 620 int32_t colorFormat = COLOR_FormatYUV420Flexible; 621 (void)format->findInt32("color-format", &colorFormat); 622 623 GraphicView2MediaImageConverter converter(*view, colorFormat); 624 if (converter.initCheck() != OK) { 625 ALOGD("Converter init failed: %d", converter.initCheck()); 626 return nullptr; 627 } 628 bool wrapped = true; 629 sp<ABuffer> aBuffer = converter.wrap(); 630 if (aBuffer == nullptr) { 631 aBuffer = alloc(converter.backBufferSize()); 632 if (!converter.setBackBuffer(aBuffer)) { 633 ALOGD("Converter failed to set back buffer"); 634 return nullptr; 635 } 636 wrapped = false; 637 converter.copyToMediaImage(); 638 // We don't need the view. 639 holder = std::move(view); 640 } 641 return new ConstGraphicBlockBuffer( 642 format, 643 aBuffer, 644 std::move(view), 645 buffer, 646 converter.imageData(), 647 wrapped); 648} 649 650// static 651sp<ConstGraphicBlockBuffer> ConstGraphicBlockBuffer::AllocateEmpty( 652 const sp<AMessage> &format, 653 std::function<sp<ABuffer>(size_t)> alloc) { 654 int32_t width, height; 655 if (!format->findInt32("width", &width) 656 || !format->findInt32("height", &height)) { 657 ALOGD("format had no width / height"); 658 return nullptr; 659 } 660 sp<ABuffer> aBuffer(alloc(width * height * 4)); 661 return new ConstGraphicBlockBuffer( 662 format, 663 aBuffer, 664 nullptr, 665 nullptr, 666 nullptr, 667 false); 668} 669 670ConstGraphicBlockBuffer::ConstGraphicBlockBuffer( 671 const sp<AMessage> &format, 672 const sp<ABuffer> &aBuffer, 673 std::unique_ptr<const C2GraphicView> &&view, 674 const std::shared_ptr<C2Buffer> &buffer, 675 const sp<ABuffer> &imageData, 676 bool wrapped) 677 : Codec2Buffer(format, aBuffer), 678 mView(std::move(view)), 679 mBufferRef(buffer), 680 mWrapped(wrapped) { 681 if (imageData != nullptr) { 682 setImageData(imageData); 683 } 684} 685 686std::shared_ptr<C2Buffer> ConstGraphicBlockBuffer::asC2Buffer() { 687 mView.reset(); 688 return std::move(mBufferRef); 689} 690 691bool ConstGraphicBlockBuffer::canCopy(const std::shared_ptr<C2Buffer> &buffer) const { 692 if (mWrapped || mBufferRef) { 693 ALOGD("ConstGraphicBlockBuffer::canCopy: %swrapped ; buffer ref %s", 694 mWrapped ? "" : "not ", mBufferRef ? "exists" : "doesn't exist"); 695 return false; 696 } 697 if (!buffer) { 698 // Nothing to copy, so we can copy by doing nothing. 699 return true; 700 } 701 if (buffer->data().type() != C2BufferData::GRAPHIC) { 702 ALOGD("ConstGraphicBlockBuffer::canCopy: buffer precondition unsatisfied"); 703 return false; 704 } 705 if (buffer->data().graphicBlocks().size() == 0) { 706 return true; 707 } else if (buffer->data().graphicBlocks().size() != 1u) { 708 ALOGD("ConstGraphicBlockBuffer::canCopy: too many blocks"); 709 return false; 710 } 711 712 int32_t colorFormat = COLOR_FormatYUV420Flexible; 713 // FIXME: format() is not const, but we cannot change it, so do a const cast here 714 const_cast<ConstGraphicBlockBuffer *>(this)->format()->findInt32("color-format", &colorFormat); 715 716 GraphicView2MediaImageConverter converter( 717 buffer->data().graphicBlocks()[0].map().get(), colorFormat); 718 if (converter.initCheck() != OK) { 719 ALOGD("ConstGraphicBlockBuffer::canCopy: converter init failed: %d", converter.initCheck()); 720 return false; 721 } 722 if (converter.backBufferSize() > capacity()) { 723 ALOGD("ConstGraphicBlockBuffer::canCopy: insufficient capacity: req %u has %zu", 724 converter.backBufferSize(), capacity()); 725 return false; 726 } 727 return true; 728} 729 730bool ConstGraphicBlockBuffer::copy(const std::shared_ptr<C2Buffer> &buffer) { 731 if (!buffer || buffer->data().graphicBlocks().size() == 0) { 732 setRange(0, 0); 733 return true; 734 } 735 int32_t colorFormat = COLOR_FormatYUV420Flexible; 736 format()->findInt32("color-format", &colorFormat); 737 738 GraphicView2MediaImageConverter converter( 739 buffer->data().graphicBlocks()[0].map().get(), colorFormat); 740 if (converter.initCheck() != OK) { 741 ALOGD("ConstGraphicBlockBuffer::copy: converter init failed: %d", converter.initCheck()); 742 return false; 743 } 744 sp<ABuffer> aBuffer = new ABuffer(base(), capacity()); 745 if (!converter.setBackBuffer(aBuffer)) { 746 ALOGD("ConstGraphicBlockBuffer::copy: set back buffer failed"); 747 return false; 748 } 749 converter.copyToMediaImage(); 750 setImageData(converter.imageData()); 751 mBufferRef = buffer; 752 return true; 753} 754 755// EncryptedLinearBlockBuffer 756 757EncryptedLinearBlockBuffer::EncryptedLinearBlockBuffer( 758 const sp<AMessage> &format, 759 const std::shared_ptr<C2LinearBlock> &block, 760 const sp<IMemory> &memory, 761 int32_t heapSeqNum) 762 : Codec2Buffer(format, new ABuffer(memory->pointer(), memory->size())), 763 mBlock(block), 764 mMemory(memory), 765 mHeapSeqNum(heapSeqNum) { 766} 767 768std::shared_ptr<C2Buffer> EncryptedLinearBlockBuffer::asC2Buffer() { 769 return C2Buffer::CreateLinearBuffer(mBlock->share(offset(), size(), C2Fence())); 770} 771 772void EncryptedLinearBlockBuffer::fillSourceBuffer( 773 ICrypto::SourceBuffer *source) { 774 source->mSharedMemory = mMemory; 775 source->mHeapSeqNum = mHeapSeqNum; 776} 777 778void EncryptedLinearBlockBuffer::fillSourceBuffer( 779 hardware::cas::native::V1_0::SharedBuffer *source) { 780 ssize_t offset; 781 size_t size; 782 783 mHidlMemory = hardware::fromHeap(mMemory->getMemory(&offset, &size)); 784 source->heapBase = *mHidlMemory; 785 source->offset = offset; 786 source->size = size; 787} 788 789bool EncryptedLinearBlockBuffer::copyDecryptedContent( 790 const sp<IMemory> &decrypted, size_t length) { 791 C2WriteView view = mBlock->map().get(); 792 if (view.error() != C2_OK) { 793 return false; 794 } 795 if (view.size() < length) { 796 return false; 797 } 798 memcpy(view.data(), decrypted->pointer(), length); 799 return true; 800} 801 802bool EncryptedLinearBlockBuffer::copyDecryptedContentFromMemory(size_t length) { 803 return copyDecryptedContent(mMemory, length); 804} 805 806native_handle_t *EncryptedLinearBlockBuffer::handle() const { 807 return const_cast<native_handle_t *>(mBlock->handle()); 808} 809 810} // namespace android 811