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