1 /*
2 * Copyright (c) 2009-2011 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_NDEBUG 0
18 #define LOG_TAG "OMXVideoDecoder"
19 #include <wrs_omxil_core/log.h>
20
21 #include <nativebase/nativebase.h>
22 #include <hardware/gralloc.h>
23 #include <va/va_android.h>
24
25 #include "OMXVideoDecoderBase.h"
26 #include "ProtectedDataBuffer.h"
27
28
29 static const char* VA_RAW_MIME_TYPE = "video/x-raw-va";
30 static const uint32_t VA_COLOR_FORMAT = 0x7FA00E00;
31
OMXVideoDecoderBase()32 OMXVideoDecoderBase::OMXVideoDecoderBase()
33 : mRotationDegrees(0),
34 #ifdef TARGET_HAS_ISV
35 mVppBufferNum(0),
36 #endif
37 mCodecPriority(1),
38 mOperatingRate(0),
39 mVideoDecoder(NULL),
40 mNativeBufferCount(OUTPORT_NATIVE_BUFFER_COUNT),
41 mWorkingMode(RAWDATA_MODE),
42 mErrorReportEnabled (false),
43 mAPMode(LEGACY_MODE),
44 mFlushMode(false),
45 mFormatChanged(false) {
46 mOMXBufferHeaderTypePtrNum = 0;
47 mMetaDataBuffersNum = 0;
48 memset(&mGraphicBufferParam, 0, sizeof(mGraphicBufferParam));
49 }
50
~OMXVideoDecoderBase()51 OMXVideoDecoderBase::~OMXVideoDecoderBase() {
52 releaseVideoDecoder(mVideoDecoder);
53
54 if (this->ports) {
55 if (this->ports[INPORT_INDEX]) {
56 delete this->ports[INPORT_INDEX];
57 this->ports[INPORT_INDEX] = NULL;
58 }
59
60 if (this->ports[OUTPORT_INDEX]) {
61 delete this->ports[OUTPORT_INDEX];
62 this->ports[OUTPORT_INDEX] = NULL;
63 }
64 }
65 }
66
InitInputPort(void)67 OMX_ERRORTYPE OMXVideoDecoderBase::InitInputPort(void) {
68 this->ports[INPORT_INDEX] = new PortVideo;
69 if (this->ports[INPORT_INDEX] == NULL) {
70 return OMX_ErrorInsufficientResources;
71 }
72
73 PortVideo *port = static_cast<PortVideo *>(this->ports[INPORT_INDEX]);
74
75 // OMX_PARAM_PORTDEFINITIONTYPE
76 OMX_PARAM_PORTDEFINITIONTYPE paramPortDefinitionInput;
77 memset(¶mPortDefinitionInput, 0, sizeof(paramPortDefinitionInput));
78 SetTypeHeader(¶mPortDefinitionInput, sizeof(paramPortDefinitionInput));
79 paramPortDefinitionInput.nPortIndex = INPORT_INDEX;
80 paramPortDefinitionInput.eDir = OMX_DirInput;
81 paramPortDefinitionInput.nBufferCountActual = INPORT_ACTUAL_BUFFER_COUNT;
82 paramPortDefinitionInput.nBufferCountMin = INPORT_MIN_BUFFER_COUNT;
83 paramPortDefinitionInput.nBufferSize = INPORT_BUFFER_SIZE;
84 paramPortDefinitionInput.bEnabled = OMX_TRUE;
85 paramPortDefinitionInput.bPopulated = OMX_FALSE;
86 paramPortDefinitionInput.eDomain = OMX_PortDomainVideo;
87 paramPortDefinitionInput.format.video.cMIMEType = NULL; // to be overridden
88 paramPortDefinitionInput.format.video.pNativeRender = NULL;
89 paramPortDefinitionInput.format.video.nFrameWidth = 176;
90 paramPortDefinitionInput.format.video.nFrameHeight = 144;
91 paramPortDefinitionInput.format.video.nStride = 0;
92 paramPortDefinitionInput.format.video.nSliceHeight = 0;
93 paramPortDefinitionInput.format.video.nBitrate = 64000;
94 paramPortDefinitionInput.format.video.xFramerate = 15 << 16;
95 // TODO: check if we need to set bFlagErrorConcealment to OMX_TRUE
96 paramPortDefinitionInput.format.video.bFlagErrorConcealment = OMX_FALSE;
97 paramPortDefinitionInput.format.video.eCompressionFormat = OMX_VIDEO_CodingUnused; // to be overridden
98 paramPortDefinitionInput.format.video.eColorFormat = OMX_COLOR_FormatUnused;
99 paramPortDefinitionInput.format.video.pNativeWindow = NULL;
100 paramPortDefinitionInput.bBuffersContiguous = OMX_FALSE;
101 paramPortDefinitionInput.nBufferAlignment = 0;
102
103 // Derived class must implement this interface and override any field if needed.
104 // eCompressionFormat and and cMIMEType must be overridden
105 InitInputPortFormatSpecific(¶mPortDefinitionInput);
106
107 port->SetPortDefinition(¶mPortDefinitionInput, true);
108
109 // OMX_VIDEO_PARAM_PORTFORMATTYPE
110 OMX_VIDEO_PARAM_PORTFORMATTYPE paramPortFormat;
111 memset(¶mPortFormat, 0, sizeof(paramPortFormat));
112 SetTypeHeader(¶mPortFormat, sizeof(paramPortFormat));
113 paramPortFormat.nPortIndex = INPORT_INDEX;
114 paramPortFormat.nIndex = 0;
115 paramPortFormat.eCompressionFormat = paramPortDefinitionInput.format.video.eCompressionFormat;
116 paramPortFormat.eColorFormat = paramPortDefinitionInput.format.video.eColorFormat;
117 paramPortFormat.xFramerate = paramPortDefinitionInput.format.video.xFramerate;
118
119 port->SetPortVideoParam(¶mPortFormat, true);
120
121 return OMX_ErrorNone;
122 }
123
124
InitOutputPort(void)125 OMX_ERRORTYPE OMXVideoDecoderBase::InitOutputPort(void) {
126 this->ports[OUTPORT_INDEX] = new PortVideo;
127 if (this->ports[OUTPORT_INDEX] == NULL) {
128 return OMX_ErrorInsufficientResources;
129 }
130
131 PortVideo *port = static_cast<PortVideo *>(this->ports[OUTPORT_INDEX]);
132
133 // OMX_PARAM_PORTDEFINITIONTYPE
134 OMX_PARAM_PORTDEFINITIONTYPE paramPortDefinitionOutput;
135
136 memset(¶mPortDefinitionOutput, 0, sizeof(paramPortDefinitionOutput));
137 SetTypeHeader(¶mPortDefinitionOutput, sizeof(paramPortDefinitionOutput));
138
139 paramPortDefinitionOutput.nPortIndex = OUTPORT_INDEX;
140 paramPortDefinitionOutput.eDir = OMX_DirOutput;
141 paramPortDefinitionOutput.nBufferCountActual = OUTPORT_ACTUAL_BUFFER_COUNT;
142 paramPortDefinitionOutput.nBufferCountMin = OUTPORT_MIN_BUFFER_COUNT;
143 paramPortDefinitionOutput.nBufferSize = sizeof(VideoRenderBuffer);
144
145 paramPortDefinitionOutput.bEnabled = OMX_TRUE;
146 paramPortDefinitionOutput.bPopulated = OMX_FALSE;
147 paramPortDefinitionOutput.eDomain = OMX_PortDomainVideo;
148 paramPortDefinitionOutput.format.video.cMIMEType = (OMX_STRING)VA_RAW_MIME_TYPE;
149 paramPortDefinitionOutput.format.video.pNativeRender = NULL;
150 paramPortDefinitionOutput.format.video.nFrameWidth = 176;
151 paramPortDefinitionOutput.format.video.nFrameHeight = 144;
152 paramPortDefinitionOutput.format.video.nStride = 176;
153 paramPortDefinitionOutput.format.video.nSliceHeight = 144;
154 paramPortDefinitionOutput.format.video.nBitrate = 64000;
155 paramPortDefinitionOutput.format.video.xFramerate = 15 << 16;
156 paramPortDefinitionOutput.format.video.bFlagErrorConcealment = OMX_FALSE;
157 paramPortDefinitionOutput.format.video.eCompressionFormat = OMX_VIDEO_CodingUnused;
158 paramPortDefinitionOutput.format.video.eColorFormat = OMX_COLOR_FormatYUV420SemiPlanar;
159 paramPortDefinitionOutput.format.video.pNativeWindow = NULL;
160 paramPortDefinitionOutput.bBuffersContiguous = OMX_FALSE;
161 paramPortDefinitionOutput.nBufferAlignment = 0;
162
163 // no format specific to initialize output port
164 InitOutputPortFormatSpecific(¶mPortDefinitionOutput);
165
166 port->SetPortDefinition(¶mPortDefinitionOutput, true);
167
168 // OMX_VIDEO_PARAM_PORTFORMATTYPE
169 OMX_VIDEO_PARAM_PORTFORMATTYPE paramPortFormat;
170 SetTypeHeader(¶mPortFormat, sizeof(paramPortFormat));
171 paramPortFormat.nPortIndex = OUTPORT_INDEX;
172 paramPortFormat.nIndex = 0;
173 paramPortFormat.eCompressionFormat = paramPortDefinitionOutput.format.video.eCompressionFormat;
174 paramPortFormat.eColorFormat = paramPortDefinitionOutput.format.video.eColorFormat;
175 paramPortFormat.xFramerate = paramPortDefinitionOutput.format.video.xFramerate;
176
177 port->SetPortVideoParam(¶mPortFormat, true);
178
179 return OMX_ErrorNone;
180 }
181
InitOutputPortFormatSpecific(OMX_PARAM_PORTDEFINITIONTYPE *)182 OMX_ERRORTYPE OMXVideoDecoderBase::InitOutputPortFormatSpecific(OMX_PARAM_PORTDEFINITIONTYPE *) {
183 // no format specific to initialize output port
184 return OMX_ErrorNone;
185 }
186
ProcessorInit(void)187 OMX_ERRORTYPE OMXVideoDecoderBase::ProcessorInit(void) {
188 OMX_ERRORTYPE ret;
189 ret = OMXComponentCodecBase::ProcessorInit();
190 CHECK_RETURN_VALUE("OMXComponentCodecBase::ProcessorInit");
191
192 if (mVideoDecoder == NULL) {
193 LOGE("ProcessorInit: Video decoder is not created.");
194 return OMX_ErrorDynamicResourcesUnavailable;
195 }
196
197 VideoConfigBuffer configBuffer;
198 ret = PrepareConfigBuffer(&configBuffer);
199 CHECK_RETURN_VALUE("PrepareConfigBuffer");
200
201 //pthread_mutex_lock(&mSerializationLock);
202 Decode_Status status = mVideoDecoder->start(&configBuffer);
203 //pthread_mutex_unlock(&mSerializationLock);
204
205 if (status != DECODE_SUCCESS) {
206 return TranslateDecodeStatus(status);
207 }
208
209 return OMX_ErrorNone;
210 }
211
ProcessorReset(void)212 OMX_ERRORTYPE OMXVideoDecoderBase::ProcessorReset(void) {
213 OMX_ERRORTYPE ret;
214 VideoConfigBuffer configBuffer;
215 // reset the configbuffer and set it to mix
216 ret = PrepareConfigBuffer(&configBuffer);
217 CHECK_RETURN_VALUE("PrepareConfigBuffer");
218 mVideoDecoder->reset(&configBuffer);
219 return OMX_ErrorNone;
220 }
221
222
ProcessorDeinit(void)223 OMX_ERRORTYPE OMXVideoDecoderBase::ProcessorDeinit(void) {
224 if (mWorkingMode != GRAPHICBUFFER_MODE) {
225 if (mVideoDecoder == NULL) {
226 LOGE("ProcessorDeinit: Video decoder is not created.");
227 return OMX_ErrorDynamicResourcesUnavailable;
228 }
229 mVideoDecoder->stop();
230 }
231 mOMXBufferHeaderTypePtrNum = 0;
232 memset(&mGraphicBufferParam, 0, sizeof(mGraphicBufferParam));
233 mRotationDegrees = 0;
234 #ifdef TARGET_HAS_ISV
235 mVppBufferNum = 0;
236 #endif
237 return OMXComponentCodecBase::ProcessorDeinit();
238 }
239
ProcessorStart(void)240 OMX_ERRORTYPE OMXVideoDecoderBase::ProcessorStart(void) {
241 return OMXComponentCodecBase::ProcessorStart();
242 }
243
ProcessorStop(void)244 OMX_ERRORTYPE OMXVideoDecoderBase::ProcessorStop(void) {
245 // There is no need to return all retained buffers as we don't accumulate buffer
246 //this->ports[INPORT_INDEX]->ReturnAllRetainedBuffers();
247
248 // TODO: this is new code
249 ProcessorFlush(OMX_ALL);
250 if (mWorkingMode == GRAPHICBUFFER_MODE) {
251 // for GRAPHICBUFFER_MODE mode, va_destroySurface need to lock the graphicbuffer,
252 // Make sure va_destroySurface is called(ExecutingToIdle) before graphicbuffer is freed(IdleToLoaded).
253 if (mVideoDecoder == NULL) {
254 LOGE("ProcessorStop: Video decoder is not created.");
255 return OMX_ErrorDynamicResourcesUnavailable;
256 }
257 mVideoDecoder->stop();
258 }
259 return OMXComponentCodecBase::ProcessorStop();
260 }
261
ProcessorPause(void)262 OMX_ERRORTYPE OMXVideoDecoderBase::ProcessorPause(void) {
263 return OMXComponentCodecBase::ProcessorPause();
264 }
265
ProcessorResume(void)266 OMX_ERRORTYPE OMXVideoDecoderBase::ProcessorResume(void) {
267 return OMXComponentCodecBase::ProcessorResume();
268 }
269
ProcessorFlush(OMX_U32 portIndex)270 OMX_ERRORTYPE OMXVideoDecoderBase::ProcessorFlush(OMX_U32 portIndex) {
271 LOGI("Flushing port# %u.", portIndex);
272 if (mVideoDecoder == NULL) {
273 LOGE("ProcessorFlush: Video decoder is not created.");
274 return OMX_ErrorDynamicResourcesUnavailable;
275 }
276
277 // Portbase has returned all retained buffers.
278 if (portIndex == INPORT_INDEX || portIndex == OMX_ALL) {
279 //pthread_mutex_lock(&mSerializationLock);
280 LOGW("Flushing video pipeline.");
281 mVideoDecoder->flush();
282 //pthread_mutex_unlock(&mSerializationLock);
283 }
284 // TODO: do we need to flush output port?
285 return OMX_ErrorNone;
286 }
287
ProcessorPreFreeBuffer(OMX_U32 nPortIndex,OMX_BUFFERHEADERTYPE * pBuffer)288 OMX_ERRORTYPE OMXVideoDecoderBase::ProcessorPreFreeBuffer(OMX_U32 nPortIndex, OMX_BUFFERHEADERTYPE * pBuffer) {
289 if (mWorkingMode == GRAPHICBUFFER_MODE)
290 return OMX_ErrorNone;
291
292 if (nPortIndex == OUTPORT_INDEX && pBuffer->pPlatformPrivate) {
293 VideoRenderBuffer *p = (VideoRenderBuffer *)pBuffer->pPlatformPrivate;
294 p->renderDone = true;
295 pBuffer->pPlatformPrivate = NULL;
296 }
297 return OMX_ErrorNone;
298 }
299
ProcessorPreFillBuffer(OMX_BUFFERHEADERTYPE * buffer)300 OMX_ERRORTYPE OMXVideoDecoderBase::ProcessorPreFillBuffer(OMX_BUFFERHEADERTYPE* buffer) {
301 if (mWorkingMode == GRAPHICBUFFER_MODE && buffer->nOutputPortIndex == OUTPORT_INDEX){
302 Decode_Status status;
303 if(mVideoDecoder == NULL){
304 LOGW("ProcessorPreFillBuffer: Video decoder is not created");
305 return OMX_ErrorDynamicResourcesUnavailable;
306 }
307
308 if (mAPMode == METADATA_MODE) {
309 bool found = false;
310 if (mOMXBufferHeaderTypePtrNum < mMetaDataBuffersNum) {
311 for (uint32_t i = 0; i < mOMXBufferHeaderTypePtrNum; i++) {
312 if (mOMXBufferHeaderTypePtrArray[i] == buffer) {
313 found = true;
314 break;
315 }
316 }
317 if (!found) {
318 mOMXBufferHeaderTypePtrArray[mOMXBufferHeaderTypePtrNum] = buffer;
319 mOMXBufferHeaderTypePtrNum++;
320 }
321 }
322
323 VideoDecoderOutputMetaData *metadata = (VideoDecoderOutputMetaData *)(buffer->pBuffer);
324 status = mVideoDecoder->signalRenderDone((void *)(metadata->pHandle), !found);
325 } else {
326 status = mVideoDecoder->signalRenderDone(buffer->pBuffer);
327 }
328
329 if (status != DECODE_SUCCESS) {
330 LOGW("ProcessorPreFillBuffer:: signalRenderDone return error");
331 return TranslateDecodeStatus(status);
332 }
333 } else if (buffer->pPlatformPrivate && buffer->nOutputPortIndex == OUTPORT_INDEX){
334 VideoRenderBuffer *p = (VideoRenderBuffer *)buffer->pPlatformPrivate;
335 p->renderDone = true;
336 buffer->pPlatformPrivate = NULL;
337 }
338 return OMX_ErrorNone;
339 }
340
ProcessorProcess(OMX_BUFFERHEADERTYPE *** pBuffers,buffer_retain_t * retains,OMX_U32)341 OMX_ERRORTYPE OMXVideoDecoderBase::ProcessorProcess(
342 OMX_BUFFERHEADERTYPE ***pBuffers,
343 buffer_retain_t *retains,
344 OMX_U32) {
345
346 OMX_ERRORTYPE ret;
347 Decode_Status status;
348 OMX_BOOL isResolutionChange = OMX_FALSE;
349 // fill render buffer without draining decoder output queue
350 ret = FillRenderBuffer(pBuffers[OUTPORT_INDEX], &retains[OUTPORT_INDEX], 0, &isResolutionChange);
351 if (ret == OMX_ErrorNone) {
352 retains[INPORT_INDEX] = BUFFER_RETAIN_GETAGAIN;
353 if (isResolutionChange) {
354 HandleFormatChange();
355 }
356
357 if (mFlushMode) {
358 LOGI("in mFlushMode, do HandleFormatChange.");
359 HandleFormatChange();
360 } else {
361 // Actually, if mAPMode is set, mWorkingMode should be GRAPHICBUFFER_MODE.
362 if (((mAPMode == METADATA_MODE) && (mWorkingMode == GRAPHICBUFFER_MODE)) && mFormatChanged) {
363 if (((*pBuffers[OUTPORT_INDEX])->nFlags & OMX_BUFFERFLAG_EOS) || (mVideoDecoder->getOutputQueueLength() == 0)) {
364 // Format changed, set mFlushMode, clear eos
365 mFlushMode = true;
366 mFormatChanged = false;
367 (*pBuffers[OUTPORT_INDEX])->nFlags &= ~OMX_BUFFERFLAG_EOS;
368 }
369 }
370 }
371
372 // TODO: continue decoding
373 return ret;
374 } else if (ret != OMX_ErrorNotReady) {
375 return ret;
376 }
377
378 VideoDecodeBuffer decodeBuffer;
379 // PrepareDecodeBuffer will set retain to either BUFFER_RETAIN_GETAGAIN or BUFFER_RETAIN_NOT_RETAIN
380 ret = PrepareDecodeBuffer(*pBuffers[INPORT_INDEX], &retains[INPORT_INDEX], &decodeBuffer);
381 if (ret == OMX_ErrorNotReady) {
382 retains[OUTPORT_INDEX] = BUFFER_RETAIN_GETAGAIN;
383 return OMX_ErrorNone;
384 } else if (ret != OMX_ErrorNone) {
385 return ret;
386 }
387
388 if (decodeBuffer.size != 0) {
389 //pthread_mutex_lock(&mSerializationLock);
390 status = mVideoDecoder->decode(&decodeBuffer);
391 //pthread_mutex_unlock(&mSerializationLock);
392
393 if (status == DECODE_FORMAT_CHANGE) {
394 if ((mAPMode == METADATA_MODE) && (mWorkingMode == GRAPHICBUFFER_MODE)) {
395 mFormatChanged = true;
396 retains[INPORT_INDEX] = BUFFER_RETAIN_GETAGAIN;
397 } else {
398 ret = HandleFormatChange();
399 CHECK_RETURN_VALUE("HandleFormatChange");
400 ((*pBuffers[OUTPORT_INDEX]))->nFilledLen = 0;
401 retains[OUTPORT_INDEX] = BUFFER_RETAIN_GETAGAIN;
402 retains[INPORT_INDEX] = BUFFER_RETAIN_GETAGAIN;
403 // real dynamic resolution change will be handled later
404 // Here is just a temporary workaround
405 // don't use the output buffer if format is changed.
406 return OMX_ErrorNone;
407 }
408 } else if (status == DECODE_NO_CONFIG) {
409 LOGW("Decoder returns DECODE_NO_CONFIG.");
410 retains[OUTPORT_INDEX] = BUFFER_RETAIN_GETAGAIN;
411 return OMX_ErrorNone;
412 } else if (status == DECODE_NO_REFERENCE) {
413 LOGW("Decoder returns DECODE_NO_REFERENCE.");
414 //retains[OUTPORT_INDEX] = BUFFER_RETAIN_GETAGAIN;
415 //return OMX_ErrorNone;
416 } else if (status == DECODE_MULTIPLE_FRAME){
417 if (decodeBuffer.ext != NULL && decodeBuffer.ext->extType == PACKED_FRAME_TYPE && decodeBuffer.ext->extData != NULL) {
418 PackedFrameData* nextFrame = (PackedFrameData*)decodeBuffer.ext->extData;
419 (*pBuffers[INPORT_INDEX])->nOffset += nextFrame->offSet;
420 (*pBuffers[INPORT_INDEX])->nTimeStamp = nextFrame->timestamp;
421 (*pBuffers[INPORT_INDEX])->nFilledLen -= nextFrame->offSet;
422 retains[INPORT_INDEX] = BUFFER_RETAIN_GETAGAIN;
423 LOGW("Find multiple frames in a buffer, next frame offset = %d, timestamp = %lld", (*pBuffers[INPORT_INDEX])->nOffset, (*pBuffers[INPORT_INDEX])->nTimeStamp);
424 }
425 }
426 else if (status != DECODE_SUCCESS && status != DECODE_FRAME_DROPPED) {
427 if (checkFatalDecoderError(status)) {
428 return TranslateDecodeStatus(status);
429 } else {
430 // For decoder errors that could be omitted, not throw error and continue to decode.
431 TranslateDecodeStatus(status);
432
433 ((*pBuffers[OUTPORT_INDEX]))->nFilledLen = 0;
434
435 // Do not return, and try to drain the output queue
436 // retains[OUTPORT_INDEX] = BUFFER_RETAIN_GETAGAIN;
437 // return OMX_ErrorNone;
438 }
439 }
440 }
441 // drain the decoder output queue when in EOS state and fill the render buffer
442 ret = FillRenderBuffer(pBuffers[OUTPORT_INDEX], &retains[OUTPORT_INDEX],
443 ((*pBuffers[INPORT_INDEX]))->nFlags,&isResolutionChange);
444
445 if (isResolutionChange) {
446 HandleFormatChange();
447 }
448
449 if (mFlushMode) {
450 LOGI("in mFlushMode, do HandleFormatChange.");
451 HandleFormatChange();
452 } else {
453 if (((mAPMode == METADATA_MODE) && (mWorkingMode == GRAPHICBUFFER_MODE)) && mFormatChanged) {
454 if (((*pBuffers[OUTPORT_INDEX])->nFlags & OMX_BUFFERFLAG_EOS) || (mVideoDecoder->getOutputQueueLength() == 0)) {
455 // Format changed, set mFlushMode, clear eos.
456 mFlushMode = true;
457 mFormatChanged = false;
458 (*pBuffers[OUTPORT_INDEX])->nFlags &= ~OMX_BUFFERFLAG_EOS;
459 }
460 }
461 }
462
463 bool inputEoS = ((*pBuffers[INPORT_INDEX])->nFlags & OMX_BUFFERFLAG_EOS);
464 bool outputEoS = ((*pBuffers[OUTPORT_INDEX])->nFlags & OMX_BUFFERFLAG_EOS);
465 // if output port is not eos, retain the input buffer until all the output buffers are drained.
466 if (inputEoS && !outputEoS) {
467 retains[INPORT_INDEX] = BUFFER_RETAIN_GETAGAIN;
468 // the input buffer is retained for draining purpose. Set nFilledLen to 0 so buffer will not be decoded again.
469 (*pBuffers[INPORT_INDEX])->nFilledLen = 0;
470 }
471
472 if (ret == OMX_ErrorNotReady) {
473 retains[OUTPORT_INDEX] = BUFFER_RETAIN_GETAGAIN;
474 ret = OMX_ErrorNone;
475 }
476
477 return ret;
478 }
479
IsAllBufferAvailable(void)480 bool OMXVideoDecoderBase::IsAllBufferAvailable(void) {
481 bool b = ComponentBase::IsAllBufferAvailable();
482 if (b == false) {
483 return false;
484 }
485
486 PortVideo *port = NULL;
487 port = static_cast<PortVideo *>(this->ports[OUTPORT_INDEX]);
488 const OMX_PARAM_PORTDEFINITIONTYPE* port_def = port->GetPortDefinition();
489 // if output port is disabled, retain the input buffer
490 if (!port_def->bEnabled) {
491 return false;
492 }
493
494 if (mVideoDecoder) {
495 return mVideoDecoder->checkBufferAvail();
496 }
497 return false;
498 }
499
PrepareConfigBuffer(VideoConfigBuffer * p)500 OMX_ERRORTYPE OMXVideoDecoderBase::PrepareConfigBuffer(VideoConfigBuffer *p) {
501 // default config buffer preparation
502 memset(p, 0, sizeof(VideoConfigBuffer));
503
504 const OMX_PARAM_PORTDEFINITIONTYPE *paramPortDefinitionInput = this->ports[INPORT_INDEX]->GetPortDefinition();
505 if (paramPortDefinitionInput == NULL) {
506 return OMX_ErrorBadParameter;
507 }
508
509 if (mWorkingMode == GRAPHICBUFFER_MODE) {
510 if (mAPMode == METADATA_MODE) {
511 const OMX_PARAM_PORTDEFINITIONTYPE *def_output = this->ports[OUTPORT_INDEX]->GetPortDefinition();
512 if (def_output == NULL) {
513 return OMX_ErrorBadParameter;
514 }
515
516 mMetaDataBuffersNum = def_output->nBufferCountActual;
517 mOMXBufferHeaderTypePtrNum = 0;
518
519 mGraphicBufferParam.graphicBufferColorFormat = def_output->format.video.eColorFormat;
520 mGraphicBufferParam.graphicBufferHStride = getStride(def_output->format.video.nFrameWidth);
521 mGraphicBufferParam.graphicBufferVStride = (def_output->format.video.nFrameHeight + 0x1f) & ~0x1f;
522 mGraphicBufferParam.graphicBufferWidth = def_output->format.video.nFrameWidth;
523 mGraphicBufferParam.graphicBufferHeight = def_output->format.video.nFrameHeight;
524
525 p->surfaceNumber = mMetaDataBuffersNum;
526 for (int i = 0; i < MAX_GRAPHIC_BUFFER_NUM; i++) {
527 p->graphicBufferHandler[i] = NULL;
528 }
529 p->flag |= WANT_STORE_META_DATA;
530 } else {
531 p->surfaceNumber = mOMXBufferHeaderTypePtrNum;
532 for (uint32_t i = 0; i < mOMXBufferHeaderTypePtrNum; i++){
533 OMX_BUFFERHEADERTYPE *buffer_hdr = mOMXBufferHeaderTypePtrArray[i];
534 p->graphicBufferHandler[i] = buffer_hdr->pBuffer;
535 LOGV("PrepareConfigBuffer bufferid = %p, handle = %p", buffer_hdr, buffer_hdr->pBuffer);
536 }
537 }
538 p->flag |= USE_NATIVE_GRAPHIC_BUFFER;
539 p->graphicBufferHStride = mGraphicBufferParam.graphicBufferHStride;
540 p->graphicBufferVStride = mGraphicBufferParam.graphicBufferVStride;
541 p->graphicBufferWidth = mGraphicBufferParam.graphicBufferWidth;
542 p->graphicBufferHeight = mGraphicBufferParam.graphicBufferHeight;
543 p->graphicBufferColorFormat = mGraphicBufferParam.graphicBufferColorFormat;
544 if (p->graphicBufferColorFormat == OMX_INTEL_COLOR_FormatYUV420PackedSemiPlanar_Tiled
545 #ifdef USE_GEN_HW
546 || p->graphicBufferColorFormat == HAL_PIXEL_FORMAT_NV12_X_TILED_INTEL
547 #endif
548 )
549 p->flag |= USE_TILING_MEMORY;
550
551 if (mEnableAdaptivePlayback)
552 p->flag |= WANT_ADAPTIVE_PLAYBACK;
553
554 PortVideo *port = NULL;
555 port = static_cast<PortVideo *>(this->ports[INPORT_INDEX]);
556 OMX_PARAM_PORTDEFINITIONTYPE port_def;
557 memcpy(&port_def, port->GetPortDefinition(), sizeof(port_def));
558
559 if (port_def.format.video.pNativeWindow != NULL) {
560 p->nativeWindow = port_def.format.video.pNativeWindow;
561 LOGD("NativeWindow = %p", p->nativeWindow);
562 }
563
564 }
565
566 p->rotationDegrees = mRotationDegrees;
567 #ifdef TARGET_HAS_ISV
568 p->vppBufferNum = mVppBufferNum;
569 #endif
570 p->width = paramPortDefinitionInput->format.video.nFrameWidth;
571 p->height = paramPortDefinitionInput->format.video.nFrameHeight;
572
573 return OMX_ErrorNone;
574 }
575
PrepareDecodeBuffer(OMX_BUFFERHEADERTYPE * buffer,buffer_retain_t * retain,VideoDecodeBuffer * p)576 OMX_ERRORTYPE OMXVideoDecoderBase::PrepareDecodeBuffer(OMX_BUFFERHEADERTYPE *buffer, buffer_retain_t *retain, VideoDecodeBuffer *p) {
577 // default decode buffer preparation
578 memset(p, 0, sizeof(VideoDecodeBuffer));
579 if (buffer->nFilledLen == 0) {
580 LOGW("Len of filled data to decode is 0.");
581 return OMX_ErrorNone; //OMX_ErrorBadParameter;
582 }
583
584 if (buffer->pBuffer == NULL) {
585 LOGE("Buffer to decode is empty.");
586 return OMX_ErrorBadParameter;
587 }
588
589 if (buffer->nFlags & OMX_BUFFERFLAG_CODECCONFIG) {
590 LOGI("Buffer has OMX_BUFFERFLAG_CODECCONFIG flag.");
591 }
592
593 if (buffer->nFlags & OMX_BUFFERFLAG_DECODEONLY) {
594 // TODO: Handle OMX_BUFFERFLAG_DECODEONLY : drop the decoded frame without rendering it.
595 LOGW("Buffer has OMX_BUFFERFLAG_DECODEONLY flag.");
596 }
597
598 p->data = buffer->pBuffer + buffer->nOffset;
599 p->size = buffer->nFilledLen;
600 p->timeStamp = buffer->nTimeStamp;
601 if (buffer->nFlags & (OMX_BUFFERFLAG_ENDOFFRAME | OMX_BUFFERFLAG_EOS)) {
602 // TODO: OMX_BUFFERFLAG_ENDOFFRAME can be used to indicate end of a NAL unit.
603 // setting this flag may cause corruption if buffer does not contain end-of-frame data.
604 p->flag = HAS_COMPLETE_FRAME;
605 }
606
607 if (buffer->nFlags & OMX_BUFFERFLAG_SYNCFRAME) {
608 p->flag |= IS_SYNC_FRAME;
609 }
610
611 if (buffer->pInputPortPrivate) {
612 uint32_t degree = 0;
613 memcpy ((void *) °ree, buffer->pInputPortPrivate, sizeof(uint32_t));
614 p->rotationDegrees = degree;
615 LOGV("rotationDegrees = %d", p->rotationDegrees);
616 } else {
617 p->rotationDegrees = mRotationDegrees;
618 }
619
620 *retain= BUFFER_RETAIN_NOT_RETAIN;
621 return OMX_ErrorNone;
622 }
623
PrepareDecodeNativeHandleBuffer(OMX_BUFFERHEADERTYPE * buffer,buffer_retain_t * retain,VideoDecodeBuffer * p)624 OMX_ERRORTYPE OMXVideoDecoderBase::PrepareDecodeNativeHandleBuffer(OMX_BUFFERHEADERTYPE *buffer, buffer_retain_t *retain, VideoDecodeBuffer *p) {
625 // default decode buffer preparation
626
627 memset(p, 0, sizeof(VideoDecodeBuffer));
628 if (buffer->nFilledLen == 0) {
629 LOGW("Len of filled data to decode is 0.");
630 return OMX_ErrorNone; //OMX_ErrorBadParameter;
631 }
632
633 if (buffer->pBuffer == NULL) {
634 LOGE("Buffer to decode is empty.");
635 return OMX_ErrorBadParameter;
636 }
637
638 if (buffer->nFlags & OMX_BUFFERFLAG_CODECCONFIG) {
639 LOGI("Buffer has OMX_BUFFERFLAG_CODECCONFIG flag.");
640 }
641
642 if (buffer->nFlags & OMX_BUFFERFLAG_DECODEONLY) {
643 // TODO: Handle OMX_BUFFERFLAG_DECODEONLY : drop the decoded frame without rendering it.
644 LOGW("Buffer has OMX_BUFFERFLAG_DECODEONLY flag.");
645 }
646 //Get data pointer from native_handle
647 native_handle_t *native_handle = (native_handle_t *)buffer->pBuffer;
648 ProtectedDataBuffer *dataBuffer = (ProtectedDataBuffer *) native_handle->data[1];
649 p->data = dataBuffer->data + buffer->nOffset;
650
651
652
653 p->size = buffer->nFilledLen;
654 p->timeStamp = buffer->nTimeStamp;
655 if (buffer->nFlags & (OMX_BUFFERFLAG_ENDOFFRAME | OMX_BUFFERFLAG_EOS)) {
656 // TODO: OMX_BUFFERFLAG_ENDOFFRAME can be used to indicate end of a NAL unit.
657 // setting this flag may cause corruption if buffer does not contain end-of-frame data.
658 p->flag = HAS_COMPLETE_FRAME;
659 }
660
661 if (buffer->nFlags & OMX_BUFFERFLAG_SYNCFRAME) {
662 p->flag |= IS_SYNC_FRAME;
663 }
664
665 if (buffer->pInputPortPrivate) {
666 uint32_t degree = 0;
667 memcpy ((void *) °ree, buffer->pInputPortPrivate, sizeof(uint32_t));
668 p->rotationDegrees = degree;
669 LOGV("rotationDegrees = %d", p->rotationDegrees);
670 } else {
671 p->rotationDegrees = mRotationDegrees;
672 }
673
674 *retain= BUFFER_RETAIN_NOT_RETAIN;
675 return OMX_ErrorNone;
676 }
677
678
FillRenderBuffer(OMX_BUFFERHEADERTYPE ** pBuffer,buffer_retain_t * retain,OMX_U32 inportBufferFlags,OMX_BOOL * isResolutionChange)679 OMX_ERRORTYPE OMXVideoDecoderBase::FillRenderBuffer(OMX_BUFFERHEADERTYPE **pBuffer, buffer_retain_t *retain, OMX_U32 inportBufferFlags, OMX_BOOL *isResolutionChange) {
680 OMX_BUFFERHEADERTYPE *buffer = *pBuffer;
681 OMX_BUFFERHEADERTYPE *buffer_orign = buffer;
682 VideoErrorBuffer *ErrBufPtr = NULL;
683
684 if (mWorkingMode != GRAPHICBUFFER_MODE && buffer->pPlatformPrivate) {
685 VideoRenderBuffer *p = (VideoRenderBuffer *)buffer->pPlatformPrivate;
686 p->renderDone = true;
687 buffer->pPlatformPrivate = NULL;
688 }
689
690 if (mWorkingMode == GRAPHICBUFFER_MODE && mErrorReportEnabled) {
691 if (buffer->pOutputPortPrivate == NULL)
692 LOGE("The App doesn't provide the output buffer for error reporting");
693 else
694 ErrBufPtr = (VideoErrorBuffer *)buffer->pOutputPortPrivate;
695 }
696
697 bool draining = (inportBufferFlags & OMX_BUFFERFLAG_EOS);
698 //pthread_mutex_lock(&mSerializationLock);
699 const VideoRenderBuffer *renderBuffer = NULL;
700 //pthread_mutex_unlock(&mSerializationLock);
701
702 // in mFlushMode, provide empty buffer.
703 if (mFlushMode) {
704 buffer->nFilledLen = 0;
705 return OMX_ErrorNone;
706 }
707
708 if (((mAPMode == METADATA_MODE) && (mWorkingMode == GRAPHICBUFFER_MODE)) && mFormatChanged) {
709 renderBuffer = mVideoDecoder->getOutput(true, ErrBufPtr);
710 } else {
711 renderBuffer = mVideoDecoder->getOutput(draining, ErrBufPtr);
712 }
713 if (renderBuffer == NULL) {
714 buffer->nFilledLen = 0;
715 if (draining) {
716 LOGI("output EOS received");
717 buffer->nFlags = OMX_BUFFERFLAG_EOS;
718 return OMX_ErrorNone;
719 }
720 return OMX_ErrorNotReady;
721 }
722
723 if (mWorkingMode == GRAPHICBUFFER_MODE) {
724 buffer = *pBuffer = mOMXBufferHeaderTypePtrArray[renderBuffer->graphicBufferIndex];
725 }
726
727 buffer->nFlags = OMX_BUFFERFLAG_ENDOFFRAME;
728 #ifdef DEINTERLACE_EXT
729 if (renderBuffer->scanFormat & (VA_TOP_FIELD | VA_BOTTOM_FIELD))
730 buffer->nFlags |= OMX_BUFFERFLAG_TFF;
731 #endif
732 buffer->nTimeStamp = renderBuffer->timeStamp;
733
734 if (renderBuffer->flag & IS_EOS) {
735 buffer->nFlags |= OMX_BUFFERFLAG_EOS;
736 }
737 *isResolutionChange = (renderBuffer->flag & IS_RESOLUTION_CHANGE)? OMX_TRUE: OMX_FALSE;
738
739 if (mWorkingMode == GRAPHICBUFFER_MODE) {
740 if (buffer_orign != buffer) {
741 VideoErrorBuffer *ErrBufOutPtr = NULL;
742 ErrBufOutPtr = (VideoErrorBuffer *)buffer->pOutputPortPrivate;
743 if (ErrBufPtr && ErrBufOutPtr) {
744 memcpy(ErrBufOutPtr, ErrBufPtr, sizeof(VideoErrorBuffer));
745 memset(ErrBufPtr, 0, sizeof(VideoErrorBuffer));
746 }
747 *retain = BUFFER_RETAIN_OVERRIDDEN;
748 }
749 buffer->nFilledLen = sizeof(OMX_U8*);
750 } else {
751 uint32_t size = 0;
752 Decode_Status status = mVideoDecoder->getRawDataFromSurface(const_cast<VideoRenderBuffer *>(renderBuffer), buffer->pBuffer + buffer->nOffset, &size, false);
753 if (status != DECODE_SUCCESS) {
754 return TranslateDecodeStatus(status);
755 }
756 buffer->nFilledLen = size;
757 buffer->pPlatformPrivate = (void *)renderBuffer;
758 }
759
760 return OMX_ErrorNone;
761 }
762
HandleFormatChange(void)763 OMX_ERRORTYPE OMXVideoDecoderBase::HandleFormatChange(void) {
764 LOGW("Video format is changed.");
765 //pthread_mutex_lock(&mSerializationLock);
766 const VideoFormatInfo *formatInfo = mVideoDecoder->getFormatInfo();
767 //pthread_mutex_unlock(&mSerializationLock);
768
769 // Sync port definition as it may change.
770 OMX_PARAM_PORTDEFINITIONTYPE paramPortDefinitionInput, paramPortDefinitionOutput;
771
772 memcpy(¶mPortDefinitionInput,
773 this->ports[INPORT_INDEX]->GetPortDefinition(),
774 sizeof(paramPortDefinitionInput));
775
776 memcpy(¶mPortDefinitionOutput,
777 this->ports[OUTPORT_INDEX]->GetPortDefinition(),
778 sizeof(paramPortDefinitionOutput));
779
780 uint32_t width = formatInfo->width;
781 uint32_t height = formatInfo->height;
782 uint32_t stride = formatInfo->width;
783 uint32_t sliceHeight = formatInfo->height;
784
785 uint32_t widthCropped = formatInfo->width - formatInfo->cropLeft - formatInfo->cropRight;
786 uint32_t heightCropped = formatInfo->height - formatInfo->cropTop - formatInfo->cropBottom;
787 if (strcasecmp(formatInfo->mimeType,"video/avc") == 0 ||
788 strcasecmp(formatInfo->mimeType,"video/avc-secure") == 0 ||
789 strcasecmp(formatInfo->mimeType,"video/h264") == 0) {
790 heightCropped = formatInfo->height;
791 widthCropped = formatInfo->width;
792 }
793 uint32_t strideCropped = widthCropped;
794 uint32_t sliceHeightCropped = heightCropped;
795 int force_realloc = 0;
796 bool isVP8 = false;
797
798 if (mAPMode == METADATA_MODE && mWorkingMode == GRAPHICBUFFER_MODE) {
799 #ifdef TARGET_HAS_ISV
800 if (paramPortDefinitionOutput.nBufferCountActual - mVppBufferNum < formatInfo->actualBufferNeeded) {
801 #else
802 if (paramPortDefinitionOutput.nBufferCountActual < formatInfo->actualBufferNeeded) {
803 #endif
804 paramPortDefinitionOutput.nBufferCountActual = mNativeBufferCount = formatInfo->actualBufferNeeded;
805 paramPortDefinitionOutput.nBufferCountMin = formatInfo->actualBufferNeeded - 4;
806 }
807 // input port
808 paramPortDefinitionInput.format.video.nFrameWidth = width;
809 paramPortDefinitionInput.format.video.nFrameHeight = height;
810 paramPortDefinitionInput.format.video.nStride = stride;
811 paramPortDefinitionInput.format.video.nSliceHeight = sliceHeight;
812 // output port
813 paramPortDefinitionOutput.format.video.nFrameWidth = width;
814 paramPortDefinitionOutput.format.video.nFrameHeight = height;
815 paramPortDefinitionOutput.format.video.eColorFormat = GetOutputColorFormat(paramPortDefinitionOutput.format.video.nFrameWidth);
816 paramPortDefinitionOutput.format.video.nStride = stride;
817 paramPortDefinitionOutput.format.video.nSliceHeight = sliceHeight;
818
819 paramPortDefinitionOutput.bEnabled = (OMX_BOOL)false;
820 mOMXBufferHeaderTypePtrNum = 0;
821 memset(&mGraphicBufferParam, 0, sizeof(mGraphicBufferParam));
822 mMetaDataBuffersNum = 0;
823
824 this->ports[INPORT_INDEX]->SetPortDefinition(¶mPortDefinitionInput, true);
825 this->ports[OUTPORT_INDEX]->SetPortDefinition(¶mPortDefinitionOutput, true);
826
827 ProcessorFlush(INPORT_INDEX);
828
829 mVideoDecoder->freeSurfaceBuffers();
830
831 this->ports[OUTPORT_INDEX]->ReportPortSettingsChanged();
832
833 mFlushMode = false;
834 return OMX_ErrorNone;
835 }
836
837 #ifdef TARGET_HAS_ISV
838 LOGI("============== mVppBufferNum = %d\n", mVppBufferNum);
839 if (paramPortDefinitionOutput.nBufferCountActual - mVppBufferNum < formatInfo->actualBufferNeeded) {
840 #else
841 if (paramPortDefinitionOutput.nBufferCountActual < formatInfo->actualBufferNeeded) {
842 #endif
843 if (mWorkingMode == GRAPHICBUFFER_MODE) {
844 LOGV("output port buffer number is not enough: %d to %d",
845 paramPortDefinitionOutput.nBufferCountActual,
846 formatInfo->actualBufferNeeded);
847 paramPortDefinitionOutput.nBufferCountActual = mNativeBufferCount = formatInfo->actualBufferNeeded;
848 paramPortDefinitionOutput.nBufferCountMin = mNativeBufferCount;
849 force_realloc = 1;
850 }
851 }
852
853 LOGV("Original size = %u x %u, new size = %d x %d, cropped size = %d x %d",
854 paramPortDefinitionInput.format.video.nFrameWidth,
855 paramPortDefinitionInput.format.video.nFrameHeight,
856 width, height, widthCropped, heightCropped);
857
858 if (paramPortDefinitionInput.format.video.eCompressionFormat == OMX_VIDEO_CodingVP8) {
859 isVP8 = true;
860 }
861
862 if (!force_realloc &&
863 widthCropped == paramPortDefinitionOutput.format.video.nFrameWidth &&
864 heightCropped == paramPortDefinitionOutput.format.video.nFrameHeight) {
865 if (mWorkingMode == RAWDATA_MODE) {
866 LOGW("Change of portsetting is not reported as size is not changed.");
867 return OMX_ErrorNone;
868 }
869 }
870
871 paramPortDefinitionInput.format.video.nFrameWidth = width;
872 paramPortDefinitionInput.format.video.nFrameHeight = height;
873 paramPortDefinitionInput.format.video.nStride = stride;
874 paramPortDefinitionInput.format.video.nSliceHeight = sliceHeight;
875
876 if (mWorkingMode == RAWDATA_MODE) {
877 paramPortDefinitionOutput.format.video.nFrameWidth = widthCropped;
878 paramPortDefinitionOutput.format.video.nFrameHeight = heightCropped;
879 paramPortDefinitionOutput.format.video.nStride = strideCropped;
880 paramPortDefinitionOutput.format.video.nSliceHeight = sliceHeightCropped;
881 } else if (mWorkingMode == GRAPHICBUFFER_MODE) {
882 // when the width and height ES parse are not larger than allocated graphic buffer in outport,
883 // there is no need to reallocate graphic buffer,just report the crop info to omx client
884 if (!force_realloc && width <= formatInfo->surfaceWidth && height <= formatInfo->surfaceHeight) {
885 this->ports[INPORT_INDEX]->SetPortDefinition(¶mPortDefinitionInput, true);
886 this->ports[OUTPORT_INDEX]->ReportOutputCrop();
887 return OMX_ErrorNone;
888 }
889
890 if (isVP8 || width > formatInfo->surfaceWidth || height > formatInfo->surfaceHeight) {
891 // update the real decoded resolution to outport instead of display resolution for graphic buffer reallocation
892 // when the width and height parsed from ES are larger than allocated graphic buffer in outport,
893 paramPortDefinitionOutput.format.video.nFrameWidth = width;
894 paramPortDefinitionOutput.format.video.nFrameHeight = height;
895 paramPortDefinitionOutput.format.video.eColorFormat = GetOutputColorFormat(
896 paramPortDefinitionOutput.format.video.nFrameWidth);
897 paramPortDefinitionOutput.format.video.nStride = stride;
898 paramPortDefinitionOutput.format.video.nSliceHeight = sliceHeight;
899 }
900 }
901
902 paramPortDefinitionOutput.bEnabled = (OMX_BOOL)false;
903 mOMXBufferHeaderTypePtrNum = 0;
904 memset(&mGraphicBufferParam, 0, sizeof(mGraphicBufferParam));
905
906 this->ports[INPORT_INDEX]->SetPortDefinition(¶mPortDefinitionInput, true);
907 this->ports[OUTPORT_INDEX]->SetPortDefinition(¶mPortDefinitionOutput, true);
908
909 if (mWorkingMode == GRAPHICBUFFER_MODE) {
910 // Make sure va_destroySurface is called before graphicbuffer is freed in case of port setting changed
911 mVideoDecoder->freeSurfaceBuffers();
912
913 // Also make sure all the reference frames are flushed
914 ProcessorFlush(INPORT_INDEX);
915 }
916 this->ports[OUTPORT_INDEX]->ReportPortSettingsChanged();
917 return OMX_ErrorNone;
918 }
919
920 OMX_ERRORTYPE OMXVideoDecoderBase::TranslateDecodeStatus(Decode_Status status) {
921 switch (status) {
922 case DECODE_NEED_RESTART:
923 LOGE("Decoder returned DECODE_NEED_RESTART");
924 return (OMX_ERRORTYPE)OMX_ErrorIntelVideoNotPermitted;
925 case DECODE_NO_CONFIG:
926 LOGE("Decoder returned DECODE_NO_CONFIG");
927 return (OMX_ERRORTYPE)OMX_ErrorIntelMissingConfig;
928 case DECODE_NO_SURFACE:
929 LOGE("Decoder returned DECODE_NO_SURFACE");
930 return OMX_ErrorDynamicResourcesUnavailable;
931 case DECODE_NO_REFERENCE:
932 LOGE("Decoder returned DECODE_NO_REFERENCE");
933 return OMX_ErrorDynamicResourcesUnavailable; // TO DO
934 case DECODE_NO_PARSER:
935 LOGE("Decoder returned DECODE_NO_PARSER");
936 return OMX_ErrorDynamicResourcesUnavailable;
937 case DECODE_INVALID_DATA:
938 LOGE("Decoder returned DECODE_INVALID_DATA");
939 return OMX_ErrorBadParameter;
940 case DECODE_DRIVER_FAIL:
941 LOGE("Decoder returned DECODE_DRIVER_FAIL");
942 return OMX_ErrorHardware;
943 case DECODE_PARSER_FAIL:
944 LOGE("Decoder returned DECODE_PARSER_FAIL");
945 return (OMX_ERRORTYPE)OMX_ErrorIntelProcessStream; // OMX_ErrorStreamCorrupt
946 case DECODE_MEMORY_FAIL:
947 LOGE("Decoder returned DECODE_MEMORY_FAIL");
948 return OMX_ErrorInsufficientResources;
949 case DECODE_FAIL:
950 LOGE("Decoder returned DECODE_FAIL");
951 return OMX_ErrorUndefined;
952 case DECODE_SUCCESS:
953 return OMX_ErrorNone;
954 case DECODE_FORMAT_CHANGE:
955 LOGW("Decoder returned DECODE_FORMAT_CHANGE");
956 return OMX_ErrorNone;
957 case DECODE_FRAME_DROPPED:
958 LOGI("Decoder returned DECODE_FRAME_DROPPED");
959 return OMX_ErrorNone;
960 default:
961 LOGW("Decoder returned unknown error");
962 return OMX_ErrorUndefined;
963 }
964 }
965
966 OMX_ERRORTYPE OMXVideoDecoderBase::BuildHandlerList(void) {
967 OMXComponentCodecBase::BuildHandlerList();
968 AddHandler(OMX_IndexParamVideoPortFormat, GetParamVideoPortFormat, SetParamVideoPortFormat);
969 AddHandler(static_cast<OMX_INDEXTYPE>(OMX_IndexExtGetNativeBufferUsage), GetNativeBufferUsage, SetNativeBufferUsage);
970 AddHandler(static_cast<OMX_INDEXTYPE>(OMX_IndexExtUseNativeBuffer), GetNativeBuffer, SetNativeBuffer);
971 AddHandler(static_cast<OMX_INDEXTYPE>(OMX_IndexExtEnableNativeBuffer), GetNativeBufferMode, SetNativeBufferMode);
972 AddHandler(static_cast<OMX_INDEXTYPE>(OMX_IndexExtRotationDegrees), GetDecoderRotation, SetDecoderRotation);
973 #ifdef TARGET_HAS_ISV
974 AddHandler(static_cast<OMX_INDEXTYPE>(OMX_IndexExtVppBufferNum), GetDecoderVppBufferNum, SetDecoderVppBufferNum);
975 #endif
976 AddHandler(OMX_IndexConfigCommonOutputCrop, GetDecoderOutputCrop, SetDecoderOutputCrop);
977 #ifdef USE_META_DATA
978 AddHandler(static_cast<OMX_INDEXTYPE>(OMX_IndexStoreMetaDataInBuffers), GetStoreMetaDataMode, SetStoreMetaDataMode);
979 #endif
980 AddHandler(static_cast<OMX_INDEXTYPE>(OMX_IndexExtEnableErrorReport), GetErrorReportMode, SetErrorReportMode);
981 AddHandler(static_cast<OMX_INDEXTYPE>(OMX_IndexConfigPriority), GetCodecPriority, SetCodecPriority);
982 AddHandler(static_cast<OMX_INDEXTYPE>(OMX_IndexConfigOperatingRate), GetDecoderOperatingRate, SetDecoderOperatingRate);
983
984 return OMX_ErrorNone;
985 }
986
987 OMX_ERRORTYPE OMXVideoDecoderBase::GetParamVideoPortFormat(OMX_PTR pStructure) {
988 OMX_ERRORTYPE ret;
989 OMX_VIDEO_PARAM_PORTFORMATTYPE *p = (OMX_VIDEO_PARAM_PORTFORMATTYPE *)pStructure;
990
991 CHECK_TYPE_HEADER(p);
992 CHECK_PORT_INDEX_RANGE(p);
993 CHECK_ENUMERATION_RANGE(p->nIndex, 1);
994
995 PortVideo *port = NULL;
996 port = static_cast<PortVideo *>(this->ports[p->nPortIndex]);
997 memcpy(p, port->GetPortVideoParam(), sizeof(*p));
998 return OMX_ErrorNone;
999 }
1000
1001 OMX_ERRORTYPE OMXVideoDecoderBase::SetParamVideoPortFormat(OMX_PTR pStructure) {
1002 OMX_ERRORTYPE ret;
1003 OMX_VIDEO_PARAM_PORTFORMATTYPE *p = (OMX_VIDEO_PARAM_PORTFORMATTYPE *)pStructure;
1004
1005 CHECK_TYPE_HEADER(p);
1006 CHECK_PORT_INDEX_RANGE(p);
1007 CHECK_SET_PARAM_STATE();
1008
1009 // TODO: do we need to check if port is enabled?
1010 PortVideo *port = NULL;
1011 port = static_cast<PortVideo *>(this->ports[p->nPortIndex]);
1012 port->SetPortVideoParam(p, false);
1013 return OMX_ErrorNone;
1014 }
1015
1016 OMX_ERRORTYPE OMXVideoDecoderBase::GetNativeBufferUsageSpecific(OMX_PTR pStructure) {
1017 OMX_ERRORTYPE ret;
1018 GetAndroidNativeBufferUsageParams *param = (GetAndroidNativeBufferUsageParams*)pStructure;
1019 CHECK_TYPE_HEADER(param);
1020 // hardware usage: consumed by GLES and HWC
1021 param->nUsage |= GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_HW_COMPOSER;
1022 // software usage: can be read/written by apps
1023 param->nUsage |= GRALLOC_USAGE_SW_READ_RARELY | GRALLOC_USAGE_SW_WRITE_RARELY;
1024 return OMX_ErrorNone;
1025 }
1026 OMX_ERRORTYPE OMXVideoDecoderBase::SetNativeBufferUsageSpecific(OMX_PTR) {
1027 CHECK_SET_PARAM_STATE();
1028 return OMX_ErrorBadParameter;
1029 }
1030
1031 OMX_ERRORTYPE OMXVideoDecoderBase::GetNativeBufferUsage(OMX_PTR pStructure) {
1032 return this->GetNativeBufferUsageSpecific(pStructure);
1033 }
1034 OMX_ERRORTYPE OMXVideoDecoderBase::SetNativeBufferUsage(OMX_PTR pStructure) {
1035 return this->SetNativeBufferUsageSpecific(pStructure);
1036 }
1037
1038 OMX_ERRORTYPE OMXVideoDecoderBase::GetNativeBuffer(OMX_PTR) {
1039 return OMX_ErrorBadParameter;
1040 }
1041
1042 OMX_ERRORTYPE OMXVideoDecoderBase::SetNativeBuffer(OMX_PTR pStructure) {
1043 OMX_ERRORTYPE ret;
1044 UseAndroidNativeBufferParams *param = (UseAndroidNativeBufferParams*)pStructure;
1045 CHECK_TYPE_HEADER(param);
1046 if (param->nPortIndex != OUTPORT_INDEX)
1047 return OMX_ErrorBadParameter;
1048 OMX_BUFFERHEADERTYPE **buf_hdr = NULL;
1049
1050 mOMXBufferHeaderTypePtrNum++;
1051 if (mOMXBufferHeaderTypePtrNum > MAX_GRAPHIC_BUFFER_NUM)
1052 return OMX_ErrorOverflow;
1053
1054 buf_hdr = &mOMXBufferHeaderTypePtrArray[mOMXBufferHeaderTypePtrNum-1];
1055
1056 ret = this->ports[OUTPORT_INDEX]->UseBuffer(buf_hdr, OUTPORT_INDEX, param->pAppPrivate, sizeof(OMX_U8*),
1057 const_cast<OMX_U8*>(reinterpret_cast<const OMX_U8*>(param->nativeBuffer->handle)));
1058 if (ret != OMX_ErrorNone)
1059 return ret;
1060
1061 if (mOMXBufferHeaderTypePtrNum == 1) {
1062 mGraphicBufferParam.graphicBufferColorFormat = param->nativeBuffer->format;
1063 mGraphicBufferParam.graphicBufferHStride = param->nativeBuffer->stride;
1064 // FIXME: use IMG_native_handle_t->aiVStride[0] instead..
1065 mGraphicBufferParam.graphicBufferVStride = param->nativeBuffer->height;
1066 mGraphicBufferParam.graphicBufferWidth = param->nativeBuffer->width;
1067 mGraphicBufferParam.graphicBufferHeight = param->nativeBuffer->height;
1068 }
1069
1070 *(param->bufferHeader) = *buf_hdr;
1071
1072 return OMX_ErrorNone;
1073 }
1074
1075 OMX_ERRORTYPE OMXVideoDecoderBase::GetNativeBufferMode(OMX_PTR pStructure) {
1076 return this->GetNativeBufferModeSpecific(pStructure);
1077 }
1078
1079 OMX_ERRORTYPE OMXVideoDecoderBase::SetNativeBufferMode(OMX_PTR pStructure) {
1080 return this->SetNativeBufferModeSpecific(pStructure);
1081 }
1082
1083 OMX_ERRORTYPE OMXVideoDecoderBase::GetNativeBufferModeSpecific(OMX_PTR) {
1084 LOGE("GetNativeBufferMode is not implemented");
1085 return OMX_ErrorNotImplemented;
1086 }
1087
1088 OMX_ERRORTYPE OMXVideoDecoderBase::SetNativeBufferModeSpecific(OMX_PTR pStructure) {
1089 OMX_ERRORTYPE ret;
1090 EnableAndroidNativeBuffersParams *param = (EnableAndroidNativeBuffersParams*)pStructure;
1091
1092 CHECK_TYPE_HEADER(param);
1093 CHECK_PORT_INDEX_RANGE(param);
1094 CHECK_SET_PARAM_STATE();
1095
1096 PortVideo *port = NULL;
1097 port = static_cast<PortVideo *>(this->ports[OUTPORT_INDEX]);
1098 OMX_PARAM_PORTDEFINITIONTYPE port_def;
1099 memcpy(&port_def,port->GetPortDefinition(),sizeof(port_def));
1100
1101 if (!param->enable) {
1102 mWorkingMode = RAWDATA_MODE;
1103 // If it is fallback from native mode the color format has been
1104 // already set to INTEL format.
1105 // We need to set back the default color format and Native stuff.
1106 port_def.format.video.eColorFormat = OMX_COLOR_FormatYUV420SemiPlanar;
1107 port_def.format.video.pNativeRender = NULL;
1108 port_def.format.video.pNativeWindow = NULL;
1109 port->SetPortDefinition(&port_def,true);
1110 return OMX_ErrorNone;
1111 }
1112
1113 mWorkingMode = GRAPHICBUFFER_MODE;
1114 port_def.nBufferCountMin = mNativeBufferCount;
1115 if (mEnableAdaptivePlayback) {
1116 SetMaxOutputBufferCount(&port_def);
1117 } else {
1118 port_def.nBufferCountActual = mNativeBufferCount;
1119 }
1120 port_def.format.video.cMIMEType = (OMX_STRING)VA_VED_RAW_MIME_TYPE;
1121 port_def.format.video.eColorFormat = OMX_INTEL_COLOR_FormatYUV420PackedSemiPlanar;
1122 port_def.format.video.nFrameHeight = port_def.format.video.nFrameHeight;
1123
1124 port_def.format.video.eColorFormat = GetOutputColorFormat(
1125 port_def.format.video.nFrameWidth);
1126 port->SetPortDefinition(&port_def,true);
1127
1128 return OMX_ErrorNone;
1129 }
1130
1131 OMX_ERRORTYPE OMXVideoDecoderBase::GetStoreMetaDataMode(OMX_PTR) {
1132 ALOGE("GetMetaDataMode is not implemented");
1133 return OMX_ErrorNotImplemented;
1134 }
1135
1136 OMX_ERRORTYPE OMXVideoDecoderBase::SetStoreMetaDataMode(OMX_PTR pStructure) {
1137 #ifndef USE_META_DATA
1138 OMX_PARAM_PORTDEFINITIONTYPE defInput;
1139 memcpy(&defInput,
1140 this->ports[INPORT_INDEX]->GetPortDefinition(),
1141 sizeof(defInput));
1142 if (defInput.format.video.eCompressionFormat == OMX_VIDEO_CodingVP9) {
1143 ALOGE("SetMetaDataMode for VP9 is not implemented");
1144 return OMX_ErrorNotImplemented;
1145 }
1146 #endif
1147 OMX_ERRORTYPE ret;
1148 StoreMetaDataInBuffersParams *param = (StoreMetaDataInBuffersParams*)pStructure;
1149
1150 CHECK_TYPE_HEADER(param);
1151 CHECK_PORT_INDEX(param, OUTPORT_INDEX);
1152 CHECK_SET_PARAM_STATE();
1153
1154 if (!param->bStoreMetaData) {
1155 mAPMode = LEGACY_MODE;
1156 // Don't return error which otherwise may cause framework crash
1157 return OMX_ErrorNone;
1158 }
1159 mAPMode = METADATA_MODE;
1160 ALOGI("We are in meta data mode!!!");
1161
1162 return OMX_ErrorNone;
1163 }
1164
1165 OMX_ERRORTYPE OMXVideoDecoderBase::GetDecoderRotation(OMX_PTR) {
1166 return OMX_ErrorBadParameter;
1167 }
1168 OMX_ERRORTYPE OMXVideoDecoderBase::SetDecoderRotation(OMX_PTR pStructure) {
1169 CHECK_SET_PARAM_STATE();
1170 int32_t rotationDegrees = 0;
1171
1172 if (pStructure) {
1173 rotationDegrees = *(static_cast<int32_t*>(pStructure));
1174 mRotationDegrees = rotationDegrees;
1175 LOGI("Rotation Degree = %d", rotationDegrees);
1176 return OMX_ErrorNone;
1177 } else {
1178 return OMX_ErrorBadParameter;
1179 }
1180 }
1181
1182 #ifdef TARGET_HAS_ISV
1183 OMX_ERRORTYPE OMXVideoDecoderBase::GetDecoderVppBufferNum(OMX_PTR) {
1184 return OMX_ErrorBadParameter;
1185 }
1186 OMX_ERRORTYPE OMXVideoDecoderBase::SetDecoderVppBufferNum(OMX_PTR pStructure) {
1187 CHECK_SET_PARAM_STATE();
1188 int32_t num = 0;
1189
1190 num = *(static_cast<int32_t*>(pStructure));
1191 mVppBufferNum = num;
1192
1193 return OMX_ErrorNone;
1194 }
1195 #endif
1196
1197 OMX_ERRORTYPE OMXVideoDecoderBase::GetDecoderOutputCropSpecific(OMX_PTR pStructure) {
1198 OMX_ERRORTYPE ret;
1199 OMX_CONFIG_RECTTYPE *rectParams = (OMX_CONFIG_RECTTYPE *)pStructure;
1200
1201 CHECK_TYPE_HEADER(rectParams);
1202
1203 if (rectParams->nPortIndex != OUTPORT_INDEX) {
1204 return OMX_ErrorUndefined;
1205 }
1206
1207 PortVideo *port = NULL;
1208 port = static_cast<PortVideo *>(this->ports[OUTPORT_INDEX]);
1209 OMX_PARAM_PORTDEFINITIONTYPE port_def;
1210 memcpy(&port_def,port->GetPortDefinition(),sizeof(port_def));
1211
1212 const VideoFormatInfo *formatInfo = mVideoDecoder->getFormatInfo();
1213 if (formatInfo->valid == true) {
1214 rectParams->nLeft = formatInfo->cropLeft;
1215 rectParams->nTop = formatInfo->cropTop;
1216 rectParams->nWidth = formatInfo->width - formatInfo->cropLeft - formatInfo->cropRight;
1217 rectParams->nHeight = formatInfo->height - formatInfo->cropTop - formatInfo->cropBottom;
1218 if (strcasecmp(formatInfo->mimeType,"video/avc") == 0 ||
1219 strcasecmp(formatInfo->mimeType,"video/avc-secure") == 0 ||
1220 strcasecmp(formatInfo->mimeType,"video/h264") == 0) {
1221 rectParams->nHeight = formatInfo->height;
1222 rectParams->nWidth = formatInfo->width;
1223 }
1224
1225 // if port width parsed from extractor is not as same as from SPS/PPS nalu header,
1226 // align it.
1227 if (port_def.format.video.nFrameWidth != rectParams->nWidth) {
1228 port_def.format.video.nFrameWidth = rectParams->nWidth;
1229 }
1230 port->SetPortDefinition(&port_def,true);
1231 return OMX_ErrorNone;
1232 } else {
1233 return OMX_ErrorFormatNotDetected;
1234 }
1235 }
1236
1237 OMX_ERRORTYPE OMXVideoDecoderBase::SetDecoderOutputCropSpecific(OMX_PTR) {
1238 return OMX_ErrorUnsupportedSetting;
1239 }
1240
1241 OMX_ERRORTYPE OMXVideoDecoderBase::SetDecoderOutputCrop(OMX_PTR pStructure) {
1242 return this->SetDecoderOutputCropSpecific(pStructure);
1243 }
1244
1245 OMX_ERRORTYPE OMXVideoDecoderBase::GetDecoderOutputCrop(OMX_PTR pStructure) {
1246 return this->GetDecoderOutputCropSpecific(pStructure);
1247 }
1248
1249
1250 OMX_ERRORTYPE OMXVideoDecoderBase::SetCodecPriority(OMX_PTR pStructure) {
1251 OMX_ERRORTYPE ret;
1252 OMX_PARAM_U32TYPE *priorityParam = (OMX_PARAM_U32TYPE *)pStructure;
1253 mCodecPriority = priorityParam->nU32;
1254 return OMX_ErrorNone;
1255 }
1256
1257
1258 OMX_ERRORTYPE OMXVideoDecoderBase::GetCodecPriority(OMX_PTR pStructure) {
1259 OMX_ERRORTYPE ret;
1260 OMX_PARAM_U32TYPE *priorityParam = (OMX_PARAM_U32TYPE *)pStructure;
1261 CHECK_TYPE_HEADER(priorityParam);
1262 priorityParam->nU32 = mCodecPriority;
1263 return OMX_ErrorNone;
1264 }
1265
1266
1267 OMX_ERRORTYPE OMXVideoDecoderBase::SetDecoderOperatingRate(OMX_PTR pStructure) {
1268 OMX_ERRORTYPE ret;
1269 OMX_PARAM_U32TYPE *operatingRateParam = (OMX_PARAM_U32TYPE *)pStructure;
1270 CHECK_TYPE_HEADER(operatingRateParam);
1271 mOperatingRate = operatingRateParam->nU32;
1272 return OMX_ErrorNone;
1273 }
1274
1275 OMX_ERRORTYPE OMXVideoDecoderBase::GetDecoderOperatingRate(OMX_PTR pStructure) {
1276 OMX_ERRORTYPE ret;
1277 OMX_PARAM_U32TYPE *operatingRateParam = (OMX_PARAM_U32TYPE *)pStructure;
1278 CHECK_TYPE_HEADER(operatingRateParam);
1279 operatingRateParam->nU32 = mOperatingRate;
1280 return OMX_ErrorNone;
1281 }
1282
1283 OMX_ERRORTYPE OMXVideoDecoderBase::GetErrorReportMode(OMX_PTR) {
1284 LOGE("GetErrorReportMode is not implemented");
1285 return OMX_ErrorNotImplemented;
1286 }
1287
1288 OMX_ERRORTYPE OMXVideoDecoderBase::SetErrorReportMode(OMX_PTR pStructure) {
1289 OMX_ERRORTYPE ret;
1290
1291 OMX_VIDEO_CONFIG_INTEL_ERROR_REPORT *p = (OMX_VIDEO_CONFIG_INTEL_ERROR_REPORT *)pStructure;
1292 CHECK_TYPE_HEADER(p);
1293 CHECK_PORT_INDEX(p, OUTPORT_INDEX);
1294
1295 mErrorReportEnabled = p->bEnable;
1296 LOGD("Error reporting is %s", mErrorReportEnabled ? "enabled" : "disabled");
1297
1298 mVideoDecoder->enableErrorReport(mErrorReportEnabled);
1299 return OMX_ErrorNone;
1300 }
1301
1302 OMX_COLOR_FORMATTYPE OMXVideoDecoderBase::GetOutputColorFormat(int width) {
1303 #ifndef VED_TILING
1304 return OMX_INTEL_COLOR_FormatYUV420PackedSemiPlanar;
1305 #else
1306 if (width > 1280 && width <= 2048) {
1307 LOGI("HD Video and use tiled format");
1308 return OMX_INTEL_COLOR_FormatYUV420PackedSemiPlanar_Tiled;
1309 } else {
1310 return OMX_INTEL_COLOR_FormatYUV420PackedSemiPlanar;
1311 }
1312 #endif
1313 }
1314
1315 OMX_ERRORTYPE OMXVideoDecoderBase::SetMaxOutputBufferCount(OMX_PARAM_PORTDEFINITIONTYPE *) {
1316 return OMX_ErrorNone;
1317 }
1318
1319 uint32_t OMXVideoDecoderBase::getStride(uint32_t width) {
1320 uint32_t stride = 0;
1321
1322 if (width <= 512)
1323 stride = 512;
1324 else if (width <= 1024)
1325 stride = 1024;
1326 else if (width <= 1280) {
1327 stride = 1280;
1328 } else if (width <= 2048)
1329 stride = 2048;
1330 else if (width <= 4096)
1331 stride = 4096;
1332 else
1333 stride = (width + 0x3f) & ~0x3f;
1334
1335 return stride;
1336 }
1337