VideoEditorVideoDecoder.cpp revision f8bd29c66308c820d579b3efb0942a53a277e2c5
1/*
2 * Copyright (C) 2011 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16/**
17*************************************************************************
18* @file   VideoEditorVideoDecoder.cpp
19* @brief  StageFright shell video decoder
20*************************************************************************
21*/
22#define LOG_NDEBUG 1
23#define LOG_TAG "VIDEOEDITOR_VIDEODECODER"
24/*******************
25 *     HEADERS     *
26 *******************/
27
28#include "VideoEditorVideoDecoder_internal.h"
29#include "VideoEditorUtils.h"
30#include "M4VD_Tools.h"
31
32#include <media/stagefright/MetaData.h>
33#include <media/stagefright/MediaDefs.h>
34#include <media/stagefright/MediaDebug.h>
35/********************
36 *   DEFINITIONS    *
37 ********************/
38#define MAX_DEC_BUFFERS 10
39
40/********************
41 *   SOURCE CLASS   *
42 ********************/
43using namespace android;
44static M4OSA_ERR copyBufferToQueue(
45    VideoEditorVideoDecoder_Context* pDecShellContext,
46    MediaBuffer* pDecodedBuffer);
47
48class VideoEditorVideoDecoderSource : public MediaSource {
49    public:
50
51        VideoEditorVideoDecoderSource(
52            const sp<MetaData> &format,
53            VIDEOEDITOR_CodecType codecType,
54            void *decoderShellContext);
55
56        virtual status_t start(MetaData *params = NULL);
57        virtual status_t stop();
58        virtual sp<MetaData> getFormat();
59        virtual status_t read(
60            MediaBuffer **buffer, const ReadOptions *options = NULL);
61
62    protected :
63        virtual ~VideoEditorVideoDecoderSource();
64
65    private:
66        sp<MetaData> mFormat;
67        MediaBuffer* mBuffer;
68        MediaBufferGroup* mGroup;
69        Mutex mLock;
70        VideoEditorVideoDecoder_Context* mpDecShellContext;
71        int32_t mMaxAUSize;
72        bool mStarted;
73        VIDEOEDITOR_CodecType mCodecType;
74
75        // Don't call me
76        VideoEditorVideoDecoderSource(const VideoEditorVideoDecoderSource &);
77        VideoEditorVideoDecoderSource &operator=(
78            const VideoEditorVideoDecoderSource &);
79};
80
81VideoEditorVideoDecoderSource::VideoEditorVideoDecoderSource(
82        const sp<MetaData> &format, VIDEOEDITOR_CodecType codecType,
83        void *decoderShellContext) :
84        mFormat(format),
85        mBuffer(NULL),
86        mGroup(NULL),
87        mStarted(false),
88        mCodecType(codecType) {
89    mpDecShellContext = (VideoEditorVideoDecoder_Context*) decoderShellContext;
90}
91
92VideoEditorVideoDecoderSource::~VideoEditorVideoDecoderSource() {
93    if (mStarted == true) {
94        stop();
95    }
96}
97
98status_t VideoEditorVideoDecoderSource::start(
99        MetaData *params) {
100
101    if (!mStarted) {
102        if (mFormat->findInt32(kKeyMaxInputSize, &mMaxAUSize) == false) {
103            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    /**
986     * StageFright graph building
987     */
988    decoderMetadata = new MetaData;
989    switch( pDecShellContext->mDecoderType ) {
990        case VIDEOEDITOR_kH263VideoDec:
991            decoderMetadata->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_H263);
992            break;
993        case VIDEOEDITOR_kMpeg4VideoDec:
994            decoderMetadata->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_MPEG4);
995            decoderMetadata->setData(kKeyESDS, kTypeESDS,
996                pStreamHandler->m_pESDSInfo,
997                pStreamHandler->m_ESDSInfoSize);
998            break;
999        case VIDEOEDITOR_kH264VideoDec:
1000            decoderMetadata->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_AVC);
1001            decoderMetadata->setData(kKeyAVCC, kTypeAVCC,
1002                pStreamHandler->m_pH264DecoderSpecificInfo,
1003                pStreamHandler->m_H264decoderSpecificInfoSize);
1004            break;
1005        default:
1006            VIDEOEDITOR_CHECK(!"VideoDecoder_create : incorrect stream type",
1007                M4ERR_PARAMETER);
1008            break;
1009    }
1010
1011    decoderMetadata->setInt32(kKeyMaxInputSize, pStreamHandler->m_maxAUSize);
1012    decoderMetadata->setInt32(kKeyWidth,
1013        pDecShellContext->m_pVideoStreamhandler->m_videoWidth);
1014    decoderMetadata->setInt32(kKeyHeight,
1015        pDecShellContext->m_pVideoStreamhandler->m_videoHeight);
1016
1017    // Create the decoder source
1018    pDecShellContext->mReaderSource = new VideoEditorVideoDecoderSource(
1019        decoderMetadata, pDecShellContext->mDecoderType,
1020        (void *)pDecShellContext);
1021    VIDEOEDITOR_CHECK(NULL != pDecShellContext->mReaderSource.get(),
1022        M4ERR_SF_DECODER_RSRC_FAIL);
1023
1024    // Connect to the OMX client
1025    status = pDecShellContext->mClient.connect();
1026    VIDEOEDITOR_CHECK(OK == status, M4ERR_SF_DECODER_RSRC_FAIL);
1027
1028    // Create the decoder
1029    pDecShellContext->mVideoDecoder = OMXCodec::Create(
1030        pDecShellContext->mClient.interface(),
1031        decoderMetadata, false, pDecShellContext->mReaderSource);
1032    VIDEOEDITOR_CHECK(NULL != pDecShellContext->mVideoDecoder.get(),
1033        M4ERR_SF_DECODER_RSRC_FAIL);
1034
1035
1036    // Get the output color format
1037    success = pDecShellContext->mVideoDecoder->getFormat()->findInt32(
1038        kKeyColorFormat, &colorFormat);
1039    VIDEOEDITOR_CHECK(TRUE == success, M4ERR_PARAMETER);
1040    pDecShellContext->decOuputColorFormat = (OMX_COLOR_FORMATTYPE)colorFormat;
1041
1042    pDecShellContext->mVideoDecoder->getFormat()->setInt32(kKeyWidth,
1043        pDecShellContext->m_pVideoStreamhandler->m_videoWidth);
1044    pDecShellContext->mVideoDecoder->getFormat()->setInt32(kKeyHeight,
1045        pDecShellContext->m_pVideoStreamhandler->m_videoHeight);
1046
1047    // Get the color converter
1048    pDecShellContext->mI420ColorConverter = new I420ColorConverter;
1049    if (pDecShellContext->mI420ColorConverter->isLoaded()) {
1050        decoderOutput = pDecShellContext->mI420ColorConverter->getDecoderOutputFormat();
1051    }
1052
1053    if (decoderOutput == OMX_COLOR_FormatYUV420Planar) {
1054        delete pDecShellContext->mI420ColorConverter;
1055        pDecShellContext->mI420ColorConverter = NULL;
1056    }
1057
1058    ALOGI("decoder output format = 0x%X\n", decoderOutput);
1059
1060    // Configure the buffer pool from the metadata
1061    err = VideoEditorVideoDecoder_configureFromMetadata(pDecShellContext,
1062        pDecShellContext->mVideoDecoder->getFormat().get());
1063    VIDEOEDITOR_CHECK(M4NO_ERROR == err, err);
1064
1065    // Start the graph
1066    status = pDecShellContext->mVideoDecoder->start();
1067    VIDEOEDITOR_CHECK(OK == status, M4ERR_SF_DECODER_RSRC_FAIL);
1068
1069    *pContext = (M4OSA_Context)pDecShellContext;
1070
1071cleanUp:
1072    if( M4NO_ERROR == err ) {
1073        ALOGV("VideoEditorVideoDecoder_create no error");
1074    } else {
1075        VideoEditorVideoDecoder_destroy(pDecShellContext);
1076        *pContext = M4OSA_NULL;
1077        ALOGV("VideoEditorVideoDecoder_create ERROR 0x%X", err);
1078    }
1079    ALOGV("VideoEditorVideoDecoder_create : DONE");
1080    return err;
1081}
1082
1083M4OSA_ERR VideoEditorVideoSoftwareDecoder_create(M4OSA_Context *pContext,
1084        M4_StreamHandler *pStreamHandler,
1085        M4READER_GlobalInterface *pReaderGlobalInterface,
1086        M4READER_DataInterface *pReaderDataInterface,
1087        M4_AccessUnit *pAccessUnit, M4OSA_Void *pUserData) {
1088    M4OSA_ERR err = M4NO_ERROR;
1089    VideoEditorVideoDecoder_Context* pDecShellContext = M4OSA_NULL;
1090    status_t status = OK;
1091    bool success = TRUE;
1092    int32_t colorFormat = 0;
1093    M4OSA_UInt32 size = 0;
1094    sp<MetaData> decoderMetadata = NULL;
1095
1096    ALOGV("VideoEditorVideoDecoder_create begin");
1097    // Input parameters check
1098    VIDEOEDITOR_CHECK(M4OSA_NULL != pContext,             M4ERR_PARAMETER);
1099    VIDEOEDITOR_CHECK(M4OSA_NULL != pStreamHandler,       M4ERR_PARAMETER);
1100    VIDEOEDITOR_CHECK(M4OSA_NULL != pReaderDataInterface, M4ERR_PARAMETER);
1101
1102    // Context allocation & initialization
1103    SAFE_MALLOC(pDecShellContext, VideoEditorVideoDecoder_Context, 1,
1104        "VideoEditorVideoDecoder");
1105    pDecShellContext->m_pVideoStreamhandler =
1106        (M4_VideoStreamHandler*)pStreamHandler;
1107    pDecShellContext->m_pNextAccessUnitToDecode = pAccessUnit;
1108    pDecShellContext->m_pReaderGlobal = pReaderGlobalInterface;
1109    pDecShellContext->m_pReader = pReaderDataInterface;
1110    pDecShellContext->m_lastDecodedCTS = -1;
1111    pDecShellContext->m_lastRenderCts = -1;
1112    switch( pStreamHandler->m_streamType ) {
1113        case M4DA_StreamTypeVideoH263:
1114            pDecShellContext->mDecoderType = VIDEOEDITOR_kH263VideoDec;
1115            break;
1116        case M4DA_StreamTypeVideoMpeg4:
1117            pDecShellContext->mDecoderType = VIDEOEDITOR_kMpeg4VideoDec;
1118            // Parse the VOL header
1119            err = VideoEditorVideoDecoder_internalParseVideoDSI(
1120                (M4OSA_UInt8*)pDecShellContext->m_pVideoStreamhandler->\
1121                    m_basicProperties.m_pDecoderSpecificInfo,
1122                pDecShellContext->m_pVideoStreamhandler->\
1123                    m_basicProperties.m_decoderSpecificInfoSize,
1124                &pDecShellContext->m_Dci, &pDecShellContext->m_VideoSize);
1125            VIDEOEDITOR_CHECK(M4NO_ERROR == err, err);
1126            break;
1127        case M4DA_StreamTypeVideoMpeg4Avc:
1128            pDecShellContext->mDecoderType = VIDEOEDITOR_kH264VideoDec;
1129            break;
1130        default:
1131            VIDEOEDITOR_CHECK(!"VideoDecoder_create : incorrect stream type",
1132                M4ERR_PARAMETER);
1133            break;
1134    }
1135
1136    pDecShellContext->mNbInputFrames     = 0;
1137    pDecShellContext->mFirstInputCts     = -1.0;
1138    pDecShellContext->mLastInputCts      = -1.0;
1139    pDecShellContext->mNbRenderedFrames  = 0;
1140    pDecShellContext->mFirstRenderedCts  = -1.0;
1141    pDecShellContext->mLastRenderedCts   = -1.0;
1142    pDecShellContext->mNbOutputFrames    = 0;
1143    pDecShellContext->mFirstOutputCts    = -1;
1144    pDecShellContext->mLastOutputCts     = -1;
1145    pDecShellContext->m_pDecBufferPool   = M4OSA_NULL;
1146
1147    /**
1148     * StageFright graph building
1149     */
1150    decoderMetadata = new MetaData;
1151    switch( pDecShellContext->mDecoderType ) {
1152        case VIDEOEDITOR_kH263VideoDec:
1153            decoderMetadata->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_H263);
1154            break;
1155        case VIDEOEDITOR_kMpeg4VideoDec:
1156            decoderMetadata->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_MPEG4);
1157            decoderMetadata->setData(kKeyESDS, kTypeESDS,
1158                pStreamHandler->m_pESDSInfo,
1159                pStreamHandler->m_ESDSInfoSize);
1160            break;
1161        case VIDEOEDITOR_kH264VideoDec:
1162            decoderMetadata->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_AVC);
1163            decoderMetadata->setData(kKeyAVCC, kTypeAVCC,
1164                pStreamHandler->m_pH264DecoderSpecificInfo,
1165                pStreamHandler->m_H264decoderSpecificInfoSize);
1166            break;
1167        default:
1168            VIDEOEDITOR_CHECK(!"VideoDecoder_create : incorrect stream type",
1169                M4ERR_PARAMETER);
1170            break;
1171    }
1172
1173    decoderMetadata->setInt32(kKeyMaxInputSize, pStreamHandler->m_maxAUSize);
1174    decoderMetadata->setInt32(kKeyWidth,
1175        pDecShellContext->m_pVideoStreamhandler->m_videoWidth);
1176    decoderMetadata->setInt32(kKeyHeight,
1177        pDecShellContext->m_pVideoStreamhandler->m_videoHeight);
1178
1179    // Create the decoder source
1180    pDecShellContext->mReaderSource = new VideoEditorVideoDecoderSource(
1181        decoderMetadata, pDecShellContext->mDecoderType,
1182        (void *)pDecShellContext);
1183    VIDEOEDITOR_CHECK(NULL != pDecShellContext->mReaderSource.get(),
1184        M4ERR_SF_DECODER_RSRC_FAIL);
1185
1186    // Connect to the OMX client
1187    status = pDecShellContext->mClient.connect();
1188    VIDEOEDITOR_CHECK(OK == status, M4ERR_SF_DECODER_RSRC_FAIL);
1189
1190     ALOGI("Using software codecs only");
1191    // Create the decoder
1192    pDecShellContext->mVideoDecoder = OMXCodec::Create(
1193        pDecShellContext->mClient.interface(),
1194        decoderMetadata, false, pDecShellContext->mReaderSource,NULL,OMXCodec::kSoftwareCodecsOnly);
1195    VIDEOEDITOR_CHECK(NULL != pDecShellContext->mVideoDecoder.get(),
1196        M4ERR_SF_DECODER_RSRC_FAIL);
1197
1198    // Get the output color format
1199    success = pDecShellContext->mVideoDecoder->getFormat()->findInt32(
1200        kKeyColorFormat, &colorFormat);
1201    VIDEOEDITOR_CHECK(TRUE == success, M4ERR_PARAMETER);
1202    pDecShellContext->decOuputColorFormat = (OMX_COLOR_FORMATTYPE)colorFormat;
1203
1204    pDecShellContext->mVideoDecoder->getFormat()->setInt32(kKeyWidth,
1205        pDecShellContext->m_pVideoStreamhandler->m_videoWidth);
1206    pDecShellContext->mVideoDecoder->getFormat()->setInt32(kKeyHeight,
1207        pDecShellContext->m_pVideoStreamhandler->m_videoHeight);
1208
1209    // Configure the buffer pool from the metadata
1210    err = VideoEditorVideoDecoder_configureFromMetadata(pDecShellContext,
1211        pDecShellContext->mVideoDecoder->getFormat().get());
1212    VIDEOEDITOR_CHECK(M4NO_ERROR == err, err);
1213
1214    // Start the graph
1215    status = pDecShellContext->mVideoDecoder->start();
1216    VIDEOEDITOR_CHECK(OK == status, M4ERR_SF_DECODER_RSRC_FAIL);
1217
1218    *pContext = (M4OSA_Context)pDecShellContext;
1219
1220cleanUp:
1221    if( M4NO_ERROR == err ) {
1222        ALOGV("VideoEditorVideoDecoder_create no error");
1223    } else {
1224        VideoEditorVideoDecoder_destroy(pDecShellContext);
1225        *pContext = M4OSA_NULL;
1226        ALOGV("VideoEditorVideoDecoder_create ERROR 0x%X", err);
1227    }
1228    ALOGV("VideoEditorVideoDecoder_create : DONE");
1229    return err;
1230}
1231
1232
1233M4OSA_ERR VideoEditorVideoDecoder_getOption(M4OSA_Context context,
1234        M4OSA_OptionID optionId, M4OSA_DataOption pValue) {
1235    M4OSA_ERR lerr = M4NO_ERROR;
1236    VideoEditorVideoDecoder_Context* pDecShellContext =
1237        (VideoEditorVideoDecoder_Context*) context;
1238    M4_VersionInfo* pVersionInfo;
1239    M4DECODER_VideoSize* pVideoSize;
1240    M4OSA_UInt32* pNextFrameCts;
1241    M4OSA_UInt32 *plastDecodedFrameCts;
1242    M4DECODER_AVCProfileLevel* profile;
1243    M4DECODER_MPEG4_DecoderConfigInfo* pDecConfInfo;
1244
1245    ALOGV("VideoEditorVideoDecoder_getOption begin");
1246
1247    switch (optionId) {
1248        case M4DECODER_kOptionID_AVCLastDecodedFrameCTS:
1249             plastDecodedFrameCts = (M4OSA_UInt32 *) pValue;
1250             *plastDecodedFrameCts = pDecShellContext->m_lastDecodedCTS;
1251             break;
1252
1253        case M4DECODER_kOptionID_Version:
1254            pVersionInfo = (M4_VersionInfo*)pValue;
1255
1256            pVersionInfo->m_major = VIDEOEDITOR_VIDEC_SHELL_VER_MAJOR;
1257            pVersionInfo->m_minor= VIDEOEDITOR_VIDEC_SHELL_VER_MINOR;
1258            pVersionInfo->m_revision = VIDEOEDITOR_VIDEC_SHELL_VER_REVISION;
1259            pVersionInfo->m_structSize=sizeof(M4_VersionInfo);
1260            break;
1261
1262        case M4DECODER_kOptionID_VideoSize:
1263            /** Only VPS uses this Option ID. */
1264            pVideoSize = (M4DECODER_VideoSize*)pValue;
1265            pDecShellContext->mVideoDecoder->getFormat()->findInt32(kKeyWidth,
1266                (int32_t*)(&pVideoSize->m_uiWidth));
1267            pDecShellContext->mVideoDecoder->getFormat()->findInt32(kKeyHeight,
1268                (int32_t*)(&pVideoSize->m_uiHeight));
1269            ALOGV("VideoEditorVideoDecoder_getOption : W=%d H=%d",
1270                pVideoSize->m_uiWidth, pVideoSize->m_uiHeight);
1271            break;
1272
1273        case M4DECODER_kOptionID_NextRenderedFrameCTS:
1274            /** How to get this information. SF decoder does not provide this. *
1275            ** Let us provide last decoded frame CTS as of now. *
1276            ** Only VPS uses this Option ID. */
1277            pNextFrameCts = (M4OSA_UInt32 *)pValue;
1278            *pNextFrameCts = pDecShellContext->m_lastDecodedCTS;
1279            break;
1280        case M4DECODER_MPEG4_kOptionID_DecoderConfigInfo:
1281            if(pDecShellContext->mDecoderType == VIDEOEDITOR_kMpeg4VideoDec) {
1282                (*(M4DECODER_MPEG4_DecoderConfigInfo*)pValue) =
1283                    pDecShellContext->m_Dci;
1284            }
1285            break;
1286        default:
1287            lerr = M4ERR_BAD_OPTION_ID;
1288            break;
1289
1290    }
1291
1292    ALOGV("VideoEditorVideoDecoder_getOption: end with err = 0x%x", lerr);
1293    return lerr;
1294}
1295
1296M4OSA_ERR VideoEditorVideoDecoder_setOption(M4OSA_Context context,
1297        M4OSA_OptionID optionId, M4OSA_DataOption pValue) {
1298    M4OSA_ERR lerr = M4NO_ERROR;
1299    VideoEditorVideoDecoder_Context *pDecShellContext =
1300        (VideoEditorVideoDecoder_Context*) context;
1301
1302    ALOGV("VideoEditorVideoDecoder_setOption begin");
1303
1304    switch (optionId) {
1305        case M4DECODER_kOptionID_OutputFilter: {
1306                M4DECODER_OutputFilter* pOutputFilter =
1307                    (M4DECODER_OutputFilter*) pValue;
1308                pDecShellContext->m_pFilter =
1309                    (M4VIFI_PlanConverterFunctionType*)pOutputFilter->\
1310                    m_pFilterFunction;
1311                pDecShellContext->m_pFilterUserData =
1312                    pOutputFilter->m_pFilterUserData;
1313            }
1314            break;
1315        case M4DECODER_kOptionID_DeblockingFilter:
1316            break;
1317        default:
1318            lerr = M4ERR_BAD_CONTEXT;
1319            break;
1320    }
1321
1322    ALOGV("VideoEditorVideoDecoder_setOption: end with err = 0x%x", lerr);
1323    return lerr;
1324}
1325
1326M4OSA_ERR VideoEditorVideoDecoder_decode(M4OSA_Context context,
1327        M4_MediaTime* pTime, M4OSA_Bool bJump, M4OSA_UInt32 tolerance) {
1328    M4OSA_ERR lerr = M4NO_ERROR;
1329    VideoEditorVideoDecoder_Context* pDecShellContext =
1330        (VideoEditorVideoDecoder_Context*) context;
1331    int64_t lFrameTime;
1332    MediaBuffer* pDecoderBuffer = NULL;
1333    MediaBuffer* pNextBuffer = NULL;
1334    status_t errStatus;
1335    bool needSeek = bJump;
1336
1337    ALOGV("VideoEditorVideoDecoder_decode begin");
1338
1339    if( M4OSA_TRUE == pDecShellContext->mReachedEOS ) {
1340        // Do not call read(), it could lead to a freeze
1341        ALOGV("VideoEditorVideoDecoder_decode : EOS already reached");
1342        lerr = M4WAR_NO_MORE_AU;
1343        goto VIDEOEDITOR_VideoDecode_cleanUP;
1344    }
1345    if(pDecShellContext->m_lastDecodedCTS >= *pTime) {
1346        ALOGV("VideoDecoder_decode: Already decoded up to this time CTS = %lf.",
1347            pDecShellContext->m_lastDecodedCTS);
1348        goto VIDEOEDITOR_VideoDecode_cleanUP;
1349    }
1350    if(M4OSA_TRUE == bJump) {
1351        ALOGV("VideoEditorVideoDecoder_decode: Jump called");
1352        pDecShellContext->m_lastDecodedCTS = -1;
1353        pDecShellContext->m_lastRenderCts = -1;
1354    }
1355
1356    pDecShellContext->mNbInputFrames++;
1357    if (0 > pDecShellContext->mFirstInputCts){
1358        pDecShellContext->mFirstInputCts = *pTime;
1359    }
1360    pDecShellContext->mLastInputCts = *pTime;
1361
1362    while (pDecoderBuffer == NULL || pDecShellContext->m_lastDecodedCTS + tolerance < *pTime) {
1363        ALOGV("VideoEditorVideoDecoder_decode, frameCTS = %lf, DecodeUpTo = %lf",
1364            pDecShellContext->m_lastDecodedCTS, *pTime);
1365
1366        // Read the buffer from the stagefright decoder
1367        if (needSeek) {
1368            MediaSource::ReadOptions options;
1369            int64_t time_us = *pTime * 1000;
1370            options.setSeekTo(time_us, MediaSource::ReadOptions::SEEK_PREVIOUS_SYNC);
1371            errStatus = pDecShellContext->mVideoDecoder->read(&pNextBuffer, &options);
1372            needSeek = false;
1373        } else {
1374            errStatus = pDecShellContext->mVideoDecoder->read(&pNextBuffer);
1375        }
1376
1377        // Handle EOS and format change
1378        if (errStatus == ERROR_END_OF_STREAM) {
1379            ALOGV("End of stream reached, returning M4WAR_NO_MORE_AU ");
1380            pDecShellContext->mReachedEOS = M4OSA_TRUE;
1381            lerr = M4WAR_NO_MORE_AU;
1382            // If we decoded a buffer before EOS, we still need to put it
1383            // into the queue.
1384            if (pDecoderBuffer && bJump) {
1385                copyBufferToQueue(pDecShellContext, pDecoderBuffer);
1386            }
1387            goto VIDEOEDITOR_VideoDecode_cleanUP;
1388        } else if (INFO_FORMAT_CHANGED == errStatus) {
1389            ALOGV("VideoDecoder_decode : source returns INFO_FORMAT_CHANGED");
1390            lerr = VideoEditorVideoDecoder_configureFromMetadata(
1391                pDecShellContext,
1392                pDecShellContext->mVideoDecoder->getFormat().get());
1393            if( M4NO_ERROR != lerr ) {
1394                ALOGV("!!! VideoEditorVideoDecoder_decode ERROR : "
1395                    "VideoDecoder_configureFromMetadata returns 0x%X", lerr);
1396                break;
1397            }
1398            continue;
1399        } else if (errStatus != OK) {
1400            ALOGE("VideoEditorVideoDecoder_decode ERROR:0x%x(%d)",
1401                errStatus,errStatus);
1402            lerr = errStatus;
1403            goto VIDEOEDITOR_VideoDecode_cleanUP;
1404        }
1405
1406        // The OMXCodec client should expect to receive 0-length buffers
1407        // and drop the 0-length buffers.
1408        if (pNextBuffer->range_length() == 0) {
1409            pNextBuffer->release();
1410            continue;
1411        }
1412
1413        // Now we have a good next buffer, release the previous one.
1414        if (pDecoderBuffer != NULL) {
1415            pDecoderBuffer->release();
1416            pDecoderBuffer = NULL;
1417        }
1418        pDecoderBuffer = pNextBuffer;
1419
1420        // Record the timestamp of last decoded buffer
1421        pDecoderBuffer->meta_data()->findInt64(kKeyTime, &lFrameTime);
1422        pDecShellContext->m_lastDecodedCTS = (M4_MediaTime)(lFrameTime/1000);
1423        ALOGV("VideoEditorVideoDecoder_decode,decoded frametime = %lf,size = %d",
1424            (M4_MediaTime)lFrameTime, pDecoderBuffer->size() );
1425
1426        // If bJump is false, we need to save every decoded buffer
1427        if (!bJump) {
1428            lerr = copyBufferToQueue(pDecShellContext, pDecoderBuffer);
1429            if (lerr != M4NO_ERROR) {
1430                goto VIDEOEDITOR_VideoDecode_cleanUP;
1431            }
1432        }
1433    }
1434
1435    // If bJump is true, we only need to copy the last buffer
1436    if (bJump) {
1437        lerr = copyBufferToQueue(pDecShellContext, pDecoderBuffer);
1438        if (lerr != M4NO_ERROR) {
1439            goto VIDEOEDITOR_VideoDecode_cleanUP;
1440        }
1441    }
1442
1443    pDecShellContext->mNbOutputFrames++;
1444    if ( 0 > pDecShellContext->mFirstOutputCts ) {
1445        pDecShellContext->mFirstOutputCts = *pTime;
1446    }
1447    pDecShellContext->mLastOutputCts = *pTime;
1448
1449VIDEOEDITOR_VideoDecode_cleanUP:
1450    *pTime = pDecShellContext->m_lastDecodedCTS;
1451    if (pDecoderBuffer != NULL) {
1452        pDecoderBuffer->release();
1453        pDecoderBuffer = NULL;
1454    }
1455
1456    ALOGV("VideoEditorVideoDecoder_decode: end with 0x%x", lerr);
1457    return lerr;
1458}
1459
1460static M4OSA_ERR copyBufferToQueue(
1461    VideoEditorVideoDecoder_Context* pDecShellContext,
1462    MediaBuffer* pDecoderBuffer) {
1463
1464    M4OSA_ERR lerr = M4NO_ERROR;
1465    VIDEOEDITOR_BUFFER_Buffer* tmpDecBuffer;
1466
1467    // Get a buffer from the queue
1468    lerr = VIDEOEDITOR_BUFFER_getBuffer(pDecShellContext->m_pDecBufferPool,
1469        VIDEOEDITOR_BUFFER_kEmpty, &tmpDecBuffer);
1470    if (lerr == (M4OSA_UInt32)M4ERR_NO_BUFFER_AVAILABLE) {
1471        lerr = VIDEOEDITOR_BUFFER_getOldestBuffer(
1472            pDecShellContext->m_pDecBufferPool,
1473            VIDEOEDITOR_BUFFER_kFilled, &tmpDecBuffer);
1474        tmpDecBuffer->state = VIDEOEDITOR_BUFFER_kEmpty;
1475        lerr = M4NO_ERROR;
1476    }
1477
1478    if (lerr != M4NO_ERROR) return lerr;
1479
1480    // Color convert or copy from the given MediaBuffer to our buffer
1481    if (pDecShellContext->mI420ColorConverter) {
1482        if (pDecShellContext->mI420ColorConverter->convertDecoderOutputToI420(
1483            (uint8_t *)pDecoderBuffer->data(),// ?? + pDecoderBuffer->range_offset(),   // decoderBits
1484            pDecShellContext->mGivenWidth,  // decoderWidth
1485            pDecShellContext->mGivenHeight,  // decoderHeight
1486            pDecShellContext->mCropRect,  // decoderRect
1487            tmpDecBuffer->pData /* dstBits */) < 0) {
1488            ALOGE("convertDecoderOutputToI420 failed");
1489            lerr = M4ERR_NOT_IMPLEMENTED;
1490        }
1491    } else if (pDecShellContext->decOuputColorFormat == OMX_COLOR_FormatYUV420Planar) {
1492        int32_t width = pDecShellContext->m_pVideoStreamhandler->m_videoWidth;
1493        int32_t height = pDecShellContext->m_pVideoStreamhandler->m_videoHeight;
1494        int32_t yPlaneSize = width * height;
1495        int32_t uvPlaneSize = width * height / 4;
1496        int32_t offsetSrc = 0;
1497
1498        if (( width == pDecShellContext->mGivenWidth )  &&
1499            ( height == pDecShellContext->mGivenHeight ))
1500        {
1501            M4OSA_MemAddr8 pTmpBuff = (M4OSA_MemAddr8)pDecoderBuffer->data() + pDecoderBuffer->range_offset();
1502
1503            memcpy((void *)tmpDecBuffer->pData, (void *)pTmpBuff, yPlaneSize);
1504
1505            offsetSrc += pDecShellContext->mGivenWidth * pDecShellContext->mGivenHeight;
1506            memcpy((void *)((M4OSA_MemAddr8)tmpDecBuffer->pData + yPlaneSize),
1507                (void *)(pTmpBuff + offsetSrc), uvPlaneSize);
1508
1509            offsetSrc += (pDecShellContext->mGivenWidth >> 1) * (pDecShellContext->mGivenHeight >> 1);
1510            memcpy((void *)((M4OSA_MemAddr8)tmpDecBuffer->pData + yPlaneSize + uvPlaneSize),
1511                (void *)(pTmpBuff + offsetSrc), uvPlaneSize);
1512        }
1513        else
1514        {
1515            M4OSA_MemAddr8 pTmpBuff = (M4OSA_MemAddr8)pDecoderBuffer->data() + pDecoderBuffer->range_offset();
1516            M4OSA_MemAddr8 pTmpBuffDst = (M4OSA_MemAddr8)tmpDecBuffer->pData;
1517            int32_t index;
1518
1519            for ( index = 0; index < height; index++)
1520            {
1521                memcpy((void *)pTmpBuffDst, (void *)pTmpBuff, width);
1522                pTmpBuffDst += width;
1523                pTmpBuff += pDecShellContext->mGivenWidth;
1524            }
1525
1526            pTmpBuff += (pDecShellContext->mGivenWidth * ( pDecShellContext->mGivenHeight - height));
1527            for ( index = 0; index < height >> 1; index++)
1528            {
1529                memcpy((void *)pTmpBuffDst, (void *)pTmpBuff, width >> 1);
1530                pTmpBuffDst += width >> 1;
1531                pTmpBuff += pDecShellContext->mGivenWidth >> 1;
1532            }
1533
1534            pTmpBuff += ((pDecShellContext->mGivenWidth * (pDecShellContext->mGivenHeight - height)) / 4);
1535            for ( index = 0; index < height >> 1; index++)
1536            {
1537                memcpy((void *)pTmpBuffDst, (void *)pTmpBuff, width >> 1);
1538                pTmpBuffDst += width >> 1;
1539                pTmpBuff += pDecShellContext->mGivenWidth >> 1;
1540            }
1541        }
1542    } else {
1543        ALOGE("VideoDecoder_decode: unexpected color format 0x%X",
1544            pDecShellContext->decOuputColorFormat);
1545        lerr = M4ERR_PARAMETER;
1546    }
1547
1548    tmpDecBuffer->buffCTS = pDecShellContext->m_lastDecodedCTS;
1549    tmpDecBuffer->state = VIDEOEDITOR_BUFFER_kFilled;
1550    tmpDecBuffer->size = pDecoderBuffer->size();
1551
1552    return lerr;
1553}
1554
1555M4OSA_ERR VideoEditorVideoDecoder_render(M4OSA_Context context,
1556        M4_MediaTime* pTime, M4VIFI_ImagePlane* pOutputPlane,
1557        M4OSA_Bool bForceRender) {
1558    M4OSA_ERR err = M4NO_ERROR;
1559    VideoEditorVideoDecoder_Context* pDecShellContext =
1560        (VideoEditorVideoDecoder_Context*) context;
1561    M4OSA_UInt32 lindex, i;
1562    M4OSA_UInt8* p_buf_src, *p_buf_dest;
1563    M4VIFI_ImagePlane tmpPlaneIn, tmpPlaneOut;
1564    VIDEOEDITOR_BUFFER_Buffer* pTmpVIDEOEDITORBuffer, *pRenderVIDEOEDITORBuffer
1565                                                                  = M4OSA_NULL;
1566    M4_MediaTime candidateTimeStamp = -1;
1567    M4OSA_Bool bFound = M4OSA_FALSE;
1568
1569    ALOGV("VideoEditorVideoDecoder_render begin");
1570    // Input parameters check
1571    VIDEOEDITOR_CHECK(M4OSA_NULL != context, M4ERR_PARAMETER);
1572    VIDEOEDITOR_CHECK(M4OSA_NULL != pTime, M4ERR_PARAMETER);
1573    VIDEOEDITOR_CHECK(M4OSA_NULL != pOutputPlane, M4ERR_PARAMETER);
1574
1575    // The output buffer is already allocated, just copy the data
1576    if ( (*pTime <= pDecShellContext->m_lastRenderCts) &&
1577            (M4OSA_FALSE == bForceRender) ) {
1578        ALOGV("VIDEOEDITOR_VIDEO_render Frame in the past");
1579        err = M4WAR_VIDEORENDERER_NO_NEW_FRAME;
1580        goto cleanUp;
1581    }
1582    ALOGV("VideoDecoder_render: lastRendered time = %lf,requested render time = "
1583        "%lf", pDecShellContext->m_lastRenderCts, *pTime);
1584
1585    /**
1586     * Find the buffer appropriate for rendering.  */
1587    for (i=0; i < pDecShellContext->m_pDecBufferPool->NB; i++) {
1588        pTmpVIDEOEDITORBuffer = &pDecShellContext->m_pDecBufferPool\
1589            ->pNXPBuffer[i];
1590        if (pTmpVIDEOEDITORBuffer->state == VIDEOEDITOR_BUFFER_kFilled) {
1591            /** Free all those buffers older than last rendered frame. */
1592            if (pTmpVIDEOEDITORBuffer->buffCTS < pDecShellContext->\
1593                    m_lastRenderCts) {
1594                pTmpVIDEOEDITORBuffer->state = VIDEOEDITOR_BUFFER_kEmpty;
1595            }
1596
1597            /** Get the buffer with appropriate timestamp  */
1598            if ( (pTmpVIDEOEDITORBuffer->buffCTS >= pDecShellContext->\
1599                    m_lastRenderCts) &&
1600                (pTmpVIDEOEDITORBuffer->buffCTS <= *pTime) &&
1601                (pTmpVIDEOEDITORBuffer->buffCTS > candidateTimeStamp)) {
1602                bFound = M4OSA_TRUE;
1603                pRenderVIDEOEDITORBuffer = pTmpVIDEOEDITORBuffer;
1604                candidateTimeStamp = pTmpVIDEOEDITORBuffer->buffCTS;
1605                ALOGV("VideoDecoder_render: found a buffer with timestamp = %lf",
1606                    candidateTimeStamp);
1607            }
1608        }
1609    }
1610    if (M4OSA_FALSE == bFound) {
1611        err = M4WAR_VIDEORENDERER_NO_NEW_FRAME;
1612        goto cleanUp;
1613    }
1614
1615    ALOGV("VideoEditorVideoDecoder_render 3 ouput %d %d %d %d",
1616        pOutputPlane[0].u_width, pOutputPlane[0].u_height,
1617        pOutputPlane[0].u_topleft, pOutputPlane[0].u_stride);
1618
1619    pDecShellContext->m_lastRenderCts = candidateTimeStamp;
1620
1621    if( M4OSA_NULL != pDecShellContext->m_pFilter ) {
1622        // Filtering was requested
1623        M4VIFI_ImagePlane tmpPlane[3];
1624        // Prepare the output image for conversion
1625        tmpPlane[0].u_width   =
1626            pDecShellContext->m_pVideoStreamhandler->m_videoWidth;
1627        tmpPlane[0].u_height  =
1628            pDecShellContext->m_pVideoStreamhandler->m_videoHeight;
1629        tmpPlane[0].u_topleft = 0;
1630        tmpPlane[0].u_stride  = tmpPlane[0].u_width;
1631        tmpPlane[0].pac_data  = (M4VIFI_UInt8*)pRenderVIDEOEDITORBuffer->pData;
1632        tmpPlane[1].u_width   = tmpPlane[0].u_width/2;
1633        tmpPlane[1].u_height  = tmpPlane[0].u_height/2;
1634        tmpPlane[1].u_topleft = 0;
1635        tmpPlane[1].u_stride  = tmpPlane[0].u_stride/2;
1636        tmpPlane[1].pac_data  = tmpPlane[0].pac_data +
1637            (tmpPlane[0].u_stride * tmpPlane[0].u_height);
1638        tmpPlane[2].u_width   = tmpPlane[1].u_width;
1639        tmpPlane[2].u_height  = tmpPlane[1].u_height;
1640        tmpPlane[2].u_topleft = 0;
1641        tmpPlane[2].u_stride  = tmpPlane[1].u_stride;
1642        tmpPlane[2].pac_data  = tmpPlane[1].pac_data +
1643            (tmpPlane[1].u_stride * tmpPlane[1].u_height);
1644
1645        ALOGV("VideoEditorVideoDecoder_render w = %d H = %d",
1646            tmpPlane[0].u_width,tmpPlane[0].u_height);
1647        pDecShellContext->m_pFilter(M4OSA_NULL, &tmpPlane[0], pOutputPlane);
1648    } else {
1649        // Just copy the YUV420P buffer
1650        M4OSA_MemAddr8 tempBuffPtr =
1651            (M4OSA_MemAddr8)pRenderVIDEOEDITORBuffer->pData;
1652        M4OSA_UInt32 tempWidth =
1653            pDecShellContext->m_pVideoStreamhandler->m_videoWidth;
1654        M4OSA_UInt32 tempHeight =
1655            pDecShellContext->m_pVideoStreamhandler->m_videoHeight;
1656
1657        memcpy((void *) pOutputPlane[0].pac_data, (void *)tempBuffPtr,
1658            tempWidth * tempHeight);
1659        tempBuffPtr += (tempWidth * tempHeight);
1660        memcpy((void *) pOutputPlane[1].pac_data, (void *)tempBuffPtr,
1661            (tempWidth/2) * (tempHeight/2));
1662        tempBuffPtr += ((tempWidth/2) * (tempHeight/2));
1663        memcpy((void *) pOutputPlane[2].pac_data, (void *)tempBuffPtr,
1664            (tempWidth/2) * (tempHeight/2));
1665    }
1666
1667    pDecShellContext->mNbRenderedFrames++;
1668    if ( 0 > pDecShellContext->mFirstRenderedCts ) {
1669        pDecShellContext->mFirstRenderedCts = *pTime;
1670    }
1671    pDecShellContext->mLastRenderedCts = *pTime;
1672
1673cleanUp:
1674    if( M4NO_ERROR == err ) {
1675        *pTime = pDecShellContext->m_lastRenderCts;
1676        ALOGV("VideoEditorVideoDecoder_render no error");
1677    } else {
1678        ALOGV("VideoEditorVideoDecoder_render ERROR 0x%X", err);
1679    }
1680    ALOGV("VideoEditorVideoDecoder_render end");
1681    return err;
1682}
1683
1684M4OSA_ERR VideoEditorVideoDecoder_getInterface(M4DECODER_VideoType decoderType,
1685        M4DECODER_VideoType *pDecoderType, M4OSA_Context *pDecInterface) {
1686    M4DECODER_VideoInterface* pDecoderInterface = M4OSA_NULL;
1687
1688    pDecoderInterface = (M4DECODER_VideoInterface*)M4OSA_32bitAlignedMalloc(
1689        sizeof(M4DECODER_VideoInterface), M4DECODER_EXTERNAL,
1690        (M4OSA_Char*)"VideoEditorVideoDecoder_getInterface" );
1691    if (M4OSA_NULL == pDecoderInterface) {
1692        return M4ERR_ALLOC;
1693    }
1694
1695    *pDecoderType = decoderType;
1696
1697    pDecoderInterface->m_pFctCreate    = VideoEditorVideoDecoder_create;
1698    pDecoderInterface->m_pFctDestroy   = VideoEditorVideoDecoder_destroy;
1699    pDecoderInterface->m_pFctGetOption = VideoEditorVideoDecoder_getOption;
1700    pDecoderInterface->m_pFctSetOption = VideoEditorVideoDecoder_setOption;
1701    pDecoderInterface->m_pFctDecode    = VideoEditorVideoDecoder_decode;
1702    pDecoderInterface->m_pFctRender    = VideoEditorVideoDecoder_render;
1703
1704    *pDecInterface = (M4OSA_Context)pDecoderInterface;
1705    return M4NO_ERROR;
1706}
1707
1708M4OSA_ERR VideoEditorVideoDecoder_getSoftwareInterface(M4DECODER_VideoType decoderType,
1709        M4DECODER_VideoType *pDecoderType, M4OSA_Context *pDecInterface) {
1710    M4DECODER_VideoInterface* pDecoderInterface = M4OSA_NULL;
1711
1712    pDecoderInterface = (M4DECODER_VideoInterface*)M4OSA_32bitAlignedMalloc(
1713        sizeof(M4DECODER_VideoInterface), M4DECODER_EXTERNAL,
1714        (M4OSA_Char*)"VideoEditorVideoDecoder_getInterface" );
1715    if (M4OSA_NULL == pDecoderInterface) {
1716        return M4ERR_ALLOC;
1717    }
1718
1719    *pDecoderType = decoderType;
1720
1721    pDecoderInterface->m_pFctCreate    = VideoEditorVideoSoftwareDecoder_create;
1722    pDecoderInterface->m_pFctDestroy   = VideoEditorVideoDecoder_destroy;
1723    pDecoderInterface->m_pFctGetOption = VideoEditorVideoDecoder_getOption;
1724    pDecoderInterface->m_pFctSetOption = VideoEditorVideoDecoder_setOption;
1725    pDecoderInterface->m_pFctDecode    = VideoEditorVideoDecoder_decode;
1726    pDecoderInterface->m_pFctRender    = VideoEditorVideoDecoder_render;
1727
1728    *pDecInterface = (M4OSA_Context)pDecoderInterface;
1729    return M4NO_ERROR;
1730}
1731extern "C" {
1732
1733M4OSA_ERR VideoEditorVideoDecoder_getInterface_MPEG4(
1734        M4DECODER_VideoType *pDecoderType, M4OSA_Context *pDecInterface) {
1735    return VideoEditorVideoDecoder_getInterface(M4DECODER_kVideoTypeMPEG4,
1736        pDecoderType, pDecInterface);
1737}
1738
1739M4OSA_ERR VideoEditorVideoDecoder_getInterface_H264(
1740        M4DECODER_VideoType *pDecoderType, M4OSA_Context *pDecInterface) {
1741    return VideoEditorVideoDecoder_getInterface(M4DECODER_kVideoTypeAVC,
1742        pDecoderType, pDecInterface);
1743
1744}
1745
1746M4OSA_ERR VideoEditorVideoDecoder_getSoftwareInterface_MPEG4(
1747        M4DECODER_VideoType *pDecoderType, M4OSA_Context *pDecInterface) {
1748    return VideoEditorVideoDecoder_getSoftwareInterface(M4DECODER_kVideoTypeMPEG4,
1749        pDecoderType, pDecInterface);
1750}
1751
1752M4OSA_ERR VideoEditorVideoDecoder_getSoftwareInterface_H264(
1753        M4DECODER_VideoType *pDecoderType, M4OSA_Context *pDecInterface) {
1754    return VideoEditorVideoDecoder_getSoftwareInterface(M4DECODER_kVideoTypeAVC,
1755        pDecoderType, pDecInterface);
1756
1757}
1758
1759M4OSA_ERR VideoEditorVideoDecoder_getVideoDecodersAndCapabilities(
1760    M4DECODER_VideoDecoders** decoders) {
1761    return queryVideoDecoderCapabilities(decoders);
1762}
1763
1764}  // extern "C"
1765