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(¶mPortDefinitionInput,
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(¶mPortDefinitionInput,
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(¶mPortDefinitionInput,
487 this->ports[INPORT_INDEX]->GetPortDefinition(),
488 sizeof(paramPortDefinitionInput));
489
490 memcpy(¶mPortDefinitionOutput,
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(¶mPortDefinitionInput, 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(¶mPortDefinitionInput, true);
551 this->ports[OUTPORT_INDEX]->SetPortDefinition(¶mPortDefinitionOutput, 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