Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 15639839 authored by Wonsik Kim's avatar Wonsik Kim
Browse files

CCodec: Episode IV --- Raw Video Buffers

Define and handle new buffer types for raw video buffers.

Bug: 69376489
Test: adb shell setprop debug.stagefright.ccodec yes
Test: adb shell setprop debug.stagefright.omx_default_rank 1000
Test: adb shell killall mediaserver
Test: atest CtsMediaTestCases:ImageReaderDecoderTest#testOtherH264ImageReader
Change-Id: I9d1061287e4c46526170ce395f826eccf4def4b7
parent e1c3b395
Loading
Loading
Loading
Loading
+446 −1
Original line number Diff line number Diff line
@@ -70,6 +70,10 @@ bool Codec2Buffer::canCopyLinear(const std::shared_ptr<C2Buffer> &buffer) const
    if (const_cast<Codec2Buffer *>(this)->base() == nullptr) {
        return false;
    }
    if (!buffer) {
        // Nothing to copy, so we can copy by doing nothing.
        return true;
    }
    if (buffer->data().type() != C2BufferData::LINEAR) {
        return false;
    }
@@ -89,7 +93,7 @@ bool Codec2Buffer::canCopyLinear(const std::shared_ptr<C2Buffer> &buffer) const

bool Codec2Buffer::copyLinear(const std::shared_ptr<C2Buffer> &buffer) {
    // We assume that all canCopyLinear() checks passed.
    if (buffer->data().linearBlocks().size() == 0u) {
    if (!buffer || buffer->data().linearBlocks().size() == 0u) {
        setRange(0, 0);
        return true;
    }
@@ -207,4 +211,445 @@ std::shared_ptr<C2Buffer> ConstLinearBlockBuffer::asC2Buffer() {
    return std::move(mBufferRef);
}

// GraphicView2MediaImageConverter

namespace {

class GraphicView2MediaImageConverter {
public:
    explicit GraphicView2MediaImageConverter(const C2GraphicView &view)
        : mInitCheck(NO_INIT),
          mView(view),
          mWidth(view.width()),
          mHeight(view.height()),
          mAllocatedDepth(0),
          mBackBufferSize(0),
          mMediaImage(new ABuffer(sizeof(MediaImage2))) {
        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;
        }
        mAllocatedDepth = layout.planes[0].allocatedDepth;
        uint32_t bitDepth = layout.planes[0].bitDepth;

        switch (layout.type) {
            case C2PlanarLayout::TYPE_YUV:
                mediaImage->mType = MediaImage2::MEDIA_IMAGE_TYPE_YUV; break;
            case C2PlanarLayout::TYPE_YUVA:
                mediaImage->mType = MediaImage2::MEDIA_IMAGE_TYPE_YUVA; break;
            case C2PlanarLayout::TYPE_RGB:
                mediaImage->mType = MediaImage2::MEDIA_IMAGE_TYPE_RGB; break;
            case C2PlanarLayout::TYPE_RGBA:
                mediaImage->mType = MediaImage2::MEDIA_IMAGE_TYPE_RGBA; break;
            default:
                mediaImage->mType = MediaImage2::MEDIA_IMAGE_TYPE_UNKNOWN; break;
        }
        mediaImage->mNumPlanes = layout.numPlanes;
        mediaImage->mWidth = mWidth;
        mediaImage->mHeight = mHeight;
        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.rightShift != 0) {
                ALOGV("rightShift value of %u unsupported", plane.rightShift);
                mInitCheck = BAD_VALUE;
                return;
            }
            if (plane.endianness != C2PlaneInfo::NATIVE) {
                ALOGV("endianness value of %u unsupported", plane.endianness);
                mInitCheck = BAD_VALUE;
                return;
            }
            if (plane.allocatedDepth != mAllocatedDepth || plane.bitDepth != bitDepth) {
                ALOGV("different allocatedDepth/bitDepth per plane unsupported");
                mInitCheck = BAD_VALUE;
                return;
            }
            bufferSize += mWidth * mHeight
                    / plane.rowSampling / plane.colSampling * (plane.allocatedDepth / 8);
        }

        mBackBufferSize = bufferSize;
        mInitCheck = OK;
    }

    status_t initCheck() const { return mInitCheck; }

    uint32_t backBufferSize() const { return mBackBufferSize; }

    /**
     * Convert C2GraphicView to MediaImage2. Note that if not wrapped, the content
     * is not copied over in this function --- the caller should use
     * CopyGraphicView2MediaImage() function to do that explicitly.
     *
     * \param   view[in]          source C2GraphicView object.
     * \param   alloc[in]         allocator function for ABuffer.
     * \param   mediaImage[out]   destination MediaImage2 object.
     * \param   buffer[out]       new buffer object.
     * \param   wrapped[out]      whether we wrapped around existing map or
     *                            allocated a new buffer
     *
     * \return  true              if conversion succeeds,
     *          false             otherwise; all output params should be ignored.
     */
    sp<ABuffer> wrap() {
        MediaImage2 *mediaImage = getMediaImage();
        const C2PlanarLayout &layout = mView.layout();
        if (layout.numPlanes == 1) {
            const C2PlaneInfo &plane = layout.planes[0];
            ssize_t offset = plane.minOffset(mWidth, mHeight);
            mediaImage->mPlane[0].mOffset = -offset;
            mediaImage->mPlane[0].mColInc = plane.colInc;
            mediaImage->mPlane[0].mRowInc = plane.rowInc;
            mediaImage->mPlane[0].mHorizSubsampling = plane.colSampling;
            mediaImage->mPlane[0].mVertSubsampling = plane.rowSampling;
            return new ABuffer(
                    const_cast<uint8_t *>(mView.data()[0] + offset),
                    plane.maxOffset(mWidth, mHeight) - offset + 1);
        }
        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];
            ssize_t minOffset = plane.minOffset(mWidth, mHeight);
            ssize_t maxOffset = plane.maxOffset(mWidth, mHeight);
            if (minPtr > mView.data()[i] + minOffset) {
                minPtr = mView.data()[i] + minOffset;
            }
            if (maxPtr < mView.data()[i] + maxOffset) {
                maxPtr = mView.data()[i] + maxOffset;
            }
            planeSize += std::abs(plane.rowInc) * mHeight
                    / plane.rowSampling / plane.colSampling * (mAllocatedDepth / 8);
        }

        if ((maxPtr - minPtr + 1) <= planeSize) {
            // FIXME: this is risky as reading/writing data out of bound results in
            //        an undefined behavior.
            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;
            }
            return new ABuffer(const_cast<uint8_t *>(minPtr), maxPtr - minPtr + 1);
        }

        return nullptr;
    }

    bool setBackBuffer(const sp<ABuffer> &backBuffer) {
        if (backBuffer->capacity() < mBackBufferSize) {
            return false;
        }
        backBuffer->setRange(0, mBackBufferSize);

        const C2PlanarLayout &layout = mView.layout();
        MediaImage2 *mediaImage = getMediaImage();
        uint32_t offset = 0;
        // TODO: keep interleaved planes together
        for (uint32_t i = 0; i < layout.numPlanes; ++i) {
            const C2PlaneInfo &plane = layout.planes[i];
            mediaImage->mPlane[i].mOffset = offset;
            mediaImage->mPlane[i].mColInc = mAllocatedDepth / 8;
            mediaImage->mPlane[i].mRowInc =
                mediaImage->mPlane[i].mColInc * mWidth / plane.colSampling;
            mediaImage->mPlane[i].mHorizSubsampling = plane.colSampling;
            mediaImage->mPlane[i].mVertSubsampling = plane.rowSampling;
            offset += mediaImage->mPlane[i].mRowInc * mHeight / plane.rowSampling;
        }
        mBackBuffer = backBuffer;
        return true;
    }

    /**
     * Copy C2GraphicView to MediaImage2. This function assumes that |mediaImage| is
     * an output from GraphicView2MediaImage(), so it mostly skips sanity check.
     *
     * \param   view[in]          source C2GraphicView object.
     * \param   mediaImage[in]    destination MediaImage2 object.
     * \param   buffer[out]       new buffer object.
     */
    void copy() {
        // TODO: more efficient copying --- e.g. one row at a time, copying
        //       interleaved planes together, etc.
        const C2PlanarLayout &layout = mView.layout();
        MediaImage2 *mediaImage = getMediaImage();
        uint8_t *dst = mBackBuffer->base();
        for (uint32_t i = 0; i < layout.numPlanes; ++i) {
            const C2PlaneInfo &plane = layout.planes[i];
            const uint8_t *src = mView.data()[i];
            int32_t planeW = mWidth / plane.colSampling;
            int32_t planeH = mHeight / plane.rowSampling;
            for (int32_t row = 0; row < planeH; ++row) {
                for(int32_t col = 0; col < planeW; ++col) {
                    memcpy(dst, src, mAllocatedDepth / 8);
                    dst += mediaImage->mPlane[i].mColInc;
                    src += plane.colInc;
                }
                dst -= mediaImage->mPlane[i].mColInc * planeW;
                dst += mediaImage->mPlane[i].mRowInc;
                src -= plane.colInc * planeW;
                src += plane.rowInc;
            }
        }
    }

    const sp<ABuffer> &imageData() const { return mMediaImage; }

