Loading media/libstagefright/BufferImpl.cpp +446 −1 Original line number Diff line number Diff line Loading @@ -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; } Loading @@ -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; } Loading Loading @@ -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 media/libstagefright/CCodec.cpp +8 −0 Original line number Diff line number Diff line Loading @@ -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); } } } Loading media/libstagefright/CCodecBufferChannel.cpp +254 −10 File changed.Preview size limit exceeded, changes collapsed. Show changes media/libstagefright/codecs/avcdec/C2SoftAvcDec.cpp +91 −51 Original line number Diff line number Diff line Loading @@ -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 {}; Loading Loading @@ -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)) { Loading @@ -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), Loading Loading @@ -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; } Loading Loading @@ -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; } Loading Loading @@ -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; } Loading Loading @@ -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; Loading Loading @@ -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) { Loading Loading @@ -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); Loading @@ -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)); Loading media/libstagefright/codecs/avcdec/C2SoftAvcDec.h +1 −1 Original line number Diff line number Diff line Loading @@ -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 Loading
media/libstagefright/BufferImpl.cpp +446 −1 Original line number Diff line number Diff line Loading @@ -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; } Loading @@ -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; } Loading Loading @@ -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
media/libstagefright/CCodec.cpp +8 −0 Original line number Diff line number Diff line Loading @@ -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); } } } Loading
media/libstagefright/CCodecBufferChannel.cpp +254 −10 File changed.Preview size limit exceeded, changes collapsed. Show changes
media/libstagefright/codecs/avcdec/C2SoftAvcDec.cpp +91 −51 Original line number Diff line number Diff line Loading @@ -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 {}; Loading Loading @@ -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)) { Loading @@ -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), Loading Loading @@ -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; } Loading Loading @@ -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; } Loading Loading @@ -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; } Loading Loading @@ -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; Loading Loading @@ -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) { Loading Loading @@ -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); Loading @@ -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)); Loading
media/libstagefright/codecs/avcdec/C2SoftAvcDec.h +1 −1 Original line number Diff line number Diff line Loading @@ -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