Home | History | Annotate | Download | only in dec
      1 /*
      2  * Copyright (C) 2011 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 //#define LOG_NDEBUG 0
     18 #define LOG_TAG "SoftMPEG4"
     19 #include <utils/Log.h>
     20 
     21 #include "SoftMPEG4.h"
     22 
     23 #include <media/stagefright/foundation/ADebug.h>
     24 #include <media/stagefright/MediaDefs.h>
     25 #include <media/stagefright/MediaErrors.h>
     26 #include <media/IOMX.h>
     27 
     28 #include "mp4dec_api.h"
     29 
     30 namespace android {
     31 
     32 static const CodecProfileLevel kM4VProfileLevels[] = {
     33     { OMX_VIDEO_MPEG4ProfileSimple, OMX_VIDEO_MPEG4Level0 },
     34     { OMX_VIDEO_MPEG4ProfileSimple, OMX_VIDEO_MPEG4Level0b },
     35     { OMX_VIDEO_MPEG4ProfileSimple, OMX_VIDEO_MPEG4Level1 },
     36     { OMX_VIDEO_MPEG4ProfileSimple, OMX_VIDEO_MPEG4Level2 },
     37     { OMX_VIDEO_MPEG4ProfileSimple, OMX_VIDEO_MPEG4Level3 },
     38 };
     39 
     40 static const CodecProfileLevel kH263ProfileLevels[] = {
     41     { OMX_VIDEO_H263ProfileBaseline, OMX_VIDEO_H263Level10 },
     42     { OMX_VIDEO_H263ProfileBaseline, OMX_VIDEO_H263Level20 },
     43     { OMX_VIDEO_H263ProfileBaseline, OMX_VIDEO_H263Level30 },
     44     { OMX_VIDEO_H263ProfileBaseline, OMX_VIDEO_H263Level45 },
     45     { OMX_VIDEO_H263ProfileISWV2,    OMX_VIDEO_H263Level10 },
     46     { OMX_VIDEO_H263ProfileISWV2,    OMX_VIDEO_H263Level20 },
     47     { OMX_VIDEO_H263ProfileISWV2,    OMX_VIDEO_H263Level30 },
     48     { OMX_VIDEO_H263ProfileISWV2,    OMX_VIDEO_H263Level45 },
     49 };
     50 
     51 template<class T>
     52 static void InitOMXParams(T *params) {
     53     params->nSize = sizeof(T);
     54     params->nVersion.s.nVersionMajor = 1;
     55     params->nVersion.s.nVersionMinor = 0;
     56     params->nVersion.s.nRevision = 0;
     57     params->nVersion.s.nStep = 0;
     58 }
     59 
     60 SoftMPEG4::SoftMPEG4(
     61         const char *name,
     62         const OMX_CALLBACKTYPE *callbacks,
     63         OMX_PTR appData,
     64         OMX_COMPONENTTYPE **component)
     65     : SimpleSoftOMXComponent(name, callbacks, appData, component),
     66       mMode(MODE_MPEG4),
     67       mHandle(new tagvideoDecControls),
     68       mInputBufferCount(0),
     69       mWidth(352),
     70       mHeight(288),
     71       mCropLeft(0),
     72       mCropTop(0),
     73       mCropRight(mWidth - 1),
     74       mCropBottom(mHeight - 1),
     75       mSignalledError(false),
     76       mInitialized(false),
     77       mFramesConfigured(false),
     78       mNumSamplesOutput(0),
     79       mOutputPortSettingsChange(NONE) {
     80     if (!strcmp(name, "OMX.google.h263.decoder")) {
     81         mMode = MODE_H263;
     82     } else {
     83         CHECK(!strcmp(name, "OMX.google.mpeg4.decoder"));
     84     }
     85 
     86     initPorts();
     87     CHECK_EQ(initDecoder(), (status_t)OK);
     88 }
     89 
     90 SoftMPEG4::~SoftMPEG4() {
     91     if (mInitialized) {
     92         PVCleanUpVideoDecoder(mHandle);
     93     }
     94 
     95     delete mHandle;
     96     mHandle = NULL;
     97 }
     98 
     99 void SoftMPEG4::initPorts() {
    100     OMX_PARAM_PORTDEFINITIONTYPE def;
    101     InitOMXParams(&def);
    102 
    103     def.nPortIndex = 0;
    104     def.eDir = OMX_DirInput;
    105     def.nBufferCountMin = kNumInputBuffers;
    106     def.nBufferCountActual = def.nBufferCountMin;
    107     def.nBufferSize = 8192;
    108     def.bEnabled = OMX_TRUE;
    109     def.bPopulated = OMX_FALSE;
    110     def.eDomain = OMX_PortDomainVideo;
    111     def.bBuffersContiguous = OMX_FALSE;
    112     def.nBufferAlignment = 1;
    113 
    114     def.format.video.cMIMEType =
    115         (mMode == MODE_MPEG4)
    116             ? const_cast<char *>(MEDIA_MIMETYPE_VIDEO_MPEG4)
    117             : const_cast<char *>(MEDIA_MIMETYPE_VIDEO_H263);
    118 
    119     def.format.video.pNativeRender = NULL;
    120     def.format.video.nFrameWidth = mWidth;
    121     def.format.video.nFrameHeight = mHeight;
    122     def.format.video.nStride = def.format.video.nFrameWidth;
    123     def.format.video.nSliceHeight = def.format.video.nFrameHeight;
    124     def.format.video.nBitrate = 0;
    125     def.format.video.xFramerate = 0;
    126     def.format.video.bFlagErrorConcealment = OMX_FALSE;
    127 
    128     def.format.video.eCompressionFormat =
    129         mMode == MODE_MPEG4 ? OMX_VIDEO_CodingMPEG4 : OMX_VIDEO_CodingH263;
    130 
    131     def.format.video.eColorFormat = OMX_COLOR_FormatUnused;
    132     def.format.video.pNativeWindow = NULL;
    133 
    134     addPort(def);
    135 
    136     def.nPortIndex = 1;
    137     def.eDir = OMX_DirOutput;
    138     def.nBufferCountMin = kNumOutputBuffers;
    139     def.nBufferCountActual = def.nBufferCountMin;
    140     def.bEnabled = OMX_TRUE;
    141     def.bPopulated = OMX_FALSE;
    142     def.eDomain = OMX_PortDomainVideo;
    143     def.bBuffersContiguous = OMX_FALSE;
    144     def.nBufferAlignment = 2;
    145 
    146     def.format.video.cMIMEType = const_cast<char *>(MEDIA_MIMETYPE_VIDEO_RAW);
    147     def.format.video.pNativeRender = NULL;
    148     def.format.video.nFrameWidth = mWidth;
    149     def.format.video.nFrameHeight = mHeight;
    150     def.format.video.nStride = def.format.video.nFrameWidth;
    151     def.format.video.nSliceHeight = def.format.video.nFrameHeight;
    152     def.format.video.nBitrate = 0;
    153     def.format.video.xFramerate = 0;
    154     def.format.video.bFlagErrorConcealment = OMX_FALSE;
    155     def.format.video.eCompressionFormat = OMX_VIDEO_CodingUnused;
    156     def.format.video.eColorFormat = OMX_COLOR_FormatYUV420Planar;
    157     def.format.video.pNativeWindow = NULL;
    158 
    159     def.nBufferSize =
    160         (def.format.video.nFrameWidth * def.format.video.nFrameHeight * 3) / 2;
    161 
    162     addPort(def);
    163 }
    164 
    165 status_t SoftMPEG4::initDecoder() {
    166     memset(mHandle, 0, sizeof(tagvideoDecControls));
    167     return OK;
    168 }
    169 
    170 OMX_ERRORTYPE SoftMPEG4::internalGetParameter(
    171         OMX_INDEXTYPE index, OMX_PTR params) {
    172     switch (index) {
    173         case OMX_IndexParamVideoPortFormat:
    174         {
    175             OMX_VIDEO_PARAM_PORTFORMATTYPE *formatParams =
    176                 (OMX_VIDEO_PARAM_PORTFORMATTYPE *)params;
    177 
    178             if (formatParams->nPortIndex > 1) {
    179                 return OMX_ErrorUndefined;
    180             }
    181 
    182             if (formatParams->nIndex != 0) {
    183                 return OMX_ErrorNoMore;
    184             }
    185 
    186             if (formatParams->nPortIndex == 0) {
    187                 formatParams->eCompressionFormat =
    188                     (mMode == MODE_MPEG4)
    189                         ? OMX_VIDEO_CodingMPEG4 : OMX_VIDEO_CodingH263;
    190 
    191                 formatParams->eColorFormat = OMX_COLOR_FormatUnused;
    192                 formatParams->xFramerate = 0;
    193             } else {
    194                 CHECK_EQ(formatParams->nPortIndex, 1u);
    195 
    196                 formatParams->eCompressionFormat = OMX_VIDEO_CodingUnused;
    197                 formatParams->eColorFormat = OMX_COLOR_FormatYUV420Planar;
    198                 formatParams->xFramerate = 0;
    199             }
    200 
    201             return OMX_ErrorNone;
    202         }
    203 
    204         case OMX_IndexParamVideoProfileLevelQuerySupported:
    205         {
    206             OMX_VIDEO_PARAM_PROFILELEVELTYPE *profileLevel =
    207                     (OMX_VIDEO_PARAM_PROFILELEVELTYPE *) params;
    208 
    209             if (profileLevel->nPortIndex != 0) {  // Input port only
    210                 ALOGE("Invalid port index: %ld", profileLevel->nPortIndex);
    211                 return OMX_ErrorUnsupportedIndex;
    212             }
    213 
    214             size_t index = profileLevel->nProfileIndex;
    215             if (mMode == MODE_H263) {
    216                 size_t nProfileLevels =
    217                     sizeof(kH263ProfileLevels) / sizeof(kH263ProfileLevels[0]);
    218                 if (index >= nProfileLevels) {
    219                     return OMX_ErrorNoMore;
    220                 }
    221 
    222                 profileLevel->eProfile = kH263ProfileLevels[index].mProfile;
    223                 profileLevel->eLevel = kH263ProfileLevels[index].mLevel;
    224             } else {
    225                 size_t nProfileLevels =
    226                     sizeof(kM4VProfileLevels) / sizeof(kM4VProfileLevels[0]);
    227                 if (index >= nProfileLevels) {
    228                     return OMX_ErrorNoMore;
    229                 }
    230 
    231                 profileLevel->eProfile = kM4VProfileLevels[index].mProfile;
    232                 profileLevel->eLevel = kM4VProfileLevels[index].mLevel;
    233             }
    234             return OMX_ErrorNone;
    235         }
    236 
    237         default:
    238             return SimpleSoftOMXComponent::internalGetParameter(index, params);
    239     }
    240 }
    241 
    242 OMX_ERRORTYPE SoftMPEG4::internalSetParameter(
    243         OMX_INDEXTYPE index, const OMX_PTR params) {
    244     switch (index) {
    245         case OMX_IndexParamStandardComponentRole:
    246         {
    247             const OMX_PARAM_COMPONENTROLETYPE *roleParams =
    248                 (const OMX_PARAM_COMPONENTROLETYPE *)params;
    249 
    250             if (mMode == MODE_MPEG4) {
    251                 if (strncmp((const char *)roleParams->cRole,
    252                             "video_decoder.mpeg4",
    253                             OMX_MAX_STRINGNAME_SIZE - 1)) {
    254                     return OMX_ErrorUndefined;
    255                 }
    256             } else {
    257                 if (strncmp((const char *)roleParams->cRole,
    258                             "video_decoder.h263",
    259                             OMX_MAX_STRINGNAME_SIZE - 1)) {
    260                     return OMX_ErrorUndefined;
    261                 }
    262             }
    263 
    264             return OMX_ErrorNone;
    265         }
    266 
    267         case OMX_IndexParamVideoPortFormat:
    268         {
    269             OMX_VIDEO_PARAM_PORTFORMATTYPE *formatParams =
    270                 (OMX_VIDEO_PARAM_PORTFORMATTYPE *)params;
    271 
    272             if (formatParams->nPortIndex > 1) {
    273                 return OMX_ErrorUndefined;
    274             }
    275 
    276             if (formatParams->nIndex != 0) {
    277                 return OMX_ErrorNoMore;
    278             }
    279 
    280             return OMX_ErrorNone;
    281         }
    282 
    283         default:
    284             return SimpleSoftOMXComponent::internalSetParameter(index, params);
    285     }
    286 }
    287 
    288 OMX_ERRORTYPE SoftMPEG4::getConfig(
    289         OMX_INDEXTYPE index, OMX_PTR params) {
    290     switch (index) {
    291         case OMX_IndexConfigCommonOutputCrop:
    292         {
    293             OMX_CONFIG_RECTTYPE *rectParams = (OMX_CONFIG_RECTTYPE *)params;
    294 
    295             if (rectParams->nPortIndex != 1) {
    296                 return OMX_ErrorUndefined;
    297             }
    298 
    299             rectParams->nLeft = mCropLeft;
    300             rectParams->nTop = mCropTop;
    301             rectParams->nWidth = mCropRight - mCropLeft + 1;
    302             rectParams->nHeight = mCropBottom - mCropTop + 1;
    303 
    304             return OMX_ErrorNone;
    305         }
    306 
    307         default:
    308             return OMX_ErrorUnsupportedIndex;
    309     }
    310 }
    311 
    312 void SoftMPEG4::onQueueFilled(OMX_U32 portIndex) {
    313     if (mSignalledError || mOutputPortSettingsChange != NONE) {
    314         return;
    315     }
    316 
    317     List<BufferInfo *> &inQueue = getPortQueue(0);
    318     List<BufferInfo *> &outQueue = getPortQueue(1);
    319 
    320     while (!inQueue.empty() && outQueue.size() == kNumOutputBuffers) {
    321         BufferInfo *inInfo = *inQueue.begin();
    322         OMX_BUFFERHEADERTYPE *inHeader = inInfo->mHeader;
    323 
    324         PortInfo *port = editPortInfo(1);
    325 
    326         OMX_BUFFERHEADERTYPE *outHeader =
    327             port->mBuffers.editItemAt(mNumSamplesOutput & 1).mHeader;
    328 
    329         if (inHeader->nFlags & OMX_BUFFERFLAG_EOS) {
    330             inQueue.erase(inQueue.begin());
    331             inInfo->mOwnedByUs = false;
    332             notifyEmptyBufferDone(inHeader);
    333 
    334             ++mInputBufferCount;
    335 
    336             outHeader->nFilledLen = 0;
    337             outHeader->nFlags = OMX_BUFFERFLAG_EOS;
    338 
    339             List<BufferInfo *>::iterator it = outQueue.begin();
    340             while ((*it)->mHeader != outHeader) {
    341                 ++it;
    342             }
    343 
    344             BufferInfo *outInfo = *it;
    345             outInfo->mOwnedByUs = false;
    346             outQueue.erase(it);
    347             outInfo = NULL;
    348 
    349             notifyFillBufferDone(outHeader);
    350             outHeader = NULL;
    351             return;
    352         }
    353 
    354         uint8_t *bitstream = inHeader->pBuffer + inHeader->nOffset;
    355 
    356         if (!mInitialized) {
    357             uint8_t *vol_data[1];
    358             int32_t vol_size = 0;
    359 
    360             vol_data[0] = NULL;
    361 
    362             if (inHeader->nFlags & OMX_BUFFERFLAG_CODECCONFIG) {
    363                 vol_data[0] = bitstream;
    364                 vol_size = inHeader->nFilledLen;
    365             }
    366 
    367             MP4DecodingMode mode =
    368                 (mMode == MODE_MPEG4) ? MPEG4_MODE : H263_MODE;
    369 
    370             Bool success = PVInitVideoDecoder(
    371                     mHandle, vol_data, &vol_size, 1, mWidth, mHeight, mode);
    372 
    373             if (!success) {
    374                 ALOGW("PVInitVideoDecoder failed. Unsupported content?");
    375 
    376                 notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL);
    377                 mSignalledError = true;
    378                 return;
    379             }
    380 
    381             MP4DecodingMode actualMode = PVGetDecBitstreamMode(mHandle);
    382             if (mode != actualMode) {
    383                 notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL);
    384                 mSignalledError = true;
    385                 return;
    386             }
    387 
    388             PVSetPostProcType((VideoDecControls *) mHandle, 0);
    389 
    390             if (inHeader->nFlags & OMX_BUFFERFLAG_CODECCONFIG) {
    391                 inInfo->mOwnedByUs = false;
    392                 inQueue.erase(inQueue.begin());
    393                 inInfo = NULL;
    394                 notifyEmptyBufferDone(inHeader);
    395                 inHeader = NULL;
    396             }
    397 
    398             mInitialized = true;
    399 
    400             if (mode == MPEG4_MODE && portSettingsChanged()) {
    401                 return;
    402             }
    403 
    404             continue;
    405         }
    406 
    407         if (!mFramesConfigured) {
    408             PortInfo *port = editPortInfo(1);
    409             OMX_BUFFERHEADERTYPE *outHeader = port->mBuffers.editItemAt(1).mHeader;
    410 
    411             PVSetReferenceYUV(mHandle, outHeader->pBuffer);
    412 
    413             mFramesConfigured = true;
    414         }
    415 
    416         uint32_t useExtTimestamp = (inHeader->nOffset == 0);
    417 
    418         // decoder deals in ms, OMX in us.
    419         uint32_t timestamp =
    420             useExtTimestamp ? (inHeader->nTimeStamp + 500) / 1000 : 0xFFFFFFFF;
    421 
    422         int32_t bufferSize = inHeader->nFilledLen;
    423         int32_t tmp = bufferSize;
    424 
    425         // The PV decoder is lying to us, sometimes it'll claim to only have
    426         // consumed a subset of the buffer when it clearly consumed all of it.
    427         // ignore whatever it says...
    428         if (PVDecodeVideoFrame(
    429                     mHandle, &bitstream, &timestamp, &tmp,
    430                     &useExtTimestamp,
    431                     outHeader->pBuffer) != PV_TRUE) {
    432             ALOGE("failed to decode video frame.");
    433 
    434             notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL);
    435             mSignalledError = true;
    436             return;
    437         }
    438 
    439         if (portSettingsChanged()) {
    440             return;
    441         }
    442 
    443         // decoder deals in ms, OMX in us.
    444         outHeader->nTimeStamp = timestamp * 1000;
    445 
    446         inHeader->nOffset += bufferSize;
    447         inHeader->nFilledLen = 0;
    448 
    449         if (inHeader->nFilledLen == 0) {
    450             inInfo->mOwnedByUs = false;
    451             inQueue.erase(inQueue.begin());
    452             inInfo = NULL;
    453             notifyEmptyBufferDone(inHeader);
    454             inHeader = NULL;
    455         }
    456 
    457         ++mInputBufferCount;
    458 
    459         outHeader->nOffset = 0;
    460         outHeader->nFilledLen = (mWidth * mHeight * 3) / 2;
    461         outHeader->nFlags = 0;
    462 
    463         List<BufferInfo *>::iterator it = outQueue.begin();
    464         while ((*it)->mHeader != outHeader) {
    465             ++it;
    466         }
    467 
    468         BufferInfo *outInfo = *it;
    469         outInfo->mOwnedByUs = false;
    470         outQueue.erase(it);
    471         outInfo = NULL;
    472 
    473         notifyFillBufferDone(outHeader);
    474         outHeader = NULL;
    475 
    476         ++mNumSamplesOutput;
    477     }
    478 }
    479 
    480 bool SoftMPEG4::portSettingsChanged() {
    481     int32_t disp_width, disp_height;
    482     PVGetVideoDimensions(mHandle, &disp_width, &disp_height);
    483 
    484     int32_t buf_width, buf_height;
    485     PVGetBufferDimensions(mHandle, &buf_width, &buf_height);
    486 
    487     CHECK_LE(disp_width, buf_width);
    488     CHECK_LE(disp_height, buf_height);
    489 
    490     ALOGV("disp_width = %d, disp_height = %d, buf_width = %d, buf_height = %d",
    491             disp_width, disp_height, buf_width, buf_height);
    492 
    493     if (mCropRight != disp_width - 1
    494             || mCropBottom != disp_height - 1) {
    495         mCropLeft = 0;
    496         mCropTop = 0;
    497         mCropRight = disp_width - 1;
    498         mCropBottom = disp_height - 1;
    499 
    500         notify(OMX_EventPortSettingsChanged,
    501                1,
    502                OMX_IndexConfigCommonOutputCrop,
    503                NULL);
    504     }
    505 
    506     if (buf_width != mWidth || buf_height != mHeight) {
    507         mWidth = buf_width;
    508         mHeight = buf_height;
    509 
    510         updatePortDefinitions();
    511 
    512         if (mMode == MODE_H263) {
    513             PVCleanUpVideoDecoder(mHandle);
    514 
    515             uint8_t *vol_data[1];
    516             int32_t vol_size = 0;
    517 
    518             vol_data[0] = NULL;
    519             if (!PVInitVideoDecoder(
    520                     mHandle, vol_data, &vol_size, 1, mWidth, mHeight,
    521                     H263_MODE)) {
    522                 notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL);
    523                 mSignalledError = true;
    524                 return true;
    525             }
    526         }
    527 
    528         mFramesConfigured = false;
    529 
    530         notify(OMX_EventPortSettingsChanged, 1, 0, NULL);
    531         mOutputPortSettingsChange = AWAITING_DISABLED;
    532         return true;
    533     }
    534 
    535     return false;
    536 }
    537 
    538 void SoftMPEG4::onPortFlushCompleted(OMX_U32 portIndex) {
    539     if (portIndex == 0 && mInitialized) {
    540         CHECK_EQ((int)PVResetVideoDecoder(mHandle), (int)PV_TRUE);
    541     }
    542 }
    543 
    544 void SoftMPEG4::onPortEnableCompleted(OMX_U32 portIndex, bool enabled) {
    545     if (portIndex != 1) {
    546         return;
    547     }
    548 
    549     switch (mOutputPortSettingsChange) {
    550         case NONE:
    551             break;
    552 
    553         case AWAITING_DISABLED:
    554         {
    555             CHECK(!enabled);
    556             mOutputPortSettingsChange = AWAITING_ENABLED;
    557             break;
    558         }
    559 
    560         default:
    561         {
    562             CHECK_EQ((int)mOutputPortSettingsChange, (int)AWAITING_ENABLED);
    563             CHECK(enabled);
    564             mOutputPortSettingsChange = NONE;
    565             break;
    566         }
    567     }
    568 }
    569 
    570 void SoftMPEG4::updatePortDefinitions() {
    571     OMX_PARAM_PORTDEFINITIONTYPE *def = &editPortInfo(0)->mDef;
    572     def->format.video.nFrameWidth = mWidth;
    573     def->format.video.nFrameHeight = mHeight;
    574     def->format.video.nStride = def->format.video.nFrameWidth;
    575     def->format.video.nSliceHeight = def->format.video.nFrameHeight;
    576 
    577     def = &editPortInfo(1)->mDef;
    578     def->format.video.nFrameWidth = mWidth;
    579     def->format.video.nFrameHeight = mHeight;
    580     def->format.video.nStride = def->format.video.nFrameWidth;
    581     def->format.video.nSliceHeight = def->format.video.nFrameHeight;
    582 
    583     def->nBufferSize =
    584         (((def->format.video.nFrameWidth + 15) & -16)
    585             * ((def->format.video.nFrameHeight + 15) & -16) * 3) / 2;
    586 }
    587 
    588 }  // namespace android
    589 
    590 android::SoftOMXComponent *createSoftOMXComponent(
    591         const char *name, const OMX_CALLBACKTYPE *callbacks,
    592         OMX_PTR appData, OMX_COMPONENTTYPE **component) {
    593     return new android::SoftMPEG4(name, callbacks, appData, component);
    594 }
    595 
    596