private:
    status_t mInitCheck;

    const C2GraphicView mView;
    uint32_t mWidth;
    uint32_t mHeight;
    uint32_t mAllocatedDepth;
    uint32_t mBackBufferSize;
    sp<ABuffer> mMediaImage;
    std::function<sp<ABuffer>(size_t)> mAlloc;

    sp<ABuffer> mBackBuffer;

    MediaImage2 *getMediaImage() {
        return (MediaImage2 *)mMediaImage->base();
    }
};

}  // namespace

// GraphicBlockBuffer

// static
sp<GraphicBlockBuffer> GraphicBlockBuffer::Allocate(
        const sp<AMessage> &format,
        const std::shared_ptr<C2GraphicBlock> &block,
        std::function<sp<ABuffer>(size_t)> alloc) {
    C2GraphicView view(block->map().get());
    if (view.error() != C2_OK) {
        ALOGD("C2GraphicBlock::map failed: %d", view.error());
        return nullptr;
    }
    GraphicView2MediaImageConverter converter(view);
    if (converter.initCheck() != OK) {
        ALOGD("Converter init failed: %d", converter.initCheck());
        return nullptr;
    }
    bool wrapped = true;
    sp<ABuffer> buffer = converter.wrap();
    if (buffer == nullptr) {
        buffer = alloc(converter.backBufferSize());
        if (!converter.setBackBuffer(buffer)) {
            ALOGD("Converter failed to set back buffer");
            return nullptr;
        }
        wrapped = false;
    }
    return new GraphicBlockBuffer(
            format,
            buffer,
            std::move(view),
            block,
            converter.imageData(),
            wrapped);
}

