• 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 
18 #define LOG_NDEBUG 0
19 #define LOG_TAG "OMXVideoDecoderVP9HWR"
20 #include <wrs_omxil_core/log.h>
21 #include "OMXVideoDecoderVP9HWR.h"
22 
23 #include <system/window.h>
24 #include <HardwareAPI.h>
25 #include <hardware/hardware.h>
26 #include <hardware/gralloc.h>
27 #include <system/graphics.h>
28 
29 static const char* VP9_MIME_TYPE = "video/x-vnd.on2.vp9";
30 
GetCPUCoreCount()31 static int GetCPUCoreCount()
32 {
33     int cpuCoreCount = 1;
34 #if defined(_SC_NPROCESSORS_ONLN)
35     cpuCoreCount = sysconf(_SC_NPROCESSORS_ONLN);
36 #else
37     // _SC_NPROC_ONLN must be defined...
38     cpuCoreCount = sysconf(_SC_NPROC_ONLN);
39 #endif
40     if (cpuCoreCount < 1) {
41         LOGW("Get CPU Core Count error.");
42         cpuCoreCount = 1;
43     }
44     LOGV("Number of CPU cores: %d", cpuCoreCount);
45     return cpuCoreCount;
46 }
47 
48 
OMXVideoDecoderVP9HWR()49 OMXVideoDecoderVP9HWR::OMXVideoDecoderVP9HWR()
50 {
51     LOGV("OMXVideoDecoderVP9HWR is constructed.");
52 
53     mNumFrameBuffer = 0;
54     mCtx = NULL;
55 
56     mNativeBufferCount = OUTPORT_NATIVE_BUFFER_COUNT;
57     extUtilBufferCount = 0;
58     extMappedNativeBufferCount = 0;
59     BuildHandlerList();
60 
61     mDecodedImageWidth = 0;
62     mDecodedImageHeight = 0;
63     mDecodedImageNewWidth = 0;
64     mDecodedImageNewHeight = 0;
65 
66 #ifdef DECODE_WITH_GRALLOC_BUFFER
67     // setup va
68     VAStatus vaStatus = VA_STATUS_SUCCESS;
69     mDisplay = new Display;
70     *mDisplay = ANDROID_DISPLAY_HANDLE;
71 
72     mVADisplay = vaGetDisplay(mDisplay);
73     if (mVADisplay == NULL) {
74         LOGE("vaGetDisplay failed.");
75     }
76 
77     int majorVersion, minorVersion;
78     vaStatus = vaInitialize(mVADisplay, &majorVersion, &minorVersion);
79     if (vaStatus != VA_STATUS_SUCCESS) {
80         LOGE("vaInitialize failed.");
81     } else {
82         LOGV("va majorVersion=%d, minorVersion=%d", majorVersion, minorVersion);
83     }
84 #endif
85 }
86 
~OMXVideoDecoderVP9HWR()87 OMXVideoDecoderVP9HWR::~OMXVideoDecoderVP9HWR()
88 {
89     LOGV("OMXVideoDecoderVP9HWR is destructed.");
90 
91     if (mVADisplay) {
92         vaTerminate(mVADisplay);
93         mVADisplay = NULL;
94     }
95 }
96 
97 
98 // Callback func for vpx decoder to get decode buffer
99 // Now we map from the vaSurface to deploy gralloc buffer
100 // as decode buffer
getVP9FrameBuffer(void * user_priv,unsigned int new_size,vpx_codec_frame_buffer_t * fb)101 int getVP9FrameBuffer(void *user_priv,
102                           unsigned int new_size,
103                           vpx_codec_frame_buffer_t *fb)
104 {
105     OMXVideoDecoderVP9HWR * p = (OMXVideoDecoderVP9HWR *)user_priv;
106     if (fb == NULL) {
107         return -1;
108     }
109 
110     // TODO: Adaptive playback case needs to reconsider
111     if (p->extNativeBufferSize < new_size) {
112         LOGE("Provided frame buffer size < requesting min size.");
113         return -1;
114     }
115 
116     int i;
117     for (i = 0; i < p->extMappedNativeBufferCount; i++ ) {
118         if ((p->extMIDs[i]->m_render_done == true) &&
119             (p->extMIDs[i]->m_released == true)) {
120             fb->data = p->extMIDs[i]->m_usrAddr;
121             fb->size = p->extNativeBufferSize;
122             fb->fb_stride = p->extActualBufferStride;
123             fb->fb_height_stride = p->extActualBufferHeightStride;
124             fb->fb_index = i;
125             p->extMIDs[i]->m_released = false;
126             break;
127         }
128     }
129 
130     if (i == p->extMappedNativeBufferCount) {
131         LOGE("No available frame buffer in pool.");
132         return -1;
133     }
134     return 0;
135 }
136 
137 // call back function from libvpx to inform frame buffer
138 // not used anymore.
releaseVP9FrameBuffer(void * user_priv,vpx_codec_frame_buffer_t * fb)139 int releaseVP9FrameBuffer(void *user_priv, vpx_codec_frame_buffer_t *fb)
140 {
141     int i;
142     OMXVideoDecoderVP9HWR * p = (OMXVideoDecoderVP9HWR *)user_priv;
143     if (fb == NULL) {
144         return -1;
145     }
146     for (i = 0; i < p->extMappedNativeBufferCount; i++ ) {
147         if (fb->data == p->extMIDs[i]->m_usrAddr) {
148             p->extMIDs[i]->m_released = true;
149             break;
150         }
151     }
152 
153     if (i == p->extMappedNativeBufferCount) {
154         LOGE("Not found matching frame buffer in pool, libvpx's wrong?");
155         return -1;
156     }
157     return 0;
158 }
159 
160 
initDecoder()161 OMX_ERRORTYPE OMXVideoDecoderVP9HWR::initDecoder()
162 {
163     mCtx = new vpx_codec_ctx_t;
164     vpx_codec_err_t vpx_err;
165     vpx_codec_dec_cfg_t cfg;
166     memset(&cfg, 0, sizeof(vpx_codec_dec_cfg_t));
167     cfg.threads = GetCPUCoreCount();
168     if ((vpx_err = vpx_codec_dec_init(
169                 (vpx_codec_ctx_t *)mCtx,
170                  &vpx_codec_vp9_dx_algo,
171                  &cfg, 0))) {
172         LOGE("on2 decoder failed to initialize. (%d)", vpx_err);
173         return OMX_ErrorNotReady;
174     }
175 
176     mNumFrameBuffer = OUTPORT_NATIVE_BUFFER_COUNT;
177 
178     if (vpx_codec_set_frame_buffer_functions((vpx_codec_ctx_t *)mCtx,
179                                     getVP9FrameBuffer,
180                                     releaseVP9FrameBuffer,
181                                     this)) {
182       LOGE("Failed to configure external frame buffers");
183       return OMX_ErrorNotReady;
184     }
185 
186     return OMX_ErrorNone;
187 }
188 
destroyDecoder()189 OMX_ERRORTYPE OMXVideoDecoderVP9HWR::destroyDecoder()
190 {
191     vpx_codec_destroy((vpx_codec_ctx_t *)mCtx);
192     delete (vpx_codec_ctx_t *)mCtx;
193     mCtx = NULL;
194     return OMX_ErrorNone;
195 }
196 
197 
InitInputPortFormatSpecific(OMX_PARAM_PORTDEFINITIONTYPE * paramPortDefinitionInput)198 OMX_ERRORTYPE OMXVideoDecoderVP9HWR::InitInputPortFormatSpecific(
199     OMX_PARAM_PORTDEFINITIONTYPE *paramPortDefinitionInput)
200 {
201     paramPortDefinitionInput->nBufferCountActual = INPORT_ACTUAL_BUFFER_COUNT;
202     paramPortDefinitionInput->nBufferCountMin = INPORT_MIN_BUFFER_COUNT;
203     paramPortDefinitionInput->nBufferSize = INPORT_BUFFER_SIZE;
204     paramPortDefinitionInput->format.video.cMIMEType = (OMX_STRING)VP9_MIME_TYPE;
205     paramPortDefinitionInput->format.video.eCompressionFormat = OMX_VIDEO_CodingVP9;
206 
207     return OMX_ErrorNone;
208 }
209 
ProcessorInit(void)210 OMX_ERRORTYPE OMXVideoDecoderVP9HWR::ProcessorInit(void)
211 {
212     unsigned int i = 0;
213 
214     for (i = 0; i < MAX_NATIVE_BUFFER_COUNT; i++) {
215         extMIDs[i] = (vaapiMemId*)malloc(sizeof(vaapiMemId));
216         extMIDs[i]->m_usrAddr = NULL;
217         extMIDs[i]->m_surface = new VASurfaceID;
218     }
219 
220     initDecoder();
221 
222     if (RAWDATA_MODE == mWorkingMode) {
223         OMX_PARAM_PORTDEFINITIONTYPE paramPortDefinitionInput;
224 
225         memcpy(&paramPortDefinitionInput,
226                this->ports[INPORT_INDEX]->GetPortDefinition(),
227                sizeof(paramPortDefinitionInput));
228 
229         extNativeBufferSize = INTERNAL_MAX_FRAME_WIDTH *
230                               INTERNAL_MAX_FRAME_HEIGHT * 1.5;
231         extActualBufferStride = INTERNAL_MAX_FRAME_WIDTH;
232         extActualBufferHeightStride = INTERNAL_MAX_FRAME_HEIGHT;
233 
234         for (i = 0; i < OUTPORT_ACTUAL_BUFFER_COUNT; i++ ) {
235             extMIDs[i]->m_usrAddr = (unsigned char*)malloc(sizeof(unsigned char) *
236                                     extNativeBufferSize);
237             extMIDs[i]->m_render_done = true;
238             extMIDs[i]->m_released = true;
239         }
240         extMappedNativeBufferCount = OUTPORT_ACTUAL_BUFFER_COUNT;
241         return OMX_ErrorNone;
242     }
243 
244 #ifdef DECODE_WITH_GRALLOC_BUFFER
245     if (mOMXBufferHeaderTypePtrNum > MAX_NATIVE_BUFFER_COUNT) {
246         LOGE("Actual OMX outport buffer header type num (%d) > MAX_NATIVE_BUFFER_COUNT (%d)",
247               mOMXBufferHeaderTypePtrNum, MAX_NATIVE_BUFFER_COUNT);
248         return OMX_ErrorOverflow;
249     }
250 
251     OMX_PARAM_PORTDEFINITIONTYPE paramPortDefinitionInput;
252 
253     memcpy(&paramPortDefinitionInput,
254         this->ports[INPORT_INDEX]->GetPortDefinition(),
255         sizeof(paramPortDefinitionInput));
256 
257     int surfaceWidth = mGraphicBufferParam.graphicBufferWidth;
258     int surfaceHeight = mGraphicBufferParam.graphicBufferHeight;
259     int surfaceHStride = mGraphicBufferParam.graphicBufferHStride;
260     int surfaceVStride = mGraphicBufferParam.graphicBufferVStride;
261     extNativeBufferSize = mGraphicBufferParam.graphicBufferHStride *
262                           mGraphicBufferParam.graphicBufferVStride * 1.5;
263     extActualBufferStride = surfaceHStride;
264     extActualBufferHeightStride = surfaceVStride;
265 
266     for (i = 0; i < mOMXBufferHeaderTypePtrNum; i++) {
267         OMX_BUFFERHEADERTYPE *buf_hdr = mOMXBufferHeaderTypePtrArray[i];
268 
269         extMIDs[i]->m_key = (unsigned int)(buf_hdr->pBuffer);
270         extMIDs[i]->m_render_done = false;
271         extMIDs[i]->m_released = true;
272 
273         VAStatus va_res;
274         unsigned int buffer;
275         VASurfaceAttrib attribs[2];
276         VASurfaceAttribExternalBuffers* surfExtBuf = new VASurfaceAttribExternalBuffers;
277         int32_t format = VA_RT_FORMAT_YUV420;
278 
279         surfExtBuf->buffers= (unsigned long *)&buffer;
280         surfExtBuf->num_buffers = 1;
281         surfExtBuf->pixel_format = VA_FOURCC_NV12;
282         surfExtBuf->width = surfaceWidth;
283         surfExtBuf->height = surfaceHeight;
284         surfExtBuf->data_size = surfaceHStride * surfaceVStride * 1.5;
285         surfExtBuf->num_planes = 2;
286         surfExtBuf->pitches[0] = surfaceHStride;
287         surfExtBuf->pitches[1] = surfaceHStride;
288         surfExtBuf->pitches[2] = 0;
289         surfExtBuf->pitches[3] = 0;
290         surfExtBuf->offsets[0] = 0;
291         surfExtBuf->offsets[1] = surfaceHStride * surfaceVStride;
292         surfExtBuf->offsets[2] = 0;
293         surfExtBuf->offsets[3] = 0;
294         surfExtBuf->flags = VA_SURFACE_ATTRIB_MEM_TYPE_ANDROID_GRALLOC;
295 
296         surfExtBuf->buffers[0] = (unsigned int)buf_hdr->pBuffer;
297 
298         attribs[0].type = (VASurfaceAttribType)VASurfaceAttribMemoryType;
299         attribs[0].flags = VA_SURFACE_ATTRIB_SETTABLE;
300         attribs[0].value.type = VAGenericValueTypeInteger;
301         attribs[0].value.value.i = VA_SURFACE_ATTRIB_MEM_TYPE_ANDROID_GRALLOC;
302 
303         attribs[1].type = (VASurfaceAttribType)VASurfaceAttribExternalBufferDescriptor;
304         attribs[1].flags = VA_SURFACE_ATTRIB_SETTABLE;
305         attribs[1].value.type = VAGenericValueTypePointer;
306         attribs[1].value.value.p = (void *)surfExtBuf;
307 
308         va_res = vaCreateSurfaces(mVADisplay,
309                                   format,
310                                   surfaceWidth,
311                                   surfaceHeight,
312                                   extMIDs[i]->m_surface,
313                                   1,
314                                   attribs,
315                                   2);
316 
317         if (va_res != VA_STATUS_SUCCESS) {
318             LOGE("Failed to create vaSurface!");
319             return OMX_ErrorUndefined;
320         }
321 
322         delete surfExtBuf;
323 
324         VAImage image;
325         unsigned char* usrptr;
326 
327         va_res = vaDeriveImage(mVADisplay, *(extMIDs[i]->m_surface), &image);
328         if (VA_STATUS_SUCCESS == va_res) {
329             va_res = vaMapBuffer(mVADisplay, image.buf, (void **) &usrptr);
330             if (VA_STATUS_SUCCESS == va_res) {
331                 extMIDs[i]->m_usrAddr = usrptr;
332                 vaUnmapBuffer(mVADisplay, image.buf);
333             }
334             vaDestroyImage(mVADisplay, image.image_id);
335         }
336         extMappedNativeBufferCount++;
337     }
338     return OMX_ErrorNone;
339 #endif
340 }
341 
ProcessorDeinit(void)342 OMX_ERRORTYPE OMXVideoDecoderVP9HWR::ProcessorDeinit(void)
343 {
344     destroyDecoder();
345     unsigned int i = 0;
346     if (mWorkingMode == GRAPHICBUFFER_MODE) {
347         for (i = 0; i < mOMXBufferHeaderTypePtrNum; i++) {
348             if (extMIDs[i]->m_surface != NULL) {
349                 vaDestroySurfaces(mVADisplay, extMIDs[i]->m_surface, 1);
350             }
351         }
352 
353     } else if (mWorkingMode == RAWDATA_MODE) {
354         for (i = 0; i < OUTPORT_ACTUAL_BUFFER_COUNT; i++ ) {
355             if (extMIDs[i]->m_usrAddr != NULL) {
356                 free(extMIDs[i]->m_usrAddr);
357                 extMIDs[i]->m_usrAddr = NULL;
358             }
359         }
360     }
361     mOMXBufferHeaderTypePtrNum = 0;
362     memset(&mGraphicBufferParam, 0, sizeof(mGraphicBufferParam));
363     for (i = 0; i < MAX_NATIVE_BUFFER_COUNT; i++) {
364         delete extMIDs[i]->m_surface;
365         free(extMIDs[i]);
366     }
367     return OMXComponentCodecBase::ProcessorDeinit();
368 }
369 
ProcessorStop(void)370 OMX_ERRORTYPE OMXVideoDecoderVP9HWR::ProcessorStop(void)
371 {
372     return OMXComponentCodecBase::ProcessorStop();
373 }
374 
ProcessorFlush(OMX_U32)375 OMX_ERRORTYPE OMXVideoDecoderVP9HWR::ProcessorFlush(OMX_U32)
376 {
377     return OMX_ErrorNone;
378 }
379 
ProcessorPreFillBuffer(OMX_BUFFERHEADERTYPE * buffer)380 OMX_ERRORTYPE OMXVideoDecoderVP9HWR::ProcessorPreFillBuffer(OMX_BUFFERHEADERTYPE* buffer)
381 {
382     unsigned int handle = (unsigned int)buffer->pBuffer;
383     unsigned int i = 0;
384 
385     if (buffer->nOutputPortIndex == OUTPORT_INDEX){
386         for (i = 0; i < mOMXBufferHeaderTypePtrNum; i++) {
387             if (handle == extMIDs[i]->m_key) {
388                 extMIDs[i]->m_render_done = true;
389                 break;
390             }
391         }
392     }
393     return OMX_ErrorNone;
394 }
395 
ProcessorProcess(OMX_BUFFERHEADERTYPE *** pBuffers,buffer_retain_t * retains,OMX_U32)396 OMX_ERRORTYPE OMXVideoDecoderVP9HWR::ProcessorProcess(
397         OMX_BUFFERHEADERTYPE ***pBuffers,
398         buffer_retain_t *retains,
399         OMX_U32)
400 {
401     OMX_ERRORTYPE ret;
402     OMX_BUFFERHEADERTYPE *inBuffer = *pBuffers[INPORT_INDEX];
403     OMX_BOOL isResolutionChange = OMX_FALSE;
404 
405     if (inBuffer->pBuffer == NULL) {
406         LOGE("Buffer to decode is empty.");
407         return OMX_ErrorBadParameter;
408     }
409 
410     if (inBuffer->nFlags & OMX_BUFFERFLAG_CODECCONFIG) {
411         LOGI("Buffer has OMX_BUFFERFLAG_CODECCONFIG flag.");
412     }
413 
414     if (inBuffer->nFlags & OMX_BUFFERFLAG_DECODEONLY) {
415         LOGW("Buffer has OMX_BUFFERFLAG_DECODEONLY flag.");
416     }
417 
418     if (inBuffer->nFlags & OMX_BUFFERFLAG_EOS) {
419         if (inBuffer->nFilledLen == 0) {
420             (*pBuffers[OUTPORT_INDEX])->nFilledLen = 0;
421             (*pBuffers[OUTPORT_INDEX])->nFlags = OMX_BUFFERFLAG_EOS;
422             return OMX_ErrorNone;
423         }
424     }
425 
426     if (vpx_codec_decode((vpx_codec_ctx_t *)mCtx,
427                          inBuffer->pBuffer + inBuffer->nOffset,
428                          inBuffer->nFilledLen,
429                          NULL,
430                          0)) {
431         LOGE("on2 decoder failed to decode frame.");
432         return OMX_ErrorBadParameter;
433     }
434 
435     ret = FillRenderBuffer(pBuffers[OUTPORT_INDEX],
436                            &retains[OUTPORT_INDEX],
437                            ((*pBuffers[INPORT_INDEX]))->nFlags,
438                            &isResolutionChange);
439 
440     if (ret == OMX_ErrorNone) {
441         (*pBuffers[OUTPORT_INDEX])->nTimeStamp = inBuffer->nTimeStamp;
442     }
443 
444     if (isResolutionChange) {
445         HandleFormatChange();
446     }
447 
448     bool inputEoS = ((*pBuffers[INPORT_INDEX])->nFlags & OMX_BUFFERFLAG_EOS);
449     bool outputEoS = ((*pBuffers[OUTPORT_INDEX])->nFlags & OMX_BUFFERFLAG_EOS);
450     // if output port is not eos, retain the input buffer
451     // until all the output buffers are drained.
452     if (inputEoS && !outputEoS) {
453         retains[INPORT_INDEX] = BUFFER_RETAIN_GETAGAIN;
454         // the input buffer is retained for draining purpose.
455         // Set nFilledLen to 0 so buffer will not be decoded again.
456         (*pBuffers[INPORT_INDEX])->nFilledLen = 0;
457     }
458 
459     if (ret == OMX_ErrorNotReady) {
460         retains[OUTPORT_INDEX] = BUFFER_RETAIN_GETAGAIN;
461         ret = OMX_ErrorNone;
462     }
463 
464     return ret;
465 }
466 
ProcessorReset(void)467 OMX_ERRORTYPE OMXVideoDecoderVP9HWR::ProcessorReset(void)
468 {
469     return OMX_ErrorNone;
470 }
471 
ALIGN(int x,int y)472 static int ALIGN(int x, int y)
473 {
474     // y must be a power of 2.
475     return (x + y - 1) & ~(y - 1);
476 }
477 
HandleFormatChange(void)478 OMX_ERRORTYPE OMXVideoDecoderVP9HWR::HandleFormatChange(void)
479 {
480     mDecodedImageWidth = mDecodedImageNewWidth;
481     mDecodedImageHeight = mDecodedImageNewHeight;
482 
483     // Sync port definition as it may change.
484     OMX_PARAM_PORTDEFINITIONTYPE paramPortDefinitionInput, paramPortDefinitionOutput;
485 
486     memcpy(&paramPortDefinitionInput,
487         this->ports[INPORT_INDEX]->GetPortDefinition(),
488         sizeof(paramPortDefinitionInput));
489 
490     memcpy(&paramPortDefinitionOutput,
491         this->ports[OUTPORT_INDEX]->GetPortDefinition(),
492         sizeof(paramPortDefinitionOutput));
493 
494     uint32_t width = mDecodedImageWidth;
495     uint32_t height = mDecodedImageHeight;
496     uint32_t stride = mDecodedImageWidth;
497     uint32_t sliceHeight = mDecodedImageHeight;
498 
499     uint32_t widthCropped = mDecodedImageWidth;
500     uint32_t heightCropped = mDecodedImageHeight;
501     uint32_t strideCropped = widthCropped;
502     uint32_t sliceHeightCropped = heightCropped;
503 
504     if (widthCropped == paramPortDefinitionOutput.format.video.nFrameWidth &&
505         heightCropped == paramPortDefinitionOutput.format.video.nFrameHeight) {
506         if (mWorkingMode == RAWDATA_MODE) {
507             LOGW("Change of portsetting is not reported as size is not changed.");
508             return OMX_ErrorNone;
509         }
510     }
511 
512     paramPortDefinitionInput.format.video.nFrameWidth = width;
513     paramPortDefinitionInput.format.video.nFrameHeight = height;
514     paramPortDefinitionInput.format.video.nStride = stride;
515     paramPortDefinitionInput.format.video.nSliceHeight = sliceHeight;
516 
517     if (mWorkingMode == RAWDATA_MODE) {
518         paramPortDefinitionOutput.format.video.nFrameWidth = widthCropped;
519         paramPortDefinitionOutput.format.video.nFrameHeight = heightCropped;
520         paramPortDefinitionOutput.format.video.nStride = strideCropped;
521         paramPortDefinitionOutput.format.video.nSliceHeight = sliceHeightCropped;
522     } else if (mWorkingMode == GRAPHICBUFFER_MODE) {
523         // when the width and height ES parse are not larger than allocated graphic buffer in outport,
524         // there is no need to reallocate graphic buffer,just report the crop info to omx client
525         if (width <= mGraphicBufferParam.graphicBufferWidth &&
526             height <= mGraphicBufferParam.graphicBufferHeight) {
527             this->ports[INPORT_INDEX]->SetPortDefinition(&paramPortDefinitionInput, true);
528             this->ports[OUTPORT_INDEX]->ReportOutputCrop();
529             return OMX_ErrorNone;
530         }
531 
532         if (width > mGraphicBufferParam.graphicBufferWidth ||
533             height > mGraphicBufferParam.graphicBufferHeight) {
534             // update the real decoded resolution to outport instead of display resolution
535             // for graphic buffer reallocation
536             // when the width and height parsed from ES are larger than allocated graphic buffer in outport,
537             paramPortDefinitionOutput.format.video.nFrameWidth = width;
538             paramPortDefinitionOutput.format.video.nFrameHeight = (height + 0x1f) & ~0x1f;
539             paramPortDefinitionOutput.format.video.eColorFormat = GetOutputColorFormat(
540                     paramPortDefinitionOutput.format.video.nFrameWidth);
541             paramPortDefinitionOutput.format.video.nStride = stride;
542             paramPortDefinitionOutput.format.video.nSliceHeight = sliceHeight;
543        }
544     }
545 
546     paramPortDefinitionOutput.bEnabled = (OMX_BOOL)false;
547     mOMXBufferHeaderTypePtrNum = 0;
548     memset(&mGraphicBufferParam, 0, sizeof(mGraphicBufferParam));
549 
550     this->ports[INPORT_INDEX]->SetPortDefinition(&paramPortDefinitionInput, true);
551     this->ports[OUTPORT_INDEX]->SetPortDefinition(&paramPortDefinitionOutput, true);
552 
553     this->ports[OUTPORT_INDEX]->ReportPortSettingsChanged();
554     return OMX_ErrorNone;
555 }
556 
FillRenderBuffer(OMX_BUFFERHEADERTYPE ** pBuffer,buffer_retain_t * retain,OMX_U32 inportBufferFlags,OMX_BOOL * isResolutionChange)557 OMX_ERRORTYPE OMXVideoDecoderVP9HWR::FillRenderBuffer(OMX_BUFFERHEADERTYPE **pBuffer,
558                                                       buffer_retain_t *retain,
559                                                       OMX_U32 inportBufferFlags,
560                                                       OMX_BOOL *isResolutionChange)
561 {
562     OMX_BUFFERHEADERTYPE *buffer = *pBuffer;
563     OMX_BUFFERHEADERTYPE *buffer_orign = buffer;
564 
565     OMX_ERRORTYPE ret = OMX_ErrorNone;
566 
567     vpx_codec_iter_t iter = NULL;
568     vpx_image_t *img = NULL;
569     img = vpx_codec_get_frame((vpx_codec_ctx_t *)mCtx, &iter);
570 
571     if (img != NULL) {
572         if ((mDecodedImageWidth == 0) && (mDecodedImageHeight == 0)) { // init value
573             mDecodedImageWidth = img->d_w;
574             mDecodedImageHeight = img->d_h;
575         }
576         if ((mDecodedImageWidth != img->d_w) && (mDecodedImageHeight != img->d_h)) {
577             mDecodedImageNewWidth = img->d_w;
578             mDecodedImageNewHeight = img->d_h;
579             *isResolutionChange = OMX_TRUE;
580         }
581     }
582 
583     if (mWorkingMode == RAWDATA_MODE) {
584         if (img == NULL) {
585             LOGE("vpx_codec_get_frame return NULL.");
586             return OMX_ErrorNotReady;
587         }
588 
589         // in Raw data mode, this flag should be always true
590         extMIDs[img->fb_index]->m_render_done = true;
591 
592         void *dst = buffer->pBuffer;
593         uint8_t *dst_y = (uint8_t *)dst;
594 
595         const OMX_PARAM_PORTDEFINITIONTYPE *paramPortDefinitionOutput
596                                       = this->ports[OUTPORT_INDEX]->GetPortDefinition();
597 
598         size_t dst_y_size = paramPortDefinitionOutput->format.video.nStride *
599                             paramPortDefinitionOutput->format.video.nFrameHeight;
600         size_t dst_c_stride = ALIGN(paramPortDefinitionOutput->format.video.nStride / 2, 16);
601         size_t dst_c_size = dst_c_stride * paramPortDefinitionOutput->format.video.nFrameHeight / 2;
602         uint8_t *dst_v = dst_y + dst_y_size;
603         uint8_t *dst_u = dst_v + dst_c_size;
604 
605         //test border
606         dst_y += VPX_DECODE_BORDER * paramPortDefinitionOutput->format.video.nStride + VPX_DECODE_BORDER;
607         dst_v += (VPX_DECODE_BORDER/2) * dst_c_stride + (VPX_DECODE_BORDER/2);
608         dst_u += (VPX_DECODE_BORDER/2) * dst_c_stride + (VPX_DECODE_BORDER/2);
609 
610         const uint8_t *srcLine = (const uint8_t *)img->planes[PLANE_Y];
611 
612         for (size_t i = 0; i < img->d_h; ++i) {
613             memcpy(dst_y, srcLine, img->d_w);
614 
615             srcLine += img->stride[PLANE_Y];
616             dst_y += paramPortDefinitionOutput->format.video.nStride;
617         }
618 
619         srcLine = (const uint8_t *)img->planes[PLANE_U];
620         for (size_t i = 0; i < img->d_h / 2; ++i) {
621             memcpy(dst_u, srcLine, img->d_w / 2);
622 
623             srcLine += img->stride[PLANE_U];
624             dst_u += dst_c_stride;
625         }
626 
627         srcLine = (const uint8_t *)img->planes[PLANE_V];
628         for (size_t i = 0; i < img->d_h / 2; ++i) {
629             memcpy(dst_v, srcLine, img->d_w / 2);
630 
631             srcLine += img->stride[PLANE_V];
632             dst_v += dst_c_stride;
633         }
634 
635         buffer->nOffset = 0;
636         buffer->nFilledLen = dst_y_size + dst_c_size * 2;
637         if (inportBufferFlags & OMX_BUFFERFLAG_EOS) {
638             buffer->nFlags = OMX_BUFFERFLAG_EOS;
639         }
640 
641         if (buffer_orign != buffer) {
642             *retain = BUFFER_RETAIN_OVERRIDDEN;
643         }
644         ret = OMX_ErrorNone;
645 
646         return ret;
647 
648     }
649 
650 #ifdef DECODE_WITH_GRALLOC_BUFFER
651     if (NULL != img) {
652         buffer = *pBuffer = mOMXBufferHeaderTypePtrArray[img->fb_index];
653 
654         if ((unsigned int)(buffer->pBuffer) != extMIDs[img->fb_index]->m_key) {
655             LOGE("There is gralloc handle mismatching between pool\
656                   and mOMXBufferHeaderTypePtrArray.");
657             return OMX_ErrorNotReady;
658         }
659 
660         extMIDs[img->fb_index]->m_render_done = false;
661 
662         buffer->nOffset = 0;
663 
664         size_t dst_y_size = img->d_w * img->d_h;
665 
666         buffer->nFilledLen = dst_y_size * 1.5; // suport only 4:2:0 for now
667 
668         if (inportBufferFlags & OMX_BUFFERFLAG_EOS) {
669             buffer->nFlags = OMX_BUFFERFLAG_EOS;
670         }
671 
672         if (buffer_orign != buffer) {
673             *retain = BUFFER_RETAIN_OVERRIDDEN;
674         }
675 
676         return OMX_ErrorNone;
677     } else {
678         LOGE("vpx_codec_get_frame return NULL.");
679         return OMX_ErrorNotReady;
680     }
681 #endif
682 }
683 
PrepareConfigBuffer(VideoConfigBuffer *)684 OMX_ERRORTYPE OMXVideoDecoderVP9HWR::PrepareConfigBuffer(VideoConfigBuffer *)
685 {
686     return OMX_ErrorNone;
687 }
688 
PrepareDecodeBuffer(OMX_BUFFERHEADERTYPE *,buffer_retain_t *,VideoDecodeBuffer *)689 OMX_ERRORTYPE OMXVideoDecoderVP9HWR::PrepareDecodeBuffer(OMX_BUFFERHEADERTYPE *,
690                                                          buffer_retain_t *,
691                                                          VideoDecodeBuffer *)
692 {
693     return OMX_ErrorNone;
694 }
695 
BuildHandlerList(void)696 OMX_ERRORTYPE OMXVideoDecoderVP9HWR::BuildHandlerList(void)
697 {
698     OMXVideoDecoderBase::BuildHandlerList();
699     return OMX_ErrorNone;
700 }
701 
GetParamVideoVp9(OMX_PTR)702 OMX_ERRORTYPE OMXVideoDecoderVP9HWR::GetParamVideoVp9(OMX_PTR)
703 {
704     return OMX_ErrorNone;
705 }
706 
SetParamVideoVp9(OMX_PTR)707 OMX_ERRORTYPE OMXVideoDecoderVP9HWR::SetParamVideoVp9(OMX_PTR)
708 {
709     return OMX_ErrorNone;
710 }
711 
GetOutputColorFormat(int)712 OMX_COLOR_FORMATTYPE OMXVideoDecoderVP9HWR::GetOutputColorFormat(int)
713 {
714     LOGV("Output color format is OMX_INTEL_COLOR_FormatHalYV12.");
715     return (OMX_COLOR_FORMATTYPE)HAL_PIXEL_FORMAT_YV12;
716 }
717 
GetDecoderOutputCropSpecific(OMX_PTR pStructure)718 OMX_ERRORTYPE OMXVideoDecoderVP9HWR::GetDecoderOutputCropSpecific(OMX_PTR pStructure)
719 {
720     OMX_ERRORTYPE ret = OMX_ErrorNone;
721     OMX_CONFIG_RECTTYPE *rectParams = (OMX_CONFIG_RECTTYPE *)pStructure;
722 
723     CHECK_TYPE_HEADER(rectParams);
724 
725     if (rectParams->nPortIndex != OUTPORT_INDEX) {
726         return OMX_ErrorUndefined;
727     }
728 
729     const OMX_PARAM_PORTDEFINITIONTYPE *paramPortDefinitionInput
730                                       = this->ports[INPORT_INDEX]->GetPortDefinition();
731 
732     rectParams->nLeft = VPX_DECODE_BORDER;
733     rectParams->nTop = VPX_DECODE_BORDER;
734     rectParams->nWidth = paramPortDefinitionInput->format.video.nFrameWidth;
735     rectParams->nHeight = paramPortDefinitionInput->format.video.nFrameHeight;
736 
737     return ret;
738 }
739 
GetNativeBufferUsageSpecific(OMX_PTR pStructure)740 OMX_ERRORTYPE OMXVideoDecoderVP9HWR::GetNativeBufferUsageSpecific(OMX_PTR pStructure)
741 {
742     OMX_ERRORTYPE ret;
743     android::GetAndroidNativeBufferUsageParams *param =
744         (android::GetAndroidNativeBufferUsageParams*)pStructure;
745     CHECK_TYPE_HEADER(param);
746 
747     param->nUsage |= (GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_SW_READ_NEVER \
748                      | GRALLOC_USAGE_SW_WRITE_OFTEN | GRALLOC_USAGE_EXTERNAL_DISP);
749     return OMX_ErrorNone;
750 
751 }
752 
SetNativeBufferModeSpecific(OMX_PTR pStructure)753 OMX_ERRORTYPE OMXVideoDecoderVP9HWR::SetNativeBufferModeSpecific(OMX_PTR pStructure)
754 {
755     OMX_ERRORTYPE ret;
756     EnableAndroidNativeBuffersParams *param =
757         (EnableAndroidNativeBuffersParams*)pStructure;
758 
759     CHECK_TYPE_HEADER(param);
760     CHECK_PORT_INDEX_RANGE(param);
761     CHECK_SET_PARAM_STATE();
762 
763     if (!param->enable) {
764         mWorkingMode = RAWDATA_MODE;
765         return OMX_ErrorNone;
766     }
767     mWorkingMode = GRAPHICBUFFER_MODE;
768     PortVideo *port = NULL;
769     port = static_cast<PortVideo *>(this->ports[OUTPORT_INDEX]);
770 
771 
772     OMX_PARAM_PORTDEFINITIONTYPE port_def;
773     memcpy(&port_def,port->GetPortDefinition(),sizeof(port_def));
774     port_def.nBufferCountMin = mNativeBufferCount;
775     port_def.nBufferCountActual = mNativeBufferCount;
776     port_def.format.video.cMIMEType = (OMX_STRING)VA_VED_RAW_MIME_TYPE;
777     port_def.format.video.eColorFormat = OMX_INTEL_COLOR_FormatYUV420PackedSemiPlanar;
778 
779     // add borders for libvpx decode need.
780     port_def.format.video.nFrameHeight += VPX_DECODE_BORDER * 2;
781     port_def.format.video.nFrameWidth += VPX_DECODE_BORDER * 2;
782     // make heigth 32bit align
783     port_def.format.video.nFrameHeight = (port_def.format.video.nFrameHeight + 0x1f) & ~0x1f;
784     port_def.format.video.eColorFormat = GetOutputColorFormat(
785                         port_def.format.video.nFrameWidth);
786     port->SetPortDefinition(&port_def,true);
787 
788      return OMX_ErrorNone;
789 }
790 
791 
IsAllBufferAvailable(void)792 bool OMXVideoDecoderVP9HWR::IsAllBufferAvailable(void)
793 {
794     bool b = ComponentBase::IsAllBufferAvailable();
795     if (b == false) {
796         return false;
797     }
798 
799     PortVideo *port = NULL;
800     port = static_cast<PortVideo *>(this->ports[OUTPORT_INDEX]);
801     const OMX_PARAM_PORTDEFINITIONTYPE* port_def = port->GetPortDefinition();
802      // if output port is disabled, retain the input buffer
803     if (!port_def->bEnabled) {
804         return false;
805     }
806 
807     unsigned int i = 0;
808     int found = 0;
809 
810     if (RAWDATA_MODE == mWorkingMode) {
811         for (i = 0; i < OUTPORT_ACTUAL_BUFFER_COUNT; i++) {
812             if (extMIDs[i]->m_released == true) {
813                found ++;
814                if (found > 1) { //libvpx sometimes needs 2 buffer when calling decode once.
815                    return true;
816                }
817             }
818         }
819     } else { // graphic buffer mode
820         for (i = 0; i < mOMXBufferHeaderTypePtrNum; i++) {
821             if ((extMIDs[i]->m_render_done == true) && (extMIDs[i]->m_released == true)) {
822                found ++;
823                if (found > 1) { //libvpx sometimes needs 2 buffer when calling decode once.
824                    return true;
825                }
826             }
827         }
828     }
829 
830     b = false;
831 
832     return b;
833 }
834 
835 DECLARE_OMX_COMPONENT("OMX.Intel.VideoDecoder.VP9.hwr", "video_decoder.vp9", OMXVideoDecoderVP9HWR);
836 
837