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