GraphicBlockBuffer::GraphicBlockBuffer(
        const sp<AMessage> &format,
        const sp<ABuffer> &buffer,
        C2GraphicView &&view,
        const std::shared_ptr<C2GraphicBlock> &block,
        const sp<ABuffer> &imageData,
        bool wrapped)
    : Codec2Buffer(format, buffer),
      mView(view),
      mBlock(block),
      mImageData(imageData),
      mWrapped(wrapped) {
    meta()->setBuffer("image-data", imageData);
}

std::shared_ptr<C2Buffer> GraphicBlockBuffer::asC2Buffer() {
    uint32_t width = mView.width();
    uint32_t height = mView.height();
    if (!mWrapped) {
        MediaImage2 *mediaImage = imageData();
        const C2PlanarLayout &layout = mView.layout();
        for (uint32_t i = 0; i < mediaImage->mNumPlanes; ++i) {
            const C2PlaneInfo &plane = layout.planes[i];
            int32_t planeW = width / plane.colSampling;
            int32_t planeH = height / plane.rowSampling;
            const uint8_t *src = base() + mediaImage->mPlane[i].mOffset;
            uint8_t *dst = mView.data()[i];
            for (int32_t row = 0; row < planeH; ++row) {
                for (int32_t col = 0; col < planeW; ++col) {
                    memcpy(dst, src, mediaImage->mBitDepthAllocated / 8);
                    src += mediaImage->mPlane[i].mColInc;
                    dst += plane.colInc;
                }
                src -= mediaImage->mPlane[i].mColInc * planeW;
                dst -= plane.colInc * planeW;
                src += mediaImage->mPlane[i].mRowInc;
                dst += plane.rowInc;
            }
        }
    }
    return C2Buffer::CreateGraphicBuffer(
            mBlock->share(C2Rect(width, height), C2Fence()));
}

