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
26static const char* VA_RAW_MIME_TYPE = "video/x-raw-va";
27static const uint32_t VA_COLOR_FORMAT = 0x7FA00E00;
28
29OMXVideoDecoderBase::OMXVideoDecoderBase()
30    : mRotationDegrees(0),
31#ifdef TARGET_HAS_ISV
32      mVppBufferNum(0),
33#endif
34      mVideoDecoder(NULL),
35      mNativeBufferCount(OUTPORT_NATIVE_BUFFER_COUNT),
36      mWorkingMode(RAWDATA_MODE),
37      mErrorReportEnabled (false) {
38      mOMXBufferHeaderTypePtrNum = 0;
39      memset(&mGraphicBufferParam, 0, sizeof(mGraphicBufferParam));
40}
41
42OMXVideoDecoderBase::~OMXVideoDecoderBase() {
43    releaseVideoDecoder(mVideoDecoder);
44
45    if (this->ports) {
46        if (this->ports[INPORT_INDEX]) {
47            delete this->ports[INPORT_INDEX];
48            this->ports[INPORT_INDEX] = NULL;
49        }
50
51        if (this->ports[OUTPORT_INDEX]) {
52            delete this->ports[OUTPORT_INDEX];
53            this->ports[OUTPORT_INDEX] = NULL;
54        }
55    }
56}
57
58OMX_ERRORTYPE OMXVideoDecoderBase::InitInputPort(void) {
59    this->ports[INPORT_INDEX] = new PortVideo;
60    if (this->ports[INPORT_INDEX] == NULL) {
61        return OMX_ErrorInsufficientResources;
62    }
63
64    PortVideo *port = static_cast<PortVideo *>(this->ports[INPORT_INDEX]);
65
66    // OMX_PARAM_PORTDEFINITIONTYPE
67    OMX_PARAM_PORTDEFINITIONTYPE paramPortDefinitionInput;
68    memset(&paramPortDefinitionInput, 0, sizeof(paramPortDefinitionInput));
69    SetTypeHeader(&paramPortDefinitionInput, sizeof(paramPortDefinitionInput));
70    paramPortDefinitionInput.nPortIndex = INPORT_INDEX;
71    paramPortDefinitionInput.eDir = OMX_DirInput;
72    paramPortDefinitionInput.nBufferCountActual = INPORT_ACTUAL_BUFFER_COUNT;
73    paramPortDefinitionInput.nBufferCountMin = INPORT_MIN_BUFFER_COUNT;
74    paramPortDefinitionInput.nBufferSize = INPORT_BUFFER_SIZE;
75    paramPortDefinitionInput.bEnabled = OMX_TRUE;
76    paramPortDefinitionInput.bPopulated = OMX_FALSE;
77    paramPortDefinitionInput.eDomain = OMX_PortDomainVideo;
78    paramPortDefinitionInput.format.video.cMIMEType = NULL; // to be overridden
79    paramPortDefinitionInput.format.video.pNativeRender = NULL;
80    paramPortDefinitionInput.format.video.nFrameWidth = 176;
81    paramPortDefinitionInput.format.video.nFrameHeight = 144;
82    paramPortDefinitionInput.format.video.nStride = 0;
83    paramPortDefinitionInput.format.video.nSliceHeight = 0;
84    paramPortDefinitionInput.format.video.nBitrate = 64000;
85    paramPortDefinitionInput.format.video.xFramerate = 15 << 16;
86    // TODO: check if we need to set bFlagErrorConcealment  to OMX_TRUE
87    paramPortDefinitionInput.format.video.bFlagErrorConcealment = OMX_FALSE;
88    paramPortDefinitionInput.format.video.eCompressionFormat = OMX_VIDEO_CodingUnused; // to be overridden
89    paramPortDefinitionInput.format.video.eColorFormat = OMX_COLOR_FormatUnused;
90    paramPortDefinitionInput.format.video.pNativeWindow = NULL;
91    paramPortDefinitionInput.bBuffersContiguous = OMX_FALSE;
92    paramPortDefinitionInput.nBufferAlignment = 0;
93
94    // Derived class must implement this interface and override any field if needed.
95    // eCompressionFormat and and cMIMEType must be overridden
96    InitInputPortFormatSpecific(&paramPortDefinitionInput);
97
98    port->SetPortDefinition(&paramPortDefinitionInput, true);
99
100    // OMX_VIDEO_PARAM_PORTFORMATTYPE
101    OMX_VIDEO_PARAM_PORTFORMATTYPE paramPortFormat;
102    memset(&paramPortFormat, 0, sizeof(paramPortFormat));
103    SetTypeHeader(&paramPortFormat, sizeof(paramPortFormat));
104    paramPortFormat.nPortIndex = INPORT_INDEX;
105    paramPortFormat.nIndex = 0;
106    paramPortFormat.eCompressionFormat = paramPortDefinitionInput.format.video.eCompressionFormat;
107    paramPortFormat.eColorFormat = paramPortDefinitionInput.format.video.eColorFormat;
108    paramPortFormat.xFramerate = paramPortDefinitionInput.format.video.xFramerate;
109
110    port->SetPortVideoParam(&paramPortFormat, true);
111
112    return OMX_ErrorNone;
113}
114
115
116OMX_ERRORTYPE OMXVideoDecoderBase::InitOutputPort(void) {
117    this->ports[OUTPORT_INDEX] = new PortVideo;
118    if (this->ports[OUTPORT_INDEX] == NULL) {
119        return OMX_ErrorInsufficientResources;
120    }
121
122    PortVideo *port = static_cast<PortVideo *>(this->ports[OUTPORT_INDEX]);
123
124    // OMX_PARAM_PORTDEFINITIONTYPE
125    OMX_PARAM_PORTDEFINITIONTYPE paramPortDefinitionOutput;
126
127    memset(&paramPortDefinitionOutput, 0, sizeof(paramPortDefinitionOutput));
128    SetTypeHeader(&paramPortDefinitionOutput, sizeof(paramPortDefinitionOutput));
129
130    paramPortDefinitionOutput.nPortIndex = OUTPORT_INDEX;
131    paramPortDefinitionOutput.eDir = OMX_DirOutput;
132    paramPortDefinitionOutput.nBufferCountActual = OUTPORT_ACTUAL_BUFFER_COUNT;
133    paramPortDefinitionOutput.nBufferCountMin = OUTPORT_MIN_BUFFER_COUNT;
134    paramPortDefinitionOutput.nBufferSize = sizeof(VideoRenderBuffer);
135
136    paramPortDefinitionOutput.bEnabled = OMX_TRUE;
137    paramPortDefinitionOutput.bPopulated = OMX_FALSE;
138    paramPortDefinitionOutput.eDomain = OMX_PortDomainVideo;
139    paramPortDefinitionOutput.format.video.cMIMEType = (OMX_STRING)VA_RAW_MIME_TYPE;
140    paramPortDefinitionOutput.format.video.pNativeRender = NULL;
141    paramPortDefinitionOutput.format.video.nFrameWidth = 176;
142    paramPortDefinitionOutput.format.video.nFrameHeight = 144;
143    paramPortDefinitionOutput.format.video.nStride = 176;
144    paramPortDefinitionOutput.format.video.nSliceHeight = 144;
145    paramPortDefinitionOutput.format.video.nBitrate = 64000;
146    paramPortDefinitionOutput.format.video.xFramerate = 15 << 16;
147    paramPortDefinitionOutput.format.video.bFlagErrorConcealment = OMX_FALSE;
148    paramPortDefinitionOutput.format.video.eCompressionFormat = OMX_VIDEO_CodingUnused;
149    paramPortDefinitionOutput.format.video.eColorFormat = OMX_COLOR_FormatYUV420SemiPlanar;
150    paramPortDefinitionOutput.format.video.pNativeWindow = NULL;
151    paramPortDefinitionOutput.bBuffersContiguous = OMX_FALSE;
152    paramPortDefinitionOutput.nBufferAlignment = 0;
153
154    // no format specific to initialize output port
155    InitOutputPortFormatSpecific(&paramPortDefinitionOutput);
156
157    port->SetPortDefinition(&paramPortDefinitionOutput, true);
158
159    // OMX_VIDEO_PARAM_PORTFORMATTYPE
160    OMX_VIDEO_PARAM_PORTFORMATTYPE paramPortFormat;
161    SetTypeHeader(&paramPortFormat, sizeof(paramPortFormat));
162    paramPortFormat.nPortIndex = OUTPORT_INDEX;
163    paramPortFormat.nIndex = 0;
164    paramPortFormat.eCompressionFormat = paramPortDefinitionOutput.format.video.eCompressionFormat;
165    paramPortFormat.eColorFormat = paramPortDefinitionOutput.format.video.eColorFormat;
166    paramPortFormat.xFramerate = paramPortDefinitionOutput.format.video.xFramerate;
167
168    port->SetPortVideoParam(&paramPortFormat, true);
169
170    return OMX_ErrorNone;
171}
172
173OMX_ERRORTYPE OMXVideoDecoderBase::InitOutputPortFormatSpecific(OMX_PARAM_PORTDEFINITIONTYPE *) {
174    // no format specific to initialize output port
175    return OMX_ErrorNone;
176}
177
178OMX_ERRORTYPE OMXVideoDecoderBase::ProcessorInit(void) {
179    OMX_ERRORTYPE ret;
180    ret = OMXComponentCodecBase::ProcessorInit();
181    CHECK_RETURN_VALUE("OMXComponentCodecBase::ProcessorInit");
182
183    if (mVideoDecoder == NULL) {
184        LOGE("ProcessorInit: Video decoder is not created.");
185        return OMX_ErrorDynamicResourcesUnavailable;
186    }
187
188    VideoConfigBuffer configBuffer;
189    ret = PrepareConfigBuffer(&configBuffer);
190    CHECK_RETURN_VALUE("PrepareConfigBuffer");
191
192    //pthread_mutex_lock(&mSerializationLock);
193    Decode_Status status = mVideoDecoder->start(&configBuffer);
194    //pthread_mutex_unlock(&mSerializationLock);
195
196    if (status != DECODE_SUCCESS) {
197        return TranslateDecodeStatus(status);
198    }
199
200    return OMX_ErrorNone;
201}
202
203OMX_ERRORTYPE OMXVideoDecoderBase::ProcessorReset(void) {
204    OMX_ERRORTYPE ret;
205    VideoConfigBuffer configBuffer;
206    // reset the configbuffer and set it to mix
207    ret = PrepareConfigBuffer(&configBuffer);
208    CHECK_RETURN_VALUE("PrepareConfigBuffer");
209    mVideoDecoder->reset(&configBuffer);
210    return OMX_ErrorNone;
211}
212
213
214OMX_ERRORTYPE OMXVideoDecoderBase::ProcessorDeinit(void) {
215    if (mWorkingMode != GRAPHICBUFFER_MODE) {
216        if (mVideoDecoder == NULL) {
217            LOGE("ProcessorDeinit: Video decoder is not created.");
218            return OMX_ErrorDynamicResourcesUnavailable;
219        }
220        mVideoDecoder->stop();
221    }
222    mOMXBufferHeaderTypePtrNum = 0;
223    memset(&mGraphicBufferParam, 0, sizeof(mGraphicBufferParam));
224    mRotationDegrees = 0;
225#ifdef TARGET_HAS_ISV
226    mVppBufferNum = 0;
227#endif
228    return OMXComponentCodecBase::ProcessorDeinit();
229}
230
231OMX_ERRORTYPE OMXVideoDecoderBase::ProcessorStart(void) {
232    return OMXComponentCodecBase::ProcessorStart();
233}
234
235OMX_ERRORTYPE OMXVideoDecoderBase::ProcessorStop(void) {
236    // There is no need to return all retained buffers as we don't accumulate buffer
237    //this->ports[INPORT_INDEX]->ReturnAllRetainedBuffers();
238
239    // TODO: this is new code
240    ProcessorFlush(OMX_ALL);
241    if (mWorkingMode == GRAPHICBUFFER_MODE) {
242        // for GRAPHICBUFFER_MODE mode, va_destroySurface need to lock the graphicbuffer,
243        // Make sure va_destroySurface is called(ExecutingToIdle) before graphicbuffer is freed(IdleToLoaded).
244        if (mVideoDecoder == NULL) {
245            LOGE("ProcessorStop: Video decoder is not created.");
246            return OMX_ErrorDynamicResourcesUnavailable;
247        }
248        mVideoDecoder->stop();
249    }
250    return OMXComponentCodecBase::ProcessorStop();
251}
252
253OMX_ERRORTYPE OMXVideoDecoderBase::ProcessorPause(void) {
254    return OMXComponentCodecBase::ProcessorPause();
255}
256
257OMX_ERRORTYPE OMXVideoDecoderBase::ProcessorResume(void) {
258    return OMXComponentCodecBase::ProcessorResume();
259}
260
261OMX_ERRORTYPE OMXVideoDecoderBase::ProcessorFlush(OMX_U32 portIndex) {
262    LOGI("Flushing port# %u.", portIndex);
263    if (mVideoDecoder == NULL) {
264        LOGE("ProcessorFlush: Video decoder is not created.");
265        return OMX_ErrorDynamicResourcesUnavailable;
266    }
267
268    // Portbase has returned all retained buffers.
269    if (portIndex == INPORT_INDEX || portIndex == OMX_ALL) {
270        //pthread_mutex_lock(&mSerializationLock);
271        LOGW("Flushing video pipeline.");
272        mVideoDecoder->flush();
273        //pthread_mutex_unlock(&mSerializationLock);
274    }
275    // TODO: do we need to flush output port?
276    return OMX_ErrorNone;
277}
278
279OMX_ERRORTYPE OMXVideoDecoderBase::ProcessorPreFreeBuffer(OMX_U32 nPortIndex, OMX_BUFFERHEADERTYPE * pBuffer) {
280    if (mWorkingMode == GRAPHICBUFFER_MODE)
281        return OMX_ErrorNone;
282
283    if (nPortIndex == OUTPORT_INDEX && pBuffer->pPlatformPrivate) {
284        VideoRenderBuffer *p = (VideoRenderBuffer *)pBuffer->pPlatformPrivate;
285        p->renderDone = true;
286        pBuffer->pPlatformPrivate = NULL;
287    }
288    return OMX_ErrorNone;
289}
290
291 OMX_ERRORTYPE OMXVideoDecoderBase::ProcessorPreFillBuffer(OMX_BUFFERHEADERTYPE* buffer) {
292    if (mWorkingMode == GRAPHICBUFFER_MODE && buffer->nOutputPortIndex == OUTPORT_INDEX){
293        Decode_Status status;
294        if(mVideoDecoder == NULL){
295            LOGW("ProcessorPreFillBuffer: Video decoder is not created");
296            return OMX_ErrorDynamicResourcesUnavailable;
297        }
298        status = mVideoDecoder->signalRenderDone(buffer->pBuffer);
299
300        if (status != DECODE_SUCCESS) {
301            LOGW("ProcessorPreFillBuffer:: signalRenderDone return error");
302            return TranslateDecodeStatus(status);
303        }
304    } else if (buffer->pPlatformPrivate && buffer->nOutputPortIndex == OUTPORT_INDEX){
305        VideoRenderBuffer *p = (VideoRenderBuffer *)buffer->pPlatformPrivate;
306        p->renderDone = true;
307        buffer->pPlatformPrivate = NULL;
308    }
309    return OMX_ErrorNone;
310}
311
312OMX_ERRORTYPE OMXVideoDecoderBase::ProcessorProcess(
313    OMX_BUFFERHEADERTYPE ***pBuffers,
314    buffer_retain_t *retains,
315    OMX_U32) {
316
317    OMX_ERRORTYPE ret;
318    Decode_Status status;
319    OMX_BOOL isResolutionChange = OMX_FALSE;
320    // fill render buffer without draining decoder output queue
321    ret = FillRenderBuffer(pBuffers[OUTPORT_INDEX], &retains[OUTPORT_INDEX], 0, &isResolutionChange);
322    if (ret == OMX_ErrorNone) {
323        retains[INPORT_INDEX] = BUFFER_RETAIN_GETAGAIN;
324        if (isResolutionChange) {
325            HandleFormatChange();
326        }
327        // TODO: continue decoding
328        return ret;
329    } else if (ret != OMX_ErrorNotReady) {
330        return ret;
331    }
332
333    VideoDecodeBuffer decodeBuffer;
334    // PrepareDecodeBuffer will set retain to either BUFFER_RETAIN_GETAGAIN or BUFFER_RETAIN_NOT_RETAIN
335    ret = PrepareDecodeBuffer(*pBuffers[INPORT_INDEX], &retains[INPORT_INDEX], &decodeBuffer);
336    if (ret == OMX_ErrorNotReady) {
337        retains[OUTPORT_INDEX] = BUFFER_RETAIN_GETAGAIN;
338        return OMX_ErrorNone;
339    } else if (ret != OMX_ErrorNone) {
340        return ret;
341    }
342
343    if (decodeBuffer.size != 0) {
344        //pthread_mutex_lock(&mSerializationLock);
345        status = mVideoDecoder->decode(&decodeBuffer);
346        //pthread_mutex_unlock(&mSerializationLock);
347
348        if (status == DECODE_FORMAT_CHANGE) {
349            ret = HandleFormatChange();
350            CHECK_RETURN_VALUE("HandleFormatChange");
351            ((*pBuffers[OUTPORT_INDEX]))->nFilledLen = 0;
352            retains[OUTPORT_INDEX] = BUFFER_RETAIN_GETAGAIN;
353            retains[INPORT_INDEX] = BUFFER_RETAIN_GETAGAIN;
354            // real dynamic resolution change will be handled later
355            // Here is just a temporary workaround
356            // don't use the output buffer if format is changed.
357            return OMX_ErrorNone;
358        } else if (status == DECODE_NO_CONFIG) {
359            LOGW("Decoder returns DECODE_NO_CONFIG.");
360            retains[OUTPORT_INDEX] = BUFFER_RETAIN_GETAGAIN;
361            return OMX_ErrorNone;
362        } else if (status == DECODE_NO_REFERENCE) {
363            LOGW("Decoder returns DECODE_NO_REFERENCE.");
364            //retains[OUTPORT_INDEX] = BUFFER_RETAIN_GETAGAIN;
365            //return OMX_ErrorNone;
366        } else if (status == DECODE_MULTIPLE_FRAME){
367            if (decodeBuffer.ext != NULL && decodeBuffer.ext->extType == PACKED_FRAME_TYPE && decodeBuffer.ext->extData != NULL) {
368                PackedFrameData* nextFrame = (PackedFrameData*)decodeBuffer.ext->extData;
369                (*pBuffers[INPORT_INDEX])->nOffset += nextFrame->offSet;
370                (*pBuffers[INPORT_INDEX])->nTimeStamp = nextFrame->timestamp;
371                (*pBuffers[INPORT_INDEX])->nFilledLen -= nextFrame->offSet;
372                retains[INPORT_INDEX] = BUFFER_RETAIN_GETAGAIN;
373                LOGW("Find multiple frames in a buffer, next frame offset = %d, timestamp = %lld", (*pBuffers[INPORT_INDEX])->nOffset, (*pBuffers[INPORT_INDEX])->nTimeStamp);
374            }
375        }
376        else if (status != DECODE_SUCCESS && status != DECODE_FRAME_DROPPED) {
377            if (checkFatalDecoderError(status)) {
378                return TranslateDecodeStatus(status);
379            } else {
380                // For decoder errors that could be omitted,  not throw error and continue to decode.
381                TranslateDecodeStatus(status);
382
383                ((*pBuffers[OUTPORT_INDEX]))->nFilledLen = 0;
384
385                // Do not return, and try to drain the output queue
386                // retains[OUTPORT_INDEX] = BUFFER_RETAIN_GETAGAIN;
387                // return OMX_ErrorNone;
388            }
389        }
390    }
391    // drain the decoder output queue when in EOS state and fill the render buffer
392    ret = FillRenderBuffer(pBuffers[OUTPORT_INDEX], &retains[OUTPORT_INDEX],
393            ((*pBuffers[INPORT_INDEX]))->nFlags,&isResolutionChange);
394
395    if (isResolutionChange) {
396        HandleFormatChange();
397    }
398
399    bool inputEoS = ((*pBuffers[INPORT_INDEX])->nFlags & OMX_BUFFERFLAG_EOS);
400    bool outputEoS = ((*pBuffers[OUTPORT_INDEX])->nFlags & OMX_BUFFERFLAG_EOS);
401    // if output port is not eos, retain the input buffer until all the output buffers are drained.
402    if (inputEoS && !outputEoS) {
403        retains[INPORT_INDEX] = BUFFER_RETAIN_GETAGAIN;
404        // the input buffer is retained for draining purpose. Set nFilledLen to 0 so buffer will not be decoded again.
405        (*pBuffers[INPORT_INDEX])->nFilledLen = 0;
406    }
407
408    if (ret == OMX_ErrorNotReady) {
409        retains[OUTPORT_INDEX] = BUFFER_RETAIN_GETAGAIN;
410        ret = OMX_ErrorNone;
411    }
412
413    return ret;
414}
415
416bool OMXVideoDecoderBase::IsAllBufferAvailable(void) {
417    bool b = ComponentBase::IsAllBufferAvailable();
418    if (b == false) {
419        return false;
420    }
421
422    PortVideo *port = NULL;
423    port = static_cast<PortVideo *>(this->ports[OUTPORT_INDEX]);
424    const OMX_PARAM_PORTDEFINITIONTYPE* port_def = port->GetPortDefinition();
425     // if output port is disabled, retain the input buffer
426    if (!port_def->bEnabled) {
427        return false;
428    }
429
430    if (mVideoDecoder) {
431        return mVideoDecoder->checkBufferAvail();
432    }
433    return false;
434}
435
436OMX_ERRORTYPE OMXVideoDecoderBase::PrepareConfigBuffer(VideoConfigBuffer *p) {
437    // default config buffer preparation
438    memset(p, 0, sizeof(VideoConfigBuffer));
439
440    const OMX_PARAM_PORTDEFINITIONTYPE *paramPortDefinitionInput = this->ports[INPORT_INDEX]->GetPortDefinition();
441    if (paramPortDefinitionInput == NULL) {
442        return OMX_ErrorBadParameter;
443    }
444
445    if (mWorkingMode == GRAPHICBUFFER_MODE) {
446        p->surfaceNumber = mOMXBufferHeaderTypePtrNum;
447        for (uint32_t i = 0; i < mOMXBufferHeaderTypePtrNum; i++){
448            OMX_BUFFERHEADERTYPE *buffer_hdr = mOMXBufferHeaderTypePtrArray[i];
449            p->graphicBufferHandler[i] = buffer_hdr->pBuffer;
450            LOGV("PrepareConfigBuffer bufferid = %p, handle = %p", buffer_hdr, buffer_hdr->pBuffer);
451        }
452        p->flag |= USE_NATIVE_GRAPHIC_BUFFER;
453        p->graphicBufferStride = mGraphicBufferParam.graphicBufferStride;
454        p->graphicBufferColorFormat = mGraphicBufferParam.graphicBufferColorFormat;
455        p->graphicBufferWidth = mGraphicBufferParam.graphicBufferWidth;
456        p->graphicBufferHeight = mGraphicBufferParam.graphicBufferHeight;
457        if (p->graphicBufferColorFormat == OMX_INTEL_COLOR_FormatYUV420PackedSemiPlanar_Tiled
458#ifdef USE_GEN_HW
459            || p->graphicBufferColorFormat == HAL_PIXEL_FORMAT_NV12_X_TILED_INTEL
460#endif
461        )
462            p->flag |= USE_TILING_MEMORY;
463
464        if (mEnableAdaptivePlayback)
465            p->flag |= WANT_ADAPTIVE_PLAYBACK;
466
467        PortVideo *port = NULL;
468        port = static_cast<PortVideo *>(this->ports[INPORT_INDEX]);
469        OMX_PARAM_PORTDEFINITIONTYPE port_def;
470        memcpy(&port_def, port->GetPortDefinition(), sizeof(port_def));
471
472        if (port_def.format.video.pNativeWindow != NULL) {
473            p->nativeWindow = port_def.format.video.pNativeWindow;
474            LOGD("NativeWindow = %p", p->nativeWindow);
475        }
476
477    }
478
479    p->rotationDegrees = mRotationDegrees;
480#ifdef TARGET_HAS_ISV
481    p->vppBufferNum = mVppBufferNum;
482#endif
483    p->width = paramPortDefinitionInput->format.video.nFrameWidth;
484    p->height = paramPortDefinitionInput->format.video.nFrameHeight;
485
486    return OMX_ErrorNone;
487}
488
489OMX_ERRORTYPE OMXVideoDecoderBase::PrepareDecodeBuffer(OMX_BUFFERHEADERTYPE *buffer, buffer_retain_t *retain, VideoDecodeBuffer *p) {
490    // default decode buffer preparation
491    memset(p, 0, sizeof(VideoDecodeBuffer));
492    if (buffer->nFilledLen == 0) {
493        LOGW("Len of filled data to decode is 0.");
494        return OMX_ErrorNone; //OMX_ErrorBadParameter;
495    }
496
497    if (buffer->pBuffer == NULL) {
498        LOGE("Buffer to decode is empty.");
499        return OMX_ErrorBadParameter;
500    }
501
502    if (buffer->nFlags & OMX_BUFFERFLAG_CODECCONFIG) {
503        LOGI("Buffer has OMX_BUFFERFLAG_CODECCONFIG flag.");
504    }
505
506    if (buffer->nFlags & OMX_BUFFERFLAG_DECODEONLY) {
507        // TODO: Handle OMX_BUFFERFLAG_DECODEONLY : drop the decoded frame without rendering it.
508        LOGW("Buffer has OMX_BUFFERFLAG_DECODEONLY flag.");
509    }
510
511    p->data = buffer->pBuffer + buffer->nOffset;
512    p->size = buffer->nFilledLen;
513    p->timeStamp = buffer->nTimeStamp;
514    if (buffer->nFlags & (OMX_BUFFERFLAG_ENDOFFRAME | OMX_BUFFERFLAG_EOS)) {
515        // TODO: OMX_BUFFERFLAG_ENDOFFRAME can be used to indicate end of a NAL unit.
516        // setting this flag may cause corruption if buffer does not contain end-of-frame data.
517        p->flag = HAS_COMPLETE_FRAME;
518    }
519
520    if (buffer->nFlags & OMX_BUFFERFLAG_SYNCFRAME) {
521        p->flag |= IS_SYNC_FRAME;
522    }
523
524    if (buffer->pInputPortPrivate) {
525        uint32_t degree = 0;
526        memcpy ((void *) &degree, buffer->pInputPortPrivate, sizeof(uint32_t));
527        p->rotationDegrees = degree;
528        LOGV("rotationDegrees = %d", p->rotationDegrees);
529    } else {
530        p->rotationDegrees = mRotationDegrees;
531    }
532
533    *retain= BUFFER_RETAIN_NOT_RETAIN;
534    return OMX_ErrorNone;
535}
536
537OMX_ERRORTYPE OMXVideoDecoderBase::FillRenderBuffer(OMX_BUFFERHEADERTYPE **pBuffer, buffer_retain_t *retain,
538    OMX_U32 inportBufferFlags, OMX_BOOL *isResolutionChange) {
539    OMX_BUFFERHEADERTYPE *buffer = *pBuffer;
540    OMX_BUFFERHEADERTYPE *buffer_orign = buffer;
541    VideoErrorBuffer *ErrBufPtr = NULL;
542
543    if (mWorkingMode != GRAPHICBUFFER_MODE && buffer->pPlatformPrivate) {
544        VideoRenderBuffer *p = (VideoRenderBuffer *)buffer->pPlatformPrivate;
545        p->renderDone = true;
546        buffer->pPlatformPrivate = NULL;
547    }
548
549    if (mWorkingMode == GRAPHICBUFFER_MODE && mErrorReportEnabled) {
550        if (buffer->pOutputPortPrivate == NULL)
551            LOGE("The App doesn't provide the output buffer for error reporting");
552        else
553            ErrBufPtr = (VideoErrorBuffer *)buffer->pOutputPortPrivate;
554    }
555
556    bool draining = (inportBufferFlags & OMX_BUFFERFLAG_EOS);
557    //pthread_mutex_lock(&mSerializationLock);
558    const VideoRenderBuffer *renderBuffer = mVideoDecoder->getOutput(draining, ErrBufPtr);
559    //pthread_mutex_unlock(&mSerializationLock);
560    if (renderBuffer == NULL) {
561        buffer->nFilledLen = 0;
562        if (draining) {
563            LOGI("output EOS received");
564            buffer->nFlags = OMX_BUFFERFLAG_EOS;
565            return OMX_ErrorNone;
566        }
567        return OMX_ErrorNotReady;
568    }
569
570    if (mWorkingMode == GRAPHICBUFFER_MODE) {
571        buffer = *pBuffer = mOMXBufferHeaderTypePtrArray[renderBuffer->graphicBufferIndex];
572     }
573
574    buffer->nFlags = OMX_BUFFERFLAG_ENDOFFRAME;
575#ifdef DEINTERLACE_EXT
576    if (renderBuffer->scanFormat & (VA_TOP_FIELD | VA_BOTTOM_FIELD))
577        buffer->nFlags |= OMX_BUFFERFLAG_TFF;
578#endif
579    buffer->nTimeStamp = renderBuffer->timeStamp;
580
581    if (renderBuffer->flag & IS_EOS) {
582        buffer->nFlags |= OMX_BUFFERFLAG_EOS;
583    }
584    *isResolutionChange = (renderBuffer->flag & IS_RESOLUTION_CHANGE)? OMX_TRUE: OMX_FALSE;
585
586    if (mWorkingMode == GRAPHICBUFFER_MODE) {
587        if (buffer_orign != buffer) {
588            VideoErrorBuffer *ErrBufOutPtr = NULL;
589            ErrBufOutPtr = (VideoErrorBuffer *)buffer->pOutputPortPrivate;
590            if (ErrBufPtr && ErrBufOutPtr) {
591                memcpy(ErrBufOutPtr, ErrBufPtr, sizeof(VideoErrorBuffer));
592                memset(ErrBufPtr, 0, sizeof(VideoErrorBuffer));
593            }
594            *retain = BUFFER_RETAIN_OVERRIDDEN;
595        }
596         buffer->nFilledLen = sizeof(OMX_U8*);
597    } else {
598        uint32_t size = 0;
599        Decode_Status status = mVideoDecoder->getRawDataFromSurface(const_cast<VideoRenderBuffer *>(renderBuffer), buffer->pBuffer + buffer->nOffset, &size, false);
600        if (status != DECODE_SUCCESS) {
601            return TranslateDecodeStatus(status);
602        }
603        buffer->nFilledLen = size;
604        buffer->pPlatformPrivate = (void *)renderBuffer;
605    }
606
607    return OMX_ErrorNone;
608}
609
610OMX_ERRORTYPE OMXVideoDecoderBase::HandleFormatChange(void) {
611    LOGW("Video format is changed.");
612    //pthread_mutex_lock(&mSerializationLock);
613    const VideoFormatInfo *formatInfo = mVideoDecoder->getFormatInfo();
614    //pthread_mutex_unlock(&mSerializationLock);
615
616    // Sync port definition as it may change.
617    OMX_PARAM_PORTDEFINITIONTYPE paramPortDefinitionInput, paramPortDefinitionOutput;
618
619    memcpy(&paramPortDefinitionInput,
620        this->ports[INPORT_INDEX]->GetPortDefinition(),
621        sizeof(paramPortDefinitionInput));
622
623    memcpy(&paramPortDefinitionOutput,
624        this->ports[OUTPORT_INDEX]->GetPortDefinition(),
625        sizeof(paramPortDefinitionOutput));
626
627    uint32_t width = formatInfo->width;
628    uint32_t height = formatInfo->height;
629    uint32_t stride = formatInfo->width;
630    uint32_t sliceHeight = formatInfo->height;
631
632    uint32_t widthCropped = formatInfo->width - formatInfo->cropLeft - formatInfo->cropRight;
633    uint32_t heightCropped = formatInfo->height - formatInfo->cropTop - formatInfo->cropBottom;
634    uint32_t strideCropped = widthCropped;
635    uint32_t sliceHeightCropped = heightCropped;
636    int force_realloc = 0;
637    bool isVP8 = false;
638
639#ifdef TARGET_HAS_ISV
640    LOGI("============== mVppBufferNum = %d\n", mVppBufferNum);
641    if (paramPortDefinitionOutput.nBufferCountActual - mVppBufferNum < formatInfo->actualBufferNeeded) {
642#else
643    if (paramPortDefinitionOutput.nBufferCountActual < formatInfo->actualBufferNeeded) {
644#endif
645        if (mWorkingMode == GRAPHICBUFFER_MODE) {
646            LOGV("output port buffer number is not enough: %d to %d",
647                 paramPortDefinitionOutput.nBufferCountActual,
648                 formatInfo->actualBufferNeeded);
649            paramPortDefinitionOutput.nBufferCountActual = mNativeBufferCount = formatInfo->actualBufferNeeded;
650            paramPortDefinitionOutput.nBufferCountMin = mNativeBufferCount;
651            force_realloc = 1;
652        }
653    }
654
655    LOGV("Original size = %u x %u, new size = %d x %d, cropped size = %d x %d",
656        paramPortDefinitionInput.format.video.nFrameWidth,
657        paramPortDefinitionInput.format.video.nFrameHeight,
658        width, height, widthCropped, heightCropped);
659
660    if (paramPortDefinitionInput.format.video.eCompressionFormat == OMX_VIDEO_CodingVP8) {
661        isVP8 = true;
662    }
663
664    if (!force_realloc &&
665        widthCropped == paramPortDefinitionOutput.format.video.nFrameWidth &&
666        heightCropped == paramPortDefinitionOutput.format.video.nFrameHeight) {
667        if (mWorkingMode == RAWDATA_MODE) {
668            LOGW("Change of portsetting is not reported as size is not changed.");
669            return OMX_ErrorNone;
670        }
671    }
672
673    paramPortDefinitionInput.format.video.nFrameWidth = width;
674    paramPortDefinitionInput.format.video.nFrameHeight = height;
675    paramPortDefinitionInput.format.video.nStride = stride;
676    paramPortDefinitionInput.format.video.nSliceHeight = sliceHeight;
677
678    if (mWorkingMode == RAWDATA_MODE) {
679        paramPortDefinitionOutput.format.video.nFrameWidth = widthCropped;
680        paramPortDefinitionOutput.format.video.nFrameHeight = heightCropped;
681        paramPortDefinitionOutput.format.video.nStride = strideCropped;
682        paramPortDefinitionOutput.format.video.nSliceHeight = sliceHeightCropped;
683    } else if (mWorkingMode == GRAPHICBUFFER_MODE) {
684        // when the width and height ES parse are not larger than allocated graphic buffer in outport,
685        // there is no need to reallocate graphic buffer,just report the crop info to omx client
686        if (!force_realloc && width <= formatInfo->surfaceWidth && height <= formatInfo->surfaceHeight) {
687            this->ports[INPORT_INDEX]->SetPortDefinition(&paramPortDefinitionInput, true);
688            this->ports[OUTPORT_INDEX]->ReportOutputCrop();
689            return OMX_ErrorNone;
690        }
691
692        if (isVP8 || width > formatInfo->surfaceWidth ||  height > formatInfo->surfaceHeight) {
693            // update the real decoded resolution to outport instead of display resolution for graphic buffer reallocation
694            // when the width and height parsed from ES are larger than allocated graphic buffer in outport,
695            paramPortDefinitionOutput.format.video.nFrameWidth = width;
696            paramPortDefinitionOutput.format.video.nFrameHeight = height;
697            paramPortDefinitionOutput.format.video.eColorFormat = GetOutputColorFormat(
698                    paramPortDefinitionOutput.format.video.nFrameWidth);
699            paramPortDefinitionOutput.format.video.nStride = stride;
700            paramPortDefinitionOutput.format.video.nSliceHeight = sliceHeight;
701       }
702    }
703
704    paramPortDefinitionOutput.bEnabled = (OMX_BOOL)false;
705    mOMXBufferHeaderTypePtrNum = 0;
706    memset(&mGraphicBufferParam, 0, sizeof(mGraphicBufferParam));
707
708    this->ports[INPORT_INDEX]->SetPortDefinition(&paramPortDefinitionInput, true);
709    this->ports[OUTPORT_INDEX]->SetPortDefinition(&paramPortDefinitionOutput, true);
710
711    if (mWorkingMode == GRAPHICBUFFER_MODE) {
712        // Make sure va_destroySurface is called before graphicbuffer is freed in case of port setting changed
713        mVideoDecoder->freeSurfaceBuffers();
714
715        // Also make sure all the reference frames are flushed
716        ProcessorFlush(INPORT_INDEX);
717    }
718    this->ports[OUTPORT_INDEX]->ReportPortSettingsChanged();
719    return OMX_ErrorNone;
720}
721
722OMX_ERRORTYPE OMXVideoDecoderBase::TranslateDecodeStatus(Decode_Status status) {
723    switch (status) {
724        case DECODE_NEED_RESTART:
725            LOGE("Decoder returned DECODE_NEED_RESTART");
726            return (OMX_ERRORTYPE)OMX_ErrorIntelVideoNotPermitted;
727        case DECODE_NO_CONFIG:
728            LOGE("Decoder returned DECODE_NO_CONFIG");
729            return (OMX_ERRORTYPE)OMX_ErrorIntelMissingConfig;
730        case DECODE_NO_SURFACE:
731            LOGE("Decoder returned DECODE_NO_SURFACE");
732            return OMX_ErrorDynamicResourcesUnavailable;
733        case DECODE_NO_REFERENCE:
734            LOGE("Decoder returned DECODE_NO_REFERENCE");
735            return OMX_ErrorDynamicResourcesUnavailable; // TO DO
736        case DECODE_NO_PARSER:
737            LOGE("Decoder returned DECODE_NO_PARSER");
738            return OMX_ErrorDynamicResourcesUnavailable;
739        case DECODE_INVALID_DATA:
740            LOGE("Decoder returned DECODE_INVALID_DATA");
741            return OMX_ErrorBadParameter;
742        case DECODE_DRIVER_FAIL:
743            LOGE("Decoder returned DECODE_DRIVER_FAIL");
744            return OMX_ErrorHardware;
745        case DECODE_PARSER_FAIL:
746            LOGE("Decoder returned DECODE_PARSER_FAIL");
747            return (OMX_ERRORTYPE)OMX_ErrorIntelProcessStream; // OMX_ErrorStreamCorrupt
748        case DECODE_MEMORY_FAIL:
749            LOGE("Decoder returned DECODE_MEMORY_FAIL");
750            return OMX_ErrorInsufficientResources;
751        case DECODE_FAIL:
752            LOGE("Decoder returned DECODE_FAIL");
753            return OMX_ErrorUndefined;
754        case DECODE_SUCCESS:
755            return OMX_ErrorNone;
756        case DECODE_FORMAT_CHANGE:
757            LOGW("Decoder returned DECODE_FORMAT_CHANGE");
758            return OMX_ErrorNone;
759        case DECODE_FRAME_DROPPED:
760            LOGI("Decoder returned DECODE_FRAME_DROPPED");
761            return OMX_ErrorNone;
762        default:
763            LOGW("Decoder returned unknown error");
764            return OMX_ErrorUndefined;
765    }
766}
767
768OMX_ERRORTYPE OMXVideoDecoderBase::BuildHandlerList(void) {
769    OMXComponentCodecBase::BuildHandlerList();
770    AddHandler(OMX_IndexParamVideoPortFormat, GetParamVideoPortFormat, SetParamVideoPortFormat);
771    AddHandler(static_cast<OMX_INDEXTYPE>(OMX_IndexExtGetNativeBufferUsage), GetNativeBufferUsage, SetNativeBufferUsage);
772    AddHandler(static_cast<OMX_INDEXTYPE>(OMX_IndexExtUseNativeBuffer), GetNativeBuffer, SetNativeBuffer);
773    AddHandler(static_cast<OMX_INDEXTYPE>(OMX_IndexExtEnableNativeBuffer), GetNativeBufferMode, SetNativeBufferMode);
774    AddHandler(static_cast<OMX_INDEXTYPE>(OMX_IndexExtRotationDegrees), GetDecoderRotation, SetDecoderRotation);
775#ifdef TARGET_HAS_ISV
776    AddHandler(static_cast<OMX_INDEXTYPE>(OMX_IndexExtVppBufferNum), GetDecoderVppBufferNum, SetDecoderVppBufferNum);
777#endif
778    AddHandler(OMX_IndexConfigCommonOutputCrop, GetDecoderOutputCrop, SetDecoderOutputCrop);
779    AddHandler(static_cast<OMX_INDEXTYPE>(OMX_IndexExtEnableErrorReport), GetErrorReportMode, SetErrorReportMode);
780
781    return OMX_ErrorNone;
782}
783
784OMX_ERRORTYPE OMXVideoDecoderBase::GetParamVideoPortFormat(OMX_PTR pStructure) {
785    OMX_ERRORTYPE ret;
786    OMX_VIDEO_PARAM_PORTFORMATTYPE *p = (OMX_VIDEO_PARAM_PORTFORMATTYPE *)pStructure;
787
788    CHECK_TYPE_HEADER(p);
789    CHECK_PORT_INDEX_RANGE(p);
790    CHECK_ENUMERATION_RANGE(p->nIndex, 1);
791
792    PortVideo *port = NULL;
793    port = static_cast<PortVideo *>(this->ports[p->nPortIndex]);
794    memcpy(p, port->GetPortVideoParam(), sizeof(*p));
795    return OMX_ErrorNone;
796}
797
798OMX_ERRORTYPE OMXVideoDecoderBase::SetParamVideoPortFormat(OMX_PTR pStructure) {
799    OMX_ERRORTYPE ret;
800    OMX_VIDEO_PARAM_PORTFORMATTYPE *p = (OMX_VIDEO_PARAM_PORTFORMATTYPE *)pStructure;
801
802    CHECK_TYPE_HEADER(p);
803    CHECK_PORT_INDEX_RANGE(p);
804    CHECK_SET_PARAM_STATE();
805
806    // TODO: do we need to check if port is enabled?
807    PortVideo *port = NULL;
808    port = static_cast<PortVideo *>(this->ports[p->nPortIndex]);
809    port->SetPortVideoParam(p, false);
810    return OMX_ErrorNone;
811}
812
813OMX_ERRORTYPE OMXVideoDecoderBase::GetNativeBufferUsageSpecific(OMX_PTR pStructure) {
814     OMX_ERRORTYPE ret;
815     GetAndroidNativeBufferUsageParams *param = (GetAndroidNativeBufferUsageParams*)pStructure;
816     CHECK_TYPE_HEADER(param);
817     param->nUsage |= GRALLOC_USAGE_HW_TEXTURE;
818     return OMX_ErrorNone;
819}
820OMX_ERRORTYPE OMXVideoDecoderBase::SetNativeBufferUsageSpecific(OMX_PTR) {
821    CHECK_SET_PARAM_STATE();
822    return OMX_ErrorBadParameter;
823}
824
825OMX_ERRORTYPE OMXVideoDecoderBase::GetNativeBufferUsage(OMX_PTR pStructure) {
826    return this->GetNativeBufferUsageSpecific(pStructure);
827}
828OMX_ERRORTYPE OMXVideoDecoderBase::SetNativeBufferUsage(OMX_PTR pStructure) {
829    return this->SetNativeBufferUsageSpecific(pStructure);
830}
831
832OMX_ERRORTYPE OMXVideoDecoderBase::GetNativeBuffer(OMX_PTR) {
833    return OMX_ErrorBadParameter;
834}
835
836OMX_ERRORTYPE OMXVideoDecoderBase::SetNativeBuffer(OMX_PTR pStructure) {
837    OMX_ERRORTYPE ret;
838    UseAndroidNativeBufferParams *param = (UseAndroidNativeBufferParams*)pStructure;
839    CHECK_TYPE_HEADER(param);
840    if (param->nPortIndex != OUTPORT_INDEX)
841        return OMX_ErrorBadParameter;
842    OMX_BUFFERHEADERTYPE **buf_hdr = NULL;
843
844    mOMXBufferHeaderTypePtrNum++;
845    if (mOMXBufferHeaderTypePtrNum > MAX_GRAPHIC_BUFFER_NUM)
846        return OMX_ErrorOverflow;
847
848    buf_hdr = &mOMXBufferHeaderTypePtrArray[mOMXBufferHeaderTypePtrNum-1];
849
850    ret = this->ports[OUTPORT_INDEX]->UseBuffer(buf_hdr, OUTPORT_INDEX, param->pAppPrivate, sizeof(OMX_U8*),
851                                      const_cast<OMX_U8*>(reinterpret_cast<const OMX_U8*>(param->nativeBuffer->handle)));
852    if (ret != OMX_ErrorNone)
853        return ret;
854
855    if (mOMXBufferHeaderTypePtrNum == 1) {
856         mGraphicBufferParam.graphicBufferColorFormat = param->nativeBuffer->format;
857         mGraphicBufferParam.graphicBufferStride = param->nativeBuffer->stride;
858         mGraphicBufferParam.graphicBufferWidth = param->nativeBuffer->width;
859         mGraphicBufferParam.graphicBufferHeight = param->nativeBuffer->height;
860    }
861
862    *(param->bufferHeader) = *buf_hdr;
863
864    return OMX_ErrorNone;
865}
866
867OMX_ERRORTYPE OMXVideoDecoderBase::GetNativeBufferMode(OMX_PTR pStructure) {
868    return this->GetNativeBufferModeSpecific(pStructure);
869}
870
871OMX_ERRORTYPE OMXVideoDecoderBase::SetNativeBufferMode(OMX_PTR pStructure) {
872    return this->SetNativeBufferModeSpecific(pStructure);
873}
874
875OMX_ERRORTYPE OMXVideoDecoderBase::GetNativeBufferModeSpecific(OMX_PTR) {
876    LOGE("GetNativeBufferMode is not implemented");
877    return OMX_ErrorNotImplemented;
878}
879
880OMX_ERRORTYPE OMXVideoDecoderBase::SetNativeBufferModeSpecific(OMX_PTR pStructure) {
881    OMX_ERRORTYPE ret;
882    EnableAndroidNativeBuffersParams *param = (EnableAndroidNativeBuffersParams*)pStructure;
883
884    CHECK_TYPE_HEADER(param);
885    CHECK_PORT_INDEX_RANGE(param);
886    CHECK_SET_PARAM_STATE();
887
888    PortVideo *port = NULL;
889    port = static_cast<PortVideo *>(this->ports[OUTPORT_INDEX]);
890    OMX_PARAM_PORTDEFINITIONTYPE port_def;
891    memcpy(&port_def,port->GetPortDefinition(),sizeof(port_def));
892
893    if (!param->enable) {
894        mWorkingMode = RAWDATA_MODE;
895        // If it is fallback from native mode the color format has been
896        // already set to INTEL format.
897        // We need to set back the default color format and Native stuff.
898        port_def.format.video.eColorFormat = OMX_COLOR_FormatYUV420SemiPlanar;
899        port_def.format.video.pNativeRender = NULL;
900        port_def.format.video.pNativeWindow = NULL;
901        port->SetPortDefinition(&port_def,true);
902        return OMX_ErrorNone;
903    }
904
905    mWorkingMode = GRAPHICBUFFER_MODE;
906    port_def.nBufferCountMin = mNativeBufferCount;
907    if (mEnableAdaptivePlayback) {
908        SetMaxOutputBufferCount(&port_def);
909    } else {
910        port_def.nBufferCountActual = mNativeBufferCount;
911    }
912    port_def.format.video.cMIMEType = (OMX_STRING)VA_VED_RAW_MIME_TYPE;
913    port_def.format.video.eColorFormat = OMX_INTEL_COLOR_FormatYUV420PackedSemiPlanar;
914    port_def.format.video.nFrameHeight = (port_def.format.video.nFrameHeight + 0x1f) & ~0x1f;
915    port_def.format.video.eColorFormat = GetOutputColorFormat(
916                        port_def.format.video.nFrameWidth);
917    port->SetPortDefinition(&port_def,true);
918
919    return OMX_ErrorNone;
920}
921
922OMX_ERRORTYPE OMXVideoDecoderBase::GetDecoderRotation(OMX_PTR) {
923    return OMX_ErrorBadParameter;
924}
925OMX_ERRORTYPE OMXVideoDecoderBase::SetDecoderRotation(OMX_PTR pStructure) {
926    CHECK_SET_PARAM_STATE();
927    int32_t rotationDegrees = 0;
928
929    if (pStructure) {
930        rotationDegrees = *(static_cast<int32_t*>(pStructure));
931        mRotationDegrees = rotationDegrees;
932        LOGI("Rotation Degree = %d", rotationDegrees);
933        return OMX_ErrorNone;
934    } else {
935        return OMX_ErrorBadParameter;
936    }
937}
938
939#ifdef TARGET_HAS_ISV
940OMX_ERRORTYPE OMXVideoDecoderBase::GetDecoderVppBufferNum(OMX_PTR) {
941    return OMX_ErrorBadParameter;
942}
943OMX_ERRORTYPE OMXVideoDecoderBase::SetDecoderVppBufferNum(OMX_PTR pStructure) {
944    CHECK_SET_PARAM_STATE();
945    int32_t num = 0;
946
947    num = *(static_cast<int32_t*>(pStructure));
948    mVppBufferNum = num;
949
950    return OMX_ErrorNone;
951}
952#endif
953
954OMX_ERRORTYPE OMXVideoDecoderBase::GetDecoderOutputCropSpecific(OMX_PTR pStructure) {
955    OMX_ERRORTYPE ret;
956    OMX_CONFIG_RECTTYPE *rectParams = (OMX_CONFIG_RECTTYPE *)pStructure;
957
958    CHECK_TYPE_HEADER(rectParams);
959
960    if (rectParams->nPortIndex != OUTPORT_INDEX) {
961        return OMX_ErrorUndefined;
962    }
963    const VideoFormatInfo *formatInfo = mVideoDecoder->getFormatInfo();
964    if (formatInfo->valid == true) {
965        rectParams->nLeft =  formatInfo->cropLeft;
966        rectParams->nTop = formatInfo->cropTop;
967        rectParams->nWidth = formatInfo->width - formatInfo->cropLeft - formatInfo->cropRight;
968        rectParams->nHeight = formatInfo->height - formatInfo->cropTop - formatInfo->cropBottom;
969        return OMX_ErrorNone;
970    } else {
971        return OMX_ErrorFormatNotDetected;
972    }
973}
974
975OMX_ERRORTYPE OMXVideoDecoderBase::SetDecoderOutputCropSpecific(OMX_PTR) {
976    return OMX_ErrorUnsupportedSetting;
977}
978
979OMX_ERRORTYPE OMXVideoDecoderBase::SetDecoderOutputCrop(OMX_PTR pStructure) {
980    return this->SetDecoderOutputCropSpecific(pStructure);
981}
982
983OMX_ERRORTYPE OMXVideoDecoderBase::GetDecoderOutputCrop(OMX_PTR pStructure) {
984    return this->GetDecoderOutputCropSpecific(pStructure);
985}
986
987OMX_ERRORTYPE OMXVideoDecoderBase::GetErrorReportMode(OMX_PTR) {
988    LOGE("GetErrorReportMode is not implemented");
989    return OMX_ErrorNotImplemented;
990}
991
992OMX_ERRORTYPE OMXVideoDecoderBase::SetErrorReportMode(OMX_PTR pStructure) {
993    OMX_ERRORTYPE ret;
994
995    OMX_VIDEO_CONFIG_INTEL_ERROR_REPORT *p = (OMX_VIDEO_CONFIG_INTEL_ERROR_REPORT *)pStructure;
996    CHECK_TYPE_HEADER(p);
997    CHECK_PORT_INDEX(p, OUTPORT_INDEX);
998
999    mErrorReportEnabled = p->bEnable;
1000    LOGD("Error reporting is %s", mErrorReportEnabled ? "enabled" : "disabled");
1001
1002    mVideoDecoder->enableErrorReport(mErrorReportEnabled);
1003    return OMX_ErrorNone;
1004}
1005
1006OMX_COLOR_FORMATTYPE OMXVideoDecoderBase::GetOutputColorFormat(int width) {
1007#ifndef VED_TILING
1008    return OMX_INTEL_COLOR_FormatYUV420PackedSemiPlanar;
1009#else
1010    if (width > 1280 && width <= 2048) {
1011        LOGI("HD Video and use tiled format");
1012        return OMX_INTEL_COLOR_FormatYUV420PackedSemiPlanar_Tiled;
1013    } else {
1014        return OMX_INTEL_COLOR_FormatYUV420PackedSemiPlanar;
1015    }
1016#endif
1017}
1018
1019OMX_ERRORTYPE OMXVideoDecoderBase::SetMaxOutputBufferCount(OMX_PARAM_PORTDEFINITIONTYPE *) {
1020    return OMX_ErrorNone;
1021}
1022