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