// ConstGraphicBlockBuffer

// static
sp<ConstGraphicBlockBuffer> ConstGraphicBlockBuffer::Allocate(
        const sp<AMessage> &format,
        const std::shared_ptr<C2Buffer> &buffer,
        std::function<sp<ABuffer>(size_t)> alloc) {
    if (!buffer
            || buffer->data().type() != C2BufferData::GRAPHIC
            || buffer->data().graphicBlocks().size() != 1u) {
        ALOGD("C2Buffer precond fail");
        return nullptr;
    }
    std::unique_ptr<const C2GraphicView> view(std::make_unique<const C2GraphicView>(
            buffer->data().graphicBlocks()[0].map().get()));
    std::unique_ptr<const C2GraphicView> holder;

    GraphicView2MediaImageConverter converter(*view);
    if (converter.initCheck() != OK) {
        ALOGD("Converter init failed: %d", converter.initCheck());
        return nullptr;
    }
    bool wrapped = true;
    sp<ABuffer> aBuffer = converter.wrap();
    if (aBuffer == nullptr) {
        aBuffer = alloc(converter.backBufferSize());
        if (!converter.setBackBuffer(aBuffer)) {
            ALOGD("Converter failed to set back buffer");
            return nullptr;
        }
        wrapped = false;
        converter.copy();
        // We don't need the view.
        holder = std::move(view);
    }
    return new ConstGraphicBlockBuffer(
            format,
            aBuffer,
            std::move(view),
            buffer,
            converter.imageData(),
            wrapped);
}

// static
sp<ConstGraphicBlockBuffer> ConstGraphicBlockBuffer::AllocateEmpty(
        const sp<AMessage> &format,
        std::function<sp<ABuffer>(size_t)> alloc) {
    int32_t width, height;
    if (!format->findInt32("width", &width)
            || !format->findInt32("height", &height)) {
        ALOGD("format had no width / height");
        return nullptr;
    }
    sp<ABuffer> aBuffer(alloc(width * height * 4));
    return new ConstGraphicBlockBuffer(
            format,
            aBuffer,
            nullptr,
            nullptr,
            nullptr,
            false);
}

ConstGraphicBlockBuffer::ConstGraphicBlockBuffer(
        const sp<AMessage> &format,
        const sp<ABuffer> &aBuffer,
        std::unique_ptr<const C2GraphicView> &&view,
        const std::shared_ptr<C2Buffer> &buffer,
        const sp<ABuffer> &imageData,
        bool wrapped)
    : Codec2Buffer(format, aBuffer),
      mView(std::move(view)),
      mBufferRef(buffer),
      mWrapped(wrapped) {
    if (imageData != nullptr) {
        meta()->setBuffer("image-data", imageData);
    }
}

std::shared_ptr<C2Buffer> ConstGraphicBlockBuffer::asC2Buffer() {
    mView.reset();
    return std::move(mBufferRef);
}

