10c1bc742181ded4930842b46e9507372f0b1b963James Dong/*
20c1bc742181ded4930842b46e9507372f0b1b963James Dong * Copyright (C) 2011 The Android Open Source Project
30c1bc742181ded4930842b46e9507372f0b1b963James Dong *
40c1bc742181ded4930842b46e9507372f0b1b963James Dong * Licensed under the Apache License, Version 2.0 (the "License");
50c1bc742181ded4930842b46e9507372f0b1b963James Dong * you may not use this file except in compliance with the License.
60c1bc742181ded4930842b46e9507372f0b1b963James Dong * You may obtain a copy of the License at
70c1bc742181ded4930842b46e9507372f0b1b963James Dong *
80c1bc742181ded4930842b46e9507372f0b1b963James Dong *      http://www.apache.org/licenses/LICENSE-2.0
90c1bc742181ded4930842b46e9507372f0b1b963James Dong *
100c1bc742181ded4930842b46e9507372f0b1b963James Dong * Unless required by applicable law or agreed to in writing, software
110c1bc742181ded4930842b46e9507372f0b1b963James Dong * distributed under the License is distributed on an "AS IS" BASIS,
120c1bc742181ded4930842b46e9507372f0b1b963James Dong * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
130c1bc742181ded4930842b46e9507372f0b1b963James Dong * See the License for the specific language governing permissions and
140c1bc742181ded4930842b46e9507372f0b1b963James Dong * limitations under the License.
150c1bc742181ded4930842b46e9507372f0b1b963James Dong */
160c1bc742181ded4930842b46e9507372f0b1b963James Dong
170c1bc742181ded4930842b46e9507372f0b1b963James Dong//#define LOG_NDEBUG 0
180c1bc742181ded4930842b46e9507372f0b1b963James Dong#define LOG_TAG "SoftAVC"
190c1bc742181ded4930842b46e9507372f0b1b963James Dong#include <utils/Log.h>
200c1bc742181ded4930842b46e9507372f0b1b963James Dong
210c1bc742181ded4930842b46e9507372f0b1b963James Dong#include "SoftAVC.h"
220c1bc742181ded4930842b46e9507372f0b1b963James Dong
230c1bc742181ded4930842b46e9507372f0b1b963James Dong#include <media/stagefright/foundation/ADebug.h>
240c1bc742181ded4930842b46e9507372f0b1b963James Dong#include <media/stagefright/MediaDefs.h>
250c1bc742181ded4930842b46e9507372f0b1b963James Dong#include <media/stagefright/MediaErrors.h>
26457116d3a01618acf9a875020ca5860551ba03a6James Dong#include <media/IOMX.h>
270c1bc742181ded4930842b46e9507372f0b1b963James Dong
280c1bc742181ded4930842b46e9507372f0b1b963James Dong
290c1bc742181ded4930842b46e9507372f0b1b963James Dongnamespace android {
300c1bc742181ded4930842b46e9507372f0b1b963James Dong
31457116d3a01618acf9a875020ca5860551ba03a6James Dongstatic const CodecProfileLevel kProfileLevels[] = {
32457116d3a01618acf9a875020ca5860551ba03a6James Dong    { OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel1  },
33457116d3a01618acf9a875020ca5860551ba03a6James Dong    { OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel1b },
34457116d3a01618acf9a875020ca5860551ba03a6James Dong    { OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel11 },
35457116d3a01618acf9a875020ca5860551ba03a6James Dong    { OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel12 },
36457116d3a01618acf9a875020ca5860551ba03a6James Dong    { OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel13 },
37457116d3a01618acf9a875020ca5860551ba03a6James Dong    { OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel2  },
38457116d3a01618acf9a875020ca5860551ba03a6James Dong    { OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel21 },
39457116d3a01618acf9a875020ca5860551ba03a6James Dong    { OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel22 },
40457116d3a01618acf9a875020ca5860551ba03a6James Dong    { OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel3  },
41457116d3a01618acf9a875020ca5860551ba03a6James Dong    { OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel31 },
42457116d3a01618acf9a875020ca5860551ba03a6James Dong    { OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel32 },
43457116d3a01618acf9a875020ca5860551ba03a6James Dong    { OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel4  },
44457116d3a01618acf9a875020ca5860551ba03a6James Dong    { OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel41 },
45457116d3a01618acf9a875020ca5860551ba03a6James Dong    { OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel42 },
46457116d3a01618acf9a875020ca5860551ba03a6James Dong    { OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel5  },
47457116d3a01618acf9a875020ca5860551ba03a6James Dong    { OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel51 },
48457116d3a01618acf9a875020ca5860551ba03a6James Dong};
49457116d3a01618acf9a875020ca5860551ba03a6James Dong
500c1bc742181ded4930842b46e9507372f0b1b963James DongSoftAVC::SoftAVC(
510c1bc742181ded4930842b46e9507372f0b1b963James Dong        const char *name,
520c1bc742181ded4930842b46e9507372f0b1b963James Dong        const OMX_CALLBACKTYPE *callbacks,
530c1bc742181ded4930842b46e9507372f0b1b963James Dong        OMX_PTR appData,
540c1bc742181ded4930842b46e9507372f0b1b963James Dong        OMX_COMPONENTTYPE **component)
557f616d3cc5366a4b8af20d3d0c768e3de1df0666Lajos Molnar    : SoftVideoDecoderOMXComponent(
567f616d3cc5366a4b8af20d3d0c768e3de1df0666Lajos Molnar            name, "video_decoder.avc", OMX_VIDEO_CodingAVC,
577f616d3cc5366a4b8af20d3d0c768e3de1df0666Lajos Molnar            kProfileLevels, ARRAY_SIZE(kProfileLevels),
587f616d3cc5366a4b8af20d3d0c768e3de1df0666Lajos Molnar            320 /* width */, 240 /* height */, callbacks, appData, component),
590c1bc742181ded4930842b46e9507372f0b1b963James Dong      mHandle(NULL),
600c1bc742181ded4930842b46e9507372f0b1b963James Dong      mInputBufferCount(0),
610c1bc742181ded4930842b46e9507372f0b1b963James Dong      mFirstPicture(NULL),
620c1bc742181ded4930842b46e9507372f0b1b963James Dong      mFirstPictureId(-1),
630c1bc742181ded4930842b46e9507372f0b1b963James Dong      mPicId(0),
640c1bc742181ded4930842b46e9507372f0b1b963James Dong      mHeadersDecoded(false),
650c1bc742181ded4930842b46e9507372f0b1b963James Dong      mEOSStatus(INPUT_DATA_AVAILABLE),
662961a85f5f00343c115ac8e5dc17de631694fb6eAndreas Huber      mSignalledError(false) {
67a0940a569f2bc24b00dc10ce0fa7658b1dc3a3a5Lajos Molnar    const size_t kMinCompressionRatio = 2;
68a0940a569f2bc24b00dc10ce0fa7658b1dc3a3a5Lajos Molnar    const size_t kMaxOutputBufferSize = 2048 * 2048 * 3 / 2;
697f616d3cc5366a4b8af20d3d0c768e3de1df0666Lajos Molnar    initPorts(
70a0940a569f2bc24b00dc10ce0fa7658b1dc3a3a5Lajos Molnar            kNumInputBuffers, kMaxOutputBufferSize / kMinCompressionRatio /* minInputBufferSize */,
71a0940a569f2bc24b00dc10ce0fa7658b1dc3a3a5Lajos Molnar            kNumOutputBuffers, MEDIA_MIMETYPE_VIDEO_AVC, kMinCompressionRatio);
727f616d3cc5366a4b8af20d3d0c768e3de1df0666Lajos Molnar
730c1bc742181ded4930842b46e9507372f0b1b963James Dong    CHECK_EQ(initDecoder(), (status_t)OK);
740c1bc742181ded4930842b46e9507372f0b1b963James Dong}
750c1bc742181ded4930842b46e9507372f0b1b963James Dong
760c1bc742181ded4930842b46e9507372f0b1b963James DongSoftAVC::~SoftAVC() {
770c1bc742181ded4930842b46e9507372f0b1b963James Dong    H264SwDecRelease(mHandle);
780c1bc742181ded4930842b46e9507372f0b1b963James Dong    mHandle = NULL;
790c1bc742181ded4930842b46e9507372f0b1b963James Dong
800c1bc742181ded4930842b46e9507372f0b1b963James Dong    while (mPicToHeaderMap.size() != 0) {
810c1bc742181ded4930842b46e9507372f0b1b963James Dong        OMX_BUFFERHEADERTYPE *header = mPicToHeaderMap.editValueAt(0);
820c1bc742181ded4930842b46e9507372f0b1b963James Dong        mPicToHeaderMap.removeItemsAt(0);
830c1bc742181ded4930842b46e9507372f0b1b963James Dong        delete header;
840c1bc742181ded4930842b46e9507372f0b1b963James Dong        header = NULL;
850c1bc742181ded4930842b46e9507372f0b1b963James Dong    }
860c1bc742181ded4930842b46e9507372f0b1b963James Dong    List<BufferInfo *> &outQueue = getPortQueue(kOutputPortIndex);
870c1bc742181ded4930842b46e9507372f0b1b963James Dong    List<BufferInfo *> &inQueue = getPortQueue(kInputPortIndex);
880c1bc742181ded4930842b46e9507372f0b1b963James Dong    CHECK(outQueue.empty());
890c1bc742181ded4930842b46e9507372f0b1b963James Dong    CHECK(inQueue.empty());
900c1bc742181ded4930842b46e9507372f0b1b963James Dong
910c1bc742181ded4930842b46e9507372f0b1b963James Dong    delete[] mFirstPicture;
920c1bc742181ded4930842b46e9507372f0b1b963James Dong}
930c1bc742181ded4930842b46e9507372f0b1b963James Dong
940c1bc742181ded4930842b46e9507372f0b1b963James Dongstatus_t SoftAVC::initDecoder() {
95486247017e0bfb9db9994a53a28c0dacfebf8567James Dong    // Force decoder to output buffers in display order.
96486247017e0bfb9db9994a53a28c0dacfebf8567James Dong    if (H264SwDecInit(&mHandle, 0) == H264SWDEC_OK) {
970c1bc742181ded4930842b46e9507372f0b1b963James Dong        return OK;
980c1bc742181ded4930842b46e9507372f0b1b963James Dong    }
990c1bc742181ded4930842b46e9507372f0b1b963James Dong    return UNKNOWN_ERROR;
1000c1bc742181ded4930842b46e9507372f0b1b963James Dong}
1010c1bc742181ded4930842b46e9507372f0b1b963James Dong
10284333e0475bc911adc16417f4ca327c975cf6c36Andreas Hubervoid SoftAVC::onQueueFilled(OMX_U32 /* portIndex */) {
1032961a85f5f00343c115ac8e5dc17de631694fb6eAndreas Huber    if (mSignalledError || mOutputPortSettingsChange != NONE) {
1040c1bc742181ded4930842b46e9507372f0b1b963James Dong        return;
1050c1bc742181ded4930842b46e9507372f0b1b963James Dong    }
1060c1bc742181ded4930842b46e9507372f0b1b963James Dong
1070c1bc742181ded4930842b46e9507372f0b1b963James Dong    if (mEOSStatus == OUTPUT_FRAMES_FLUSHED) {
1080c1bc742181ded4930842b46e9507372f0b1b963James Dong        return;
1090c1bc742181ded4930842b46e9507372f0b1b963James Dong    }
1100c1bc742181ded4930842b46e9507372f0b1b963James Dong
1110c1bc742181ded4930842b46e9507372f0b1b963James Dong    List<BufferInfo *> &inQueue = getPortQueue(kInputPortIndex);
1120c1bc742181ded4930842b46e9507372f0b1b963James Dong    List<BufferInfo *> &outQueue = getPortQueue(kOutputPortIndex);
1132309d1a1ff016a31d9aa68272bcb471e64a26cfaAndreas Huber
1142309d1a1ff016a31d9aa68272bcb471e64a26cfaAndreas Huber    if (mHeadersDecoded) {
1152309d1a1ff016a31d9aa68272bcb471e64a26cfaAndreas Huber        // Dequeue any already decoded output frames to free up space
1162309d1a1ff016a31d9aa68272bcb471e64a26cfaAndreas Huber        // in the output queue.
1172309d1a1ff016a31d9aa68272bcb471e64a26cfaAndreas Huber
1182309d1a1ff016a31d9aa68272bcb471e64a26cfaAndreas Huber        drainAllOutputBuffers(false /* eos */);
1192309d1a1ff016a31d9aa68272bcb471e64a26cfaAndreas Huber    }
1202309d1a1ff016a31d9aa68272bcb471e64a26cfaAndreas Huber
1210c1bc742181ded4930842b46e9507372f0b1b963James Dong    H264SwDecRet ret = H264SWDEC_PIC_RDY;
122bf220f3e6e799f28d1599c3c5106e9e15631a91dRonghua Wu    bool portWillReset = false;
1230c1bc742181ded4930842b46e9507372f0b1b963James Dong    while ((mEOSStatus != INPUT_DATA_AVAILABLE || !inQueue.empty())
1240c1bc742181ded4930842b46e9507372f0b1b963James Dong            && outQueue.size() == kNumOutputBuffers) {
1250c1bc742181ded4930842b46e9507372f0b1b963James Dong
1260c1bc742181ded4930842b46e9507372f0b1b963James Dong        if (mEOSStatus == INPUT_EOS_SEEN) {
1272309d1a1ff016a31d9aa68272bcb471e64a26cfaAndreas Huber            drainAllOutputBuffers(true /* eos */);
1280c1bc742181ded4930842b46e9507372f0b1b963James Dong            return;
1290c1bc742181ded4930842b46e9507372f0b1b963James Dong        }
1300c1bc742181ded4930842b46e9507372f0b1b963James Dong
1310c1bc742181ded4930842b46e9507372f0b1b963James Dong        BufferInfo *inInfo = *inQueue.begin();
1320c1bc742181ded4930842b46e9507372f0b1b963James Dong        OMX_BUFFERHEADERTYPE *inHeader = inInfo->mHeader;
1330c1bc742181ded4930842b46e9507372f0b1b963James Dong        ++mPicId;
1340c1bc742181ded4930842b46e9507372f0b1b963James Dong
1350c1bc742181ded4930842b46e9507372f0b1b963James Dong        OMX_BUFFERHEADERTYPE *header = new OMX_BUFFERHEADERTYPE;
1360c1bc742181ded4930842b46e9507372f0b1b963James Dong        memset(header, 0, sizeof(OMX_BUFFERHEADERTYPE));
1370c1bc742181ded4930842b46e9507372f0b1b963James Dong        header->nTimeStamp = inHeader->nTimeStamp;
1380c1bc742181ded4930842b46e9507372f0b1b963James Dong        header->nFlags = inHeader->nFlags;
1394c44e9fed87ff6363393f2559b150291242da247Marco Nelissen        if (header->nFlags & OMX_BUFFERFLAG_EOS) {
1404c44e9fed87ff6363393f2559b150291242da247Marco Nelissen            mEOSStatus = INPUT_EOS_SEEN;
1414c44e9fed87ff6363393f2559b150291242da247Marco Nelissen        }
1420c1bc742181ded4930842b46e9507372f0b1b963James Dong        mPicToHeaderMap.add(mPicId, header);
1430c1bc742181ded4930842b46e9507372f0b1b963James Dong        inQueue.erase(inQueue.begin());
1440c1bc742181ded4930842b46e9507372f0b1b963James Dong
1450c1bc742181ded4930842b46e9507372f0b1b963James Dong        H264SwDecInput inPicture;
1460c1bc742181ded4930842b46e9507372f0b1b963James Dong        H264SwDecOutput outPicture;
1470c1bc742181ded4930842b46e9507372f0b1b963James Dong        memset(&inPicture, 0, sizeof(inPicture));
1480c1bc742181ded4930842b46e9507372f0b1b963James Dong        inPicture.dataLen = inHeader->nFilledLen;
1490c1bc742181ded4930842b46e9507372f0b1b963James Dong        inPicture.pStream = inHeader->pBuffer + inHeader->nOffset;
1500c1bc742181ded4930842b46e9507372f0b1b963James Dong        inPicture.picId = mPicId;
1510c1bc742181ded4930842b46e9507372f0b1b963James Dong        inPicture.intraConcealmentMethod = 1;
1520c1bc742181ded4930842b46e9507372f0b1b963James Dong        H264SwDecPicture decodedPicture;
1530c1bc742181ded4930842b46e9507372f0b1b963James Dong
1540c1bc742181ded4930842b46e9507372f0b1b963James Dong        while (inPicture.dataLen > 0) {
1550c1bc742181ded4930842b46e9507372f0b1b963James Dong            ret = H264SwDecDecode(mHandle, &inPicture, &outPicture);
1560c1bc742181ded4930842b46e9507372f0b1b963James Dong            if (ret == H264SWDEC_HDRS_RDY_BUFF_NOT_EMPTY ||
1570c1bc742181ded4930842b46e9507372f0b1b963James Dong                ret == H264SWDEC_PIC_RDY_BUFF_NOT_EMPTY) {
1580c1bc742181ded4930842b46e9507372f0b1b963James Dong                inPicture.dataLen -= (u32)(outPicture.pStrmCurrPos - inPicture.pStream);
1590c1bc742181ded4930842b46e9507372f0b1b963James Dong                inPicture.pStream = outPicture.pStrmCurrPos;
1600c1bc742181ded4930842b46e9507372f0b1b963James Dong                if (ret == H264SWDEC_HDRS_RDY_BUFF_NOT_EMPTY) {
1610c1bc742181ded4930842b46e9507372f0b1b963James Dong                    mHeadersDecoded = true;
1620c1bc742181ded4930842b46e9507372f0b1b963James Dong                    H264SwDecInfo decoderInfo;
1630c1bc742181ded4930842b46e9507372f0b1b963James Dong                    CHECK(H264SwDecGetInfo(mHandle, &decoderInfo) == H264SWDEC_OK);
1640c1bc742181ded4930842b46e9507372f0b1b963James Dong
165d5a2f55034022f2d0425fa0701894d0c4787b726Ronghua Wu                    SoftVideoDecoderOMXComponent::CropSettingsMode cropSettingsMode =
166d5a2f55034022f2d0425fa0701894d0c4787b726Ronghua Wu                        handleCropParams(decoderInfo);
167bf220f3e6e799f28d1599c3c5106e9e15631a91dRonghua Wu                    handlePortSettingsChange(
168bf220f3e6e799f28d1599c3c5106e9e15631a91dRonghua Wu                            &portWillReset, decoderInfo.picWidth, decoderInfo.picHeight,
169d5a2f55034022f2d0425fa0701894d0c4787b726Ronghua Wu                            cropSettingsMode);
1700c1bc742181ded4930842b46e9507372f0b1b963James Dong                }
1710c1bc742181ded4930842b46e9507372f0b1b963James Dong            } else {
172bf220f3e6e799f28d1599c3c5106e9e15631a91dRonghua Wu                if (portWillReset) {
1730c1bc742181ded4930842b46e9507372f0b1b963James Dong                    if (H264SwDecNextPicture(mHandle, &decodedPicture, 0)
1740c1bc742181ded4930842b46e9507372f0b1b963James Dong                        == H264SWDEC_PIC_RDY) {
1750c1bc742181ded4930842b46e9507372f0b1b963James Dong
1760c1bc742181ded4930842b46e9507372f0b1b963James Dong                        // Save this output buffer; otherwise, it will be
1770c1bc742181ded4930842b46e9507372f0b1b963James Dong                        // lost during dynamic port reconfiguration because
1780c1bc742181ded4930842b46e9507372f0b1b963James Dong                        // OpenMAX client will delete _all_ output buffers
1790c1bc742181ded4930842b46e9507372f0b1b963James Dong                        // in the process.
1800c1bc742181ded4930842b46e9507372f0b1b963James Dong                        saveFirstOutputBuffer(
1810c1bc742181ded4930842b46e9507372f0b1b963James Dong                            decodedPicture.picId,
1820c1bc742181ded4930842b46e9507372f0b1b963James Dong                            (uint8_t *)decodedPicture.pOutputPicture);
1830c1bc742181ded4930842b46e9507372f0b1b963James Dong                    }
1840c1bc742181ded4930842b46e9507372f0b1b963James Dong                }
1850c1bc742181ded4930842b46e9507372f0b1b963James Dong                inPicture.dataLen = 0;
1860c1bc742181ded4930842b46e9507372f0b1b963James Dong                if (ret < 0) {
18729357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block                    ALOGE("Decoder failed: %d", ret);
1882961a85f5f00343c115ac8e5dc17de631694fb6eAndreas Huber
1892961a85f5f00343c115ac8e5dc17de631694fb6eAndreas Huber                    notify(OMX_EventError, OMX_ErrorUndefined,
1902961a85f5f00343c115ac8e5dc17de631694fb6eAndreas Huber                           ERROR_MALFORMED, NULL);
1912961a85f5f00343c115ac8e5dc17de631694fb6eAndreas Huber
1922961a85f5f00343c115ac8e5dc17de631694fb6eAndreas Huber                    mSignalledError = true;
1932961a85f5f00343c115ac8e5dc17de631694fb6eAndreas Huber                    return;
1940c1bc742181ded4930842b46e9507372f0b1b963James Dong                }
1950c1bc742181ded4930842b46e9507372f0b1b963James Dong            }
1960c1bc742181ded4930842b46e9507372f0b1b963James Dong        }
1970c1bc742181ded4930842b46e9507372f0b1b963James Dong        inInfo->mOwnedByUs = false;
1980c1bc742181ded4930842b46e9507372f0b1b963James Dong        notifyEmptyBufferDone(inHeader);
1990c1bc742181ded4930842b46e9507372f0b1b963James Dong
200bf220f3e6e799f28d1599c3c5106e9e15631a91dRonghua Wu        if (portWillReset) {
2010c1bc742181ded4930842b46e9507372f0b1b963James Dong            return;
2020c1bc742181ded4930842b46e9507372f0b1b963James Dong        }
2030c1bc742181ded4930842b46e9507372f0b1b963James Dong
2040c1bc742181ded4930842b46e9507372f0b1b963James Dong        if (mFirstPicture && !outQueue.empty()) {
2053a3c3f7fc658ef874f82e46857ad9df3616aac95Wonsik Kim            if (!drainOneOutputBuffer(mFirstPictureId, mFirstPicture)) {
2063a3c3f7fc658ef874f82e46857ad9df3616aac95Wonsik Kim                ALOGE("Drain failed");
2073a3c3f7fc658ef874f82e46857ad9df3616aac95Wonsik Kim                notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL);
2083a3c3f7fc658ef874f82e46857ad9df3616aac95Wonsik Kim                mSignalledError = true;
2093a3c3f7fc658ef874f82e46857ad9df3616aac95Wonsik Kim                return;
2103a3c3f7fc658ef874f82e46857ad9df3616aac95Wonsik Kim            }
2110c1bc742181ded4930842b46e9507372f0b1b963James Dong            delete[] mFirstPicture;
2120c1bc742181ded4930842b46e9507372f0b1b963James Dong            mFirstPicture = NULL;
2130c1bc742181ded4930842b46e9507372f0b1b963James Dong            mFirstPictureId = -1;
2140c1bc742181ded4930842b46e9507372f0b1b963James Dong        }
2150c1bc742181ded4930842b46e9507372f0b1b963James Dong
2162309d1a1ff016a31d9aa68272bcb471e64a26cfaAndreas Huber        drainAllOutputBuffers(false /* eos */);
2170c1bc742181ded4930842b46e9507372f0b1b963James Dong    }
2180c1bc742181ded4930842b46e9507372f0b1b963James Dong}
2190c1bc742181ded4930842b46e9507372f0b1b963James Dong
220d5a2f55034022f2d0425fa0701894d0c4787b726Ronghua WuSoftVideoDecoderOMXComponent::CropSettingsMode SoftAVC::handleCropParams(
221d5a2f55034022f2d0425fa0701894d0c4787b726Ronghua Wu        const H264SwDecInfo& decInfo) {
222bf220f3e6e799f28d1599c3c5106e9e15631a91dRonghua Wu    if (!decInfo.croppingFlag) {
223d5a2f55034022f2d0425fa0701894d0c4787b726Ronghua Wu        return kCropUnSet;
2240c1bc742181ded4930842b46e9507372f0b1b963James Dong    }
2250c1bc742181ded4930842b46e9507372f0b1b963James Dong
226bf220f3e6e799f28d1599c3c5106e9e15631a91dRonghua Wu    const CropParams& crop = decInfo.cropParams;
227bf220f3e6e799f28d1599c3c5106e9e15631a91dRonghua Wu    if (mCropLeft == crop.cropLeftOffset &&
228bf220f3e6e799f28d1599c3c5106e9e15631a91dRonghua Wu        mCropTop == crop.cropTopOffset &&
229bf220f3e6e799f28d1599c3c5106e9e15631a91dRonghua Wu        mCropWidth == crop.cropOutWidth &&
230bf220f3e6e799f28d1599c3c5106e9e15631a91dRonghua Wu        mCropHeight == crop.cropOutHeight) {
231d5a2f55034022f2d0425fa0701894d0c4787b726Ronghua Wu        return kCropSet;
2320c1bc742181ded4930842b46e9507372f0b1b963James Dong    }
233bf220f3e6e799f28d1599c3c5106e9e15631a91dRonghua Wu
234bf220f3e6e799f28d1599c3c5106e9e15631a91dRonghua Wu    mCropLeft = crop.cropLeftOffset;
235bf220f3e6e799f28d1599c3c5106e9e15631a91dRonghua Wu    mCropTop = crop.cropTopOffset;
236bf220f3e6e799f28d1599c3c5106e9e15631a91dRonghua Wu    mCropWidth = crop.cropOutWidth;
237bf220f3e6e799f28d1599c3c5106e9e15631a91dRonghua Wu    mCropHeight = crop.cropOutHeight;
238d5a2f55034022f2d0425fa0701894d0c4787b726Ronghua Wu    return kCropChanged;
2390c1bc742181ded4930842b46e9507372f0b1b963James Dong}
2400c1bc742181ded4930842b46e9507372f0b1b963James Dong
2410c1bc742181ded4930842b46e9507372f0b1b963James Dongvoid SoftAVC::saveFirstOutputBuffer(int32_t picId, uint8_t *data) {
2420c1bc742181ded4930842b46e9507372f0b1b963James Dong    CHECK(mFirstPicture == NULL);
2430c1bc742181ded4930842b46e9507372f0b1b963James Dong    mFirstPictureId = picId;
2440c1bc742181ded4930842b46e9507372f0b1b963James Dong
245bf220f3e6e799f28d1599c3c5106e9e15631a91dRonghua Wu    uint32_t pictureSize = mWidth * mHeight * 3 / 2;
246bf220f3e6e799f28d1599c3c5106e9e15631a91dRonghua Wu    mFirstPicture = new uint8_t[pictureSize];
247bf220f3e6e799f28d1599c3c5106e9e15631a91dRonghua Wu    memcpy(mFirstPicture, data, pictureSize);
2480c1bc742181ded4930842b46e9507372f0b1b963James Dong}
2490c1bc742181ded4930842b46e9507372f0b1b963James Dong
2503a3c3f7fc658ef874f82e46857ad9df3616aac95Wonsik Kimbool SoftAVC::drainOneOutputBuffer(int32_t picId, uint8_t* data) {
2510c1bc742181ded4930842b46e9507372f0b1b963James Dong    List<BufferInfo *> &outQueue = getPortQueue(kOutputPortIndex);
2520c1bc742181ded4930842b46e9507372f0b1b963James Dong    BufferInfo *outInfo = *outQueue.begin();
2530c1bc742181ded4930842b46e9507372f0b1b963James Dong    OMX_BUFFERHEADERTYPE *outHeader = outInfo->mHeader;
2543a3c3f7fc658ef874f82e46857ad9df3616aac95Wonsik Kim    OMX_U32 frameSize = mWidth * mHeight * 3 / 2;
2553a3c3f7fc658ef874f82e46857ad9df3616aac95Wonsik Kim    if (outHeader->nAllocLen - outHeader->nOffset < frameSize) {
2563a3c3f7fc658ef874f82e46857ad9df3616aac95Wonsik Kim        android_errorWriteLog(0x534e4554, "27833616");
2573a3c3f7fc658ef874f82e46857ad9df3616aac95Wonsik Kim        return false;
2583a3c3f7fc658ef874f82e46857ad9df3616aac95Wonsik Kim    }
2593a3c3f7fc658ef874f82e46857ad9df3616aac95Wonsik Kim    outQueue.erase(outQueue.begin());
2600c1bc742181ded4930842b46e9507372f0b1b963James Dong    OMX_BUFFERHEADERTYPE *header = mPicToHeaderMap.valueFor(picId);
2610c1bc742181ded4930842b46e9507372f0b1b963James Dong    outHeader->nTimeStamp = header->nTimeStamp;
2620c1bc742181ded4930842b46e9507372f0b1b963James Dong    outHeader->nFlags = header->nFlags;
2633a3c3f7fc658ef874f82e46857ad9df3616aac95Wonsik Kim    outHeader->nFilledLen = frameSize;
264bf220f3e6e799f28d1599c3c5106e9e15631a91dRonghua Wu
265bf220f3e6e799f28d1599c3c5106e9e15631a91dRonghua Wu    uint8_t *dst = outHeader->pBuffer + outHeader->nOffset;
266bf220f3e6e799f28d1599c3c5106e9e15631a91dRonghua Wu    const uint8_t *srcY = data;
267bf220f3e6e799f28d1599c3c5106e9e15631a91dRonghua Wu    const uint8_t *srcU = srcY + mWidth * mHeight;
268bf220f3e6e799f28d1599c3c5106e9e15631a91dRonghua Wu    const uint8_t *srcV = srcU + mWidth * mHeight / 4;
269bf220f3e6e799f28d1599c3c5106e9e15631a91dRonghua Wu    size_t srcYStride = mWidth;
270bf220f3e6e799f28d1599c3c5106e9e15631a91dRonghua Wu    size_t srcUStride = mWidth / 2;
271bf220f3e6e799f28d1599c3c5106e9e15631a91dRonghua Wu    size_t srcVStride = srcUStride;
272bf220f3e6e799f28d1599c3c5106e9e15631a91dRonghua Wu    copyYV12FrameToOutputBuffer(dst, srcY, srcU, srcV, srcYStride, srcUStride, srcVStride);
273bf220f3e6e799f28d1599c3c5106e9e15631a91dRonghua Wu
2740c1bc742181ded4930842b46e9507372f0b1b963James Dong    mPicToHeaderMap.removeItem(picId);
2750c1bc742181ded4930842b46e9507372f0b1b963James Dong    delete header;
2760c1bc742181ded4930842b46e9507372f0b1b963James Dong    outInfo->mOwnedByUs = false;
2770c1bc742181ded4930842b46e9507372f0b1b963James Dong    notifyFillBufferDone(outHeader);
2783a3c3f7fc658ef874f82e46857ad9df3616aac95Wonsik Kim    return true;
2790c1bc742181ded4930842b46e9507372f0b1b963James Dong}
2800c1bc742181ded4930842b46e9507372f0b1b963James Dong
2812309d1a1ff016a31d9aa68272bcb471e64a26cfaAndreas Hubervoid SoftAVC::drainAllOutputBuffers(bool eos) {
2820c1bc742181ded4930842b46e9507372f0b1b963James Dong    List<BufferInfo *> &outQueue = getPortQueue(kOutputPortIndex);
2830c1bc742181ded4930842b46e9507372f0b1b963James Dong    H264SwDecPicture decodedPicture;
2840c1bc742181ded4930842b46e9507372f0b1b963James Dong
2852309d1a1ff016a31d9aa68272bcb471e64a26cfaAndreas Huber    if (mHeadersDecoded) {
2862309d1a1ff016a31d9aa68272bcb471e64a26cfaAndreas Huber        while (!outQueue.empty()
2872309d1a1ff016a31d9aa68272bcb471e64a26cfaAndreas Huber                && H264SWDEC_PIC_RDY == H264SwDecNextPicture(
2882309d1a1ff016a31d9aa68272bcb471e64a26cfaAndreas Huber                    mHandle, &decodedPicture, eos /* flush */)) {
2892309d1a1ff016a31d9aa68272bcb471e64a26cfaAndreas Huber            int32_t picId = decodedPicture.picId;
2902309d1a1ff016a31d9aa68272bcb471e64a26cfaAndreas Huber            uint8_t *data = (uint8_t *) decodedPicture.pOutputPicture;
2913a3c3f7fc658ef874f82e46857ad9df3616aac95Wonsik Kim            if (!drainOneOutputBuffer(picId, data)) {
2923a3c3f7fc658ef874f82e46857ad9df3616aac95Wonsik Kim                ALOGE("Drain failed");
2933a3c3f7fc658ef874f82e46857ad9df3616aac95Wonsik Kim                notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL);
2943a3c3f7fc658ef874f82e46857ad9df3616aac95Wonsik Kim                mSignalledError = true;
2953a3c3f7fc658ef874f82e46857ad9df3616aac95Wonsik Kim                return;
2963a3c3f7fc658ef874f82e46857ad9df3616aac95Wonsik Kim            }
2972309d1a1ff016a31d9aa68272bcb471e64a26cfaAndreas Huber        }
2982309d1a1ff016a31d9aa68272bcb471e64a26cfaAndreas Huber    }
2992309d1a1ff016a31d9aa68272bcb471e64a26cfaAndreas Huber
3002309d1a1ff016a31d9aa68272bcb471e64a26cfaAndreas Huber    if (!eos) {
3012309d1a1ff016a31d9aa68272bcb471e64a26cfaAndreas Huber        return;
3022309d1a1ff016a31d9aa68272bcb471e64a26cfaAndreas Huber    }
3032309d1a1ff016a31d9aa68272bcb471e64a26cfaAndreas Huber
3040c1bc742181ded4930842b46e9507372f0b1b963James Dong    while (!outQueue.empty()) {
3050c1bc742181ded4930842b46e9507372f0b1b963James Dong        BufferInfo *outInfo = *outQueue.begin();
3060c1bc742181ded4930842b46e9507372f0b1b963James Dong        outQueue.erase(outQueue.begin());
3070c1bc742181ded4930842b46e9507372f0b1b963James Dong        OMX_BUFFERHEADERTYPE *outHeader = outInfo->mHeader;
3080c1bc742181ded4930842b46e9507372f0b1b963James Dong
3092309d1a1ff016a31d9aa68272bcb471e64a26cfaAndreas Huber        outHeader->nTimeStamp = 0;
3102309d1a1ff016a31d9aa68272bcb471e64a26cfaAndreas Huber        outHeader->nFilledLen = 0;
3112309d1a1ff016a31d9aa68272bcb471e64a26cfaAndreas Huber        outHeader->nFlags = OMX_BUFFERFLAG_EOS;
3120c1bc742181ded4930842b46e9507372f0b1b963James Dong
3130c1bc742181ded4930842b46e9507372f0b1b963James Dong        outInfo->mOwnedByUs = false;
3140c1bc742181ded4930842b46e9507372f0b1b963James Dong        notifyFillBufferDone(outHeader);
3150c1bc742181ded4930842b46e9507372f0b1b963James Dong
3162309d1a1ff016a31d9aa68272bcb471e64a26cfaAndreas Huber        mEOSStatus = OUTPUT_FRAMES_FLUSHED;
3172309d1a1ff016a31d9aa68272bcb471e64a26cfaAndreas Huber    }
3180c1bc742181ded4930842b46e9507372f0b1b963James Dong}
3190c1bc742181ded4930842b46e9507372f0b1b963James Dong
3200c1bc742181ded4930842b46e9507372f0b1b963James Dongvoid SoftAVC::onPortFlushCompleted(OMX_U32 portIndex) {
3210c1bc742181ded4930842b46e9507372f0b1b963James Dong    if (portIndex == kInputPortIndex) {
3220c1bc742181ded4930842b46e9507372f0b1b963James Dong        mEOSStatus = INPUT_DATA_AVAILABLE;
3230c1bc742181ded4930842b46e9507372f0b1b963James Dong    }
3240c1bc742181ded4930842b46e9507372f0b1b963James Dong}
3250c1bc742181ded4930842b46e9507372f0b1b963James Dong
326d94e716af0e49d775f0c0c4f36dd2c136ba5f2b2Andreas Hubervoid SoftAVC::onReset() {
3277f616d3cc5366a4b8af20d3d0c768e3de1df0666Lajos Molnar    SoftVideoDecoderOMXComponent::onReset();
328d94e716af0e49d775f0c0c4f36dd2c136ba5f2b2Andreas Huber    mSignalledError = false;
3290c1bc742181ded4930842b46e9507372f0b1b963James Dong}
3300c1bc742181ded4930842b46e9507372f0b1b963James Dong
3310c1bc742181ded4930842b46e9507372f0b1b963James Dong}  // namespace android
3320c1bc742181ded4930842b46e9507372f0b1b963James Dong
3330c1bc742181ded4930842b46e9507372f0b1b963James Dongandroid::SoftOMXComponent *createSoftOMXComponent(
3340c1bc742181ded4930842b46e9507372f0b1b963James Dong        const char *name, const OMX_CALLBACKTYPE *callbacks,
3350c1bc742181ded4930842b46e9507372f0b1b963James Dong        OMX_PTR appData, OMX_COMPONENTTYPE **component) {
3360c1bc742181ded4930842b46e9507372f0b1b963James Dong    return new android::SoftAVC(name, callbacks, appData, component);
3370c1bc742181ded4930842b46e9507372f0b1b963James Dong}
338