Loading media/codec2/sfplugin/Codec2Buffer.cpp +1 −476 Original line number Diff line number Diff line Loading @@ -43,6 +43,7 @@ #include <C2Debug.h> #include "Codec2Buffer.h" #include "Codec2BufferUtils.h" namespace android { Loading Loading @@ -215,482 +216,6 @@ void ConstLinearBlockBuffer::clearC2BufferRefs() { mBufferRef.reset(); } // GraphicView2MediaImageConverter namespace { class GraphicView2MediaImageConverter { public: /** * Creates a C2GraphicView <=> MediaImage converter * * \param view C2GraphicView object * \param format buffer format * \param copy whether the converter is used for copy or not */ GraphicView2MediaImageConverter( const C2GraphicView &view, const sp<AMessage> &format, bool copy) : mInitCheck(NO_INIT), mView(view), mWidth(view.width()), mHeight(view.height()), mAllocatedDepth(0), mBackBufferSize(0), mMediaImage(new ABuffer(sizeof(MediaImage2))) { ATRACE_CALL(); if (!format->findInt32(KEY_COLOR_FORMAT, &mClientColorFormat)) { mClientColorFormat = COLOR_FormatYUV420Flexible; } if (!format->findInt32("android._color-format", &mComponentColorFormat)) { mComponentColorFormat = COLOR_FormatYUV420Flexible; } if (view.error() != C2_OK) { ALOGD("Converter: view.error() = %d", view.error()); mInitCheck = BAD_VALUE; return; } MediaImage2 *mediaImage = (MediaImage2 *)mMediaImage->base(); const C2PlanarLayout &layout = view.layout(); if (layout.numPlanes == 0) { ALOGD("Converter: 0 planes"); mInitCheck = BAD_VALUE; return; } memset(mediaImage, 0, sizeof(*mediaImage)); mAllocatedDepth = layout.planes[0].allocatedDepth; uint32_t bitDepth = layout.planes[0].bitDepth; // align width and height to support subsampling cleanly uint32_t stride = align(view.crop().width, 2) * divUp(layout.planes[0].allocatedDepth, 8u); uint32_t vStride = align(view.crop().height, 2); bool tryWrapping = !copy; switch (layout.type) { case C2PlanarLayout::TYPE_YUV: { mediaImage->mType = MediaImage2::MEDIA_IMAGE_TYPE_YUV; if (layout.numPlanes != 3) { ALOGD("Converter: %d planes for YUV layout", layout.numPlanes); mInitCheck = BAD_VALUE; return; } std::optional<int> clientBitDepth = {}; switch (mClientColorFormat) { case COLOR_FormatYUVP010: clientBitDepth = 10; break; case COLOR_FormatYUV411PackedPlanar: case COLOR_FormatYUV411Planar: case COLOR_FormatYUV420Flexible: case COLOR_FormatYUV420PackedPlanar: case COLOR_FormatYUV420PackedSemiPlanar: case COLOR_FormatYUV420Planar: case COLOR_FormatYUV420SemiPlanar: case COLOR_FormatYUV422Flexible: case COLOR_FormatYUV422PackedPlanar: case COLOR_FormatYUV422PackedSemiPlanar: case COLOR_FormatYUV422Planar: case COLOR_FormatYUV422SemiPlanar: case COLOR_FormatYUV444Flexible: case COLOR_FormatYUV444Interleaved: clientBitDepth = 8; break; default: // no-op; used with optional break; } // conversion fails if client bit-depth and the component bit-depth differs if ((clientBitDepth) && (bitDepth != clientBitDepth.value())) { ALOGD("Bit depth of client: %d and component: %d differs", *clientBitDepth, bitDepth); mInitCheck = BAD_VALUE; return; } C2PlaneInfo yPlane = layout.planes[C2PlanarLayout::PLANE_Y]; C2PlaneInfo uPlane = layout.planes[C2PlanarLayout::PLANE_U]; C2PlaneInfo vPlane = layout.planes[C2PlanarLayout::PLANE_V]; if (yPlane.channel != C2PlaneInfo::CHANNEL_Y || uPlane.channel != C2PlaneInfo::CHANNEL_CB || vPlane.channel != C2PlaneInfo::CHANNEL_CR) { ALOGD("Converter: not YUV layout"); mInitCheck = BAD_VALUE; return; } bool yuv420888 = yPlane.rowSampling == 1 && yPlane.colSampling == 1 && uPlane.rowSampling == 2 && uPlane.colSampling == 2 && vPlane.rowSampling == 2 && vPlane.colSampling == 2; if (yuv420888) { for (uint32_t i = 0; i < 3; ++i) { const C2PlaneInfo &plane = layout.planes[i]; if (plane.allocatedDepth != 8 || plane.bitDepth != 8) { yuv420888 = false; break; } } yuv420888 = yuv420888 && yPlane.colInc == 1 && uPlane.rowInc == vPlane.rowInc; } int32_t copyFormat = mClientColorFormat; if (yuv420888 && mClientColorFormat == COLOR_FormatYUV420Flexible) { if (uPlane.colInc == 2 && vPlane.colInc == 2 && yPlane.rowInc == uPlane.rowInc) { copyFormat = COLOR_FormatYUV420PackedSemiPlanar; } else if (uPlane.colInc == 1 && vPlane.colInc == 1 && yPlane.rowInc == uPlane.rowInc * 2) { copyFormat = COLOR_FormatYUV420PackedPlanar; } } ALOGV("client_fmt=0x%x y:{colInc=%d rowInc=%d} u:{colInc=%d rowInc=%d} " "v:{colInc=%d rowInc=%d}", mClientColorFormat, yPlane.colInc, yPlane.rowInc, uPlane.colInc, uPlane.rowInc, vPlane.colInc, vPlane.rowInc); switch (copyFormat) { case COLOR_FormatYUV420Flexible: case COLOR_FormatYUV420Planar: case COLOR_FormatYUV420PackedPlanar: mediaImage->mPlane[mediaImage->Y].mOffset = 0; mediaImage->mPlane[mediaImage->Y].mColInc = 1; mediaImage->mPlane[mediaImage->Y].mRowInc = stride; mediaImage->mPlane[mediaImage->Y].mHorizSubsampling = 1; mediaImage->mPlane[mediaImage->Y].mVertSubsampling = 1; mediaImage->mPlane[mediaImage->U].mOffset = stride * vStride; mediaImage->mPlane[mediaImage->U].mColInc = 1; mediaImage->mPlane[mediaImage->U].mRowInc = stride / 2; mediaImage->mPlane[mediaImage->U].mHorizSubsampling = 2; mediaImage->mPlane[mediaImage->U].mVertSubsampling = 2; mediaImage->mPlane[mediaImage->V].mOffset = stride * vStride * 5 / 4; mediaImage->mPlane[mediaImage->V].mColInc = 1; mediaImage->mPlane[mediaImage->V].mRowInc = stride / 2; mediaImage->mPlane[mediaImage->V].mHorizSubsampling = 2; mediaImage->mPlane[mediaImage->V].mVertSubsampling = 2; if (tryWrapping && mClientColorFormat != COLOR_FormatYUV420Flexible) { tryWrapping = yuv420888 && uPlane.colInc == 1 && vPlane.colInc == 1 && yPlane.rowInc == uPlane.rowInc * 2 && view.data()[0] < view.data()[1] && view.data()[1] < view.data()[2]; } break; case COLOR_FormatYUV420SemiPlanar: case COLOR_FormatYUV420PackedSemiPlanar: mediaImage->mPlane[mediaImage->Y].mOffset = 0; mediaImage->mPlane[mediaImage->Y].mColInc = 1; mediaImage->mPlane[mediaImage->Y].mRowInc = stride; mediaImage->mPlane[mediaImage->Y].mHorizSubsampling = 1; mediaImage->mPlane[mediaImage->Y].mVertSubsampling = 1; mediaImage->mPlane[mediaImage->U].mOffset = stride * vStride; mediaImage->mPlane[mediaImage->U].mColInc = 2; mediaImage->mPlane[mediaImage->U].mRowInc = stride; mediaImage->mPlane[mediaImage->U].mHorizSubsampling = 2; mediaImage->mPlane[mediaImage->U].mVertSubsampling = 2; mediaImage->mPlane[mediaImage->V].mOffset = stride * vStride + 1; mediaImage->mPlane[mediaImage->V].mColInc = 2; mediaImage->mPlane[mediaImage->V].mRowInc = stride; mediaImage->mPlane[mediaImage->V].mHorizSubsampling = 2; mediaImage->mPlane[mediaImage->V].mVertSubsampling = 2; if (tryWrapping && mClientColorFormat != COLOR_FormatYUV420Flexible) { tryWrapping = yuv420888 && uPlane.colInc == 2 && vPlane.colInc == 2 && yPlane.rowInc == uPlane.rowInc && view.data()[0] < view.data()[1] && view.data()[1] < view.data()[2]; } break; case COLOR_FormatYUVP010: // stride is in bytes mediaImage->mPlane[mediaImage->Y].mOffset = 0; mediaImage->mPlane[mediaImage->Y].mColInc = 2; mediaImage->mPlane[mediaImage->Y].mRowInc = stride; mediaImage->mPlane[mediaImage->Y].mHorizSubsampling = 1; mediaImage->mPlane[mediaImage->Y].mVertSubsampling = 1; mediaImage->mPlane[mediaImage->U].mOffset = stride * vStride; mediaImage->mPlane[mediaImage->U].mColInc = 4; mediaImage->mPlane[mediaImage->U].mRowInc = stride; mediaImage->mPlane[mediaImage->U].mHorizSubsampling = 2; mediaImage->mPlane[mediaImage->U].mVertSubsampling = 2; mediaImage->mPlane[mediaImage->V].mOffset = stride * vStride + 2; mediaImage->mPlane[mediaImage->V].mColInc = 4; mediaImage->mPlane[mediaImage->V].mRowInc = stride; mediaImage->mPlane[mediaImage->V].mHorizSubsampling = 2; mediaImage->mPlane[mediaImage->V].mVertSubsampling = 2; if (tryWrapping) { tryWrapping = yPlane.allocatedDepth == 16 && uPlane.allocatedDepth == 16 && vPlane.allocatedDepth == 16 && yPlane.bitDepth == 10 && uPlane.bitDepth == 10 && vPlane.bitDepth == 10 && yPlane.rightShift == 6 && uPlane.rightShift == 6 && vPlane.rightShift == 6 && yPlane.rowSampling == 1 && yPlane.colSampling == 1 && uPlane.rowSampling == 2 && uPlane.colSampling == 2 && vPlane.rowSampling == 2 && vPlane.colSampling == 2 && yPlane.colInc == 2 && uPlane.colInc == 4 && vPlane.colInc == 4 && yPlane.rowInc == uPlane.rowInc && yPlane.rowInc == vPlane.rowInc; } break; default: { // default to fully planar format --- this will be overridden if wrapping // TODO: keep interleaved format int32_t colInc = divUp(mAllocatedDepth, 8u); int32_t rowInc = stride * colInc / yPlane.colSampling; mediaImage->mPlane[mediaImage->Y].mOffset = 0; mediaImage->mPlane[mediaImage->Y].mColInc = colInc; mediaImage->mPlane[mediaImage->Y].mRowInc = rowInc; mediaImage->mPlane[mediaImage->Y].mHorizSubsampling = yPlane.colSampling; mediaImage->mPlane[mediaImage->Y].mVertSubsampling = yPlane.rowSampling; int32_t offset = rowInc * vStride / yPlane.rowSampling; rowInc = stride * colInc / uPlane.colSampling; mediaImage->mPlane[mediaImage->U].mOffset = offset; mediaImage->mPlane[mediaImage->U].mColInc = colInc; mediaImage->mPlane[mediaImage->U].mRowInc = rowInc; mediaImage->mPlane[mediaImage->U].mHorizSubsampling = uPlane.colSampling; mediaImage->mPlane[mediaImage->U].mVertSubsampling = uPlane.rowSampling; offset += rowInc * vStride / uPlane.rowSampling; rowInc = stride * colInc / vPlane.colSampling; mediaImage->mPlane[mediaImage->V].mOffset = offset; mediaImage->mPlane[mediaImage->V].mColInc = colInc; mediaImage->mPlane[mediaImage->V].mRowInc = rowInc; mediaImage->mPlane[mediaImage->V].mHorizSubsampling = vPlane.colSampling; mediaImage->mPlane[mediaImage->V].mVertSubsampling = vPlane.rowSampling; break; } } break; } case C2PlanarLayout::TYPE_YUVA: ALOGD("Converter: unrecognized color format " "(client %d component %d) for YUVA layout", mClientColorFormat, mComponentColorFormat); mInitCheck = NO_INIT; return; case C2PlanarLayout::TYPE_RGB: mediaImage->mType = MediaImage2::MEDIA_IMAGE_TYPE_RGB; // TODO: support MediaImage layout switch (mClientColorFormat) { case COLOR_FormatSurface: case COLOR_FormatRGBFlexible: case COLOR_Format24bitBGR888: case COLOR_Format24bitRGB888: ALOGD("Converter: accept color format " "(client %d component %d) for RGB layout", mClientColorFormat, mComponentColorFormat); break; default: ALOGD("Converter: unrecognized color format " "(client %d component %d) for RGB layout", mClientColorFormat, mComponentColorFormat); mInitCheck = BAD_VALUE; return; } if (layout.numPlanes != 3) { ALOGD("Converter: %d planes for RGB layout", layout.numPlanes); mInitCheck = BAD_VALUE; return; } break; case C2PlanarLayout::TYPE_RGBA: mediaImage->mType = MediaImage2::MEDIA_IMAGE_TYPE_RGBA; // TODO: support MediaImage layout switch (mClientColorFormat) { case COLOR_FormatSurface: case COLOR_FormatRGBAFlexible: case COLOR_Format32bitABGR8888: case COLOR_Format32bitARGB8888: case COLOR_Format32bitBGRA8888: ALOGD("Converter: accept color format " "(client %d component %d) for RGBA layout", mClientColorFormat, mComponentColorFormat); break; default: ALOGD("Converter: unrecognized color format " "(client %d component %d) for RGBA layout", mClientColorFormat, mComponentColorFormat); mInitCheck = BAD_VALUE; return; } if (layout.numPlanes != 4) { ALOGD("Converter: %d planes for RGBA layout", layout.numPlanes); mInitCheck = BAD_VALUE; return; } break; default: mediaImage->mType = MediaImage2::MEDIA_IMAGE_TYPE_UNKNOWN; if (layout.numPlanes == 1) { const C2PlaneInfo &plane = layout.planes[0]; if (plane.colInc < 0 || plane.rowInc < 0) { // Copy-only if we have negative colInc/rowInc tryWrapping = false; } mediaImage->mPlane[0].mOffset = 0; mediaImage->mPlane[0].mColInc = std::abs(plane.colInc); mediaImage->mPlane[0].mRowInc = std::abs(plane.rowInc); mediaImage->mPlane[0].mHorizSubsampling = plane.colSampling; mediaImage->mPlane[0].mVertSubsampling = plane.rowSampling; } else { ALOGD("Converter: unrecognized layout: color format (client %d component %d)", mClientColorFormat, mComponentColorFormat); mInitCheck = NO_INIT; return; } break; } if (tryWrapping) { // try to map directly. check if the planes are near one another const uint8_t *minPtr = mView.data()[0]; const uint8_t *maxPtr = mView.data()[0]; int32_t planeSize = 0; for (uint32_t i = 0; i < layout.numPlanes; ++i) { const C2PlaneInfo &plane = layout.planes[i]; int64_t planeStride = std::abs(plane.rowInc / plane.colInc); ssize_t minOffset = plane.minOffset( mWidth / plane.colSampling, mHeight / plane.rowSampling); ssize_t maxOffset = plane.maxOffset( mWidth / plane.colSampling, mHeight / plane.rowSampling); if (minPtr > mView.data()[i] + minOffset) { minPtr = mView.data()[i] + minOffset; } if (maxPtr < mView.data()[i] + maxOffset) { maxPtr = mView.data()[i] + maxOffset; } planeSize += planeStride * divUp(mAllocatedDepth, 8u) * align(mHeight, 64) / plane.rowSampling; } if (minPtr == mView.data()[0] && (maxPtr - minPtr) <= planeSize) { // FIXME: this is risky as reading/writing data out of bound results // in an undefined behavior, but gralloc does assume a // contiguous mapping for (uint32_t i = 0; i < layout.numPlanes; ++i) { const C2PlaneInfo &plane = layout.planes[i]; mediaImage->mPlane[i].mOffset = mView.data()[i] - minPtr; mediaImage->mPlane[i].mColInc = plane.colInc; mediaImage->mPlane[i].mRowInc = plane.rowInc; mediaImage->mPlane[i].mHorizSubsampling = plane.colSampling; mediaImage->mPlane[i].mVertSubsampling = plane.rowSampling; } mWrapped = new ABuffer(const_cast<uint8_t *>(minPtr), maxPtr - minPtr); ALOGV("Converter: wrapped (capacity=%zu)", mWrapped->capacity()); } } mediaImage->mNumPlanes = layout.numPlanes; mediaImage->mWidth = view.crop().width; mediaImage->mHeight = view.crop().height; mediaImage->mBitDepth = bitDepth; mediaImage->mBitDepthAllocated = mAllocatedDepth; uint32_t bufferSize = 0; for (uint32_t i = 0; i < layout.numPlanes; ++i) { const C2PlaneInfo &plane = layout.planes[i]; if (plane.allocatedDepth < plane.bitDepth || plane.rightShift != plane.allocatedDepth - plane.bitDepth) { ALOGD("rightShift value of %u unsupported", plane.rightShift); mInitCheck = BAD_VALUE; return; } if (plane.allocatedDepth > 8 && plane.endianness != C2PlaneInfo::NATIVE) { ALOGD("endianness value of %u unsupported", plane.endianness); mInitCheck = BAD_VALUE; return; } if (plane.allocatedDepth != mAllocatedDepth || plane.bitDepth != bitDepth) { ALOGD("different allocatedDepth/bitDepth per plane unsupported"); mInitCheck = BAD_VALUE; return; } // stride is in bytes bufferSize += stride * vStride / plane.rowSampling / plane.colSampling; } mBackBufferSize = bufferSize; mInitCheck = OK; } status_t initCheck() const { return mInitCheck; } uint32_t backBufferSize() const { return mBackBufferSize; } /** * Wrap C2GraphicView using a MediaImage2. Note that if not wrapped, the content is not mapped * in this function --- the caller should use CopyGraphicView2MediaImage() function to copy the * data into a backing buffer explicitly. * * \return media buffer. This is null if wrapping failed. */ sp<ABuffer> wrap() const { if (mBackBuffer == nullptr) { return mWrapped; } return nullptr; } bool setBackBuffer(const sp<ABuffer> &backBuffer) { if (backBuffer == nullptr) { return false; } if (backBuffer->capacity() < mBackBufferSize) { return false; } backBuffer->setRange(0, mBackBufferSize); mBackBuffer = backBuffer; return true; } /** * Copy C2GraphicView to MediaImage2. */ status_t copyToMediaImage() { ATRACE_CALL(); if (mInitCheck != OK) { return mInitCheck; } return ImageCopy(mBackBuffer->base(), getMediaImage(), mView); } const sp<ABuffer> &imageData() const { return mMediaImage; } private: status_t mInitCheck; const C2GraphicView mView; uint32_t mWidth; uint32_t mHeight; int32_t mClientColorFormat; ///< SDK color format for MediaImage int32_t mComponentColorFormat; ///< SDK color format from component sp<ABuffer> mWrapped; ///< wrapped buffer (if we can map C2Buffer to an ABuffer) uint32_t mAllocatedDepth; uint32_t mBackBufferSize; sp<ABuffer> mMediaImage; std::function<sp<ABuffer>(size_t)> mAlloc; sp<ABuffer> mBackBuffer; ///< backing buffer if we have to copy C2Buffer <=> ABuffer MediaImage2 *getMediaImage() { return (MediaImage2 *)mMediaImage->base(); } }; } // namespace // GraphicBlockBuffer // static Loading media/codec2/sfplugin/Codec2Buffer.h +0 −22 Original line number Diff line number Diff line Loading @@ -44,28 +44,6 @@ struct SharedBuffer; } // namespace drm } // namespace hardware /** * Copies a graphic view into a media image. * * \param imgBase base of MediaImage * \param img MediaImage data * \param view graphic view * * \return OK on success */ status_t ImageCopy(uint8_t *imgBase, const MediaImage2 *img, const C2GraphicView &view); /** * Copies a media image into a graphic view. * * \param view graphic view * \param imgBase base of MediaImage * \param img MediaImage data * * \return OK on success */ status_t ImageCopy(C2GraphicView &view, const uint8_t *imgBase, const MediaImage2 *img); class Codec2Buffer : public MediaCodecBuffer { public: using MediaCodecBuffer::MediaCodecBuffer; Loading Loading
media/codec2/sfplugin/Codec2Buffer.cpp +1 −476 Original line number Diff line number Diff line Loading @@ -43,6 +43,7 @@ #include <C2Debug.h> #include "Codec2Buffer.h" #include "Codec2BufferUtils.h" namespace android { Loading Loading @@ -215,482 +216,6 @@ void ConstLinearBlockBuffer::clearC2BufferRefs() { mBufferRef.reset(); } // GraphicView2MediaImageConverter namespace { class GraphicView2MediaImageConverter { public: /** * Creates a C2GraphicView <=> MediaImage converter * * \param view C2GraphicView object * \param format buffer format * \param copy whether the converter is used for copy or not */ GraphicView2MediaImageConverter( const C2GraphicView &view, const sp<AMessage> &format, bool copy) : mInitCheck(NO_INIT), mView(view), mWidth(view.width()), mHeight(view.height()), mAllocatedDepth(0), mBackBufferSize(0), mMediaImage(new ABuffer(sizeof(MediaImage2))) { ATRACE_CALL(); if (!format->findInt32(KEY_COLOR_FORMAT, &mClientColorFormat)) { mClientColorFormat = COLOR_FormatYUV420Flexible; } if (!format->findInt32("android._color-format", &mComponentColorFormat)) { mComponentColorFormat = COLOR_FormatYUV420Flexible; } if (view.error() != C2_OK) { ALOGD("Converter: view.error() = %d", view.error()); mInitCheck = BAD_VALUE; return; } MediaImage2 *mediaImage = (MediaImage2 *)mMediaImage->base(); const C2PlanarLayout &layout = view.layout(); if (layout.numPlanes == 0) { ALOGD("Converter: 0 planes"); mInitCheck = BAD_VALUE; return; } memset(mediaImage, 0, sizeof(*mediaImage)); mAllocatedDepth = layout.planes[0].allocatedDepth; uint32_t bitDepth = layout.planes[0].bitDepth; // align width and height to support subsampling cleanly uint32_t stride = align(view.crop().width, 2) * divUp(layout.planes[0].allocatedDepth, 8u); uint32_t vStride = align(view.crop().height, 2); bool tryWrapping = !copy; switch (layout.type) { case C2PlanarLayout::TYPE_YUV: { mediaImage->mType = MediaImage2::MEDIA_IMAGE_TYPE_YUV; if (layout.numPlanes != 3) { ALOGD("Converter: %d planes for YUV layout", layout.numPlanes); mInitCheck = BAD_VALUE; return; } std::optional<int> clientBitDepth = {}; switch (mClientColorFormat) { case COLOR_FormatYUVP010: clientBitDepth = 10; break; case COLOR_FormatYUV411PackedPlanar: case COLOR_FormatYUV411Planar: case COLOR_FormatYUV420Flexible: case COLOR_FormatYUV420PackedPlanar: case COLOR_FormatYUV420PackedSemiPlanar: case COLOR_FormatYUV420Planar: case COLOR_FormatYUV420SemiPlanar: case COLOR_FormatYUV422Flexible: case COLOR_FormatYUV422PackedPlanar: case COLOR_FormatYUV422PackedSemiPlanar: case COLOR_FormatYUV422Planar: case COLOR_FormatYUV422SemiPlanar: case COLOR_FormatYUV444Flexible: case COLOR_FormatYUV444Interleaved: clientBitDepth = 8; break; default: // no-op; used with optional break; } // conversion fails if client bit-depth and the component bit-depth differs if ((clientBitDepth) && (bitDepth != clientBitDepth.value())) { ALOGD("Bit depth of client: %d and component: %d differs", *clientBitDepth, bitDepth); mInitCheck = BAD_VALUE; return; } C2PlaneInfo yPlane = layout.planes[C2PlanarLayout::PLANE_Y]; C2PlaneInfo uPlane = layout.planes[C2PlanarLayout::PLANE_U]; C2PlaneInfo vPlane = layout.planes[C2PlanarLayout::PLANE_V]; if (yPlane.channel != C2PlaneInfo::CHANNEL_Y || uPlane.channel != C2PlaneInfo::CHANNEL_CB || vPlane.channel != C2PlaneInfo::CHANNEL_CR) { ALOGD("Converter: not YUV layout"); mInitCheck = BAD_VALUE; return; } bool yuv420888 = yPlane.rowSampling == 1 && yPlane.colSampling == 1 && uPlane.rowSampling == 2 && uPlane.colSampling == 2 && vPlane.rowSampling == 2 && vPlane.colSampling == 2; if (yuv420888) { for (uint32_t i = 0; i < 3; ++i) { const C2PlaneInfo &plane = layout.planes[i]; if (plane.allocatedDepth != 8 || plane.bitDepth != 8) { yuv420888 = false; break; } } yuv420888 = yuv420888 && yPlane.colInc == 1 && uPlane.rowInc == vPlane.rowInc; } int32_t copyFormat = mClientColorFormat; if (yuv420888 && mClientColorFormat == COLOR_FormatYUV420Flexible) { if (uPlane.colInc == 2 && vPlane.colInc == 2 && yPlane.rowInc == uPlane.rowInc) { copyFormat = COLOR_FormatYUV420PackedSemiPlanar; } else if (uPlane.colInc == 1 && vPlane.colInc == 1 && yPlane.rowInc == uPlane.rowInc * 2) { copyFormat = COLOR_FormatYUV420PackedPlanar; } } ALOGV("client_fmt=0x%x y:{colInc=%d rowInc=%d} u:{colInc=%d rowInc=%d} " "v:{colInc=%d rowInc=%d}", mClientColorFormat, yPlane.colInc, yPlane.rowInc, uPlane.colInc, uPlane.rowInc, vPlane.colInc, vPlane.rowInc); switch (copyFormat) { case COLOR_FormatYUV420Flexible: case COLOR_FormatYUV420Planar: case COLOR_FormatYUV420PackedPlanar: mediaImage->mPlane[mediaImage->Y].mOffset = 0; mediaImage->mPlane[mediaImage->Y].mColInc = 1; mediaImage->mPlane[mediaImage->Y].mRowInc = stride; mediaImage->mPlane[mediaImage->Y].mHorizSubsampling = 1; mediaImage->mPlane[mediaImage->Y].mVertSubsampling = 1; mediaImage->mPlane[mediaImage->U].mOffset = stride * vStride; mediaImage->mPlane[mediaImage->U].mColInc = 1; mediaImage->mPlane[mediaImage->U].mRowInc = stride / 2; mediaImage->mPlane[mediaImage->U].mHorizSubsampling = 2; mediaImage->mPlane[mediaImage->U].mVertSubsampling = 2; mediaImage->mPlane[mediaImage->V].mOffset = stride * vStride * 5 / 4; mediaImage->mPlane[mediaImage->V].mColInc = 1; mediaImage->mPlane[mediaImage->V].mRowInc = stride / 2; mediaImage->mPlane[mediaImage->V].mHorizSubsampling = 2; mediaImage->mPlane[mediaImage->V].mVertSubsampling = 2; if (tryWrapping && mClientColorFormat != COLOR_FormatYUV420Flexible) { tryWrapping = yuv420888 && uPlane.colInc == 1 && vPlane.colInc == 1 && yPlane.rowInc == uPlane.rowInc * 2 && view.data()[0] < view.data()[1] && view.data()[1] < view.data()[2]; } break; case COLOR_FormatYUV420SemiPlanar: case COLOR_FormatYUV420PackedSemiPlanar: mediaImage->mPlane[mediaImage->Y].mOffset = 0; mediaImage->mPlane[mediaImage->Y].mColInc = 1; mediaImage->mPlane[mediaImage->Y].mRowInc = stride; mediaImage->mPlane[mediaImage->Y].mHorizSubsampling = 1; mediaImage->mPlane[mediaImage->Y].mVertSubsampling = 1; mediaImage->mPlane[mediaImage->U].mOffset = stride * vStride; mediaImage->mPlane[mediaImage->U].mColInc = 2; mediaImage->mPlane[mediaImage->U].mRowInc = stride; mediaImage->mPlane[mediaImage->U].mHorizSubsampling = 2; mediaImage->mPlane[mediaImage->U].mVertSubsampling = 2; mediaImage->mPlane[mediaImage->V].mOffset = stride * vStride + 1; mediaImage->mPlane[mediaImage->V].mColInc = 2; mediaImage->mPlane[mediaImage->V].mRowInc = stride; mediaImage->mPlane[mediaImage->V].mHorizSubsampling = 2; mediaImage->mPlane[mediaImage->V].mVertSubsampling = 2; if (tryWrapping && mClientColorFormat != COLOR_FormatYUV420Flexible) { tryWrapping = yuv420888 && uPlane.colInc == 2 && vPlane.colInc == 2 && yPlane.rowInc == uPlane.rowInc && view.data()[0] < view.data()[1] && view.data()[1] < view.data()[2]; } break; case COLOR_FormatYUVP010: // stride is in bytes mediaImage->mPlane[mediaImage->Y].mOffset = 0; mediaImage->mPlane[mediaImage->Y].mColInc = 2; mediaImage->mPlane[mediaImage->Y].mRowInc = stride; mediaImage->mPlane[mediaImage->Y].mHorizSubsampling = 1; mediaImage->mPlane[mediaImage->Y].mVertSubsampling = 1; mediaImage->mPlane[mediaImage->U].mOffset = stride * vStride; mediaImage->mPlane[mediaImage->U].mColInc = 4; mediaImage->mPlane[mediaImage->U].mRowInc = stride; mediaImage->mPlane[mediaImage->U].mHorizSubsampling = 2; mediaImage->mPlane[mediaImage->U].mVertSubsampling = 2; mediaImage->mPlane[mediaImage->V].mOffset = stride * vStride + 2; mediaImage->mPlane[mediaImage->V].mColInc = 4; mediaImage->mPlane[mediaImage->V].mRowInc = stride; mediaImage->mPlane[mediaImage->V].mHorizSubsampling = 2; mediaImage->mPlane[mediaImage->V].mVertSubsampling = 2; if (tryWrapping) { tryWrapping = yPlane.allocatedDepth == 16 && uPlane.allocatedDepth == 16 && vPlane.allocatedDepth == 16 && yPlane.bitDepth == 10 && uPlane.bitDepth == 10 && vPlane.bitDepth == 10 && yPlane.rightShift == 6 && uPlane.rightShift == 6 && vPlane.rightShift == 6 && yPlane.rowSampling == 1 && yPlane.colSampling == 1 && uPlane.rowSampling == 2 && uPlane.colSampling == 2 && vPlane.rowSampling == 2 && vPlane.colSampling == 2 && yPlane.colInc == 2 && uPlane.colInc == 4 && vPlane.colInc == 4 && yPlane.rowInc == uPlane.rowInc && yPlane.rowInc == vPlane.rowInc; } break; default: { // default to fully planar format --- this will be overridden if wrapping // TODO: keep interleaved format int32_t colInc = divUp(mAllocatedDepth, 8u); int32_t rowInc = stride * colInc / yPlane.colSampling; mediaImage->mPlane[mediaImage->Y].mOffset = 0; mediaImage->mPlane[mediaImage->Y].mColInc = colInc; mediaImage->mPlane[mediaImage->Y].mRowInc = rowInc; mediaImage->mPlane[mediaImage->Y].mHorizSubsampling = yPlane.colSampling; mediaImage->mPlane[mediaImage->Y].mVertSubsampling = yPlane.rowSampling; int32_t offset = rowInc * vStride / yPlane.rowSampling; rowInc = stride * colInc / uPlane.colSampling; mediaImage->mPlane[mediaImage->U].mOffset = offset; mediaImage->mPlane[mediaImage->U].mColInc = colInc; mediaImage->mPlane[mediaImage->U].mRowInc = rowInc; mediaImage->mPlane[mediaImage->U].mHorizSubsampling = uPlane.colSampling; mediaImage->mPlane[mediaImage->U].mVertSubsampling = uPlane.rowSampling; offset += rowInc * vStride / uPlane.rowSampling; rowInc = stride * colInc / vPlane.colSampling; mediaImage->mPlane[mediaImage->V].mOffset = offset; mediaImage->mPlane[mediaImage->V].mColInc = colInc; mediaImage->mPlane[mediaImage->V].mRowInc = rowInc; mediaImage->mPlane[mediaImage->V].mHorizSubsampling = vPlane.colSampling; mediaImage->mPlane[mediaImage->V].mVertSubsampling = vPlane.rowSampling; break; } } break; } case C2PlanarLayout::TYPE_YUVA: ALOGD("Converter: unrecognized color format " "(client %d component %d) for YUVA layout", mClientColorFormat, mComponentColorFormat); mInitCheck = NO_INIT; return; case C2PlanarLayout::TYPE_RGB: mediaImage->mType = MediaImage2::MEDIA_IMAGE_TYPE_RGB; // TODO: support MediaImage layout switch (mClientColorFormat) { case COLOR_FormatSurface: case COLOR_FormatRGBFlexible: case COLOR_Format24bitBGR888: case COLOR_Format24bitRGB888: ALOGD("Converter: accept color format " "(client %d component %d) for RGB layout", mClientColorFormat, mComponentColorFormat); break; default: ALOGD("Converter: unrecognized color format " "(client %d component %d) for RGB layout", mClientColorFormat, mComponentColorFormat); mInitCheck = BAD_VALUE; return; } if (layout.numPlanes != 3) { ALOGD("Converter: %d planes for RGB layout", layout.numPlanes); mInitCheck = BAD_VALUE; return; } break; case C2PlanarLayout::TYPE_RGBA: mediaImage->mType = MediaImage2::MEDIA_IMAGE_TYPE_RGBA; // TODO: support MediaImage layout switch (mClientColorFormat) { case COLOR_FormatSurface: case COLOR_FormatRGBAFlexible: case COLOR_Format32bitABGR8888: case COLOR_Format32bitARGB8888: case COLOR_Format32bitBGRA8888: ALOGD("Converter: accept color format " "(client %d component %d) for RGBA layout", mClientColorFormat, mComponentColorFormat); break; default: ALOGD("Converter: unrecognized color format " "(client %d component %d) for RGBA layout", mClientColorFormat, mComponentColorFormat); mInitCheck = BAD_VALUE; return; } if (layout.numPlanes != 4) { ALOGD("Converter: %d planes for RGBA layout", layout.numPlanes); mInitCheck = BAD_VALUE; return; } break; default: mediaImage->mType = MediaImage2::MEDIA_IMAGE_TYPE_UNKNOWN; if (layout.numPlanes == 1) { const C2PlaneInfo &plane = layout.planes[0]; if (plane.colInc < 0 || plane.rowInc < 0) { // Copy-only if we have negative colInc/rowInc tryWrapping = false; } mediaImage->mPlane[0].mOffset = 0; mediaImage->mPlane[0].mColInc = std::abs(plane.colInc); mediaImage->mPlane[0].mRowInc = std::abs(plane.rowInc); mediaImage->mPlane[0].mHorizSubsampling = plane.colSampling; mediaImage->mPlane[0].mVertSubsampling = plane.rowSampling; } else { ALOGD("Converter: unrecognized layout: color format (client %d component %d)", mClientColorFormat, mComponentColorFormat); mInitCheck = NO_INIT; return; } break; } if (tryWrapping) { // try to map directly. check if the planes are near one another const uint8_t *minPtr = mView.data()[0]; const uint8_t *maxPtr = mView.data()[0]; int32_t planeSize = 0; for (uint32_t i = 0; i < layout.numPlanes; ++i) { const C2PlaneInfo &plane = layout.planes[i]; int64_t planeStride = std::abs(plane.rowInc / plane.colInc); ssize_t minOffset = plane.minOffset( mWidth / plane.colSampling, mHeight / plane.rowSampling); ssize_t maxOffset = plane.maxOffset( mWidth / plane.colSampling, mHeight / plane.rowSampling); if (minPtr > mView.data()[i] + minOffset) { minPtr = mView.data()[i] + minOffset; } if (maxPtr < mView.data()[i] + maxOffset) { maxPtr = mView.data()[i] + maxOffset; } planeSize += planeStride * divUp(mAllocatedDepth, 8u) * align(mHeight, 64) / plane.rowSampling; } if (minPtr == mView.data()[0] && (maxPtr - minPtr) <= planeSize) { // FIXME: this is risky as reading/writing data out of bound results // in an undefined behavior, but gralloc does assume a // contiguous mapping for (uint32_t i = 0; i < layout.numPlanes; ++i) { const C2PlaneInfo &plane = layout.planes[i]; mediaImage->mPlane[i].mOffset = mView.data()[i] - minPtr; mediaImage->mPlane[i].mColInc = plane.colInc; mediaImage->mPlane[i].mRowInc = plane.rowInc; mediaImage->mPlane[i].mHorizSubsampling = plane.colSampling; mediaImage->mPlane[i].mVertSubsampling = plane.rowSampling; } mWrapped = new ABuffer(const_cast<uint8_t *>(minPtr), maxPtr - minPtr); ALOGV("Converter: wrapped (capacity=%zu)", mWrapped->capacity()); } } mediaImage->mNumPlanes = layout.numPlanes; mediaImage->mWidth = view.crop().width; mediaImage->mHeight = view.crop().height; mediaImage->mBitDepth = bitDepth; mediaImage->mBitDepthAllocated = mAllocatedDepth; uint32_t bufferSize = 0; for (uint32_t i = 0; i < layout.numPlanes; ++i) { const C2PlaneInfo &plane = layout.planes[i]; if (plane.allocatedDepth < plane.bitDepth || plane.rightShift != plane.allocatedDepth - plane.bitDepth) { ALOGD("rightShift value of %u unsupported", plane.rightShift); mInitCheck = BAD_VALUE; return; } if (plane.allocatedDepth > 8 && plane.endianness != C2PlaneInfo::NATIVE) { ALOGD("endianness value of %u unsupported", plane.endianness); mInitCheck = BAD_VALUE; return; } if (plane.allocatedDepth != mAllocatedDepth || plane.bitDepth != bitDepth) { ALOGD("different allocatedDepth/bitDepth per plane unsupported"); mInitCheck = BAD_VALUE; return; } // stride is in bytes bufferSize += stride * vStride / plane.rowSampling / plane.colSampling; } mBackBufferSize = bufferSize; mInitCheck = OK; } status_t initCheck() const { return mInitCheck; } uint32_t backBufferSize() const { return mBackBufferSize; } /** * Wrap C2GraphicView using a MediaImage2. Note that if not wrapped, the content is not mapped * in this function --- the caller should use CopyGraphicView2MediaImage() function to copy the * data into a backing buffer explicitly. * * \return media buffer. This is null if wrapping failed. */ sp<ABuffer> wrap() const { if (mBackBuffer == nullptr) { return mWrapped; } return nullptr; } bool setBackBuffer(const sp<ABuffer> &backBuffer) { if (backBuffer == nullptr) { return false; } if (backBuffer->capacity() < mBackBufferSize) { return false; } backBuffer->setRange(0, mBackBufferSize); mBackBuffer = backBuffer; return true; } /** * Copy C2GraphicView to MediaImage2. */ status_t copyToMediaImage() { ATRACE_CALL(); if (mInitCheck != OK) { return mInitCheck; } return ImageCopy(mBackBuffer->base(), getMediaImage(), mView); } const sp<ABuffer> &imageData() const { return mMediaImage; } private: status_t mInitCheck; const C2GraphicView mView; uint32_t mWidth; uint32_t mHeight; int32_t mClientColorFormat; ///< SDK color format for MediaImage int32_t mComponentColorFormat; ///< SDK color format from component sp<ABuffer> mWrapped; ///< wrapped buffer (if we can map C2Buffer to an ABuffer) uint32_t mAllocatedDepth; uint32_t mBackBufferSize; sp<ABuffer> mMediaImage; std::function<sp<ABuffer>(size_t)> mAlloc; sp<ABuffer> mBackBuffer; ///< backing buffer if we have to copy C2Buffer <=> ABuffer MediaImage2 *getMediaImage() { return (MediaImage2 *)mMediaImage->base(); } }; } // namespace // GraphicBlockBuffer // static Loading
media/codec2/sfplugin/Codec2Buffer.h +0 −22 Original line number Diff line number Diff line Loading @@ -44,28 +44,6 @@ struct SharedBuffer; } // namespace drm } // namespace hardware /** * Copies a graphic view into a media image. * * \param imgBase base of MediaImage * \param img MediaImage data * \param view graphic view * * \return OK on success */ status_t ImageCopy(uint8_t *imgBase, const MediaImage2 *img, const C2GraphicView &view); /** * Copies a media image into a graphic view. * * \param view graphic view * \param imgBase base of MediaImage * \param img MediaImage data * * \return OK on success */ status_t ImageCopy(C2GraphicView &view, const uint8_t *imgBase, const MediaImage2 *img); class Codec2Buffer : public MediaCodecBuffer { public: using MediaCodecBuffer::MediaCodecBuffer; Loading