bool ConstGraphicBlockBuffer::canCopy(const std::shared_ptr<C2Buffer> &buffer) const {
    if (mWrapped || mBufferRef) {
        ALOGD("ConstGraphicBlockBuffer::canCopy: %swrapped ; buffer ref %s",
                mWrapped ? "" : "not ", mBufferRef ? "exists" : "doesn't exist");
        return false;
    }
    if (!buffer) {
        // Nothing to copy, so we can copy by doing nothing.
        return true;
    }
    if (buffer->data().type() != C2BufferData::GRAPHIC) {
        ALOGD("ConstGraphicBlockBuffer::canCopy: buffer precondition unsatisfied");
        return false;
    }
    if (buffer->data().graphicBlocks().size() == 0) {
        return true;
    } else if (buffer->data().graphicBlocks().size() != 1u) {
        ALOGD("ConstGraphicBlockBuffer::canCopy: too many blocks");
        return false;
    }
    GraphicView2MediaImageConverter converter(
            buffer->data().graphicBlocks()[0].map().get());
    if (converter.initCheck() != OK) {
        ALOGD("ConstGraphicBlockBuffer::canCopy: converter init failed: %d", converter.initCheck());
        return false;
    }
    if (converter.backBufferSize() > capacity()) {
        ALOGD("ConstGraphicBlockBuffer::canCopy: insufficient capacity: req %u has %zu",
                converter.backBufferSize(), capacity());
        return false;
    }
    return true;
}

bool ConstGraphicBlockBuffer::copy(const std::shared_ptr<C2Buffer> &buffer) {
    if (!buffer || buffer->data().graphicBlocks().size() == 0) {
        setRange(0, 0);
        return true;
    }
    GraphicView2MediaImageConverter converter(
            buffer->data().graphicBlocks()[0].map().get());
    if (converter.initCheck() != OK) {
        ALOGD("ConstGraphicBlockBuffer::copy: converter init failed: %d", converter.initCheck());
        return false;
    }
    sp<ABuffer> aBuffer = new ABuffer(base(), capacity());
    if (!converter.setBackBuffer(aBuffer)) {
        ALOGD("ConstGraphicBlockBuffer::copy: set back buffer failed");
        return false;
    }
    converter.copy();
    meta()->setBuffer("image-data", converter.imageData());
    mBufferRef = buffer;
    return true;
}

}  // namespace android
+8 −0
Original line number Diff line number Diff line
@@ -404,6 +404,14 @@ void CCodec::configure(const sp<AMessage> &msg) {
            if (audio) {
                outputFormat->setInt32("channel-count", 2);
                outputFormat->setInt32("sample-rate", 44100);
            } else {
                int32_t tmp;
                if (msg->findInt32("width", &tmp)) {
                    outputFormat->setInt32("width", tmp);
                }
                if (msg->findInt32("height", &tmp)) {
                    outputFormat->setInt32("height", tmp);
                }
            }
        }

+254 −10

File changed.

Preview size limit exceeded, changes collapsed.

+91 −51
Original line number Diff line number Diff line
@@ -37,15 +37,6 @@

#include "ih264d_defs.h"

namespace {

template <class T>
inline int32_t floor32(T arg) {
   return (int32_t) std::llround(std::floor(arg));
}

} // namespace

