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 Dongtemplate<class T>
510c1bc742181ded4930842b46e9507372f0b1b963James Dongstatic void InitOMXParams(T *params) {
520c1bc742181ded4930842b46e9507372f0b1b963James Dong    params->nSize = sizeof(T);
530c1bc742181ded4930842b46e9507372f0b1b963James Dong    params->nVersion.s.nVersionMajor = 1;
540c1bc742181ded4930842b46e9507372f0b1b963James Dong    params->nVersion.s.nVersionMinor = 0;
550c1bc742181ded4930842b46e9507372f0b1b963James Dong    params->nVersion.s.nRevision = 0;
560c1bc742181ded4930842b46e9507372f0b1b963James Dong    params->nVersion.s.nStep = 0;
570c1bc742181ded4930842b46e9507372f0b1b963James Dong}
580c1bc742181ded4930842b46e9507372f0b1b963James Dong
590c1bc742181ded4930842b46e9507372f0b1b963James DongSoftAVC::SoftAVC(
600c1bc742181ded4930842b46e9507372f0b1b963James Dong        const char *name,
610c1bc742181ded4930842b46e9507372f0b1b963James Dong        const OMX_CALLBACKTYPE *callbacks,
620c1bc742181ded4930842b46e9507372f0b1b963James Dong        OMX_PTR appData,
630c1bc742181ded4930842b46e9507372f0b1b963James Dong        OMX_COMPONENTTYPE **component)
640c1bc742181ded4930842b46e9507372f0b1b963James Dong    : SimpleSoftOMXComponent(name, callbacks, appData, component),
650c1bc742181ded4930842b46e9507372f0b1b963James Dong      mHandle(NULL),
660c1bc742181ded4930842b46e9507372f0b1b963James Dong      mInputBufferCount(0),
670c1bc742181ded4930842b46e9507372f0b1b963James Dong      mWidth(320),
680c1bc742181ded4930842b46e9507372f0b1b963James Dong      mHeight(240),
690c1bc742181ded4930842b46e9507372f0b1b963James Dong      mPictureSize(mWidth * mHeight * 3 / 2),
700c1bc742181ded4930842b46e9507372f0b1b963James Dong      mCropLeft(0),
710c1bc742181ded4930842b46e9507372f0b1b963James Dong      mCropTop(0),
72639ffaca514deb9de538bc2dc6e712380db68fd3James Dong      mCropWidth(mWidth),
73639ffaca514deb9de538bc2dc6e712380db68fd3James Dong      mCropHeight(mHeight),
740c1bc742181ded4930842b46e9507372f0b1b963James Dong      mFirstPicture(NULL),
750c1bc742181ded4930842b46e9507372f0b1b963James Dong      mFirstPictureId(-1),
760c1bc742181ded4930842b46e9507372f0b1b963James Dong      mPicId(0),
770c1bc742181ded4930842b46e9507372f0b1b963James Dong      mHeadersDecoded(false),
780c1bc742181ded4930842b46e9507372f0b1b963James Dong      mEOSStatus(INPUT_DATA_AVAILABLE),
792961a85f5f00343c115ac8e5dc17de631694fb6eAndreas Huber      mOutputPortSettingsChange(NONE),
802961a85f5f00343c115ac8e5dc17de631694fb6eAndreas Huber      mSignalledError(false) {
810c1bc742181ded4930842b46e9507372f0b1b963James Dong    initPorts();
820c1bc742181ded4930842b46e9507372f0b1b963James Dong    CHECK_EQ(initDecoder(), (status_t)OK);
830c1bc742181ded4930842b46e9507372f0b1b963James Dong}
840c1bc742181ded4930842b46e9507372f0b1b963James Dong
850c1bc742181ded4930842b46e9507372f0b1b963James DongSoftAVC::~SoftAVC() {
860c1bc742181ded4930842b46e9507372f0b1b963James Dong    H264SwDecRelease(mHandle);
870c1bc742181ded4930842b46e9507372f0b1b963James Dong    mHandle = NULL;
880c1bc742181ded4930842b46e9507372f0b1b963James Dong
890c1bc742181ded4930842b46e9507372f0b1b963James Dong    while (mPicToHeaderMap.size() != 0) {
900c1bc742181ded4930842b46e9507372f0b1b963James Dong        OMX_BUFFERHEADERTYPE *header = mPicToHeaderMap.editValueAt(0);
910c1bc742181ded4930842b46e9507372f0b1b963James Dong        mPicToHeaderMap.removeItemsAt(0);
920c1bc742181ded4930842b46e9507372f0b1b963James Dong        delete header;
930c1bc742181ded4930842b46e9507372f0b1b963James Dong        header = NULL;
940c1bc742181ded4930842b46e9507372f0b1b963James Dong    }
950c1bc742181ded4930842b46e9507372f0b1b963James Dong    List<BufferInfo *> &outQueue = getPortQueue(kOutputPortIndex);
960c1bc742181ded4930842b46e9507372f0b1b963James Dong    List<BufferInfo *> &inQueue = getPortQueue(kInputPortIndex);
970c1bc742181ded4930842b46e9507372f0b1b963James Dong    CHECK(outQueue.empty());
980c1bc742181ded4930842b46e9507372f0b1b963James Dong    CHECK(inQueue.empty());
990c1bc742181ded4930842b46e9507372f0b1b963James Dong
1000c1bc742181ded4930842b46e9507372f0b1b963James Dong    delete[] mFirstPicture;
1010c1bc742181ded4930842b46e9507372f0b1b963James Dong}
1020c1bc742181ded4930842b46e9507372f0b1b963James Dong
1030c1bc742181ded4930842b46e9507372f0b1b963James Dongvoid SoftAVC::initPorts() {
1040c1bc742181ded4930842b46e9507372f0b1b963James Dong    OMX_PARAM_PORTDEFINITIONTYPE def;
1050c1bc742181ded4930842b46e9507372f0b1b963James Dong    InitOMXParams(&def);
1060c1bc742181ded4930842b46e9507372f0b1b963James Dong
1070c1bc742181ded4930842b46e9507372f0b1b963James Dong    def.nPortIndex = kInputPortIndex;
1080c1bc742181ded4930842b46e9507372f0b1b963James Dong    def.eDir = OMX_DirInput;
1090c1bc742181ded4930842b46e9507372f0b1b963James Dong    def.nBufferCountMin = kNumInputBuffers;
1100c1bc742181ded4930842b46e9507372f0b1b963James Dong    def.nBufferCountActual = def.nBufferCountMin;
1110c1bc742181ded4930842b46e9507372f0b1b963James Dong    def.nBufferSize = 8192;
1120c1bc742181ded4930842b46e9507372f0b1b963James Dong    def.bEnabled = OMX_TRUE;
1130c1bc742181ded4930842b46e9507372f0b1b963James Dong    def.bPopulated = OMX_FALSE;
1140c1bc742181ded4930842b46e9507372f0b1b963James Dong    def.eDomain = OMX_PortDomainVideo;
1150c1bc742181ded4930842b46e9507372f0b1b963James Dong    def.bBuffersContiguous = OMX_FALSE;
1160c1bc742181ded4930842b46e9507372f0b1b963James Dong    def.nBufferAlignment = 1;
1170c1bc742181ded4930842b46e9507372f0b1b963James Dong
1180c1bc742181ded4930842b46e9507372f0b1b963James Dong    def.format.video.cMIMEType = const_cast<char *>(MEDIA_MIMETYPE_VIDEO_AVC);
1190c1bc742181ded4930842b46e9507372f0b1b963James Dong    def.format.video.pNativeRender = NULL;
1200c1bc742181ded4930842b46e9507372f0b1b963James Dong    def.format.video.nFrameWidth = mWidth;
1210c1bc742181ded4930842b46e9507372f0b1b963James Dong    def.format.video.nFrameHeight = mHeight;
1220c1bc742181ded4930842b46e9507372f0b1b963James Dong    def.format.video.nStride = def.format.video.nFrameWidth;
1230c1bc742181ded4930842b46e9507372f0b1b963James Dong    def.format.video.nSliceHeight = def.format.video.nFrameHeight;
1240c1bc742181ded4930842b46e9507372f0b1b963James Dong    def.format.video.nBitrate = 0;
1250c1bc742181ded4930842b46e9507372f0b1b963James Dong    def.format.video.xFramerate = 0;
1260c1bc742181ded4930842b46e9507372f0b1b963James Dong    def.format.video.bFlagErrorConcealment = OMX_FALSE;
1270c1bc742181ded4930842b46e9507372f0b1b963James Dong    def.format.video.eCompressionFormat = OMX_VIDEO_CodingAVC;
1280c1bc742181ded4930842b46e9507372f0b1b963James Dong    def.format.video.eColorFormat = OMX_COLOR_FormatUnused;
1290c1bc742181ded4930842b46e9507372f0b1b963James Dong    def.format.video.pNativeWindow = NULL;
1300c1bc742181ded4930842b46e9507372f0b1b963James Dong
1310c1bc742181ded4930842b46e9507372f0b1b963James Dong    addPort(def);
1320c1bc742181ded4930842b46e9507372f0b1b963James Dong
1330c1bc742181ded4930842b46e9507372f0b1b963James Dong    def.nPortIndex = kOutputPortIndex;
1340c1bc742181ded4930842b46e9507372f0b1b963James Dong    def.eDir = OMX_DirOutput;
1350c1bc742181ded4930842b46e9507372f0b1b963James Dong    def.nBufferCountMin = kNumOutputBuffers;
1360c1bc742181ded4930842b46e9507372f0b1b963James Dong    def.nBufferCountActual = def.nBufferCountMin;
1370c1bc742181ded4930842b46e9507372f0b1b963James Dong    def.bEnabled = OMX_TRUE;
1380c1bc742181ded4930842b46e9507372f0b1b963James Dong    def.bPopulated = OMX_FALSE;
1390c1bc742181ded4930842b46e9507372f0b1b963James Dong    def.eDomain = OMX_PortDomainVideo;
1400c1bc742181ded4930842b46e9507372f0b1b963James Dong    def.bBuffersContiguous = OMX_FALSE;
1410c1bc742181ded4930842b46e9507372f0b1b963James Dong    def.nBufferAlignment = 2;
1420c1bc742181ded4930842b46e9507372f0b1b963James Dong
1430c1bc742181ded4930842b46e9507372f0b1b963James Dong    def.format.video.cMIMEType = const_cast<char *>(MEDIA_MIMETYPE_VIDEO_RAW);
1440c1bc742181ded4930842b46e9507372f0b1b963James Dong    def.format.video.pNativeRender = NULL;
1450c1bc742181ded4930842b46e9507372f0b1b963James Dong    def.format.video.nFrameWidth = mWidth;
1460c1bc742181ded4930842b46e9507372f0b1b963James Dong    def.format.video.nFrameHeight = mHeight;
1470c1bc742181ded4930842b46e9507372f0b1b963James Dong    def.format.video.nStride = def.format.video.nFrameWidth;
1480c1bc742181ded4930842b46e9507372f0b1b963James Dong    def.format.video.nSliceHeight = def.format.video.nFrameHeight;
1490c1bc742181ded4930842b46e9507372f0b1b963James Dong    def.format.video.nBitrate = 0;
1500c1bc742181ded4930842b46e9507372f0b1b963James Dong    def.format.video.xFramerate = 0;
1510c1bc742181ded4930842b46e9507372f0b1b963James Dong    def.format.video.bFlagErrorConcealment = OMX_FALSE;
1520c1bc742181ded4930842b46e9507372f0b1b963James Dong    def.format.video.eCompressionFormat = OMX_VIDEO_CodingUnused;
1530c1bc742181ded4930842b46e9507372f0b1b963James Dong    def.format.video.eColorFormat = OMX_COLOR_FormatYUV420Planar;
1540c1bc742181ded4930842b46e9507372f0b1b963James Dong    def.format.video.pNativeWindow = NULL;
1550c1bc742181ded4930842b46e9507372f0b1b963James Dong
1560c1bc742181ded4930842b46e9507372f0b1b963James Dong    def.nBufferSize =
1570c1bc742181ded4930842b46e9507372f0b1b963James Dong        (def.format.video.nFrameWidth * def.format.video.nFrameHeight * 3) / 2;
1580c1bc742181ded4930842b46e9507372f0b1b963James Dong
1590c1bc742181ded4930842b46e9507372f0b1b963James Dong    addPort(def);
1600c1bc742181ded4930842b46e9507372f0b1b963James Dong}
1610c1bc742181ded4930842b46e9507372f0b1b963James Dong
1620c1bc742181ded4930842b46e9507372f0b1b963James Dongstatus_t SoftAVC::initDecoder() {
163486247017e0bfb9db9994a53a28c0dacfebf8567James Dong    // Force decoder to output buffers in display order.
164486247017e0bfb9db9994a53a28c0dacfebf8567James Dong    if (H264SwDecInit(&mHandle, 0) == H264SWDEC_OK) {
1650c1bc742181ded4930842b46e9507372f0b1b963James Dong        return OK;
1660c1bc742181ded4930842b46e9507372f0b1b963James Dong    }
1670c1bc742181ded4930842b46e9507372f0b1b963James Dong    return UNKNOWN_ERROR;
1680c1bc742181ded4930842b46e9507372f0b1b963James Dong}
1690c1bc742181ded4930842b46e9507372f0b1b963James Dong
1700c1bc742181ded4930842b46e9507372f0b1b963James DongOMX_ERRORTYPE SoftAVC::internalGetParameter(
1710c1bc742181ded4930842b46e9507372f0b1b963James Dong        OMX_INDEXTYPE index, OMX_PTR params) {
1720c1bc742181ded4930842b46e9507372f0b1b963James Dong    switch (index) {
1730c1bc742181ded4930842b46e9507372f0b1b963James Dong        case OMX_IndexParamVideoPortFormat:
1740c1bc742181ded4930842b46e9507372f0b1b963James Dong        {
1750c1bc742181ded4930842b46e9507372f0b1b963James Dong            OMX_VIDEO_PARAM_PORTFORMATTYPE *formatParams =
1760c1bc742181ded4930842b46e9507372f0b1b963James Dong                (OMX_VIDEO_PARAM_PORTFORMATTYPE *)params;
1770c1bc742181ded4930842b46e9507372f0b1b963James Dong
1780c1bc742181ded4930842b46e9507372f0b1b963James Dong            if (formatParams->nPortIndex > kOutputPortIndex) {
1790c1bc742181ded4930842b46e9507372f0b1b963James Dong                return OMX_ErrorUndefined;
1800c1bc742181ded4930842b46e9507372f0b1b963James Dong            }
1810c1bc742181ded4930842b46e9507372f0b1b963James Dong
1820c1bc742181ded4930842b46e9507372f0b1b963James Dong            if (formatParams->nIndex != 0) {
1830c1bc742181ded4930842b46e9507372f0b1b963James Dong                return OMX_ErrorNoMore;
1840c1bc742181ded4930842b46e9507372f0b1b963James Dong            }
1850c1bc742181ded4930842b46e9507372f0b1b963James Dong
1860c1bc742181ded4930842b46e9507372f0b1b963James Dong            if (formatParams->nPortIndex == kInputPortIndex) {
1870c1bc742181ded4930842b46e9507372f0b1b963James Dong                formatParams->eCompressionFormat = OMX_VIDEO_CodingAVC;
1880c1bc742181ded4930842b46e9507372f0b1b963James Dong                formatParams->eColorFormat = OMX_COLOR_FormatUnused;
1890c1bc742181ded4930842b46e9507372f0b1b963James Dong                formatParams->xFramerate = 0;
1900c1bc742181ded4930842b46e9507372f0b1b963James Dong            } else {
1910c1bc742181ded4930842b46e9507372f0b1b963James Dong                CHECK(formatParams->nPortIndex == kOutputPortIndex);
1920c1bc742181ded4930842b46e9507372f0b1b963James Dong
1930c1bc742181ded4930842b46e9507372f0b1b963James Dong                formatParams->eCompressionFormat = OMX_VIDEO_CodingUnused;
1940c1bc742181ded4930842b46e9507372f0b1b963James Dong                formatParams->eColorFormat = OMX_COLOR_FormatYUV420Planar;
1950c1bc742181ded4930842b46e9507372f0b1b963James Dong                formatParams->xFramerate = 0;
1960c1bc742181ded4930842b46e9507372f0b1b963James Dong            }
1970c1bc742181ded4930842b46e9507372f0b1b963James Dong
1980c1bc742181ded4930842b46e9507372f0b1b963James Dong            return OMX_ErrorNone;
199457116d3a01618acf9a875020ca5860551ba03a6James Dong        }
200457116d3a01618acf9a875020ca5860551ba03a6James Dong
201457116d3a01618acf9a875020ca5860551ba03a6James Dong        case OMX_IndexParamVideoProfileLevelQuerySupported:
202457116d3a01618acf9a875020ca5860551ba03a6James Dong        {
203457116d3a01618acf9a875020ca5860551ba03a6James Dong            OMX_VIDEO_PARAM_PROFILELEVELTYPE *profileLevel =
204457116d3a01618acf9a875020ca5860551ba03a6James Dong                    (OMX_VIDEO_PARAM_PROFILELEVELTYPE *) params;
205457116d3a01618acf9a875020ca5860551ba03a6James Dong
206457116d3a01618acf9a875020ca5860551ba03a6James Dong            if (profileLevel->nPortIndex != kInputPortIndex) {
20729357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block                ALOGE("Invalid port index: %ld", profileLevel->nPortIndex);
208457116d3a01618acf9a875020ca5860551ba03a6James Dong                return OMX_ErrorUnsupportedIndex;
209457116d3a01618acf9a875020ca5860551ba03a6James Dong            }
210457116d3a01618acf9a875020ca5860551ba03a6James Dong
211457116d3a01618acf9a875020ca5860551ba03a6James Dong            size_t index = profileLevel->nProfileIndex;
212457116d3a01618acf9a875020ca5860551ba03a6James Dong            size_t nProfileLevels =
213457116d3a01618acf9a875020ca5860551ba03a6James Dong                    sizeof(kProfileLevels) / sizeof(kProfileLevels[0]);
214457116d3a01618acf9a875020ca5860551ba03a6James Dong            if (index >= nProfileLevels) {
215457116d3a01618acf9a875020ca5860551ba03a6James Dong                return OMX_ErrorNoMore;
216457116d3a01618acf9a875020ca5860551ba03a6James Dong            }
217457116d3a01618acf9a875020ca5860551ba03a6James Dong
218457116d3a01618acf9a875020ca5860551ba03a6James Dong            profileLevel->eProfile = kProfileLevels[index].mProfile;
219457116d3a01618acf9a875020ca5860551ba03a6James Dong            profileLevel->eLevel = kProfileLevels[index].mLevel;
220457116d3a01618acf9a875020ca5860551ba03a6James Dong            return OMX_ErrorNone;
2210c1bc742181ded4930842b46e9507372f0b1b963James Dong        }
2220c1bc742181ded4930842b46e9507372f0b1b963James Dong
2230c1bc742181ded4930842b46e9507372f0b1b963James Dong        default:
2240c1bc742181ded4930842b46e9507372f0b1b963James Dong            return SimpleSoftOMXComponent::internalGetParameter(index, params);
2250c1bc742181ded4930842b46e9507372f0b1b963James Dong    }
2260c1bc742181ded4930842b46e9507372f0b1b963James Dong}
2270c1bc742181ded4930842b46e9507372f0b1b963James Dong
2280c1bc742181ded4930842b46e9507372f0b1b963James DongOMX_ERRORTYPE SoftAVC::internalSetParameter(
2290c1bc742181ded4930842b46e9507372f0b1b963James Dong        OMX_INDEXTYPE index, const OMX_PTR params) {
2300c1bc742181ded4930842b46e9507372f0b1b963James Dong    switch (index) {
2310c1bc742181ded4930842b46e9507372f0b1b963James Dong        case OMX_IndexParamStandardComponentRole:
2320c1bc742181ded4930842b46e9507372f0b1b963James Dong        {
2330c1bc742181ded4930842b46e9507372f0b1b963James Dong            const OMX_PARAM_COMPONENTROLETYPE *roleParams =
2340c1bc742181ded4930842b46e9507372f0b1b963James Dong                (const OMX_PARAM_COMPONENTROLETYPE *)params;
2350c1bc742181ded4930842b46e9507372f0b1b963James Dong
2360c1bc742181ded4930842b46e9507372f0b1b963James Dong            if (strncmp((const char *)roleParams->cRole,
2370c1bc742181ded4930842b46e9507372f0b1b963James Dong                        "video_decoder.avc",
2380c1bc742181ded4930842b46e9507372f0b1b963James Dong                        OMX_MAX_STRINGNAME_SIZE - 1)) {
2390c1bc742181ded4930842b46e9507372f0b1b963James Dong                return OMX_ErrorUndefined;
2400c1bc742181ded4930842b46e9507372f0b1b963James Dong            }
2410c1bc742181ded4930842b46e9507372f0b1b963James Dong
2420c1bc742181ded4930842b46e9507372f0b1b963James Dong            return OMX_ErrorNone;
2430c1bc742181ded4930842b46e9507372f0b1b963James Dong        }
2440c1bc742181ded4930842b46e9507372f0b1b963James Dong
2450c1bc742181ded4930842b46e9507372f0b1b963James Dong        case OMX_IndexParamVideoPortFormat:
2460c1bc742181ded4930842b46e9507372f0b1b963James Dong        {
2470c1bc742181ded4930842b46e9507372f0b1b963James Dong            OMX_VIDEO_PARAM_PORTFORMATTYPE *formatParams =
2480c1bc742181ded4930842b46e9507372f0b1b963James Dong                (OMX_VIDEO_PARAM_PORTFORMATTYPE *)params;
2490c1bc742181ded4930842b46e9507372f0b1b963James Dong
2500c1bc742181ded4930842b46e9507372f0b1b963James Dong            if (formatParams->nPortIndex > kOutputPortIndex) {
2510c1bc742181ded4930842b46e9507372f0b1b963James Dong                return OMX_ErrorUndefined;
2520c1bc742181ded4930842b46e9507372f0b1b963James Dong            }
2530c1bc742181ded4930842b46e9507372f0b1b963James Dong
2540c1bc742181ded4930842b46e9507372f0b1b963James Dong            if (formatParams->nIndex != 0) {
2550c1bc742181ded4930842b46e9507372f0b1b963James Dong                return OMX_ErrorNoMore;
2560c1bc742181ded4930842b46e9507372f0b1b963James Dong            }
2570c1bc742181ded4930842b46e9507372f0b1b963James Dong
2580c1bc742181ded4930842b46e9507372f0b1b963James Dong            return OMX_ErrorNone;
2590c1bc742181ded4930842b46e9507372f0b1b963James Dong        }
2600c1bc742181ded4930842b46e9507372f0b1b963James Dong
2610c1bc742181ded4930842b46e9507372f0b1b963James Dong        default:
2620c1bc742181ded4930842b46e9507372f0b1b963James Dong            return SimpleSoftOMXComponent::internalSetParameter(index, params);
2630c1bc742181ded4930842b46e9507372f0b1b963James Dong    }
2640c1bc742181ded4930842b46e9507372f0b1b963James Dong}
2650c1bc742181ded4930842b46e9507372f0b1b963James Dong
2660c1bc742181ded4930842b46e9507372f0b1b963James DongOMX_ERRORTYPE SoftAVC::getConfig(
2670c1bc742181ded4930842b46e9507372f0b1b963James Dong        OMX_INDEXTYPE index, OMX_PTR params) {
2680c1bc742181ded4930842b46e9507372f0b1b963James Dong    switch (index) {
2690c1bc742181ded4930842b46e9507372f0b1b963James Dong        case OMX_IndexConfigCommonOutputCrop:
2700c1bc742181ded4930842b46e9507372f0b1b963James Dong        {
2710c1bc742181ded4930842b46e9507372f0b1b963James Dong            OMX_CONFIG_RECTTYPE *rectParams = (OMX_CONFIG_RECTTYPE *)params;
2720c1bc742181ded4930842b46e9507372f0b1b963James Dong
2730c1bc742181ded4930842b46e9507372f0b1b963James Dong            if (rectParams->nPortIndex != 1) {
2740c1bc742181ded4930842b46e9507372f0b1b963James Dong                return OMX_ErrorUndefined;
2750c1bc742181ded4930842b46e9507372f0b1b963James Dong            }
2760c1bc742181ded4930842b46e9507372f0b1b963James Dong
2770c1bc742181ded4930842b46e9507372f0b1b963James Dong            rectParams->nLeft = mCropLeft;
2780c1bc742181ded4930842b46e9507372f0b1b963James Dong            rectParams->nTop = mCropTop;
279639ffaca514deb9de538bc2dc6e712380db68fd3James Dong            rectParams->nWidth = mCropWidth;
280639ffaca514deb9de538bc2dc6e712380db68fd3James Dong            rectParams->nHeight = mCropHeight;
2810c1bc742181ded4930842b46e9507372f0b1b963James Dong
2820c1bc742181ded4930842b46e9507372f0b1b963James Dong            return OMX_ErrorNone;
2830c1bc742181ded4930842b46e9507372f0b1b963James Dong        }
2840c1bc742181ded4930842b46e9507372f0b1b963James Dong
2850c1bc742181ded4930842b46e9507372f0b1b963James Dong        default:
2860c1bc742181ded4930842b46e9507372f0b1b963James Dong            return OMX_ErrorUnsupportedIndex;
2870c1bc742181ded4930842b46e9507372f0b1b963James Dong    }
2880c1bc742181ded4930842b46e9507372f0b1b963James Dong}
2890c1bc742181ded4930842b46e9507372f0b1b963James Dong
2900c1bc742181ded4930842b46e9507372f0b1b963James Dongvoid SoftAVC::onQueueFilled(OMX_U32 portIndex) {
2912961a85f5f00343c115ac8e5dc17de631694fb6eAndreas Huber    if (mSignalledError || mOutputPortSettingsChange != NONE) {
2920c1bc742181ded4930842b46e9507372f0b1b963James Dong        return;
2930c1bc742181ded4930842b46e9507372f0b1b963James Dong    }
2940c1bc742181ded4930842b46e9507372f0b1b963James Dong
2950c1bc742181ded4930842b46e9507372f0b1b963James Dong    if (mEOSStatus == OUTPUT_FRAMES_FLUSHED) {
2960c1bc742181ded4930842b46e9507372f0b1b963James Dong        return;
2970c1bc742181ded4930842b46e9507372f0b1b963James Dong    }
2980c1bc742181ded4930842b46e9507372f0b1b963James Dong
2990c1bc742181ded4930842b46e9507372f0b1b963James Dong    List<BufferInfo *> &inQueue = getPortQueue(kInputPortIndex);
3000c1bc742181ded4930842b46e9507372f0b1b963James Dong    List<BufferInfo *> &outQueue = getPortQueue(kOutputPortIndex);
3010c1bc742181ded4930842b46e9507372f0b1b963James Dong    H264SwDecRet ret = H264SWDEC_PIC_RDY;
3020c1bc742181ded4930842b46e9507372f0b1b963James Dong    bool portSettingsChanged = false;
3030c1bc742181ded4930842b46e9507372f0b1b963James Dong    while ((mEOSStatus != INPUT_DATA_AVAILABLE || !inQueue.empty())
3040c1bc742181ded4930842b46e9507372f0b1b963James Dong            && outQueue.size() == kNumOutputBuffers) {
3050c1bc742181ded4930842b46e9507372f0b1b963James Dong
3060c1bc742181ded4930842b46e9507372f0b1b963James Dong        if (mEOSStatus == INPUT_EOS_SEEN) {
3070c1bc742181ded4930842b46e9507372f0b1b963James Dong            drainAllOutputBuffers();
3080c1bc742181ded4930842b46e9507372f0b1b963James Dong            return;
3090c1bc742181ded4930842b46e9507372f0b1b963James Dong        }
3100c1bc742181ded4930842b46e9507372f0b1b963James Dong
3110c1bc742181ded4930842b46e9507372f0b1b963James Dong        BufferInfo *inInfo = *inQueue.begin();
3120c1bc742181ded4930842b46e9507372f0b1b963James Dong        OMX_BUFFERHEADERTYPE *inHeader = inInfo->mHeader;
3130c1bc742181ded4930842b46e9507372f0b1b963James Dong        ++mPicId;
3140c1bc742181ded4930842b46e9507372f0b1b963James Dong
3150c1bc742181ded4930842b46e9507372f0b1b963James Dong        OMX_BUFFERHEADERTYPE *header = new OMX_BUFFERHEADERTYPE;
3160c1bc742181ded4930842b46e9507372f0b1b963James Dong        memset(header, 0, sizeof(OMX_BUFFERHEADERTYPE));
3170c1bc742181ded4930842b46e9507372f0b1b963James Dong        header->nTimeStamp = inHeader->nTimeStamp;
3180c1bc742181ded4930842b46e9507372f0b1b963James Dong        header->nFlags = inHeader->nFlags;
31979399a427dad4a65e20dafc6c8f7cb07c8d719c7Marco Nelissen        if (header->nFlags & OMX_BUFFERFLAG_EOS) {
32079399a427dad4a65e20dafc6c8f7cb07c8d719c7Marco Nelissen            mEOSStatus = INPUT_EOS_SEEN;
32179399a427dad4a65e20dafc6c8f7cb07c8d719c7Marco Nelissen        }
3220c1bc742181ded4930842b46e9507372f0b1b963James Dong        mPicToHeaderMap.add(mPicId, header);
3230c1bc742181ded4930842b46e9507372f0b1b963James Dong        inQueue.erase(inQueue.begin());
3240c1bc742181ded4930842b46e9507372f0b1b963James Dong
3250c1bc742181ded4930842b46e9507372f0b1b963James Dong        H264SwDecInput inPicture;
3260c1bc742181ded4930842b46e9507372f0b1b963James Dong        H264SwDecOutput outPicture;
3270c1bc742181ded4930842b46e9507372f0b1b963James Dong        memset(&inPicture, 0, sizeof(inPicture));
3280c1bc742181ded4930842b46e9507372f0b1b963James Dong        inPicture.dataLen = inHeader->nFilledLen;
3290c1bc742181ded4930842b46e9507372f0b1b963James Dong        inPicture.pStream = inHeader->pBuffer + inHeader->nOffset;
3300c1bc742181ded4930842b46e9507372f0b1b963James Dong        inPicture.picId = mPicId;
3310c1bc742181ded4930842b46e9507372f0b1b963James Dong        inPicture.intraConcealmentMethod = 1;
3320c1bc742181ded4930842b46e9507372f0b1b963James Dong        H264SwDecPicture decodedPicture;
3330c1bc742181ded4930842b46e9507372f0b1b963James Dong
3340c1bc742181ded4930842b46e9507372f0b1b963James Dong        while (inPicture.dataLen > 0) {
3350c1bc742181ded4930842b46e9507372f0b1b963James Dong            ret = H264SwDecDecode(mHandle, &inPicture, &outPicture);
3360c1bc742181ded4930842b46e9507372f0b1b963James Dong            if (ret == H264SWDEC_HDRS_RDY_BUFF_NOT_EMPTY ||
3370c1bc742181ded4930842b46e9507372f0b1b963James Dong                ret == H264SWDEC_PIC_RDY_BUFF_NOT_EMPTY) {
3380c1bc742181ded4930842b46e9507372f0b1b963James Dong                inPicture.dataLen -= (u32)(outPicture.pStrmCurrPos - inPicture.pStream);
3390c1bc742181ded4930842b46e9507372f0b1b963James Dong                inPicture.pStream = outPicture.pStrmCurrPos;
3400c1bc742181ded4930842b46e9507372f0b1b963James Dong                if (ret == H264SWDEC_HDRS_RDY_BUFF_NOT_EMPTY) {
3410c1bc742181ded4930842b46e9507372f0b1b963James Dong                    mHeadersDecoded = true;
3420c1bc742181ded4930842b46e9507372f0b1b963James Dong                    H264SwDecInfo decoderInfo;
3430c1bc742181ded4930842b46e9507372f0b1b963James Dong                    CHECK(H264SwDecGetInfo(mHandle, &decoderInfo) == H264SWDEC_OK);
3440c1bc742181ded4930842b46e9507372f0b1b963James Dong
3450c1bc742181ded4930842b46e9507372f0b1b963James Dong                    if (handlePortSettingChangeEvent(&decoderInfo)) {
3460c1bc742181ded4930842b46e9507372f0b1b963James Dong                        portSettingsChanged = true;
3470c1bc742181ded4930842b46e9507372f0b1b963James Dong                    }
3480c1bc742181ded4930842b46e9507372f0b1b963James Dong
3490c1bc742181ded4930842b46e9507372f0b1b963James Dong                    if (decoderInfo.croppingFlag &&
3500c1bc742181ded4930842b46e9507372f0b1b963James Dong                        handleCropRectEvent(&decoderInfo.cropParams)) {
3510c1bc742181ded4930842b46e9507372f0b1b963James Dong                        portSettingsChanged = true;
3520c1bc742181ded4930842b46e9507372f0b1b963James Dong                    }
3530c1bc742181ded4930842b46e9507372f0b1b963James Dong                }
3540c1bc742181ded4930842b46e9507372f0b1b963James Dong            } else {
3550c1bc742181ded4930842b46e9507372f0b1b963James Dong                if (portSettingsChanged) {
3560c1bc742181ded4930842b46e9507372f0b1b963James Dong                    if (H264SwDecNextPicture(mHandle, &decodedPicture, 0)
3570c1bc742181ded4930842b46e9507372f0b1b963James Dong                        == H264SWDEC_PIC_RDY) {
3580c1bc742181ded4930842b46e9507372f0b1b963James Dong
3590c1bc742181ded4930842b46e9507372f0b1b963James Dong                        // Save this output buffer; otherwise, it will be
3600c1bc742181ded4930842b46e9507372f0b1b963James Dong                        // lost during dynamic port reconfiguration because
3610c1bc742181ded4930842b46e9507372f0b1b963James Dong                        // OpenMAX client will delete _all_ output buffers
3620c1bc742181ded4930842b46e9507372f0b1b963James Dong                        // in the process.
3630c1bc742181ded4930842b46e9507372f0b1b963James Dong                        saveFirstOutputBuffer(
3640c1bc742181ded4930842b46e9507372f0b1b963James Dong                            decodedPicture.picId,
3650c1bc742181ded4930842b46e9507372f0b1b963James Dong                            (uint8_t *)decodedPicture.pOutputPicture);
3660c1bc742181ded4930842b46e9507372f0b1b963James Dong                    }
3670c1bc742181ded4930842b46e9507372f0b1b963James Dong                }
3680c1bc742181ded4930842b46e9507372f0b1b963James Dong                inPicture.dataLen = 0;
3690c1bc742181ded4930842b46e9507372f0b1b963James Dong                if (ret < 0) {
37029357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block                    ALOGE("Decoder failed: %d", ret);
3712961a85f5f00343c115ac8e5dc17de631694fb6eAndreas Huber
3722961a85f5f00343c115ac8e5dc17de631694fb6eAndreas Huber                    notify(OMX_EventError, OMX_ErrorUndefined,
3732961a85f5f00343c115ac8e5dc17de631694fb6eAndreas Huber                           ERROR_MALFORMED, NULL);
3742961a85f5f00343c115ac8e5dc17de631694fb6eAndreas Huber
3752961a85f5f00343c115ac8e5dc17de631694fb6eAndreas Huber                    mSignalledError = true;
3762961a85f5f00343c115ac8e5dc17de631694fb6eAndreas Huber                    return;
3770c1bc742181ded4930842b46e9507372f0b1b963James Dong                }
3780c1bc742181ded4930842b46e9507372f0b1b963James Dong            }
3790c1bc742181ded4930842b46e9507372f0b1b963James Dong        }
3800c1bc742181ded4930842b46e9507372f0b1b963James Dong        inInfo->mOwnedByUs = false;
3810c1bc742181ded4930842b46e9507372f0b1b963James Dong        notifyEmptyBufferDone(inHeader);
3820c1bc742181ded4930842b46e9507372f0b1b963James Dong
3830c1bc742181ded4930842b46e9507372f0b1b963James Dong        if (portSettingsChanged) {
3840c1bc742181ded4930842b46e9507372f0b1b963James Dong            portSettingsChanged = false;
3850c1bc742181ded4930842b46e9507372f0b1b963James Dong            return;
3860c1bc742181ded4930842b46e9507372f0b1b963James Dong        }
3870c1bc742181ded4930842b46e9507372f0b1b963James Dong
3880c1bc742181ded4930842b46e9507372f0b1b963James Dong        if (mFirstPicture && !outQueue.empty()) {
3890c1bc742181ded4930842b46e9507372f0b1b963James Dong            drainOneOutputBuffer(mFirstPictureId, mFirstPicture);
3900c1bc742181ded4930842b46e9507372f0b1b963James Dong            delete[] mFirstPicture;
3910c1bc742181ded4930842b46e9507372f0b1b963James Dong            mFirstPicture = NULL;
3920c1bc742181ded4930842b46e9507372f0b1b963James Dong            mFirstPictureId = -1;
3930c1bc742181ded4930842b46e9507372f0b1b963James Dong        }
3940c1bc742181ded4930842b46e9507372f0b1b963James Dong
3950c1bc742181ded4930842b46e9507372f0b1b963James Dong        while (!outQueue.empty() &&
3960c1bc742181ded4930842b46e9507372f0b1b963James Dong                mHeadersDecoded &&
3970c1bc742181ded4930842b46e9507372f0b1b963James Dong                H264SwDecNextPicture(mHandle, &decodedPicture, 0)
3980c1bc742181ded4930842b46e9507372f0b1b963James Dong                    == H264SWDEC_PIC_RDY) {
3990c1bc742181ded4930842b46e9507372f0b1b963James Dong
4000c1bc742181ded4930842b46e9507372f0b1b963James Dong            int32_t picId = decodedPicture.picId;
4010c1bc742181ded4930842b46e9507372f0b1b963James Dong            uint8_t *data = (uint8_t *) decodedPicture.pOutputPicture;
4020c1bc742181ded4930842b46e9507372f0b1b963James Dong            drainOneOutputBuffer(picId, data);
4030c1bc742181ded4930842b46e9507372f0b1b963James Dong        }
4040c1bc742181ded4930842b46e9507372f0b1b963James Dong    }
4050c1bc742181ded4930842b46e9507372f0b1b963James Dong}
4060c1bc742181ded4930842b46e9507372f0b1b963James Dong
4070c1bc742181ded4930842b46e9507372f0b1b963James Dongbool SoftAVC::handlePortSettingChangeEvent(const H264SwDecInfo *info) {
4080c1bc742181ded4930842b46e9507372f0b1b963James Dong    if (mWidth != info->picWidth || mHeight != info->picHeight) {
4090c1bc742181ded4930842b46e9507372f0b1b963James Dong        mWidth  = info->picWidth;
4100c1bc742181ded4930842b46e9507372f0b1b963James Dong        mHeight = info->picHeight;
4110c1bc742181ded4930842b46e9507372f0b1b963James Dong        mPictureSize = mWidth * mHeight * 3 / 2;
412639ffaca514deb9de538bc2dc6e712380db68fd3James Dong        mCropWidth = mWidth;
413639ffaca514deb9de538bc2dc6e712380db68fd3James Dong        mCropHeight = mHeight;
4140c1bc742181ded4930842b46e9507372f0b1b963James Dong        updatePortDefinitions();
4150c1bc742181ded4930842b46e9507372f0b1b963James Dong        notify(OMX_EventPortSettingsChanged, 1, 0, NULL);
4160c1bc742181ded4930842b46e9507372f0b1b963James Dong        mOutputPortSettingsChange = AWAITING_DISABLED;
4170c1bc742181ded4930842b46e9507372f0b1b963James Dong        return true;
4180c1bc742181ded4930842b46e9507372f0b1b963James Dong    }
4190c1bc742181ded4930842b46e9507372f0b1b963James Dong
4200c1bc742181ded4930842b46e9507372f0b1b963James Dong    return false;
4210c1bc742181ded4930842b46e9507372f0b1b963James Dong}
4220c1bc742181ded4930842b46e9507372f0b1b963James Dong
4230c1bc742181ded4930842b46e9507372f0b1b963James Dongbool SoftAVC::handleCropRectEvent(const CropParams *crop) {
4240c1bc742181ded4930842b46e9507372f0b1b963James Dong    if (mCropLeft != crop->cropLeftOffset ||
4250c1bc742181ded4930842b46e9507372f0b1b963James Dong        mCropTop != crop->cropTopOffset ||
426639ffaca514deb9de538bc2dc6e712380db68fd3James Dong        mCropWidth != crop->cropOutWidth ||
427639ffaca514deb9de538bc2dc6e712380db68fd3James Dong        mCropHeight != crop->cropOutHeight) {
4280c1bc742181ded4930842b46e9507372f0b1b963James Dong        mCropLeft = crop->cropLeftOffset;
4290c1bc742181ded4930842b46e9507372f0b1b963James Dong        mCropTop = crop->cropTopOffset;
430639ffaca514deb9de538bc2dc6e712380db68fd3James Dong        mCropWidth = crop->cropOutWidth;
431639ffaca514deb9de538bc2dc6e712380db68fd3James Dong        mCropHeight = crop->cropOutHeight;
4320c1bc742181ded4930842b46e9507372f0b1b963James Dong
4330c1bc742181ded4930842b46e9507372f0b1b963James Dong        notify(OMX_EventPortSettingsChanged, 1,
4340c1bc742181ded4930842b46e9507372f0b1b963James Dong                OMX_IndexConfigCommonOutputCrop, NULL);
4350c1bc742181ded4930842b46e9507372f0b1b963James Dong
4360c1bc742181ded4930842b46e9507372f0b1b963James Dong        return true;
4370c1bc742181ded4930842b46e9507372f0b1b963James Dong    }
4380c1bc742181ded4930842b46e9507372f0b1b963James Dong    return false;
4390c1bc742181ded4930842b46e9507372f0b1b963James Dong}
4400c1bc742181ded4930842b46e9507372f0b1b963James Dong
4410c1bc742181ded4930842b46e9507372f0b1b963James Dongvoid SoftAVC::saveFirstOutputBuffer(int32_t picId, uint8_t *data) {
4420c1bc742181ded4930842b46e9507372f0b1b963James Dong    CHECK(mFirstPicture == NULL);
4430c1bc742181ded4930842b46e9507372f0b1b963James Dong    mFirstPictureId = picId;
4440c1bc742181ded4930842b46e9507372f0b1b963James Dong
4450c1bc742181ded4930842b46e9507372f0b1b963James Dong    mFirstPicture = new uint8_t[mPictureSize];
4460c1bc742181ded4930842b46e9507372f0b1b963James Dong    memcpy(mFirstPicture, data, mPictureSize);
4470c1bc742181ded4930842b46e9507372f0b1b963James Dong}
4480c1bc742181ded4930842b46e9507372f0b1b963James Dong
4490c1bc742181ded4930842b46e9507372f0b1b963James Dongvoid SoftAVC::drainOneOutputBuffer(int32_t picId, uint8_t* data) {
4500c1bc742181ded4930842b46e9507372f0b1b963James Dong    List<BufferInfo *> &outQueue = getPortQueue(kOutputPortIndex);
4510c1bc742181ded4930842b46e9507372f0b1b963James Dong    BufferInfo *outInfo = *outQueue.begin();
4520c1bc742181ded4930842b46e9507372f0b1b963James Dong    outQueue.erase(outQueue.begin());
4530c1bc742181ded4930842b46e9507372f0b1b963James Dong    OMX_BUFFERHEADERTYPE *outHeader = outInfo->mHeader;
4540c1bc742181ded4930842b46e9507372f0b1b963James Dong    OMX_BUFFERHEADERTYPE *header = mPicToHeaderMap.valueFor(picId);
4550c1bc742181ded4930842b46e9507372f0b1b963James Dong    outHeader->nTimeStamp = header->nTimeStamp;
4560c1bc742181ded4930842b46e9507372f0b1b963James Dong    outHeader->nFlags = header->nFlags;
4570c1bc742181ded4930842b46e9507372f0b1b963James Dong    outHeader->nFilledLen = mPictureSize;
4580c1bc742181ded4930842b46e9507372f0b1b963James Dong    memcpy(outHeader->pBuffer + outHeader->nOffset,
4590c1bc742181ded4930842b46e9507372f0b1b963James Dong            data, mPictureSize);
4600c1bc742181ded4930842b46e9507372f0b1b963James Dong    mPicToHeaderMap.removeItem(picId);
4610c1bc742181ded4930842b46e9507372f0b1b963James Dong    delete header;
4620c1bc742181ded4930842b46e9507372f0b1b963James Dong    outInfo->mOwnedByUs = false;
4630c1bc742181ded4930842b46e9507372f0b1b963James Dong    notifyFillBufferDone(outHeader);
4640c1bc742181ded4930842b46e9507372f0b1b963James Dong}
4650c1bc742181ded4930842b46e9507372f0b1b963James Dong
4660c1bc742181ded4930842b46e9507372f0b1b963James Dongbool SoftAVC::drainAllOutputBuffers() {
4670c1bc742181ded4930842b46e9507372f0b1b963James Dong    List<BufferInfo *> &outQueue = getPortQueue(kOutputPortIndex);
4680c1bc742181ded4930842b46e9507372f0b1b963James Dong    H264SwDecPicture decodedPicture;
4690c1bc742181ded4930842b46e9507372f0b1b963James Dong
4700c1bc742181ded4930842b46e9507372f0b1b963James Dong    while (!outQueue.empty()) {
4710c1bc742181ded4930842b46e9507372f0b1b963James Dong        BufferInfo *outInfo = *outQueue.begin();
4720c1bc742181ded4930842b46e9507372f0b1b963James Dong        outQueue.erase(outQueue.begin());
4730c1bc742181ded4930842b46e9507372f0b1b963James Dong        OMX_BUFFERHEADERTYPE *outHeader = outInfo->mHeader;
4740c1bc742181ded4930842b46e9507372f0b1b963James Dong        if (mHeadersDecoded &&
4750c1bc742181ded4930842b46e9507372f0b1b963James Dong            H264SWDEC_PIC_RDY ==
4760c1bc742181ded4930842b46e9507372f0b1b963James Dong                H264SwDecNextPicture(mHandle, &decodedPicture, 1 /* flush */)) {
4770c1bc742181ded4930842b46e9507372f0b1b963James Dong
4780c1bc742181ded4930842b46e9507372f0b1b963James Dong            int32_t picId = decodedPicture.picId;
4790c1bc742181ded4930842b46e9507372f0b1b963James Dong            CHECK(mPicToHeaderMap.indexOfKey(picId) >= 0);
4800c1bc742181ded4930842b46e9507372f0b1b963James Dong
4810c1bc742181ded4930842b46e9507372f0b1b963James Dong            memcpy(outHeader->pBuffer + outHeader->nOffset,
4820c1bc742181ded4930842b46e9507372f0b1b963James Dong                decodedPicture.pOutputPicture,
4830c1bc742181ded4930842b46e9507372f0b1b963James Dong                mPictureSize);
4840c1bc742181ded4930842b46e9507372f0b1b963James Dong
4850c1bc742181ded4930842b46e9507372f0b1b963James Dong            OMX_BUFFERHEADERTYPE *header = mPicToHeaderMap.valueFor(picId);
4860c1bc742181ded4930842b46e9507372f0b1b963James Dong            outHeader->nTimeStamp = header->nTimeStamp;
4870c1bc742181ded4930842b46e9507372f0b1b963James Dong            outHeader->nFlags = header->nFlags;
4880c1bc742181ded4930842b46e9507372f0b1b963James Dong            outHeader->nFilledLen = mPictureSize;
4890c1bc742181ded4930842b46e9507372f0b1b963James Dong            mPicToHeaderMap.removeItem(picId);
4900c1bc742181ded4930842b46e9507372f0b1b963James Dong            delete header;
4910c1bc742181ded4930842b46e9507372f0b1b963James Dong        } else {
4920c1bc742181ded4930842b46e9507372f0b1b963James Dong            outHeader->nTimeStamp = 0;
4930c1bc742181ded4930842b46e9507372f0b1b963James Dong            outHeader->nFilledLen = 0;
4940c1bc742181ded4930842b46e9507372f0b1b963James Dong            outHeader->nFlags = OMX_BUFFERFLAG_EOS;
4950c1bc742181ded4930842b46e9507372f0b1b963James Dong            mEOSStatus = OUTPUT_FRAMES_FLUSHED;
4960c1bc742181ded4930842b46e9507372f0b1b963James Dong        }
4970c1bc742181ded4930842b46e9507372f0b1b963James Dong
4980c1bc742181ded4930842b46e9507372f0b1b963James Dong        outInfo->mOwnedByUs = false;
4990c1bc742181ded4930842b46e9507372f0b1b963James Dong        notifyFillBufferDone(outHeader);
5000c1bc742181ded4930842b46e9507372f0b1b963James Dong    }
5010c1bc742181ded4930842b46e9507372f0b1b963James Dong
5020c1bc742181ded4930842b46e9507372f0b1b963James Dong    return true;
5030c1bc742181ded4930842b46e9507372f0b1b963James Dong}
5040c1bc742181ded4930842b46e9507372f0b1b963James Dong
5050c1bc742181ded4930842b46e9507372f0b1b963James Dongvoid SoftAVC::onPortFlushCompleted(OMX_U32 portIndex) {
5060c1bc742181ded4930842b46e9507372f0b1b963James Dong    if (portIndex == kInputPortIndex) {
5070c1bc742181ded4930842b46e9507372f0b1b963James Dong        mEOSStatus = INPUT_DATA_AVAILABLE;
5080c1bc742181ded4930842b46e9507372f0b1b963James Dong    }
5090c1bc742181ded4930842b46e9507372f0b1b963James Dong}
5100c1bc742181ded4930842b46e9507372f0b1b963James Dong
5110c1bc742181ded4930842b46e9507372f0b1b963James Dongvoid SoftAVC::onPortEnableCompleted(OMX_U32 portIndex, bool enabled) {
5120c1bc742181ded4930842b46e9507372f0b1b963James Dong    switch (mOutputPortSettingsChange) {
5130c1bc742181ded4930842b46e9507372f0b1b963James Dong        case NONE:
5140c1bc742181ded4930842b46e9507372f0b1b963James Dong            break;
5150c1bc742181ded4930842b46e9507372f0b1b963James Dong
5160c1bc742181ded4930842b46e9507372f0b1b963James Dong        case AWAITING_DISABLED:
5170c1bc742181ded4930842b46e9507372f0b1b963James Dong        {
5180c1bc742181ded4930842b46e9507372f0b1b963James Dong            CHECK(!enabled);
5190c1bc742181ded4930842b46e9507372f0b1b963James Dong            mOutputPortSettingsChange = AWAITING_ENABLED;
5200c1bc742181ded4930842b46e9507372f0b1b963James Dong            break;
5210c1bc742181ded4930842b46e9507372f0b1b963James Dong        }
5220c1bc742181ded4930842b46e9507372f0b1b963James Dong
5230c1bc742181ded4930842b46e9507372f0b1b963James Dong        default:
5240c1bc742181ded4930842b46e9507372f0b1b963James Dong        {
5250c1bc742181ded4930842b46e9507372f0b1b963James Dong            CHECK_EQ((int)mOutputPortSettingsChange, (int)AWAITING_ENABLED);
5260c1bc742181ded4930842b46e9507372f0b1b963James Dong            CHECK(enabled);
5270c1bc742181ded4930842b46e9507372f0b1b963James Dong            mOutputPortSettingsChange = NONE;
5280c1bc742181ded4930842b46e9507372f0b1b963James Dong            break;
5290c1bc742181ded4930842b46e9507372f0b1b963James Dong        }
5300c1bc742181ded4930842b46e9507372f0b1b963James Dong    }
5310c1bc742181ded4930842b46e9507372f0b1b963James Dong}
5320c1bc742181ded4930842b46e9507372f0b1b963James Dong
5330c1bc742181ded4930842b46e9507372f0b1b963James Dongvoid SoftAVC::updatePortDefinitions() {
5340c1bc742181ded4930842b46e9507372f0b1b963James Dong    OMX_PARAM_PORTDEFINITIONTYPE *def = &editPortInfo(0)->mDef;
5350c1bc742181ded4930842b46e9507372f0b1b963James Dong    def->format.video.nFrameWidth = mWidth;
5360c1bc742181ded4930842b46e9507372f0b1b963James Dong    def->format.video.nFrameHeight = mHeight;
5370c1bc742181ded4930842b46e9507372f0b1b963James Dong    def->format.video.nStride = def->format.video.nFrameWidth;
5380c1bc742181ded4930842b46e9507372f0b1b963James Dong    def->format.video.nSliceHeight = def->format.video.nFrameHeight;
5390c1bc742181ded4930842b46e9507372f0b1b963James Dong
5400c1bc742181ded4930842b46e9507372f0b1b963James Dong    def = &editPortInfo(1)->mDef;
5410c1bc742181ded4930842b46e9507372f0b1b963James Dong    def->format.video.nFrameWidth = mWidth;
5420c1bc742181ded4930842b46e9507372f0b1b963James Dong    def->format.video.nFrameHeight = mHeight;
5430c1bc742181ded4930842b46e9507372f0b1b963James Dong    def->format.video.nStride = def->format.video.nFrameWidth;
5440c1bc742181ded4930842b46e9507372f0b1b963James Dong    def->format.video.nSliceHeight = def->format.video.nFrameHeight;
5450c1bc742181ded4930842b46e9507372f0b1b963James Dong
5460c1bc742181ded4930842b46e9507372f0b1b963James Dong    def->nBufferSize =
5470c1bc742181ded4930842b46e9507372f0b1b963James Dong        (def->format.video.nFrameWidth
5480c1bc742181ded4930842b46e9507372f0b1b963James Dong            * def->format.video.nFrameHeight * 3) / 2;
5490c1bc742181ded4930842b46e9507372f0b1b963James Dong}
5500c1bc742181ded4930842b46e9507372f0b1b963James Dong
5510c1bc742181ded4930842b46e9507372f0b1b963James Dong}  // namespace android
5520c1bc742181ded4930842b46e9507372f0b1b963James Dong
5530c1bc742181ded4930842b46e9507372f0b1b963James Dongandroid::SoftOMXComponent *createSoftOMXComponent(
5540c1bc742181ded4930842b46e9507372f0b1b963James Dong        const char *name, const OMX_CALLBACKTYPE *callbacks,
5550c1bc742181ded4930842b46e9507372f0b1b963James Dong        OMX_PTR appData, OMX_COMPONENTTYPE **component) {
5560c1bc742181ded4930842b46e9507372f0b1b963James Dong    return new android::SoftAVC(name, callbacks, appData, component);
5570c1bc742181ded4930842b46e9507372f0b1b963James Dong}
558