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