portbase.cpp revision 78c1837ebe200a58aebed8bad480064da909d6ff
1/* 2 * portbase.cpp, base port class 3 * 4 * Copyright (c) 2009-2010 Wind River Systems, Inc. 5 * 6 * Licensed under the Apache License, Version 2.0 (the "License"); 7 * you may not use this file except in compliance with the License. 8 * You may obtain a copy of the License at 9 * 10 * http://www.apache.org/licenses/LICENSE-2.0 11 * 12 * Unless required by applicable law or agreed to in writing, software 13 * distributed under the License is distributed on an "AS IS" BASIS, 14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 * See the License for the specific language governing permissions and 16 * limitations under the License. 17 */ 18 19#include <stdlib.h> 20#include <string.h> 21 22#include <OMX_Core.h> 23#include <OMX_Component.h> 24 25#include <portbase.h> 26#include <componentbase.h> 27#include <OMX_VideoExt.h> 28//#define LOG_NDEBUG 0 29 30#define LOG_TAG "portbase" 31#include <log.h> 32 33/* 34 * constructor & destructor 35 */ 36void PortBase::__PortBase(void) 37{ 38 buffer_hdrs = NULL; 39 nr_buffer_hdrs = 0; 40 buffer_hdrs_completion = false; 41 42 custom_mem_alloc = NULL; 43 custom_mem_free = NULL; 44 custom_mem_userdata = NULL; 45 46 mem_alignment = 0; 47 48 pthread_mutex_init(&hdrs_lock, NULL); 49 pthread_cond_init(&hdrs_wait, NULL); 50 51 __queue_init(&bufferq); 52 pthread_mutex_init(&bufferq_lock, NULL); 53 54 __queue_init(&retainedbufferq); 55 pthread_mutex_init(&retainedbufferq_lock, NULL); 56 57 __queue_init(&markq); 58 pthread_mutex_init(&markq_lock, NULL); 59 60 state = OMX_PortEnabled; 61 pthread_mutex_init(&state_lock, NULL); 62 63 memset(&portdefinition, 0, sizeof(portdefinition)); 64 ComponentBase::SetTypeHeader(&portdefinition, sizeof(portdefinition)); 65 memset(definition_format_mimetype, 0, OMX_MAX_STRINGNAME_SIZE); 66 portdefinition.format.audio.cMIMEType = &definition_format_mimetype[0]; 67 portdefinition.format.video.cMIMEType = &definition_format_mimetype[0]; 68 portdefinition.format.image.cMIMEType = &definition_format_mimetype[0]; 69 70 memset(&audioparam, 0, sizeof(audioparam)); 71 72 owner = NULL; 73 appdata = NULL; 74 callbacks = NULL; 75 76 cbase = NULL; 77} 78 79PortBase::PortBase() 80{ 81 __PortBase(); 82} 83 84PortBase::PortBase(const OMX_PARAM_PORTDEFINITIONTYPE *portdefinition) 85{ 86 __PortBase(); 87 SetPortDefinition(portdefinition, true); 88} 89 90PortBase::~PortBase() 91{ 92 struct list *entry, *temp; 93 94 /* should've been already freed at FreeBuffer() */ 95 list_foreach_safe(buffer_hdrs, entry, temp) { 96 free(entry->data); /* OMX_BUFFERHEADERTYPE */ 97 __list_delete(buffer_hdrs, entry); 98 } 99 100 pthread_cond_destroy(&hdrs_wait); 101 pthread_mutex_destroy(&hdrs_lock); 102 103 /* should've been already freed at buffer processing */ 104 queue_free_all(&bufferq); 105 pthread_mutex_destroy(&bufferq_lock); 106 107 /* should've been already freed at buffer processing */ 108 queue_free_all(&retainedbufferq); 109 pthread_mutex_destroy(&retainedbufferq_lock); 110 111 /* should've been already empty in PushThisBuffer () */ 112 queue_free_all(&markq); 113 pthread_mutex_destroy(&markq_lock); 114 115 pthread_mutex_destroy(&state_lock); 116} 117 118/* end of constructor & destructor */ 119 120/* 121 * accessor 122 */ 123/* owner */ 124void PortBase::SetOwner(OMX_COMPONENTTYPE *handle) 125{ 126 owner = handle; 127 cbase = static_cast<ComponentBase *>(handle->pComponentPrivate); 128} 129 130OMX_COMPONENTTYPE *PortBase::GetOwner(void) 131{ 132 return owner; 133} 134 135OMX_ERRORTYPE PortBase::SetCallbacks(OMX_HANDLETYPE hComponent, 136 OMX_CALLBACKTYPE *pCallbacks, 137 OMX_PTR pAppData) 138{ 139 if (owner != hComponent) 140 return OMX_ErrorBadParameter; 141 142 appdata = pAppData; 143 callbacks = pCallbacks; 144 145 return OMX_ErrorNone; 146} 147 148OMX_ERRORTYPE PortBase::SetMemAllocator(CustomMemAlloc *pMemAlloc, CustomMemFree *pMemFree, OMX_PTR pUserData) 149{ 150 custom_mem_alloc = pMemAlloc; 151 custom_mem_free = pMemFree; 152 custom_mem_userdata = pUserData; 153 return OMX_ErrorNone; 154} 155 156OMX_ERRORTYPE PortBase::SetMemAlignment(OMX_U32 nAlignment) 157{ 158 mem_alignment = nAlignment; 159 return OMX_ErrorNone; 160} 161 162OMX_U32 PortBase::getFrameBufSize(OMX_COLOR_FORMATTYPE colorFormat, OMX_U32 width, OMX_U32 height) 163{ 164 switch (colorFormat) { 165 case OMX_COLOR_FormatYCbYCr: 166 case OMX_COLOR_FormatCbYCrY: 167 return width * height * 2; 168 case OMX_COLOR_FormatYUV420Planar: 169 case OMX_COLOR_FormatYUV420SemiPlanar: 170 return (width * height * 3) >> 1; 171 case OMX_COLOR_FormatUnused: 172 return (width * height * 3) >> 1; 173 174 default: 175 LOGV("unsupport color format !"); 176 return -1; 177 } 178} 179 180/* end of accessor */ 181 182/* 183 * component methods & helpers 184 */ 185/* Get/SetParameter */ 186OMX_ERRORTYPE PortBase::SetPortDefinition( 187 const OMX_PARAM_PORTDEFINITIONTYPE *p, bool overwrite_readonly) 188{ 189 OMX_PARAM_PORTDEFINITIONTYPE temp; 190 191 memcpy(&temp, &portdefinition, sizeof(temp)); 192 193 if (!overwrite_readonly) { 194 if (temp.nPortIndex != p->nPortIndex) 195 return OMX_ErrorBadParameter; 196 if (temp.eDir != p->eDir) 197 return OMX_ErrorBadParameter; 198 if (temp.eDomain != p->eDomain) 199 return OMX_ErrorBadParameter; 200 if (temp.nBufferCountActual != p->nBufferCountActual) { 201 if (temp.nBufferCountMin > p->nBufferCountActual) 202 return OMX_ErrorBadParameter; 203 temp.nBufferCountActual = p->nBufferCountActual; 204 } 205 if ((p->nBufferSize > temp.nBufferSize) && (temp.eDir == OMX_DirInput)) { 206 if (p->nBufferSize <= MAX_INPUT_PORT_SIZE) { 207 LOGW("Input port size has been changed!"); 208 temp.nBufferSize = p->nBufferSize; 209 } else { 210 LOGE("Invalid input port size!"); 211 return OMX_ErrorBadParameter; 212 } 213 } 214 } 215 else { 216 temp.nPortIndex = p->nPortIndex; 217 temp.eDir = p->eDir; 218 temp.nBufferCountActual = p->nBufferCountActual; 219 temp.nBufferCountMin = p->nBufferCountMin; 220 temp.nBufferSize = p->nBufferSize; 221 temp.bEnabled = p->bEnabled; 222 temp.bPopulated = p->bPopulated; 223 temp.eDomain = p->eDomain; 224 temp.bBuffersContiguous = p->bBuffersContiguous; 225 temp.nBufferAlignment = p->nBufferAlignment; 226 } 227 228 switch (p->eDomain) { 229 case OMX_PortDomainAudio: { 230 OMX_AUDIO_PORTDEFINITIONTYPE *format = &temp.format.audio; 231 const OMX_AUDIO_PORTDEFINITIONTYPE *pformat = &p->format.audio; 232 OMX_U32 mimetype_len = strlen(pformat->cMIMEType); 233 234 mimetype_len = OMX_MAX_STRINGNAME_SIZE-1 > mimetype_len ? 235 mimetype_len : OMX_MAX_STRINGNAME_SIZE-1; 236 237 strncpy(format->cMIMEType, pformat->cMIMEType, 238 mimetype_len); 239 format->cMIMEType[mimetype_len+1] = '\0'; 240 format->pNativeRender = pformat->pNativeRender; 241 format->bFlagErrorConcealment = pformat->bFlagErrorConcealment; 242 format->eEncoding = pformat->eEncoding; 243 244 break; 245 } 246 case OMX_PortDomainVideo: { 247 OMX_VIDEO_PORTDEFINITIONTYPE *format = &temp.format.video; 248 const OMX_VIDEO_PORTDEFINITIONTYPE *pformat = &p->format.video; 249 OMX_U32 mimetype_len = strlen(pformat->cMIMEType); 250 251 mimetype_len = OMX_MAX_STRINGNAME_SIZE-1 > mimetype_len ? 252 mimetype_len : OMX_MAX_STRINGNAME_SIZE-1; 253 254 strncpy(format->cMIMEType, pformat->cMIMEType, 255 mimetype_len); 256 format->cMIMEType[mimetype_len+1] = '\0'; 257 format->pNativeRender = pformat->pNativeRender; 258 format->nFrameWidth = pformat->nFrameWidth; 259 format->nFrameHeight = pformat->nFrameHeight; 260 format->nBitrate = pformat->nBitrate; 261 format->xFramerate = pformat->xFramerate; 262 format->bFlagErrorConcealment = pformat->bFlagErrorConcealment; 263 format->eCompressionFormat = pformat->eCompressionFormat; 264 format->eColorFormat = pformat->eColorFormat; 265 format->pNativeWindow = pformat->pNativeWindow; 266 OMX_U32 nFrameSize = getFrameBufSize(format->eColorFormat,format->nFrameWidth,format->nFrameHeight); 267 if(nFrameSize!=-1) 268 temp.nBufferSize = nFrameSize; 269 if (overwrite_readonly) { 270 format->nStride = pformat->nStride; 271 format->nSliceHeight = pformat->nSliceHeight; 272 } 273 274 break; 275 } 276 case OMX_PortDomainImage: { 277 OMX_IMAGE_PORTDEFINITIONTYPE *format = &temp.format.image; 278 const OMX_IMAGE_PORTDEFINITIONTYPE *pformat = &p->format.image; 279 OMX_U32 mimetype_len = strlen(pformat->cMIMEType); 280 281 mimetype_len = OMX_MAX_STRINGNAME_SIZE-1 > mimetype_len ? 282 mimetype_len : OMX_MAX_STRINGNAME_SIZE-1; 283 284 strncpy(format->cMIMEType, pformat->cMIMEType, 285 mimetype_len+1); 286 format->cMIMEType[mimetype_len+1] = '\0'; 287 format->nFrameWidth = pformat->nFrameWidth; 288 format->nFrameHeight = pformat->nFrameHeight; 289 format->nStride = pformat->nStride; 290 format->bFlagErrorConcealment = pformat->bFlagErrorConcealment; 291 format->eCompressionFormat = pformat->eCompressionFormat; 292 format->eColorFormat = pformat->eColorFormat; 293 format->pNativeWindow = pformat->pNativeWindow; 294 295 if (overwrite_readonly) 296 format->nSliceHeight = pformat->nSliceHeight; 297 298 break; 299 } 300 case OMX_PortDomainOther: { 301 OMX_OTHER_PORTDEFINITIONTYPE *format = &temp.format.other; 302 const OMX_OTHER_PORTDEFINITIONTYPE *pformat = &p->format.other; 303 304 format->eFormat = pformat->eFormat; 305 break; 306 } 307 default: 308 LOGE("cannot find 0x%08x port domain\n", p->eDomain); 309 return OMX_ErrorBadParameter; 310 } 311 312 memcpy(&portdefinition, &temp, sizeof(temp)); 313 return OMX_ErrorNone; 314} 315 316const OMX_PARAM_PORTDEFINITIONTYPE *PortBase::GetPortDefinition(void) 317{ 318 return &portdefinition; 319} 320 321/* Use/Allocate/FreeBuffer */ 322OMX_ERRORTYPE PortBase::UseBuffer(OMX_BUFFERHEADERTYPE **ppBufferHdr, 323 OMX_U32 nPortIndex, 324 OMX_PTR pAppPrivate, 325 OMX_U32 nSizeBytes, 326 OMX_U8 *pBuffer) 327{ 328 OMX_BUFFERHEADERTYPE *buffer_hdr; 329 struct list *entry; 330 331 LOGV("%s(): %s:%s:PortIndex %lu: enter, nSizeBytes=%lu\n", __FUNCTION__, 332 cbase->GetName(), cbase->GetWorkingRole(), nPortIndex, nSizeBytes); 333 334 pthread_mutex_lock(&hdrs_lock); 335 336 if (portdefinition.bPopulated == OMX_TRUE) { 337 pthread_mutex_unlock(&hdrs_lock); 338 LOGV("%s(): %s:%s:PortIndex %lu: exit done, already populated\n", 339 __FUNCTION__, cbase->GetName(), cbase->GetWorkingRole(), 340 nPortIndex); 341 return OMX_ErrorNone; 342 } 343 344 buffer_hdr = (OMX_BUFFERHEADERTYPE *)calloc(1, sizeof(*buffer_hdr)); 345 if (!buffer_hdr) { 346 pthread_mutex_unlock(&hdrs_lock); 347 LOGE("%s(): %s:%s:PortIndex %lu: exit failure, " 348 "connot allocate buffer header\n", __FUNCTION__, 349 cbase->GetName(), cbase->GetWorkingRole(), nPortIndex); 350 return OMX_ErrorInsufficientResources; 351 } 352 353 entry = list_alloc(buffer_hdr); 354 if (!entry) { 355 free(buffer_hdr); 356 pthread_mutex_unlock(&hdrs_lock); 357 LOGE("%s(): %s:%s:PortIndex %lu: exit failure, " 358 "cannot allocate list entry\n", __FUNCTION__, 359 cbase->GetName(), cbase->GetWorkingRole(), nPortIndex); 360 return OMX_ErrorInsufficientResources; 361 } 362 363 ComponentBase::SetTypeHeader(buffer_hdr, sizeof(*buffer_hdr)); 364 buffer_hdr->pBuffer = pBuffer; 365 buffer_hdr->nAllocLen = nSizeBytes; 366 buffer_hdr->pAppPrivate = pAppPrivate; 367 buffer_hdr->pInputPortPrivate = NULL; 368 buffer_hdr->pOutputPortPrivate = NULL; 369 if (portdefinition.eDir == OMX_DirInput) { 370 buffer_hdr->nInputPortIndex = nPortIndex; 371 buffer_hdr->nOutputPortIndex = 0x7fffffff; 372 } 373 else { 374 buffer_hdr->nOutputPortIndex = nPortIndex; 375 buffer_hdr->nInputPortIndex = 0x7fffffff; 376 } 377 378 buffer_hdrs = __list_add_tail(buffer_hdrs, entry); 379 nr_buffer_hdrs++; 380 381 LOGV("%s(): %s:%s:PortIndex %lu: a buffer allocated (%p:%lu/%lu)\n", 382 __FUNCTION__, 383 cbase->GetName(), cbase->GetWorkingRole(), nPortIndex, 384 buffer_hdr, nr_buffer_hdrs, portdefinition.nBufferCountActual); 385 386 if (nr_buffer_hdrs >= portdefinition.nBufferCountActual) { 387 portdefinition.bPopulated = OMX_TRUE; 388 buffer_hdrs_completion = true; 389 pthread_cond_signal(&hdrs_wait); 390 LOGV("%s(): %s:%s:PortIndex %lu: allocate all buffers (%lu)\n", 391 __FUNCTION__, cbase->GetName(), cbase->GetWorkingRole(), 392 nPortIndex, portdefinition.nBufferCountActual); 393 } 394 395 *ppBufferHdr = buffer_hdr; 396 397 pthread_mutex_unlock(&hdrs_lock); 398 399 LOGV("%s(): %s:%s:PortIndex %lu: exit done\n", __FUNCTION__, 400 cbase->GetName(), cbase->GetWorkingRole(), nPortIndex); 401 return OMX_ErrorNone; 402} 403 404OMX_ERRORTYPE PortBase:: AllocateBuffer(OMX_BUFFERHEADERTYPE **ppBuffer, 405 OMX_U32 nPortIndex, 406 OMX_PTR pAppPrivate, 407 OMX_U32 nSizeBytes) 408{ 409 OMX_BUFFERHEADERTYPE *buffer_hdr; 410 struct list *entry; 411 412 LOGV("%s(): %s:%s:PortIndex %lu: enter, nSizeBytes=%lu\n", __FUNCTION__, 413 cbase->GetName(), cbase->GetWorkingRole(), nPortIndex, nSizeBytes); 414 415 pthread_mutex_lock(&hdrs_lock); 416 if (portdefinition.bPopulated == OMX_TRUE) { 417 pthread_mutex_unlock(&hdrs_lock); 418 LOGV("%s(): %s:%s:PortIndex %lu: exit done, already populated\n", 419 __FUNCTION__, cbase->GetName(), cbase->GetWorkingRole(), 420 nPortIndex); 421 return OMX_ErrorNone; 422 } 423 424 if (custom_mem_alloc) { 425 buffer_hdr = (OMX_BUFFERHEADERTYPE *) calloc(1, sizeof(*buffer_hdr)); 426 } else { 427 if (mem_alignment > 0) 428 buffer_hdr = (OMX_BUFFERHEADERTYPE *) calloc(1, sizeof(*buffer_hdr) + nSizeBytes + mem_alignment); 429 else 430 buffer_hdr = (OMX_BUFFERHEADERTYPE *) calloc(1, sizeof(*buffer_hdr) + nSizeBytes); 431 } 432 433 if (!buffer_hdr) { 434 pthread_mutex_unlock(&hdrs_lock); 435 LOGE("%s(): %s:%s:PortIndex %lu: exit failure, " 436 "connot allocate buffer header\n", __FUNCTION__, 437 cbase->GetName(), cbase->GetWorkingRole(), nPortIndex); 438 return OMX_ErrorInsufficientResources; 439 } 440 441 entry = list_alloc(buffer_hdr); 442 if (!entry) { 443 free(buffer_hdr); 444 pthread_mutex_unlock(&hdrs_lock); 445 LOGE("%s(): %s:%s:PortIndex %lu: exit failure, " 446 "connot allocate list entry\n", __FUNCTION__, 447 cbase->GetName(), cbase->GetWorkingRole(), nPortIndex); 448 return OMX_ErrorInsufficientResources; 449 } 450 451 ComponentBase::SetTypeHeader(buffer_hdr, sizeof(*buffer_hdr)); 452 if (custom_mem_alloc) { 453 buffer_hdr->pBuffer = (*custom_mem_alloc)(nSizeBytes, custom_mem_userdata); 454 } else { 455 if (mem_alignment > 0) 456 buffer_hdr->pBuffer = (OMX_U8 *)(((OMX_U32)((OMX_U8 *)buffer_hdr + sizeof(*buffer_hdr)) / mem_alignment + 1) * mem_alignment); 457 else 458 buffer_hdr->pBuffer = (OMX_U8 *)buffer_hdr + sizeof(*buffer_hdr); 459 } 460 if (buffer_hdr->pBuffer == NULL) { 461 return OMX_ErrorInsufficientResources; 462 } 463 464 buffer_hdr->nAllocLen = nSizeBytes; 465 buffer_hdr->pAppPrivate = pAppPrivate; 466 buffer_hdr->pInputPortPrivate = NULL; 467 buffer_hdr->pOutputPortPrivate = NULL; 468 if (portdefinition.eDir == OMX_DirInput) { 469 buffer_hdr->nInputPortIndex = nPortIndex; 470 buffer_hdr->nOutputPortIndex = (OMX_U32)-1; 471 } 472 else { 473 buffer_hdr->nOutputPortIndex = nPortIndex; 474 buffer_hdr->nInputPortIndex = (OMX_U32)-1; 475 } 476 477 buffer_hdrs = __list_add_tail(buffer_hdrs, entry); 478 nr_buffer_hdrs++; 479 480 LOGV("%s(): %s:%s:PortIndex %lu: a buffer allocated (%p:%lu/%lu)\n", 481 __FUNCTION__, 482 cbase->GetName(), cbase->GetWorkingRole(), nPortIndex, 483 buffer_hdr, nr_buffer_hdrs, portdefinition.nBufferCountActual); 484 485 if (nr_buffer_hdrs == portdefinition.nBufferCountActual) { 486 portdefinition.bPopulated = OMX_TRUE; 487 buffer_hdrs_completion = true; 488 pthread_cond_signal(&hdrs_wait); 489 LOGV("%s(): %s:%s:PortIndex %lu: allocate all buffers (%lu)\n", 490 __FUNCTION__, cbase->GetName(), cbase->GetWorkingRole(), 491 nPortIndex, portdefinition.nBufferCountActual); 492 } 493 494 *ppBuffer = buffer_hdr; 495 496 pthread_mutex_unlock(&hdrs_lock); 497 498 LOGV("%s(): %s:%s:PortIndex %lu: exit done\n", __FUNCTION__, 499 cbase->GetName(), cbase->GetWorkingRole(), nPortIndex); 500 return OMX_ErrorNone; 501} 502 503OMX_ERRORTYPE PortBase::FreeBuffer(OMX_U32 nPortIndex, 504 OMX_BUFFERHEADERTYPE *pBuffer) 505{ 506 struct list *entry; 507 OMX_ERRORTYPE ret; 508 509 LOGV("%s(): %s:%s:PortIndex %lu:pBuffer %p: enter\n", __FUNCTION__, 510 cbase->GetName(), cbase->GetWorkingRole(), nPortIndex, pBuffer); 511 512 pthread_mutex_lock(&hdrs_lock); 513 entry = list_find(buffer_hdrs, pBuffer); 514 515 if (!entry) { 516 pthread_mutex_unlock(&hdrs_lock); 517 LOGE("%s(): %s:%s:PortIndex %lu:pBuffer %p: exit failure, " 518 "cannot find list entry for pBuffer\n", __FUNCTION__, 519 cbase->GetName(), cbase->GetWorkingRole(), nPortIndex, pBuffer); 520 return OMX_ErrorBadParameter; 521 } 522 523 if (entry->data != pBuffer) { 524 pthread_mutex_unlock(&hdrs_lock); 525 LOGE("%s(): %s:%s:PortIndex %lu:pBuffer %p: exit failure," 526 "mismatch list entry\n" , __FUNCTION__, 527 cbase->GetName(), cbase->GetWorkingRole(), nPortIndex, pBuffer); 528 return OMX_ErrorBadParameter; 529 } 530 531 ret = ComponentBase::CheckTypeHeader(pBuffer, sizeof(*pBuffer)); 532 if (ret != OMX_ErrorNone) { 533 pthread_mutex_unlock(&hdrs_lock); 534 LOGE("%s(): %s:%s:PortIndex %lu:pBuffer %p: exit failure," 535 "invalid type header\n", __FUNCTION__, 536 cbase->GetName(), cbase->GetWorkingRole(), nPortIndex, pBuffer); 537 return ret; 538 } 539 540 buffer_hdrs = __list_delete(buffer_hdrs, entry); 541 nr_buffer_hdrs--; 542 543 LOGV("%s(): %s:%s:PortIndex %lu:pBuffer %p: free a buffer (%lu/%lu)\n", 544 __FUNCTION__, cbase->GetName(), cbase->GetWorkingRole(), nPortIndex, 545 pBuffer, nr_buffer_hdrs, portdefinition.nBufferCountActual); 546 if (custom_mem_free) { 547 (*custom_mem_free)(pBuffer->pBuffer, custom_mem_userdata); 548 pBuffer->pBuffer = NULL; 549 } 550 free(pBuffer); 551 552 portdefinition.bPopulated = OMX_FALSE; 553 if (!nr_buffer_hdrs) { 554 buffer_hdrs_completion = true; 555 pthread_cond_signal(&hdrs_wait); 556 LOGV("%s(): %s:%s:PortIndex %lu: free all allocated buffers (%lu)\n", 557 __FUNCTION__, cbase->GetName(), cbase->GetWorkingRole(), 558 nPortIndex, portdefinition.nBufferCountActual); 559 } 560 561 pthread_mutex_unlock(&hdrs_lock); 562 563 LOGV("%s(): %s:%s:PortIndex %lu: exit done\n", __FUNCTION__, 564 cbase->GetName(), cbase->GetWorkingRole(), nPortIndex); 565 return OMX_ErrorNone; 566} 567 568void PortBase::WaitPortBufferCompletion(void) 569{ 570 pthread_mutex_lock(&hdrs_lock); 571 if (!buffer_hdrs_completion) { 572 LOGV("%s(): %s:%s:PortIndex %lu: wait for buffer header completion\n", 573 __FUNCTION__, cbase->GetName(), cbase->GetWorkingRole(), 574 portdefinition.nPortIndex); 575 pthread_cond_wait(&hdrs_wait, &hdrs_lock); 576 LOGV("%s(): %s:%s:PortIndex %lu: wokeup (buffer header completion)\n", 577 __FUNCTION__, cbase->GetName(), cbase->GetWorkingRole(), 578 portdefinition.nPortIndex); 579 } 580 buffer_hdrs_completion = !buffer_hdrs_completion; 581 pthread_mutex_unlock(&hdrs_lock); 582} 583 584/* Empty/FillThisBuffer */ 585OMX_ERRORTYPE PortBase::PushThisBuffer(OMX_BUFFERHEADERTYPE *pBuffer) 586{ 587 int ret; 588 589 LOGV_IF(pBuffer != NULL, "%s(): %s:%s:PortIndex %lu:pBuffer %p:\n", 590 __FUNCTION__, cbase->GetName(), cbase->GetWorkingRole(), 591 portdefinition.nPortIndex, pBuffer); 592 593 pthread_mutex_lock(&bufferq_lock); 594 ret = queue_push_tail(&bufferq, pBuffer); 595 pthread_mutex_unlock(&bufferq_lock); 596 597 if (ret) 598 return OMX_ErrorInsufficientResources; 599 600 return OMX_ErrorNone; 601} 602 603OMX_BUFFERHEADERTYPE *PortBase::PopBuffer(void) 604{ 605 OMX_BUFFERHEADERTYPE *buffer; 606 607 pthread_mutex_lock(&bufferq_lock); 608 buffer = (OMX_BUFFERHEADERTYPE *)queue_pop_head(&bufferq); 609 pthread_mutex_unlock(&bufferq_lock); 610 611 LOGV_IF(buffer != NULL, "%s(): %s:%s:PortIndex %lu:pBuffer %p:\n", 612 __FUNCTION__, cbase->GetName(), cbase->GetWorkingRole(), 613 portdefinition.nPortIndex, buffer); 614 615 return buffer; 616} 617 618OMX_U32 PortBase::BufferQueueLength(void) 619{ 620 OMX_U32 length; 621 622 pthread_mutex_lock(&bufferq_lock); 623 length = queue_length(&bufferq); 624 pthread_mutex_unlock(&bufferq_lock); 625 626 return length; 627} 628 629OMX_ERRORTYPE PortBase::ReturnThisBuffer(OMX_BUFFERHEADERTYPE *pBuffer) 630{ 631 OMX_DIRTYPE direction = portdefinition.eDir; 632 OMX_U32 port_index; 633 OMX_ERRORTYPE (*bufferdone_callback)(OMX_HANDLETYPE, 634 OMX_PTR, 635 OMX_BUFFERHEADERTYPE *); 636 OMX_ERRORTYPE ret; 637 638 LOGV("%s(): %s:%s:PortIndex %lu:pBuffer %p: enter\n", __FUNCTION__, 639 cbase->GetName(), cbase->GetWorkingRole(), portdefinition.nPortIndex, 640 pBuffer); 641 642 if (!pBuffer) { 643 LOGE("%s(): %s:%s:PortIndex %lu:pBuffer %p: exit failure, " 644 "invalid buffer pointer\n", 645 __FUNCTION__, cbase->GetName(), cbase->GetWorkingRole(), 646 portdefinition.nPortIndex, pBuffer); 647 return OMX_ErrorBadParameter; 648 } 649 650 if (direction == OMX_DirInput) { 651 port_index = pBuffer->nInputPortIndex; 652 bufferdone_callback = callbacks->EmptyBufferDone; 653 } 654 else if (direction == OMX_DirOutput) { 655 port_index = pBuffer->nOutputPortIndex; 656 bufferdone_callback = callbacks->FillBufferDone; 657 } 658 else { 659 LOGE("%s(): %s:%s:PortIndex %lu:pBuffer %p: exit failure, " 660 "invalid direction (%d)\n", 661 __FUNCTION__, cbase->GetName(), cbase->GetWorkingRole(), 662 portdefinition.nPortIndex, pBuffer, 663 direction); 664 return OMX_ErrorBadParameter; 665 } 666 667 if (port_index != portdefinition.nPortIndex) { 668 LOGE("%s(): %s:%s:PortIndex %lu:pBuffer %p: exit failure, " 669 "invalid port index (%lu)\n", __FUNCTION__, 670 cbase->GetName(), cbase->GetWorkingRole(), 671 portdefinition.nPortIndex, pBuffer, port_index); 672 return OMX_ErrorBadParameter; 673 } 674 675 if (pBuffer->nFlags & OMX_BUFFERFLAG_EOS) { 676 LOGV("%s(): %s:%s:PortIndex %lu:pBuffer %p: " 677 "Report OMX_EventBufferFlag (OMX_BUFFERFLAG_EOS)\n", 678 __FUNCTION__, cbase->GetName(), cbase->GetWorkingRole(), 679 portdefinition.nPortIndex, pBuffer); 680 681 callbacks->EventHandler(owner, appdata, 682 OMX_EventBufferFlag, 683 port_index, pBuffer->nFlags, NULL); 684 } 685 686 if (pBuffer->hMarkTargetComponent == owner) { 687 LOGV("%s(): %s:%s:PortIndex %lu:pBuffer %p: " 688 "Report OMX_EventMark\n", 689 __FUNCTION__, cbase->GetName(), cbase->GetWorkingRole(), 690 portdefinition.nPortIndex, pBuffer); 691 692 callbacks->EventHandler(owner, appdata, OMX_EventMark, 693 0, 0, pBuffer->pMarkData); 694 pBuffer->hMarkTargetComponent = NULL; 695 pBuffer->pMarkData = NULL; 696 } 697 698 ret = bufferdone_callback(owner, appdata, pBuffer); 699 700 LOGV("%s(): %s:%s:PortIndex %lu: exit done, " 701 "callback returned (0x%08x)\n", __FUNCTION__, 702 cbase->GetName(), cbase->GetWorkingRole(), portdefinition.nPortIndex, 703 ret); 704 705 return OMX_ErrorNone; 706} 707 708OMX_ERRORTYPE PortBase::RetainAndReturnBuffer( OMX_BUFFERHEADERTYPE *pRetain, OMX_BUFFERHEADERTYPE *pReturn) 709{ 710 OMX_ERRORTYPE ret; 711 OMX_U32 length; 712 if (pReturn == pRetain) { 713 return ReturnThisBuffer(pReturn); 714 } 715 ret = RetainThisBuffer(pRetain, false); 716 if (ret != OMX_ErrorNone) { 717 return ret; 718 } 719 720 pthread_mutex_lock(&bufferq_lock); 721 length = queue_length(&bufferq); 722 OMX_BUFFERHEADERTYPE *p; 723 /* remove returned buffer from the queue */ 724 for (OMX_U32 i = 0; i < length; i++) { 725 p = (OMX_BUFFERHEADERTYPE *)queue_pop_head(&bufferq); 726 if (p == pReturn) { 727 break; 728 } 729 queue_push_tail(&bufferq, p); 730 } 731 732 pthread_mutex_unlock(&bufferq_lock); 733 734 return ReturnThisBuffer(pReturn); 735} 736 737/* retain buffer */ 738OMX_ERRORTYPE PortBase::RetainThisBuffer(OMX_BUFFERHEADERTYPE *pBuffer, 739 bool accumulate) 740{ 741 int ret; 742 743 LOGV("%s(): %s:%s:PortIndex %lu:pBuffer %p: enter, %s\n", __FUNCTION__, 744 cbase->GetName(), cbase->GetWorkingRole(), portdefinition.nPortIndex, 745 pBuffer, (accumulate == true) ? "accumulate" : "getagain"); 746 747 /* push at tail of retainedbufferq */ 748 if (accumulate == true) { 749 /* do not accumulate a buffer set EOS flag */ 750 if (pBuffer->nFlags & OMX_BUFFERFLAG_EOS) { 751 LOGE("%s(): %s:%s:PortIndex %lu:pBuffer %p: exit failure, " 752 "cannot accumulate EOS buffer\n", __FUNCTION__, 753 cbase->GetName(), cbase->GetWorkingRole(), 754 portdefinition.nPortIndex, pBuffer); 755 return OMX_ErrorBadParameter; 756 } 757 758 pthread_mutex_lock(&retainedbufferq_lock); 759 if ((OMX_U32)queue_length(&retainedbufferq) < 760 portdefinition.nBufferCountActual) 761 ret = queue_push_tail(&retainedbufferq, pBuffer); 762 else { 763 ret = OMX_ErrorInsufficientResources; 764 LOGE("%s(): %s:%s:PortIndex %lu:pBuffer %p: exit failure, " 765 "retained bufferq length (%d) exceeds port's actual count " 766 "(%lu)\n", __FUNCTION__, 767 cbase->GetName(), cbase->GetWorkingRole(), 768 portdefinition.nPortIndex, pBuffer, 769 queue_length(&retainedbufferq), 770 portdefinition.nBufferCountActual); 771 } 772 pthread_mutex_unlock(&retainedbufferq_lock); 773 } 774 /* 775 * just push at head of bufferq to get this buffer again in 776 * ComponentBase::ProcessorProcess() 777 */ 778 else { 779 pthread_mutex_lock(&bufferq_lock); 780 ret = queue_push_head(&bufferq, pBuffer); 781 pthread_mutex_unlock(&bufferq_lock); 782 } 783 784 if (ret) 785 return OMX_ErrorInsufficientResources; 786 787 LOGV("%s(): %s:%s:PortIndex %lu:pBuffer %p: exit done\n", __FUNCTION__, 788 cbase->GetName(), cbase->GetWorkingRole(), 789 portdefinition.nPortIndex, pBuffer); 790 return OMX_ErrorNone; 791} 792 793void PortBase::ReturnAllRetainedBuffers(void) 794{ 795 OMX_BUFFERHEADERTYPE *buffer; 796 OMX_ERRORTYPE ret; 797 int i = 0; 798 799 pthread_mutex_lock(&retainedbufferq_lock); 800 801 do { 802 buffer = (OMX_BUFFERHEADERTYPE *)queue_pop_head(&retainedbufferq); 803 804 if (buffer) { 805 LOGV("%s(): %s:%s:PortIndex %lu: returns a retained buffer " 806 "(%p:%d/%d)\n", __FUNCTION__, cbase->GetName(), 807 cbase->GetWorkingRole(), portdefinition.nPortIndex, 808 buffer, i++, queue_length(&retainedbufferq)); 809 810 ret = ReturnThisBuffer(buffer); 811 if (ret != OMX_ErrorNone) 812 LOGE("%s(): %s:%s:PortIndex %lu: failed (ret : 0x%x08x)\n", 813 __FUNCTION__, 814 cbase->GetName(), cbase->GetWorkingRole(), 815 portdefinition.nPortIndex, ret); 816 } 817 } while (buffer); 818 819 pthread_mutex_unlock(&retainedbufferq_lock); 820 821 LOGV_IF(i != 0, 822 "%s(): %s:%s:PortIndex %lu: returned all retained buffers (%d)\n", 823 __FUNCTION__, cbase->GetName(), cbase->GetWorkingRole(), 824 portdefinition.nPortIndex, i); 825} 826 827/* SendCommand:Flush/PortEnable/Disable */ 828/* must be held ComponentBase::ports_block */ 829OMX_ERRORTYPE PortBase::FlushPort(void) 830{ 831 OMX_BUFFERHEADERTYPE *buffer; 832 833 LOGV("%s(): %s:%s:PortIndex %lu: enter\n", __FUNCTION__, 834 cbase->GetName(), cbase->GetWorkingRole(), 835 portdefinition.nPortIndex); 836 837 ReturnAllRetainedBuffers(); 838 839 while ((buffer = PopBuffer())) 840 ReturnThisBuffer(buffer); 841 842 LOGV("%s(): %s:%s:PortIndex %lu: exit\n", __FUNCTION__, 843 cbase->GetName(), cbase->GetWorkingRole(), 844 portdefinition.nPortIndex); 845 846 return OMX_ErrorNone; 847} 848 849OMX_STATETYPE PortBase::GetOwnerState(void) 850{ 851 OMX_STATETYPE state = OMX_StateInvalid; 852 853 if (owner) { 854 ComponentBase *cbase; 855 cbase = static_cast<ComponentBase *>(owner->pComponentPrivate); 856 if (!cbase) 857 return state; 858 859 cbase->CBaseGetState((void *)owner, &state); 860 } 861 862 return state; 863} 864 865bool PortBase::IsEnabled(void) 866{ 867 bool enabled; 868 bool unlock = true; 869 870 if (pthread_mutex_trylock(&state_lock)) 871 unlock = false; 872 873 enabled = (state == OMX_PortEnabled) ? true : false; 874 875 if (unlock) 876 pthread_mutex_unlock(&state_lock); 877 878 return enabled; 879} 880 881OMX_DIRTYPE PortBase::GetPortDirection(void) 882{ 883 return portdefinition.eDir; 884} 885 886OMX_U32 PortBase::GetPortBufferCount(void) 887{ 888 return nr_buffer_hdrs; 889} 890 891OMX_ERRORTYPE PortBase::PushMark(OMX_MARKTYPE *mark) 892{ 893 int ret; 894 895 pthread_mutex_lock(&markq_lock); 896 ret = queue_push_tail(&markq, mark); 897 pthread_mutex_unlock(&markq_lock); 898 899 if (ret) 900 return OMX_ErrorInsufficientResources; 901 902 return OMX_ErrorNone; 903} 904 905OMX_MARKTYPE *PortBase::PopMark(void) 906{ 907 OMX_MARKTYPE *mark; 908 909 pthread_mutex_lock(&markq_lock); 910 mark = (OMX_MARKTYPE *)queue_pop_head(&markq); 911 pthread_mutex_unlock(&markq_lock); 912 913 return mark; 914} 915 916static const char *state_name[PortBase::OMX_PortEnabled+2] = { 917 "OMX_PortDisabled", 918 "OMX_PortEnabled", 919 "UnKnown Port State", 920}; 921 922const char *GetPortStateName(OMX_U8 state) 923{ 924 if (state > PortBase::OMX_PortEnabled) 925 state = PortBase::OMX_PortEnabled+1; 926 927 return state_name[state]; 928} 929 930OMX_ERRORTYPE PortBase::TransState(OMX_U8 transition) 931{ 932 OMX_U8 current; 933 OMX_ERRORTYPE ret = OMX_ErrorNone; 934 935 LOGV("%s(): %s:%s:PortIndex %lu: enter, transition from %s to %s\n", 936 __FUNCTION__, 937 cbase->GetName(), cbase->GetWorkingRole(), portdefinition.nPortIndex, 938 GetPortStateName(state), GetPortStateName(transition)); 939 940 pthread_mutex_lock(&state_lock); 941 942 current = state; 943 944 if (current == transition) { 945 ret = OMX_ErrorSameState; 946 LOGE("%s(): %s:%s:PortIndex %lu: exit failure, same state (%s)\n", 947 __FUNCTION__, 948 cbase->GetName(), cbase->GetWorkingRole(), 949 portdefinition.nPortIndex, GetPortStateName(current)); 950 goto unlock; 951 } 952 953 if (transition == OMX_PortEnabled) { 954 WaitPortBufferCompletion(); 955 portdefinition.bEnabled = OMX_TRUE; 956 } 957 else if(transition == OMX_PortDisabled) { 958 /*need to flush only if port is not empty*/ 959 if (nr_buffer_hdrs) 960 { 961 FlushPort(); 962 WaitPortBufferCompletion(); 963 } 964 portdefinition.bEnabled = OMX_FALSE; 965 } 966 else { 967 ret = OMX_ErrorBadParameter; 968 LOGE("%s(): %s:%s:PortIndex %lu: exit failure, invalid transition " 969 "(%s)\n", __FUNCTION__, 970 cbase->GetName(), cbase->GetWorkingRole(), 971 portdefinition.nPortIndex, GetPortStateName(transition)); 972 goto unlock; 973 } 974 975 state = transition; 976 977 LOGV("%s(): %s:%s:PortIndex %lu: transition from %s to %s complete\n", 978 __FUNCTION__, 979 cbase->GetName(), cbase->GetWorkingRole(), portdefinition.nPortIndex, 980 GetPortStateName(current), GetPortStateName(state)); 981 982unlock: 983 pthread_mutex_unlock(&state_lock); 984 return ret; 985} 986 987OMX_ERRORTYPE PortBase::ReportPortSettingsChanged(void) 988{ 989 OMX_ERRORTYPE ret; 990 991 ret = callbacks->EventHandler(owner, appdata, 992 OMX_EventPortSettingsChanged, 993 portdefinition.nPortIndex,OMX_IndexParamPortDefinition, NULL); 994 995 FlushPort(); 996 997 return ret; 998} 999 1000OMX_ERRORTYPE PortBase::ReportOutputCrop(void) 1001{ 1002 OMX_ERRORTYPE ret; 1003 1004 ret = callbacks->EventHandler(owner, appdata, 1005 OMX_EventPortSettingsChanged, 1006 portdefinition.nPortIndex,OMX_IndexConfigCommonOutputCrop, NULL); 1007 1008 return ret; 1009} 1010 1011 1012/* end of component methods & helpers */ 1013 1014/* end of PortBase */ 1015