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