10c1bc742181ded4930842b46e9507372f0b1b963James Dong/* 20c1bc742181ded4930842b46e9507372f0b1b963James Dong * Copyright (C) 2011 The Android Open Source Project 30c1bc742181ded4930842b46e9507372f0b1b963James Dong * 40c1bc742181ded4930842b46e9507372f0b1b963James Dong * Licensed under the Apache License, Version 2.0 (the "License"); 50c1bc742181ded4930842b46e9507372f0b1b963James Dong * you may not use this file except in compliance with the License. 60c1bc742181ded4930842b46e9507372f0b1b963James Dong * You may obtain a copy of the License at 70c1bc742181ded4930842b46e9507372f0b1b963James Dong * 80c1bc742181ded4930842b46e9507372f0b1b963James Dong * http://www.apache.org/licenses/LICENSE-2.0 90c1bc742181ded4930842b46e9507372f0b1b963James Dong * 100c1bc742181ded4930842b46e9507372f0b1b963James Dong * Unless required by applicable law or agreed to in writing, software 110c1bc742181ded4930842b46e9507372f0b1b963James Dong * distributed under the License is distributed on an "AS IS" BASIS, 120c1bc742181ded4930842b46e9507372f0b1b963James Dong * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 130c1bc742181ded4930842b46e9507372f0b1b963James Dong * See the License for the specific language governing permissions and 140c1bc742181ded4930842b46e9507372f0b1b963James Dong * limitations under the License. 150c1bc742181ded4930842b46e9507372f0b1b963James Dong */ 160c1bc742181ded4930842b46e9507372f0b1b963James Dong 170c1bc742181ded4930842b46e9507372f0b1b963James Dong//#define LOG_NDEBUG 0 180c1bc742181ded4930842b46e9507372f0b1b963James Dong#define LOG_TAG "SoftAVC" 190c1bc742181ded4930842b46e9507372f0b1b963James Dong#include <utils/Log.h> 200c1bc742181ded4930842b46e9507372f0b1b963James Dong 210c1bc742181ded4930842b46e9507372f0b1b963James Dong#include "SoftAVC.h" 220c1bc742181ded4930842b46e9507372f0b1b963James Dong 230c1bc742181ded4930842b46e9507372f0b1b963James Dong#include <media/stagefright/foundation/ADebug.h> 240c1bc742181ded4930842b46e9507372f0b1b963James Dong#include <media/stagefright/MediaDefs.h> 250c1bc742181ded4930842b46e9507372f0b1b963James Dong#include <media/stagefright/MediaErrors.h> 26457116d3a01618acf9a875020ca5860551ba03a6James Dong#include <media/IOMX.h> 270c1bc742181ded4930842b46e9507372f0b1b963James Dong 280c1bc742181ded4930842b46e9507372f0b1b963James Dong 290c1bc742181ded4930842b46e9507372f0b1b963James Dongnamespace android { 300c1bc742181ded4930842b46e9507372f0b1b963James Dong 31457116d3a01618acf9a875020ca5860551ba03a6James Dongstatic const CodecProfileLevel kProfileLevels[] = { 32457116d3a01618acf9a875020ca5860551ba03a6James Dong { OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel1 }, 33457116d3a01618acf9a875020ca5860551ba03a6James Dong { OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel1b }, 34457116d3a01618acf9a875020ca5860551ba03a6James Dong { OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel11 }, 35457116d3a01618acf9a875020ca5860551ba03a6James Dong { OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel12 }, 36457116d3a01618acf9a875020ca5860551ba03a6James Dong { OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel13 }, 37457116d3a01618acf9a875020ca5860551ba03a6James Dong { OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel2 }, 38457116d3a01618acf9a875020ca5860551ba03a6James Dong { OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel21 }, 39457116d3a01618acf9a875020ca5860551ba03a6James Dong { OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel22 }, 40457116d3a01618acf9a875020ca5860551ba03a6James Dong { OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel3 }, 41457116d3a01618acf9a875020ca5860551ba03a6James Dong { OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel31 }, 42457116d3a01618acf9a875020ca5860551ba03a6James Dong { OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel32 }, 43457116d3a01618acf9a875020ca5860551ba03a6James Dong { OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel4 }, 44457116d3a01618acf9a875020ca5860551ba03a6James Dong { OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel41 }, 45457116d3a01618acf9a875020ca5860551ba03a6James Dong { OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel42 }, 46457116d3a01618acf9a875020ca5860551ba03a6James Dong { OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel5 }, 47457116d3a01618acf9a875020ca5860551ba03a6James Dong { OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel51 }, 48457116d3a01618acf9a875020ca5860551ba03a6James Dong}; 49457116d3a01618acf9a875020ca5860551ba03a6James Dong 500c1bc742181ded4930842b46e9507372f0b1b963James DongSoftAVC::SoftAVC( 510c1bc742181ded4930842b46e9507372f0b1b963James Dong const char *name, 520c1bc742181ded4930842b46e9507372f0b1b963James Dong const OMX_CALLBACKTYPE *callbacks, 530c1bc742181ded4930842b46e9507372f0b1b963James Dong OMX_PTR appData, 540c1bc742181ded4930842b46e9507372f0b1b963James Dong OMX_COMPONENTTYPE **component) 557f616d3cc5366a4b8af20d3d0c768e3de1df0666Lajos Molnar : SoftVideoDecoderOMXComponent( 567f616d3cc5366a4b8af20d3d0c768e3de1df0666Lajos Molnar name, "video_decoder.avc", OMX_VIDEO_CodingAVC, 577f616d3cc5366a4b8af20d3d0c768e3de1df0666Lajos Molnar kProfileLevels, ARRAY_SIZE(kProfileLevels), 587f616d3cc5366a4b8af20d3d0c768e3de1df0666Lajos Molnar 320 /* width */, 240 /* height */, callbacks, appData, component), 590c1bc742181ded4930842b46e9507372f0b1b963James Dong mHandle(NULL), 600c1bc742181ded4930842b46e9507372f0b1b963James Dong mInputBufferCount(0), 610c1bc742181ded4930842b46e9507372f0b1b963James Dong mFirstPicture(NULL), 620c1bc742181ded4930842b46e9507372f0b1b963James Dong mFirstPictureId(-1), 630c1bc742181ded4930842b46e9507372f0b1b963James Dong mPicId(0), 640c1bc742181ded4930842b46e9507372f0b1b963James Dong mHeadersDecoded(false), 650c1bc742181ded4930842b46e9507372f0b1b963James Dong mEOSStatus(INPUT_DATA_AVAILABLE), 662961a85f5f00343c115ac8e5dc17de631694fb6eAndreas Huber mSignalledError(false) { 67a0940a569f2bc24b00dc10ce0fa7658b1dc3a3a5Lajos Molnar const size_t kMinCompressionRatio = 2; 68a0940a569f2bc24b00dc10ce0fa7658b1dc3a3a5Lajos Molnar const size_t kMaxOutputBufferSize = 2048 * 2048 * 3 / 2; 697f616d3cc5366a4b8af20d3d0c768e3de1df0666Lajos Molnar initPorts( 70a0940a569f2bc24b00dc10ce0fa7658b1dc3a3a5Lajos Molnar kNumInputBuffers, kMaxOutputBufferSize / kMinCompressionRatio /* minInputBufferSize */, 71a0940a569f2bc24b00dc10ce0fa7658b1dc3a3a5Lajos Molnar kNumOutputBuffers, MEDIA_MIMETYPE_VIDEO_AVC, kMinCompressionRatio); 727f616d3cc5366a4b8af20d3d0c768e3de1df0666Lajos Molnar 730c1bc742181ded4930842b46e9507372f0b1b963James Dong CHECK_EQ(initDecoder(), (status_t)OK); 740c1bc742181ded4930842b46e9507372f0b1b963James Dong} 750c1bc742181ded4930842b46e9507372f0b1b963James Dong 760c1bc742181ded4930842b46e9507372f0b1b963James DongSoftAVC::~SoftAVC() { 770c1bc742181ded4930842b46e9507372f0b1b963James Dong H264SwDecRelease(mHandle); 780c1bc742181ded4930842b46e9507372f0b1b963James Dong mHandle = NULL; 790c1bc742181ded4930842b46e9507372f0b1b963James Dong 800c1bc742181ded4930842b46e9507372f0b1b963James Dong while (mPicToHeaderMap.size() != 0) { 810c1bc742181ded4930842b46e9507372f0b1b963James Dong OMX_BUFFERHEADERTYPE *header = mPicToHeaderMap.editValueAt(0); 820c1bc742181ded4930842b46e9507372f0b1b963James Dong mPicToHeaderMap.removeItemsAt(0); 830c1bc742181ded4930842b46e9507372f0b1b963James Dong delete header; 840c1bc742181ded4930842b46e9507372f0b1b963James Dong header = NULL; 850c1bc742181ded4930842b46e9507372f0b1b963James Dong } 860c1bc742181ded4930842b46e9507372f0b1b963James Dong List<BufferInfo *> &outQueue = getPortQueue(kOutputPortIndex); 870c1bc742181ded4930842b46e9507372f0b1b963James Dong List<BufferInfo *> &inQueue = getPortQueue(kInputPortIndex); 880c1bc742181ded4930842b46e9507372f0b1b963James Dong CHECK(outQueue.empty()); 890c1bc742181ded4930842b46e9507372f0b1b963James Dong CHECK(inQueue.empty()); 900c1bc742181ded4930842b46e9507372f0b1b963James Dong 910c1bc742181ded4930842b46e9507372f0b1b963James Dong delete[] mFirstPicture; 920c1bc742181ded4930842b46e9507372f0b1b963James Dong} 930c1bc742181ded4930842b46e9507372f0b1b963James Dong 940c1bc742181ded4930842b46e9507372f0b1b963James Dongstatus_t SoftAVC::initDecoder() { 95486247017e0bfb9db9994a53a28c0dacfebf8567James Dong // Force decoder to output buffers in display order. 96486247017e0bfb9db9994a53a28c0dacfebf8567James Dong if (H264SwDecInit(&mHandle, 0) == H264SWDEC_OK) { 970c1bc742181ded4930842b46e9507372f0b1b963James Dong return OK; 980c1bc742181ded4930842b46e9507372f0b1b963James Dong } 990c1bc742181ded4930842b46e9507372f0b1b963James Dong return UNKNOWN_ERROR; 1000c1bc742181ded4930842b46e9507372f0b1b963James Dong} 1010c1bc742181ded4930842b46e9507372f0b1b963James Dong 10284333e0475bc911adc16417f4ca327c975cf6c36Andreas Hubervoid SoftAVC::onQueueFilled(OMX_U32 /* portIndex */) { 1032961a85f5f00343c115ac8e5dc17de631694fb6eAndreas Huber if (mSignalledError || mOutputPortSettingsChange != NONE) { 1040c1bc742181ded4930842b46e9507372f0b1b963James Dong return; 1050c1bc742181ded4930842b46e9507372f0b1b963James Dong } 1060c1bc742181ded4930842b46e9507372f0b1b963James Dong 1070c1bc742181ded4930842b46e9507372f0b1b963James Dong if (mEOSStatus == OUTPUT_FRAMES_FLUSHED) { 1080c1bc742181ded4930842b46e9507372f0b1b963James Dong return; 1090c1bc742181ded4930842b46e9507372f0b1b963James Dong } 1100c1bc742181ded4930842b46e9507372f0b1b963James Dong 1110c1bc742181ded4930842b46e9507372f0b1b963James Dong List<BufferInfo *> &inQueue = getPortQueue(kInputPortIndex); 1120c1bc742181ded4930842b46e9507372f0b1b963James Dong List<BufferInfo *> &outQueue = getPortQueue(kOutputPortIndex); 1132309d1a1ff016a31d9aa68272bcb471e64a26cfaAndreas Huber 1142309d1a1ff016a31d9aa68272bcb471e64a26cfaAndreas Huber if (mHeadersDecoded) { 1152309d1a1ff016a31d9aa68272bcb471e64a26cfaAndreas Huber // Dequeue any already decoded output frames to free up space 1162309d1a1ff016a31d9aa68272bcb471e64a26cfaAndreas Huber // in the output queue. 1172309d1a1ff016a31d9aa68272bcb471e64a26cfaAndreas Huber 1182309d1a1ff016a31d9aa68272bcb471e64a26cfaAndreas Huber drainAllOutputBuffers(false /* eos */); 1192309d1a1ff016a31d9aa68272bcb471e64a26cfaAndreas Huber } 1202309d1a1ff016a31d9aa68272bcb471e64a26cfaAndreas Huber 1210c1bc742181ded4930842b46e9507372f0b1b963James Dong H264SwDecRet ret = H264SWDEC_PIC_RDY; 122bf220f3e6e799f28d1599c3c5106e9e15631a91dRonghua Wu bool portWillReset = false; 1230c1bc742181ded4930842b46e9507372f0b1b963James Dong while ((mEOSStatus != INPUT_DATA_AVAILABLE || !inQueue.empty()) 1240c1bc742181ded4930842b46e9507372f0b1b963James Dong && outQueue.size() == kNumOutputBuffers) { 1250c1bc742181ded4930842b46e9507372f0b1b963James Dong 1260c1bc742181ded4930842b46e9507372f0b1b963James Dong if (mEOSStatus == INPUT_EOS_SEEN) { 1272309d1a1ff016a31d9aa68272bcb471e64a26cfaAndreas Huber drainAllOutputBuffers(true /* eos */); 1280c1bc742181ded4930842b46e9507372f0b1b963James Dong return; 1290c1bc742181ded4930842b46e9507372f0b1b963James Dong } 1300c1bc742181ded4930842b46e9507372f0b1b963James Dong 1310c1bc742181ded4930842b46e9507372f0b1b963James Dong BufferInfo *inInfo = *inQueue.begin(); 1320c1bc742181ded4930842b46e9507372f0b1b963James Dong OMX_BUFFERHEADERTYPE *inHeader = inInfo->mHeader; 1330c1bc742181ded4930842b46e9507372f0b1b963James Dong ++mPicId; 1340c1bc742181ded4930842b46e9507372f0b1b963James Dong 1350c1bc742181ded4930842b46e9507372f0b1b963James Dong OMX_BUFFERHEADERTYPE *header = new OMX_BUFFERHEADERTYPE; 1360c1bc742181ded4930842b46e9507372f0b1b963James Dong memset(header, 0, sizeof(OMX_BUFFERHEADERTYPE)); 1370c1bc742181ded4930842b46e9507372f0b1b963James Dong header->nTimeStamp = inHeader->nTimeStamp; 1380c1bc742181ded4930842b46e9507372f0b1b963James Dong header->nFlags = inHeader->nFlags; 1394c44e9fed87ff6363393f2559b150291242da247Marco Nelissen if (header->nFlags & OMX_BUFFERFLAG_EOS) { 1404c44e9fed87ff6363393f2559b150291242da247Marco Nelissen mEOSStatus = INPUT_EOS_SEEN; 1414c44e9fed87ff6363393f2559b150291242da247Marco Nelissen } 1420c1bc742181ded4930842b46e9507372f0b1b963James Dong mPicToHeaderMap.add(mPicId, header); 1430c1bc742181ded4930842b46e9507372f0b1b963James Dong inQueue.erase(inQueue.begin()); 1440c1bc742181ded4930842b46e9507372f0b1b963James Dong 1450c1bc742181ded4930842b46e9507372f0b1b963James Dong H264SwDecInput inPicture; 1460c1bc742181ded4930842b46e9507372f0b1b963James Dong H264SwDecOutput outPicture; 1470c1bc742181ded4930842b46e9507372f0b1b963James Dong memset(&inPicture, 0, sizeof(inPicture)); 1480c1bc742181ded4930842b46e9507372f0b1b963James Dong inPicture.dataLen = inHeader->nFilledLen; 1490c1bc742181ded4930842b46e9507372f0b1b963James Dong inPicture.pStream = inHeader->pBuffer + inHeader->nOffset; 1500c1bc742181ded4930842b46e9507372f0b1b963James Dong inPicture.picId = mPicId; 1510c1bc742181ded4930842b46e9507372f0b1b963James Dong inPicture.intraConcealmentMethod = 1; 1520c1bc742181ded4930842b46e9507372f0b1b963James Dong H264SwDecPicture decodedPicture; 1530c1bc742181ded4930842b46e9507372f0b1b963James Dong 1540c1bc742181ded4930842b46e9507372f0b1b963James Dong while (inPicture.dataLen > 0) { 1550c1bc742181ded4930842b46e9507372f0b1b963James Dong ret = H264SwDecDecode(mHandle, &inPicture, &outPicture); 1560c1bc742181ded4930842b46e9507372f0b1b963James Dong if (ret == H264SWDEC_HDRS_RDY_BUFF_NOT_EMPTY || 1570c1bc742181ded4930842b46e9507372f0b1b963James Dong ret == H264SWDEC_PIC_RDY_BUFF_NOT_EMPTY) { 1580c1bc742181ded4930842b46e9507372f0b1b963James Dong inPicture.dataLen -= (u32)(outPicture.pStrmCurrPos - inPicture.pStream); 1590c1bc742181ded4930842b46e9507372f0b1b963James Dong inPicture.pStream = outPicture.pStrmCurrPos; 1600c1bc742181ded4930842b46e9507372f0b1b963James Dong if (ret == H264SWDEC_HDRS_RDY_BUFF_NOT_EMPTY) { 1610c1bc742181ded4930842b46e9507372f0b1b963James Dong mHeadersDecoded = true; 1620c1bc742181ded4930842b46e9507372f0b1b963James Dong H264SwDecInfo decoderInfo; 1630c1bc742181ded4930842b46e9507372f0b1b963James Dong CHECK(H264SwDecGetInfo(mHandle, &decoderInfo) == H264SWDEC_OK); 1640c1bc742181ded4930842b46e9507372f0b1b963James Dong 165d5a2f55034022f2d0425fa0701894d0c4787b726Ronghua Wu SoftVideoDecoderOMXComponent::CropSettingsMode cropSettingsMode = 166d5a2f55034022f2d0425fa0701894d0c4787b726Ronghua Wu handleCropParams(decoderInfo); 167bf220f3e6e799f28d1599c3c5106e9e15631a91dRonghua Wu handlePortSettingsChange( 168bf220f3e6e799f28d1599c3c5106e9e15631a91dRonghua Wu &portWillReset, decoderInfo.picWidth, decoderInfo.picHeight, 169d5a2f55034022f2d0425fa0701894d0c4787b726Ronghua Wu cropSettingsMode); 1700c1bc742181ded4930842b46e9507372f0b1b963James Dong } 1710c1bc742181ded4930842b46e9507372f0b1b963James Dong } else { 172bf220f3e6e799f28d1599c3c5106e9e15631a91dRonghua Wu if (portWillReset) { 1730c1bc742181ded4930842b46e9507372f0b1b963James Dong if (H264SwDecNextPicture(mHandle, &decodedPicture, 0) 1740c1bc742181ded4930842b46e9507372f0b1b963James Dong == H264SWDEC_PIC_RDY) { 1750c1bc742181ded4930842b46e9507372f0b1b963James Dong 1760c1bc742181ded4930842b46e9507372f0b1b963James Dong // Save this output buffer; otherwise, it will be 1770c1bc742181ded4930842b46e9507372f0b1b963James Dong // lost during dynamic port reconfiguration because 1780c1bc742181ded4930842b46e9507372f0b1b963James Dong // OpenMAX client will delete _all_ output buffers 1790c1bc742181ded4930842b46e9507372f0b1b963James Dong // in the process. 1800c1bc742181ded4930842b46e9507372f0b1b963James Dong saveFirstOutputBuffer( 1810c1bc742181ded4930842b46e9507372f0b1b963James Dong decodedPicture.picId, 1820c1bc742181ded4930842b46e9507372f0b1b963James Dong (uint8_t *)decodedPicture.pOutputPicture); 1830c1bc742181ded4930842b46e9507372f0b1b963James Dong } 1840c1bc742181ded4930842b46e9507372f0b1b963James Dong } 1850c1bc742181ded4930842b46e9507372f0b1b963James Dong inPicture.dataLen = 0; 1860c1bc742181ded4930842b46e9507372f0b1b963James Dong if (ret < 0) { 18729357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Decoder failed: %d", ret); 1882961a85f5f00343c115ac8e5dc17de631694fb6eAndreas Huber 1892961a85f5f00343c115ac8e5dc17de631694fb6eAndreas Huber notify(OMX_EventError, OMX_ErrorUndefined, 1902961a85f5f00343c115ac8e5dc17de631694fb6eAndreas Huber ERROR_MALFORMED, NULL); 1912961a85f5f00343c115ac8e5dc17de631694fb6eAndreas Huber 1922961a85f5f00343c115ac8e5dc17de631694fb6eAndreas Huber mSignalledError = true; 1932961a85f5f00343c115ac8e5dc17de631694fb6eAndreas Huber return; 1940c1bc742181ded4930842b46e9507372f0b1b963James Dong } 1950c1bc742181ded4930842b46e9507372f0b1b963James Dong } 1960c1bc742181ded4930842b46e9507372f0b1b963James Dong } 1970c1bc742181ded4930842b46e9507372f0b1b963James Dong inInfo->mOwnedByUs = false; 1980c1bc742181ded4930842b46e9507372f0b1b963James Dong notifyEmptyBufferDone(inHeader); 1990c1bc742181ded4930842b46e9507372f0b1b963James Dong 200bf220f3e6e799f28d1599c3c5106e9e15631a91dRonghua Wu if (portWillReset) { 2010c1bc742181ded4930842b46e9507372f0b1b963James Dong return; 2020c1bc742181ded4930842b46e9507372f0b1b963James Dong } 2030c1bc742181ded4930842b46e9507372f0b1b963James Dong 2040c1bc742181ded4930842b46e9507372f0b1b963James Dong if (mFirstPicture && !outQueue.empty()) { 2050c1bc742181ded4930842b46e9507372f0b1b963James Dong drainOneOutputBuffer(mFirstPictureId, mFirstPicture); 2060c1bc742181ded4930842b46e9507372f0b1b963James Dong delete[] mFirstPicture; 2070c1bc742181ded4930842b46e9507372f0b1b963James Dong mFirstPicture = NULL; 2080c1bc742181ded4930842b46e9507372f0b1b963James Dong mFirstPictureId = -1; 2090c1bc742181ded4930842b46e9507372f0b1b963James Dong } 2100c1bc742181ded4930842b46e9507372f0b1b963James Dong 2112309d1a1ff016a31d9aa68272bcb471e64a26cfaAndreas Huber drainAllOutputBuffers(false /* eos */); 2120c1bc742181ded4930842b46e9507372f0b1b963James Dong } 2130c1bc742181ded4930842b46e9507372f0b1b963James Dong} 2140c1bc742181ded4930842b46e9507372f0b1b963James Dong 215d5a2f55034022f2d0425fa0701894d0c4787b726Ronghua WuSoftVideoDecoderOMXComponent::CropSettingsMode SoftAVC::handleCropParams( 216d5a2f55034022f2d0425fa0701894d0c4787b726Ronghua Wu const H264SwDecInfo& decInfo) { 217bf220f3e6e799f28d1599c3c5106e9e15631a91dRonghua Wu if (!decInfo.croppingFlag) { 218d5a2f55034022f2d0425fa0701894d0c4787b726Ronghua Wu return kCropUnSet; 2190c1bc742181ded4930842b46e9507372f0b1b963James Dong } 2200c1bc742181ded4930842b46e9507372f0b1b963James Dong 221bf220f3e6e799f28d1599c3c5106e9e15631a91dRonghua Wu const CropParams& crop = decInfo.cropParams; 222bf220f3e6e799f28d1599c3c5106e9e15631a91dRonghua Wu if (mCropLeft == crop.cropLeftOffset && 223bf220f3e6e799f28d1599c3c5106e9e15631a91dRonghua Wu mCropTop == crop.cropTopOffset && 224bf220f3e6e799f28d1599c3c5106e9e15631a91dRonghua Wu mCropWidth == crop.cropOutWidth && 225bf220f3e6e799f28d1599c3c5106e9e15631a91dRonghua Wu mCropHeight == crop.cropOutHeight) { 226d5a2f55034022f2d0425fa0701894d0c4787b726Ronghua Wu return kCropSet; 2270c1bc742181ded4930842b46e9507372f0b1b963James Dong } 228bf220f3e6e799f28d1599c3c5106e9e15631a91dRonghua Wu 229bf220f3e6e799f28d1599c3c5106e9e15631a91dRonghua Wu mCropLeft = crop.cropLeftOffset; 230bf220f3e6e799f28d1599c3c5106e9e15631a91dRonghua Wu mCropTop = crop.cropTopOffset; 231bf220f3e6e799f28d1599c3c5106e9e15631a91dRonghua Wu mCropWidth = crop.cropOutWidth; 232bf220f3e6e799f28d1599c3c5106e9e15631a91dRonghua Wu mCropHeight = crop.cropOutHeight; 233d5a2f55034022f2d0425fa0701894d0c4787b726Ronghua Wu return kCropChanged; 2340c1bc742181ded4930842b46e9507372f0b1b963James Dong} 2350c1bc742181ded4930842b46e9507372f0b1b963James Dong 2360c1bc742181ded4930842b46e9507372f0b1b963James Dongvoid SoftAVC::saveFirstOutputBuffer(int32_t picId, uint8_t *data) { 2370c1bc742181ded4930842b46e9507372f0b1b963James Dong CHECK(mFirstPicture == NULL); 2380c1bc742181ded4930842b46e9507372f0b1b963James Dong mFirstPictureId = picId; 2390c1bc742181ded4930842b46e9507372f0b1b963James Dong 240bf220f3e6e799f28d1599c3c5106e9e15631a91dRonghua Wu uint32_t pictureSize = mWidth * mHeight * 3 / 2; 241bf220f3e6e799f28d1599c3c5106e9e15631a91dRonghua Wu mFirstPicture = new uint8_t[pictureSize]; 242bf220f3e6e799f28d1599c3c5106e9e15631a91dRonghua Wu memcpy(mFirstPicture, data, pictureSize); 2430c1bc742181ded4930842b46e9507372f0b1b963James Dong} 2440c1bc742181ded4930842b46e9507372f0b1b963James Dong 2450c1bc742181ded4930842b46e9507372f0b1b963James Dongvoid SoftAVC::drainOneOutputBuffer(int32_t picId, uint8_t* data) { 2460c1bc742181ded4930842b46e9507372f0b1b963James Dong List<BufferInfo *> &outQueue = getPortQueue(kOutputPortIndex); 2470c1bc742181ded4930842b46e9507372f0b1b963James Dong BufferInfo *outInfo = *outQueue.begin(); 2480c1bc742181ded4930842b46e9507372f0b1b963James Dong outQueue.erase(outQueue.begin()); 2490c1bc742181ded4930842b46e9507372f0b1b963James Dong OMX_BUFFERHEADERTYPE *outHeader = outInfo->mHeader; 2500c1bc742181ded4930842b46e9507372f0b1b963James Dong OMX_BUFFERHEADERTYPE *header = mPicToHeaderMap.valueFor(picId); 2510c1bc742181ded4930842b46e9507372f0b1b963James Dong outHeader->nTimeStamp = header->nTimeStamp; 2520c1bc742181ded4930842b46e9507372f0b1b963James Dong outHeader->nFlags = header->nFlags; 253bf220f3e6e799f28d1599c3c5106e9e15631a91dRonghua Wu outHeader->nFilledLen = mWidth * mHeight * 3 / 2; 254bf220f3e6e799f28d1599c3c5106e9e15631a91dRonghua Wu 255bf220f3e6e799f28d1599c3c5106e9e15631a91dRonghua Wu uint8_t *dst = outHeader->pBuffer + outHeader->nOffset; 256bf220f3e6e799f28d1599c3c5106e9e15631a91dRonghua Wu const uint8_t *srcY = data; 257bf220f3e6e799f28d1599c3c5106e9e15631a91dRonghua Wu const uint8_t *srcU = srcY + mWidth * mHeight; 258bf220f3e6e799f28d1599c3c5106e9e15631a91dRonghua Wu const uint8_t *srcV = srcU + mWidth * mHeight / 4; 259bf220f3e6e799f28d1599c3c5106e9e15631a91dRonghua Wu size_t srcYStride = mWidth; 260bf220f3e6e799f28d1599c3c5106e9e15631a91dRonghua Wu size_t srcUStride = mWidth / 2; 261bf220f3e6e799f28d1599c3c5106e9e15631a91dRonghua Wu size_t srcVStride = srcUStride; 262bf220f3e6e799f28d1599c3c5106e9e15631a91dRonghua Wu copyYV12FrameToOutputBuffer(dst, srcY, srcU, srcV, srcYStride, srcUStride, srcVStride); 263bf220f3e6e799f28d1599c3c5106e9e15631a91dRonghua Wu 2640c1bc742181ded4930842b46e9507372f0b1b963James Dong mPicToHeaderMap.removeItem(picId); 2650c1bc742181ded4930842b46e9507372f0b1b963James Dong delete header; 2660c1bc742181ded4930842b46e9507372f0b1b963James Dong outInfo->mOwnedByUs = false; 2670c1bc742181ded4930842b46e9507372f0b1b963James Dong notifyFillBufferDone(outHeader); 2680c1bc742181ded4930842b46e9507372f0b1b963James Dong} 2690c1bc742181ded4930842b46e9507372f0b1b963James Dong 2702309d1a1ff016a31d9aa68272bcb471e64a26cfaAndreas Hubervoid SoftAVC::drainAllOutputBuffers(bool eos) { 2710c1bc742181ded4930842b46e9507372f0b1b963James Dong List<BufferInfo *> &outQueue = getPortQueue(kOutputPortIndex); 2720c1bc742181ded4930842b46e9507372f0b1b963James Dong H264SwDecPicture decodedPicture; 2730c1bc742181ded4930842b46e9507372f0b1b963James Dong 2742309d1a1ff016a31d9aa68272bcb471e64a26cfaAndreas Huber if (mHeadersDecoded) { 2752309d1a1ff016a31d9aa68272bcb471e64a26cfaAndreas Huber while (!outQueue.empty() 2762309d1a1ff016a31d9aa68272bcb471e64a26cfaAndreas Huber && H264SWDEC_PIC_RDY == H264SwDecNextPicture( 2772309d1a1ff016a31d9aa68272bcb471e64a26cfaAndreas Huber mHandle, &decodedPicture, eos /* flush */)) { 2782309d1a1ff016a31d9aa68272bcb471e64a26cfaAndreas Huber int32_t picId = decodedPicture.picId; 2792309d1a1ff016a31d9aa68272bcb471e64a26cfaAndreas Huber uint8_t *data = (uint8_t *) decodedPicture.pOutputPicture; 2802309d1a1ff016a31d9aa68272bcb471e64a26cfaAndreas Huber drainOneOutputBuffer(picId, data); 2812309d1a1ff016a31d9aa68272bcb471e64a26cfaAndreas Huber } 2822309d1a1ff016a31d9aa68272bcb471e64a26cfaAndreas Huber } 2832309d1a1ff016a31d9aa68272bcb471e64a26cfaAndreas Huber 2842309d1a1ff016a31d9aa68272bcb471e64a26cfaAndreas Huber if (!eos) { 2852309d1a1ff016a31d9aa68272bcb471e64a26cfaAndreas Huber return; 2862309d1a1ff016a31d9aa68272bcb471e64a26cfaAndreas Huber } 2872309d1a1ff016a31d9aa68272bcb471e64a26cfaAndreas Huber 2880c1bc742181ded4930842b46e9507372f0b1b963James Dong while (!outQueue.empty()) { 2890c1bc742181ded4930842b46e9507372f0b1b963James Dong BufferInfo *outInfo = *outQueue.begin(); 2900c1bc742181ded4930842b46e9507372f0b1b963James Dong outQueue.erase(outQueue.begin()); 2910c1bc742181ded4930842b46e9507372f0b1b963James Dong OMX_BUFFERHEADERTYPE *outHeader = outInfo->mHeader; 2920c1bc742181ded4930842b46e9507372f0b1b963James Dong 2932309d1a1ff016a31d9aa68272bcb471e64a26cfaAndreas Huber outHeader->nTimeStamp = 0; 2942309d1a1ff016a31d9aa68272bcb471e64a26cfaAndreas Huber outHeader->nFilledLen = 0; 2952309d1a1ff016a31d9aa68272bcb471e64a26cfaAndreas Huber outHeader->nFlags = OMX_BUFFERFLAG_EOS; 2960c1bc742181ded4930842b46e9507372f0b1b963James Dong 2970c1bc742181ded4930842b46e9507372f0b1b963James Dong outInfo->mOwnedByUs = false; 2980c1bc742181ded4930842b46e9507372f0b1b963James Dong notifyFillBufferDone(outHeader); 2990c1bc742181ded4930842b46e9507372f0b1b963James Dong 3002309d1a1ff016a31d9aa68272bcb471e64a26cfaAndreas Huber mEOSStatus = OUTPUT_FRAMES_FLUSHED; 3012309d1a1ff016a31d9aa68272bcb471e64a26cfaAndreas Huber } 3020c1bc742181ded4930842b46e9507372f0b1b963James Dong} 3030c1bc742181ded4930842b46e9507372f0b1b963James Dong 3040c1bc742181ded4930842b46e9507372f0b1b963James Dongvoid SoftAVC::onPortFlushCompleted(OMX_U32 portIndex) { 3050c1bc742181ded4930842b46e9507372f0b1b963James Dong if (portIndex == kInputPortIndex) { 3060c1bc742181ded4930842b46e9507372f0b1b963James Dong mEOSStatus = INPUT_DATA_AVAILABLE; 3070c1bc742181ded4930842b46e9507372f0b1b963James Dong } 3080c1bc742181ded4930842b46e9507372f0b1b963James Dong} 3090c1bc742181ded4930842b46e9507372f0b1b963James Dong 310d94e716af0e49d775f0c0c4f36dd2c136ba5f2b2Andreas Hubervoid SoftAVC::onReset() { 3117f616d3cc5366a4b8af20d3d0c768e3de1df0666Lajos Molnar SoftVideoDecoderOMXComponent::onReset(); 312d94e716af0e49d775f0c0c4f36dd2c136ba5f2b2Andreas Huber mSignalledError = false; 3130c1bc742181ded4930842b46e9507372f0b1b963James Dong} 3140c1bc742181ded4930842b46e9507372f0b1b963James Dong 3150c1bc742181ded4930842b46e9507372f0b1b963James Dong} // namespace android 3160c1bc742181ded4930842b46e9507372f0b1b963James Dong 3170c1bc742181ded4930842b46e9507372f0b1b963James Dongandroid::SoftOMXComponent *createSoftOMXComponent( 3180c1bc742181ded4930842b46e9507372f0b1b963James Dong const char *name, const OMX_CALLBACKTYPE *callbacks, 3190c1bc742181ded4930842b46e9507372f0b1b963James Dong OMX_PTR appData, OMX_COMPONENTTYPE **component) { 3200c1bc742181ded4930842b46e9507372f0b1b963James Dong return new android::SoftAVC(name, callbacks, appData, component); 3210c1bc742181ded4930842b46e9507372f0b1b963James Dong} 322