1/*
2* Copyright (c) 2009-2011 Intel Corporation.  All rights reserved.
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//#define LOG_NDEBUG 0
18#define LOG_TAG "OMXVideoDecoder"
19#include <wrs_omxil_core/log.h>
20
21#include <hardware/gralloc.h>
22#include <va/va_android.h>
23
24#include "OMXVideoDecoderBase.h"
25#include "ProtectedDataBuffer.h"
26
27
28static const char* VA_RAW_MIME_TYPE = "video/x-raw-va";
29static const uint32_t VA_COLOR_FORMAT = 0x7FA00E00;
30
31OMXVideoDecoderBase::OMXVideoDecoderBase()
32    : mRotationDegrees(0),
33#ifdef TARGET_HAS_ISV
34      mVppBufferNum(0),
35#endif
36      mCodecPriority(1),
37      mOperatingRate(0),
38      mVideoDecoder(NULL),
39      mNativeBufferCount(OUTPORT_NATIVE_BUFFER_COUNT),
40      mWorkingMode(RAWDATA_MODE),
41      mErrorReportEnabled (false),
42      mAPMode(LEGACY_MODE),
43      mFlushMode(false),
44      mFormatChanged(false) {
45      mOMXBufferHeaderTypePtrNum = 0;
46      mMetaDataBuffersNum = 0;
47      memset(&mGraphicBufferParam, 0, sizeof(mGraphicBufferParam));
48}
49
50OMXVideoDecoderBase::~OMXVideoDecoderBase() {
51    releaseVideoDecoder(mVideoDecoder);
52
53    if (this->ports) {
54        if (this->ports[INPORT_INDEX]) {
55            delete this->ports[INPORT_INDEX];
56            this->ports[INPORT_INDEX] = NULL;
57        }
58
59        if (this->ports[OUTPORT_INDEX]) {
60            delete this->ports[OUTPORT_INDEX];
61            this->ports[OUTPORT_INDEX] = NULL;
62        }
63    }
64}
65
66OMX_ERRORTYPE OMXVideoDecoderBase::InitInputPort(void) {
67    this->ports[INPORT_INDEX] = new PortVideo;
68    if (this->ports[INPORT_INDEX] == NULL) {
69        return OMX_ErrorInsufficientResources;
70    }
71
72    PortVideo *port = static_cast<PortVideo *>(this->ports[INPORT_INDEX]);
73
74    // OMX_PARAM_PORTDEFINITIONTYPE
75    OMX_PARAM_PORTDEFINITIONTYPE paramPortDefinitionInput;
76    memset(&paramPortDefinitionInput, 0, sizeof(paramPortDefinitionInput));
77    SetTypeHeader(&paramPortDefinitionInput, sizeof(paramPortDefinitionInput));
78    paramPortDefinitionInput.nPortIndex = INPORT_INDEX;
79    paramPortDefinitionInput.eDir = OMX_DirInput;
80    paramPortDefinitionInput.nBufferCountActual = INPORT_ACTUAL_BUFFER_COUNT;
81    paramPortDefinitionInput.nBufferCountMin = INPORT_MIN_BUFFER_COUNT;
82    paramPortDefinitionInput.nBufferSize = INPORT_BUFFER_SIZE;
83    paramPortDefinitionInput.bEnabled = OMX_TRUE;
84    paramPortDefinitionInput.bPopulated = OMX_FALSE;
85    paramPortDefinitionInput.eDomain = OMX_PortDomainVideo;
86    paramPortDefinitionInput.format.video.cMIMEType = NULL; // to be overridden
87    paramPortDefinitionInput.format.video.pNativeRender = NULL;
88    paramPortDefinitionInput.format.video.nFrameWidth = 176;
89    paramPortDefinitionInput.format.video.nFrameHeight = 144;
90    paramPortDefinitionInput.format.video.nStride = 0;
91    paramPortDefinitionInput.format.video.nSliceHeight = 0;
92    paramPortDefinitionInput.format.video.nBitrate = 64000;
93    paramPortDefinitionInput.format.video.xFramerate = 15 << 16;
94    // TODO: check if we need to set bFlagErrorConcealment  to OMX_TRUE
95    paramPortDefinitionInput.format.video.bFlagErrorConcealment = OMX_FALSE;
96    paramPortDefinitionInput.format.video.eCompressionFormat = OMX_VIDEO_CodingUnused; // to be overridden
97    paramPortDefinitionInput.format.video.eColorFormat = OMX_COLOR_FormatUnused;
98    paramPortDefinitionInput.format.video.pNativeWindow = NULL;
99    paramPortDefinitionInput.bBuffersContiguous = OMX_FALSE;
100    paramPortDefinitionInput.nBufferAlignment = 0;
101
102    // Derived class must implement this interface and override any field if needed.
103    // eCompressionFormat and and cMIMEType must be overridden
104    InitInputPortFormatSpecific(&paramPortDefinitionInput);
105
106    port->SetPortDefinition(&paramPortDefinitionInput, true);
107
108    // OMX_VIDEO_PARAM_PORTFORMATTYPE
109    OMX_VIDEO_PARAM_PORTFORMATTYPE paramPortFormat;
110    memset(&paramPortFormat, 0, sizeof(paramPortFormat));
111    SetTypeHeader(&paramPortFormat, sizeof(paramPortFormat));
112    paramPortFormat.nPortIndex = INPORT_INDEX;
113    paramPortFormat.nIndex = 0;
114    paramPortFormat.eCompressionFormat = paramPortDefinitionInput.format.video.eCompressionFormat;
115    paramPortFormat.eColorFormat = paramPortDefinitionInput.format.video.eColorFormat;
116    paramPortFormat.xFramerate = paramPortDefinitionInput.format.video.xFramerate;
117
118    port->SetPortVideoParam(&paramPortFormat, true);
119
120    return OMX_ErrorNone;
121}
122
123
124OMX_ERRORTYPE OMXVideoDecoderBase::InitOutputPort(void) {
125    this->ports[OUTPORT_INDEX] = new PortVideo;
126    if (this->ports[OUTPORT_INDEX] == NULL) {
127        return OMX_ErrorInsufficientResources;
128    }
129
130    PortVideo *port = static_cast<PortVideo *>(this->ports[OUTPORT_INDEX]);
131
132    // OMX_PARAM_PORTDEFINITIONTYPE
133    OMX_PARAM_PORTDEFINITIONTYPE paramPortDefinitionOutput;
134
135    memset(&paramPortDefinitionOutput, 0, sizeof(paramPortDefinitionOutput));
136    SetTypeHeader(&paramPortDefinitionOutput, sizeof(paramPortDefinitionOutput));
137
138    paramPortDefinitionOutput.nPortIndex = OUTPORT_INDEX;
139    paramPortDefinitionOutput.eDir = OMX_DirOutput;
140    paramPortDefinitionOutput.nBufferCountActual = OUTPORT_ACTUAL_BUFFER_COUNT;
141    paramPortDefinitionOutput.nBufferCountMin = OUTPORT_MIN_BUFFER_COUNT;
142    paramPortDefinitionOutput.nBufferSize = sizeof(VideoRenderBuffer);
143
144    paramPortDefinitionOutput.bEnabled = OMX_TRUE;
145    paramPortDefinitionOutput.bPopulated = OMX_FALSE;
146    paramPortDefinitionOutput.eDomain = OMX_PortDomainVideo;
147    paramPortDefinitionOutput.format.video.cMIMEType = (OMX_STRING)VA_RAW_MIME_TYPE;
148    paramPortDefinitionOutput.format.video.pNativeRender = NULL;
149    paramPortDefinitionOutput.format.video.nFrameWidth = 176;
150    paramPortDefinitionOutput.format.video.nFrameHeight = 144;
151    paramPortDefinitionOutput.format.video.nStride = 176;
152    paramPortDefinitionOutput.format.video.nSliceHeight = 144;
153    paramPortDefinitionOutput.format.video.nBitrate = 64000;
154    paramPortDefinitionOutput.format.video.xFramerate = 15 << 16;
155    paramPortDefinitionOutput.format.video.bFlagErrorConcealment = OMX_FALSE;
156    paramPortDefinitionOutput.format.video.eCompressionFormat = OMX_VIDEO_CodingUnused;
157    paramPortDefinitionOutput.format.video.eColorFormat = OMX_COLOR_FormatYUV420SemiPlanar;
158    paramPortDefinitionOutput.format.video.pNativeWindow = NULL;
159    paramPortDefinitionOutput.bBuffersContiguous = OMX_FALSE;
160    paramPortDefinitionOutput.nBufferAlignment = 0;
161
162    // no format specific to initialize output port
163    InitOutputPortFormatSpecific(&paramPortDefinitionOutput);
164
165    port->SetPortDefinition(&paramPortDefinitionOutput, true);
166
167    // OMX_VIDEO_PARAM_PORTFORMATTYPE
168    OMX_VIDEO_PARAM_PORTFORMATTYPE paramPortFormat;
169    SetTypeHeader(&paramPortFormat, sizeof(paramPortFormat));
170    paramPortFormat.nPortIndex = OUTPORT_INDEX;
171    paramPortFormat.nIndex = 0;
172    paramPortFormat.eCompressionFormat = paramPortDefinitionOutput.format.video.eCompressionFormat;
173    paramPortFormat.eColorFormat = paramPortDefinitionOutput.format.video.eColorFormat;
174    paramPortFormat.xFramerate = paramPortDefinitionOutput.format.video.xFramerate;
175
176    port->SetPortVideoParam(&paramPortFormat, true);
177
178    return OMX_ErrorNone;
179}
180
181OMX_ERRORTYPE OMXVideoDecoderBase::InitOutputPortFormatSpecific(OMX_PARAM_PORTDEFINITIONTYPE *) {
182    // no format specific to initialize output port
183    return OMX_ErrorNone;
184}
185
186OMX_ERRORTYPE OMXVideoDecoderBase::ProcessorInit(void) {
187    OMX_ERRORTYPE ret;
188    ret = OMXComponentCodecBase::ProcessorInit();
189    CHECK_RETURN_VALUE("OMXComponentCodecBase::ProcessorInit");
190
191    if (mVideoDecoder == NULL) {
192        LOGE("ProcessorInit: Video decoder is not created.");
193        return OMX_ErrorDynamicResourcesUnavailable;
194    }
195
196    VideoConfigBuffer configBuffer;
197    ret = PrepareConfigBuffer(&configBuffer);
198    CHECK_RETURN_VALUE("PrepareConfigBuffer");
199
200    //pthread_mutex_lock(&mSerializationLock);
201    Decode_Status status = mVideoDecoder->start(&configBuffer);
202    //pthread_mutex_unlock(&mSerializationLock);
203
204    if (status != DECODE_SUCCESS) {
205        return TranslateDecodeStatus(status);
206    }
207
208    return OMX_ErrorNone;
209}
210
211OMX_ERRORTYPE OMXVideoDecoderBase::ProcessorReset(void) {
212    OMX_ERRORTYPE ret;
213    VideoConfigBuffer configBuffer;
214    // reset the configbuffer and set it to mix
215    ret = PrepareConfigBuffer(&configBuffer);
216    CHECK_RETURN_VALUE("PrepareConfigBuffer");
217    mVideoDecoder->reset(&configBuffer);
218    return OMX_ErrorNone;
219}
220
221
222OMX_ERRORTYPE OMXVideoDecoderBase::ProcessorDeinit(void) {
223    if (mWorkingMode != GRAPHICBUFFER_MODE) {
224        if (mVideoDecoder == NULL) {
225            LOGE("ProcessorDeinit: Video decoder is not created.");
226            return OMX_ErrorDynamicResourcesUnavailable;
227        }
228        mVideoDecoder->stop();
229    }
230    mOMXBufferHeaderTypePtrNum = 0;
231    memset(&mGraphicBufferParam, 0, sizeof(mGraphicBufferParam));
232    mRotationDegrees = 0;
233#ifdef TARGET_HAS_ISV
234    mVppBufferNum = 0;
235#endif
236    return OMXComponentCodecBase::ProcessorDeinit();
237}
238
239OMX_ERRORTYPE OMXVideoDecoderBase::ProcessorStart(void) {
240    return OMXComponentCodecBase::ProcessorStart();
241}
242
243OMX_ERRORTYPE OMXVideoDecoderBase::ProcessorStop(void) {
244    // There is no need to return all retained buffers as we don't accumulate buffer
245    //this->ports[INPORT_INDEX]->ReturnAllRetainedBuffers();
246
247    // TODO: this is new code
248    ProcessorFlush(OMX_ALL);
249    if (mWorkingMode == GRAPHICBUFFER_MODE) {
250        // for GRAPHICBUFFER_MODE mode, va_destroySurface need to lock the graphicbuffer,
251        // Make sure va_destroySurface is called(ExecutingToIdle) before graphicbuffer is freed(IdleToLoaded).
252        if (mVideoDecoder == NULL) {
253            LOGE("ProcessorStop: Video decoder is not created.");
254            return OMX_ErrorDynamicResourcesUnavailable;
255        }
256        mVideoDecoder->stop();
257    }
258    return OMXComponentCodecBase::ProcessorStop();
259}
260
261OMX_ERRORTYPE OMXVideoDecoderBase::ProcessorPause(void) {
262    return OMXComponentCodecBase::ProcessorPause();
263}
264
265OMX_ERRORTYPE OMXVideoDecoderBase::ProcessorResume(void) {
266    return OMXComponentCodecBase::ProcessorResume();
267}
268
269OMX_ERRORTYPE OMXVideoDecoderBase::ProcessorFlush(OMX_U32 portIndex) {
270    LOGI("Flushing port# %u.", portIndex);
271    if (mVideoDecoder == NULL) {
272        LOGE("ProcessorFlush: Video decoder is not created.");
273        return OMX_ErrorDynamicResourcesUnavailable;
274    }
275
276    // Portbase has returned all retained buffers.
277    if (portIndex == INPORT_INDEX || portIndex == OMX_ALL) {
278        //pthread_mutex_lock(&mSerializationLock);
279        LOGW("Flushing video pipeline.");
280        mVideoDecoder->flush();
281        //pthread_mutex_unlock(&mSerializationLock);
282    }
283    // TODO: do we need to flush output port?
284    return OMX_ErrorNone;
285}
286
287OMX_ERRORTYPE OMXVideoDecoderBase::ProcessorPreFreeBuffer(OMX_U32 nPortIndex, OMX_BUFFERHEADERTYPE * pBuffer) {
288    if (mWorkingMode == GRAPHICBUFFER_MODE)
289        return OMX_ErrorNone;
290
291    if (nPortIndex == OUTPORT_INDEX && pBuffer->pPlatformPrivate) {
292        VideoRenderBuffer *p = (VideoRenderBuffer *)pBuffer->pPlatformPrivate;
293        p->renderDone = true;
294        pBuffer->pPlatformPrivate = NULL;
295    }
296    return OMX_ErrorNone;
297}
298
299 OMX_ERRORTYPE OMXVideoDecoderBase::ProcessorPreFillBuffer(OMX_BUFFERHEADERTYPE* buffer) {
300    if (mWorkingMode == GRAPHICBUFFER_MODE && buffer->nOutputPortIndex == OUTPORT_INDEX){
301        Decode_Status status;
302        if(mVideoDecoder == NULL){
303            LOGW("ProcessorPreFillBuffer: Video decoder is not created");
304            return OMX_ErrorDynamicResourcesUnavailable;
305        }
306
307        if (mAPMode == METADATA_MODE) {
308            bool found = false;
309            if (mOMXBufferHeaderTypePtrNum < mMetaDataBuffersNum) {
310                for (uint32_t i = 0; i < mOMXBufferHeaderTypePtrNum; i++) {
311                    if (mOMXBufferHeaderTypePtrArray[i] == buffer) {
312                        found = true;
313                        break;
314                    }
315                }
316                if (!found) {
317                    mOMXBufferHeaderTypePtrArray[mOMXBufferHeaderTypePtrNum] = buffer;
318                    mOMXBufferHeaderTypePtrNum++;
319                }
320            }
321
322            VideoDecoderOutputMetaData *metadata = (VideoDecoderOutputMetaData *)(buffer->pBuffer);
323            status = mVideoDecoder->signalRenderDone((void *)(metadata->pHandle), !found);
324        } else {
325            status = mVideoDecoder->signalRenderDone(buffer->pBuffer);
326        }
327
328        if (status != DECODE_SUCCESS) {
329            LOGW("ProcessorPreFillBuffer:: signalRenderDone return error");
330            return TranslateDecodeStatus(status);
331        }
332    } else if (buffer->pPlatformPrivate && buffer->nOutputPortIndex == OUTPORT_INDEX){
333        VideoRenderBuffer *p = (VideoRenderBuffer *)buffer->pPlatformPrivate;
334        p->renderDone = true;
335        buffer->pPlatformPrivate = NULL;
336    }
337    return OMX_ErrorNone;
338}
339
340OMX_ERRORTYPE OMXVideoDecoderBase::ProcessorProcess(
341    OMX_BUFFERHEADERTYPE ***pBuffers,
342    buffer_retain_t *retains,
343    OMX_U32) {
344
345    OMX_ERRORTYPE ret;
346    Decode_Status status;
347    OMX_BOOL isResolutionChange = OMX_FALSE;
348    // fill render buffer without draining decoder output queue
349    ret = FillRenderBuffer(pBuffers[OUTPORT_INDEX], &retains[OUTPORT_INDEX], 0, &isResolutionChange);
350    if (ret == OMX_ErrorNone) {
351        retains[INPORT_INDEX] = BUFFER_RETAIN_GETAGAIN;
352        if (isResolutionChange) {
353            HandleFormatChange();
354        }
355
356        if (mFlushMode) {
357            LOGI("in mFlushMode, do HandleFormatChange.");
358            HandleFormatChange();
359        } else {
360            // Actually, if mAPMode is set, mWorkingMode should be GRAPHICBUFFER_MODE.
361            if (((mAPMode == METADATA_MODE) && (mWorkingMode == GRAPHICBUFFER_MODE)) && mFormatChanged) {
362                if (((*pBuffers[OUTPORT_INDEX])->nFlags & OMX_BUFFERFLAG_EOS) || (mVideoDecoder->getOutputQueueLength() == 0)) {
363                    // Format changed, set mFlushMode, clear eos
364                    mFlushMode = true;
365                    mFormatChanged = false;
366                    (*pBuffers[OUTPORT_INDEX])->nFlags &= ~OMX_BUFFERFLAG_EOS;
367                }
368            }
369        }
370
371        // TODO: continue decoding
372        return ret;
373    } else if (ret != OMX_ErrorNotReady) {
374        return ret;
375    }
376
377    VideoDecodeBuffer decodeBuffer;
378    // PrepareDecodeBuffer will set retain to either BUFFER_RETAIN_GETAGAIN or BUFFER_RETAIN_NOT_RETAIN
379    ret = PrepareDecodeBuffer(*pBuffers[INPORT_INDEX], &retains[INPORT_INDEX], &decodeBuffer);
380    if (ret == OMX_ErrorNotReady) {
381        retains[OUTPORT_INDEX] = BUFFER_RETAIN_GETAGAIN;
382        return OMX_ErrorNone;
383    } else if (ret != OMX_ErrorNone) {
384        return ret;
385    }
386
387    if (decodeBuffer.size != 0) {
388        //pthread_mutex_lock(&mSerializationLock);
389        status = mVideoDecoder->decode(&decodeBuffer);
390        //pthread_mutex_unlock(&mSerializationLock);
391
392        if (status == DECODE_FORMAT_CHANGE) {
393            if ((mAPMode == METADATA_MODE) && (mWorkingMode == GRAPHICBUFFER_MODE)) {
394                mFormatChanged = true;
395                retains[INPORT_INDEX] = BUFFER_RETAIN_GETAGAIN;
396            } else {
397                ret = HandleFormatChange();
398                CHECK_RETURN_VALUE("HandleFormatChange");
399                ((*pBuffers[OUTPORT_INDEX]))->nFilledLen = 0;
400                retains[OUTPORT_INDEX] = BUFFER_RETAIN_GETAGAIN;
401                retains[INPORT_INDEX] = BUFFER_RETAIN_GETAGAIN;
402                // real dynamic resolution change will be handled later
403                // Here is just a temporary workaround
404                // don't use the output buffer if format is changed.
405                return OMX_ErrorNone;
406            }
407        } else if (status == DECODE_NO_CONFIG) {
408            LOGW("Decoder returns DECODE_NO_CONFIG.");
409            retains[OUTPORT_INDEX] = BUFFER_RETAIN_GETAGAIN;
410            return OMX_ErrorNone;
411        } else if (status == DECODE_NO_REFERENCE) {
412            LOGW("Decoder returns DECODE_NO_REFERENCE.");
413            //retains[OUTPORT_INDEX] = BUFFER_RETAIN_GETAGAIN;
414            //return OMX_ErrorNone;
415        } else if (status == DECODE_MULTIPLE_FRAME){
416            if (decodeBuffer.ext != NULL && decodeBuffer.ext->extType == PACKED_FRAME_TYPE && decodeBuffer.ext->extData != NULL) {
417                PackedFrameData* nextFrame = (PackedFrameData*)decodeBuffer.ext->extData;
418                (*pBuffers[INPORT_INDEX])->nOffset += nextFrame->offSet;
419                (*pBuffers[INPORT_INDEX])->nTimeStamp = nextFrame->timestamp;
420                (*pBuffers[INPORT_INDEX])->nFilledLen -= nextFrame->offSet;
421                retains[INPORT_INDEX] = BUFFER_RETAIN_GETAGAIN;
422                LOGW("Find multiple frames in a buffer, next frame offset = %d, timestamp = %lld", (*pBuffers[INPORT_INDEX])->nOffset, (*pBuffers[INPORT_INDEX])->nTimeStamp);
423            }
424        }
425        else if (status != DECODE_SUCCESS && status != DECODE_FRAME_DROPPED) {
426            if (checkFatalDecoderError(status)) {
427                return TranslateDecodeStatus(status);
428            } else {
429                // For decoder errors that could be omitted,  not throw error and continue to decode.
430                TranslateDecodeStatus(status);
431
432                ((*pBuffers[OUTPORT_INDEX]))->nFilledLen = 0;
433
434                // Do not return, and try to drain the output queue
435                // retains[OUTPORT_INDEX] = BUFFER_RETAIN_GETAGAIN;
436                // return OMX_ErrorNone;
437            }
438        }
439    }
440    // drain the decoder output queue when in EOS state and fill the render buffer
441    ret = FillRenderBuffer(pBuffers[OUTPORT_INDEX], &retains[OUTPORT_INDEX],
442            ((*pBuffers[INPORT_INDEX]))->nFlags,&isResolutionChange);
443
444    if (isResolutionChange) {
445        HandleFormatChange();
446    }
447
448    if (mFlushMode) {
449        LOGI("in mFlushMode, do HandleFormatChange.");
450        HandleFormatChange();
451    } else {
452        if (((mAPMode == METADATA_MODE) && (mWorkingMode == GRAPHICBUFFER_MODE)) && mFormatChanged) {
453            if (((*pBuffers[OUTPORT_INDEX])->nFlags & OMX_BUFFERFLAG_EOS) || (mVideoDecoder->getOutputQueueLength() == 0)) {
454                // Format changed, set mFlushMode, clear eos.
455                mFlushMode = true;
456                mFormatChanged = false;
457                (*pBuffers[OUTPORT_INDEX])->nFlags &= ~OMX_BUFFERFLAG_EOS;
458            }
459        }
460    }
461
462    bool inputEoS = ((*pBuffers[INPORT_INDEX])->nFlags & OMX_BUFFERFLAG_EOS);
463    bool outputEoS = ((*pBuffers[OUTPORT_INDEX])->nFlags & OMX_BUFFERFLAG_EOS);
464    // if output port is not eos, retain the input buffer until all the output buffers are drained.
465    if (inputEoS && !outputEoS) {
466        retains[INPORT_INDEX] = BUFFER_RETAIN_GETAGAIN;
467        // the input buffer is retained for draining purpose. Set nFilledLen to 0 so buffer will not be decoded again.
468        (*pBuffers[INPORT_INDEX])->nFilledLen = 0;
469    }
470
471    if (ret == OMX_ErrorNotReady) {
472        retains[OUTPORT_INDEX] = BUFFER_RETAIN_GETAGAIN;
473        ret = OMX_ErrorNone;
474    }
475
476    return ret;
477}
478
479bool OMXVideoDecoderBase::IsAllBufferAvailable(void) {
480    bool b = ComponentBase::IsAllBufferAvailable();
481    if (b == false) {
482        return false;
483    }
484
485    PortVideo *port = NULL;
486    port = static_cast<PortVideo *>(this->ports[OUTPORT_INDEX]);
487    const OMX_PARAM_PORTDEFINITIONTYPE* port_def = port->GetPortDefinition();
488     // if output port is disabled, retain the input buffer
489    if (!port_def->bEnabled) {
490        return false;
491    }
492
493    if (mVideoDecoder) {
494        return mVideoDecoder->checkBufferAvail();
495    }
496    return false;
497}
498
499OMX_ERRORTYPE OMXVideoDecoderBase::PrepareConfigBuffer(VideoConfigBuffer *p) {
500    // default config buffer preparation
501    memset(p, 0, sizeof(VideoConfigBuffer));
502
503    const OMX_PARAM_PORTDEFINITIONTYPE *paramPortDefinitionInput = this->ports[INPORT_INDEX]->GetPortDefinition();
504    if (paramPortDefinitionInput == NULL) {
505        return OMX_ErrorBadParameter;
506    }
507
508    if (mWorkingMode == GRAPHICBUFFER_MODE) {
509        if (mAPMode == METADATA_MODE) {
510            const OMX_PARAM_PORTDEFINITIONTYPE *def_output = this->ports[OUTPORT_INDEX]->GetPortDefinition();
511            if (def_output == NULL) {
512                return OMX_ErrorBadParameter;
513            }
514
515            mMetaDataBuffersNum = def_output->nBufferCountActual;
516            mOMXBufferHeaderTypePtrNum = 0;
517
518            mGraphicBufferParam.graphicBufferColorFormat = def_output->format.video.eColorFormat;
519            mGraphicBufferParam.graphicBufferHStride = getStride(def_output->format.video.nFrameWidth);
520            mGraphicBufferParam.graphicBufferVStride = (def_output->format.video.nFrameHeight + 0x1f) & ~0x1f;
521            mGraphicBufferParam.graphicBufferWidth = def_output->format.video.nFrameWidth;
522            mGraphicBufferParam.graphicBufferHeight = def_output->format.video.nFrameHeight;
523
524            p->surfaceNumber = mMetaDataBuffersNum;
525            for (int i = 0; i < MAX_GRAPHIC_BUFFER_NUM; i++) {
526                p->graphicBufferHandler[i] = NULL;
527            }
528            p->flag |= WANT_STORE_META_DATA;
529        } else {
530            p->surfaceNumber = mOMXBufferHeaderTypePtrNum;
531            for (uint32_t i = 0; i < mOMXBufferHeaderTypePtrNum; i++){
532                OMX_BUFFERHEADERTYPE *buffer_hdr = mOMXBufferHeaderTypePtrArray[i];
533                p->graphicBufferHandler[i] = buffer_hdr->pBuffer;
534                LOGV("PrepareConfigBuffer bufferid = %p, handle = %p", buffer_hdr, buffer_hdr->pBuffer);
535            }
536        }
537        p->flag |= USE_NATIVE_GRAPHIC_BUFFER;
538        p->graphicBufferHStride = mGraphicBufferParam.graphicBufferHStride;
539        p->graphicBufferVStride = mGraphicBufferParam.graphicBufferVStride;
540        p->graphicBufferWidth = mGraphicBufferParam.graphicBufferWidth;
541        p->graphicBufferHeight = mGraphicBufferParam.graphicBufferHeight;
542        p->graphicBufferColorFormat = mGraphicBufferParam.graphicBufferColorFormat;
543        if (p->graphicBufferColorFormat == OMX_INTEL_COLOR_FormatYUV420PackedSemiPlanar_Tiled
544#ifdef USE_GEN_HW
545            || p->graphicBufferColorFormat == HAL_PIXEL_FORMAT_NV12_X_TILED_INTEL
546#endif
547        )
548            p->flag |= USE_TILING_MEMORY;
549
550        if (mEnableAdaptivePlayback)
551            p->flag |= WANT_ADAPTIVE_PLAYBACK;
552
553        PortVideo *port = NULL;
554        port = static_cast<PortVideo *>(this->ports[INPORT_INDEX]);
555        OMX_PARAM_PORTDEFINITIONTYPE port_def;
556        memcpy(&port_def, port->GetPortDefinition(), sizeof(port_def));
557
558        if (port_def.format.video.pNativeWindow != NULL) {
559            p->nativeWindow = port_def.format.video.pNativeWindow;
560            LOGD("NativeWindow = %p", p->nativeWindow);
561        }
562
563    }
564
565    p->rotationDegrees = mRotationDegrees;
566#ifdef TARGET_HAS_ISV
567    p->vppBufferNum = mVppBufferNum;
568#endif
569    p->width = paramPortDefinitionInput->format.video.nFrameWidth;
570    p->height = paramPortDefinitionInput->format.video.nFrameHeight;
571
572    return OMX_ErrorNone;
573}
574
575OMX_ERRORTYPE OMXVideoDecoderBase::PrepareDecodeBuffer(OMX_BUFFERHEADERTYPE *buffer, buffer_retain_t *retain, VideoDecodeBuffer *p) {
576    // default decode buffer preparation
577    memset(p, 0, sizeof(VideoDecodeBuffer));
578    if (buffer->nFilledLen == 0) {
579        LOGW("Len of filled data to decode is 0.");
580        return OMX_ErrorNone; //OMX_ErrorBadParameter;
581    }
582
583    if (buffer->pBuffer == NULL) {
584        LOGE("Buffer to decode is empty.");
585        return OMX_ErrorBadParameter;
586    }
587
588    if (buffer->nFlags & OMX_BUFFERFLAG_CODECCONFIG) {
589        LOGI("Buffer has OMX_BUFFERFLAG_CODECCONFIG flag.");
590    }
591
592    if (buffer->nFlags & OMX_BUFFERFLAG_DECODEONLY) {
593        // TODO: Handle OMX_BUFFERFLAG_DECODEONLY : drop the decoded frame without rendering it.
594        LOGW("Buffer has OMX_BUFFERFLAG_DECODEONLY flag.");
595    }
596
597    p->data = buffer->pBuffer + buffer->nOffset;
598    p->size = buffer->nFilledLen;
599    p->timeStamp = buffer->nTimeStamp;
600    if (buffer->nFlags & (OMX_BUFFERFLAG_ENDOFFRAME | OMX_BUFFERFLAG_EOS)) {
601        // TODO: OMX_BUFFERFLAG_ENDOFFRAME can be used to indicate end of a NAL unit.
602        // setting this flag may cause corruption if buffer does not contain end-of-frame data.
603        p->flag = HAS_COMPLETE_FRAME;
604    }
605
606    if (buffer->nFlags & OMX_BUFFERFLAG_SYNCFRAME) {
607        p->flag |= IS_SYNC_FRAME;
608    }
609
610    if (buffer->pInputPortPrivate) {
611        uint32_t degree = 0;
612        memcpy ((void *) &degree, buffer->pInputPortPrivate, sizeof(uint32_t));
613        p->rotationDegrees = degree;
614        LOGV("rotationDegrees = %d", p->rotationDegrees);
615    } else {
616        p->rotationDegrees = mRotationDegrees;
617    }
618
619    *retain= BUFFER_RETAIN_NOT_RETAIN;
620    return OMX_ErrorNone;
621}
622
623OMX_ERRORTYPE OMXVideoDecoderBase::PrepareDecodeNativeHandleBuffer(OMX_BUFFERHEADERTYPE *buffer, buffer_retain_t *retain, VideoDecodeBuffer *p) {
624    // default decode buffer preparation
625
626    memset(p, 0, sizeof(VideoDecodeBuffer));
627    if (buffer->nFilledLen == 0) {
628        LOGW("Len of filled data to decode is 0.");
629        return OMX_ErrorNone; //OMX_ErrorBadParameter;
630    }
631
632    if (buffer->pBuffer == NULL) {
633        LOGE("Buffer to decode is empty.");
634        return OMX_ErrorBadParameter;
635    }
636
637    if (buffer->nFlags & OMX_BUFFERFLAG_CODECCONFIG) {
638        LOGI("Buffer has OMX_BUFFERFLAG_CODECCONFIG flag.");
639    }
640
641    if (buffer->nFlags & OMX_BUFFERFLAG_DECODEONLY) {
642        // TODO: Handle OMX_BUFFERFLAG_DECODEONLY : drop the decoded frame without rendering it.
643        LOGW("Buffer has OMX_BUFFERFLAG_DECODEONLY flag.");
644    }
645    //Get data pointer from native_handle
646    native_handle_t *native_handle = (native_handle_t *)buffer->pBuffer;
647    ProtectedDataBuffer *dataBuffer = (ProtectedDataBuffer *) native_handle->data[1];
648    p->data =  dataBuffer->data + buffer->nOffset;
649
650
651
652    p->size = buffer->nFilledLen;
653    p->timeStamp = buffer->nTimeStamp;
654    if (buffer->nFlags & (OMX_BUFFERFLAG_ENDOFFRAME | OMX_BUFFERFLAG_EOS)) {
655        // TODO: OMX_BUFFERFLAG_ENDOFFRAME can be used to indicate end of a NAL unit.
656        // setting this flag may cause corruption if buffer does not contain end-of-frame data.
657        p->flag = HAS_COMPLETE_FRAME;
658    }
659
660    if (buffer->nFlags & OMX_BUFFERFLAG_SYNCFRAME) {
661        p->flag |= IS_SYNC_FRAME;
662    }
663
664    if (buffer->pInputPortPrivate) {
665        uint32_t degree = 0;
666        memcpy ((void *) &degree, buffer->pInputPortPrivate, sizeof(uint32_t));
667        p->rotationDegrees = degree;
668        LOGV("rotationDegrees = %d", p->rotationDegrees);
669    } else {
670        p->rotationDegrees = mRotationDegrees;
671    }
672
673    *retain= BUFFER_RETAIN_NOT_RETAIN;
674    return OMX_ErrorNone;
675}
676
677
678OMX_ERRORTYPE OMXVideoDecoderBase::FillRenderBuffer(OMX_BUFFERHEADERTYPE **pBuffer, buffer_retain_t *retain, OMX_U32 inportBufferFlags, OMX_BOOL *isResolutionChange) {
679    OMX_BUFFERHEADERTYPE *buffer = *pBuffer;
680    OMX_BUFFERHEADERTYPE *buffer_orign = buffer;
681    VideoErrorBuffer *ErrBufPtr = NULL;
682
683    if (mWorkingMode != GRAPHICBUFFER_MODE && buffer->pPlatformPrivate) {
684        VideoRenderBuffer *p = (VideoRenderBuffer *)buffer->pPlatformPrivate;
685        p->renderDone = true;
686        buffer->pPlatformPrivate = NULL;
687    }
688
689    if (mWorkingMode == GRAPHICBUFFER_MODE && mErrorReportEnabled) {
690        if (buffer->pOutputPortPrivate == NULL)
691            LOGE("The App doesn't provide the output buffer for error reporting");
692        else
693            ErrBufPtr = (VideoErrorBuffer *)buffer->pOutputPortPrivate;
694    }
695
696    bool draining = (inportBufferFlags & OMX_BUFFERFLAG_EOS);
697    //pthread_mutex_lock(&mSerializationLock);
698    const VideoRenderBuffer *renderBuffer = NULL;
699    //pthread_mutex_unlock(&mSerializationLock);
700
701    // in mFlushMode, provide empty buffer.
702    if (mFlushMode) {
703        buffer->nFilledLen = 0;
704        return OMX_ErrorNone;
705    }
706
707    if (((mAPMode == METADATA_MODE) && (mWorkingMode == GRAPHICBUFFER_MODE)) && mFormatChanged) {
708         renderBuffer = mVideoDecoder->getOutput(true, ErrBufPtr);
709    } else {
710         renderBuffer = mVideoDecoder->getOutput(draining, ErrBufPtr);
711    }
712    if (renderBuffer == NULL) {
713        buffer->nFilledLen = 0;
714        if (draining) {
715            LOGI("output EOS received");
716            buffer->nFlags = OMX_BUFFERFLAG_EOS;
717            return OMX_ErrorNone;
718        }
719        return OMX_ErrorNotReady;
720    }
721
722    if (mWorkingMode == GRAPHICBUFFER_MODE) {
723        buffer = *pBuffer = mOMXBufferHeaderTypePtrArray[renderBuffer->graphicBufferIndex];
724     }
725
726    buffer->nFlags = OMX_BUFFERFLAG_ENDOFFRAME;
727#ifdef DEINTERLACE_EXT
728    if (renderBuffer->scanFormat & (VA_TOP_FIELD | VA_BOTTOM_FIELD))
729        buffer->nFlags |= OMX_BUFFERFLAG_TFF;
730#endif
731    buffer->nTimeStamp = renderBuffer->timeStamp;
732
733    if (renderBuffer->flag & IS_EOS) {
734        buffer->nFlags |= OMX_BUFFERFLAG_EOS;
735    }
736    *isResolutionChange = (renderBuffer->flag & IS_RESOLUTION_CHANGE)? OMX_TRUE: OMX_FALSE;
737
738    if (mWorkingMode == GRAPHICBUFFER_MODE) {
739        if (buffer_orign != buffer) {
740            VideoErrorBuffer *ErrBufOutPtr = NULL;
741            ErrBufOutPtr = (VideoErrorBuffer *)buffer->pOutputPortPrivate;
742            if (ErrBufPtr && ErrBufOutPtr) {
743                memcpy(ErrBufOutPtr, ErrBufPtr, sizeof(VideoErrorBuffer));
744                memset(ErrBufPtr, 0, sizeof(VideoErrorBuffer));
745            }
746            *retain = BUFFER_RETAIN_OVERRIDDEN;
747        }
748         buffer->nFilledLen = sizeof(OMX_U8*);
749    } else {
750        uint32_t size = 0;
751        Decode_Status status = mVideoDecoder->getRawDataFromSurface(const_cast<VideoRenderBuffer *>(renderBuffer), buffer->pBuffer + buffer->nOffset, &size, false);
752        if (status != DECODE_SUCCESS) {
753            return TranslateDecodeStatus(status);
754        }
755        buffer->nFilledLen = size;
756        buffer->pPlatformPrivate = (void *)renderBuffer;
757    }
758
759    return OMX_ErrorNone;
760}
761
762OMX_ERRORTYPE OMXVideoDecoderBase::HandleFormatChange(void) {
763    LOGW("Video format is changed.");
764    //pthread_mutex_lock(&mSerializationLock);
765    const VideoFormatInfo *formatInfo = mVideoDecoder->getFormatInfo();
766    //pthread_mutex_unlock(&mSerializationLock);
767
768    // Sync port definition as it may change.
769    OMX_PARAM_PORTDEFINITIONTYPE paramPortDefinitionInput, paramPortDefinitionOutput;
770
771    memcpy(&paramPortDefinitionInput,
772        this->ports[INPORT_INDEX]->GetPortDefinition(),
773        sizeof(paramPortDefinitionInput));
774
775    memcpy(&paramPortDefinitionOutput,
776        this->ports[OUTPORT_INDEX]->GetPortDefinition(),
777        sizeof(paramPortDefinitionOutput));
778
779    uint32_t width = formatInfo->width;
780    uint32_t height = formatInfo->height;
781    uint32_t stride = formatInfo->width;
782    uint32_t sliceHeight = formatInfo->height;
783
784    uint32_t widthCropped = formatInfo->width - formatInfo->cropLeft - formatInfo->cropRight;
785    uint32_t heightCropped = formatInfo->height - formatInfo->cropTop - formatInfo->cropBottom;
786    if (strcasecmp(formatInfo->mimeType,"video/avc") == 0 ||
787        strcasecmp(formatInfo->mimeType,"video/h264") == 0) {
788        heightCropped = formatInfo->height;
789        widthCropped = formatInfo->width;
790    }
791    uint32_t strideCropped = widthCropped;
792    uint32_t sliceHeightCropped = heightCropped;
793    int force_realloc = 0;
794    bool isVP8 = false;
795
796    if (mAPMode == METADATA_MODE && mWorkingMode == GRAPHICBUFFER_MODE) {
797#ifdef TARGET_HAS_ISV
798        if (paramPortDefinitionOutput.nBufferCountActual - mVppBufferNum < formatInfo->actualBufferNeeded) {
799#else
800        if (paramPortDefinitionOutput.nBufferCountActual < formatInfo->actualBufferNeeded) {
801#endif
802            paramPortDefinitionOutput.nBufferCountActual = mNativeBufferCount = formatInfo->actualBufferNeeded;
803            paramPortDefinitionOutput.nBufferCountMin = formatInfo->actualBufferNeeded - 4;
804        }
805        // input port
806        paramPortDefinitionInput.format.video.nFrameWidth = width;
807        paramPortDefinitionInput.format.video.nFrameHeight = height;
808        paramPortDefinitionInput.format.video.nStride = stride;
809        paramPortDefinitionInput.format.video.nSliceHeight = sliceHeight;
810        // output port
811        paramPortDefinitionOutput.format.video.nFrameWidth = width;
812        paramPortDefinitionOutput.format.video.nFrameHeight = height;
813        paramPortDefinitionOutput.format.video.eColorFormat = GetOutputColorFormat(paramPortDefinitionOutput.format.video.nFrameWidth);
814        paramPortDefinitionOutput.format.video.nStride = stride;
815        paramPortDefinitionOutput.format.video.nSliceHeight = sliceHeight;
816
817        paramPortDefinitionOutput.bEnabled = (OMX_BOOL)false;
818        mOMXBufferHeaderTypePtrNum = 0;
819        memset(&mGraphicBufferParam, 0, sizeof(mGraphicBufferParam));
820        mMetaDataBuffersNum = 0;
821
822        this->ports[INPORT_INDEX]->SetPortDefinition(&paramPortDefinitionInput, true);
823        this->ports[OUTPORT_INDEX]->SetPortDefinition(&paramPortDefinitionOutput, true);
824
825        ProcessorFlush(INPORT_INDEX);
826
827        mVideoDecoder->freeSurfaceBuffers();
828
829        this->ports[OUTPORT_INDEX]->ReportPortSettingsChanged();
830
831        mFlushMode = false;
832        return OMX_ErrorNone;
833    }
834
835#ifdef TARGET_HAS_ISV
836    LOGI("============== mVppBufferNum = %d\n", mVppBufferNum);
837    if (paramPortDefinitionOutput.nBufferCountActual - mVppBufferNum < formatInfo->actualBufferNeeded) {
838#else
839    if (paramPortDefinitionOutput.nBufferCountActual < formatInfo->actualBufferNeeded) {
840#endif
841        if (mWorkingMode == GRAPHICBUFFER_MODE) {
842            LOGV("output port buffer number is not enough: %d to %d",
843                 paramPortDefinitionOutput.nBufferCountActual,
844                 formatInfo->actualBufferNeeded);
845            paramPortDefinitionOutput.nBufferCountActual = mNativeBufferCount = formatInfo->actualBufferNeeded;
846            paramPortDefinitionOutput.nBufferCountMin = mNativeBufferCount;
847            force_realloc = 1;
848        }
849    }
850
851    LOGV("Original size = %u x %u, new size = %d x %d, cropped size = %d x %d",
852        paramPortDefinitionInput.format.video.nFrameWidth,
853        paramPortDefinitionInput.format.video.nFrameHeight,
854        width, height, widthCropped, heightCropped);
855
856    if (paramPortDefinitionInput.format.video.eCompressionFormat == OMX_VIDEO_CodingVP8) {
857        isVP8 = true;
858    }
859
860    if (!force_realloc &&
861        widthCropped == paramPortDefinitionOutput.format.video.nFrameWidth &&
862        heightCropped == paramPortDefinitionOutput.format.video.nFrameHeight) {
863        if (mWorkingMode == RAWDATA_MODE) {
864            LOGW("Change of portsetting is not reported as size is not changed.");
865            return OMX_ErrorNone;
866        }
867    }
868
869    paramPortDefinitionInput.format.video.nFrameWidth = width;
870    paramPortDefinitionInput.format.video.nFrameHeight = height;
871    paramPortDefinitionInput.format.video.nStride = stride;
872    paramPortDefinitionInput.format.video.nSliceHeight = sliceHeight;
873
874    if (mWorkingMode == RAWDATA_MODE) {
875        paramPortDefinitionOutput.format.video.nFrameWidth = widthCropped;
876        paramPortDefinitionOutput.format.video.nFrameHeight = heightCropped;
877        paramPortDefinitionOutput.format.video.nStride = strideCropped;
878        paramPortDefinitionOutput.format.video.nSliceHeight = sliceHeightCropped;
879    } else if (mWorkingMode == GRAPHICBUFFER_MODE) {
880        // when the width and height ES parse are not larger than allocated graphic buffer in outport,
881        // there is no need to reallocate graphic buffer,just report the crop info to omx client
882        if (!force_realloc && width <= formatInfo->surfaceWidth && height <= formatInfo->surfaceHeight) {
883            this->ports[INPORT_INDEX]->SetPortDefinition(&paramPortDefinitionInput, true);
884            this->ports[OUTPORT_INDEX]->ReportOutputCrop();
885            return OMX_ErrorNone;
886        }
887
888        if (isVP8 || width > formatInfo->surfaceWidth ||  height > formatInfo->surfaceHeight) {
889            // update the real decoded resolution to outport instead of display resolution for graphic buffer reallocation
890            // when the width and height parsed from ES are larger than allocated graphic buffer in outport,
891            paramPortDefinitionOutput.format.video.nFrameWidth = width;
892            paramPortDefinitionOutput.format.video.nFrameHeight = height;
893            paramPortDefinitionOutput.format.video.eColorFormat = GetOutputColorFormat(
894                    paramPortDefinitionOutput.format.video.nFrameWidth);
895            paramPortDefinitionOutput.format.video.nStride = stride;
896            paramPortDefinitionOutput.format.video.nSliceHeight = sliceHeight;
897       }
898    }
899
900    paramPortDefinitionOutput.bEnabled = (OMX_BOOL)false;
901    mOMXBufferHeaderTypePtrNum = 0;
902    memset(&mGraphicBufferParam, 0, sizeof(mGraphicBufferParam));
903
904    this->ports[INPORT_INDEX]->SetPortDefinition(&paramPortDefinitionInput, true);
905    this->ports[OUTPORT_INDEX]->SetPortDefinition(&paramPortDefinitionOutput, true);
906
907    if (mWorkingMode == GRAPHICBUFFER_MODE) {
908        // Make sure va_destroySurface is called before graphicbuffer is freed in case of port setting changed
909        mVideoDecoder->freeSurfaceBuffers();
910
911        // Also make sure all the reference frames are flushed
912        ProcessorFlush(INPORT_INDEX);
913    }
914    this->ports[OUTPORT_INDEX]->ReportPortSettingsChanged();
915    return OMX_ErrorNone;
916}
917
918OMX_ERRORTYPE OMXVideoDecoderBase::TranslateDecodeStatus(Decode_Status status) {
919    switch (status) {
920        case DECODE_NEED_RESTART:
921            LOGE("Decoder returned DECODE_NEED_RESTART");
922            return (OMX_ERRORTYPE)OMX_ErrorIntelVideoNotPermitted;
923        case DECODE_NO_CONFIG:
924            LOGE("Decoder returned DECODE_NO_CONFIG");
925            return (OMX_ERRORTYPE)OMX_ErrorIntelMissingConfig;
926        case DECODE_NO_SURFACE:
927            LOGE("Decoder returned DECODE_NO_SURFACE");
928            return OMX_ErrorDynamicResourcesUnavailable;
929        case DECODE_NO_REFERENCE:
930            LOGE("Decoder returned DECODE_NO_REFERENCE");
931            return OMX_ErrorDynamicResourcesUnavailable; // TO DO
932        case DECODE_NO_PARSER:
933            LOGE("Decoder returned DECODE_NO_PARSER");
934            return OMX_ErrorDynamicResourcesUnavailable;
935        case DECODE_INVALID_DATA:
936            LOGE("Decoder returned DECODE_INVALID_DATA");
937            return OMX_ErrorBadParameter;
938        case DECODE_DRIVER_FAIL:
939            LOGE("Decoder returned DECODE_DRIVER_FAIL");
940            return OMX_ErrorHardware;
941        case DECODE_PARSER_FAIL:
942            LOGE("Decoder returned DECODE_PARSER_FAIL");
943            return (OMX_ERRORTYPE)OMX_ErrorIntelProcessStream; // OMX_ErrorStreamCorrupt
944        case DECODE_MEMORY_FAIL:
945            LOGE("Decoder returned DECODE_MEMORY_FAIL");
946            return OMX_ErrorInsufficientResources;
947        case DECODE_FAIL:
948            LOGE("Decoder returned DECODE_FAIL");
949            return OMX_ErrorUndefined;
950        case DECODE_SUCCESS:
951            return OMX_ErrorNone;
952        case DECODE_FORMAT_CHANGE:
953            LOGW("Decoder returned DECODE_FORMAT_CHANGE");
954            return OMX_ErrorNone;
955        case DECODE_FRAME_DROPPED:
956            LOGI("Decoder returned DECODE_FRAME_DROPPED");
957            return OMX_ErrorNone;
958        default:
959            LOGW("Decoder returned unknown error");
960            return OMX_ErrorUndefined;
961    }
962}
963
964OMX_ERRORTYPE OMXVideoDecoderBase::BuildHandlerList(void) {
965    OMXComponentCodecBase::BuildHandlerList();
966    AddHandler(OMX_IndexParamVideoPortFormat, GetParamVideoPortFormat, SetParamVideoPortFormat);
967    AddHandler(static_cast<OMX_INDEXTYPE>(OMX_IndexExtGetNativeBufferUsage), GetNativeBufferUsage, SetNativeBufferUsage);
968    AddHandler(static_cast<OMX_INDEXTYPE>(OMX_IndexExtUseNativeBuffer), GetNativeBuffer, SetNativeBuffer);
969    AddHandler(static_cast<OMX_INDEXTYPE>(OMX_IndexExtEnableNativeBuffer), GetNativeBufferMode, SetNativeBufferMode);
970    AddHandler(static_cast<OMX_INDEXTYPE>(OMX_IndexExtRotationDegrees), GetDecoderRotation, SetDecoderRotation);
971#ifdef TARGET_HAS_ISV
972    AddHandler(static_cast<OMX_INDEXTYPE>(OMX_IndexExtVppBufferNum), GetDecoderVppBufferNum, SetDecoderVppBufferNum);
973#endif
974    AddHandler(OMX_IndexConfigCommonOutputCrop, GetDecoderOutputCrop, SetDecoderOutputCrop);
975#ifdef USE_META_DATA
976    AddHandler(static_cast<OMX_INDEXTYPE>(OMX_IndexStoreMetaDataInBuffers), GetStoreMetaDataMode, SetStoreMetaDataMode);
977#endif
978    AddHandler(static_cast<OMX_INDEXTYPE>(OMX_IndexExtEnableErrorReport), GetErrorReportMode, SetErrorReportMode);
979    AddHandler(static_cast<OMX_INDEXTYPE>(OMX_IndexConfigPriority), GetCodecPriority, SetCodecPriority);
980    AddHandler(static_cast<OMX_INDEXTYPE>(OMX_IndexConfigOperatingRate), GetDecoderOperatingRate, SetDecoderOperatingRate);
981
982    return OMX_ErrorNone;
983}
984
985OMX_ERRORTYPE OMXVideoDecoderBase::GetParamVideoPortFormat(OMX_PTR pStructure) {
986    OMX_ERRORTYPE ret;
987    OMX_VIDEO_PARAM_PORTFORMATTYPE *p = (OMX_VIDEO_PARAM_PORTFORMATTYPE *)pStructure;
988
989    CHECK_TYPE_HEADER(p);
990    CHECK_PORT_INDEX_RANGE(p);
991    CHECK_ENUMERATION_RANGE(p->nIndex, 1);
992
993    PortVideo *port = NULL;
994    port = static_cast<PortVideo *>(this->ports[p->nPortIndex]);
995    memcpy(p, port->GetPortVideoParam(), sizeof(*p));
996    return OMX_ErrorNone;
997}
998
999OMX_ERRORTYPE OMXVideoDecoderBase::SetParamVideoPortFormat(OMX_PTR pStructure) {
1000    OMX_ERRORTYPE ret;
1001    OMX_VIDEO_PARAM_PORTFORMATTYPE *p = (OMX_VIDEO_PARAM_PORTFORMATTYPE *)pStructure;
1002
1003    CHECK_TYPE_HEADER(p);
1004    CHECK_PORT_INDEX_RANGE(p);
1005    CHECK_SET_PARAM_STATE();
1006
1007    // TODO: do we need to check if port is enabled?
1008    PortVideo *port = NULL;
1009    port = static_cast<PortVideo *>(this->ports[p->nPortIndex]);
1010    port->SetPortVideoParam(p, false);
1011    return OMX_ErrorNone;
1012}
1013
1014OMX_ERRORTYPE OMXVideoDecoderBase::GetNativeBufferUsageSpecific(OMX_PTR pStructure) {
1015     OMX_ERRORTYPE ret;
1016     GetAndroidNativeBufferUsageParams *param = (GetAndroidNativeBufferUsageParams*)pStructure;
1017     CHECK_TYPE_HEADER(param);
1018     // hardware usage: consumed by GLES and HWC
1019     param->nUsage |= GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_HW_COMPOSER;
1020     // software usage: can be read/written by apps
1021     param->nUsage |= GRALLOC_USAGE_SW_READ_RARELY | GRALLOC_USAGE_SW_WRITE_RARELY;
1022     return OMX_ErrorNone;
1023}
1024OMX_ERRORTYPE OMXVideoDecoderBase::SetNativeBufferUsageSpecific(OMX_PTR) {
1025    CHECK_SET_PARAM_STATE();
1026    return OMX_ErrorBadParameter;
1027}
1028
1029OMX_ERRORTYPE OMXVideoDecoderBase::GetNativeBufferUsage(OMX_PTR pStructure) {
1030    return this->GetNativeBufferUsageSpecific(pStructure);
1031}
1032OMX_ERRORTYPE OMXVideoDecoderBase::SetNativeBufferUsage(OMX_PTR pStructure) {
1033    return this->SetNativeBufferUsageSpecific(pStructure);
1034}
1035
1036OMX_ERRORTYPE OMXVideoDecoderBase::GetNativeBuffer(OMX_PTR) {
1037    return OMX_ErrorBadParameter;
1038}
1039
1040OMX_ERRORTYPE OMXVideoDecoderBase::SetNativeBuffer(OMX_PTR pStructure) {
1041    OMX_ERRORTYPE ret;
1042    UseAndroidNativeBufferParams *param = (UseAndroidNativeBufferParams*)pStructure;
1043    CHECK_TYPE_HEADER(param);
1044    if (param->nPortIndex != OUTPORT_INDEX)
1045        return OMX_ErrorBadParameter;
1046    OMX_BUFFERHEADERTYPE **buf_hdr = NULL;
1047
1048    mOMXBufferHeaderTypePtrNum++;
1049    if (mOMXBufferHeaderTypePtrNum > MAX_GRAPHIC_BUFFER_NUM)
1050        return OMX_ErrorOverflow;
1051
1052    buf_hdr = &mOMXBufferHeaderTypePtrArray[mOMXBufferHeaderTypePtrNum-1];
1053
1054    ret = this->ports[OUTPORT_INDEX]->UseBuffer(buf_hdr, OUTPORT_INDEX, param->pAppPrivate, sizeof(OMX_U8*),
1055                                      const_cast<OMX_U8*>(reinterpret_cast<const OMX_U8*>(param->nativeBuffer->handle)));
1056    if (ret != OMX_ErrorNone)
1057        return ret;
1058
1059    if (mOMXBufferHeaderTypePtrNum == 1) {
1060         mGraphicBufferParam.graphicBufferColorFormat = param->nativeBuffer->format;
1061         mGraphicBufferParam.graphicBufferHStride = param->nativeBuffer->stride;
1062         // FIXME: use IMG_native_handle_t->aiVStride[0] instead..
1063         mGraphicBufferParam.graphicBufferVStride = param->nativeBuffer->height;
1064         mGraphicBufferParam.graphicBufferWidth = param->nativeBuffer->width;
1065         mGraphicBufferParam.graphicBufferHeight = param->nativeBuffer->height;
1066    }
1067
1068    *(param->bufferHeader) = *buf_hdr;
1069
1070    return OMX_ErrorNone;
1071}
1072
1073OMX_ERRORTYPE OMXVideoDecoderBase::GetNativeBufferMode(OMX_PTR pStructure) {
1074    return this->GetNativeBufferModeSpecific(pStructure);
1075}
1076
1077OMX_ERRORTYPE OMXVideoDecoderBase::SetNativeBufferMode(OMX_PTR pStructure) {
1078    return this->SetNativeBufferModeSpecific(pStructure);
1079}
1080
1081OMX_ERRORTYPE OMXVideoDecoderBase::GetNativeBufferModeSpecific(OMX_PTR) {
1082    LOGE("GetNativeBufferMode is not implemented");
1083    return OMX_ErrorNotImplemented;
1084}
1085
1086OMX_ERRORTYPE OMXVideoDecoderBase::SetNativeBufferModeSpecific(OMX_PTR pStructure) {
1087    OMX_ERRORTYPE ret;
1088    EnableAndroidNativeBuffersParams *param = (EnableAndroidNativeBuffersParams*)pStructure;
1089
1090    CHECK_TYPE_HEADER(param);
1091    CHECK_PORT_INDEX_RANGE(param);
1092    CHECK_SET_PARAM_STATE();
1093
1094    PortVideo *port = NULL;
1095    port = static_cast<PortVideo *>(this->ports[OUTPORT_INDEX]);
1096    OMX_PARAM_PORTDEFINITIONTYPE port_def;
1097    memcpy(&port_def,port->GetPortDefinition(),sizeof(port_def));
1098
1099    if (!param->enable) {
1100        mWorkingMode = RAWDATA_MODE;
1101        // If it is fallback from native mode the color format has been
1102        // already set to INTEL format.
1103        // We need to set back the default color format and Native stuff.
1104        port_def.format.video.eColorFormat = OMX_COLOR_FormatYUV420SemiPlanar;
1105        port_def.format.video.pNativeRender = NULL;
1106        port_def.format.video.pNativeWindow = NULL;
1107        port->SetPortDefinition(&port_def,true);
1108        return OMX_ErrorNone;
1109    }
1110
1111    mWorkingMode = GRAPHICBUFFER_MODE;
1112    port_def.nBufferCountMin = mNativeBufferCount;
1113    if (mEnableAdaptivePlayback) {
1114        SetMaxOutputBufferCount(&port_def);
1115    } else {
1116        port_def.nBufferCountActual = mNativeBufferCount;
1117    }
1118    port_def.format.video.cMIMEType = (OMX_STRING)VA_VED_RAW_MIME_TYPE;
1119    port_def.format.video.eColorFormat = OMX_INTEL_COLOR_FormatYUV420PackedSemiPlanar;
1120    port_def.format.video.nFrameHeight = port_def.format.video.nFrameHeight;
1121
1122    port_def.format.video.eColorFormat = GetOutputColorFormat(
1123                        port_def.format.video.nFrameWidth);
1124    port->SetPortDefinition(&port_def,true);
1125
1126    return OMX_ErrorNone;
1127}
1128
1129OMX_ERRORTYPE OMXVideoDecoderBase::GetStoreMetaDataMode(OMX_PTR) {
1130    ALOGE("GetMetaDataMode is not implemented");
1131    return OMX_ErrorNotImplemented;
1132}
1133
1134OMX_ERRORTYPE OMXVideoDecoderBase::SetStoreMetaDataMode(OMX_PTR pStructure) {
1135#ifndef USE_META_DATA
1136    OMX_PARAM_PORTDEFINITIONTYPE defInput;
1137    memcpy(&defInput,
1138        this->ports[INPORT_INDEX]->GetPortDefinition(),
1139        sizeof(defInput));
1140    if (defInput.format.video.eCompressionFormat == OMX_VIDEO_CodingVP9) {
1141        ALOGE("SetMetaDataMode for VP9 is not implemented");
1142        return OMX_ErrorNotImplemented;
1143    }
1144#endif
1145    OMX_ERRORTYPE ret;
1146    StoreMetaDataInBuffersParams *param = (StoreMetaDataInBuffersParams*)pStructure;
1147
1148    CHECK_TYPE_HEADER(param);
1149    CHECK_PORT_INDEX(param, OUTPORT_INDEX);
1150    CHECK_SET_PARAM_STATE();
1151
1152    if (!param->bStoreMetaData) {
1153        mAPMode = LEGACY_MODE;
1154        // Don't return error which otherwise may cause framework crash
1155        return OMX_ErrorNone;
1156    }
1157    mAPMode = METADATA_MODE;
1158    ALOGI("We are in meta data mode!!!");
1159
1160    return OMX_ErrorNone;
1161}
1162
1163OMX_ERRORTYPE OMXVideoDecoderBase::GetDecoderRotation(OMX_PTR) {
1164    return OMX_ErrorBadParameter;
1165}
1166OMX_ERRORTYPE OMXVideoDecoderBase::SetDecoderRotation(OMX_PTR pStructure) {
1167    CHECK_SET_PARAM_STATE();
1168    int32_t rotationDegrees = 0;
1169
1170    if (pStructure) {
1171        rotationDegrees = *(static_cast<int32_t*>(pStructure));
1172        mRotationDegrees = rotationDegrees;
1173        LOGI("Rotation Degree = %d", rotationDegrees);
1174        return OMX_ErrorNone;
1175    } else {
1176        return OMX_ErrorBadParameter;
1177    }
1178}
1179
1180#ifdef TARGET_HAS_ISV
1181OMX_ERRORTYPE OMXVideoDecoderBase::GetDecoderVppBufferNum(OMX_PTR) {
1182    return OMX_ErrorBadParameter;
1183}
1184OMX_ERRORTYPE OMXVideoDecoderBase::SetDecoderVppBufferNum(OMX_PTR pStructure) {
1185    CHECK_SET_PARAM_STATE();
1186    int32_t num = 0;
1187
1188    num = *(static_cast<int32_t*>(pStructure));
1189    mVppBufferNum = num;
1190
1191    return OMX_ErrorNone;
1192}
1193#endif
1194
1195OMX_ERRORTYPE OMXVideoDecoderBase::GetDecoderOutputCropSpecific(OMX_PTR pStructure) {
1196    OMX_ERRORTYPE ret;
1197    OMX_CONFIG_RECTTYPE *rectParams = (OMX_CONFIG_RECTTYPE *)pStructure;
1198
1199    CHECK_TYPE_HEADER(rectParams);
1200
1201    if (rectParams->nPortIndex != OUTPORT_INDEX) {
1202        return OMX_ErrorUndefined;
1203    }
1204
1205    PortVideo *port = NULL;
1206    port = static_cast<PortVideo *>(this->ports[OUTPORT_INDEX]);
1207    OMX_PARAM_PORTDEFINITIONTYPE port_def;
1208    memcpy(&port_def,port->GetPortDefinition(),sizeof(port_def));
1209
1210    const VideoFormatInfo *formatInfo = mVideoDecoder->getFormatInfo();
1211    if (formatInfo->valid == true) {
1212        rectParams->nLeft =  formatInfo->cropLeft;
1213        rectParams->nTop = formatInfo->cropTop;
1214        rectParams->nWidth = formatInfo->width - formatInfo->cropLeft - formatInfo->cropRight;
1215        rectParams->nHeight = formatInfo->height - formatInfo->cropTop - formatInfo->cropBottom;
1216        if (strcasecmp(formatInfo->mimeType,"video/avc") == 0 ||
1217            strcasecmp(formatInfo->mimeType,"video/h264") == 0) {
1218            rectParams->nHeight = formatInfo->height;
1219            rectParams->nWidth = formatInfo->width;
1220        }
1221
1222        // if port width parsed from extractor is not as same as from SPS/PPS nalu header,
1223        // align it.
1224        if (port_def.format.video.nFrameWidth != rectParams->nWidth) {
1225            port_def.format.video.nFrameWidth = rectParams->nWidth;
1226        }
1227        port->SetPortDefinition(&port_def,true);
1228        return OMX_ErrorNone;
1229    } else {
1230        return OMX_ErrorFormatNotDetected;
1231    }
1232}
1233
1234OMX_ERRORTYPE OMXVideoDecoderBase::SetDecoderOutputCropSpecific(OMX_PTR) {
1235    return OMX_ErrorUnsupportedSetting;
1236}
1237
1238OMX_ERRORTYPE OMXVideoDecoderBase::SetDecoderOutputCrop(OMX_PTR pStructure) {
1239    return this->SetDecoderOutputCropSpecific(pStructure);
1240}
1241
1242OMX_ERRORTYPE OMXVideoDecoderBase::GetDecoderOutputCrop(OMX_PTR pStructure) {
1243    return this->GetDecoderOutputCropSpecific(pStructure);
1244}
1245
1246
1247OMX_ERRORTYPE OMXVideoDecoderBase::SetCodecPriority(OMX_PTR pStructure) {
1248    OMX_ERRORTYPE ret;
1249    OMX_PARAM_U32TYPE *priorityParam = (OMX_PARAM_U32TYPE *)pStructure;
1250    mCodecPriority = priorityParam->nU32;
1251    return OMX_ErrorNone;
1252}
1253
1254
1255OMX_ERRORTYPE OMXVideoDecoderBase::GetCodecPriority(OMX_PTR pStructure) {
1256    OMX_ERRORTYPE ret;
1257    OMX_PARAM_U32TYPE *priorityParam = (OMX_PARAM_U32TYPE *)pStructure;
1258    CHECK_TYPE_HEADER(priorityParam);
1259    priorityParam->nU32 = mCodecPriority;
1260    return OMX_ErrorNone;
1261}
1262
1263
1264OMX_ERRORTYPE OMXVideoDecoderBase::SetDecoderOperatingRate(OMX_PTR pStructure) {
1265    OMX_ERRORTYPE ret;
1266    OMX_PARAM_U32TYPE *operatingRateParam = (OMX_PARAM_U32TYPE *)pStructure;
1267    CHECK_TYPE_HEADER(operatingRateParam);
1268    mOperatingRate = operatingRateParam->nU32;
1269    return OMX_ErrorNone;
1270}
1271
1272OMX_ERRORTYPE OMXVideoDecoderBase::GetDecoderOperatingRate(OMX_PTR pStructure) {
1273    OMX_ERRORTYPE ret;
1274    OMX_PARAM_U32TYPE *operatingRateParam = (OMX_PARAM_U32TYPE *)pStructure;
1275    CHECK_TYPE_HEADER(operatingRateParam);
1276    operatingRateParam->nU32 = mOperatingRate;
1277    return OMX_ErrorNone;
1278}
1279
1280OMX_ERRORTYPE OMXVideoDecoderBase::GetErrorReportMode(OMX_PTR) {
1281    LOGE("GetErrorReportMode is not implemented");
1282    return OMX_ErrorNotImplemented;
1283}
1284
1285OMX_ERRORTYPE OMXVideoDecoderBase::SetErrorReportMode(OMX_PTR pStructure) {
1286    OMX_ERRORTYPE ret;
1287
1288    OMX_VIDEO_CONFIG_INTEL_ERROR_REPORT *p = (OMX_VIDEO_CONFIG_INTEL_ERROR_REPORT *)pStructure;
1289    CHECK_TYPE_HEADER(p);
1290    CHECK_PORT_INDEX(p, OUTPORT_INDEX);
1291
1292    mErrorReportEnabled = p->bEnable;
1293    LOGD("Error reporting is %s", mErrorReportEnabled ? "enabled" : "disabled");
1294
1295    mVideoDecoder->enableErrorReport(mErrorReportEnabled);
1296    return OMX_ErrorNone;
1297}
1298
1299OMX_COLOR_FORMATTYPE OMXVideoDecoderBase::GetOutputColorFormat(int width) {
1300#ifndef VED_TILING
1301    return OMX_INTEL_COLOR_FormatYUV420PackedSemiPlanar;
1302#else
1303    if (width > 1280 && width <= 2048) {
1304        LOGI("HD Video and use tiled format");
1305        return OMX_INTEL_COLOR_FormatYUV420PackedSemiPlanar_Tiled;
1306    } else {
1307        return OMX_INTEL_COLOR_FormatYUV420PackedSemiPlanar;
1308    }
1309#endif
1310}
1311
1312OMX_ERRORTYPE OMXVideoDecoderBase::SetMaxOutputBufferCount(OMX_PARAM_PORTDEFINITIONTYPE *) {
1313    return OMX_ErrorNone;
1314}
1315
1316uint32_t OMXVideoDecoderBase::getStride(uint32_t width) {
1317    uint32_t stride = 0;
1318
1319    if (width <= 512)
1320        stride = 512;
1321    else if (width <= 1024)
1322        stride = 1024;
1323    else if (width <= 1280) {
1324        stride = 1280;
1325    } else if (width <= 2048)
1326        stride = 2048;
1327    else if (width <= 4096)
1328        stride = 4096;
1329    else
1330        stride = (width + 0x3f) & ~0x3f;
1331
1332    return stride;
1333}
1334