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()) {
2050c1bc742181ded4930842b46e9507372f0b1b963James Dong            drainOneOutputBuffer(mFirstPictureId, mFirstPicture);
2060c1bc742181ded4930842b46e9507372f0b1b963James Dong            delete[] mFirstPicture;
2070c1bc742181ded4930842b46e9507372f0b1b963James Dong            mFirstPicture = NULL;
2080c1bc742181ded4930842b46e9507372f0b1b963James Dong            mFirstPictureId = -1;
2090c1bc742181ded4930842b46e9507372f0b1b963James Dong        }
2100c1bc742181ded4930842b46e9507372f0b1b963James Dong
2112309d1a1ff016a31d9aa68272bcb471e64a26cfaAndreas Huber        drainAllOutputBuffers(false /* eos */);
2120c1bc742181ded4930842b46e9507372f0b1b963James Dong    }
2130c1bc742181ded4930842b46e9507372f0b1b963James Dong}
2140c1bc742181ded4930842b46e9507372f0b1b963James Dong
215d5a2f55034022f2d0425fa0701894d0c4787b726Ronghua WuSoftVideoDecoderOMXComponent::CropSettingsMode SoftAVC::handleCropParams(
216d5a2f55034022f2d0425fa0701894d0c4787b726Ronghua Wu        const H264SwDecInfo& decInfo) {
217bf220f3e6e799f28d1599c3c5106e9e15631a91dRonghua Wu    if (!decInfo.croppingFlag) {
218d5a2f55034022f2d0425fa0701894d0c4787b726Ronghua Wu        return kCropUnSet;
2190c1bc742181ded4930842b46e9507372f0b1b963James Dong    }
2200c1bc742181ded4930842b46e9507372f0b1b963James Dong
221bf220f3e6e799f28d1599c3c5106e9e15631a91dRonghua Wu    const CropParams& crop = decInfo.cropParams;
222bf220f3e6e799f28d1599c3c5106e9e15631a91dRonghua Wu    if (mCropLeft == crop.cropLeftOffset &&
223bf220f3e6e799f28d1599c3c5106e9e15631a91dRonghua Wu        mCropTop == crop.cropTopOffset &&
224bf220f3e6e799f28d1599c3c5106e9e15631a91dRonghua Wu        mCropWidth == crop.cropOutWidth &&
225bf220f3e6e799f28d1599c3c5106e9e15631a91dRonghua Wu        mCropHeight == crop.cropOutHeight) {
226d5a2f55034022f2d0425fa0701894d0c4787b726Ronghua Wu        return kCropSet;
2270c1bc742181ded4930842b46e9507372f0b1b963James Dong    }
228bf220f3e6e799f28d1599c3c5106e9e15631a91dRonghua Wu
229bf220f3e6e799f28d1599c3c5106e9e15631a91dRonghua Wu    mCropLeft = crop.cropLeftOffset;
230bf220f3e6e799f28d1599c3c5106e9e15631a91dRonghua Wu    mCropTop = crop.cropTopOffset;
231bf220f3e6e799f28d1599c3c5106e9e15631a91dRonghua Wu    mCropWidth = crop.cropOutWidth;
232bf220f3e6e799f28d1599c3c5106e9e15631a91dRonghua Wu    mCropHeight = crop.cropOutHeight;
233d5a2f55034022f2d0425fa0701894d0c4787b726Ronghua Wu    return kCropChanged;
2340c1bc742181ded4930842b46e9507372f0b1b963James Dong}
2350c1bc742181ded4930842b46e9507372f0b1b963James Dong
2360c1bc742181ded4930842b46e9507372f0b1b963James Dongvoid SoftAVC::saveFirstOutputBuffer(int32_t picId, uint8_t *data) {
2370c1bc742181ded4930842b46e9507372f0b1b963James Dong    CHECK(mFirstPicture == NULL);
2380c1bc742181ded4930842b46e9507372f0b1b963James Dong    mFirstPictureId = picId;
2390c1bc742181ded4930842b46e9507372f0b1b963James Dong
240bf220f3e6e799f28d1599c3c5106e9e15631a91dRonghua Wu    uint32_t pictureSize = mWidth * mHeight * 3 / 2;
241bf220f3e6e799f28d1599c3c5106e9e15631a91dRonghua Wu    mFirstPicture = new uint8_t[pictureSize];
242bf220f3e6e799f28d1599c3c5106e9e15631a91dRonghua Wu    memcpy(mFirstPicture, data, pictureSize);
2430c1bc742181ded4930842b46e9507372f0b1b963James Dong}
2440c1bc742181ded4930842b46e9507372f0b1b963James Dong
2450c1bc742181ded4930842b46e9507372f0b1b963James Dongvoid SoftAVC::drainOneOutputBuffer(int32_t picId, uint8_t* data) {
2460c1bc742181ded4930842b46e9507372f0b1b963James Dong    List<BufferInfo *> &outQueue = getPortQueue(kOutputPortIndex);
2470c1bc742181ded4930842b46e9507372f0b1b963James Dong    BufferInfo *outInfo = *outQueue.begin();
2480c1bc742181ded4930842b46e9507372f0b1b963James Dong    outQueue.erase(outQueue.begin());
2490c1bc742181ded4930842b46e9507372f0b1b963James Dong    OMX_BUFFERHEADERTYPE *outHeader = outInfo->mHeader;
2500c1bc742181ded4930842b46e9507372f0b1b963James Dong    OMX_BUFFERHEADERTYPE *header = mPicToHeaderMap.valueFor(picId);
2510c1bc742181ded4930842b46e9507372f0b1b963James Dong    outHeader->nTimeStamp = header->nTimeStamp;
2520c1bc742181ded4930842b46e9507372f0b1b963James Dong    outHeader->nFlags = header->nFlags;
253bf220f3e6e799f28d1599c3c5106e9e15631a91dRonghua Wu    outHeader->nFilledLen = mWidth * mHeight * 3 / 2;
254bf220f3e6e799f28d1599c3c5106e9e15631a91dRonghua Wu
255bf220f3e6e799f28d1599c3c5106e9e15631a91dRonghua Wu    uint8_t *dst = outHeader->pBuffer + outHeader->nOffset;
256bf220f3e6e799f28d1599c3c5106e9e15631a91dRonghua Wu    const uint8_t *srcY = data;
257bf220f3e6e799f28d1599c3c5106e9e15631a91dRonghua Wu    const uint8_t *srcU = srcY + mWidth * mHeight;
258bf220f3e6e799f28d1599c3c5106e9e15631a91dRonghua Wu    const uint8_t *srcV = srcU + mWidth * mHeight / 4;
259bf220f3e6e799f28d1599c3c5106e9e15631a91dRonghua Wu    size_t srcYStride = mWidth;
260bf220f3e6e799f28d1599c3c5106e9e15631a91dRonghua Wu    size_t srcUStride = mWidth / 2;
261bf220f3e6e799f28d1599c3c5106e9e15631a91dRonghua Wu    size_t srcVStride = srcUStride;
262bf220f3e6e799f28d1599c3c5106e9e15631a91dRonghua Wu    copyYV12FrameToOutputBuffer(dst, srcY, srcU, srcV, srcYStride, srcUStride, srcVStride);
263bf220f3e6e799f28d1599c3c5106e9e15631a91dRonghua Wu
2640c1bc742181ded4930842b46e9507372f0b1b963James Dong    mPicToHeaderMap.removeItem(picId);
2650c1bc742181ded4930842b46e9507372f0b1b963James Dong    delete header;
2660c1bc742181ded4930842b46e9507372f0b1b963James Dong    outInfo->mOwnedByUs = false;
2670c1bc742181ded4930842b46e9507372f0b1b963James Dong    notifyFillBufferDone(outHeader);
2680c1bc742181ded4930842b46e9507372f0b1b963James Dong}
2690c1bc742181ded4930842b46e9507372f0b1b963James Dong
2702309d1a1ff016a31d9aa68272bcb471e64a26cfaAndreas Hubervoid SoftAVC::drainAllOutputBuffers(bool eos) {
2710c1bc742181ded4930842b46e9507372f0b1b963James Dong    List<BufferInfo *> &outQueue = getPortQueue(kOutputPortIndex);
2720c1bc742181ded4930842b46e9507372f0b1b963James Dong    H264SwDecPicture decodedPicture;
2730c1bc742181ded4930842b46e9507372f0b1b963James Dong
2742309d1a1ff016a31d9aa68272bcb471e64a26cfaAndreas Huber    if (mHeadersDecoded) {
2752309d1a1ff016a31d9aa68272bcb471e64a26cfaAndreas Huber        while (!outQueue.empty()
2762309d1a1ff016a31d9aa68272bcb471e64a26cfaAndreas Huber                && H264SWDEC_PIC_RDY == H264SwDecNextPicture(
2772309d1a1ff016a31d9aa68272bcb471e64a26cfaAndreas Huber                    mHandle, &decodedPicture, eos /* flush */)) {
2782309d1a1ff016a31d9aa68272bcb471e64a26cfaAndreas Huber            int32_t picId = decodedPicture.picId;
2792309d1a1ff016a31d9aa68272bcb471e64a26cfaAndreas Huber            uint8_t *data = (uint8_t *) decodedPicture.pOutputPicture;
2802309d1a1ff016a31d9aa68272bcb471e64a26cfaAndreas Huber            drainOneOutputBuffer(picId, data);
2812309d1a1ff016a31d9aa68272bcb471e64a26cfaAndreas Huber        }
2822309d1a1ff016a31d9aa68272bcb471e64a26cfaAndreas Huber    }
2832309d1a1ff016a31d9aa68272bcb471e64a26cfaAndreas Huber
2842309d1a1ff016a31d9aa68272bcb471e64a26cfaAndreas Huber    if (!eos) {
2852309d1a1ff016a31d9aa68272bcb471e64a26cfaAndreas Huber        return;
2862309d1a1ff016a31d9aa68272bcb471e64a26cfaAndreas Huber    }
2872309d1a1ff016a31d9aa68272bcb471e64a26cfaAndreas Huber
2880c1bc742181ded4930842b46e9507372f0b1b963James Dong    while (!outQueue.empty()) {
2890c1bc742181ded4930842b46e9507372f0b1b963James Dong        BufferInfo *outInfo = *outQueue.begin();
2900c1bc742181ded4930842b46e9507372f0b1b963James Dong        outQueue.erase(outQueue.begin());
2910c1bc742181ded4930842b46e9507372f0b1b963James Dong        OMX_BUFFERHEADERTYPE *outHeader = outInfo->mHeader;
2920c1bc742181ded4930842b46e9507372f0b1b963James Dong
2932309d1a1ff016a31d9aa68272bcb471e64a26cfaAndreas Huber        outHeader->nTimeStamp = 0;
2942309d1a1ff016a31d9aa68272bcb471e64a26cfaAndreas Huber        outHeader->nFilledLen = 0;
2952309d1a1ff016a31d9aa68272bcb471e64a26cfaAndreas Huber        outHeader->nFlags = OMX_BUFFERFLAG_EOS;
2960c1bc742181ded4930842b46e9507372f0b1b963James Dong
2970c1bc742181ded4930842b46e9507372f0b1b963James Dong        outInfo->mOwnedByUs = false;
2980c1bc742181ded4930842b46e9507372f0b1b963James Dong        notifyFillBufferDone(outHeader);
2990c1bc742181ded4930842b46e9507372f0b1b963James Dong
3002309d1a1ff016a31d9aa68272bcb471e64a26cfaAndreas Huber        mEOSStatus = OUTPUT_FRAMES_FLUSHED;
3012309d1a1ff016a31d9aa68272bcb471e64a26cfaAndreas Huber    }
3020c1bc742181ded4930842b46e9507372f0b1b963James Dong}
3030c1bc742181ded4930842b46e9507372f0b1b963James Dong
3040c1bc742181ded4930842b46e9507372f0b1b963James Dongvoid SoftAVC::onPortFlushCompleted(OMX_U32 portIndex) {
3050c1bc742181ded4930842b46e9507372f0b1b963James Dong    if (portIndex == kInputPortIndex) {
3060c1bc742181ded4930842b46e9507372f0b1b963James Dong        mEOSStatus = INPUT_DATA_AVAILABLE;
3070c1bc742181ded4930842b46e9507372f0b1b963James Dong    }
3080c1bc742181ded4930842b46e9507372f0b1b963James Dong}
3090c1bc742181ded4930842b46e9507372f0b1b963James Dong
310d94e716af0e49d775f0c0c4f36dd2c136ba5f2b2Andreas Hubervoid SoftAVC::onReset() {
3117f616d3cc5366a4b8af20d3d0c768e3de1df0666Lajos Molnar    SoftVideoDecoderOMXComponent::onReset();
312d94e716af0e49d775f0c0c4f36dd2c136ba5f2b2Andreas Huber    mSignalledError = false;
3130c1bc742181ded4930842b46e9507372f0b1b963James Dong}
3140c1bc742181ded4930842b46e9507372f0b1b963James Dong
3150c1bc742181ded4930842b46e9507372f0b1b963James Dong}  // namespace android
3160c1bc742181ded4930842b46e9507372f0b1b963James Dong
3170c1bc742181ded4930842b46e9507372f0b1b963James Dongandroid::SoftOMXComponent *createSoftOMXComponent(
3180c1bc742181ded4930842b46e9507372f0b1b963James Dong        const char *name, const OMX_CALLBACKTYPE *callbacks,
3190c1bc742181ded4930842b46e9507372f0b1b963James Dong        OMX_PTR appData, OMX_COMPONENTTYPE **component) {
3200c1bc742181ded4930842b46e9507372f0b1b963James Dong    return new android::SoftAVC(name, callbacks, appData, component);
3210c1bc742181ded4930842b46e9507372f0b1b963James Dong}
322