portbase.cpp revision f4ab90019707fb84477f62dd3093eaff0ac466eb
1/* 2 * Copyright (C) 2009 Wind River Systems 3 * Author: Ho-Eun Ryu <ho-eun.ryu@windriver.com> 4 */ 5 6#include <stdlib.h> 7#include <string.h> 8 9#include <OMX_Core.h> 10#include <OMX_Component.h> 11 12#include <portbase.h> 13#include <componentbase.h> 14 15#define LOG_TAG "portbase" 16#include <log.h> 17 18/* 19 * constructor & destructor 20 */ 21void PortBase::__PortBase(void) 22{ 23 buffer_hdrs = NULL; 24 nr_buffer_hdrs = 0; 25 buffer_hdrs_completion = false; 26 27 pthread_mutex_init(&hdrs_lock, NULL); 28 pthread_cond_init(&hdrs_wait, NULL); 29 30 __queue_init(&bufferq); 31 pthread_mutex_init(&bufferq_lock, NULL); 32 33 __queue_init(&markq); 34 pthread_mutex_init(&markq_lock, NULL); 35 36 state = OMX_PortEnabled; 37 pthread_mutex_init(&state_lock, NULL); 38 39 memset(&portdefinition, 0, sizeof(portdefinition)); 40 ComponentBase::SetTypeHeader(&portdefinition, sizeof(portdefinition)); 41 memset(definition_format_mimetype, 0, OMX_MAX_STRINGNAME_SIZE); 42 portdefinition.format.audio.cMIMEType = &definition_format_mimetype[0]; 43 portdefinition.format.video.cMIMEType = &definition_format_mimetype[0]; 44 portdefinition.format.image.cMIMEType = &definition_format_mimetype[0]; 45 46 memset(&audioparam, 0, sizeof(audioparam)); 47 48 owner = NULL; 49 appdata = NULL; 50 callbacks = NULL; 51} 52 53PortBase::PortBase() 54{ 55 __PortBase(); 56} 57 58PortBase::PortBase(const OMX_PARAM_PORTDEFINITIONTYPE *portdefinition) 59{ 60 __PortBase(); 61 SetPortDefinition(portdefinition, true); 62} 63 64PortBase::~PortBase() 65{ 66 struct list *entry, *temp; 67 68 /* should've been already freed at FreeBuffer() */ 69 list_foreach_safe(buffer_hdrs, entry, temp) { 70 free(entry->data); /* OMX_BUFFERHEADERTYPE */ 71 __list_delete(buffer_hdrs, entry); 72 } 73 74 pthread_cond_destroy(&hdrs_wait); 75 pthread_mutex_destroy(&hdrs_lock); 76 77 /* should've been already freed at buffer processing */ 78 queue_free_all(&bufferq); 79 pthread_mutex_destroy(&bufferq_lock); 80 81 /* should've been already empty in PushThisBuffer () */ 82 queue_free_all(&markq); 83 pthread_mutex_destroy(&markq_lock); 84 85 pthread_mutex_destroy(&state_lock); 86} 87 88/* end of constructor & destructor */ 89 90/* 91 * accessor 92 */ 93/* owner */ 94void PortBase::SetOwner(OMX_COMPONENTTYPE *handle) 95{ 96 owner = handle; 97} 98 99OMX_COMPONENTTYPE *PortBase::GetOwner(void) 100{ 101 return owner; 102} 103 104OMX_ERRORTYPE PortBase::SetCallbacks(OMX_HANDLETYPE hComponent, 105 OMX_CALLBACKTYPE *pCallbacks, 106 OMX_PTR pAppData) 107{ 108 if (owner != hComponent) 109 return OMX_ErrorBadParameter; 110 111 appdata = pAppData; 112 callbacks = pCallbacks; 113 114 return OMX_ErrorNone; 115} 116 117/* end of accessor */ 118 119/* 120 * component methods & helpers 121 */ 122/* Get/SetParameter */ 123OMX_ERRORTYPE PortBase::SetPortDefinition( 124 const OMX_PARAM_PORTDEFINITIONTYPE *p, bool overwrite_readonly) 125{ 126 OMX_PARAM_PORTDEFINITIONTYPE temp; 127 128 memcpy(&temp, &portdefinition, sizeof(temp)); 129 130 if (!overwrite_readonly) { 131 if (temp.nPortIndex != p->nPortIndex) 132 return OMX_ErrorBadParameter; 133 if (temp.eDir != p->eDir) 134 return OMX_ErrorBadParameter; 135 if (temp.eDomain != p->eDomain) 136 return OMX_ErrorBadParameter; 137 if (temp.nBufferCountActual != p->nBufferCountActual) { 138 if (temp.nBufferCountMin > p->nBufferCountActual) 139 return OMX_ErrorBadParameter; 140 141 temp.nBufferCountActual = p->nBufferCountActual; 142 } 143 } 144 else { 145 temp.nPortIndex = p->nPortIndex; 146 temp.eDir = p->eDir; 147 temp.nBufferCountActual = p->nBufferCountActual; 148 temp.nBufferCountMin = p->nBufferCountMin; 149 temp.bEnabled = p->bEnabled; 150 temp.bPopulated = p->bPopulated; 151 temp.eDomain = p->eDomain; 152 temp.bBuffersContiguous = p->bBuffersContiguous; 153 temp.nBufferAlignment = p->nBufferAlignment; 154 } 155 156 switch (p->eDomain) { 157 case OMX_PortDomainAudio: { 158 OMX_AUDIO_PORTDEFINITIONTYPE *format = &temp.format.audio; 159 const OMX_AUDIO_PORTDEFINITIONTYPE *pformat = &p->format.audio; 160 OMX_U32 mimetype_len = strlen(pformat->cMIMEType); 161 162 mimetype_len = OMX_MAX_STRINGNAME_SIZE-1 > mimetype_len ? 163 mimetype_len : OMX_MAX_STRINGNAME_SIZE-1; 164 165 strncpy(format->cMIMEType, pformat->cMIMEType, 166 mimetype_len); 167 format->cMIMEType[mimetype_len+1] = '\0'; 168 format->pNativeRender = pformat->pNativeRender; 169 format->bFlagErrorConcealment = pformat->bFlagErrorConcealment; 170 format->eEncoding = pformat->eEncoding; 171 172 break; 173 } 174 case OMX_PortDomainVideo: { 175 OMX_VIDEO_PORTDEFINITIONTYPE *format = &temp.format.video; 176 const OMX_VIDEO_PORTDEFINITIONTYPE *pformat = &p->format.video; 177 OMX_U32 mimetype_len = strlen(pformat->cMIMEType); 178 179 mimetype_len = OMX_MAX_STRINGNAME_SIZE-1 > mimetype_len ? 180 mimetype_len : OMX_MAX_STRINGNAME_SIZE-1; 181 182 strncpy(format->cMIMEType, pformat->cMIMEType, 183 mimetype_len); 184 format->cMIMEType[mimetype_len+1] = '\0'; 185 format->pNativeRender = pformat->pNativeRender; 186 format->nFrameWidth = pformat->nFrameWidth; 187 format->nFrameHeight = pformat->nFrameHeight; 188 format->nBitrate = pformat->nBitrate; 189 format->xFramerate = pformat->xFramerate; 190 format->bFlagErrorConcealment = pformat->bFlagErrorConcealment; 191 format->eCompressionFormat = pformat->eCompressionFormat; 192 format->eColorFormat = pformat->eColorFormat; 193 format->pNativeWindow = pformat->pNativeWindow; 194 195 if (overwrite_readonly) { 196 format->nStride = pformat->nStride; 197 format->nSliceHeight = pformat->nSliceHeight; 198 } 199 200 break; 201 } 202 case OMX_PortDomainImage: { 203 OMX_IMAGE_PORTDEFINITIONTYPE *format = &temp.format.image; 204 const OMX_IMAGE_PORTDEFINITIONTYPE *pformat = &p->format.image; 205 OMX_U32 mimetype_len = strlen(pformat->cMIMEType); 206 207 mimetype_len = OMX_MAX_STRINGNAME_SIZE-1 > mimetype_len ? 208 mimetype_len : OMX_MAX_STRINGNAME_SIZE-1; 209 210 strncpy(format->cMIMEType, pformat->cMIMEType, 211 mimetype_len+1); 212 format->cMIMEType[mimetype_len+1] = '\0'; 213 format->nFrameWidth = pformat->nFrameWidth; 214 format->nFrameHeight = pformat->nFrameHeight; 215 format->nStride = pformat->nStride; 216 format->bFlagErrorConcealment = pformat->bFlagErrorConcealment; 217 format->eCompressionFormat = pformat->eCompressionFormat; 218 format->eColorFormat = pformat->eColorFormat; 219 format->pNativeWindow = pformat->pNativeWindow; 220 221 if (overwrite_readonly) 222 format->nSliceHeight = pformat->nSliceHeight; 223 224 break; 225 } 226 case OMX_PortDomainOther: { 227 OMX_OTHER_PORTDEFINITIONTYPE *format = &temp.format.other; 228 const OMX_OTHER_PORTDEFINITIONTYPE *pformat = &p->format.other; 229 230 format->eFormat = pformat->eFormat; 231 break; 232 } 233 default: 234 LOGE("cannot find 0x%08x port domain\n", p->eDomain); 235 return OMX_ErrorBadParameter; 236 } 237 238 memcpy(&portdefinition, &temp, sizeof(temp)); 239 return OMX_ErrorNone; 240} 241 242const OMX_PARAM_PORTDEFINITIONTYPE *PortBase::GetPortDefinition(void) 243{ 244 return &portdefinition; 245} 246 247/* Use/Allocate/FreeBuffer */ 248OMX_ERRORTYPE PortBase::UseBuffer(OMX_BUFFERHEADERTYPE **ppBufferHdr, 249 OMX_U32 nPortIndex, 250 OMX_PTR pAppPrivate, 251 OMX_U32 nSizeBytes, 252 OMX_U8 *pBuffer) 253{ 254 OMX_BUFFERHEADERTYPE *buffer_hdr; 255 struct list *entry; 256 257 pthread_mutex_lock(&hdrs_lock); 258 259 if (portdefinition.bPopulated == OMX_TRUE) { 260 pthread_mutex_unlock(&hdrs_lock); 261 return OMX_ErrorNone; 262 } 263 264 buffer_hdr = (OMX_BUFFERHEADERTYPE *)calloc(1, sizeof(*buffer_hdr)); 265 if (!buffer_hdr) { 266 pthread_mutex_unlock(&hdrs_lock); 267 return OMX_ErrorInsufficientResources; 268 } 269 270 entry = list_alloc(buffer_hdr); 271 if (!entry) { 272 free(buffer_hdr); 273 pthread_mutex_unlock(&hdrs_lock); 274 return OMX_ErrorInsufficientResources; 275 } 276 277 ComponentBase::SetTypeHeader(buffer_hdr, sizeof(*buffer_hdr)); 278 buffer_hdr->pBuffer = pBuffer; 279 buffer_hdr->nAllocLen = nSizeBytes; 280 buffer_hdr->pAppPrivate = pAppPrivate; 281 if (portdefinition.eDir == OMX_DirInput) { 282 buffer_hdr->nInputPortIndex = nPortIndex; 283 buffer_hdr->nOutputPortIndex = 0x7fffffff; 284 buffer_hdr->pInputPortPrivate = this; 285 buffer_hdr->pOutputPortPrivate = NULL; 286 } 287 else { 288 buffer_hdr->nOutputPortIndex = nPortIndex; 289 buffer_hdr->nInputPortIndex = 0x7fffffff; 290 buffer_hdr->pOutputPortPrivate = this; 291 buffer_hdr->pInputPortPrivate = NULL; 292 } 293 294 buffer_hdrs = __list_add_tail(buffer_hdrs, entry); 295 nr_buffer_hdrs++; 296 297 if (nr_buffer_hdrs >= portdefinition.nBufferCountActual) { 298 portdefinition.bPopulated = OMX_TRUE; 299 buffer_hdrs_completion = true; 300 pthread_cond_signal(&hdrs_wait); 301 } 302 303 *ppBufferHdr = buffer_hdr; 304 305 pthread_mutex_unlock(&hdrs_lock); 306 return OMX_ErrorNone; 307} 308 309OMX_ERRORTYPE PortBase::AllocateBuffer(OMX_BUFFERHEADERTYPE **ppBuffer, 310 OMX_U32 nPortIndex, 311 OMX_PTR pAppPrivate, 312 OMX_U32 nSizeBytes) 313{ 314 OMX_BUFFERHEADERTYPE *buffer_hdr; 315 struct list *entry; 316 317 pthread_mutex_lock(&hdrs_lock); 318 if (portdefinition.bPopulated == OMX_TRUE) { 319 pthread_mutex_unlock(&hdrs_lock); 320 return OMX_ErrorNone; 321 } 322 323 buffer_hdr = (OMX_BUFFERHEADERTYPE *) 324 calloc(1, sizeof(*buffer_hdr) + nSizeBytes); 325 if (!buffer_hdr) { 326 pthread_mutex_unlock(&hdrs_lock); 327 return OMX_ErrorInsufficientResources; 328 } 329 330 entry = list_alloc(buffer_hdr); 331 if (!entry) { 332 free(buffer_hdr); 333 pthread_mutex_unlock(&hdrs_lock); 334 return OMX_ErrorInsufficientResources; 335 } 336 337 ComponentBase::SetTypeHeader(buffer_hdr, sizeof(*buffer_hdr)); 338 buffer_hdr->pBuffer = (OMX_U8 *)buffer_hdr + sizeof(*buffer_hdr); 339 buffer_hdr->nAllocLen = nSizeBytes; 340 buffer_hdr->pAppPrivate = pAppPrivate; 341 if (portdefinition.eDir == OMX_DirInput) { 342 buffer_hdr->nInputPortIndex = nPortIndex; 343 buffer_hdr->nOutputPortIndex = (OMX_U32)-1; 344 buffer_hdr->pInputPortPrivate = this; 345 buffer_hdr->pOutputPortPrivate = NULL; 346 } 347 else { 348 buffer_hdr->nOutputPortIndex = nPortIndex; 349 buffer_hdr->nInputPortIndex = (OMX_U32)-1; 350 buffer_hdr->pOutputPortPrivate = this; 351 buffer_hdr->pInputPortPrivate = NULL; 352 } 353 354 buffer_hdrs = __list_add_tail(buffer_hdrs, entry); 355 nr_buffer_hdrs++; 356 357 if (nr_buffer_hdrs == portdefinition.nBufferCountActual) { 358 portdefinition.bPopulated = OMX_TRUE; 359 buffer_hdrs_completion = true; 360 pthread_cond_signal(&hdrs_wait); 361 } 362 363 *ppBuffer = buffer_hdr; 364 365 pthread_mutex_unlock(&hdrs_lock); 366 return OMX_ErrorNone; 367} 368 369OMX_ERRORTYPE PortBase::FreeBuffer(OMX_U32 nPortIndex, 370 OMX_BUFFERHEADERTYPE *pBuffer) 371{ 372 struct list *entry; 373 OMX_ERRORTYPE ret; 374 375 pthread_mutex_lock(&hdrs_lock); 376 entry = list_find(buffer_hdrs, pBuffer); 377 378 if (!entry) { 379 pthread_mutex_unlock(&hdrs_lock); 380 return OMX_ErrorNone; 381 } 382 383 if (entry->data != pBuffer) { 384 pthread_mutex_unlock(&hdrs_lock); 385 return OMX_ErrorBadParameter; 386 } 387 388 ret = ComponentBase::CheckTypeHeader(pBuffer, sizeof(*pBuffer)); 389 if (ret != OMX_ErrorNone) { 390 pthread_mutex_unlock(&hdrs_lock); 391 return ret; 392 } 393 394 buffer_hdrs = __list_delete(buffer_hdrs, entry); 395 nr_buffer_hdrs--; 396 397 portdefinition.bPopulated = OMX_FALSE; 398 if (!nr_buffer_hdrs) { 399 buffer_hdrs_completion = true; 400 pthread_cond_signal(&hdrs_wait); 401 } 402 403 free(pBuffer); 404 405 pthread_mutex_unlock(&hdrs_lock); 406 return OMX_ErrorNone; 407} 408 409void PortBase::WaitPortBufferCompletion(void) 410{ 411 pthread_mutex_lock(&hdrs_lock); 412 if (!buffer_hdrs_completion) 413 pthread_cond_wait(&hdrs_wait, &hdrs_lock); 414 buffer_hdrs_completion = !buffer_hdrs_completion; 415 pthread_mutex_unlock(&hdrs_lock); 416} 417 418/* Empty/FillThisBuffer */ 419OMX_ERRORTYPE PortBase::PushThisBuffer(OMX_BUFFERHEADERTYPE *pBuffer) 420{ 421 int ret; 422 423 pthread_mutex_lock(&bufferq_lock); 424 ret = queue_push_tail(&bufferq, pBuffer); 425 pthread_mutex_unlock(&bufferq_lock); 426 427 if (ret) 428 return OMX_ErrorInsufficientResources; 429 430 return OMX_ErrorNone; 431} 432 433OMX_ERRORTYPE PortBase::RetainThisBuffer(OMX_BUFFERHEADERTYPE *pBuffer) 434{ 435 int ret; 436 437 pthread_mutex_lock(&bufferq_lock); 438 ret = queue_push_head(&bufferq, pBuffer); 439 pthread_mutex_unlock(&bufferq_lock); 440 441 if (ret) 442 return OMX_ErrorInsufficientResources; 443 444 return OMX_ErrorNone; 445} 446 447OMX_BUFFERHEADERTYPE *PortBase::PopBuffer(void) 448{ 449 OMX_BUFFERHEADERTYPE *buffer; 450 451 pthread_mutex_lock(&bufferq_lock); 452 buffer = (OMX_BUFFERHEADERTYPE *)queue_pop_head(&bufferq); 453 pthread_mutex_unlock(&bufferq_lock); 454 455 return buffer; 456} 457 458OMX_U32 PortBase::BufferQueueLength(void) 459{ 460 OMX_U32 length; 461 462 pthread_mutex_lock(&bufferq_lock); 463 length = queue_length(&bufferq); 464 pthread_mutex_unlock(&bufferq_lock); 465 466 return length; 467} 468 469OMX_ERRORTYPE PortBase::ReturnThisBuffer(OMX_BUFFERHEADERTYPE *pBuffer) 470{ 471 OMX_DIRTYPE direction = portdefinition.eDir; 472 OMX_U32 port_index; 473 OMX_ERRORTYPE (*bufferdone_callback)(OMX_HANDLETYPE, 474 OMX_PTR, 475 OMX_BUFFERHEADERTYPE *); 476 477 if (!pBuffer) 478 return OMX_ErrorBadParameter; 479 480 if (direction == OMX_DirInput) { 481 port_index = pBuffer->nInputPortIndex; 482 bufferdone_callback = callbacks->EmptyBufferDone; 483 } 484 else if (direction == OMX_DirOutput) { 485 port_index = pBuffer->nOutputPortIndex; 486 bufferdone_callback = callbacks->FillBufferDone; 487 } 488 else 489 return OMX_ErrorBadParameter; 490 491 if (port_index != portdefinition.nPortIndex) 492 return OMX_ErrorBadParameter; 493 494 return bufferdone_callback(owner, appdata, pBuffer); 495} 496 497/* SendCommand:Flush/PortEnable/Disable */ 498/* must be held ComponentBase::ports_block */ 499OMX_ERRORTYPE PortBase::FlushPort(void) 500{ 501 OMX_BUFFERHEADERTYPE *buffer; 502 503 while ((buffer = PopBuffer())) 504 ReturnThisBuffer(buffer); 505 506 return OMX_ErrorNone; 507} 508 509OMX_STATETYPE PortBase::GetOwnerState(void) 510{ 511 OMX_STATETYPE state = OMX_StateInvalid; 512 513 if (owner) { 514 ComponentBase *cbase; 515 cbase = static_cast<ComponentBase *>(owner->pComponentPrivate); 516 if (!cbase) 517 return state; 518 519 cbase->CBaseGetState((void *)owner, &state); 520 } 521 522 return state; 523} 524 525bool PortBase::IsEnabled(void) 526{ 527 bool enabled; 528 bool unlock = true; 529 530 if (pthread_mutex_trylock(&state_lock)) 531 unlock = false; 532 533 enabled = (state == OMX_PortEnabled) ? true : false; 534 535 if (unlock) 536 pthread_mutex_unlock(&state_lock); 537 538 return enabled; 539} 540 541OMX_DIRTYPE PortBase::GetPortDirection(void) 542{ 543 return portdefinition.eDir; 544} 545 546OMX_ERRORTYPE PortBase::PushMark(OMX_MARKTYPE *mark) 547{ 548 int ret; 549 550 pthread_mutex_lock(&markq_lock); 551 ret = queue_push_tail(&markq, mark); 552 pthread_mutex_unlock(&markq_lock); 553 554 if (ret) 555 return OMX_ErrorInsufficientResources; 556 557 return OMX_ErrorNone; 558} 559 560OMX_MARKTYPE *PortBase::PopMark(void) 561{ 562 OMX_MARKTYPE *mark; 563 564 pthread_mutex_lock(&markq_lock); 565 mark = (OMX_MARKTYPE *)queue_pop_head(&markq); 566 pthread_mutex_unlock(&markq_lock); 567 568 return mark; 569} 570 571OMX_ERRORTYPE PortBase::TransState(OMX_U8 transition) 572{ 573 OMX_U8 current; 574 OMX_ERRORTYPE ret = OMX_ErrorNone; 575 576 pthread_mutex_lock(&state_lock); 577 578 current = state; 579 580 if (current == transition) { 581 ret = OMX_ErrorSameState; 582 goto unlock; 583 } 584 585 if (transition == OMX_PortEnabled) { 586 WaitPortBufferCompletion(); 587 portdefinition.bEnabled = OMX_TRUE; 588 } 589 else if(transition == OMX_PortDisabled) { 590 FlushPort(); 591 WaitPortBufferCompletion(); 592 portdefinition.bEnabled = OMX_FALSE; 593 } 594 else { 595 ret = OMX_ErrorBadParameter; 596 goto unlock; 597 } 598 599 state = transition; 600 601unlock: 602 pthread_mutex_unlock(&state_lock); 603 return ret; 604} 605 606/* end of component methods & helpers */ 607 608/* end of PortBase */ 609