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