VideoEditorVideoDecoder.cpp revision 35cb2de64cb6482a08f446e80733e7d344a0dcac
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    int32_t vWidth, vHeight;
725    int32_t cropLeft, cropTop, cropRight, cropBottom;
726
727    VIDEOEDITOR_CHECK(M4OSA_NULL != pContext, M4ERR_PARAMETER);
728    VIDEOEDITOR_CHECK(M4OSA_NULL != meta,     M4ERR_PARAMETER);
729
730    LOGV("VideoEditorVideoDecoder_configureFromMetadata begin");
731
732    pDecShellContext = (VideoEditorVideoDecoder_Context*)pContext;
733
734    success = meta->findInt32(kKeyWidth, &vWidth);
735    VIDEOEDITOR_CHECK(TRUE == success, M4ERR_PARAMETER);
736    success = meta->findInt32(kKeyHeight, &vHeight);
737    VIDEOEDITOR_CHECK(TRUE == success, M4ERR_PARAMETER);
738
739    pDecShellContext->mGivenWidth = vWidth;
740    pDecShellContext->mGivenHeight = vHeight;
741
742    if (!meta->findRect(
743                kKeyCropRect, &cropLeft, &cropTop, &cropRight, &cropBottom)) {
744
745        cropLeft = cropTop = 0;
746        cropRight = vWidth - 1;
747        cropBottom = vHeight - 1;
748
749        LOGI("got dimensions only %d x %d", width, height);
750    } else {
751        LOGI("got crop rect %d, %d, %d, %d",
752             cropLeft, cropTop, cropRight, cropBottom);
753    }
754
755    width = cropRight - cropLeft + 1;
756    height = cropBottom - cropTop + 1;
757
758    LOGV("VideoDecoder_configureFromMetadata : W=%d H=%d", width, height);
759    VIDEOEDITOR_CHECK((0 != width) && (0 != height), M4ERR_PARAMETER);
760
761    LOGV("VideoDecoder_configureFromMetadata : W=%d H=%d", width, height);
762
763    if( (M4OSA_NULL != pDecShellContext->m_pDecBufferPool) &&
764        (pDecShellContext->m_pVideoStreamhandler->m_videoWidth  == \
765            (uint32_t)width) &&
766        (pDecShellContext->m_pVideoStreamhandler->m_videoHeight == \
767            (uint32_t)height) ) {
768        // No need to reconfigure
769        goto cleanUp;
770    }
771    LOGV("VideoDecoder_configureFromMetadata  reset: W=%d H=%d", width, height);
772    // Update the stream handler parameters
773    pDecShellContext->m_pVideoStreamhandler->m_videoWidth  = width;
774    pDecShellContext->m_pVideoStreamhandler->m_videoHeight = height;
775    frameSize = (width * height * 3) / 2;
776
777    // Configure the buffer pool
778    if( M4OSA_NULL != pDecShellContext->m_pDecBufferPool ) {
779        LOGV("VideoDecoder_configureFromMetadata : reset the buffer pool");
780        VIDEOEDITOR_BUFFER_freePool(pDecShellContext->m_pDecBufferPool);
781        pDecShellContext->m_pDecBufferPool = M4OSA_NULL;
782    }
783    err =  VIDEOEDITOR_BUFFER_allocatePool(&pDecShellContext->m_pDecBufferPool,
784        MAX_DEC_BUFFERS, (M4OSA_Char*)"VIDEOEDITOR_DecodedBufferPool");
785    VIDEOEDITOR_CHECK(M4NO_ERROR == err, err);
786    err = VIDEOEDITOR_BUFFER_initPoolBuffers(pDecShellContext->m_pDecBufferPool,
787                frameSize + pDecShellContext->mGivenWidth * 2);
788
789    VIDEOEDITOR_CHECK(M4NO_ERROR == err, err);
790
791cleanUp:
792    if( M4NO_ERROR == err ) {
793        LOGV("VideoEditorVideoDecoder_configureFromMetadata no error");
794    } else {
795        if( M4OSA_NULL != pDecShellContext->m_pDecBufferPool ) {
796            VIDEOEDITOR_BUFFER_freePool(pDecShellContext->m_pDecBufferPool);
797            pDecShellContext->m_pDecBufferPool = M4OSA_NULL;
798        }
799        LOGV("VideoEditorVideoDecoder_configureFromMetadata ERROR 0x%X", err);
800    }
801    LOGV("VideoEditorVideoDecoder_configureFromMetadata end");
802    return err;
803}
804
805M4OSA_ERR VideoEditorVideoDecoder_destroy(M4OSA_Context pContext) {
806    M4OSA_ERR err = M4NO_ERROR;
807    VideoEditorVideoDecoder_Context* pDecShellContext =
808        (VideoEditorVideoDecoder_Context*)pContext;
809
810    // Input parameters check
811    LOGV("VideoEditorVideoDecoder_destroy begin");
812    VIDEOEDITOR_CHECK(M4OSA_NULL != pContext, M4ERR_PARAMETER);
813
814    // Destroy the graph
815    if( pDecShellContext->mVideoDecoder != NULL ) {
816        LOGV("### VideoEditorVideoDecoder_destroy : releasing decoder");
817        pDecShellContext->mVideoDecoder->stop();
818        pDecShellContext->mVideoDecoder.clear();
819    }
820    pDecShellContext->mClient.disconnect();
821    pDecShellContext->mReaderSource.clear();
822
823    // Release memory
824    if( pDecShellContext->m_pDecBufferPool != M4OSA_NULL ) {
825        VIDEOEDITOR_BUFFER_freePool(pDecShellContext->m_pDecBufferPool);
826        pDecShellContext->m_pDecBufferPool = M4OSA_NULL;
827    }
828    SAFE_FREE(pDecShellContext);
829    pContext = NULL;
830
831cleanUp:
832    if( M4NO_ERROR == err ) {
833        LOGV("VideoEditorVideoDecoder_destroy no error");
834    } else {
835        LOGV("VideoEditorVideoDecoder_destroy ERROR 0x%X", err);
836    }
837    LOGV("VideoEditorVideoDecoder_destroy end");
838    return err;
839}
840
841M4OSA_ERR VideoEditorVideoDecoder_create(M4OSA_Context *pContext,
842        M4_StreamHandler *pStreamHandler,
843        M4READER_DataInterface *pReaderDataInterface,
844        M4_AccessUnit *pAccessUnit, M4OSA_Void *pUserData) {
845    M4OSA_ERR err = M4NO_ERROR;
846    VideoEditorVideoDecoder_Context* pDecShellContext = M4OSA_NULL;
847    status_t status = OK;
848    bool success = TRUE;
849    int32_t colorFormat = 0;
850    M4OSA_UInt32 size = 0;
851    sp<MetaData> decoderMetadata = NULL;
852
853    LOGV("VideoEditorVideoDecoder_create begin");
854    // Input parameters check
855    VIDEOEDITOR_CHECK(M4OSA_NULL != pContext,             M4ERR_PARAMETER);
856    VIDEOEDITOR_CHECK(M4OSA_NULL != pStreamHandler,       M4ERR_PARAMETER);
857    VIDEOEDITOR_CHECK(M4OSA_NULL != pReaderDataInterface, M4ERR_PARAMETER);
858
859    // Context allocation & initialization
860    SAFE_MALLOC(pDecShellContext, VideoEditorVideoDecoder_Context, 1,
861        "VideoEditorVideoDecoder");
862    pDecShellContext->m_pVideoStreamhandler =
863        (M4_VideoStreamHandler*)pStreamHandler;
864    pDecShellContext->m_pNextAccessUnitToDecode = pAccessUnit;
865    pDecShellContext->m_pReader = pReaderDataInterface;
866    pDecShellContext->m_lastDecodedCTS = -1;
867    pDecShellContext->m_lastRenderCts = -1;
868    switch( pStreamHandler->m_streamType ) {
869        case M4DA_StreamTypeVideoH263:
870            pDecShellContext->mDecoderType = VIDEOEDITOR_kH263VideoDec;
871            break;
872        case M4DA_StreamTypeVideoMpeg4:
873            pDecShellContext->mDecoderType = VIDEOEDITOR_kMpeg4VideoDec;
874            // Parse the VOL header
875            err = VideoEditorVideoDecoder_internalParseVideoDSI(
876                (M4OSA_UInt8*)pDecShellContext->m_pVideoStreamhandler->\
877                    m_basicProperties.m_pDecoderSpecificInfo,
878                pDecShellContext->m_pVideoStreamhandler->\
879                    m_basicProperties.m_decoderSpecificInfoSize,
880                &pDecShellContext->m_Dci, &pDecShellContext->m_VideoSize);
881            VIDEOEDITOR_CHECK(M4NO_ERROR == err, err);
882            break;
883        case M4DA_StreamTypeVideoMpeg4Avc:
884            pDecShellContext->mDecoderType = VIDEOEDITOR_kH264VideoDec;
885            break;
886        default:
887            VIDEOEDITOR_CHECK(!"VideoDecoder_create : incorrect stream type",
888                M4ERR_PARAMETER);
889            break;
890    }
891
892    pDecShellContext->mNbInputFrames     = 0;
893    pDecShellContext->mFirstInputCts     = -1.0;
894    pDecShellContext->mLastInputCts      = -1.0;
895    pDecShellContext->mNbRenderedFrames  = 0;
896    pDecShellContext->mFirstRenderedCts  = -1.0;
897    pDecShellContext->mLastRenderedCts   = -1.0;
898    pDecShellContext->mNbOutputFrames    = 0;
899    pDecShellContext->mFirstOutputCts    = -1;
900    pDecShellContext->mLastOutputCts     = -1;
901    pDecShellContext->m_pDecBufferPool   = M4OSA_NULL;
902
903    /**
904     * StageFright graph building
905     */
906    decoderMetadata = new MetaData;
907    switch( pDecShellContext->mDecoderType ) {
908        case VIDEOEDITOR_kH263VideoDec:
909            decoderMetadata->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_H263);
910            break;
911        case VIDEOEDITOR_kMpeg4VideoDec:
912            decoderMetadata->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_MPEG4);
913            decoderMetadata->setData(kKeyESDS, kTypeESDS,
914                pStreamHandler->m_pESDSInfo,
915                pStreamHandler->m_ESDSInfoSize);
916            break;
917        case VIDEOEDITOR_kH264VideoDec:
918            decoderMetadata->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_AVC);
919            decoderMetadata->setData(kKeyAVCC, kTypeAVCC,
920                pStreamHandler->m_pH264DecoderSpecificInfo,
921                pStreamHandler->m_H264decoderSpecificInfoSize);
922            break;
923        default:
924            VIDEOEDITOR_CHECK(!"VideoDecoder_create : incorrect stream type",
925                M4ERR_PARAMETER);
926            break;
927    }
928
929    decoderMetadata->setInt32(kKeyMaxInputSize, pStreamHandler->m_maxAUSize);
930    decoderMetadata->setInt32(kKeyWidth,
931        pDecShellContext->m_pVideoStreamhandler->m_videoWidth);
932    decoderMetadata->setInt32(kKeyHeight,
933        pDecShellContext->m_pVideoStreamhandler->m_videoHeight);
934
935    // Create the decoder source
936    pDecShellContext->mReaderSource = new VideoEditorVideoDecoderSource(
937        decoderMetadata, pDecShellContext->mDecoderType,
938        (void *)pDecShellContext);
939    VIDEOEDITOR_CHECK(NULL != pDecShellContext->mReaderSource.get(),
940        M4ERR_SF_DECODER_RSRC_FAIL);
941
942    // Connect to the OMX client
943    status = pDecShellContext->mClient.connect();
944    VIDEOEDITOR_CHECK(OK == status, M4ERR_SF_DECODER_RSRC_FAIL);
945
946    // Create the decoder
947    pDecShellContext->mVideoDecoder = OMXCodec::Create(
948        pDecShellContext->mClient.interface(),
949        decoderMetadata, false, pDecShellContext->mReaderSource);
950    VIDEOEDITOR_CHECK(NULL != pDecShellContext->mVideoDecoder.get(),
951        M4ERR_SF_DECODER_RSRC_FAIL);
952
953
954    // Get the output color format
955    success = pDecShellContext->mVideoDecoder->getFormat()->findInt32(
956        kKeyColorFormat, &colorFormat);
957    VIDEOEDITOR_CHECK(TRUE == success, M4ERR_PARAMETER);
958    pDecShellContext->decOuputColorFormat = (OMX_COLOR_FORMATTYPE)colorFormat;
959
960    pDecShellContext->mVideoDecoder->getFormat()->setInt32(kKeyWidth,
961        pDecShellContext->m_pVideoStreamhandler->m_videoWidth);
962    pDecShellContext->mVideoDecoder->getFormat()->setInt32(kKeyHeight,
963        pDecShellContext->m_pVideoStreamhandler->m_videoHeight);
964
965    // Configure the buffer pool from the metadata
966    err = VideoEditorVideoDecoder_configureFromMetadata(pDecShellContext,
967        pDecShellContext->mVideoDecoder->getFormat().get());
968    VIDEOEDITOR_CHECK(M4NO_ERROR == err, err);
969
970    // Start the graph
971    status = pDecShellContext->mVideoDecoder->start();
972    VIDEOEDITOR_CHECK(OK == status, M4ERR_SF_DECODER_RSRC_FAIL);
973
974    *pContext = (M4OSA_Context)pDecShellContext;
975
976cleanUp:
977    if( M4NO_ERROR == err ) {
978        LOGV("VideoEditorVideoDecoder_create no error");
979    } else {
980        VideoEditorVideoDecoder_destroy(pDecShellContext);
981        *pContext = M4OSA_NULL;
982        LOGV("VideoEditorVideoDecoder_create ERROR 0x%X", err);
983    }
984    LOGV("VideoEditorVideoDecoder_create : DONE");
985    return err;
986}
987
988M4OSA_ERR VideoEditorVideoDecoder_getOption(M4OSA_Context context,
989        M4OSA_OptionID optionId, M4OSA_DataOption pValue) {
990    M4OSA_ERR lerr = M4NO_ERROR;
991    VideoEditorVideoDecoder_Context* pDecShellContext =
992        (VideoEditorVideoDecoder_Context*) context;
993    M4_VersionInfo* pVersionInfo;
994    M4DECODER_VideoSize* pVideoSize;
995    M4OSA_UInt32* pNextFrameCts;
996    M4OSA_UInt32 *plastDecodedFrameCts;
997    M4DECODER_AVCProfileLevel* profile;
998    M4DECODER_MPEG4_DecoderConfigInfo* pDecConfInfo;
999
1000    LOGV("VideoEditorVideoDecoder_getOption begin");
1001
1002    switch (optionId) {
1003        case M4DECODER_kOptionID_AVCLastDecodedFrameCTS:
1004             plastDecodedFrameCts = (M4OSA_UInt32 *) pValue;
1005             *plastDecodedFrameCts = pDecShellContext->m_lastDecodedCTS;
1006             break;
1007
1008        case M4DECODER_kOptionID_Version:
1009            pVersionInfo = (M4_VersionInfo*)pValue;
1010
1011            pVersionInfo->m_major = VIDEOEDITOR_VIDEC_SHELL_VER_MAJOR;
1012            pVersionInfo->m_minor= VIDEOEDITOR_VIDEC_SHELL_VER_MINOR;
1013            pVersionInfo->m_revision = VIDEOEDITOR_VIDEC_SHELL_VER_REVISION;
1014            pVersionInfo->m_structSize=sizeof(M4_VersionInfo);
1015            break;
1016
1017        case M4DECODER_kOptionID_VideoSize:
1018            /** Only VPS uses this Option ID. */
1019            pVideoSize = (M4DECODER_VideoSize*)pValue;
1020            pDecShellContext->mVideoDecoder->getFormat()->findInt32(kKeyWidth,
1021                (int32_t*)(&pVideoSize->m_uiWidth));
1022            pDecShellContext->mVideoDecoder->getFormat()->findInt32(kKeyHeight,
1023                (int32_t*)(&pVideoSize->m_uiHeight));
1024            LOGV("VideoEditorVideoDecoder_getOption : W=%d H=%d",
1025                pVideoSize->m_uiWidth, pVideoSize->m_uiHeight);
1026            break;
1027
1028        case M4DECODER_kOptionID_NextRenderedFrameCTS:
1029            /** How to get this information. SF decoder does not provide this. *
1030            ** Let us provide last decoded frame CTS as of now. *
1031            ** Only VPS uses this Option ID. */
1032            pNextFrameCts = (M4OSA_UInt32 *)pValue;
1033            *pNextFrameCts = pDecShellContext->m_lastDecodedCTS;
1034            break;
1035        case M4DECODER_kOptionID_AVCProfileAndLevel:
1036            profile = (M4DECODER_AVCProfileLevel *) pValue;
1037            VideoEditorVideoDecoder_ParseAVCDSI (
1038                pDecShellContext->m_pVideoStreamhandler->\
1039                    m_basicProperties.m_pDecoderSpecificInfo,
1040                pDecShellContext->m_pVideoStreamhandler->\
1041                    m_basicProperties.m_decoderSpecificInfoSize,
1042                profile);
1043            break;
1044        case M4DECODER_MPEG4_kOptionID_DecoderConfigInfo:
1045            if(pDecShellContext->mDecoderType == VIDEOEDITOR_kMpeg4VideoDec) {
1046                (*(M4DECODER_MPEG4_DecoderConfigInfo*)pValue) =
1047                    pDecShellContext->m_Dci;
1048            }
1049            break;
1050        default:
1051            lerr = M4ERR_BAD_OPTION_ID;
1052            break;
1053
1054    }
1055
1056    LOGV("VideoEditorVideoDecoder_getOption: end with err = 0x%x", lerr);
1057    return lerr;
1058}
1059
1060M4OSA_ERR VideoEditorVideoDecoder_setOption(M4OSA_Context context,
1061        M4OSA_OptionID optionId, M4OSA_DataOption pValue) {
1062    M4OSA_ERR lerr = M4NO_ERROR;
1063    VideoEditorVideoDecoder_Context *pDecShellContext =
1064        (VideoEditorVideoDecoder_Context*) context;
1065
1066    LOGV("VideoEditorVideoDecoder_setOption begin");
1067
1068    switch (optionId) {
1069        case M4DECODER_kOptionID_OutputFilter: {
1070                M4DECODER_OutputFilter* pOutputFilter =
1071                    (M4DECODER_OutputFilter*) pValue;
1072                pDecShellContext->m_pFilter =
1073                    (M4VIFI_PlanConverterFunctionType*)pOutputFilter->\
1074                    m_pFilterFunction;
1075                pDecShellContext->m_pFilterUserData =
1076                    pOutputFilter->m_pFilterUserData;
1077            }
1078            break;
1079        case M4DECODER_kOptionID_DeblockingFilter:
1080            break;
1081        default:
1082            lerr = M4ERR_BAD_CONTEXT;
1083            break;
1084    }
1085
1086    LOGV("VideoEditorVideoDecoder_setOption: end with err = 0x%x", lerr);
1087    return lerr;
1088}
1089
1090M4OSA_ERR VideoEditorVideoDecoder_decode(M4OSA_Context context,
1091        M4_MediaTime* pTime, M4OSA_Bool bJump) {
1092    M4OSA_ERR lerr = M4NO_ERROR;
1093    VideoEditorVideoDecoder_Context* pDecShellContext =
1094        (VideoEditorVideoDecoder_Context*) context;
1095    int64_t lFrameTime;
1096    VIDEOEDITOR_BUFFER_Buffer* tmpDecBuffer;
1097    MediaSource::ReadOptions decShellOptions;
1098    MediaBuffer* pDecoderBuffer = NULL;
1099    status_t errStatus;
1100
1101
1102    LOGV("VideoEditorVideoDecoder_decode begin");
1103
1104    if( M4OSA_TRUE == pDecShellContext->mReachedEOS ) {
1105        // Do not call read(), it could lead to a freeze
1106        LOGV("VideoEditorVideoDecoder_decode : EOS already reached");
1107        lerr = M4WAR_NO_MORE_AU;
1108        goto VIDEOEDITOR_VideoDecode_cleanUP;
1109    }
1110    if(pDecShellContext->m_lastDecodedCTS >= *pTime) {
1111        LOGV("VideoDecoder_decode: Already decoded up to this time CTS = %lf.",
1112            pDecShellContext->m_lastDecodedCTS);
1113        goto VIDEOEDITOR_VideoDecode_cleanUP;
1114    }
1115    if(M4OSA_TRUE == bJump) {
1116        LOGV("VideoEditorVideoDecoder_decode: Jump called");
1117        pDecShellContext->m_lastDecodedCTS = -1;
1118        pDecShellContext->m_lastRenderCts = -1;
1119    }
1120
1121    pDecShellContext->mNbInputFrames++;
1122    if (0 > pDecShellContext->mFirstInputCts){
1123        pDecShellContext->mFirstInputCts = *pTime;
1124    }
1125    pDecShellContext->mLastInputCts = *pTime;
1126
1127    while (pDecShellContext->m_lastDecodedCTS < *pTime) {
1128        LOGV("VideoEditorVideoDecoder_decode, frameCTS = %lf, DecodeUpTo = %lf",
1129            pDecShellContext->m_lastDecodedCTS, *pTime);
1130        lerr = VIDEOEDITOR_BUFFER_getBuffer(pDecShellContext->m_pDecBufferPool,
1131            VIDEOEDITOR_BUFFER_kEmpty, &tmpDecBuffer);
1132        if (lerr == (M4OSA_UInt32)M4ERR_NO_BUFFER_AVAILABLE) {
1133            lerr = VIDEOEDITOR_BUFFER_getOldestBuffer(
1134                pDecShellContext->m_pDecBufferPool,
1135                VIDEOEDITOR_BUFFER_kFilled, &tmpDecBuffer);
1136            tmpDecBuffer->state = VIDEOEDITOR_BUFFER_kEmpty;
1137            lerr = M4NO_ERROR;
1138        }
1139
1140        if (lerr != M4NO_ERROR) {
1141            goto VIDEOEDITOR_VideoDecode_cleanUP;
1142        }
1143
1144        if (pDecoderBuffer != NULL) {
1145            pDecoderBuffer->release();
1146            pDecoderBuffer = NULL;
1147        }
1148
1149        decShellOptions.reset();
1150        errStatus = pDecShellContext->mVideoDecoder->read(&pDecoderBuffer,
1151            &decShellOptions);
1152        if (errStatus == ERROR_END_OF_STREAM) {
1153            LOGV("End of stream reached, returning M4WAR_NO_MORE_AU ");
1154            pDecShellContext->mReachedEOS = M4OSA_TRUE;
1155            lerr = M4WAR_NO_MORE_AU;
1156            goto VIDEOEDITOR_VideoDecode_cleanUP;
1157        } else if ( INFO_FORMAT_CHANGED == errStatus ) {
1158            LOGV("VideoDecoder_decode:source returns INFO_FORMAT_CHANGED:TODO");
1159
1160#if 1
1161            LOGV("VideoDecoder_decode : source returns INFO_FORMAT_CHANGED");
1162            lerr = VideoEditorVideoDecoder_configureFromMetadata(
1163                pDecShellContext,
1164                pDecShellContext->mVideoDecoder->getFormat().get());
1165            if( M4NO_ERROR != lerr ) {
1166                LOGV("!!! VideoEditorVideoDecoder_decode ERROR : "
1167                    "VideoDecoder_configureFromMetadata returns 0x%X", lerr);
1168                break;
1169            }
1170#endif
1171            continue;
1172        }
1173
1174        if( 0 < pDecoderBuffer->range_length() ) {
1175        LOGV("VIDEOEDITOR_VideoDecoder frame buffer size = %d",
1176            pDecoderBuffer->range_length());
1177
1178        pDecoderBuffer->meta_data()->findInt64(kKeyTime, &lFrameTime);
1179        pDecShellContext->m_lastDecodedCTS = (M4_MediaTime)(lFrameTime/1000);
1180        LOGV("VideoEditorVideoDecoder_decode,decoded frametime = %lf,size = %d",
1181            (M4_MediaTime)lFrameTime, pDecoderBuffer->size() );
1182
1183        switch ( pDecShellContext->decOuputColorFormat ) {
1184            case OMX_QCOM_COLOR_FormatYVU420SemiPlanar: {
1185                M4VIFI_ImagePlane tmpPlane[3];
1186                // Prepare the output image for conversion
1187                if( pDecoderBuffer->range_length() != (
1188                    pDecShellContext->m_pVideoStreamhandler->m_videoWidth *
1189                    pDecShellContext->m_pVideoStreamhandler->m_videoHeight \
1190                     * 3)/2 ) {
1191                    LOGV("VideoEditorVideoDecoder_decod invalid frame size S=%d"
1192                        "W=%d H=%d", pDecoderBuffer->range_length(),
1193                        pDecShellContext->m_pVideoStreamhandler->m_videoWidth,
1194                        pDecShellContext->m_pVideoStreamhandler->m_videoHeight);
1195                    lerr = M4ERR_PARAMETER;
1196                    goto VIDEOEDITOR_VideoDecode_cleanUP;
1197                }
1198                tmpPlane[0].u_width   =
1199                    pDecShellContext->m_pVideoStreamhandler->m_videoWidth;
1200                tmpPlane[0].u_height  =
1201                    pDecShellContext->m_pVideoStreamhandler->m_videoHeight;
1202                tmpPlane[0].u_topleft = 0;
1203                tmpPlane[0].u_stride  = tmpPlane[0].u_width;
1204                tmpPlane[0].pac_data  = (M4VIFI_UInt8*)tmpDecBuffer->pData;
1205                tmpPlane[1].u_width   = tmpPlane[0].u_width/2;
1206                tmpPlane[1].u_height  = tmpPlane[0].u_height/2;
1207                tmpPlane[1].u_topleft = 0;
1208                tmpPlane[1].u_stride  = tmpPlane[0].u_stride/2;
1209                tmpPlane[1].pac_data  = tmpPlane[0].pac_data +
1210                    (tmpPlane[0].u_stride * tmpPlane[0].u_height);
1211                tmpPlane[2].u_width   = tmpPlane[1].u_width;
1212                tmpPlane[2].u_height  = tmpPlane[1].u_height;
1213                tmpPlane[2].u_topleft = 0;
1214                tmpPlane[2].u_stride  = tmpPlane[1].u_stride;
1215                tmpPlane[2].pac_data  = tmpPlane[1].pac_data +
1216                    (tmpPlane[1].u_stride * tmpPlane[1].u_height);
1217                M4VIFI_SemiplanarYVU420toYUV420(M4OSA_NULL,
1218                    (M4VIFI_UInt8 *)pDecoderBuffer->data() + \
1219                    pDecoderBuffer->range_offset(), &tmpPlane[0]);
1220                break;
1221            }
1222            case OMX_COLOR_FormatYUV420Planar:
1223            {
1224                int32_t width = pDecShellContext->m_pVideoStreamhandler->m_videoWidth;
1225                int32_t height = pDecShellContext->m_pVideoStreamhandler->m_videoHeight;
1226                int32_t yPlaneSize = width * height;
1227                int32_t uvPlaneSize = width * height / 4;
1228                int32_t offsetSrc = 0;
1229
1230                M4OSA_MemAddr8 pTmpBuff = (M4OSA_MemAddr8)pDecoderBuffer->data() + pDecoderBuffer->range_offset();
1231
1232                M4OSA_memcpy((M4OSA_MemAddr8)tmpDecBuffer->pData, pTmpBuff, yPlaneSize);
1233
1234                offsetSrc += pDecShellContext->mGivenWidth * pDecShellContext->mGivenHeight;
1235                M4OSA_memcpy((M4OSA_MemAddr8)tmpDecBuffer->pData + yPlaneSize,
1236                    pTmpBuff + offsetSrc, uvPlaneSize);
1237
1238                offsetSrc += (pDecShellContext->mGivenWidth >> 1) * (pDecShellContext->mGivenHeight >> 1);
1239                M4OSA_memcpy((M4OSA_MemAddr8)tmpDecBuffer->pData + yPlaneSize + uvPlaneSize,
1240                                pTmpBuff + offsetSrc, uvPlaneSize);
1241
1242                break;
1243            }
1244            default:
1245                LOGV("VideoDecoder_decode: unexpected color format 0x%X",
1246                    pDecShellContext->decOuputColorFormat);
1247                return M4ERR_PARAMETER;
1248        }
1249
1250        tmpDecBuffer->buffCTS = pDecShellContext->m_lastDecodedCTS;
1251        tmpDecBuffer->state = VIDEOEDITOR_BUFFER_kFilled;
1252        tmpDecBuffer->size = pDecoderBuffer->size();
1253
1254        } else {
1255            LOGV("VideoEditorVideoDecoder_decode : empty buffer was returned");
1256        }
1257    }
1258    pDecShellContext->mNbOutputFrames++;
1259    if ( 0 > pDecShellContext->mFirstOutputCts ) {
1260        pDecShellContext->mFirstOutputCts = *pTime;
1261    }
1262    pDecShellContext->mLastOutputCts = *pTime;
1263
1264VIDEOEDITOR_VideoDecode_cleanUP:
1265    *pTime = pDecShellContext->m_lastDecodedCTS;
1266    if (pDecoderBuffer != NULL) {
1267        pDecoderBuffer->release();
1268        pDecoderBuffer = NULL;
1269    }
1270
1271    LOGV("VideoEditorVideoDecoder_decode: end with 0x%x", lerr);
1272    return lerr;
1273}
1274
1275M4OSA_ERR VideoEditorVideoDecoder_render(M4OSA_Context context,
1276        M4_MediaTime* pTime, M4VIFI_ImagePlane* pOutputPlane,
1277        M4OSA_Bool bForceRender) {
1278    M4OSA_ERR err = M4NO_ERROR;
1279    VideoEditorVideoDecoder_Context* pDecShellContext =
1280        (VideoEditorVideoDecoder_Context*) context;
1281    M4OSA_UInt32 lindex, i;
1282    M4OSA_UInt8* p_buf_src, *p_buf_dest;
1283    M4VIFI_ImagePlane tmpPlaneIn, tmpPlaneOut;
1284    VIDEOEDITOR_BUFFER_Buffer* pTmpVIDEOEDITORBuffer, *pRenderVIDEOEDITORBuffer
1285                                                                  = M4OSA_NULL;
1286    M4_MediaTime candidateTimeStamp = -1;
1287    M4OSA_Bool bFound = M4OSA_FALSE;
1288
1289    LOGV("VideoEditorVideoDecoder_render begin");
1290    // Input parameters check
1291    VIDEOEDITOR_CHECK(M4OSA_NULL != context, M4ERR_PARAMETER);
1292    VIDEOEDITOR_CHECK(M4OSA_NULL != pTime, M4ERR_PARAMETER);
1293    VIDEOEDITOR_CHECK(M4OSA_NULL != pOutputPlane, M4ERR_PARAMETER);
1294
1295    // The output buffer is already allocated, just copy the data
1296    if ( (*pTime <= pDecShellContext->m_lastRenderCts) &&
1297            (M4OSA_FALSE == bForceRender) ) {
1298        LOGV("VIDEOEDITOR_VIDEO_render Frame in the past");
1299        err = M4WAR_VIDEORENDERER_NO_NEW_FRAME;
1300        goto cleanUp;
1301    }
1302    LOGV("VideoDecoder_render: lastRendered time = %lf,requested render time = "
1303        "%lf", pDecShellContext->m_lastRenderCts, *pTime);
1304
1305    /**
1306     * Find the buffer appropriate for rendering.  */
1307    for (i=0; i < pDecShellContext->m_pDecBufferPool->NB; i++) {
1308        pTmpVIDEOEDITORBuffer = &pDecShellContext->m_pDecBufferPool\
1309            ->pNXPBuffer[i];
1310        if (pTmpVIDEOEDITORBuffer->state == VIDEOEDITOR_BUFFER_kFilled) {
1311            /** Free all those buffers older than last rendered frame. */
1312            if (pTmpVIDEOEDITORBuffer->buffCTS < pDecShellContext->\
1313                    m_lastRenderCts) {
1314                pTmpVIDEOEDITORBuffer->state = VIDEOEDITOR_BUFFER_kEmpty;
1315            }
1316
1317            /** Get the buffer with appropriate timestamp  */
1318            if ( (pTmpVIDEOEDITORBuffer->buffCTS >= pDecShellContext->\
1319                    m_lastRenderCts) &&
1320                (pTmpVIDEOEDITORBuffer->buffCTS <= *pTime) &&
1321                (pTmpVIDEOEDITORBuffer->buffCTS > candidateTimeStamp)) {
1322                bFound = M4OSA_TRUE;
1323                pRenderVIDEOEDITORBuffer = pTmpVIDEOEDITORBuffer;
1324                candidateTimeStamp = pTmpVIDEOEDITORBuffer->buffCTS;
1325                LOGV("VideoDecoder_render: found a buffer with timestamp = %lf",
1326                    candidateTimeStamp);
1327            }
1328        }
1329    }
1330    if (M4OSA_FALSE == bFound) {
1331        err = M4WAR_VIDEORENDERER_NO_NEW_FRAME;
1332        goto cleanUp;
1333    }
1334
1335    LOGV("VideoEditorVideoDecoder_render 3 ouput %d %d %d %d",
1336        pOutputPlane[0].u_width, pOutputPlane[0].u_height,
1337        pOutputPlane[0].u_topleft, pOutputPlane[0].u_stride);
1338
1339    pDecShellContext->m_lastRenderCts = candidateTimeStamp;
1340
1341    if( M4OSA_NULL != pDecShellContext->m_pFilter ) {
1342        // Filtering was requested
1343        M4VIFI_ImagePlane tmpPlane[3];
1344        // Prepare the output image for conversion
1345        tmpPlane[0].u_width   =
1346            pDecShellContext->m_pVideoStreamhandler->m_videoWidth;
1347        tmpPlane[0].u_height  =
1348            pDecShellContext->m_pVideoStreamhandler->m_videoHeight;
1349        tmpPlane[0].u_topleft = 0;
1350        tmpPlane[0].u_stride  = tmpPlane[0].u_width;
1351        tmpPlane[0].pac_data  = (M4VIFI_UInt8*)pRenderVIDEOEDITORBuffer->pData;
1352        tmpPlane[1].u_width   = tmpPlane[0].u_width/2;
1353        tmpPlane[1].u_height  = tmpPlane[0].u_height/2;
1354        tmpPlane[1].u_topleft = 0;
1355        tmpPlane[1].u_stride  = tmpPlane[0].u_stride/2;
1356        tmpPlane[1].pac_data  = tmpPlane[0].pac_data +
1357            (tmpPlane[0].u_stride * tmpPlane[0].u_height);
1358        tmpPlane[2].u_width   = tmpPlane[1].u_width;
1359        tmpPlane[2].u_height  = tmpPlane[1].u_height;
1360        tmpPlane[2].u_topleft = 0;
1361        tmpPlane[2].u_stride  = tmpPlane[1].u_stride;
1362        tmpPlane[2].pac_data  = tmpPlane[1].pac_data +
1363            (tmpPlane[1].u_stride * tmpPlane[1].u_height);
1364
1365        LOGV("VideoEditorVideoDecoder_render w = %d H = %d",
1366            tmpPlane[0].u_width,tmpPlane[0].u_height);
1367        pDecShellContext->m_pFilter(M4OSA_NULL, &tmpPlane[0], pOutputPlane);
1368    } else {
1369        // Just copy the YUV420P buffer
1370        M4OSA_MemAddr8 tempBuffPtr =
1371            (M4OSA_MemAddr8)pRenderVIDEOEDITORBuffer->pData;
1372        M4OSA_UInt32 tempWidth =
1373            pDecShellContext->m_pVideoStreamhandler->m_videoWidth;
1374        M4OSA_UInt32 tempHeight =
1375            pDecShellContext->m_pVideoStreamhandler->m_videoHeight;
1376
1377        M4OSA_memcpy((M4OSA_MemAddr8) pOutputPlane[0].pac_data, tempBuffPtr,
1378            tempWidth * tempHeight);
1379        tempBuffPtr += (tempWidth * tempHeight);
1380        M4OSA_memcpy((M4OSA_MemAddr8) pOutputPlane[1].pac_data, tempBuffPtr,
1381            (tempWidth/2) * (tempHeight/2));
1382        tempBuffPtr += ((tempWidth/2) * (tempHeight/2));
1383        M4OSA_memcpy((M4OSA_MemAddr8) pOutputPlane[2].pac_data, tempBuffPtr,
1384            (tempWidth/2) * (tempHeight/2));
1385    }
1386
1387    pDecShellContext->mNbRenderedFrames++;
1388    if ( 0 > pDecShellContext->mFirstRenderedCts ) {
1389        pDecShellContext->mFirstRenderedCts = *pTime;
1390    }
1391    pDecShellContext->mLastRenderedCts = *pTime;
1392
1393cleanUp:
1394    if( M4NO_ERROR == err ) {
1395        *pTime = pDecShellContext->m_lastRenderCts;
1396        LOGV("VideoEditorVideoDecoder_render no error");
1397    } else {
1398        LOGV("VideoEditorVideoDecoder_render ERROR 0x%X", err);
1399    }
1400    LOGV("VideoEditorVideoDecoder_render end");
1401    return err;
1402}
1403
1404M4OSA_ERR VideoEditorVideoDecoder_getInterface(M4DECODER_VideoType decoderType,
1405        M4DECODER_VideoType *pDecoderType, M4OSA_Context *pDecInterface) {
1406    M4DECODER_VideoInterface* pDecoderInterface = M4OSA_NULL;
1407
1408    pDecoderInterface = (M4DECODER_VideoInterface*)M4OSA_malloc(
1409        sizeof(M4DECODER_VideoInterface), M4DECODER_EXTERNAL,
1410        (M4OSA_Char*)"VideoEditorVideoDecoder_getInterface" );
1411    if (M4OSA_NULL == pDecoderInterface) {
1412        return M4ERR_ALLOC;
1413    }
1414
1415    *pDecoderType = decoderType;
1416
1417    pDecoderInterface->m_pFctCreate    = VideoEditorVideoDecoder_create;
1418    pDecoderInterface->m_pFctDestroy   = VideoEditorVideoDecoder_destroy;
1419    pDecoderInterface->m_pFctGetOption = VideoEditorVideoDecoder_getOption;
1420    pDecoderInterface->m_pFctSetOption = VideoEditorVideoDecoder_setOption;
1421    pDecoderInterface->m_pFctDecode    = VideoEditorVideoDecoder_decode;
1422    pDecoderInterface->m_pFctRender    = VideoEditorVideoDecoder_render;
1423
1424    *pDecInterface = (M4OSA_Context)pDecoderInterface;
1425    return M4NO_ERROR;
1426}
1427
1428extern "C" {
1429
1430M4OSA_ERR VideoEditorVideoDecoder_getInterface_MPEG4(
1431        M4DECODER_VideoType *pDecoderType, M4OSA_Context *pDecInterface) {
1432    return VideoEditorVideoDecoder_getInterface(M4DECODER_kVideoTypeMPEG4,
1433        pDecoderType, pDecInterface);
1434}
1435
1436M4OSA_ERR VideoEditorVideoDecoder_getInterface_H264(
1437        M4DECODER_VideoType *pDecoderType, M4OSA_Context *pDecInterface) {
1438    return VideoEditorVideoDecoder_getInterface(M4DECODER_kVideoTypeAVC,
1439        pDecoderType, pDecInterface);
1440
1441}
1442
1443}  // extern "C"
1444