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