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