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