Пример #1
0
void SoftAVC::drainAllOutputBuffers(bool eos) {
    List<BufferInfo *> &outQueue = getPortQueue(kOutputPortIndex);
    H264SwDecPicture decodedPicture;

    if (mHeadersDecoded) {
        while (!outQueue.empty()
                && H264SWDEC_PIC_RDY == H264SwDecNextPicture(
                    mHandle, &decodedPicture, eos /* flush */)) {
            int32_t picId = decodedPicture.picId;
            uint8_t *data = (uint8_t *) decodedPicture.pOutputPicture;
            drainOneOutputBuffer(picId, data);
        }
    }

    if (!eos) {
        return;
    }

    while (!outQueue.empty()) {
        BufferInfo *outInfo = *outQueue.begin();
        outQueue.erase(outQueue.begin());
        OMX_BUFFERHEADERTYPE *outHeader = outInfo->mHeader;

        outHeader->nTimeStamp = 0;
        outHeader->nFilledLen = 0;
        outHeader->nFlags = OMX_BUFFERFLAG_EOS;

        outInfo->mOwnedByUs = false;
        notifyFillBufferDone(outHeader);

        mEOSStatus = OUTPUT_FRAMES_FLUSHED;
    }
}
Пример #2
0
bool SoftAVC::drainAllOutputBuffers() {
    List<BufferInfo *> &outQueue = getPortQueue(kOutputPortIndex);
    H264SwDecPicture decodedPicture;

    while (!outQueue.empty()) {
        BufferInfo *outInfo = *outQueue.begin();
        outQueue.erase(outQueue.begin());
        OMX_BUFFERHEADERTYPE *outHeader = outInfo->mHeader;
        if (mHeadersDecoded &&
            H264SWDEC_PIC_RDY ==
                H264SwDecNextPicture(mHandle, &decodedPicture, 1 /* flush */)) {

            int32_t picId = decodedPicture.picId;
            CHECK(mPicToHeaderMap.indexOfKey(picId) >= 0);

            memcpy(outHeader->pBuffer + outHeader->nOffset,
                decodedPicture.pOutputPicture,
                mPictureSize);

            OMX_BUFFERHEADERTYPE *header = mPicToHeaderMap.valueFor(picId);
            outHeader->nTimeStamp = header->nTimeStamp;
            outHeader->nFlags = header->nFlags;
            outHeader->nFilledLen = mPictureSize;
            mPicToHeaderMap.removeItem(picId);
            delete header;
        } else if (mFirstPicture) {

            // Sending the saved output buffer because of dynamic port reconfiguration
            drainOneOutputBuffer(mFirstPictureId, mFirstPicture);
            delete[] mFirstPicture;
            mFirstPicture = NULL;
            mFirstPictureId = -1;
        } else {
            outHeader->nTimeStamp = 0;
            outHeader->nFilledLen = 0;
            outHeader->nFlags = OMX_BUFFERFLAG_EOS;
            mEOSStatus = OUTPUT_FRAMES_FLUSHED;
        }

        outInfo->mOwnedByUs = false;
        notifyFillBufferDone(outHeader);
    }

    return true;
}
Пример #3
0
void SoftAVC::onQueueFilled(OMX_U32 /* portIndex */) {
    if (mSignalledError || mOutputPortSettingsChange != NONE) {
        return;
    }

    if (mEOSStatus == OUTPUT_FRAMES_FLUSHED) {
        return;
    }

    List<BufferInfo *> &inQueue = getPortQueue(kInputPortIndex);
    List<BufferInfo *> &outQueue = getPortQueue(kOutputPortIndex);

    if (mHeadersDecoded) {
        // Dequeue any already decoded output frames to free up space
        // in the output queue.

        drainAllOutputBuffers(false /* eos */);
    }

    H264SwDecRet ret = H264SWDEC_PIC_RDY;
    bool portWillReset = false;
    while ((mEOSStatus != INPUT_DATA_AVAILABLE || !inQueue.empty())
            && outQueue.size() == kNumOutputBuffers) {

        if (mEOSStatus == INPUT_EOS_SEEN) {
            drainAllOutputBuffers(true /* eos */);
            return;
        }

        BufferInfo *inInfo = *inQueue.begin();
        OMX_BUFFERHEADERTYPE *inHeader = inInfo->mHeader;
        ++mPicId;

        OMX_BUFFERHEADERTYPE *header = new OMX_BUFFERHEADERTYPE;
        memset(header, 0, sizeof(OMX_BUFFERHEADERTYPE));
        header->nTimeStamp = inHeader->nTimeStamp;
        header->nFlags = inHeader->nFlags;
        if (header->nFlags & OMX_BUFFERFLAG_EOS) {
            mEOSStatus = INPUT_EOS_SEEN;
        }
        mPicToHeaderMap.add(mPicId, header);
        inQueue.erase(inQueue.begin());

        H264SwDecInput inPicture;
        H264SwDecOutput outPicture;
        memset(&inPicture, 0, sizeof(inPicture));
        inPicture.dataLen = inHeader->nFilledLen;
        inPicture.pStream = inHeader->pBuffer + inHeader->nOffset;
        inPicture.picId = mPicId;
        inPicture.intraConcealmentMethod = 1;
        H264SwDecPicture decodedPicture;

        while (inPicture.dataLen > 0) {
            ret = H264SwDecDecode(mHandle, &inPicture, &outPicture);
            if (ret == H264SWDEC_HDRS_RDY_BUFF_NOT_EMPTY ||
                ret == H264SWDEC_PIC_RDY_BUFF_NOT_EMPTY) {
                inPicture.dataLen -= (u32)(outPicture.pStrmCurrPos - inPicture.pStream);
                inPicture.pStream = outPicture.pStrmCurrPos;
                if (ret == H264SWDEC_HDRS_RDY_BUFF_NOT_EMPTY) {
                    mHeadersDecoded = true;
                    H264SwDecInfo decoderInfo;
                    CHECK(H264SwDecGetInfo(mHandle, &decoderInfo) == H264SWDEC_OK);

                    SoftVideoDecoderOMXComponent::CropSettingsMode cropSettingsMode =
                        handleCropParams(decoderInfo);
                    handlePortSettingsChange(
                            &portWillReset, decoderInfo.picWidth, decoderInfo.picHeight,
                            cropSettingsMode);
                }
            } else {
                if (portWillReset) {
                    if (H264SwDecNextPicture(mHandle, &decodedPicture, 0)
                        == H264SWDEC_PIC_RDY) {

                        // Save this output buffer; otherwise, it will be
                        // lost during dynamic port reconfiguration because
                        // OpenMAX client will delete _all_ output buffers
                        // in the process.
                        saveFirstOutputBuffer(
                            decodedPicture.picId,
                            (uint8_t *)decodedPicture.pOutputPicture);
                    }
                }
                inPicture.dataLen = 0;
                if (ret < 0) {
                    ALOGE("Decoder failed: %d", ret);

                    notify(OMX_EventError, OMX_ErrorUndefined,
                           ERROR_MALFORMED, NULL);

                    mSignalledError = true;
                    return;
                }
            }
        }
        inInfo->mOwnedByUs = false;
        notifyEmptyBufferDone(inHeader);

        if (portWillReset) {
            return;
        }

        if (mFirstPicture && !outQueue.empty()) {
            drainOneOutputBuffer(mFirstPictureId, mFirstPicture);
            delete[] mFirstPicture;
            mFirstPicture = NULL;
            mFirstPictureId = -1;
        }

        drainAllOutputBuffers(false /* eos */);
    }
}