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(¶mPortDefinitionInput,
551 this->ports[INPORT_INDEX]->GetPortDefinition(),
552 sizeof(paramPortDefinitionInput));
553
554 memcpy(¶mPortDefinitionOutput,
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(¶mPortDefinitionInput, 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(¶mPortDefinitionInput, true);
623 this->ports[OUTPORT_INDEX]->SetPortDefinition(¶mPortDefinitionOutput, 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