namespace android {

struct iv_obj_t : public ::iv_obj_t {};
@@ -83,6 +74,20 @@ std::shared_ptr<C2ComponentInterface> BuildIntf(
            .build();
}

void CopyPlane(
        uint8_t *dst, const C2PlaneInfo &plane,
        const uint8_t *src, uint32_t width, uint32_t height) {
    for (uint32_t row = 0; row < height; ++row) {
        for (uint32_t col = 0; col < width; ++col) {
            *dst = *src;
            dst += plane.colInc;
            ++src;
        }
        dst -= plane.colInc * width;
        dst += plane.rowInc;
    }
}

void fillEmptyWork(const std::unique_ptr<C2Work> &work) {
    uint32_t flags = 0;
    if ((work->input.flags & C2FrameData::FLAG_END_OF_STREAM)) {
@@ -103,7 +108,7 @@ C2SoftAvcDec::C2SoftAvcDec(
        c2_node_id_t id)
    : SimpleC2Component(BuildIntf(name, id)),
      mCodecCtx(NULL),
      mFlushOutBuffer(NULL),
      mOutBuffer(NULL),
      mIvColorFormat(IV_YUV_420P),
      mChangingResolution(false),
      mSignalledError(false),
@@ -164,9 +169,9 @@ c2_status_t C2SoftAvcDec::onFlush_sm() {
        }
    }

    if (mFlushOutBuffer) {
        free(mFlushOutBuffer);
        mFlushOutBuffer = NULL;
    if (mOutBuffer) {
        free(mOutBuffer);
        mOutBuffer = NULL;
    }
    return C2_OK;
}
@@ -244,6 +249,16 @@ status_t C2SoftAvcDec::setParams(size_t stride) {

        return UNKNOWN_ERROR;
    }

    if (mOutBuffer != NULL) {
        free(mOutBuffer);
    }
    uint32_t bufferSize = mWidth * mHeight * 3 / 2;
    mOutBuffer = (uint8_t *)memalign(128, bufferSize);
    if (NULL == mOutBuffer) {
        ALOGE("Could not allocate output buffer of size %u", bufferSize);
        return C2_NO_MEMORY;
    }
    return OK;
}

@@ -321,17 +336,6 @@ status_t C2SoftAvcDec::setFlushMode() {
        return UNKNOWN_ERROR;
    }

    /* Allocate a picture buffer to flushed data */
    uint32_t displayStride = mWidth;
    uint32_t displayHeight = mHeight;

    uint32_t bufferSize = displayStride * displayHeight * 3 / 2;
    mFlushOutBuffer = (uint8_t *)memalign(128, bufferSize);
    if (NULL == mFlushOutBuffer) {
        ALOGE("Could not allocate flushOutputBuffer of size %u", bufferSize);
        return C2_NO_MEMORY;
    }

    return OK;
}

@@ -499,14 +503,29 @@ bool C2SoftAvcDec::setDecodeArgs(
                  outBuffer->width(), outBuffer->height(), width, height);
            return false;
        }
        ALOGV("width = %u, stride[0] = %u, stride[1] = %u, stride[2] = %u",
                outBuffer->width(),
                outBuffer->layout().planes[0].rowInc,
                outBuffer->layout().planes[1].rowInc,
                outBuffer->layout().planes[2].rowInc);
        const C2PlanarLayout &layout = outBuffer->layout();
        ps_dec_ip->s_out_buffer.pu1_bufs[0] = outBuffer->data()[0];
        if (layout.planes[0].rowInc != (int32_t)mWidth || layout.planes[1].colInc != 1) {
            ps_dec_ip->s_out_buffer.pu1_bufs[0] = mOutBuffer;
        }
        ps_dec_ip->s_out_buffer.pu1_bufs[1] = outBuffer->data()[1];
        if (layout.planes[1].rowInc != (int32_t)mWidth / 2 || layout.planes[1].colInc != 1) {
            ps_dec_ip->s_out_buffer.pu1_bufs[1] = mOutBuffer + sizeY;
        }
        ps_dec_ip->s_out_buffer.pu1_bufs[2] = outBuffer->data()[2];
        if (layout.planes[2].rowInc != (int32_t)mWidth / 2 || layout.planes[2].colInc != 1) {
            ps_dec_ip->s_out_buffer.pu1_bufs[2] = mOutBuffer + sizeY + sizeUV;
        }
    } else {
        // mFlushOutBuffer always has the right size.
        ps_dec_ip->s_out_buffer.pu1_bufs[0] = mFlushOutBuffer;
        ps_dec_ip->s_out_buffer.pu1_bufs[1] = mFlushOutBuffer + sizeY;
        ps_dec_ip->s_out_buffer.pu1_bufs[2] = mFlushOutBuffer + sizeY + sizeUV;
        // mOutBuffer always has the right size.
        ps_dec_ip->s_out_buffer.pu1_bufs[0] = mOutBuffer;
        ps_dec_ip->s_out_buffer.pu1_bufs[1] = mOutBuffer + sizeY;
        ps_dec_ip->s_out_buffer.pu1_bufs[2] = mOutBuffer + sizeY + sizeUV;
    }

    ps_dec_ip->s_out_buffer.u4_num_bufs = 3;
