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