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 
28 static const char* VA_RAW_MIME_TYPE = "video/x-raw-va";
29 static const uint32_t VA_COLOR_FORMAT = 0x7FA00E00;
30 
OMXVideoDecoderBase()31 OMXVideoDecoderBase::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 
~OMXVideoDecoderBase()50 OMXVideoDecoderBase::~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 
InitInputPort(void)66 OMX_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 
InitOutputPort(void)124 OMX_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 
InitOutputPortFormatSpecific(OMX_PARAM_PORTDEFINITIONTYPE *)181 OMX_ERRORTYPE OMXVideoDecoderBase::InitOutputPortFormatSpecific(OMX_PARAM_PORTDEFINITIONTYPE *) {
182     // no format specific to initialize output port
183     return OMX_ErrorNone;
184 }
185 
ProcessorInit(void)186 OMX_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 
ProcessorReset(void)211 OMX_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 
ProcessorDeinit(void)222 OMX_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 
ProcessorStart(void)239 OMX_ERRORTYPE OMXVideoDecoderBase::ProcessorStart(void) {
240     return OMXComponentCodecBase::ProcessorStart();
241 }
242 
ProcessorStop(void)243 OMX_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 
ProcessorPause(void)261 OMX_ERRORTYPE OMXVideoDecoderBase::ProcessorPause(void) {
262     return OMXComponentCodecBase::ProcessorPause();
263 }
264 
ProcessorResume(void)265 OMX_ERRORTYPE OMXVideoDecoderBase::ProcessorResume(void) {
266     return OMXComponentCodecBase::ProcessorResume();
267 }
268 
ProcessorFlush(OMX_U32 portIndex)269 OMX_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 
ProcessorPreFreeBuffer(OMX_U32 nPortIndex,OMX_BUFFERHEADERTYPE * pBuffer)287 OMX_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 
ProcessorPreFillBuffer(OMX_BUFFERHEADERTYPE * buffer)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 
ProcessorProcess(OMX_BUFFERHEADERTYPE *** pBuffers,buffer_retain_t * retains,OMX_U32)340 OMX_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 
IsAllBufferAvailable(void)479 bool 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 
PrepareConfigBuffer(VideoConfigBuffer * p)499 OMX_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 
PrepareDecodeBuffer(OMX_BUFFERHEADERTYPE * buffer,buffer_retain_t * retain,VideoDecodeBuffer * p)575 OMX_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 
PrepareDecodeNativeHandleBuffer(OMX_BUFFERHEADERTYPE * buffer,buffer_retain_t * retain,VideoDecodeBuffer * p)623 OMX_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 
FillRenderBuffer(OMX_BUFFERHEADERTYPE ** pBuffer,buffer_retain_t * retain,OMX_U32 inportBufferFlags,OMX_BOOL * isResolutionChange)678 OMX_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 
HandleFormatChange(void)762 OMX_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/avc-secure") == 0 ||
788         strcasecmp(formatInfo->mimeType,"video/h264") == 0) {
789         heightCropped = formatInfo->height;
790         widthCropped = formatInfo->width;
791     }
792     uint32_t strideCropped = widthCropped;
793     uint32_t sliceHeightCropped = heightCropped;
794     int force_realloc = 0;
795     bool isVP8 = false;
796 
797     if (mAPMode == METADATA_MODE && mWorkingMode == GRAPHICBUFFER_MODE) {
798 #ifdef TARGET_HAS_ISV
799         if (paramPortDefinitionOutput.nBufferCountActual - mVppBufferNum < formatInfo->actualBufferNeeded) {
800 #else
801         if (paramPortDefinitionOutput.nBufferCountActual < formatInfo->actualBufferNeeded) {
802 #endif
803             paramPortDefinitionOutput.nBufferCountActual = mNativeBufferCount = formatInfo->actualBufferNeeded;
804             paramPortDefinitionOutput.nBufferCountMin = formatInfo->actualBufferNeeded - 4;
805         }
806         // input port
807         paramPortDefinitionInput.format.video.nFrameWidth = width;
808         paramPortDefinitionInput.format.video.nFrameHeight = height;
809         paramPortDefinitionInput.format.video.nStride = stride;
810         paramPortDefinitionInput.format.video.nSliceHeight = sliceHeight;
811         // output port
812         paramPortDefinitionOutput.format.video.nFrameWidth = width;
813         paramPortDefinitionOutput.format.video.nFrameHeight = height;
814         paramPortDefinitionOutput.format.video.eColorFormat = GetOutputColorFormat(paramPortDefinitionOutput.format.video.nFrameWidth);
815         paramPortDefinitionOutput.format.video.nStride = stride;
816         paramPortDefinitionOutput.format.video.nSliceHeight = sliceHeight;
817 
818         paramPortDefinitionOutput.bEnabled = (OMX_BOOL)false;
819         mOMXBufferHeaderTypePtrNum = 0;
820         memset(&mGraphicBufferParam, 0, sizeof(mGraphicBufferParam));
821         mMetaDataBuffersNum = 0;
822 
823         this->ports[INPORT_INDEX]->SetPortDefinition(&paramPortDefinitionInput, true);
824         this->ports[OUTPORT_INDEX]->SetPortDefinition(&paramPortDefinitionOutput, true);
825 
826         ProcessorFlush(INPORT_INDEX);
827 
828         mVideoDecoder->freeSurfaceBuffers();
829 
830         this->ports[OUTPORT_INDEX]->ReportPortSettingsChanged();
831 
832         mFlushMode = false;
833         return OMX_ErrorNone;
834     }
835 
836 #ifdef TARGET_HAS_ISV
837     LOGI("============== mVppBufferNum = %d\n", mVppBufferNum);
838     if (paramPortDefinitionOutput.nBufferCountActual - mVppBufferNum < formatInfo->actualBufferNeeded) {
839 #else
840     if (paramPortDefinitionOutput.nBufferCountActual < formatInfo->actualBufferNeeded) {
841 #endif
842         if (mWorkingMode == GRAPHICBUFFER_MODE) {
843             LOGV("output port buffer number is not enough: %d to %d",
844                  paramPortDefinitionOutput.nBufferCountActual,
845                  formatInfo->actualBufferNeeded);
846             paramPortDefinitionOutput.nBufferCountActual = mNativeBufferCount = formatInfo->actualBufferNeeded;
847             paramPortDefinitionOutput.nBufferCountMin = mNativeBufferCount;
848             force_realloc = 1;
849         }
850     }
851 
852     LOGV("Original size = %u x %u, new size = %d x %d, cropped size = %d x %d",
853         paramPortDefinitionInput.format.video.nFrameWidth,
854         paramPortDefinitionInput.format.video.nFrameHeight,
855         width, height, widthCropped, heightCropped);
856 
857     if (paramPortDefinitionInput.format.video.eCompressionFormat == OMX_VIDEO_CodingVP8) {
858         isVP8 = true;
859     }
860 
861     if (!force_realloc &&
862         widthCropped == paramPortDefinitionOutput.format.video.nFrameWidth &&
863         heightCropped == paramPortDefinitionOutput.format.video.nFrameHeight) {
864         if (mWorkingMode == RAWDATA_MODE) {
865             LOGW("Change of portsetting is not reported as size is not changed.");
866             return OMX_ErrorNone;
867         }
868     }
869 
870     paramPortDefinitionInput.format.video.nFrameWidth = width;
871     paramPortDefinitionInput.format.video.nFrameHeight = height;
872     paramPortDefinitionInput.format.video.nStride = stride;
873     paramPortDefinitionInput.format.video.nSliceHeight = sliceHeight;
874 
875     if (mWorkingMode == RAWDATA_MODE) {
876         paramPortDefinitionOutput.format.video.nFrameWidth = widthCropped;
877         paramPortDefinitionOutput.format.video.nFrameHeight = heightCropped;
878         paramPortDefinitionOutput.format.video.nStride = strideCropped;
879         paramPortDefinitionOutput.format.video.nSliceHeight = sliceHeightCropped;
880     } else if (mWorkingMode == GRAPHICBUFFER_MODE) {
881         // when the width and height ES parse are not larger than allocated graphic buffer in outport,
882         // there is no need to reallocate graphic buffer,just report the crop info to omx client
883         if (!force_realloc && width <= formatInfo->surfaceWidth && height <= formatInfo->surfaceHeight) {
884             this->ports[INPORT_INDEX]->SetPortDefinition(&paramPortDefinitionInput, true);
885             this->ports[OUTPORT_INDEX]->ReportOutputCrop();
886             return OMX_ErrorNone;
887         }
888 
889         if (isVP8 || width > formatInfo->surfaceWidth ||  height > formatInfo->surfaceHeight) {
890             // update the real decoded resolution to outport instead of display resolution for graphic buffer reallocation
891             // when the width and height parsed from ES are larger than allocated graphic buffer in outport,
892             paramPortDefinitionOutput.format.video.nFrameWidth = width;
893             paramPortDefinitionOutput.format.video.nFrameHeight = height;
894             paramPortDefinitionOutput.format.video.eColorFormat = GetOutputColorFormat(
895                     paramPortDefinitionOutput.format.video.nFrameWidth);
896             paramPortDefinitionOutput.format.video.nStride = stride;
897             paramPortDefinitionOutput.format.video.nSliceHeight = sliceHeight;
898        }
899     }
900 
901     paramPortDefinitionOutput.bEnabled = (OMX_BOOL)false;
902     mOMXBufferHeaderTypePtrNum = 0;
903     memset(&mGraphicBufferParam, 0, sizeof(mGraphicBufferParam));
904 
905     this->ports[INPORT_INDEX]->SetPortDefinition(&paramPortDefinitionInput, true);
906     this->ports[OUTPORT_INDEX]->SetPortDefinition(&paramPortDefinitionOutput, true);
907 
908     if (mWorkingMode == GRAPHICBUFFER_MODE) {
909         // Make sure va_destroySurface is called before graphicbuffer is freed in case of port setting changed
910         mVideoDecoder->freeSurfaceBuffers();
911 
912         // Also make sure all the reference frames are flushed
913         ProcessorFlush(INPORT_INDEX);
914     }
915     this->ports[OUTPORT_INDEX]->ReportPortSettingsChanged();
916     return OMX_ErrorNone;
917 }
918 
919 OMX_ERRORTYPE OMXVideoDecoderBase::TranslateDecodeStatus(Decode_Status status) {
920     switch (status) {
921         case DECODE_NEED_RESTART:
922             LOGE("Decoder returned DECODE_NEED_RESTART");
923             return (OMX_ERRORTYPE)OMX_ErrorIntelVideoNotPermitted;
924         case DECODE_NO_CONFIG:
925             LOGE("Decoder returned DECODE_NO_CONFIG");
926             return (OMX_ERRORTYPE)OMX_ErrorIntelMissingConfig;
927         case DECODE_NO_SURFACE:
928             LOGE("Decoder returned DECODE_NO_SURFACE");
929             return OMX_ErrorDynamicResourcesUnavailable;
930         case DECODE_NO_REFERENCE:
931             LOGE("Decoder returned DECODE_NO_REFERENCE");
932             return OMX_ErrorDynamicResourcesUnavailable; // TO DO
933         case DECODE_NO_PARSER:
934             LOGE("Decoder returned DECODE_NO_PARSER");
935             return OMX_ErrorDynamicResourcesUnavailable;
936         case DECODE_INVALID_DATA:
937             LOGE("Decoder returned DECODE_INVALID_DATA");
938             return OMX_ErrorBadParameter;
939         case DECODE_DRIVER_FAIL:
940             LOGE("Decoder returned DECODE_DRIVER_FAIL");
941             return OMX_ErrorHardware;
942         case DECODE_PARSER_FAIL:
943             LOGE("Decoder returned DECODE_PARSER_FAIL");
944             return (OMX_ERRORTYPE)OMX_ErrorIntelProcessStream; // OMX_ErrorStreamCorrupt
945         case DECODE_MEMORY_FAIL:
946             LOGE("Decoder returned DECODE_MEMORY_FAIL");
947             return OMX_ErrorInsufficientResources;
948         case DECODE_FAIL:
949             LOGE("Decoder returned DECODE_FAIL");
950             return OMX_ErrorUndefined;
951         case DECODE_SUCCESS:
952             return OMX_ErrorNone;
953         case DECODE_FORMAT_CHANGE:
954             LOGW("Decoder returned DECODE_FORMAT_CHANGE");
955             return OMX_ErrorNone;
956         case DECODE_FRAME_DROPPED:
957             LOGI("Decoder returned DECODE_FRAME_DROPPED");
958             return OMX_ErrorNone;
959         default:
960             LOGW("Decoder returned unknown error");
961             return OMX_ErrorUndefined;
962     }
963 }
964 
965 OMX_ERRORTYPE OMXVideoDecoderBase::BuildHandlerList(void) {
966     OMXComponentCodecBase::BuildHandlerList();
967     AddHandler(OMX_IndexParamVideoPortFormat, GetParamVideoPortFormat, SetParamVideoPortFormat);
968     AddHandler(static_cast<OMX_INDEXTYPE>(OMX_IndexExtGetNativeBufferUsage), GetNativeBufferUsage, SetNativeBufferUsage);
969     AddHandler(static_cast<OMX_INDEXTYPE>(OMX_IndexExtUseNativeBuffer), GetNativeBuffer, SetNativeBuffer);
970     AddHandler(static_cast<OMX_INDEXTYPE>(OMX_IndexExtEnableNativeBuffer), GetNativeBufferMode, SetNativeBufferMode);
971     AddHandler(static_cast<OMX_INDEXTYPE>(OMX_IndexExtRotationDegrees), GetDecoderRotation, SetDecoderRotation);
972 #ifdef TARGET_HAS_ISV
973     AddHandler(static_cast<OMX_INDEXTYPE>(OMX_IndexExtVppBufferNum), GetDecoderVppBufferNum, SetDecoderVppBufferNum);
974 #endif
975     AddHandler(OMX_IndexConfigCommonOutputCrop, GetDecoderOutputCrop, SetDecoderOutputCrop);
976 #ifdef USE_META_DATA
977     AddHandler(static_cast<OMX_INDEXTYPE>(OMX_IndexStoreMetaDataInBuffers), GetStoreMetaDataMode, SetStoreMetaDataMode);
978 #endif
979     AddHandler(static_cast<OMX_INDEXTYPE>(OMX_IndexExtEnableErrorReport), GetErrorReportMode, SetErrorReportMode);
980     AddHandler(static_cast<OMX_INDEXTYPE>(OMX_IndexConfigPriority), GetCodecPriority, SetCodecPriority);
981     AddHandler(static_cast<OMX_INDEXTYPE>(OMX_IndexConfigOperatingRate), GetDecoderOperatingRate, SetDecoderOperatingRate);
982 
983     return OMX_ErrorNone;
984 }
985 
986 OMX_ERRORTYPE OMXVideoDecoderBase::GetParamVideoPortFormat(OMX_PTR pStructure) {
987     OMX_ERRORTYPE ret;
988     OMX_VIDEO_PARAM_PORTFORMATTYPE *p = (OMX_VIDEO_PARAM_PORTFORMATTYPE *)pStructure;
989 
990     CHECK_TYPE_HEADER(p);
991     CHECK_PORT_INDEX_RANGE(p);
992     CHECK_ENUMERATION_RANGE(p->nIndex, 1);
993 
994     PortVideo *port = NULL;
995     port = static_cast<PortVideo *>(this->ports[p->nPortIndex]);
996     memcpy(p, port->GetPortVideoParam(), sizeof(*p));
997     return OMX_ErrorNone;
998 }
999 
1000 OMX_ERRORTYPE OMXVideoDecoderBase::SetParamVideoPortFormat(OMX_PTR pStructure) {
1001     OMX_ERRORTYPE ret;
1002     OMX_VIDEO_PARAM_PORTFORMATTYPE *p = (OMX_VIDEO_PARAM_PORTFORMATTYPE *)pStructure;
1003 
1004     CHECK_TYPE_HEADER(p);
1005     CHECK_PORT_INDEX_RANGE(p);
1006     CHECK_SET_PARAM_STATE();
1007 
1008     // TODO: do we need to check if port is enabled?
1009     PortVideo *port = NULL;
1010     port = static_cast<PortVideo *>(this->ports[p->nPortIndex]);
1011     port->SetPortVideoParam(p, false);
1012     return OMX_ErrorNone;
1013 }
1014 
1015 OMX_ERRORTYPE OMXVideoDecoderBase::GetNativeBufferUsageSpecific(OMX_PTR pStructure) {
1016      OMX_ERRORTYPE ret;
1017      GetAndroidNativeBufferUsageParams *param = (GetAndroidNativeBufferUsageParams*)pStructure;
1018      CHECK_TYPE_HEADER(param);
1019      // hardware usage: consumed by GLES and HWC
1020      param->nUsage |= GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_HW_COMPOSER;
1021      // software usage: can be read/written by apps
1022      param->nUsage |= GRALLOC_USAGE_SW_READ_RARELY | GRALLOC_USAGE_SW_WRITE_RARELY;
1023      return OMX_ErrorNone;
1024 }
1025 OMX_ERRORTYPE OMXVideoDecoderBase::SetNativeBufferUsageSpecific(OMX_PTR) {
1026     CHECK_SET_PARAM_STATE();
1027     return OMX_ErrorBadParameter;
1028 }
1029 
1030 OMX_ERRORTYPE OMXVideoDecoderBase::GetNativeBufferUsage(OMX_PTR pStructure) {
1031     return this->GetNativeBufferUsageSpecific(pStructure);
1032 }
1033 OMX_ERRORTYPE OMXVideoDecoderBase::SetNativeBufferUsage(OMX_PTR pStructure) {
1034     return this->SetNativeBufferUsageSpecific(pStructure);
1035 }
1036 
1037 OMX_ERRORTYPE OMXVideoDecoderBase::GetNativeBuffer(OMX_PTR) {
1038     return OMX_ErrorBadParameter;
1039 }
1040 
1041 OMX_ERRORTYPE OMXVideoDecoderBase::SetNativeBuffer(OMX_PTR pStructure) {
1042     OMX_ERRORTYPE ret;
1043     UseAndroidNativeBufferParams *param = (UseAndroidNativeBufferParams*)pStructure;
1044     CHECK_TYPE_HEADER(param);
1045     if (param->nPortIndex != OUTPORT_INDEX)
1046         return OMX_ErrorBadParameter;
1047     OMX_BUFFERHEADERTYPE **buf_hdr = NULL;
1048 
1049     mOMXBufferHeaderTypePtrNum++;
1050     if (mOMXBufferHeaderTypePtrNum > MAX_GRAPHIC_BUFFER_NUM)
1051         return OMX_ErrorOverflow;
1052 
1053     buf_hdr = &mOMXBufferHeaderTypePtrArray[mOMXBufferHeaderTypePtrNum-1];
1054 
1055     ret = this->ports[OUTPORT_INDEX]->UseBuffer(buf_hdr, OUTPORT_INDEX, param->pAppPrivate, sizeof(OMX_U8*),
1056                                       const_cast<OMX_U8*>(reinterpret_cast<const OMX_U8*>(param->nativeBuffer->handle)));
1057     if (ret != OMX_ErrorNone)
1058         return ret;
1059 
1060     if (mOMXBufferHeaderTypePtrNum == 1) {
1061          mGraphicBufferParam.graphicBufferColorFormat = param->nativeBuffer->format;
1062          mGraphicBufferParam.graphicBufferHStride = param->nativeBuffer->stride;
1063          // FIXME: use IMG_native_handle_t->aiVStride[0] instead..
1064          mGraphicBufferParam.graphicBufferVStride = param->nativeBuffer->height;
1065          mGraphicBufferParam.graphicBufferWidth = param->nativeBuffer->width;
1066          mGraphicBufferParam.graphicBufferHeight = param->nativeBuffer->height;
1067     }
1068 
1069     *(param->bufferHeader) = *buf_hdr;
1070 
1071     return OMX_ErrorNone;
1072 }
1073 
1074 OMX_ERRORTYPE OMXVideoDecoderBase::GetNativeBufferMode(OMX_PTR pStructure) {
1075     return this->GetNativeBufferModeSpecific(pStructure);
1076 }
1077 
1078 OMX_ERRORTYPE OMXVideoDecoderBase::SetNativeBufferMode(OMX_PTR pStructure) {
1079     return this->SetNativeBufferModeSpecific(pStructure);
1080 }
1081 
1082 OMX_ERRORTYPE OMXVideoDecoderBase::GetNativeBufferModeSpecific(OMX_PTR) {
1083     LOGE("GetNativeBufferMode is not implemented");
1084     return OMX_ErrorNotImplemented;
1085 }
1086 
1087 OMX_ERRORTYPE OMXVideoDecoderBase::SetNativeBufferModeSpecific(OMX_PTR pStructure) {
1088     OMX_ERRORTYPE ret;
1089     EnableAndroidNativeBuffersParams *param = (EnableAndroidNativeBuffersParams*)pStructure;
1090 
1091     CHECK_TYPE_HEADER(param);
1092     CHECK_PORT_INDEX_RANGE(param);
1093     CHECK_SET_PARAM_STATE();
1094 
1095     PortVideo *port = NULL;
1096     port = static_cast<PortVideo *>(this->ports[OUTPORT_INDEX]);
1097     OMX_PARAM_PORTDEFINITIONTYPE port_def;
1098     memcpy(&port_def,port->GetPortDefinition(),sizeof(port_def));
1099 
1100     if (!param->enable) {
1101         mWorkingMode = RAWDATA_MODE;
1102         // If it is fallback from native mode the color format has been
1103         // already set to INTEL format.
1104         // We need to set back the default color format and Native stuff.
1105         port_def.format.video.eColorFormat = OMX_COLOR_FormatYUV420SemiPlanar;
1106         port_def.format.video.pNativeRender = NULL;
1107         port_def.format.video.pNativeWindow = NULL;
1108         port->SetPortDefinition(&port_def,true);
1109         return OMX_ErrorNone;
1110     }
1111 
1112     mWorkingMode = GRAPHICBUFFER_MODE;
1113     port_def.nBufferCountMin = mNativeBufferCount;
1114     if (mEnableAdaptivePlayback) {
1115         SetMaxOutputBufferCount(&port_def);
1116     } else {
1117         port_def.nBufferCountActual = mNativeBufferCount;
1118     }
1119     port_def.format.video.cMIMEType = (OMX_STRING)VA_VED_RAW_MIME_TYPE;
1120     port_def.format.video.eColorFormat = OMX_INTEL_COLOR_FormatYUV420PackedSemiPlanar;
1121     port_def.format.video.nFrameHeight = port_def.format.video.nFrameHeight;
1122 
1123     port_def.format.video.eColorFormat = GetOutputColorFormat(
1124                         port_def.format.video.nFrameWidth);
1125     port->SetPortDefinition(&port_def,true);
1126 
1127     return OMX_ErrorNone;
1128 }
1129 
1130 OMX_ERRORTYPE OMXVideoDecoderBase::GetStoreMetaDataMode(OMX_PTR) {
1131     ALOGE("GetMetaDataMode is not implemented");
1132     return OMX_ErrorNotImplemented;
1133 }
1134 
1135 OMX_ERRORTYPE OMXVideoDecoderBase::SetStoreMetaDataMode(OMX_PTR pStructure) {
1136 #ifndef USE_META_DATA
1137     OMX_PARAM_PORTDEFINITIONTYPE defInput;
1138     memcpy(&defInput,
1139         this->ports[INPORT_INDEX]->GetPortDefinition(),
1140         sizeof(defInput));
1141     if (defInput.format.video.eCompressionFormat == OMX_VIDEO_CodingVP9) {
1142         ALOGE("SetMetaDataMode for VP9 is not implemented");
1143         return OMX_ErrorNotImplemented;
1144     }
1145 #endif
1146     OMX_ERRORTYPE ret;
1147     StoreMetaDataInBuffersParams *param = (StoreMetaDataInBuffersParams*)pStructure;
1148 
1149     CHECK_TYPE_HEADER(param);
1150     CHECK_PORT_INDEX(param, OUTPORT_INDEX);
1151     CHECK_SET_PARAM_STATE();
1152 
1153     if (!param->bStoreMetaData) {
1154         mAPMode = LEGACY_MODE;
1155         // Don't return error which otherwise may cause framework crash
1156         return OMX_ErrorNone;
1157     }
1158     mAPMode = METADATA_MODE;
1159     ALOGI("We are in meta data mode!!!");
1160 
1161     return OMX_ErrorNone;
1162 }
1163 
1164 OMX_ERRORTYPE OMXVideoDecoderBase::GetDecoderRotation(OMX_PTR) {
1165     return OMX_ErrorBadParameter;
1166 }
1167 OMX_ERRORTYPE OMXVideoDecoderBase::SetDecoderRotation(OMX_PTR pStructure) {
1168     CHECK_SET_PARAM_STATE();
1169     int32_t rotationDegrees = 0;
1170 
1171     if (pStructure) {
1172         rotationDegrees = *(static_cast<int32_t*>(pStructure));
1173         mRotationDegrees = rotationDegrees;
1174         LOGI("Rotation Degree = %d", rotationDegrees);
1175         return OMX_ErrorNone;
1176     } else {
1177         return OMX_ErrorBadParameter;
1178     }
1179 }
1180 
1181 #ifdef TARGET_HAS_ISV
1182 OMX_ERRORTYPE OMXVideoDecoderBase::GetDecoderVppBufferNum(OMX_PTR) {
1183     return OMX_ErrorBadParameter;
1184 }
1185 OMX_ERRORTYPE OMXVideoDecoderBase::SetDecoderVppBufferNum(OMX_PTR pStructure) {
1186     CHECK_SET_PARAM_STATE();
1187     int32_t num = 0;
1188 
1189     num = *(static_cast<int32_t*>(pStructure));
1190     mVppBufferNum = num;
1191 
1192     return OMX_ErrorNone;
1193 }
1194 #endif
1195 
1196 OMX_ERRORTYPE OMXVideoDecoderBase::GetDecoderOutputCropSpecific(OMX_PTR pStructure) {
1197     OMX_ERRORTYPE ret;
1198     OMX_CONFIG_RECTTYPE *rectParams = (OMX_CONFIG_RECTTYPE *)pStructure;
1199 
1200     CHECK_TYPE_HEADER(rectParams);
1201 
1202     if (rectParams->nPortIndex != OUTPORT_INDEX) {
1203         return OMX_ErrorUndefined;
1204     }
1205 
1206     PortVideo *port = NULL;
1207     port = static_cast<PortVideo *>(this->ports[OUTPORT_INDEX]);
1208     OMX_PARAM_PORTDEFINITIONTYPE port_def;
1209     memcpy(&port_def,port->GetPortDefinition(),sizeof(port_def));
1210 
1211     const VideoFormatInfo *formatInfo = mVideoDecoder->getFormatInfo();
1212     if (formatInfo->valid == true) {
1213         rectParams->nLeft =  formatInfo->cropLeft;
1214         rectParams->nTop = formatInfo->cropTop;
1215         rectParams->nWidth = formatInfo->width - formatInfo->cropLeft - formatInfo->cropRight;
1216         rectParams->nHeight = formatInfo->height - formatInfo->cropTop - formatInfo->cropBottom;
1217         if (strcasecmp(formatInfo->mimeType,"video/avc") == 0 ||
1218             strcasecmp(formatInfo->mimeType,"video/avc-secure") == 0 ||
1219             strcasecmp(formatInfo->mimeType,"video/h264") == 0) {
1220             rectParams->nHeight = formatInfo->height;
1221             rectParams->nWidth = formatInfo->width;
1222         }
1223 
1224         // if port width parsed from extractor is not as same as from SPS/PPS nalu header,
1225         // align it.
1226         if (port_def.format.video.nFrameWidth != rectParams->nWidth) {
1227             port_def.format.video.nFrameWidth = rectParams->nWidth;
1228         }
1229         port->SetPortDefinition(&port_def,true);
1230         return OMX_ErrorNone;
1231     } else {
1232         return OMX_ErrorFormatNotDetected;
1233     }
1234 }
1235 
1236 OMX_ERRORTYPE OMXVideoDecoderBase::SetDecoderOutputCropSpecific(OMX_PTR) {
1237     return OMX_ErrorUnsupportedSetting;
1238 }
1239 
1240 OMX_ERRORTYPE OMXVideoDecoderBase::SetDecoderOutputCrop(OMX_PTR pStructure) {
1241     return this->SetDecoderOutputCropSpecific(pStructure);
1242 }
1243 
1244 OMX_ERRORTYPE OMXVideoDecoderBase::GetDecoderOutputCrop(OMX_PTR pStructure) {
1245     return this->GetDecoderOutputCropSpecific(pStructure);
1246 }
1247 
1248 
1249 OMX_ERRORTYPE OMXVideoDecoderBase::SetCodecPriority(OMX_PTR pStructure) {
1250     OMX_ERRORTYPE ret;
1251     OMX_PARAM_U32TYPE *priorityParam = (OMX_PARAM_U32TYPE *)pStructure;
1252     mCodecPriority = priorityParam->nU32;
1253     return OMX_ErrorNone;
1254 }
1255 
1256 
1257 OMX_ERRORTYPE OMXVideoDecoderBase::GetCodecPriority(OMX_PTR pStructure) {
1258     OMX_ERRORTYPE ret;
1259     OMX_PARAM_U32TYPE *priorityParam = (OMX_PARAM_U32TYPE *)pStructure;
1260     CHECK_TYPE_HEADER(priorityParam);
1261     priorityParam->nU32 = mCodecPriority;
1262     return OMX_ErrorNone;
1263 }
1264 
1265 
1266 OMX_ERRORTYPE OMXVideoDecoderBase::SetDecoderOperatingRate(OMX_PTR pStructure) {
1267     OMX_ERRORTYPE ret;
1268     OMX_PARAM_U32TYPE *operatingRateParam = (OMX_PARAM_U32TYPE *)pStructure;
1269     CHECK_TYPE_HEADER(operatingRateParam);
1270     mOperatingRate = operatingRateParam->nU32;
1271     return OMX_ErrorNone;
1272 }
1273 
1274 OMX_ERRORTYPE OMXVideoDecoderBase::GetDecoderOperatingRate(OMX_PTR pStructure) {
1275     OMX_ERRORTYPE ret;
1276     OMX_PARAM_U32TYPE *operatingRateParam = (OMX_PARAM_U32TYPE *)pStructure;
1277     CHECK_TYPE_HEADER(operatingRateParam);
1278     operatingRateParam->nU32 = mOperatingRate;
1279     return OMX_ErrorNone;
1280 }
1281 
1282 OMX_ERRORTYPE OMXVideoDecoderBase::GetErrorReportMode(OMX_PTR) {
1283     LOGE("GetErrorReportMode is not implemented");
1284     return OMX_ErrorNotImplemented;
1285 }
1286 
1287 OMX_ERRORTYPE OMXVideoDecoderBase::SetErrorReportMode(OMX_PTR pStructure) {
1288     OMX_ERRORTYPE ret;
1289 
1290     OMX_VIDEO_CONFIG_INTEL_ERROR_REPORT *p = (OMX_VIDEO_CONFIG_INTEL_ERROR_REPORT *)pStructure;
1291     CHECK_TYPE_HEADER(p);
1292     CHECK_PORT_INDEX(p, OUTPORT_INDEX);
1293 
1294     mErrorReportEnabled = p->bEnable;
1295     LOGD("Error reporting is %s", mErrorReportEnabled ? "enabled" : "disabled");
1296 
1297     mVideoDecoder->enableErrorReport(mErrorReportEnabled);
1298     return OMX_ErrorNone;
1299 }
1300 
1301 OMX_COLOR_FORMATTYPE OMXVideoDecoderBase::GetOutputColorFormat(int width) {
1302 #ifndef VED_TILING
1303     return OMX_INTEL_COLOR_FormatYUV420PackedSemiPlanar;
1304 #else
1305     if (width > 1280 && width <= 2048) {
1306         LOGI("HD Video and use tiled format");
1307         return OMX_INTEL_COLOR_FormatYUV420PackedSemiPlanar_Tiled;
1308     } else {
1309         return OMX_INTEL_COLOR_FormatYUV420PackedSemiPlanar;
1310     }
1311 #endif
1312 }
1313 
1314 OMX_ERRORTYPE OMXVideoDecoderBase::SetMaxOutputBufferCount(OMX_PARAM_PORTDEFINITIONTYPE *) {
1315     return OMX_ErrorNone;
1316 }
1317 
1318 uint32_t OMXVideoDecoderBase::getStride(uint32_t width) {
1319     uint32_t stride = 0;
1320 
1321     if (width <= 512)
1322         stride = 512;
1323     else if (width <= 1024)
1324         stride = 1024;
1325     else if (width <= 1280) {
1326         stride = 1280;
1327     } else if (width <= 2048)
1328         stride = 2048;
1329     else if (width <= 4096)
1330         stride = 4096;
1331     else
1332         stride = (width + 0x3f) & ~0x3f;
1333 
1334     return stride;
1335 }
1336