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