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