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      mPictureSize(mWidth * mHeight * 3 / 2),
620c1bc742181ded4930842b46e9507372f0b1b963James Dong      mFirstPicture(NULL),
630c1bc742181ded4930842b46e9507372f0b1b963James Dong      mFirstPictureId(-1),
640c1bc742181ded4930842b46e9507372f0b1b963James Dong      mPicId(0),
650c1bc742181ded4930842b46e9507372f0b1b963James Dong      mHeadersDecoded(false),
660c1bc742181ded4930842b46e9507372f0b1b963James Dong      mEOSStatus(INPUT_DATA_AVAILABLE),
672961a85f5f00343c115ac8e5dc17de631694fb6eAndreas Huber      mSignalledError(false) {
687f616d3cc5366a4b8af20d3d0c768e3de1df0666Lajos Molnar    initPorts(
697f616d3cc5366a4b8af20d3d0c768e3de1df0666Lajos Molnar            kNumInputBuffers, 8192 /* inputBufferSize */,
707f616d3cc5366a4b8af20d3d0c768e3de1df0666Lajos Molnar            kNumOutputBuffers, MEDIA_MIMETYPE_VIDEO_AVC);
717f616d3cc5366a4b8af20d3d0c768e3de1df0666Lajos Molnar
720c1bc742181ded4930842b46e9507372f0b1b963James Dong    CHECK_EQ(initDecoder(), (status_t)OK);
730c1bc742181ded4930842b46e9507372f0b1b963James Dong}
740c1bc742181ded4930842b46e9507372f0b1b963James Dong
750c1bc742181ded4930842b46e9507372f0b1b963James DongSoftAVC::~SoftAVC() {
760c1bc742181ded4930842b46e9507372f0b1b963James Dong    H264SwDecRelease(mHandle);
770c1bc742181ded4930842b46e9507372f0b1b963James Dong    mHandle = NULL;
780c1bc742181ded4930842b46e9507372f0b1b963James Dong
790c1bc742181ded4930842b46e9507372f0b1b963James Dong    while (mPicToHeaderMap.size() != 0) {
800c1bc742181ded4930842b46e9507372f0b1b963James Dong        OMX_BUFFERHEADERTYPE *header = mPicToHeaderMap.editValueAt(0);
810c1bc742181ded4930842b46e9507372f0b1b963James Dong        mPicToHeaderMap.removeItemsAt(0);
820c1bc742181ded4930842b46e9507372f0b1b963James Dong        delete header;
830c1bc742181ded4930842b46e9507372f0b1b963James Dong        header = NULL;
840c1bc742181ded4930842b46e9507372f0b1b963James Dong    }
850c1bc742181ded4930842b46e9507372f0b1b963James Dong    List<BufferInfo *> &outQueue = getPortQueue(kOutputPortIndex);
860c1bc742181ded4930842b46e9507372f0b1b963James Dong    List<BufferInfo *> &inQueue = getPortQueue(kInputPortIndex);
870c1bc742181ded4930842b46e9507372f0b1b963James Dong    CHECK(outQueue.empty());
880c1bc742181ded4930842b46e9507372f0b1b963James Dong    CHECK(inQueue.empty());
890c1bc742181ded4930842b46e9507372f0b1b963James Dong
900c1bc742181ded4930842b46e9507372f0b1b963James Dong    delete[] mFirstPicture;
910c1bc742181ded4930842b46e9507372f0b1b963James Dong}
920c1bc742181ded4930842b46e9507372f0b1b963James Dong
930c1bc742181ded4930842b46e9507372f0b1b963James Dongstatus_t SoftAVC::initDecoder() {
94486247017e0bfb9db9994a53a28c0dacfebf8567James Dong    // Force decoder to output buffers in display order.
95486247017e0bfb9db9994a53a28c0dacfebf8567James Dong    if (H264SwDecInit(&mHandle, 0) == H264SWDEC_OK) {
960c1bc742181ded4930842b46e9507372f0b1b963James Dong        return OK;
970c1bc742181ded4930842b46e9507372f0b1b963James Dong    }
980c1bc742181ded4930842b46e9507372f0b1b963James Dong    return UNKNOWN_ERROR;
990c1bc742181ded4930842b46e9507372f0b1b963James Dong}
1000c1bc742181ded4930842b46e9507372f0b1b963James Dong
1010c1bc742181ded4930842b46e9507372f0b1b963James Dongvoid SoftAVC::onQueueFilled(OMX_U32 portIndex) {
1022961a85f5f00343c115ac8e5dc17de631694fb6eAndreas Huber    if (mSignalledError || mOutputPortSettingsChange != NONE) {
1030c1bc742181ded4930842b46e9507372f0b1b963James Dong        return;
1040c1bc742181ded4930842b46e9507372f0b1b963James Dong    }
1050c1bc742181ded4930842b46e9507372f0b1b963James Dong
1060c1bc742181ded4930842b46e9507372f0b1b963James Dong    if (mEOSStatus == OUTPUT_FRAMES_FLUSHED) {
1070c1bc742181ded4930842b46e9507372f0b1b963James Dong        return;
1080c1bc742181ded4930842b46e9507372f0b1b963James Dong    }
1090c1bc742181ded4930842b46e9507372f0b1b963James Dong
1100c1bc742181ded4930842b46e9507372f0b1b963James Dong    List<BufferInfo *> &inQueue = getPortQueue(kInputPortIndex);
1110c1bc742181ded4930842b46e9507372f0b1b963James Dong    List<BufferInfo *> &outQueue = getPortQueue(kOutputPortIndex);
1122309d1a1ff016a31d9aa68272bcb471e64a26cfaAndreas Huber
1132309d1a1ff016a31d9aa68272bcb471e64a26cfaAndreas Huber    if (mHeadersDecoded) {
1142309d1a1ff016a31d9aa68272bcb471e64a26cfaAndreas Huber        // Dequeue any already decoded output frames to free up space
1152309d1a1ff016a31d9aa68272bcb471e64a26cfaAndreas Huber        // in the output queue.
1162309d1a1ff016a31d9aa68272bcb471e64a26cfaAndreas Huber
1172309d1a1ff016a31d9aa68272bcb471e64a26cfaAndreas Huber        drainAllOutputBuffers(false /* eos */);
1182309d1a1ff016a31d9aa68272bcb471e64a26cfaAndreas Huber    }
1192309d1a1ff016a31d9aa68272bcb471e64a26cfaAndreas Huber
1200c1bc742181ded4930842b46e9507372f0b1b963James Dong    H264SwDecRet ret = H264SWDEC_PIC_RDY;
1210c1bc742181ded4930842b46e9507372f0b1b963James Dong    bool portSettingsChanged = false;
1220c1bc742181ded4930842b46e9507372f0b1b963James Dong    while ((mEOSStatus != INPUT_DATA_AVAILABLE || !inQueue.empty())
1230c1bc742181ded4930842b46e9507372f0b1b963James Dong            && outQueue.size() == kNumOutputBuffers) {
1240c1bc742181ded4930842b46e9507372f0b1b963James Dong
1250c1bc742181ded4930842b46e9507372f0b1b963James Dong        if (mEOSStatus == INPUT_EOS_SEEN) {
1262309d1a1ff016a31d9aa68272bcb471e64a26cfaAndreas Huber            drainAllOutputBuffers(true /* eos */);
1270c1bc742181ded4930842b46e9507372f0b1b963James Dong            return;
1280c1bc742181ded4930842b46e9507372f0b1b963James Dong        }
1290c1bc742181ded4930842b46e9507372f0b1b963James Dong
1300c1bc742181ded4930842b46e9507372f0b1b963James Dong        BufferInfo *inInfo = *inQueue.begin();
1310c1bc742181ded4930842b46e9507372f0b1b963James Dong        OMX_BUFFERHEADERTYPE *inHeader = inInfo->mHeader;
1320c1bc742181ded4930842b46e9507372f0b1b963James Dong        ++mPicId;
1330c1bc742181ded4930842b46e9507372f0b1b963James Dong
1340c1bc742181ded4930842b46e9507372f0b1b963James Dong        OMX_BUFFERHEADERTYPE *header = new OMX_BUFFERHEADERTYPE;
1350c1bc742181ded4930842b46e9507372f0b1b963James Dong        memset(header, 0, sizeof(OMX_BUFFERHEADERTYPE));
1360c1bc742181ded4930842b46e9507372f0b1b963James Dong        header->nTimeStamp = inHeader->nTimeStamp;
1370c1bc742181ded4930842b46e9507372f0b1b963James Dong        header->nFlags = inHeader->nFlags;
1384c44e9fed87ff6363393f2559b150291242da247Marco Nelissen        if (header->nFlags & OMX_BUFFERFLAG_EOS) {
1394c44e9fed87ff6363393f2559b150291242da247Marco Nelissen            mEOSStatus = INPUT_EOS_SEEN;
1404c44e9fed87ff6363393f2559b150291242da247Marco Nelissen        }
1410c1bc742181ded4930842b46e9507372f0b1b963James Dong        mPicToHeaderMap.add(mPicId, header);
1420c1bc742181ded4930842b46e9507372f0b1b963James Dong        inQueue.erase(inQueue.begin());
1430c1bc742181ded4930842b46e9507372f0b1b963James Dong
1440c1bc742181ded4930842b46e9507372f0b1b963James Dong        H264SwDecInput inPicture;
1450c1bc742181ded4930842b46e9507372f0b1b963James Dong        H264SwDecOutput outPicture;
1460c1bc742181ded4930842b46e9507372f0b1b963James Dong        memset(&inPicture, 0, sizeof(inPicture));
1470c1bc742181ded4930842b46e9507372f0b1b963James Dong        inPicture.dataLen = inHeader->nFilledLen;
1480c1bc742181ded4930842b46e9507372f0b1b963James Dong        inPicture.pStream = inHeader->pBuffer + inHeader->nOffset;
1490c1bc742181ded4930842b46e9507372f0b1b963James Dong        inPicture.picId = mPicId;
1500c1bc742181ded4930842b46e9507372f0b1b963James Dong        inPicture.intraConcealmentMethod = 1;
1510c1bc742181ded4930842b46e9507372f0b1b963James Dong        H264SwDecPicture decodedPicture;
1520c1bc742181ded4930842b46e9507372f0b1b963James Dong
1530c1bc742181ded4930842b46e9507372f0b1b963James Dong        while (inPicture.dataLen > 0) {
1540c1bc742181ded4930842b46e9507372f0b1b963James Dong            ret = H264SwDecDecode(mHandle, &inPicture, &outPicture);
1550c1bc742181ded4930842b46e9507372f0b1b963James Dong            if (ret == H264SWDEC_HDRS_RDY_BUFF_NOT_EMPTY ||
1560c1bc742181ded4930842b46e9507372f0b1b963James Dong                ret == H264SWDEC_PIC_RDY_BUFF_NOT_EMPTY) {
1570c1bc742181ded4930842b46e9507372f0b1b963James Dong                inPicture.dataLen -= (u32)(outPicture.pStrmCurrPos - inPicture.pStream);
1580c1bc742181ded4930842b46e9507372f0b1b963James Dong                inPicture.pStream = outPicture.pStrmCurrPos;
1590c1bc742181ded4930842b46e9507372f0b1b963James Dong                if (ret == H264SWDEC_HDRS_RDY_BUFF_NOT_EMPTY) {
1600c1bc742181ded4930842b46e9507372f0b1b963James Dong                    mHeadersDecoded = true;
1610c1bc742181ded4930842b46e9507372f0b1b963James Dong                    H264SwDecInfo decoderInfo;
1620c1bc742181ded4930842b46e9507372f0b1b963James Dong                    CHECK(H264SwDecGetInfo(mHandle, &decoderInfo) == H264SWDEC_OK);
1630c1bc742181ded4930842b46e9507372f0b1b963James Dong
1640c1bc742181ded4930842b46e9507372f0b1b963James Dong                    if (handlePortSettingChangeEvent(&decoderInfo)) {
1650c1bc742181ded4930842b46e9507372f0b1b963James Dong                        portSettingsChanged = true;
1660c1bc742181ded4930842b46e9507372f0b1b963James Dong                    }
1670c1bc742181ded4930842b46e9507372f0b1b963James Dong
1680c1bc742181ded4930842b46e9507372f0b1b963James Dong                    if (decoderInfo.croppingFlag &&
1690c1bc742181ded4930842b46e9507372f0b1b963James Dong                        handleCropRectEvent(&decoderInfo.cropParams)) {
1700c1bc742181ded4930842b46e9507372f0b1b963James Dong                        portSettingsChanged = true;
1710c1bc742181ded4930842b46e9507372f0b1b963James Dong                    }
1720c1bc742181ded4930842b46e9507372f0b1b963James Dong                }
1730c1bc742181ded4930842b46e9507372f0b1b963James Dong            } else {
1740c1bc742181ded4930842b46e9507372f0b1b963James Dong                if (portSettingsChanged) {
1750c1bc742181ded4930842b46e9507372f0b1b963James Dong                    if (H264SwDecNextPicture(mHandle, &decodedPicture, 0)
1760c1bc742181ded4930842b46e9507372f0b1b963James Dong                        == H264SWDEC_PIC_RDY) {
1770c1bc742181ded4930842b46e9507372f0b1b963James Dong
1780c1bc742181ded4930842b46e9507372f0b1b963James Dong                        // Save this output buffer; otherwise, it will be
1790c1bc742181ded4930842b46e9507372f0b1b963James Dong                        // lost during dynamic port reconfiguration because
1800c1bc742181ded4930842b46e9507372f0b1b963James Dong                        // OpenMAX client will delete _all_ output buffers
1810c1bc742181ded4930842b46e9507372f0b1b963James Dong                        // in the process.
1820c1bc742181ded4930842b46e9507372f0b1b963James Dong                        saveFirstOutputBuffer(
1830c1bc742181ded4930842b46e9507372f0b1b963James Dong                            decodedPicture.picId,
1840c1bc742181ded4930842b46e9507372f0b1b963James Dong                            (uint8_t *)decodedPicture.pOutputPicture);
1850c1bc742181ded4930842b46e9507372f0b1b963James Dong                    }
1860c1bc742181ded4930842b46e9507372f0b1b963James Dong                }
1870c1bc742181ded4930842b46e9507372f0b1b963James Dong                inPicture.dataLen = 0;
1880c1bc742181ded4930842b46e9507372f0b1b963James Dong                if (ret < 0) {
18929357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block                    ALOGE("Decoder failed: %d", ret);
1902961a85f5f00343c115ac8e5dc17de631694fb6eAndreas Huber
1912961a85f5f00343c115ac8e5dc17de631694fb6eAndreas Huber                    notify(OMX_EventError, OMX_ErrorUndefined,
1922961a85f5f00343c115ac8e5dc17de631694fb6eAndreas Huber                           ERROR_MALFORMED, NULL);
1932961a85f5f00343c115ac8e5dc17de631694fb6eAndreas Huber
1942961a85f5f00343c115ac8e5dc17de631694fb6eAndreas Huber                    mSignalledError = true;
1952961a85f5f00343c115ac8e5dc17de631694fb6eAndreas Huber                    return;
1960c1bc742181ded4930842b46e9507372f0b1b963James Dong                }
1970c1bc742181ded4930842b46e9507372f0b1b963James Dong            }
1980c1bc742181ded4930842b46e9507372f0b1b963James Dong        }
1990c1bc742181ded4930842b46e9507372f0b1b963James Dong        inInfo->mOwnedByUs = false;
2000c1bc742181ded4930842b46e9507372f0b1b963James Dong        notifyEmptyBufferDone(inHeader);
2010c1bc742181ded4930842b46e9507372f0b1b963James Dong
2020c1bc742181ded4930842b46e9507372f0b1b963James Dong        if (portSettingsChanged) {
2030c1bc742181ded4930842b46e9507372f0b1b963James Dong            portSettingsChanged = false;
2040c1bc742181ded4930842b46e9507372f0b1b963James Dong            return;
2050c1bc742181ded4930842b46e9507372f0b1b963James Dong        }
2060c1bc742181ded4930842b46e9507372f0b1b963James Dong
2070c1bc742181ded4930842b46e9507372f0b1b963James Dong        if (mFirstPicture && !outQueue.empty()) {
2080c1bc742181ded4930842b46e9507372f0b1b963James Dong            drainOneOutputBuffer(mFirstPictureId, mFirstPicture);
2090c1bc742181ded4930842b46e9507372f0b1b963James Dong            delete[] mFirstPicture;
2100c1bc742181ded4930842b46e9507372f0b1b963James Dong            mFirstPicture = NULL;
2110c1bc742181ded4930842b46e9507372f0b1b963James Dong            mFirstPictureId = -1;
2120c1bc742181ded4930842b46e9507372f0b1b963James Dong        }
2130c1bc742181ded4930842b46e9507372f0b1b963James Dong
2142309d1a1ff016a31d9aa68272bcb471e64a26cfaAndreas Huber        drainAllOutputBuffers(false /* eos */);
2150c1bc742181ded4930842b46e9507372f0b1b963James Dong    }
2160c1bc742181ded4930842b46e9507372f0b1b963James Dong}
2170c1bc742181ded4930842b46e9507372f0b1b963James Dong
2180c1bc742181ded4930842b46e9507372f0b1b963James Dongbool SoftAVC::handlePortSettingChangeEvent(const H264SwDecInfo *info) {
2190c1bc742181ded4930842b46e9507372f0b1b963James Dong    if (mWidth != info->picWidth || mHeight != info->picHeight) {
2200c1bc742181ded4930842b46e9507372f0b1b963James Dong        mWidth  = info->picWidth;
2210c1bc742181ded4930842b46e9507372f0b1b963James Dong        mHeight = info->picHeight;
2220c1bc742181ded4930842b46e9507372f0b1b963James Dong        mPictureSize = mWidth * mHeight * 3 / 2;
2230c1bc742181ded4930842b46e9507372f0b1b963James Dong        updatePortDefinitions();
2240c1bc742181ded4930842b46e9507372f0b1b963James Dong        notify(OMX_EventPortSettingsChanged, 1, 0, NULL);
2250c1bc742181ded4930842b46e9507372f0b1b963James Dong        mOutputPortSettingsChange = AWAITING_DISABLED;
2260c1bc742181ded4930842b46e9507372f0b1b963James Dong        return true;
2270c1bc742181ded4930842b46e9507372f0b1b963James Dong    }
2280c1bc742181ded4930842b46e9507372f0b1b963James Dong
2290c1bc742181ded4930842b46e9507372f0b1b963James Dong    return false;
2300c1bc742181ded4930842b46e9507372f0b1b963James Dong}
2310c1bc742181ded4930842b46e9507372f0b1b963James Dong
2320c1bc742181ded4930842b46e9507372f0b1b963James Dongbool SoftAVC::handleCropRectEvent(const CropParams *crop) {
2330c1bc742181ded4930842b46e9507372f0b1b963James Dong    if (mCropLeft != crop->cropLeftOffset ||
2340c1bc742181ded4930842b46e9507372f0b1b963James Dong        mCropTop != crop->cropTopOffset ||
235639ffaca514deb9de538bc2dc6e712380db68fd3James Dong        mCropWidth != crop->cropOutWidth ||
236639ffaca514deb9de538bc2dc6e712380db68fd3James Dong        mCropHeight != crop->cropOutHeight) {
2370c1bc742181ded4930842b46e9507372f0b1b963James Dong        mCropLeft = crop->cropLeftOffset;
2380c1bc742181ded4930842b46e9507372f0b1b963James Dong        mCropTop = crop->cropTopOffset;
239639ffaca514deb9de538bc2dc6e712380db68fd3James Dong        mCropWidth = crop->cropOutWidth;
240639ffaca514deb9de538bc2dc6e712380db68fd3James Dong        mCropHeight = crop->cropOutHeight;
2410c1bc742181ded4930842b46e9507372f0b1b963James Dong
2420c1bc742181ded4930842b46e9507372f0b1b963James Dong        notify(OMX_EventPortSettingsChanged, 1,
2430c1bc742181ded4930842b46e9507372f0b1b963James Dong                OMX_IndexConfigCommonOutputCrop, NULL);
2440c1bc742181ded4930842b46e9507372f0b1b963James Dong
2450c1bc742181ded4930842b46e9507372f0b1b963James Dong        return true;
2460c1bc742181ded4930842b46e9507372f0b1b963James Dong    }
2470c1bc742181ded4930842b46e9507372f0b1b963James Dong    return false;
2480c1bc742181ded4930842b46e9507372f0b1b963James Dong}
2490c1bc742181ded4930842b46e9507372f0b1b963James Dong
2500c1bc742181ded4930842b46e9507372f0b1b963James Dongvoid SoftAVC::saveFirstOutputBuffer(int32_t picId, uint8_t *data) {
2510c1bc742181ded4930842b46e9507372f0b1b963James Dong    CHECK(mFirstPicture == NULL);
2520c1bc742181ded4930842b46e9507372f0b1b963James Dong    mFirstPictureId = picId;
2530c1bc742181ded4930842b46e9507372f0b1b963James Dong
2540c1bc742181ded4930842b46e9507372f0b1b963James Dong    mFirstPicture = new uint8_t[mPictureSize];
2550c1bc742181ded4930842b46e9507372f0b1b963James Dong    memcpy(mFirstPicture, data, mPictureSize);
2560c1bc742181ded4930842b46e9507372f0b1b963James Dong}
2570c1bc742181ded4930842b46e9507372f0b1b963James Dong
2580c1bc742181ded4930842b46e9507372f0b1b963James Dongvoid SoftAVC::drainOneOutputBuffer(int32_t picId, uint8_t* data) {
2590c1bc742181ded4930842b46e9507372f0b1b963James Dong    List<BufferInfo *> &outQueue = getPortQueue(kOutputPortIndex);
2600c1bc742181ded4930842b46e9507372f0b1b963James Dong    BufferInfo *outInfo = *outQueue.begin();
2610c1bc742181ded4930842b46e9507372f0b1b963James Dong    outQueue.erase(outQueue.begin());
2620c1bc742181ded4930842b46e9507372f0b1b963James Dong    OMX_BUFFERHEADERTYPE *outHeader = outInfo->mHeader;
2630c1bc742181ded4930842b46e9507372f0b1b963James Dong    OMX_BUFFERHEADERTYPE *header = mPicToHeaderMap.valueFor(picId);
2640c1bc742181ded4930842b46e9507372f0b1b963James Dong    outHeader->nTimeStamp = header->nTimeStamp;
2650c1bc742181ded4930842b46e9507372f0b1b963James Dong    outHeader->nFlags = header->nFlags;
2660c1bc742181ded4930842b46e9507372f0b1b963James Dong    outHeader->nFilledLen = mPictureSize;
2670c1bc742181ded4930842b46e9507372f0b1b963James Dong    memcpy(outHeader->pBuffer + outHeader->nOffset,
2680c1bc742181ded4930842b46e9507372f0b1b963James Dong            data, mPictureSize);
2690c1bc742181ded4930842b46e9507372f0b1b963James Dong    mPicToHeaderMap.removeItem(picId);
2700c1bc742181ded4930842b46e9507372f0b1b963James Dong    delete header;
2710c1bc742181ded4930842b46e9507372f0b1b963James Dong    outInfo->mOwnedByUs = false;
2720c1bc742181ded4930842b46e9507372f0b1b963James Dong    notifyFillBufferDone(outHeader);
2730c1bc742181ded4930842b46e9507372f0b1b963James Dong}
2740c1bc742181ded4930842b46e9507372f0b1b963James Dong
2752309d1a1ff016a31d9aa68272bcb471e64a26cfaAndreas Hubervoid SoftAVC::drainAllOutputBuffers(bool eos) {
2760c1bc742181ded4930842b46e9507372f0b1b963James Dong    List<BufferInfo *> &outQueue = getPortQueue(kOutputPortIndex);
2770c1bc742181ded4930842b46e9507372f0b1b963James Dong    H264SwDecPicture decodedPicture;
2780c1bc742181ded4930842b46e9507372f0b1b963James Dong
2792309d1a1ff016a31d9aa68272bcb471e64a26cfaAndreas Huber    if (mHeadersDecoded) {
2802309d1a1ff016a31d9aa68272bcb471e64a26cfaAndreas Huber        while (!outQueue.empty()
2812309d1a1ff016a31d9aa68272bcb471e64a26cfaAndreas Huber                && H264SWDEC_PIC_RDY == H264SwDecNextPicture(
2822309d1a1ff016a31d9aa68272bcb471e64a26cfaAndreas Huber                    mHandle, &decodedPicture, eos /* flush */)) {
2832309d1a1ff016a31d9aa68272bcb471e64a26cfaAndreas Huber            int32_t picId = decodedPicture.picId;
2842309d1a1ff016a31d9aa68272bcb471e64a26cfaAndreas Huber            uint8_t *data = (uint8_t *) decodedPicture.pOutputPicture;
2852309d1a1ff016a31d9aa68272bcb471e64a26cfaAndreas Huber            drainOneOutputBuffer(picId, data);
2862309d1a1ff016a31d9aa68272bcb471e64a26cfaAndreas Huber        }
2872309d1a1ff016a31d9aa68272bcb471e64a26cfaAndreas Huber    }
2882309d1a1ff016a31d9aa68272bcb471e64a26cfaAndreas Huber
2892309d1a1ff016a31d9aa68272bcb471e64a26cfaAndreas Huber    if (!eos) {
2902309d1a1ff016a31d9aa68272bcb471e64a26cfaAndreas Huber        return;
2912309d1a1ff016a31d9aa68272bcb471e64a26cfaAndreas Huber    }
2922309d1a1ff016a31d9aa68272bcb471e64a26cfaAndreas Huber
2930c1bc742181ded4930842b46e9507372f0b1b963James Dong    while (!outQueue.empty()) {
2940c1bc742181ded4930842b46e9507372f0b1b963James Dong        BufferInfo *outInfo = *outQueue.begin();
2950c1bc742181ded4930842b46e9507372f0b1b963James Dong        outQueue.erase(outQueue.begin());
2960c1bc742181ded4930842b46e9507372f0b1b963James Dong        OMX_BUFFERHEADERTYPE *outHeader = outInfo->mHeader;
2970c1bc742181ded4930842b46e9507372f0b1b963James Dong
2982309d1a1ff016a31d9aa68272bcb471e64a26cfaAndreas Huber        outHeader->nTimeStamp = 0;
2992309d1a1ff016a31d9aa68272bcb471e64a26cfaAndreas Huber        outHeader->nFilledLen = 0;
3002309d1a1ff016a31d9aa68272bcb471e64a26cfaAndreas Huber        outHeader->nFlags = OMX_BUFFERFLAG_EOS;
3010c1bc742181ded4930842b46e9507372f0b1b963James Dong
3020c1bc742181ded4930842b46e9507372f0b1b963James Dong        outInfo->mOwnedByUs = false;
3030c1bc742181ded4930842b46e9507372f0b1b963James Dong        notifyFillBufferDone(outHeader);
3040c1bc742181ded4930842b46e9507372f0b1b963James Dong
3052309d1a1ff016a31d9aa68272bcb471e64a26cfaAndreas Huber        mEOSStatus = OUTPUT_FRAMES_FLUSHED;
3062309d1a1ff016a31d9aa68272bcb471e64a26cfaAndreas Huber    }
3070c1bc742181ded4930842b46e9507372f0b1b963James Dong}
3080c1bc742181ded4930842b46e9507372f0b1b963James Dong
3090c1bc742181ded4930842b46e9507372f0b1b963James Dongvoid SoftAVC::onPortFlushCompleted(OMX_U32 portIndex) {
3100c1bc742181ded4930842b46e9507372f0b1b963James Dong    if (portIndex == kInputPortIndex) {
3110c1bc742181ded4930842b46e9507372f0b1b963James Dong        mEOSStatus = INPUT_DATA_AVAILABLE;
3120c1bc742181ded4930842b46e9507372f0b1b963James Dong    }
3130c1bc742181ded4930842b46e9507372f0b1b963James Dong}
3140c1bc742181ded4930842b46e9507372f0b1b963James Dong
315d94e716af0e49d775f0c0c4f36dd2c136ba5f2b2Andreas Hubervoid SoftAVC::onReset() {
3167f616d3cc5366a4b8af20d3d0c768e3de1df0666Lajos Molnar    SoftVideoDecoderOMXComponent::onReset();
317d94e716af0e49d775f0c0c4f36dd2c136ba5f2b2Andreas Huber    mSignalledError = false;
3180c1bc742181ded4930842b46e9507372f0b1b963James Dong}
3190c1bc742181ded4930842b46e9507372f0b1b963James Dong
3200c1bc742181ded4930842b46e9507372f0b1b963James Dong}  // namespace android
3210c1bc742181ded4930842b46e9507372f0b1b963James Dong
3220c1bc742181ded4930842b46e9507372f0b1b963James Dongandroid::SoftOMXComponent *createSoftOMXComponent(
3230c1bc742181ded4930842b46e9507372f0b1b963James Dong        const char *name, const OMX_CALLBACKTYPE *callbacks,
3240c1bc742181ded4930842b46e9507372f0b1b963James Dong        OMX_PTR appData, OMX_COMPONENTTYPE **component) {
3250c1bc742181ded4930842b46e9507372f0b1b963James Dong    return new android::SoftAVC(name, callbacks, appData, component);
3260c1bc742181ded4930842b46e9507372f0b1b963James Dong}
327