Home | History | Annotate | Download | only in src
      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 *************************************************************************
     18 * @file   VideoEditorVideoDecoder.cpp
     19 * @brief  StageFright shell video decoder
     20 *************************************************************************
     21 */
     22 #define LOG_NDEBUG 1
     23 #define LOG_TAG "VIDEOEDITOR_VIDEODECODER"
     24 /*******************
     25  *     HEADERS     *
     26  *******************/
     27 
     28 #include "VideoEditorVideoDecoder_internal.h"
     29 #include "VideoEditorUtils.h"
     30 #include "M4VD_Tools.h"
     31 
     32 #include <media/stagefright/MetaData.h>
     33 #include <media/stagefright/MediaDefs.h>
     34 #include <media/stagefright/MediaDebug.h>
     35 /********************
     36  *   DEFINITIONS    *
     37  ********************/
     38 #define MAX_DEC_BUFFERS 10
     39 
     40 /********************
     41  *   SOURCE CLASS   *
     42  ********************/
     43 using namespace android;
     44 static M4OSA_ERR copyBufferToQueue(
     45     VideoEditorVideoDecoder_Context* pDecShellContext,
     46     MediaBuffer* pDecodedBuffer);
     47 
     48 class VideoEditorVideoDecoderSource : public MediaSource {
     49     public:
     50 
     51         VideoEditorVideoDecoderSource(
     52             const sp<MetaData> &format,
     53             VIDEOEDITOR_CodecType codecType,
     54             void *decoderShellContext);
     55 
     56         virtual status_t start(MetaData *params = NULL);
     57         virtual status_t stop();
     58         virtual sp<MetaData> getFormat();
     59         virtual status_t read(
     60             MediaBuffer **buffer, const ReadOptions *options = NULL);
     61 
     62     protected :
     63         virtual ~VideoEditorVideoDecoderSource();
     64 
     65     private:
     66         sp<MetaData> mFormat;
     67         MediaBuffer* mBuffer;
     68         MediaBufferGroup* mGroup;
     69         Mutex mLock;
     70         VideoEditorVideoDecoder_Context* mpDecShellContext;
     71         int32_t mMaxAUSize;
     72         bool mStarted;
     73         VIDEOEDITOR_CodecType mCodecType;
     74 
     75         // Don't call me
     76         VideoEditorVideoDecoderSource(const VideoEditorVideoDecoderSource &);
     77         VideoEditorVideoDecoderSource &operator=(
     78             const VideoEditorVideoDecoderSource &);
     79 };
     80 
     81 VideoEditorVideoDecoderSource::VideoEditorVideoDecoderSource(
     82         const sp<MetaData> &format, VIDEOEDITOR_CodecType codecType,
     83         void *decoderShellContext) :
     84         mFormat(format),
     85         mBuffer(NULL),
     86         mGroup(NULL),
     87         mStarted(false),
     88         mCodecType(codecType) {
     89     mpDecShellContext = (VideoEditorVideoDecoder_Context*) decoderShellContext;
     90 }
     91 
     92 VideoEditorVideoDecoderSource::~VideoEditorVideoDecoderSource() {
     93     if (mStarted == true) {
     94         stop();
     95     }
     96 }
     97 
     98 status_t VideoEditorVideoDecoderSource::start(
     99         MetaData *params) {
    100 
    101     if (!mStarted) {
    102         if (mFormat->findInt32(kKeyMaxInputSize, &mMaxAUSize) == false) {
    103             LOGE("Could not find kKeyMaxInputSize");
    104             return ERROR_MALFORMED;
    105         }
    106 
    107         mGroup = new MediaBufferGroup;
    108         if (mGroup == NULL) {
    109             LOGE("FATAL: memory limitation ! ");
    110             return NO_MEMORY;
    111         }
    112 
    113         mGroup->add_buffer(new MediaBuffer(mMaxAUSize));
    114 
    115         mStarted = true;
    116     }
    117     return OK;
    118 }
    119 
    120 status_t VideoEditorVideoDecoderSource::stop() {
    121     if (mStarted) {
    122         if (mBuffer != NULL) {
    123 
    124             // FIXME:
    125             // Why do we need to check on the ref count?
    126             int ref_count = mBuffer->refcount();
    127             LOGV("MediaBuffer refcount is %d",ref_count);
    128             for (int i = 0; i < ref_count; ++i) {
    129                 mBuffer->release();
    130             }
    131 
    132             mBuffer = NULL;
    133         }
    134         delete mGroup;
    135         mGroup = NULL;
    136         mStarted = false;
    137     }
    138     return OK;
    139 }
    140 
    141 sp<MetaData> VideoEditorVideoDecoderSource::getFormat() {
    142     Mutex::Autolock autolock(mLock);
    143 
    144     return mFormat;
    145 }
    146 
    147 status_t VideoEditorVideoDecoderSource::read(MediaBuffer** buffer_out,
    148         const ReadOptions *options) {
    149 
    150     Mutex::Autolock autolock(mLock);
    151     if (options != NULL) {
    152         int64_t time_us;
    153         MediaSource::ReadOptions::SeekMode mode;
    154         options->getSeekTo(&time_us, &mode);
    155         if (mode != MediaSource::ReadOptions::SEEK_PREVIOUS_SYNC) {
    156             LOGE("Unexpected read options");
    157             return BAD_VALUE;
    158         }
    159 
    160         M4OSA_ERR err;
    161         M4OSA_Int32 rapTime = time_us / 1000;
    162 
    163         /*--- Retrieve the previous RAP time ---*/
    164         err = mpDecShellContext->m_pReaderGlobal->m_pFctGetPrevRapTime(
    165                   mpDecShellContext->m_pReader->m_readerContext,
    166                   (M4_StreamHandler*)mpDecShellContext->m_pVideoStreamhandler,
    167                   &rapTime);
    168 
    169         if (err == M4WAR_READER_INFORMATION_NOT_PRESENT) {
    170             /* No RAP table, jump backward and predecode */
    171             rapTime -= 40000;
    172             if(rapTime < 0) rapTime = 0;
    173         } else if (err != OK) {
    174             LOGE("get rap time error = 0x%x\n", (uint32_t)err);
    175             return UNKNOWN_ERROR;
    176         }
    177 
    178         err = mpDecShellContext->m_pReaderGlobal->m_pFctJump(
    179                    mpDecShellContext->m_pReader->m_readerContext,
    180                    (M4_StreamHandler*)mpDecShellContext->m_pVideoStreamhandler,
    181                    &rapTime);
    182 
    183         if (err != OK) {
    184             LOGE("jump err = 0x%x\n", (uint32_t)err);
    185             return BAD_VALUE;
    186         }
    187     }
    188 
    189     *buffer_out = NULL;
    190 
    191     M4OSA_ERR lerr = mGroup->acquire_buffer(&mBuffer);
    192     if (lerr != OK) {
    193         return lerr;
    194     }
    195     mBuffer->meta_data()->clear();  // clear all the meta data
    196 
    197     if (mStarted) {
    198         //getNext AU from reader.
    199         M4_AccessUnit* pAccessUnit = mpDecShellContext->m_pNextAccessUnitToDecode;
    200         lerr = mpDecShellContext->m_pReader->m_pFctGetNextAu(
    201                    mpDecShellContext->m_pReader->m_readerContext,
    202                    (M4_StreamHandler*)mpDecShellContext->m_pVideoStreamhandler,
    203                    pAccessUnit);
    204         if (lerr == M4WAR_NO_DATA_YET || lerr == M4WAR_NO_MORE_AU) {
    205             *buffer_out = NULL;
    206             return ERROR_END_OF_STREAM;
    207         }
    208 
    209         //copy the reader AU buffer to mBuffer
    210         M4OSA_UInt32 lSize  = (pAccessUnit->m_size > (M4OSA_UInt32)mMaxAUSize)\
    211             ? (M4OSA_UInt32)mMaxAUSize : pAccessUnit->m_size;
    212         memcpy((void *)mBuffer->data(),(void *)pAccessUnit->m_dataAddress,
    213             lSize);
    214 
    215         mBuffer->set_range(0, lSize);
    216         int64_t frameTimeUs = (int64_t) (pAccessUnit->m_CTS * 1000);
    217         mBuffer->meta_data()->setInt64(kKeyTime, frameTimeUs);
    218 
    219         // Replace the AU start code for H264
    220         if (VIDEOEDITOR_kH264VideoDec == mCodecType) {
    221             uint8_t *data =(uint8_t *)mBuffer->data() + mBuffer->range_offset();
    222             data[0]=0;
    223             data[1]=0;
    224             data[2]=0;
    225             data[3]=1;
    226         }
    227         mBuffer->meta_data()->setInt32(kKeyIsSyncFrame,
    228             (pAccessUnit->m_attribute == 0x04)? 1 : 0);
    229         *buffer_out = mBuffer;
    230     }
    231     return OK;
    232 }
    233 
    234 static M4OSA_UInt32 VideoEditorVideoDecoder_GetBitsFromMemory(
    235         VIDEOEDITOR_VIDEO_Bitstream_ctxt* parsingCtxt, M4OSA_UInt32 nb_bits) {
    236     return (M4VD_Tools_GetBitsFromMemory((M4VS_Bitstream_ctxt*) parsingCtxt,
    237             nb_bits));
    238 }
    239 
    240 M4OSA_ERR VideoEditorVideoDecoder_internalParseVideoDSI(M4OSA_UInt8* pVol,
    241         M4OSA_Int32 aVolSize, M4DECODER_MPEG4_DecoderConfigInfo* pDci,
    242         M4DECODER_VideoSize* pVideoSize) {
    243 
    244     VIDEOEDITOR_VIDEO_Bitstream_ctxt parsingCtxt;
    245     M4OSA_UInt32 code, j;
    246     M4OSA_MemAddr8 start;
    247     M4OSA_UInt8 i;
    248     M4OSA_UInt32 time_incr_length;
    249     M4OSA_UInt8 vol_verid=0, b_hierarchy_type;
    250 
    251     /* Parsing variables */
    252     M4OSA_UInt8 video_object_layer_shape = 0;
    253     M4OSA_UInt8 sprite_enable = 0;
    254     M4OSA_UInt8 reduced_resolution_vop_enable = 0;
    255     M4OSA_UInt8 scalability = 0;
    256     M4OSA_UInt8 enhancement_type = 0;
    257     M4OSA_UInt8 complexity_estimation_disable = 0;
    258     M4OSA_UInt8 interlaced = 0;
    259     M4OSA_UInt8 sprite_warping_points = 0;
    260     M4OSA_UInt8 sprite_brightness_change = 0;
    261     M4OSA_UInt8 quant_precision = 0;
    262 
    263     /* Fill the structure with default parameters */
    264     pVideoSize->m_uiWidth      = 0;
    265     pVideoSize->m_uiHeight     = 0;
    266 
    267     pDci->uiTimeScale          = 0;
    268     pDci->uiProfile            = 0;
    269     pDci->uiUseOfResynchMarker = 0;
    270     pDci->bDataPartition       = M4OSA_FALSE;
    271     pDci->bUseOfRVLC           = M4OSA_FALSE;
    272 
    273     /* Reset the bitstream context */
    274     parsingCtxt.stream_byte = 0;
    275     parsingCtxt.stream_index = 8;
    276     parsingCtxt.in = (M4OSA_MemAddr8) pVol;
    277 
    278     start = (M4OSA_MemAddr8) pVol;
    279 
    280     /* Start parsing */
    281     while (parsingCtxt.in - start < aVolSize) {
    282         code = VideoEditorVideoDecoder_GetBitsFromMemory(&parsingCtxt, 8);
    283         if (code == 0) {
    284             code = VideoEditorVideoDecoder_GetBitsFromMemory(&parsingCtxt, 8);
    285             if (code == 0) {
    286                 code = VideoEditorVideoDecoder_GetBitsFromMemory(&parsingCtxt,8);
    287                 if (code == 1) {
    288                     /* start code found */
    289                     code = VideoEditorVideoDecoder_GetBitsFromMemory(
    290                         &parsingCtxt, 8);
    291 
    292                     /* ----- 0x20..0x2F : video_object_layer_start_code ----- */
    293 
    294                     if ((code > 0x1F) && (code < 0x30)) {
    295                         code = VideoEditorVideoDecoder_GetBitsFromMemory(
    296                             &parsingCtxt, 1);
    297                         code = VideoEditorVideoDecoder_GetBitsFromMemory(
    298                             &parsingCtxt, 8);
    299                         code = VideoEditorVideoDecoder_GetBitsFromMemory(
    300                             &parsingCtxt, 1);
    301                         if (code == 1) {
    302                             code = VideoEditorVideoDecoder_GetBitsFromMemory(
    303                                 &parsingCtxt, 4);
    304                             vol_verid = (M4OSA_UInt8)code;
    305                             code = VideoEditorVideoDecoder_GetBitsFromMemory(
    306                                 &parsingCtxt, 3);
    307                         }
    308                         code = VideoEditorVideoDecoder_GetBitsFromMemory(
    309                             &parsingCtxt, 4);
    310                         if (code == 15) {
    311                             code = VideoEditorVideoDecoder_GetBitsFromMemory(
    312                                 &parsingCtxt, 16);
    313                         }
    314                         code = VideoEditorVideoDecoder_GetBitsFromMemory(
    315                             &parsingCtxt, 1);
    316                         if (code == 1) {
    317                             code = VideoEditorVideoDecoder_GetBitsFromMemory(
    318                                 &parsingCtxt, 3);
    319                             code = VideoEditorVideoDecoder_GetBitsFromMemory(
    320                                 &parsingCtxt, 1);
    321                             if (code == 1) {
    322                                 code = VideoEditorVideoDecoder_GetBitsFromMemory(
    323                                     &parsingCtxt, 32);
    324                                 code = VideoEditorVideoDecoder_GetBitsFromMemory(
    325                                     &parsingCtxt, 31);
    326                                 code = VideoEditorVideoDecoder_GetBitsFromMemory(
    327                                     &parsingCtxt, 16);
    328                             }
    329                         }
    330                         code = VideoEditorVideoDecoder_GetBitsFromMemory(
    331                             &parsingCtxt, 2);
    332                         /* Need to save it for vop parsing */
    333                         video_object_layer_shape = (M4OSA_UInt8)code;
    334 
    335                         if (code != 0) {
    336                             return 0;    /* only rectangular case supported */
    337                         }
    338 
    339                         code = VideoEditorVideoDecoder_GetBitsFromMemory(
    340                             &parsingCtxt, 1);
    341                         code = VideoEditorVideoDecoder_GetBitsFromMemory(
    342                             &parsingCtxt, 16);
    343                         pDci->uiTimeScale = code;
    344 
    345                         /* Computes time increment length */
    346                         j    = code - 1;
    347                         for (i = 0; (i < 32) && (j != 0); j >>=1) {
    348                             i++;
    349                         }
    350                         time_incr_length = (i == 0) ? 1 : i;
    351 
    352                         code = VideoEditorVideoDecoder_GetBitsFromMemory(
    353                             &parsingCtxt, 1);
    354                         code = VideoEditorVideoDecoder_GetBitsFromMemory(
    355                             &parsingCtxt, 1);
    356                         if (code == 1) {
    357                             code = VideoEditorVideoDecoder_GetBitsFromMemory(
    358                                 &parsingCtxt, time_incr_length);
    359                         }
    360 
    361                         if(video_object_layer_shape != 1) { /* 1 = Binary */
    362                             if(video_object_layer_shape == 0) {
    363                                 code = VideoEditorVideoDecoder_GetBitsFromMemory(
    364                                     &parsingCtxt, 1);/* Marker bit */
    365                                 code = VideoEditorVideoDecoder_GetBitsFromMemory(
    366                                     &parsingCtxt, 13);/* Width */
    367                                 pVideoSize->m_uiWidth = code;
    368                                 code = VideoEditorVideoDecoder_GetBitsFromMemory(
    369                                     &parsingCtxt, 1);/* Marker bit */
    370                                 code = VideoEditorVideoDecoder_GetBitsFromMemory(
    371                                     &parsingCtxt, 13);/* Height */
    372                                 pVideoSize->m_uiHeight = code;
    373                                 code = VideoEditorVideoDecoder_GetBitsFromMemory(
    374                                     &parsingCtxt, 1);/* Marker bit */
    375                             }
    376                         }
    377 
    378                         code = VideoEditorVideoDecoder_GetBitsFromMemory(
    379                             &parsingCtxt, 1);/* interlaced */
    380                         interlaced = (M4OSA_UInt8)code;
    381                         code = VideoEditorVideoDecoder_GetBitsFromMemory(
    382                             &parsingCtxt, 1);/* OBMC disable */
    383 
    384                         if(vol_verid == 1) {
    385                             code = VideoEditorVideoDecoder_GetBitsFromMemory(
    386                                 &parsingCtxt, 1);/* sprite enable */
    387                             sprite_enable = (M4OSA_UInt8)code;
    388                         } else {
    389                             code = VideoEditorVideoDecoder_GetBitsFromMemory(
    390                                 &parsingCtxt, 2);/* sprite enable */
    391                             sprite_enable = (M4OSA_UInt8)code;
    392                         }
    393                         if ((sprite_enable == 1) || (sprite_enable == 2)) {
    394                             if (sprite_enable != 2) {
    395 
    396                                 code = VideoEditorVideoDecoder_GetBitsFromMemory(
    397                                     &parsingCtxt, 13);/* sprite width */
    398                                 code = VideoEditorVideoDecoder_GetBitsFromMemory(
    399                                     &parsingCtxt, 1);/* Marker bit */
    400                                 code = VideoEditorVideoDecoder_GetBitsFromMemory(
    401                                     &parsingCtxt, 13);/* sprite height */
    402                                 code = VideoEditorVideoDecoder_GetBitsFromMemory(
    403                                     &parsingCtxt, 1);/* Marker bit */
    404                                 code = VideoEditorVideoDecoder_GetBitsFromMemory(
    405                                     &parsingCtxt, 13);/* sprite l coordinate */
    406                                 code = VideoEditorVideoDecoder_GetBitsFromMemory(
    407                                     &parsingCtxt, 1);/* Marker bit */
    408                                 code = VideoEditorVideoDecoder_GetBitsFromMemory(
    409                                     &parsingCtxt, 13);/* sprite top coordinate */
    410                                 code = VideoEditorVideoDecoder_GetBitsFromMemory(
    411                                     &parsingCtxt, 1);/* Marker bit */
    412                             }
    413 
    414                             code = VideoEditorVideoDecoder_GetBitsFromMemory(
    415                                 &parsingCtxt, 6);/* sprite warping points */
    416                             sprite_warping_points = (M4OSA_UInt8)code;
    417                             code = VideoEditorVideoDecoder_GetBitsFromMemory(
    418                                 &parsingCtxt, 2);/* sprite warping accuracy */
    419                             code = VideoEditorVideoDecoder_GetBitsFromMemory(
    420                                 &parsingCtxt, 1);/* sprite brightness change */
    421                             sprite_brightness_change = (M4OSA_UInt8)code;
    422                             if (sprite_enable != 2) {
    423                                 code = VideoEditorVideoDecoder_GetBitsFromMemory(
    424                                     &parsingCtxt, 1);
    425                             }
    426                         }
    427                         if ((vol_verid != 1) && (video_object_layer_shape != 0)){
    428                             code = VideoEditorVideoDecoder_GetBitsFromMemory(
    429                             &parsingCtxt, 1);/* sadct disable */
    430                         }
    431 
    432                         code = VideoEditorVideoDecoder_GetBitsFromMemory(
    433                             &parsingCtxt, 1); /* not 8 bits */
    434                         if (code) {
    435                             code = VideoEditorVideoDecoder_GetBitsFromMemory(
    436                                 &parsingCtxt, 4);/* quant precision */
    437                             quant_precision = (M4OSA_UInt8)code;
    438                             code = VideoEditorVideoDecoder_GetBitsFromMemory(
    439                                 &parsingCtxt, 4);/* bits per pixel */
    440                         }
    441 
    442                         /* greyscale not supported */
    443                         if(video_object_layer_shape == 3) {
    444                             code = VideoEditorVideoDecoder_GetBitsFromMemory(
    445                                 &parsingCtxt, 3);
    446                         }
    447 
    448                         code = VideoEditorVideoDecoder_GetBitsFromMemory(
    449                             &parsingCtxt, 1);/* quant type */
    450                         if (code) {
    451                             code = VideoEditorVideoDecoder_GetBitsFromMemory(
    452                                 &parsingCtxt, 1);/* load intra quant mat */
    453                             if (code) {
    454                                 code = VideoEditorVideoDecoder_GetBitsFromMemory(
    455                                     &parsingCtxt, 8);/* */
    456                                 i    = 1;
    457                                 while (i < 64) {
    458                                     code =
    459                                         VideoEditorVideoDecoder_GetBitsFromMemory(
    460                                             &parsingCtxt, 8);
    461                                     if (code == 0) {
    462                                         break;
    463                                     }
    464                                     i++;
    465                                 }
    466                             }
    467 
    468                             code = VideoEditorVideoDecoder_GetBitsFromMemory(
    469                                 &parsingCtxt, 1);/* load non intra quant mat */
    470                             if (code) {
    471                                 code = VideoEditorVideoDecoder_GetBitsFromMemory(
    472                                     &parsingCtxt, 8);/* */
    473                                 i    = 1;
    474                                 while (i < 64) {
    475                                     code =
    476                                         VideoEditorVideoDecoder_GetBitsFromMemory(
    477                                         &parsingCtxt, 8);
    478                                     if (code == 0) {
    479                                         break;
    480                                     }
    481                                     i++;
    482                                 }
    483                             }
    484                         }
    485 
    486                         if (vol_verid != 1) {
    487                             code = VideoEditorVideoDecoder_GetBitsFromMemory(
    488                                 &parsingCtxt, 1);/* quarter sample */
    489                         }
    490 
    491                         code = VideoEditorVideoDecoder_GetBitsFromMemory(
    492                             &parsingCtxt, 1);/* complexity estimation disable */
    493                         complexity_estimation_disable = (M4OSA_UInt8)code;
    494                         if (!code) {
    495                             //return M4ERR_NOT_IMPLEMENTED;
    496                         }
    497 
    498                         code = VideoEditorVideoDecoder_GetBitsFromMemory(
    499                             &parsingCtxt, 1);/* resync marker disable */
    500                         pDci->uiUseOfResynchMarker = (code) ? 0 : 1;
    501 
    502                         code = VideoEditorVideoDecoder_GetBitsFromMemory(
    503                             &parsingCtxt, 1);/* data partitionned */
    504                         pDci->bDataPartition = (code) ? M4OSA_TRUE : M4OSA_FALSE;
    505                         if (code) {
    506                             code = VideoEditorVideoDecoder_GetBitsFromMemory(
    507                                 &parsingCtxt, 1);/* reversible VLC */
    508                             pDci->bUseOfRVLC = (code) ? M4OSA_TRUE : M4OSA_FALSE;
    509                         }
    510 
    511                         if (vol_verid != 1) {
    512                             code = VideoEditorVideoDecoder_GetBitsFromMemory(
    513                                 &parsingCtxt, 1);/* newpred */
    514                             if (code) {
    515                                 //return M4ERR_PARAMETER;
    516                             }
    517 
    518                             code = VideoEditorVideoDecoder_GetBitsFromMemory(
    519                                 &parsingCtxt, 1);
    520                             reduced_resolution_vop_enable = (M4OSA_UInt8)code;
    521                         }
    522 
    523                         code = VideoEditorVideoDecoder_GetBitsFromMemory(
    524                             &parsingCtxt, 1);/* scalability */
    525                         scalability = (M4OSA_UInt8)code;
    526                         if (code) {
    527                             code = VideoEditorVideoDecoder_GetBitsFromMemory(
    528                                 &parsingCtxt, 1);/* hierarchy type */
    529                             b_hierarchy_type = (M4OSA_UInt8)code;
    530                             code = VideoEditorVideoDecoder_GetBitsFromMemory(
    531                                 &parsingCtxt, 4);/* ref layer id */
    532                             code = VideoEditorVideoDecoder_GetBitsFromMemory(
    533                                 &parsingCtxt, 1);/* ref sampling direct */
    534                             code = VideoEditorVideoDecoder_GetBitsFromMemory(
    535                                 &parsingCtxt, 5);/* hor sampling factor N */
    536                             code = VideoEditorVideoDecoder_GetBitsFromMemory(
    537                                 &parsingCtxt, 5);/* hor sampling factor M */
    538                             code = VideoEditorVideoDecoder_GetBitsFromMemory(
    539                                 &parsingCtxt, 5);/* vert sampling factor N */
    540                             code = VideoEditorVideoDecoder_GetBitsFromMemory(
    541                                 &parsingCtxt, 5);/* vert sampling factor M */
    542                             code = VideoEditorVideoDecoder_GetBitsFromMemory(
    543                                 &parsingCtxt, 1);/* enhancement type */
    544                             enhancement_type = (M4OSA_UInt8)code;
    545                             if ((!b_hierarchy_type) &&
    546                                     (video_object_layer_shape == 1)) {
    547                                 code = VideoEditorVideoDecoder_GetBitsFromMemory(
    548                                     &parsingCtxt, 1);/* use ref shape */
    549                                 code = VideoEditorVideoDecoder_GetBitsFromMemory(
    550                                     &parsingCtxt, 1);/* use ref texture */
    551                                 code = VideoEditorVideoDecoder_GetBitsFromMemory(
    552                                     &parsingCtxt, 5);
    553                                 code = VideoEditorVideoDecoder_GetBitsFromMemory(
    554                                     &parsingCtxt, 5);
    555                                 code = VideoEditorVideoDecoder_GetBitsFromMemory(
    556                                     &parsingCtxt, 5);
    557                                 code = VideoEditorVideoDecoder_GetBitsFromMemory(
    558                                     &parsingCtxt, 5);
    559                             }
    560                         }
    561                         break;
    562                     }
    563 
    564                     /* ----- 0xB0 : visual_object_sequence_start_code ----- */
    565 
    566                     else if(code == 0xB0) {
    567                         code = VideoEditorVideoDecoder_GetBitsFromMemory(
    568                             &parsingCtxt, 8);/* profile_and_level_indication */
    569                         pDci->uiProfile = (M4OSA_UInt8)code;
    570                     }
    571 
    572                     /* ----- 0xB5 : visual_object_start_code ----- */
    573 
    574                     else if(code == 0xB5) {
    575                         code = VideoEditorVideoDecoder_GetBitsFromMemory(
    576                             &parsingCtxt, 1);/* is object layer identifier */
    577                         if (code == 1) {
    578                             code = VideoEditorVideoDecoder_GetBitsFromMemory(
    579                                 &parsingCtxt, 4); /* visual object verid */
    580                             vol_verid = (M4OSA_UInt8)code;
    581                             code = VideoEditorVideoDecoder_GetBitsFromMemory(
    582                                 &parsingCtxt, 3);
    583                         } else {
    584                             code = VideoEditorVideoDecoder_GetBitsFromMemory(
    585                                 &parsingCtxt, 7); /* Realign on byte */
    586                             vol_verid = 1;
    587                         }
    588                     }
    589 
    590                     /* ----- end ----- */
    591                 } else {
    592                     if ((code >> 2) == 0x20) {
    593                         /* H263 ...-> wrong*/
    594                         break;
    595                     }
    596                 }
    597             }
    598         }
    599     }
    600     return M4NO_ERROR;
    601 }
    602 
    603 M4VIFI_UInt8 M4VIFI_SemiplanarYVU420toYUV420(void *user_data,
    604         M4VIFI_UInt8 *inyuv, M4VIFI_ImagePlane *PlaneOut ) {
    605     M4VIFI_UInt8 return_code = M4VIFI_OK;
    606     M4VIFI_UInt8 *outyuv =
    607         ((M4VIFI_UInt8*)&(PlaneOut[0].pac_data[PlaneOut[0].u_topleft]));
    608     int32_t width = PlaneOut[0].u_width;
    609     int32_t height = PlaneOut[0].u_height;
    610 
    611     int32_t outYsize = width * height;
    612     uint32_t *outy =  (uint32_t *) outyuv;
    613     uint16_t *outcb =
    614         (uint16_t *) &(PlaneOut[1].pac_data[PlaneOut[1].u_topleft]);
    615     uint16_t *outcr =
    616         (uint16_t *) &(PlaneOut[2].pac_data[PlaneOut[2].u_topleft]);
    617 
    618     /* Y copying */
    619     memcpy((void *)outy, (void *)inyuv, outYsize);
    620 
    621     /* U & V copying */
    622     uint32_t *inyuv_4 = (uint32_t *) (inyuv + outYsize);
    623     for (int32_t i = height >> 1; i > 0; --i) {
    624         for (int32_t j = width >> 2; j > 0; --j) {
    625             uint32_t temp = *inyuv_4++;
    626             uint32_t tempU = temp & 0xFF;
    627             tempU = tempU | ((temp >> 8) & 0xFF00);
    628 
    629             uint32_t tempV = (temp >> 8) & 0xFF;
    630             tempV = tempV | ((temp >> 16) & 0xFF00);
    631 
    632             // Flip U and V
    633             *outcb++ = tempV;
    634             *outcr++ = tempU;
    635         }
    636     }
    637     return return_code;
    638 }
    639 void logSupportDecodersAndCapabilities(M4DECODER_VideoDecoders* decoders) {
    640     VideoDecoder *pDecoder;
    641     VideoComponentCapabilities *pOmxComponents = NULL;
    642     VideoProfileLevel *pProfileLevel = NULL;
    643     pDecoder = decoders->decoder;
    644     for (size_t i = 0; i< decoders->decoderNumber; i++) {
    645         LOGV("Supported Codec[%d] :%d", i, pDecoder->codec);
    646         pOmxComponents = pDecoder->component;
    647         for(size_t j = 0; j <  pDecoder->componentNumber; j++) {
    648            pProfileLevel = pOmxComponents->profileLevel;
    649            LOGV("-->component %d", j);
    650            for(size_t k = 0; k < pOmxComponents->profileNumber; k++) {
    651                LOGV("-->profile:%ld maxLevel:%ld", pProfileLevel->mProfile,
    652                    pProfileLevel->mLevel);
    653                pProfileLevel++;
    654            }
    655            pOmxComponents++;
    656         }
    657         pDecoder++;
    658     }
    659 }
    660 
    661 M4OSA_ERR queryVideoDecoderCapabilities
    662     (M4DECODER_VideoDecoders** decoders) {
    663     M4OSA_ERR err = M4NO_ERROR;
    664     const char *kMimeTypes[] = {
    665         MEDIA_MIMETYPE_VIDEO_AVC, MEDIA_MIMETYPE_VIDEO_MPEG4,
    666         MEDIA_MIMETYPE_VIDEO_H263
    667     };
    668 
    669     int32_t supportFormats = sizeof(kMimeTypes) / sizeof(kMimeTypes[0]);
    670     M4DECODER_VideoDecoders *pDecoders;
    671     VideoDecoder *pDecoder;
    672     VideoComponentCapabilities *pOmxComponents = NULL;
    673     VideoProfileLevel *pProfileLevel = NULL;
    674     OMXClient client;
    675     status_t status = OK;
    676     SAFE_MALLOC(pDecoders, M4DECODER_VideoDecoders, 1, "VideoDecoders");
    677     SAFE_MALLOC(pDecoder, VideoDecoder, supportFormats,
    678         "VideoDecoder");
    679     pDecoders->decoder = pDecoder;
    680 
    681     pDecoders->decoderNumber= supportFormats;
    682     status = client.connect();
    683     CHECK(status == OK);
    684     for (size_t k = 0; k < sizeof(kMimeTypes) / sizeof(kMimeTypes[0]);
    685              ++k) {
    686             Vector<CodecCapabilities> results;
    687             CHECK_EQ(QueryCodecs(client.interface(), kMimeTypes[k],
    688                                  true, // queryDecoders
    689                                  &results), (status_t)OK);
    690 
    691             if (results.size()) {
    692                 SAFE_MALLOC(pOmxComponents, VideoComponentCapabilities,
    693                     results.size(), "VideoComponentCapabilities");
    694                 LOGV("K=%d",k);
    695                 pDecoder->component = pOmxComponents;
    696                 pDecoder->componentNumber = results.size();
    697             }
    698 
    699             for (size_t i = 0; i < results.size(); ++i) {
    700                 LOGV("  decoder '%s' supports ",
    701                        results[i].mComponentName.string());
    702 
    703                 if (results[i].mProfileLevels.size() == 0) {
    704                     LOGV("NOTHING.\n");
    705                     continue;
    706                 }
    707 
    708 #if 0
    709                 // FIXME:
    710                 // We should ignore the software codecs and make IsSoftwareCodec()
    711                 // part of pubic API from OMXCodec.cpp
    712                 if (IsSoftwareCodec(results[i].mComponentName.string())) {
    713                     LOGV("Ignore software codec %s", results[i].mComponentName.string());
    714                     continue;
    715                 }
    716 #endif
    717 
    718                 // Count the supported profiles
    719                 int32_t profileNumber = 0;
    720                 int32_t profile = -1;
    721                 for (size_t j = 0; j < results[i].mProfileLevels.size(); ++j) {
    722                     const CodecProfileLevel &profileLevel =
    723                         results[i].mProfileLevels[j];
    724                     // FIXME: assume that the profiles are ordered
    725                     if (profileLevel.mProfile != profile) {
    726                         profile = profileLevel.mProfile;
    727                         profileNumber++;
    728                     }
    729                 }
    730                 SAFE_MALLOC(pProfileLevel, VideoProfileLevel,
    731                     profileNumber, "VideoProfileLevel");
    732                 pOmxComponents->profileLevel = pProfileLevel;
    733                 pOmxComponents->profileNumber = profileNumber;
    734 
    735                 // Get the max Level for each profile.
    736                 int32_t maxLevel = -1;
    737                 profile = -1;
    738                 profileNumber = 0;
    739                 for (size_t j = 0; j < results[i].mProfileLevels.size(); ++j) {
    740                     const CodecProfileLevel &profileLevel =
    741                         results[i].mProfileLevels[j];
    742                     if (profile == -1 && maxLevel == -1) {
    743                         profile = profileLevel.mProfile;
    744                         maxLevel = profileLevel.mLevel;
    745                         pProfileLevel->mProfile = profile;
    746                         pProfileLevel->mLevel = maxLevel;
    747                         LOGV("%d profile: %ld, max level: %ld",
    748                             __LINE__, pProfileLevel->mProfile, pProfileLevel->mLevel);
    749                     }
    750                     if (profileLevel.mProfile != profile) {
    751                         profile = profileLevel.mProfile;
    752                         maxLevel = profileLevel.mLevel;
    753                         profileNumber++;
    754                         pProfileLevel++;
    755                         pProfileLevel->mProfile = profile;
    756                         pProfileLevel->mLevel = maxLevel;
    757                         LOGV("%d profile: %ld, max level: %ld",
    758                             __LINE__, pProfileLevel->mProfile, pProfileLevel->mLevel);
    759                     } else if (profileLevel.mLevel > maxLevel) {
    760                         maxLevel = profileLevel.mLevel;
    761                         pProfileLevel->mLevel = maxLevel;
    762                         LOGV("%d profile: %ld, max level: %ld",
    763                             __LINE__, pProfileLevel->mProfile, pProfileLevel->mLevel);
    764                     }
    765 
    766                 }
    767                 pOmxComponents++;
    768             }
    769             if (!strcmp(MEDIA_MIMETYPE_VIDEO_AVC, kMimeTypes[k]))
    770                 pDecoder->codec = M4DA_StreamTypeVideoMpeg4Avc;
    771             if (!strcmp(MEDIA_MIMETYPE_VIDEO_MPEG4, kMimeTypes[k]))
    772                 pDecoder->codec = M4DA_StreamTypeVideoMpeg4;
    773             if (!strcmp(MEDIA_MIMETYPE_VIDEO_H263, kMimeTypes[k]))
    774                 pDecoder->codec = M4DA_StreamTypeVideoH263;
    775 
    776             pDecoder++;
    777     }
    778 
    779     logSupportDecodersAndCapabilities(pDecoders);
    780     *decoders = pDecoders;
    781 cleanUp:
    782     return err;
    783 }
    784 /********************
    785  * ENGINE INTERFACE *
    786  ********************/
    787 M4OSA_ERR VideoEditorVideoDecoder_configureFromMetadata(M4OSA_Context pContext,
    788         MetaData* meta) {
    789     M4OSA_ERR err = M4NO_ERROR;
    790     VideoEditorVideoDecoder_Context* pDecShellContext = M4OSA_NULL;
    791     bool success = OK;
    792     int32_t width = 0;
    793     int32_t height = 0;
    794     int32_t frameSize = 0;
    795     int32_t vWidth, vHeight;
    796     int32_t cropLeft, cropTop, cropRight, cropBottom;
    797 
    798     VIDEOEDITOR_CHECK(M4OSA_NULL != pContext, M4ERR_PARAMETER);
    799     VIDEOEDITOR_CHECK(M4OSA_NULL != meta,     M4ERR_PARAMETER);
    800 
    801     LOGV("VideoEditorVideoDecoder_configureFromMetadata begin");
    802 
    803     pDecShellContext = (VideoEditorVideoDecoder_Context*)pContext;
    804 
    805     success = meta->findInt32(kKeyWidth, &vWidth);
    806     VIDEOEDITOR_CHECK(TRUE == success, M4ERR_PARAMETER);
    807     success = meta->findInt32(kKeyHeight, &vHeight);
    808     VIDEOEDITOR_CHECK(TRUE == success, M4ERR_PARAMETER);
    809 
    810     LOGV("vWidth = %d, vHeight = %d", vWidth, vHeight);
    811 
    812     pDecShellContext->mGivenWidth = vWidth;
    813     pDecShellContext->mGivenHeight = vHeight;
    814 
    815     if (!meta->findRect(
    816                 kKeyCropRect, &cropLeft, &cropTop, &cropRight, &cropBottom)) {
    817 
    818         cropLeft = cropTop = 0;
    819         cropRight = vWidth - 1;
    820         cropBottom = vHeight - 1;
    821 
    822         LOGV("got dimensions only %d x %d", width, height);
    823     } else {
    824         LOGV("got crop rect %d, %d, %d, %d",
    825              cropLeft, cropTop, cropRight, cropBottom);
    826     }
    827 
    828     pDecShellContext->mCropRect.left = cropLeft;
    829     pDecShellContext->mCropRect.right = cropRight;
    830     pDecShellContext->mCropRect.top = cropTop;
    831     pDecShellContext->mCropRect.bottom = cropBottom;
    832 
    833     width = cropRight - cropLeft + 1;
    834     height = cropBottom - cropTop + 1;
    835 
    836     LOGV("VideoDecoder_configureFromMetadata : W=%d H=%d", width, height);
    837     VIDEOEDITOR_CHECK((0 != width) && (0 != height), M4ERR_PARAMETER);
    838 
    839     if( (M4OSA_NULL != pDecShellContext->m_pDecBufferPool) &&
    840         (pDecShellContext->m_pVideoStreamhandler->m_videoWidth  == \
    841             (uint32_t)width) &&
    842         (pDecShellContext->m_pVideoStreamhandler->m_videoHeight == \
    843             (uint32_t)height) ) {
    844         // No need to reconfigure
    845         goto cleanUp;
    846     }
    847     LOGV("VideoDecoder_configureFromMetadata  reset: W=%d H=%d", width, height);
    848     // Update the stream handler parameters
    849     pDecShellContext->m_pVideoStreamhandler->m_videoWidth  = width;
    850     pDecShellContext->m_pVideoStreamhandler->m_videoHeight = height;
    851     frameSize = (width * height * 3) / 2;
    852 
    853     // Configure the buffer pool
    854     if( M4OSA_NULL != pDecShellContext->m_pDecBufferPool ) {
    855         LOGV("VideoDecoder_configureFromMetadata : reset the buffer pool");
    856         VIDEOEDITOR_BUFFER_freePool(pDecShellContext->m_pDecBufferPool);
    857         pDecShellContext->m_pDecBufferPool = M4OSA_NULL;
    858     }
    859     err =  VIDEOEDITOR_BUFFER_allocatePool(&pDecShellContext->m_pDecBufferPool,
    860         MAX_DEC_BUFFERS, (M4OSA_Char*)"VIDEOEDITOR_DecodedBufferPool");
    861     VIDEOEDITOR_CHECK(M4NO_ERROR == err, err);
    862     err = VIDEOEDITOR_BUFFER_initPoolBuffers(pDecShellContext->m_pDecBufferPool,
    863                 frameSize + pDecShellContext->mGivenWidth * 2);
    864 
    865     VIDEOEDITOR_CHECK(M4NO_ERROR == err, err);
    866 
    867 cleanUp:
    868     if( M4NO_ERROR == err ) {
    869         LOGV("VideoEditorVideoDecoder_configureFromMetadata no error");
    870     } else {
    871         if( M4OSA_NULL != pDecShellContext->m_pDecBufferPool ) {
    872             VIDEOEDITOR_BUFFER_freePool(pDecShellContext->m_pDecBufferPool);
    873             pDecShellContext->m_pDecBufferPool = M4OSA_NULL;
    874         }
    875         LOGV("VideoEditorVideoDecoder_configureFromMetadata ERROR 0x%X", err);
    876     }
    877     LOGV("VideoEditorVideoDecoder_configureFromMetadata end");
    878     return err;
    879 }
    880 
    881 M4OSA_ERR VideoEditorVideoDecoder_destroy(M4OSA_Context pContext) {
    882     M4OSA_ERR err = M4NO_ERROR;
    883     VideoEditorVideoDecoder_Context* pDecShellContext =
    884         (VideoEditorVideoDecoder_Context*)pContext;
    885 
    886     // Input parameters check
    887     LOGV("VideoEditorVideoDecoder_destroy begin");
    888     VIDEOEDITOR_CHECK(M4OSA_NULL != pContext, M4ERR_PARAMETER);
    889 
    890     // Release the color converter
    891     delete pDecShellContext->mI420ColorConverter;
    892 
    893     // Destroy the graph
    894     if( pDecShellContext->mVideoDecoder != NULL ) {
    895         LOGV("### VideoEditorVideoDecoder_destroy : releasing decoder");
    896         pDecShellContext->mVideoDecoder->stop();
    897         pDecShellContext->mVideoDecoder.clear();
    898     }
    899     pDecShellContext->mClient.disconnect();
    900     pDecShellContext->mReaderSource.clear();
    901 
    902     // Release memory
    903     if( pDecShellContext->m_pDecBufferPool != M4OSA_NULL ) {
    904         VIDEOEDITOR_BUFFER_freePool(pDecShellContext->m_pDecBufferPool);
    905         pDecShellContext->m_pDecBufferPool = M4OSA_NULL;
    906     }
    907     SAFE_FREE(pDecShellContext);
    908     pContext = NULL;
    909 
    910 cleanUp:
    911     if( M4NO_ERROR == err ) {
    912         LOGV("VideoEditorVideoDecoder_destroy no error");
    913     } else {
    914         LOGV("VideoEditorVideoDecoder_destroy ERROR 0x%X", err);
    915     }
    916     LOGV("VideoEditorVideoDecoder_destroy end");
    917     return err;
    918 }
    919 
    920 M4OSA_ERR VideoEditorVideoDecoder_create(M4OSA_Context *pContext,
    921         M4_StreamHandler *pStreamHandler,
    922         M4READER_GlobalInterface *pReaderGlobalInterface,
    923         M4READER_DataInterface *pReaderDataInterface,
    924         M4_AccessUnit *pAccessUnit, M4OSA_Void *pUserData) {
    925     M4OSA_ERR err = M4NO_ERROR;
    926     VideoEditorVideoDecoder_Context* pDecShellContext = M4OSA_NULL;
    927     status_t status = OK;
    928     bool success = TRUE;
    929     int32_t colorFormat = 0;
    930     M4OSA_UInt32 size = 0;
    931     sp<MetaData> decoderMetadata = NULL;
    932     int decoderOutput = OMX_COLOR_FormatYUV420Planar;
    933 
    934     LOGV("VideoEditorVideoDecoder_create begin");
    935     // Input parameters check
    936     VIDEOEDITOR_CHECK(M4OSA_NULL != pContext,             M4ERR_PARAMETER);
    937     VIDEOEDITOR_CHECK(M4OSA_NULL != pStreamHandler,       M4ERR_PARAMETER);
    938     VIDEOEDITOR_CHECK(M4OSA_NULL != pReaderDataInterface, M4ERR_PARAMETER);
    939 
    940     // Context allocation & initialization
    941     SAFE_MALLOC(pDecShellContext, VideoEditorVideoDecoder_Context, 1,
    942         "VideoEditorVideoDecoder");
    943     pDecShellContext->m_pVideoStreamhandler =
    944         (M4_VideoStreamHandler*)pStreamHandler;
    945     pDecShellContext->m_pNextAccessUnitToDecode = pAccessUnit;
    946     pDecShellContext->m_pReaderGlobal = pReaderGlobalInterface;
    947     pDecShellContext->m_pReader = pReaderDataInterface;
    948     pDecShellContext->m_lastDecodedCTS = -1;
    949     pDecShellContext->m_lastRenderCts = -1;
    950     switch( pStreamHandler->m_streamType ) {
    951         case M4DA_StreamTypeVideoH263:
    952             pDecShellContext->mDecoderType = VIDEOEDITOR_kH263VideoDec;
    953             break;
    954         case M4DA_StreamTypeVideoMpeg4:
    955             pDecShellContext->mDecoderType = VIDEOEDITOR_kMpeg4VideoDec;
    956             // Parse the VOL header
    957             err = VideoEditorVideoDecoder_internalParseVideoDSI(
    958                 (M4OSA_UInt8*)pDecShellContext->m_pVideoStreamhandler->\
    959                     m_basicProperties.m_pDecoderSpecificInfo,
    960                 pDecShellContext->m_pVideoStreamhandler->\
    961                     m_basicProperties.m_decoderSpecificInfoSize,
    962                 &pDecShellContext->m_Dci, &pDecShellContext->m_VideoSize);
    963             VIDEOEDITOR_CHECK(M4NO_ERROR == err, err);
    964             break;
    965         case M4DA_StreamTypeVideoMpeg4Avc:
    966             pDecShellContext->mDecoderType = VIDEOEDITOR_kH264VideoDec;
    967             break;
    968         default:
    969             VIDEOEDITOR_CHECK(!"VideoDecoder_create : incorrect stream type",
    970                 M4ERR_PARAMETER);
    971             break;
    972     }
    973 
    974     pDecShellContext->mNbInputFrames     = 0;
    975     pDecShellContext->mFirstInputCts     = -1.0;
    976     pDecShellContext->mLastInputCts      = -1.0;
    977     pDecShellContext->mNbRenderedFrames  = 0;
    978     pDecShellContext->mFirstRenderedCts  = -1.0;
    979     pDecShellContext->mLastRenderedCts   = -1.0;
    980     pDecShellContext->mNbOutputFrames    = 0;
    981     pDecShellContext->mFirstOutputCts    = -1;
    982     pDecShellContext->mLastOutputCts     = -1;
    983     pDecShellContext->m_pDecBufferPool   = M4OSA_NULL;
    984 
    985     /**
    986      * StageFright graph building
    987      */
    988     decoderMetadata = new MetaData;
    989     switch( pDecShellContext->mDecoderType ) {
    990         case VIDEOEDITOR_kH263VideoDec:
    991             decoderMetadata->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_H263);
    992             break;
    993         case VIDEOEDITOR_kMpeg4VideoDec:
    994             decoderMetadata->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_MPEG4);
    995             decoderMetadata->setData(kKeyESDS, kTypeESDS,
    996                 pStreamHandler->m_pESDSInfo,
    997                 pStreamHandler->m_ESDSInfoSize);
    998             break;
    999         case VIDEOEDITOR_kH264VideoDec:
   1000             decoderMetadata->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_AVC);
   1001             decoderMetadata->setData(kKeyAVCC, kTypeAVCC,
   1002                 pStreamHandler->m_pH264DecoderSpecificInfo,
   1003                 pStreamHandler->m_H264decoderSpecificInfoSize);
   1004             break;
   1005         default:
   1006             VIDEOEDITOR_CHECK(!"VideoDecoder_create : incorrect stream type",
   1007                 M4ERR_PARAMETER);
   1008             break;
   1009     }
   1010 
   1011     decoderMetadata->setInt32(kKeyMaxInputSize, pStreamHandler->m_maxAUSize);
   1012     decoderMetadata->setInt32(kKeyWidth,
   1013         pDecShellContext->m_pVideoStreamhandler->m_videoWidth);
   1014     decoderMetadata->setInt32(kKeyHeight,
   1015         pDecShellContext->m_pVideoStreamhandler->m_videoHeight);
   1016 
   1017     // Create the decoder source
   1018     pDecShellContext->mReaderSource = new VideoEditorVideoDecoderSource(
   1019         decoderMetadata, pDecShellContext->mDecoderType,
   1020         (void *)pDecShellContext);
   1021     VIDEOEDITOR_CHECK(NULL != pDecShellContext->mReaderSource.get(),
   1022         M4ERR_SF_DECODER_RSRC_FAIL);
   1023 
   1024     // Connect to the OMX client
   1025     status = pDecShellContext->mClient.connect();
   1026     VIDEOEDITOR_CHECK(OK == status, M4ERR_SF_DECODER_RSRC_FAIL);
   1027 
   1028     // Create the decoder
   1029     pDecShellContext->mVideoDecoder = OMXCodec::Create(
   1030         pDecShellContext->mClient.interface(),
   1031         decoderMetadata, false, pDecShellContext->mReaderSource);
   1032     VIDEOEDITOR_CHECK(NULL != pDecShellContext->mVideoDecoder.get(),
   1033         M4ERR_SF_DECODER_RSRC_FAIL);
   1034 
   1035 
   1036     // Get the output color format
   1037     success = pDecShellContext->mVideoDecoder->getFormat()->findInt32(
   1038         kKeyColorFormat, &colorFormat);
   1039     VIDEOEDITOR_CHECK(TRUE == success, M4ERR_PARAMETER);
   1040     pDecShellContext->decOuputColorFormat = (OMX_COLOR_FORMATTYPE)colorFormat;
   1041 
   1042     pDecShellContext->mVideoDecoder->getFormat()->setInt32(kKeyWidth,
   1043         pDecShellContext->m_pVideoStreamhandler->m_videoWidth);
   1044     pDecShellContext->mVideoDecoder->getFormat()->setInt32(kKeyHeight,
   1045         pDecShellContext->m_pVideoStreamhandler->m_videoHeight);
   1046 
   1047     // Get the color converter
   1048     pDecShellContext->mI420ColorConverter = new I420ColorConverter;
   1049     if (pDecShellContext->mI420ColorConverter->isLoaded()) {
   1050         decoderOutput = pDecShellContext->mI420ColorConverter->getDecoderOutputFormat();
   1051     }
   1052 
   1053     if (decoderOutput == OMX_COLOR_FormatYUV420Planar) {
   1054         delete pDecShellContext->mI420ColorConverter;
   1055         pDecShellContext->mI420ColorConverter = NULL;
   1056     }
   1057 
   1058     LOGI("decoder output format = 0x%X\n", decoderOutput);
   1059 
   1060     // Configure the buffer pool from the metadata
   1061     err = VideoEditorVideoDecoder_configureFromMetadata(pDecShellContext,
   1062         pDecShellContext->mVideoDecoder->getFormat().get());
   1063     VIDEOEDITOR_CHECK(M4NO_ERROR == err, err);
   1064 
   1065     // Start the graph
   1066     status = pDecShellContext->mVideoDecoder->start();
   1067     VIDEOEDITOR_CHECK(OK == status, M4ERR_SF_DECODER_RSRC_FAIL);
   1068 
   1069     *pContext = (M4OSA_Context)pDecShellContext;
   1070 
   1071 cleanUp:
   1072     if( M4NO_ERROR == err ) {
   1073         LOGV("VideoEditorVideoDecoder_create no error");
   1074     } else {
   1075         VideoEditorVideoDecoder_destroy(pDecShellContext);
   1076         *pContext = M4OSA_NULL;
   1077         LOGV("VideoEditorVideoDecoder_create ERROR 0x%X", err);
   1078     }
   1079     LOGV("VideoEditorVideoDecoder_create : DONE");
   1080     return err;
   1081 }
   1082 
   1083 M4OSA_ERR VideoEditorVideoSoftwareDecoder_create(M4OSA_Context *pContext,
   1084         M4_StreamHandler *pStreamHandler,
   1085         M4READER_GlobalInterface *pReaderGlobalInterface,
   1086         M4READER_DataInterface *pReaderDataInterface,
   1087         M4_AccessUnit *pAccessUnit, M4OSA_Void *pUserData) {
   1088     M4OSA_ERR err = M4NO_ERROR;
   1089     VideoEditorVideoDecoder_Context* pDecShellContext = M4OSA_NULL;
   1090     status_t status = OK;
   1091     bool success = TRUE;
   1092     int32_t colorFormat = 0;
   1093     M4OSA_UInt32 size = 0;
   1094     sp<MetaData> decoderMetadata = NULL;
   1095 
   1096     LOGV("VideoEditorVideoDecoder_create begin");
   1097     // Input parameters check
   1098     VIDEOEDITOR_CHECK(M4OSA_NULL != pContext,             M4ERR_PARAMETER);
   1099     VIDEOEDITOR_CHECK(M4OSA_NULL != pStreamHandler,       M4ERR_PARAMETER);
   1100     VIDEOEDITOR_CHECK(M4OSA_NULL != pReaderDataInterface, M4ERR_PARAMETER);
   1101 
   1102     // Context allocation & initialization
   1103     SAFE_MALLOC(pDecShellContext, VideoEditorVideoDecoder_Context, 1,
   1104         "VideoEditorVideoDecoder");
   1105     pDecShellContext->m_pVideoStreamhandler =
   1106         (M4_VideoStreamHandler*)pStreamHandler;
   1107     pDecShellContext->m_pNextAccessUnitToDecode = pAccessUnit;
   1108     pDecShellContext->m_pReaderGlobal = pReaderGlobalInterface;
   1109     pDecShellContext->m_pReader = pReaderDataInterface;
   1110     pDecShellContext->m_lastDecodedCTS = -1;
   1111     pDecShellContext->m_lastRenderCts = -1;
   1112     switch( pStreamHandler->m_streamType ) {
   1113         case M4DA_StreamTypeVideoH263:
   1114             pDecShellContext->mDecoderType = VIDEOEDITOR_kH263VideoDec;
   1115             break;
   1116         case M4DA_StreamTypeVideoMpeg4:
   1117             pDecShellContext->mDecoderType = VIDEOEDITOR_kMpeg4VideoDec;
   1118             // Parse the VOL header
   1119             err = VideoEditorVideoDecoder_internalParseVideoDSI(
   1120                 (M4OSA_UInt8*)pDecShellContext->m_pVideoStreamhandler->\
   1121                     m_basicProperties.m_pDecoderSpecificInfo,
   1122                 pDecShellContext->m_pVideoStreamhandler->\
   1123                     m_basicProperties.m_decoderSpecificInfoSize,
   1124                 &pDecShellContext->m_Dci, &pDecShellContext->m_VideoSize);
   1125             VIDEOEDITOR_CHECK(M4NO_ERROR == err, err);
   1126             break;
   1127         case M4DA_StreamTypeVideoMpeg4Avc:
   1128             pDecShellContext->mDecoderType = VIDEOEDITOR_kH264VideoDec;
   1129             break;
   1130         default:
   1131             VIDEOEDITOR_CHECK(!"VideoDecoder_create : incorrect stream type",
   1132                 M4ERR_PARAMETER);
   1133             break;
   1134     }
   1135 
   1136     pDecShellContext->mNbInputFrames     = 0;
   1137     pDecShellContext->mFirstInputCts     = -1.0;
   1138     pDecShellContext->mLastInputCts      = -1.0;
   1139     pDecShellContext->mNbRenderedFrames  = 0;
   1140     pDecShellContext->mFirstRenderedCts  = -1.0;
   1141     pDecShellContext->mLastRenderedCts   = -1.0;
   1142     pDecShellContext->mNbOutputFrames    = 0;
   1143     pDecShellContext->mFirstOutputCts    = -1;
   1144     pDecShellContext->mLastOutputCts     = -1;
   1145     pDecShellContext->m_pDecBufferPool   = M4OSA_NULL;
   1146 
   1147     /**
   1148      * StageFright graph building
   1149      */
   1150     decoderMetadata = new MetaData;
   1151     switch( pDecShellContext->mDecoderType ) {
   1152         case VIDEOEDITOR_kH263VideoDec:
   1153             decoderMetadata->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_H263);
   1154             break;
   1155         case VIDEOEDITOR_kMpeg4VideoDec:
   1156             decoderMetadata->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_MPEG4);
   1157             decoderMetadata->setData(kKeyESDS, kTypeESDS,
   1158                 pStreamHandler->m_pESDSInfo,
   1159                 pStreamHandler->m_ESDSInfoSize);
   1160             break;
   1161         case VIDEOEDITOR_kH264VideoDec:
   1162             decoderMetadata->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_AVC);
   1163             decoderMetadata->setData(kKeyAVCC, kTypeAVCC,
   1164                 pStreamHandler->m_pH264DecoderSpecificInfo,
   1165                 pStreamHandler->m_H264decoderSpecificInfoSize);
   1166             break;
   1167         default:
   1168             VIDEOEDITOR_CHECK(!"VideoDecoder_create : incorrect stream type",
   1169                 M4ERR_PARAMETER);
   1170             break;
   1171     }
   1172 
   1173     decoderMetadata->setInt32(kKeyMaxInputSize, pStreamHandler->m_maxAUSize);
   1174     decoderMetadata->setInt32(kKeyWidth,
   1175         pDecShellContext->m_pVideoStreamhandler->m_videoWidth);
   1176     decoderMetadata->setInt32(kKeyHeight,
   1177         pDecShellContext->m_pVideoStreamhandler->m_videoHeight);
   1178 
   1179     // Create the decoder source
   1180     pDecShellContext->mReaderSource = new VideoEditorVideoDecoderSource(
   1181         decoderMetadata, pDecShellContext->mDecoderType,
   1182         (void *)pDecShellContext);
   1183     VIDEOEDITOR_CHECK(NULL != pDecShellContext->mReaderSource.get(),
   1184         M4ERR_SF_DECODER_RSRC_FAIL);
   1185 
   1186     // Connect to the OMX client
   1187     status = pDecShellContext->mClient.connect();
   1188     VIDEOEDITOR_CHECK(OK == status, M4ERR_SF_DECODER_RSRC_FAIL);
   1189 
   1190      LOGI("Using software codecs only");
   1191     // Create the decoder
   1192     pDecShellContext->mVideoDecoder = OMXCodec::Create(
   1193         pDecShellContext->mClient.interface(),
   1194         decoderMetadata, false, pDecShellContext->mReaderSource,NULL,OMXCodec::kSoftwareCodecsOnly);
   1195     VIDEOEDITOR_CHECK(NULL != pDecShellContext->mVideoDecoder.get(),
   1196         M4ERR_SF_DECODER_RSRC_FAIL);
   1197 
   1198     // Get the output color format
   1199     success = pDecShellContext->mVideoDecoder->getFormat()->findInt32(
   1200         kKeyColorFormat, &colorFormat);
   1201     VIDEOEDITOR_CHECK(TRUE == success, M4ERR_PARAMETER);
   1202     pDecShellContext->decOuputColorFormat = (OMX_COLOR_FORMATTYPE)colorFormat;
   1203 
   1204     pDecShellContext->mVideoDecoder->getFormat()->setInt32(kKeyWidth,
   1205         pDecShellContext->m_pVideoStreamhandler->m_videoWidth);
   1206     pDecShellContext->mVideoDecoder->getFormat()->setInt32(kKeyHeight,
   1207         pDecShellContext->m_pVideoStreamhandler->m_videoHeight);
   1208 
   1209     // Configure the buffer pool from the metadata
   1210     err = VideoEditorVideoDecoder_configureFromMetadata(pDecShellContext,
   1211         pDecShellContext->mVideoDecoder->getFormat().get());
   1212     VIDEOEDITOR_CHECK(M4NO_ERROR == err, err);
   1213 
   1214     // Start the graph
   1215     status = pDecShellContext->mVideoDecoder->start();
   1216     VIDEOEDITOR_CHECK(OK == status, M4ERR_SF_DECODER_RSRC_FAIL);
   1217 
   1218     *pContext = (M4OSA_Context)pDecShellContext;
   1219 
   1220 cleanUp:
   1221     if( M4NO_ERROR == err ) {
   1222         LOGV("VideoEditorVideoDecoder_create no error");
   1223     } else {
   1224         VideoEditorVideoDecoder_destroy(pDecShellContext);
   1225         *pContext = M4OSA_NULL;
   1226         LOGV("VideoEditorVideoDecoder_create ERROR 0x%X", err);
   1227     }
   1228     LOGV("VideoEditorVideoDecoder_create : DONE");
   1229     return err;
   1230 }
   1231 
   1232 
   1233 M4OSA_ERR VideoEditorVideoDecoder_getOption(M4OSA_Context context,
   1234         M4OSA_OptionID optionId, M4OSA_DataOption pValue) {
   1235     M4OSA_ERR lerr = M4NO_ERROR;
   1236     VideoEditorVideoDecoder_Context* pDecShellContext =
   1237         (VideoEditorVideoDecoder_Context*) context;
   1238     M4_VersionInfo* pVersionInfo;
   1239     M4DECODER_VideoSize* pVideoSize;
   1240     M4OSA_UInt32* pNextFrameCts;
   1241     M4OSA_UInt32 *plastDecodedFrameCts;
   1242     M4DECODER_AVCProfileLevel* profile;
   1243     M4DECODER_MPEG4_DecoderConfigInfo* pDecConfInfo;
   1244 
   1245     LOGV("VideoEditorVideoDecoder_getOption begin");
   1246 
   1247     switch (optionId) {
   1248         case M4DECODER_kOptionID_AVCLastDecodedFrameCTS:
   1249              plastDecodedFrameCts = (M4OSA_UInt32 *) pValue;
   1250              *plastDecodedFrameCts = pDecShellContext->m_lastDecodedCTS;
   1251              break;
   1252 
   1253         case M4DECODER_kOptionID_Version:
   1254             pVersionInfo = (M4_VersionInfo*)pValue;
   1255 
   1256             pVersionInfo->m_major = VIDEOEDITOR_VIDEC_SHELL_VER_MAJOR;
   1257             pVersionInfo->m_minor= VIDEOEDITOR_VIDEC_SHELL_VER_MINOR;
   1258             pVersionInfo->m_revision = VIDEOEDITOR_VIDEC_SHELL_VER_REVISION;
   1259             pVersionInfo->m_structSize=sizeof(M4_VersionInfo);
   1260             break;
   1261 
   1262         case M4DECODER_kOptionID_VideoSize:
   1263             /** Only VPS uses this Option ID. */
   1264             pVideoSize = (M4DECODER_VideoSize*)pValue;
   1265             pDecShellContext->mVideoDecoder->getFormat()->findInt32(kKeyWidth,
   1266                 (int32_t*)(&pVideoSize->m_uiWidth));
   1267             pDecShellContext->mVideoDecoder->getFormat()->findInt32(kKeyHeight,
   1268                 (int32_t*)(&pVideoSize->m_uiHeight));
   1269             LOGV("VideoEditorVideoDecoder_getOption : W=%d H=%d",
   1270                 pVideoSize->m_uiWidth, pVideoSize->m_uiHeight);
   1271             break;
   1272 
   1273         case M4DECODER_kOptionID_NextRenderedFrameCTS:
   1274             /** How to get this information. SF decoder does not provide this. *
   1275             ** Let us provide last decoded frame CTS as of now. *
   1276             ** Only VPS uses this Option ID. */
   1277             pNextFrameCts = (M4OSA_UInt32 *)pValue;
   1278             *pNextFrameCts = pDecShellContext->m_lastDecodedCTS;
   1279             break;
   1280         case M4DECODER_MPEG4_kOptionID_DecoderConfigInfo:
   1281             if(pDecShellContext->mDecoderType == VIDEOEDITOR_kMpeg4VideoDec) {
   1282                 (*(M4DECODER_MPEG4_DecoderConfigInfo*)pValue) =
   1283                     pDecShellContext->m_Dci;
   1284             }
   1285             break;
   1286         default:
   1287             lerr = M4ERR_BAD_OPTION_ID;
   1288             break;
   1289 
   1290     }
   1291 
   1292     LOGV("VideoEditorVideoDecoder_getOption: end with err = 0x%x", lerr);
   1293     return lerr;
   1294 }
   1295 
   1296 M4OSA_ERR VideoEditorVideoDecoder_setOption(M4OSA_Context context,
   1297         M4OSA_OptionID optionId, M4OSA_DataOption pValue) {
   1298     M4OSA_ERR lerr = M4NO_ERROR;
   1299     VideoEditorVideoDecoder_Context *pDecShellContext =
   1300         (VideoEditorVideoDecoder_Context*) context;
   1301 
   1302     LOGV("VideoEditorVideoDecoder_setOption begin");
   1303 
   1304     switch (optionId) {
   1305         case M4DECODER_kOptionID_OutputFilter: {
   1306                 M4DECODER_OutputFilter* pOutputFilter =
   1307                     (M4DECODER_OutputFilter*) pValue;
   1308                 pDecShellContext->m_pFilter =
   1309                     (M4VIFI_PlanConverterFunctionType*)pOutputFilter->\
   1310                     m_pFilterFunction;
   1311                 pDecShellContext->m_pFilterUserData =
   1312                     pOutputFilter->m_pFilterUserData;
   1313             }
   1314             break;
   1315         case M4DECODER_kOptionID_DeblockingFilter:
   1316             break;
   1317         default:
   1318             lerr = M4ERR_BAD_CONTEXT;
   1319             break;
   1320     }
   1321 
   1322     LOGV("VideoEditorVideoDecoder_setOption: end with err = 0x%x", lerr);
   1323     return lerr;
   1324 }
   1325 
   1326 M4OSA_ERR VideoEditorVideoDecoder_decode(M4OSA_Context context,
   1327         M4_MediaTime* pTime, M4OSA_Bool bJump, M4OSA_UInt32 tolerance) {
   1328     M4OSA_ERR lerr = M4NO_ERROR;
   1329     VideoEditorVideoDecoder_Context* pDecShellContext =
   1330         (VideoEditorVideoDecoder_Context*) context;
   1331     int64_t lFrameTime;
   1332     MediaBuffer* pDecoderBuffer = NULL;
   1333     MediaBuffer* pNextBuffer = NULL;
   1334     status_t errStatus;
   1335     bool needSeek = bJump;
   1336 
   1337     LOGV("VideoEditorVideoDecoder_decode begin");
   1338 
   1339     if( M4OSA_TRUE == pDecShellContext->mReachedEOS ) {
   1340         // Do not call read(), it could lead to a freeze
   1341         LOGV("VideoEditorVideoDecoder_decode : EOS already reached");
   1342         lerr = M4WAR_NO_MORE_AU;
   1343         goto VIDEOEDITOR_VideoDecode_cleanUP;
   1344     }
   1345     if(pDecShellContext->m_lastDecodedCTS >= *pTime) {
   1346         LOGV("VideoDecoder_decode: Already decoded up to this time CTS = %lf.",
   1347             pDecShellContext->m_lastDecodedCTS);
   1348         goto VIDEOEDITOR_VideoDecode_cleanUP;
   1349     }
   1350     if(M4OSA_TRUE == bJump) {
   1351         LOGV("VideoEditorVideoDecoder_decode: Jump called");
   1352         pDecShellContext->m_lastDecodedCTS = -1;
   1353         pDecShellContext->m_lastRenderCts = -1;
   1354     }
   1355 
   1356     pDecShellContext->mNbInputFrames++;
   1357     if (0 > pDecShellContext->mFirstInputCts){
   1358         pDecShellContext->mFirstInputCts = *pTime;
   1359     }
   1360     pDecShellContext->mLastInputCts = *pTime;
   1361 
   1362     while (pDecoderBuffer == NULL || pDecShellContext->m_lastDecodedCTS + tolerance < *pTime) {
   1363         LOGV("VideoEditorVideoDecoder_decode, frameCTS = %lf, DecodeUpTo = %lf",
   1364             pDecShellContext->m_lastDecodedCTS, *pTime);
   1365 
   1366         // Read the buffer from the stagefright decoder
   1367         if (needSeek) {
   1368             MediaSource::ReadOptions options;
   1369             int64_t time_us = *pTime * 1000;
   1370             options.setSeekTo(time_us, MediaSource::ReadOptions::SEEK_PREVIOUS_SYNC);
   1371             errStatus = pDecShellContext->mVideoDecoder->read(&pNextBuffer, &options);
   1372             needSeek = false;
   1373         } else {
   1374             errStatus = pDecShellContext->mVideoDecoder->read(&pNextBuffer);
   1375         }
   1376 
   1377         // Handle EOS and format change
   1378         if (errStatus == ERROR_END_OF_STREAM) {
   1379             LOGV("End of stream reached, returning M4WAR_NO_MORE_AU ");
   1380             pDecShellContext->mReachedEOS = M4OSA_TRUE;
   1381             lerr = M4WAR_NO_MORE_AU;
   1382             // If we decoded a buffer before EOS, we still need to put it
   1383             // into the queue.
   1384             if (pDecoderBuffer && bJump) {
   1385                 copyBufferToQueue(pDecShellContext, pDecoderBuffer);
   1386             }
   1387             goto VIDEOEDITOR_VideoDecode_cleanUP;
   1388         } else if (INFO_FORMAT_CHANGED == errStatus) {
   1389             LOGV("VideoDecoder_decode : source returns INFO_FORMAT_CHANGED");
   1390             lerr = VideoEditorVideoDecoder_configureFromMetadata(
   1391                 pDecShellContext,
   1392                 pDecShellContext->mVideoDecoder->getFormat().get());
   1393             if( M4NO_ERROR != lerr ) {
   1394                 LOGV("!!! VideoEditorVideoDecoder_decode ERROR : "
   1395                     "VideoDecoder_configureFromMetadata returns 0x%X", lerr);
   1396                 break;
   1397             }
   1398             continue;
   1399         } else if (errStatus != OK) {
   1400             LOGE("VideoEditorVideoDecoder_decode ERROR:0x%x(%d)",
   1401                 errStatus,errStatus);
   1402             lerr = errStatus;
   1403             goto VIDEOEDITOR_VideoDecode_cleanUP;
   1404         }
   1405 
   1406         // The OMXCodec client should expect to receive 0-length buffers
   1407         // and drop the 0-length buffers.
   1408         if (pNextBuffer->range_length() == 0) {
   1409             pNextBuffer->release();
   1410             continue;
   1411         }
   1412 
   1413         // Now we have a good next buffer, release the previous one.
   1414         if (pDecoderBuffer != NULL) {
   1415             pDecoderBuffer->release();
   1416             pDecoderBuffer = NULL;
   1417         }
   1418         pDecoderBuffer = pNextBuffer;
   1419 
   1420         // Record the timestamp of last decoded buffer
   1421         pDecoderBuffer->meta_data()->findInt64(kKeyTime, &lFrameTime);
   1422         pDecShellContext->m_lastDecodedCTS = (M4_MediaTime)(lFrameTime/1000);
   1423         LOGV("VideoEditorVideoDecoder_decode,decoded frametime = %lf,size = %d",
   1424             (M4_MediaTime)lFrameTime, pDecoderBuffer->size() );
   1425 
   1426         // If bJump is false, we need to save every decoded buffer
   1427         if (!bJump) {
   1428             lerr = copyBufferToQueue(pDecShellContext, pDecoderBuffer);
   1429             if (lerr != M4NO_ERROR) {
   1430                 goto VIDEOEDITOR_VideoDecode_cleanUP;
   1431             }
   1432         }
   1433     }
   1434 
   1435     // If bJump is true, we only need to copy the last buffer
   1436     if (bJump) {
   1437         lerr = copyBufferToQueue(pDecShellContext, pDecoderBuffer);
   1438         if (lerr != M4NO_ERROR) {
   1439             goto VIDEOEDITOR_VideoDecode_cleanUP;
   1440         }
   1441     }
   1442 
   1443     pDecShellContext->mNbOutputFrames++;
   1444     if ( 0 > pDecShellContext->mFirstOutputCts ) {
   1445         pDecShellContext->mFirstOutputCts = *pTime;
   1446     }
   1447     pDecShellContext->mLastOutputCts = *pTime;
   1448 
   1449 VIDEOEDITOR_VideoDecode_cleanUP:
   1450     *pTime = pDecShellContext->m_lastDecodedCTS;
   1451     if (pDecoderBuffer != NULL) {
   1452         pDecoderBuffer->release();
   1453         pDecoderBuffer = NULL;
   1454     }
   1455 
   1456     LOGV("VideoEditorVideoDecoder_decode: end with 0x%x", lerr);
   1457     return lerr;
   1458 }
   1459 
   1460 static M4OSA_ERR copyBufferToQueue(
   1461     VideoEditorVideoDecoder_Context* pDecShellContext,
   1462     MediaBuffer* pDecoderBuffer) {
   1463 
   1464     M4OSA_ERR lerr = M4NO_ERROR;
   1465     VIDEOEDITOR_BUFFER_Buffer* tmpDecBuffer;
   1466 
   1467     // Get a buffer from the queue
   1468     lerr = VIDEOEDITOR_BUFFER_getBuffer(pDecShellContext->m_pDecBufferPool,
   1469         VIDEOEDITOR_BUFFER_kEmpty, &tmpDecBuffer);
   1470     if (lerr == (M4OSA_UInt32)M4ERR_NO_BUFFER_AVAILABLE) {
   1471         lerr = VIDEOEDITOR_BUFFER_getOldestBuffer(
   1472             pDecShellContext->m_pDecBufferPool,
   1473             VIDEOEDITOR_BUFFER_kFilled, &tmpDecBuffer);
   1474         tmpDecBuffer->state = VIDEOEDITOR_BUFFER_kEmpty;
   1475         lerr = M4NO_ERROR;
   1476     }
   1477 
   1478     if (lerr != M4NO_ERROR) return lerr;
   1479 
   1480     // Color convert or copy from the given MediaBuffer to our buffer
   1481     if (pDecShellContext->mI420ColorConverter) {
   1482         if (pDecShellContext->mI420ColorConverter->convertDecoderOutputToI420(
   1483             (uint8_t *)pDecoderBuffer->data(),// ?? + pDecoderBuffer->range_offset(),   // decoderBits
   1484             pDecShellContext->mGivenWidth,  // decoderWidth
   1485             pDecShellContext->mGivenHeight,  // decoderHeight
   1486             pDecShellContext->mCropRect,  // decoderRect
   1487             tmpDecBuffer->pData /* dstBits */) < 0) {
   1488             LOGE("convertDecoderOutputToI420 failed");
   1489             lerr = M4ERR_NOT_IMPLEMENTED;
   1490         }
   1491     } else if (pDecShellContext->decOuputColorFormat == OMX_COLOR_FormatYUV420Planar) {
   1492         int32_t width = pDecShellContext->m_pVideoStreamhandler->m_videoWidth;
   1493         int32_t height = pDecShellContext->m_pVideoStreamhandler->m_videoHeight;
   1494         int32_t yPlaneSize = width * height;
   1495         int32_t uvPlaneSize = width * height / 4;
   1496         int32_t offsetSrc = 0;
   1497 
   1498         if (( width == pDecShellContext->mGivenWidth )  &&
   1499             ( height == pDecShellContext->mGivenHeight ))
   1500         {
   1501             M4OSA_MemAddr8 pTmpBuff = (M4OSA_MemAddr8)pDecoderBuffer->data() + pDecoderBuffer->range_offset();
   1502 
   1503             memcpy((void *)tmpDecBuffer->pData, (void *)pTmpBuff, yPlaneSize);
   1504 
   1505             offsetSrc += pDecShellContext->mGivenWidth * pDecShellContext->mGivenHeight;
   1506             memcpy((void *)((M4OSA_MemAddr8)tmpDecBuffer->pData + yPlaneSize),
   1507                 (void *)(pTmpBuff + offsetSrc), uvPlaneSize);
   1508 
   1509             offsetSrc += (pDecShellContext->mGivenWidth >> 1) * (pDecShellContext->mGivenHeight >> 1);
   1510             memcpy((void *)((M4OSA_MemAddr8)tmpDecBuffer->pData + yPlaneSize + uvPlaneSize),
   1511                 (void *)(pTmpBuff + offsetSrc), uvPlaneSize);
   1512         }
   1513         else
   1514         {
   1515             M4OSA_MemAddr8 pTmpBuff = (M4OSA_MemAddr8)pDecoderBuffer->data() + pDecoderBuffer->range_offset();
   1516             M4OSA_MemAddr8 pTmpBuffDst = (M4OSA_MemAddr8)tmpDecBuffer->pData;
   1517             int32_t index;
   1518 
   1519             for ( index = 0; index < height; index++)
   1520             {
   1521                 memcpy((void *)pTmpBuffDst, (void *)pTmpBuff, width);
   1522                 pTmpBuffDst += width;
   1523                 pTmpBuff += pDecShellContext->mGivenWidth;
   1524             }
   1525 
   1526             pTmpBuff += (pDecShellContext->mGivenWidth * ( pDecShellContext->mGivenHeight - height));
   1527             for ( index = 0; index < height >> 1; index++)
   1528             {
   1529                 memcpy((void *)pTmpBuffDst, (void *)pTmpBuff, width >> 1);
   1530                 pTmpBuffDst += width >> 1;
   1531                 pTmpBuff += pDecShellContext->mGivenWidth >> 1;
   1532             }
   1533 
   1534             pTmpBuff += ((pDecShellContext->mGivenWidth * (pDecShellContext->mGivenHeight - height)) / 4);
   1535             for ( index = 0; index < height >> 1; index++)
   1536             {
   1537                 memcpy((void *)pTmpBuffDst, (void *)pTmpBuff, width >> 1);
   1538                 pTmpBuffDst += width >> 1;
   1539                 pTmpBuff += pDecShellContext->mGivenWidth >> 1;
   1540             }
   1541         }
   1542     } else {
   1543         LOGE("VideoDecoder_decode: unexpected color format 0x%X",
   1544             pDecShellContext->decOuputColorFormat);
   1545         lerr = M4ERR_PARAMETER;
   1546     }
   1547 
   1548     tmpDecBuffer->buffCTS = pDecShellContext->m_lastDecodedCTS;
   1549     tmpDecBuffer->state = VIDEOEDITOR_BUFFER_kFilled;
   1550     tmpDecBuffer->size = pDecoderBuffer->size();
   1551 
   1552     return lerr;
   1553 }
   1554 
   1555 M4OSA_ERR VideoEditorVideoDecoder_render(M4OSA_Context context,
   1556         M4_MediaTime* pTime, M4VIFI_ImagePlane* pOutputPlane,
   1557         M4OSA_Bool bForceRender) {
   1558     M4OSA_ERR err = M4NO_ERROR;
   1559     VideoEditorVideoDecoder_Context* pDecShellContext =
   1560         (VideoEditorVideoDecoder_Context*) context;
   1561     M4OSA_UInt32 lindex, i;
   1562     M4OSA_UInt8* p_buf_src, *p_buf_dest;
   1563     M4VIFI_ImagePlane tmpPlaneIn, tmpPlaneOut;
   1564     VIDEOEDITOR_BUFFER_Buffer* pTmpVIDEOEDITORBuffer, *pRenderVIDEOEDITORBuffer
   1565                                                                   = M4OSA_NULL;
   1566     M4_MediaTime candidateTimeStamp = -1;
   1567     M4OSA_Bool bFound = M4OSA_FALSE;
   1568 
   1569     LOGV("VideoEditorVideoDecoder_render begin");
   1570     // Input parameters check
   1571     VIDEOEDITOR_CHECK(M4OSA_NULL != context, M4ERR_PARAMETER);
   1572     VIDEOEDITOR_CHECK(M4OSA_NULL != pTime, M4ERR_PARAMETER);
   1573     VIDEOEDITOR_CHECK(M4OSA_NULL != pOutputPlane, M4ERR_PARAMETER);
   1574 
   1575     // The output buffer is already allocated, just copy the data
   1576     if ( (*pTime <= pDecShellContext->m_lastRenderCts) &&
   1577             (M4OSA_FALSE == bForceRender) ) {
   1578         LOGV("VIDEOEDITOR_VIDEO_render Frame in the past");
   1579         err = M4WAR_VIDEORENDERER_NO_NEW_FRAME;
   1580         goto cleanUp;
   1581     }
   1582     LOGV("VideoDecoder_render: lastRendered time = %lf,requested render time = "
   1583         "%lf", pDecShellContext->m_lastRenderCts, *pTime);
   1584 
   1585     /**
   1586      * Find the buffer appropriate for rendering.  */
   1587     for (i=0; i < pDecShellContext->m_pDecBufferPool->NB; i++) {
   1588         pTmpVIDEOEDITORBuffer = &pDecShellContext->m_pDecBufferPool\
   1589             ->pNXPBuffer[i];
   1590         if (pTmpVIDEOEDITORBuffer->state == VIDEOEDITOR_BUFFER_kFilled) {
   1591             /** Free all those buffers older than last rendered frame. */
   1592             if (pTmpVIDEOEDITORBuffer->buffCTS < pDecShellContext->\
   1593                     m_lastRenderCts) {
   1594                 pTmpVIDEOEDITORBuffer->state = VIDEOEDITOR_BUFFER_kEmpty;
   1595             }
   1596 
   1597             /** Get the buffer with appropriate timestamp  */
   1598             if ( (pTmpVIDEOEDITORBuffer->buffCTS >= pDecShellContext->\
   1599                     m_lastRenderCts) &&
   1600                 (pTmpVIDEOEDITORBuffer->buffCTS <= *pTime) &&
   1601                 (pTmpVIDEOEDITORBuffer->buffCTS > candidateTimeStamp)) {
   1602                 bFound = M4OSA_TRUE;
   1603                 pRenderVIDEOEDITORBuffer = pTmpVIDEOEDITORBuffer;
   1604                 candidateTimeStamp = pTmpVIDEOEDITORBuffer->buffCTS;
   1605                 LOGV("VideoDecoder_render: found a buffer with timestamp = %lf",
   1606                     candidateTimeStamp);
   1607             }
   1608         }
   1609     }
   1610     if (M4OSA_FALSE == bFound) {
   1611         err = M4WAR_VIDEORENDERER_NO_NEW_FRAME;
   1612         goto cleanUp;
   1613     }
   1614 
   1615     LOGV("VideoEditorVideoDecoder_render 3 ouput %d %d %d %d",
   1616         pOutputPlane[0].u_width, pOutputPlane[0].u_height,
   1617         pOutputPlane[0].u_topleft, pOutputPlane[0].u_stride);
   1618 
   1619     pDecShellContext->m_lastRenderCts = candidateTimeStamp;
   1620 
   1621     if( M4OSA_NULL != pDecShellContext->m_pFilter ) {
   1622         // Filtering was requested
   1623         M4VIFI_ImagePlane tmpPlane[3];
   1624         // Prepare the output image for conversion
   1625         tmpPlane[0].u_width   =
   1626             pDecShellContext->m_pVideoStreamhandler->m_videoWidth;
   1627         tmpPlane[0].u_height  =
   1628             pDecShellContext->m_pVideoStreamhandler->m_videoHeight;
   1629         tmpPlane[0].u_topleft = 0;
   1630         tmpPlane[0].u_stride  = tmpPlane[0].u_width;
   1631         tmpPlane[0].pac_data  = (M4VIFI_UInt8*)pRenderVIDEOEDITORBuffer->pData;
   1632         tmpPlane[1].u_width   = tmpPlane[0].u_width/2;
   1633         tmpPlane[1].u_height  = tmpPlane[0].u_height/2;
   1634         tmpPlane[1].u_topleft = 0;
   1635         tmpPlane[1].u_stride  = tmpPlane[0].u_stride/2;
   1636         tmpPlane[1].pac_data  = tmpPlane[0].pac_data +
   1637             (tmpPlane[0].u_stride * tmpPlane[0].u_height);
   1638         tmpPlane[2].u_width   = tmpPlane[1].u_width;
   1639         tmpPlane[2].u_height  = tmpPlane[1].u_height;
   1640         tmpPlane[2].u_topleft = 0;
   1641         tmpPlane[2].u_stride  = tmpPlane[1].u_stride;
   1642         tmpPlane[2].pac_data  = tmpPlane[1].pac_data +
   1643             (tmpPlane[1].u_stride * tmpPlane[1].u_height);
   1644 
   1645         LOGV("VideoEditorVideoDecoder_render w = %d H = %d",
   1646             tmpPlane[0].u_width,tmpPlane[0].u_height);
   1647         pDecShellContext->m_pFilter(M4OSA_NULL, &tmpPlane[0], pOutputPlane);
   1648     } else {
   1649         // Just copy the YUV420P buffer
   1650         M4OSA_MemAddr8 tempBuffPtr =
   1651             (M4OSA_MemAddr8)pRenderVIDEOEDITORBuffer->pData;
   1652         M4OSA_UInt32 tempWidth =
   1653             pDecShellContext->m_pVideoStreamhandler->m_videoWidth;
   1654         M4OSA_UInt32 tempHeight =
   1655             pDecShellContext->m_pVideoStreamhandler->m_videoHeight;
   1656 
   1657         memcpy((void *) pOutputPlane[0].pac_data, (void *)tempBuffPtr,
   1658             tempWidth * tempHeight);
   1659         tempBuffPtr += (tempWidth * tempHeight);
   1660         memcpy((void *) pOutputPlane[1].pac_data, (void *)tempBuffPtr,
   1661             (tempWidth/2) * (tempHeight/2));
   1662         tempBuffPtr += ((tempWidth/2) * (tempHeight/2));
   1663         memcpy((void *) pOutputPlane[2].pac_data, (void *)tempBuffPtr,
   1664             (tempWidth/2) * (tempHeight/2));
   1665     }
   1666 
   1667     pDecShellContext->mNbRenderedFrames++;
   1668     if ( 0 > pDecShellContext->mFirstRenderedCts ) {
   1669         pDecShellContext->mFirstRenderedCts = *pTime;
   1670     }
   1671     pDecShellContext->mLastRenderedCts = *pTime;
   1672 
   1673 cleanUp:
   1674     if( M4NO_ERROR == err ) {
   1675         *pTime = pDecShellContext->m_lastRenderCts;
   1676         LOGV("VideoEditorVideoDecoder_render no error");
   1677     } else {
   1678         LOGV("VideoEditorVideoDecoder_render ERROR 0x%X", err);
   1679     }
   1680     LOGV("VideoEditorVideoDecoder_render end");
   1681     return err;
   1682 }
   1683 
   1684 M4OSA_ERR VideoEditorVideoDecoder_getInterface(M4DECODER_VideoType decoderType,
   1685         M4DECODER_VideoType *pDecoderType, M4OSA_Context *pDecInterface) {
   1686     M4DECODER_VideoInterface* pDecoderInterface = M4OSA_NULL;
   1687 
   1688     pDecoderInterface = (M4DECODER_VideoInterface*)M4OSA_32bitAlignedMalloc(
   1689         sizeof(M4DECODER_VideoInterface), M4DECODER_EXTERNAL,
   1690         (M4OSA_Char*)"VideoEditorVideoDecoder_getInterface" );
   1691     if (M4OSA_NULL == pDecoderInterface) {
   1692         return M4ERR_ALLOC;
   1693     }
   1694 
   1695     *pDecoderType = decoderType;
   1696 
   1697     pDecoderInterface->m_pFctCreate    = VideoEditorVideoDecoder_create;
   1698     pDecoderInterface->m_pFctDestroy   = VideoEditorVideoDecoder_destroy;
   1699     pDecoderInterface->m_pFctGetOption = VideoEditorVideoDecoder_getOption;
   1700     pDecoderInterface->m_pFctSetOption = VideoEditorVideoDecoder_setOption;
   1701     pDecoderInterface->m_pFctDecode    = VideoEditorVideoDecoder_decode;
   1702     pDecoderInterface->m_pFctRender    = VideoEditorVideoDecoder_render;
   1703 
   1704     *pDecInterface = (M4OSA_Context)pDecoderInterface;
   1705     return M4NO_ERROR;
   1706 }
   1707 
   1708 M4OSA_ERR VideoEditorVideoDecoder_getSoftwareInterface(M4DECODER_VideoType decoderType,
   1709         M4DECODER_VideoType *pDecoderType, M4OSA_Context *pDecInterface) {
   1710     M4DECODER_VideoInterface* pDecoderInterface = M4OSA_NULL;
   1711 
   1712     pDecoderInterface = (M4DECODER_VideoInterface*)M4OSA_32bitAlignedMalloc(
   1713         sizeof(M4DECODER_VideoInterface), M4DECODER_EXTERNAL,
   1714         (M4OSA_Char*)"VideoEditorVideoDecoder_getInterface" );
   1715     if (M4OSA_NULL == pDecoderInterface) {
   1716         return M4ERR_ALLOC;
   1717     }
   1718 
   1719     *pDecoderType = decoderType;
   1720 
   1721     pDecoderInterface->m_pFctCreate    = VideoEditorVideoSoftwareDecoder_create;
   1722     pDecoderInterface->m_pFctDestroy   = VideoEditorVideoDecoder_destroy;
   1723     pDecoderInterface->m_pFctGetOption = VideoEditorVideoDecoder_getOption;
   1724     pDecoderInterface->m_pFctSetOption = VideoEditorVideoDecoder_setOption;
   1725     pDecoderInterface->m_pFctDecode    = VideoEditorVideoDecoder_decode;
   1726     pDecoderInterface->m_pFctRender    = VideoEditorVideoDecoder_render;
   1727 
   1728     *pDecInterface = (M4OSA_Context)pDecoderInterface;
   1729     return M4NO_ERROR;
   1730 }
   1731 extern "C" {
   1732 
   1733 M4OSA_ERR VideoEditorVideoDecoder_getInterface_MPEG4(
   1734         M4DECODER_VideoType *pDecoderType, M4OSA_Context *pDecInterface) {
   1735     return VideoEditorVideoDecoder_getInterface(M4DECODER_kVideoTypeMPEG4,
   1736         pDecoderType, pDecInterface);
   1737 }
   1738 
   1739 M4OSA_ERR VideoEditorVideoDecoder_getInterface_H264(
   1740         M4DECODER_VideoType *pDecoderType, M4OSA_Context *pDecInterface) {
   1741     return VideoEditorVideoDecoder_getInterface(M4DECODER_kVideoTypeAVC,
   1742         pDecoderType, pDecInterface);
   1743 
   1744 }
   1745 
   1746 M4OSA_ERR VideoEditorVideoDecoder_getSoftwareInterface_MPEG4(
   1747         M4DECODER_VideoType *pDecoderType, M4OSA_Context *pDecInterface) {
   1748     return VideoEditorVideoDecoder_getSoftwareInterface(M4DECODER_kVideoTypeMPEG4,
   1749         pDecoderType, pDecInterface);
   1750 }
   1751 
   1752 M4OSA_ERR VideoEditorVideoDecoder_getSoftwareInterface_H264(
   1753         M4DECODER_VideoType *pDecoderType, M4OSA_Context *pDecInterface) {
   1754     return VideoEditorVideoDecoder_getSoftwareInterface(M4DECODER_kVideoTypeAVC,
   1755         pDecoderType, pDecInterface);
   1756 
   1757 }
   1758 
   1759 M4OSA_ERR VideoEditorVideoDecoder_getVideoDecodersAndCapabilities(
   1760     M4DECODER_VideoDecoders** decoders) {
   1761     return queryVideoDecoderCapabilities(decoders);
   1762 }
   1763 
   1764 }  // extern "C"
   1765