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