@@ -544,7 +563,8 @@ c2_status_t C2SoftAvcDec::ensureDecoderState(const std::shared_ptr<C2BlockPool>
}

void C2SoftAvcDec::finishWork(uint64_t index, const std::unique_ptr<C2Work> &work) {
    std::shared_ptr<C2Buffer> buffer = createGraphicBuffer(std::move(mAllocatedBlock));
    std::shared_ptr<C2Buffer> buffer = createGraphicBuffer(mAllocatedBlock);
    mAllocatedBlock.reset();
    auto fillWork = [buffer](const std::unique_ptr<C2Work> &work) {
        uint32_t flags = 0;
        if (work->input.flags & C2FrameData::FLAG_END_OF_STREAM) {
@@ -603,16 +623,19 @@ void C2SoftAvcDec::process(
            break;
        }
        (void)ensureDecoderState(pool);
        C2GraphicView output = mAllocatedBlock->map().get();
        if (output.error() != OK) {
            ALOGE("mapped err = %d", output.error());
        }

        ivd_video_decode_ip_t s_dec_ip;
        ivd_video_decode_op_t s_dec_op;
        WORD32 timeDelay, timeTaken;
        //size_t sizeY, sizeUV;

        {
            C2GraphicView output = mAllocatedBlock->map().get();
            if (output.error() != C2_OK) {
                ALOGE("mapped err = %d", output.error());
                work->result = output.error();
                fillEmptyWork(work);
                return;
            }
            if (!setDecodeArgs(&s_dec_ip, &s_dec_op, &input, &output, workIndex, inOffset)) {
                ALOGE("Decoder arg setup failed");
                // TODO: notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL);
@@ -631,6 +654,23 @@ void C2SoftAvcDec::process(
            IV_API_CALL_STATUS_T status;
            status = ivdec_api_function(mCodecCtx, (void *)&s_dec_ip, (void *)&s_dec_op);
            ALOGV("status = %d, error_code = %d", status, (s_dec_op.u4_error_code & 0xFF));
            if (s_dec_op.u4_output_present) {
                const C2PlanarLayout &layout = output.layout();
                if (layout.planes[0].rowInc != (int32_t)mWidth || layout.planes[1].colInc != 1) {
                    CopyPlane(output.data()[0], layout.planes[0], mOutBuffer, mWidth, mHeight);
                }
                if (layout.planes[1].rowInc != (int32_t)mWidth / 2 || layout.planes[1].colInc != 1) {
                    CopyPlane(
                            output.data()[1], layout.planes[1],
                            mOutBuffer + (mWidth * mHeight), mWidth / 2, mHeight / 2);
                }
                if (layout.planes[2].rowInc != (int32_t)mWidth / 2 || layout.planes[2].colInc != 1) {
                    CopyPlane(
                            output.data()[2], layout.planes[2],
                            mOutBuffer + (mWidth * mHeight * 5 / 4), mWidth / 2, mHeight / 2);
                }
            }
        }

        bool unsupportedResolution =
            (IVD_STREAM_WIDTH_HEIGHT_NOT_SUPPORTED == (s_dec_op.u4_error_code & 0xFF));
+1 −1
Original line number Diff line number Diff line
@@ -189,7 +189,7 @@ private:
    struct timeval mTimeEnd;     // Time at the end of decode()

    // Internal buffer to be used to flush out the buffers from decoder
    uint8_t *mFlushOutBuffer;
    uint8_t *mOutBuffer;

#ifdef FILE_DUMP_ENABLE
    char mInFile[200];
Loading