1 /*
2 * Copyright (c) 2012 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_TIME 0
18 //#define LOG_NDEBUG 0
19 #define LOG_TAG "OMXVideoDecoderVP9Hybrid"
20 #include <wrs_omxil_core/log.h>
21 #include "OMXVideoDecoderVP9Hybrid.h"
22 
23 #include <hardware/hardware.h>
24 #include <hardware/gralloc.h>
25 #include <system/graphics.h>
26 
27 #include <hal_public.h>
28 
29 #define VP9_YV12_ALIGN (128-1)
30 static const char* VP9_MIME_TYPE = "video/x-vnd.on2.vp9";
31 
OMXVideoDecoderVP9Hybrid()32 OMXVideoDecoderVP9Hybrid::OMXVideoDecoderVP9Hybrid() {
33     LOGV("OMXVideoDecoderVP9Hybrid is constructed.");
34     mNativeBufferCount = OUTPORT_NATIVE_BUFFER_COUNT;
35     BuildHandlerList();
36     mLibHandle = NULL;
37     mOpenDecoder = NULL;
38     mInitDecoder = NULL;
39     mCloseDecoder = NULL;
40     mSingalRenderDone = NULL;
41     mDecoderDecode = NULL;
42     mCheckBufferAvailable = NULL;
43     mGetOutput = NULL;
44     mGetRawDataOutput = NULL;
45     mGetFrameResolution = NULL;
46     mDeinitDecoder = NULL;
47     mLastTimeStamp = 0;
48     mWorkingMode = RAWDATA_MODE;
49     mDecodedImageWidth = 0;
50     mDecodedImageHeight = 0;
51     mDecodedImageNewWidth = 0;
52     mDecodedImageNewHeight = 0;
53 }
54 
~OMXVideoDecoderVP9Hybrid()55 OMXVideoDecoderVP9Hybrid::~OMXVideoDecoderVP9Hybrid() {
56     LOGV("OMXVideoDecoderVP9Hybrid is destructed.");
57 }
58 
InitInputPortFormatSpecific(OMX_PARAM_PORTDEFINITIONTYPE * paramPortDefinitionInput)59 OMX_ERRORTYPE OMXVideoDecoderVP9Hybrid::InitInputPortFormatSpecific(
60     OMX_PARAM_PORTDEFINITIONTYPE *paramPortDefinitionInput) {
61     // OMX_PARAM_PORTDEFINITIONTYPE
62     paramPortDefinitionInput->nBufferCountActual = INPORT_ACTUAL_BUFFER_COUNT;
63     paramPortDefinitionInput->nBufferCountMin = INPORT_MIN_BUFFER_COUNT;
64     paramPortDefinitionInput->nBufferSize = INPORT_BUFFER_SIZE;
65     paramPortDefinitionInput->format.video.cMIMEType = (OMX_STRING)VP9_MIME_TYPE;
66     paramPortDefinitionInput->format.video.eCompressionFormat = OMX_VIDEO_CodingVP9;
67     return OMX_ErrorNone;
68 }
69 
ProcessorInit(void)70 OMX_ERRORTYPE OMXVideoDecoderVP9Hybrid::ProcessorInit(void) {
71     uint32_t buff[MAX_GRAPHIC_BUFFER_NUM];
72     uint32_t i, bufferCount;
73     bool gralloc_mode = (mWorkingMode == GRAPHICBUFFER_MODE);
74     uint32_t bufferSize, bufferHStride, bufferHeight, bufferVStride, bufferWidth;
75     if (!gralloc_mode) {
76         bufferHStride = 1920;
77         bufferVStride = 1088;
78         bufferWidth = 1920;
79         bufferHeight = 1080;
80         bufferCount = 12;
81     } else {
82         if (mAPMode == METADATA_MODE) {
83             const OMX_PARAM_PORTDEFINITIONTYPE *def_output = this->ports[OUTPORT_INDEX]->GetPortDefinition();
84             if (def_output == NULL) {
85                 return OMX_ErrorBadParameter;
86             }
87             bufferCount = mMetaDataBuffersNum = def_output->nBufferCountActual;
88             mOMXBufferHeaderTypePtrNum = 0;
89 
90             mGraphicBufferParam.graphicBufferColorFormat = def_output->format.video.eColorFormat;
91             mGraphicBufferParam.graphicBufferHStride = (def_output->format.video.nFrameWidth + VP9_YV12_ALIGN) & ~VP9_YV12_ALIGN;
92             mGraphicBufferParam.graphicBufferVStride = (def_output->format.video.nFrameHeight + 0x1f) & ~0x1f;
93             mGraphicBufferParam.graphicBufferWidth = def_output->format.video.nFrameWidth;
94             mGraphicBufferParam.graphicBufferHeight = def_output->format.video.nFrameHeight;
95             mDecodedImageWidth = def_output->format.video.nFrameWidth;
96             mDecodedImageHeight = def_output->format.video.nFrameHeight;
97         } else{
98             bufferCount = mOMXBufferHeaderTypePtrNum;
99 
100             for (i = 0; i < bufferCount; i++ ) {
101                 OMX_BUFFERHEADERTYPE *buf_hdr = mOMXBufferHeaderTypePtrArray[i];
102                 buff[i] = (uint32_t)(buf_hdr->pBuffer);
103             }
104         }
105 
106         bufferHStride = mGraphicBufferParam.graphicBufferHStride;
107         bufferVStride = mGraphicBufferParam.graphicBufferVStride;
108         bufferWidth = mGraphicBufferParam.graphicBufferWidth;
109         bufferHeight = mGraphicBufferParam.graphicBufferHeight;
110     }
111 
112     bufferSize = bufferHStride * bufferVStride * 1.5;
113 
114     mLibHandle = dlopen("libDecoderVP9Hybrid.so", RTLD_NOW);
115     if (mLibHandle == NULL) {
116         LOGE("dlopen libDecoderVP9Hybrid.so fail\n");
117         return OMX_ErrorBadParameter;
118     } else {
119         LOGI("dlopen libDecoderVP9Hybrid.so successfully\n");
120     }
121     mOpenDecoder = (OpenFunc)dlsym(mLibHandle, "Decoder_Open");
122     mCloseDecoder = (CloseFunc)dlsym(mLibHandle, "Decoder_Close");
123     mInitDecoder = (InitFunc)dlsym(mLibHandle, "Decoder_Init");
124     mSingalRenderDone = (SingalRenderDoneFunc)dlsym(mLibHandle, "Decoder_SingalRenderDone");
125     mDecoderDecode = (DecodeFunc)dlsym(mLibHandle, "Decoder_Decode");
126     mCheckBufferAvailable = (IsBufferAvailableFunc)dlsym(mLibHandle, "Decoder_IsBufferAvailable");
127     mGetOutput = (GetOutputFunc)dlsym(mLibHandle, "Decoder_GetOutput");
128     mGetRawDataOutput = (GetRawDataOutputFunc)dlsym(mLibHandle, "Decoder_GetRawDataOutput");
129     mGetFrameResolution = (GetFrameResolutionFunc)dlsym(mLibHandle, "Decoder_GetFrameResolution");
130     mDeinitDecoder = (DeinitFunc)dlsym(mLibHandle, "Decoder_Deinit");
131     if (mOpenDecoder == NULL || mCloseDecoder == NULL
132         || mInitDecoder == NULL || mSingalRenderDone == NULL
133         || mDecoderDecode == NULL || mCheckBufferAvailable == NULL
134         || mGetOutput == NULL || mGetRawDataOutput == NULL
135         || mGetFrameResolution == NULL || mDeinitDecoder == NULL) {
136         return OMX_ErrorBadParameter;
137     }
138 
139     if (mOpenDecoder(&mCtx,&mHybridCtx) == false) {
140         LOGE("open hybrid Decoder fail\n");
141         return OMX_ErrorBadParameter;
142     }
143 
144     // FIXME: The proprietary part of the vp9hybrid decoder should be updated
145     //        to take VStride as well as Height. For now it's convenient to
146     //        use VStride as that was effectively what was done before..
147     mInitDecoder(mHybridCtx, bufferSize, bufferHStride, bufferWidth,
148         bufferHeight, bufferCount, gralloc_mode, buff, (uint32_t)mAPMode);
149     return OMX_ErrorNone;
150 }
151 
ProcessorReset(void)152 OMX_ERRORTYPE OMXVideoDecoderVP9Hybrid::ProcessorReset(void)
153 {
154     uint32_t buff[MAX_GRAPHIC_BUFFER_NUM];
155     uint32_t i, bufferCount;
156     bool gralloc_mode = (mWorkingMode == GRAPHICBUFFER_MODE);
157     uint32_t bufferSize, bufferHStride, bufferHeight, bufferVStride, bufferWidth;
158     if (!gralloc_mode) {
159         bufferHStride = mDecodedImageWidth;
160         bufferVStride = mDecodedImageHeight;
161         bufferWidth = mDecodedImageWidth;
162         bufferHeight = mDecodedImageHeight;
163         bufferSize = bufferHStride * bufferVStride * 1.5;
164         bufferCount = 12;
165     } else {
166         if (mAPMode == METADATA_MODE) {
167             const OMX_PARAM_PORTDEFINITIONTYPE *def_output = this->ports[OUTPORT_INDEX]->GetPortDefinition();
168             if (def_output == NULL) {
169                 return OMX_ErrorBadParameter;
170             }
171             bufferCount = mMetaDataBuffersNum = def_output->nBufferCountActual;
172             mOMXBufferHeaderTypePtrNum = 0;
173 
174             mGraphicBufferParam.graphicBufferColorFormat = def_output->format.video.eColorFormat;
175             mGraphicBufferParam.graphicBufferHStride = (def_output->format.video.nFrameWidth + VP9_YV12_ALIGN) & ~VP9_YV12_ALIGN;
176             mGraphicBufferParam.graphicBufferVStride = (def_output->format.video.nFrameHeight + 0x1f) & ~0x1f;
177             mGraphicBufferParam.graphicBufferWidth = def_output->format.video.nFrameWidth;
178             mGraphicBufferParam.graphicBufferHeight = def_output->format.video.nFrameHeight;
179         } else{
180             bufferCount = mOMXBufferHeaderTypePtrNum;
181 
182             for (i = 0; i < bufferCount; i++ ) {
183                 OMX_BUFFERHEADERTYPE *buf_hdr = mOMXBufferHeaderTypePtrArray[i];
184                 buff[i] = (uint32_t)(buf_hdr->pBuffer);
185             }
186         }
187         bufferHStride = mGraphicBufferParam.graphicBufferHStride;
188         bufferVStride = mGraphicBufferParam.graphicBufferVStride;
189         bufferWidth = mGraphicBufferParam.graphicBufferWidth;
190         bufferHeight = mGraphicBufferParam.graphicBufferHeight;
191     }
192 
193     bufferSize = bufferHStride * bufferVStride * 1.5;
194 
195     // FIXME: The proprietary part of the vp9hybrid decoder should be updated
196     //        to take VStride as well as Height. For now it's convenient to
197     //        use VStride as that was effectively what was done before..
198     mInitDecoder(mHybridCtx, bufferSize, bufferHStride, bufferWidth,
199         bufferHeight, bufferCount, gralloc_mode, buff, (uint32_t)mAPMode);
200     mFormatChanged = false;
201     return OMX_ErrorNone;
202 }
203 
isReallocateNeeded(const uint8_t * data,uint32_t data_sz)204 bool OMXVideoDecoderVP9Hybrid::isReallocateNeeded(const uint8_t * data,uint32_t data_sz)
205 {
206     bool gralloc_mode = (mWorkingMode == GRAPHICBUFFER_MODE);
207     uint32_t width, height;
208     bool ret = true;
209     if (gralloc_mode) {
210         ret = mGetFrameResolution(data,data_sz, &width, &height);
211         if (width == 0 || height == 0)
212             return false;
213 
214         if (ret) {
215             if (mAPMode == METADATA_MODE) {
216                 ret = (width != mDecodedImageWidth)
217                     || (height != mDecodedImageHeight);
218             } else {
219                 ret = width > mGraphicBufferParam.graphicBufferWidth
220                     || height > mGraphicBufferParam.graphicBufferHeight;
221             }
222             if (ret) {
223                 mDecodedImageNewWidth = width;
224                 mDecodedImageNewHeight = height;
225                 return true;
226             }
227         }
228     }
229 
230     return ret;
231 }
232 
ProcessorDeinit(void)233 OMX_ERRORTYPE OMXVideoDecoderVP9Hybrid::ProcessorDeinit(void) {
234     mCloseDecoder(mCtx,mHybridCtx);
235     mOMXBufferHeaderTypePtrNum = 0;
236     if (mLibHandle != NULL) {
237         dlclose(mLibHandle);
238         mLibHandle = NULL;
239     }
240     return OMX_ErrorNone;
241 }
242 
ProcessorStop(void)243 OMX_ERRORTYPE OMXVideoDecoderVP9Hybrid::ProcessorStop(void) {
244     return OMXComponentCodecBase::ProcessorStop();
245 }
246 
ProcessorFlush(OMX_U32 portIndex)247 OMX_ERRORTYPE OMXVideoDecoderVP9Hybrid::ProcessorFlush(OMX_U32 portIndex) {
248     if (portIndex == INPORT_INDEX || portIndex == OMX_ALL) {
249         // end the last frame
250         unsigned int width, height;
251         mDecoderDecode(mCtx,mHybridCtx,NULL,0,true);
252         mGetOutput(mCtx,mHybridCtx, &width, &height);
253     }
254     return OMX_ErrorNone;
255 }
256 
ProcessorPreFillBuffer(OMX_BUFFERHEADERTYPE * buffer)257 OMX_ERRORTYPE OMXVideoDecoderVP9Hybrid::ProcessorPreFillBuffer(OMX_BUFFERHEADERTYPE* buffer) {
258     if (buffer->nOutputPortIndex == OUTPORT_INDEX){
259         unsigned int handle;
260         if (mAPMode == METADATA_MODE) {
261             bool found = false;
262             if (mOMXBufferHeaderTypePtrNum < mMetaDataBuffersNum) {
263                 for (uint32_t i = 0; i < mOMXBufferHeaderTypePtrNum; i++) {
264                     if (mOMXBufferHeaderTypePtrArray[i] == buffer) {
265                         found = true;
266                         break;
267                     }
268                 }
269                 if (!found) {
270                     mOMXBufferHeaderTypePtrArray[mOMXBufferHeaderTypePtrNum] = buffer;
271                     mOMXBufferHeaderTypePtrNum++;
272                 }
273             } else {
274                 found = true;
275             }
276 
277             android::VideoGrallocMetadata *metadata = (android::VideoGrallocMetadata *)(buffer->pBuffer);
278             handle = (unsigned int)metadata->pHandle;
279             mSingalRenderDone(mHybridCtx, handle, !found);
280         } else {
281             handle = (unsigned int)buffer->pBuffer;
282             mSingalRenderDone(mHybridCtx, handle, false);
283         }
284     }
285     return OMX_ErrorNone;
286 }
287 
ProcessorProcess(OMX_BUFFERHEADERTYPE *** pBuffers,buffer_retain_t * retains,OMX_U32)288 OMX_ERRORTYPE OMXVideoDecoderVP9Hybrid::ProcessorProcess(
289         OMX_BUFFERHEADERTYPE ***pBuffers,
290         buffer_retain_t *retains,
291         OMX_U32)
292 {
293     OMX_ERRORTYPE ret;
294     OMX_BUFFERHEADERTYPE *inBuffer = *pBuffers[INPORT_INDEX];
295     OMX_BUFFERHEADERTYPE *outBuffer = *pBuffers[OUTPORT_INDEX];
296     OMX_BOOL isResolutionChange = OMX_FALSE;
297     bool eos = (inBuffer->nFlags & OMX_BUFFERFLAG_EOS)? true : false;
298     eos = eos && (inBuffer->nFilledLen == 0);
299     static unsigned char *firstFrame = NULL;
300     static uint32_t firstFrameSize = 0;
301 
302     if (inBuffer->pBuffer == NULL) {
303         LOGE("Buffer to decode is empty.");
304         return OMX_ErrorBadParameter;
305     }
306 
307     if (inBuffer->nFlags & OMX_BUFFERFLAG_CODECCONFIG) {
308         LOGI("Buffer has OMX_BUFFERFLAG_CODECCONFIG flag.");
309     }
310 
311     if (inBuffer->nFlags & OMX_BUFFERFLAG_DECODEONLY) {
312         LOGW("Buffer has OMX_BUFFERFLAG_DECODEONLY flag.");
313     }
314 
315     if (firstFrameSize == 0 && inBuffer->nFilledLen != 0 && inBuffer->nTimeStamp != 0) {
316         if (firstFrame != NULL) {
317             free(firstFrame);
318             firstFrame = NULL;
319         }
320 
321         firstFrame = (unsigned char *)malloc(inBuffer->nFilledLen);
322         memcpy(firstFrame, inBuffer->pBuffer + inBuffer->nOffset, inBuffer->nFilledLen);
323         firstFrameSize = inBuffer->nFilledLen;
324     }
325 
326     if ((mWorkingMode == GRAPHICBUFFER_MODE) && (mAPMode == METADATA_MODE) && (!mFormatChanged)) {
327         bool mRet = mGetFrameResolution(inBuffer->pBuffer + inBuffer->nOffset, inBuffer->nFilledLen,
328             &mDecodedImageNewWidth,&mDecodedImageNewHeight);
329 
330         if (mRet && ((mDecodedImageNewWidth != 0) && (mDecodedImageNewHeight != 0)) &&
331             ((mDecodedImageWidth != 0) && (mDecodedImageHeight != 0)) &&
332             ((mDecodedImageNewWidth != mDecodedImageWidth || mDecodedImageNewHeight != mDecodedImageHeight))) {
333             if (mLastTimeStamp == 0) {
334                 retains[INPORT_INDEX] = BUFFER_RETAIN_GETAGAIN;
335                 HandleFormatChange();
336                 return OMX_ErrorNone;
337             } else {
338                 // Detected format change in time.
339                 // drain the last frame, keep the current input buffer
340                 mDecoderDecode(mCtx, mHybridCtx, firstFrame, firstFrameSize, false);
341                 retains[INPORT_INDEX] = BUFFER_RETAIN_GETAGAIN;
342 
343                 mFormatChanged = true;
344 
345                 ret = FillRenderBuffer(pBuffers[OUTPORT_INDEX], &retains[OUTPORT_INDEX],
346                     eos ? OMX_BUFFERFLAG_EOS : 0, &isResolutionChange);
347 
348                 if (ret == OMX_ErrorNone)
349                     (*pBuffers[OUTPORT_INDEX])->nTimeStamp = mLastTimeStamp;
350 
351                 mLastTimeStamp = inBuffer->nTimeStamp;
352 
353                 free(firstFrame);
354                 firstFrame = NULL;
355                 firstFrameSize = 0;
356                 return ret;
357             }
358         } else if (!mRet && (mDecodedImageNewWidth == 0 || mDecodedImageNewHeight == 0)) {
359             retains[INPORT_INDEX] = BUFFER_RETAIN_NOT_RETAIN;
360             return OMX_ErrorBadParameter;
361         }
362     }
363 
364 #if LOG_TIME == 1
365     struct timeval tv_start, tv_end;
366     int32_t time_ms;
367     gettimeofday(&tv_start,NULL);
368 #endif
369     int res = mDecoderDecode(mCtx,mHybridCtx,inBuffer->pBuffer + inBuffer->nOffset,inBuffer->nFilledLen, eos);
370     if (res != 0) {
371         if (res == -2) {
372             if (isReallocateNeeded(inBuffer->pBuffer + inBuffer->nOffset,inBuffer->nFilledLen)) {
373                 if (mAPMode == METADATA_MODE) {
374                     mFormatChanged = true;
375                 } else {
376                     retains[INPORT_INDEX] = BUFFER_RETAIN_GETAGAIN;
377                     HandleFormatChange();
378                     return OMX_ErrorNone;
379                 }
380             }
381             // drain the last frame, keep the current input buffer
382             res = mDecoderDecode(mCtx,mHybridCtx,NULL,0,true);
383             retains[INPORT_INDEX] = BUFFER_RETAIN_GETAGAIN;
384         } else if (res == -3) {
385             LOGW("on2 decoder skipped to decode the frame.");
386             (*pBuffers[OUTPORT_INDEX])->nOffset = 0;
387             (*pBuffers[OUTPORT_INDEX])->nFilledLen = 0;
388             return OMX_ErrorNone;
389         } else {
390             LOGE("on2 decoder failed to decode frame.");
391             return OMX_ErrorBadParameter;
392         }
393     }
394 
395 #if LOG_TIME == 1
396     gettimeofday(&tv_end,NULL);
397     time_ms = (int32_t)(tv_end.tv_sec - tv_start.tv_sec) * 1000 + (int32_t)(tv_end.tv_usec - tv_start.tv_usec)/1000;
398     LOGI("vpx_codec_decode: %d ms", time_ms);
399 #endif
400 
401     ret = FillRenderBuffer(pBuffers[OUTPORT_INDEX],
402                            &retains[OUTPORT_INDEX],
403                            eos? OMX_BUFFERFLAG_EOS:0,
404                            &isResolutionChange);
405 
406     if (ret == OMX_ErrorNone) {
407         (*pBuffers[OUTPORT_INDEX])->nTimeStamp = mLastTimeStamp;
408     }
409     mLastTimeStamp = inBuffer->nTimeStamp;
410 
411     if (isResolutionChange == OMX_TRUE) {
412         HandleFormatChange();
413     }
414     bool inputEoS = ((*pBuffers[INPORT_INDEX])->nFlags & OMX_BUFFERFLAG_EOS);
415     bool outputEoS = ((*pBuffers[OUTPORT_INDEX])->nFlags & OMX_BUFFERFLAG_EOS);
416     // if output port is not eos, retain the input buffer
417     // until all the output buffers are drained.
418     if (inputEoS && !outputEoS && retains[INPORT_INDEX] != BUFFER_RETAIN_GETAGAIN) {
419         retains[INPORT_INDEX] = BUFFER_RETAIN_GETAGAIN;
420         // the input buffer is retained for draining purpose.
421         // Set nFilledLen to 0 so buffer will not be decoded again.
422         (*pBuffers[INPORT_INDEX])->nFilledLen = 0;
423     }
424 
425     if (ret == OMX_ErrorNotReady) {
426         retains[OUTPORT_INDEX] = BUFFER_RETAIN_GETAGAIN;
427         ret = OMX_ErrorNone;
428     }
429 
430     return ret;
431 }
432 
FillRenderBuffer(OMX_BUFFERHEADERTYPE ** pBuffer,buffer_retain_t * retain,OMX_U32 inportBufferFlags,OMX_BOOL * isResolutionChange)433 OMX_ERRORTYPE OMXVideoDecoderVP9Hybrid::FillRenderBuffer(OMX_BUFFERHEADERTYPE **pBuffer,
434                                                       buffer_retain_t *retain,
435                                                       OMX_U32 inportBufferFlags,
436                                                       OMX_BOOL *isResolutionChange)
437 {
438     OMX_BUFFERHEADERTYPE *buffer = *pBuffer;
439     OMX_BUFFERHEADERTYPE *buffer_orign = buffer;
440 
441     OMX_ERRORTYPE ret = OMX_ErrorNone;
442 
443     int fb_index;
444     if (mWorkingMode == RAWDATA_MODE) {
445         const OMX_PARAM_PORTDEFINITIONTYPE *paramPortDefinitionOutput
446                        = this->ports[OUTPORT_INDEX]->GetPortDefinition();
447         int32_t stride = paramPortDefinitionOutput->format.video.nStride;
448         int32_t height =  paramPortDefinitionOutput->format.video.nFrameHeight;
449         int32_t width = paramPortDefinitionOutput->format.video.nFrameWidth;
450         unsigned char *dst = buffer->pBuffer;
451         fb_index = mGetRawDataOutput(mCtx,mHybridCtx,dst,height,stride);
452         if (fb_index == -1) {
453             if (inportBufferFlags & OMX_BUFFERFLAG_EOS) {
454                 // eos frame is non-shown frame
455                 buffer->nFlags = OMX_BUFFERFLAG_EOS;
456                 buffer->nOffset = 0;
457                 buffer->nFilledLen = 0;
458                 return OMX_ErrorNone;
459             }
460             LOGV("vpx_codec_get_frame return NULL.");
461             return OMX_ErrorNotReady;
462         }
463         buffer->nOffset = 0;
464         buffer->nFilledLen = stride*height*3/2;
465         if (inportBufferFlags & OMX_BUFFERFLAG_EOS) {
466             buffer->nFlags = OMX_BUFFERFLAG_EOS;
467         }
468         return OMX_ErrorNone;
469     }
470 
471     if (mFormatChanged && mAPMode == METADATA_MODE) {
472         fb_index = mGetOutput(mCtx,mHybridCtx, &mDecodedImageWidth, &mDecodedImageHeight);
473     } else {
474         fb_index = mGetOutput(mCtx,mHybridCtx, &mDecodedImageNewWidth, &mDecodedImageNewHeight);
475     }
476     if (fb_index == -1) {
477         if (mFormatChanged && mAPMode == METADATA_MODE) {
478             *isResolutionChange = OMX_TRUE;
479             return OMX_ErrorNone;
480     }
481 
482         if (inportBufferFlags & OMX_BUFFERFLAG_EOS) {
483             // eos frame is no-shown frame
484             buffer->nFlags = OMX_BUFFERFLAG_EOS;
485             buffer->nOffset = 0;
486             buffer->nFilledLen = 0;
487             return OMX_ErrorNone;
488         }
489         LOGV("vpx_codec_get_frame return NULL.");
490         return OMX_ErrorNotReady;
491     }
492     if (mDecodedImageHeight == 0 && mDecodedImageWidth == 0) {
493         mDecodedImageWidth = mDecodedImageNewWidth;
494         mDecodedImageHeight = mDecodedImageNewHeight;
495         if (mAPMode == LEGACY_MODE)
496             *isResolutionChange = OMX_TRUE;
497     }
498 
499     if (mAPMode == LEGACY_MODE) {
500     if ((mDecodedImageNewWidth != mDecodedImageWidth)
501         || (mDecodedImageNewHeight!= mDecodedImageHeight))
502         *isResolutionChange = OMX_TRUE;
503     } else {
504         if (mFormatChanged && ((mDecodedImageNewWidth != mDecodedImageWidth)
505             || (mDecodedImageNewHeight!= mDecodedImageHeight)))
506             *isResolutionChange = OMX_TRUE;
507     }
508     buffer = *pBuffer = mOMXBufferHeaderTypePtrArray[fb_index];
509     buffer->nOffset = 0;
510     buffer->nFilledLen = sizeof(OMX_U8*);
511     if (inportBufferFlags & OMX_BUFFERFLAG_EOS) {
512         buffer->nFlags = OMX_BUFFERFLAG_EOS;
513     }
514 
515     if (buffer_orign != buffer) {
516         *retain = BUFFER_RETAIN_OVERRIDDEN;
517     }
518 
519     ret = OMX_ErrorNone;
520 
521     return ret;
522 
523 }
524 
PrepareConfigBuffer(VideoConfigBuffer *)525 OMX_ERRORTYPE OMXVideoDecoderVP9Hybrid::PrepareConfigBuffer(VideoConfigBuffer *) {
526     return OMX_ErrorNone;
527 }
528 
PrepareDecodeBuffer(OMX_BUFFERHEADERTYPE *,buffer_retain_t *,VideoDecodeBuffer *)529 OMX_ERRORTYPE OMXVideoDecoderVP9Hybrid::PrepareDecodeBuffer(OMX_BUFFERHEADERTYPE *,
530                                                          buffer_retain_t *,
531                                                          VideoDecodeBuffer *) {
532     return OMX_ErrorNone;
533 }
534 
BuildHandlerList(void)535 OMX_ERRORTYPE OMXVideoDecoderVP9Hybrid::BuildHandlerList(void) {
536     OMXVideoDecoderBase::BuildHandlerList();
537     return OMX_ErrorNone;
538 }
539 
GetParamVideoVp9(OMX_PTR)540 OMX_ERRORTYPE OMXVideoDecoderVP9Hybrid::GetParamVideoVp9(OMX_PTR) {
541     return OMX_ErrorNone;
542 }
543 
SetParamVideoVp9(OMX_PTR)544 OMX_ERRORTYPE OMXVideoDecoderVP9Hybrid::SetParamVideoVp9(OMX_PTR) {
545     return OMX_ErrorNone;
546 }
547 
HandleFormatChange(void)548 OMX_ERRORTYPE OMXVideoDecoderVP9Hybrid::HandleFormatChange(void)
549 {
550     ALOGE("handle format change from %dx%d to %dx%d",
551         mDecodedImageWidth,mDecodedImageHeight,mDecodedImageNewWidth,mDecodedImageNewHeight);
552     mDecodedImageWidth = mDecodedImageNewWidth;
553     mDecodedImageHeight = mDecodedImageNewHeight;
554     // Sync port definition as it may change.
555     OMX_PARAM_PORTDEFINITIONTYPE paramPortDefinitionInput, paramPortDefinitionOutput;
556 
557     memcpy(&paramPortDefinitionInput,
558         this->ports[INPORT_INDEX]->GetPortDefinition(),
559         sizeof(paramPortDefinitionInput));
560 
561     memcpy(&paramPortDefinitionOutput,
562         this->ports[OUTPORT_INDEX]->GetPortDefinition(),
563         sizeof(paramPortDefinitionOutput));
564 
565     unsigned int width = mDecodedImageWidth;
566     unsigned int height = mDecodedImageHeight;
567     unsigned int stride = mDecodedImageWidth;
568     unsigned int sliceHeight = mDecodedImageHeight;
569 
570     unsigned int widthCropped = mDecodedImageWidth;
571     unsigned int heightCropped = mDecodedImageHeight;
572     unsigned int strideCropped = widthCropped;
573     unsigned int sliceHeightCropped = heightCropped;
574 
575     if (widthCropped == paramPortDefinitionOutput.format.video.nFrameWidth &&
576         heightCropped == paramPortDefinitionOutput.format.video.nFrameHeight) {
577         if (mWorkingMode == RAWDATA_MODE) {
578             LOGW("Change of portsetting is not reported as size is not changed.");
579             return OMX_ErrorNone;
580         }
581     }
582 
583     if (mAPMode == METADATA_MODE) {
584        paramPortDefinitionOutput.nBufferCountActual = mNativeBufferCount;
585        paramPortDefinitionOutput.nBufferCountMin = mNativeBufferCount - 4;
586     }
587     paramPortDefinitionInput.format.video.nFrameWidth = width;
588     paramPortDefinitionInput.format.video.nFrameHeight = height;
589     paramPortDefinitionInput.format.video.nStride = stride;
590     paramPortDefinitionInput.format.video.nSliceHeight = sliceHeight;
591 
592     if (mWorkingMode == RAWDATA_MODE) {
593         paramPortDefinitionOutput.format.video.nFrameWidth = widthCropped;
594         paramPortDefinitionOutput.format.video.nFrameHeight = heightCropped;
595         paramPortDefinitionOutput.format.video.nStride = strideCropped;
596         paramPortDefinitionOutput.format.video.nSliceHeight = sliceHeightCropped;
597     } else if (mWorkingMode == GRAPHICBUFFER_MODE) {
598         // when the width and height ES parse are not larger than allocated graphic buffer in outport,
599         // there is no need to reallocate graphic buffer,just report the crop info to omx client
600         if (mAPMode == LEGACY_MODE &&
601             width <= mGraphicBufferParam.graphicBufferWidth &&
602             height <= mGraphicBufferParam.graphicBufferHeight) {
603             this->ports[INPORT_INDEX]->SetPortDefinition(&paramPortDefinitionInput, true);
604             this->ports[OUTPORT_INDEX]->ReportOutputCrop();
605             return OMX_ErrorNone;
606         }
607 
608         if (mAPMode == METADATA_MODE ||
609             width > mGraphicBufferParam.graphicBufferWidth ||
610             height > mGraphicBufferParam.graphicBufferHeight) {
611             // update the real decoded resolution to outport instead of display resolution
612             // for graphic buffer reallocation
613             // when the width and height parsed from ES are larger than allocated graphic buffer in outport,
614             paramPortDefinitionOutput.format.video.nFrameWidth = width;
615             paramPortDefinitionOutput.format.video.nFrameHeight = height;
616             paramPortDefinitionOutput.format.video.eColorFormat = GetOutputColorFormat(
617                     paramPortDefinitionOutput.format.video.nFrameWidth);
618             paramPortDefinitionOutput.format.video.nStride = stride;
619             paramPortDefinitionOutput.format.video.nSliceHeight = sliceHeight;
620        }
621     }
622 
623     paramPortDefinitionOutput.bEnabled = (OMX_BOOL)false;
624     mOMXBufferHeaderTypePtrNum = 0;
625     mMetaDataBuffersNum = 0;
626     memset(&mGraphicBufferParam, 0, sizeof(mGraphicBufferParam));
627     mDeinitDecoder(mHybridCtx);
628 
629     this->ports[INPORT_INDEX]->SetPortDefinition(&paramPortDefinitionInput, true);
630     this->ports[OUTPORT_INDEX]->SetPortDefinition(&paramPortDefinitionOutput, true);
631 
632     this->ports[OUTPORT_INDEX]->ReportPortSettingsChanged();
633     return OMX_ErrorNone;
634 }
635 
636 
GetOutputColorFormat(int)637 OMX_COLOR_FORMATTYPE OMXVideoDecoderVP9Hybrid::GetOutputColorFormat(int) {
638     LOGV("Output color format is HAL_PIXEL_FORMAT_INTEL_YV12.");
639     return (OMX_COLOR_FORMATTYPE)HAL_PIXEL_FORMAT_INTEL_YV12;
640 }
641 
GetDecoderOutputCropSpecific(OMX_PTR pStructure)642 OMX_ERRORTYPE OMXVideoDecoderVP9Hybrid::GetDecoderOutputCropSpecific(OMX_PTR pStructure) {
643 
644     OMX_ERRORTYPE ret = OMX_ErrorNone;
645     OMX_CONFIG_RECTTYPE *rectParams = (OMX_CONFIG_RECTTYPE *)pStructure;
646 
647     CHECK_TYPE_HEADER(rectParams);
648 
649     if (rectParams->nPortIndex != OUTPORT_INDEX) {
650         return OMX_ErrorUndefined;
651     }
652 
653     const OMX_PARAM_PORTDEFINITIONTYPE *paramPortDefinitionInput
654                                       = this->ports[INPORT_INDEX]->GetPortDefinition();
655 
656     rectParams->nLeft = VPX_DECODE_BORDER;
657     rectParams->nTop = VPX_DECODE_BORDER;
658     rectParams->nWidth = paramPortDefinitionInput->format.video.nFrameWidth;
659     rectParams->nHeight = paramPortDefinitionInput->format.video.nFrameHeight;
660 
661     return ret;
662 }
663 
GetNativeBufferUsageSpecific(OMX_PTR pStructure)664 OMX_ERRORTYPE OMXVideoDecoderVP9Hybrid::GetNativeBufferUsageSpecific(OMX_PTR pStructure) {
665     OMX_ERRORTYPE ret;
666     android::GetAndroidNativeBufferUsageParams *param =
667         (android::GetAndroidNativeBufferUsageParams*)pStructure;
668     CHECK_TYPE_HEADER(param);
669 
670     param->nUsage |= (GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_SW_READ_OFTEN
671                      | GRALLOC_USAGE_SW_WRITE_OFTEN | GRALLOC_USAGE_EXTERNAL_DISP);
672     return OMX_ErrorNone;
673 
674 }
SetNativeBufferModeSpecific(OMX_PTR pStructure)675 OMX_ERRORTYPE OMXVideoDecoderVP9Hybrid::SetNativeBufferModeSpecific(OMX_PTR pStructure) {
676     OMX_ERRORTYPE ret;
677     android::EnableAndroidNativeBuffersParams *param =
678         (android::EnableAndroidNativeBuffersParams*)pStructure;
679 
680     CHECK_TYPE_HEADER(param);
681     CHECK_PORT_INDEX_RANGE(param);
682     CHECK_SET_PARAM_STATE();
683 
684     PortVideo *port = NULL;
685     port = static_cast<PortVideo *>(this->ports[OUTPORT_INDEX]);
686     OMX_PARAM_PORTDEFINITIONTYPE port_def;
687     memcpy(&port_def,port->GetPortDefinition(),sizeof(port_def));
688 
689     if (!param->enable) {
690         mWorkingMode = RAWDATA_MODE;
691         LOGI("Raw data mode is used");
692         // If it is fallback from native mode the color format has been
693         // already set to INTEL format.
694         // We need to set back the default color format and Native stuff.
695         port_def.format.video.eColorFormat = OMX_COLOR_FormatYUV420SemiPlanar;
696         port_def.format.video.pNativeRender = NULL;
697         port_def.format.video.pNativeWindow = NULL;
698         port->SetPortDefinition(&port_def,true);
699         return OMX_ErrorNone;
700     }
701 
702     mWorkingMode = GRAPHICBUFFER_MODE;
703     port_def.nBufferCountMin = mNativeBufferCount - 4;
704     port_def.nBufferCountActual = mNativeBufferCount;
705     port_def.format.video.cMIMEType = (OMX_STRING)VA_VED_RAW_MIME_TYPE;
706     // add borders for libvpx decode need.
707     port_def.format.video.nFrameWidth += VPX_DECODE_BORDER * 2;
708     port_def.format.video.nFrameHeight += VPX_DECODE_BORDER * 2;
709     mDecodedImageWidth = port_def.format.video.nFrameWidth;
710     mDecodedImageHeight = port_def.format.video.nFrameHeight;
711     port_def.format.video.eColorFormat = GetOutputColorFormat(port_def.format.video.nFrameWidth);
712     port->SetPortDefinition(&port_def,true);
713 
714      return OMX_ErrorNone;
715 }
716 
717 
IsAllBufferAvailable(void)718 bool OMXVideoDecoderVP9Hybrid::IsAllBufferAvailable(void) {
719     bool b = ComponentBase::IsAllBufferAvailable();
720     if (b == false) {
721         return false;
722     }
723 
724     PortVideo *port = NULL;
725     port = static_cast<PortVideo *>(this->ports[OUTPORT_INDEX]);
726     const OMX_PARAM_PORTDEFINITIONTYPE* port_def = port->GetPortDefinition();
727      // if output port is disabled, retain the input buffer
728     if (!port_def->bEnabled) {
729         return false;
730     }
731     return mCheckBufferAvailable(mHybridCtx);
732 }
733 
734 DECLARE_OMX_COMPONENT("OMX.Intel.VideoDecoder.VP9.hybrid", "video_decoder.vp9", OMXVideoDecoderVP9Hybrid);
735