OMXNodeInstance.cpp revision fef6435a0692f3c9b6055903dfb7699e90e19d46
1/* 2 * Copyright (C) 2009 The Android Open Source Project 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 "OMXNodeInstance" 19#include <utils/Log.h> 20 21#include "../include/OMXNodeInstance.h" 22#include "OMXMaster.h" 23 24#include <OMX_Component.h> 25 26#include <binder/IMemory.h> 27#include <media/stagefright/MediaDebug.h> 28 29namespace android { 30 31struct BufferMeta { 32 BufferMeta(const sp<IMemory> &mem, bool is_backup = false) 33 : mMem(mem), 34 mIsBackup(is_backup) { 35 } 36 37 BufferMeta(size_t size) 38 : mSize(size), 39 mIsBackup(false) { 40 } 41 42 void CopyFromOMX(const OMX_BUFFERHEADERTYPE *header) { 43 if (!mIsBackup) { 44 return; 45 } 46 47 memcpy((OMX_U8 *)mMem->pointer() + header->nOffset, 48 header->pBuffer + header->nOffset, 49 header->nFilledLen); 50 } 51 52 void CopyToOMX(const OMX_BUFFERHEADERTYPE *header) { 53 if (!mIsBackup) { 54 return; 55 } 56 57 memcpy(header->pBuffer + header->nOffset, 58 (const OMX_U8 *)mMem->pointer() + header->nOffset, 59 header->nFilledLen); 60 } 61 62private: 63 sp<IMemory> mMem; 64 size_t mSize; 65 bool mIsBackup; 66 67 BufferMeta(const BufferMeta &); 68 BufferMeta &operator=(const BufferMeta &); 69}; 70 71// static 72OMX_CALLBACKTYPE OMXNodeInstance::kCallbacks = { 73 &OnEvent, &OnEmptyBufferDone, &OnFillBufferDone 74}; 75 76OMXNodeInstance::OMXNodeInstance( 77 OMX *owner, const sp<IOMXObserver> &observer) 78 : mOwner(owner), 79 mNodeID(NULL), 80 mHandle(NULL), 81 mObserver(observer) { 82} 83 84OMXNodeInstance::~OMXNodeInstance() { 85 CHECK_EQ(mHandle, NULL); 86} 87 88void OMXNodeInstance::setHandle(OMX::node_id node_id, OMX_HANDLETYPE handle) { 89 CHECK_EQ(mHandle, NULL); 90 mNodeID = node_id; 91 mHandle = handle; 92} 93 94OMX *OMXNodeInstance::owner() { 95 return mOwner; 96} 97 98sp<IOMXObserver> OMXNodeInstance::observer() { 99 return mObserver; 100} 101 102OMX::node_id OMXNodeInstance::nodeID() { 103 return mNodeID; 104} 105 106static status_t StatusFromOMXError(OMX_ERRORTYPE err) { 107 return (err == OMX_ErrorNone) ? OK : UNKNOWN_ERROR; 108} 109 110status_t OMXNodeInstance::freeNode(OMXMaster *master) { 111 // Transition the node from its current state all the way down 112 // to "Loaded". 113 // This ensures that all active buffers are properly freed even 114 // for components that don't do this themselves on a call to 115 // "FreeHandle". 116 117 OMX_STATETYPE state; 118 CHECK_EQ(OMX_GetState(mHandle, &state), OMX_ErrorNone); 119 switch (state) { 120 case OMX_StateExecuting: 121 { 122 LOGV("forcing Executing->Idle"); 123 sendCommand(OMX_CommandStateSet, OMX_StateIdle); 124 OMX_ERRORTYPE err; 125 while ((err = OMX_GetState(mHandle, &state)) == OMX_ErrorNone 126 && state != OMX_StateIdle) { 127 usleep(100000); 128 } 129 CHECK_EQ(err, OMX_ErrorNone); 130 131 // fall through 132 } 133 134 case OMX_StateIdle: 135 { 136 LOGV("forcing Idle->Loaded"); 137 sendCommand(OMX_CommandStateSet, OMX_StateLoaded); 138 139 freeActiveBuffers(); 140 141 OMX_ERRORTYPE err; 142 while ((err = OMX_GetState(mHandle, &state)) == OMX_ErrorNone 143 && state != OMX_StateLoaded) { 144 LOGV("waiting for Loaded state..."); 145 usleep(100000); 146 } 147 CHECK_EQ(err, OMX_ErrorNone); 148 149 // fall through 150 } 151 152 case OMX_StateLoaded: 153 case OMX_StateInvalid: 154 break; 155 156 default: 157 CHECK(!"should not be here, unknown state."); 158 break; 159 } 160 161 OMX_ERRORTYPE err = master->destroyComponentInstance( 162 static_cast<OMX_COMPONENTTYPE *>(mHandle)); 163 164 mHandle = NULL; 165 166 if (err != OMX_ErrorNone) { 167 LOGE("FreeHandle FAILED with error 0x%08x.", err); 168 } 169 170 mOwner->invalidateNodeID(mNodeID); 171 mNodeID = NULL; 172 173 LOGV("OMXNodeInstance going away."); 174 delete this; 175 176 return StatusFromOMXError(err); 177} 178 179status_t OMXNodeInstance::sendCommand( 180 OMX_COMMANDTYPE cmd, OMX_S32 param) { 181 Mutex::Autolock autoLock(mLock); 182 183 OMX_ERRORTYPE err = OMX_SendCommand(mHandle, cmd, param, NULL); 184 return StatusFromOMXError(err); 185} 186 187status_t OMXNodeInstance::getParameter( 188 OMX_INDEXTYPE index, void *params, size_t size) { 189 Mutex::Autolock autoLock(mLock); 190 191 OMX_ERRORTYPE err = OMX_GetParameter(mHandle, index, params); 192 return StatusFromOMXError(err); 193} 194 195status_t OMXNodeInstance::setParameter( 196 OMX_INDEXTYPE index, const void *params, size_t size) { 197 Mutex::Autolock autoLock(mLock); 198 199 OMX_ERRORTYPE err = OMX_SetParameter( 200 mHandle, index, const_cast<void *>(params)); 201 202 return StatusFromOMXError(err); 203} 204 205status_t OMXNodeInstance::getConfig( 206 OMX_INDEXTYPE index, void *params, size_t size) { 207 Mutex::Autolock autoLock(mLock); 208 209 OMX_ERRORTYPE err = OMX_GetConfig(mHandle, index, params); 210 return StatusFromOMXError(err); 211} 212 213status_t OMXNodeInstance::setConfig( 214 OMX_INDEXTYPE index, const void *params, size_t size) { 215 Mutex::Autolock autoLock(mLock); 216 217 OMX_ERRORTYPE err = OMX_SetConfig( 218 mHandle, index, const_cast<void *>(params)); 219 220 return StatusFromOMXError(err); 221} 222 223status_t OMXNodeInstance::useBuffer( 224 OMX_U32 portIndex, const sp<IMemory> ¶ms, 225 OMX::buffer_id *buffer) { 226 Mutex::Autolock autoLock(mLock); 227 228 BufferMeta *buffer_meta = new BufferMeta(params); 229 230 OMX_BUFFERHEADERTYPE *header; 231 232 OMX_ERRORTYPE err = OMX_UseBuffer( 233 mHandle, &header, portIndex, buffer_meta, 234 params->size(), static_cast<OMX_U8 *>(params->pointer())); 235 236 if (err != OMX_ErrorNone) { 237 LOGE("OMX_UseBuffer failed with error %d (0x%08x)", err, err); 238 239 delete buffer_meta; 240 buffer_meta = NULL; 241 242 *buffer = 0; 243 244 return UNKNOWN_ERROR; 245 } 246 247 *buffer = header; 248 249 addActiveBuffer(portIndex, *buffer); 250 251 return OK; 252} 253 254status_t OMXNodeInstance::allocateBuffer( 255 OMX_U32 portIndex, size_t size, OMX::buffer_id *buffer) { 256 Mutex::Autolock autoLock(mLock); 257 258 BufferMeta *buffer_meta = new BufferMeta(size); 259 260 OMX_BUFFERHEADERTYPE *header; 261 262 OMX_ERRORTYPE err = OMX_AllocateBuffer( 263 mHandle, &header, portIndex, buffer_meta, size); 264 265 if (err != OMX_ErrorNone) { 266 LOGE("OMX_AllocateBuffer failed with error %d (0x%08x)", err, err); 267 268 delete buffer_meta; 269 buffer_meta = NULL; 270 271 *buffer = 0; 272 273 return UNKNOWN_ERROR; 274 } 275 276 *buffer = header; 277 278 addActiveBuffer(portIndex, *buffer); 279 280 return OK; 281} 282 283status_t OMXNodeInstance::allocateBufferWithBackup( 284 OMX_U32 portIndex, const sp<IMemory> ¶ms, 285 OMX::buffer_id *buffer) { 286 Mutex::Autolock autoLock(mLock); 287 288 BufferMeta *buffer_meta = new BufferMeta(params, true); 289 290 OMX_BUFFERHEADERTYPE *header; 291 292 OMX_ERRORTYPE err = OMX_AllocateBuffer( 293 mHandle, &header, portIndex, buffer_meta, params->size()); 294 295 if (err != OMX_ErrorNone) { 296 LOGE("OMX_AllocateBuffer failed with error %d (0x%08x)", err, err); 297 298 delete buffer_meta; 299 buffer_meta = NULL; 300 301 *buffer = 0; 302 303 return UNKNOWN_ERROR; 304 } 305 306 *buffer = header; 307 308 addActiveBuffer(portIndex, *buffer); 309 310 return OK; 311} 312 313status_t OMXNodeInstance::freeBuffer( 314 OMX_U32 portIndex, OMX::buffer_id buffer) { 315 Mutex::Autolock autoLock(mLock); 316 317 removeActiveBuffer(portIndex, buffer); 318 319 OMX_BUFFERHEADERTYPE *header = (OMX_BUFFERHEADERTYPE *)buffer; 320 BufferMeta *buffer_meta = static_cast<BufferMeta *>(header->pAppPrivate); 321 322 OMX_ERRORTYPE err = OMX_FreeBuffer(mHandle, portIndex, header); 323 324 delete buffer_meta; 325 buffer_meta = NULL; 326 327 return StatusFromOMXError(err); 328} 329 330status_t OMXNodeInstance::fillBuffer(OMX::buffer_id buffer) { 331 Mutex::Autolock autoLock(mLock); 332 333 OMX_BUFFERHEADERTYPE *header = (OMX_BUFFERHEADERTYPE *)buffer; 334 header->nFilledLen = 0; 335 header->nOffset = 0; 336 header->nFlags = 0; 337 338 OMX_ERRORTYPE err = OMX_FillThisBuffer(mHandle, header); 339 340 return StatusFromOMXError(err); 341} 342 343status_t OMXNodeInstance::emptyBuffer( 344 OMX::buffer_id buffer, 345 OMX_U32 rangeOffset, OMX_U32 rangeLength, 346 OMX_U32 flags, OMX_TICKS timestamp) { 347 Mutex::Autolock autoLock(mLock); 348 349 OMX_BUFFERHEADERTYPE *header = (OMX_BUFFERHEADERTYPE *)buffer; 350 header->nFilledLen = rangeLength; 351 header->nOffset = rangeOffset; 352 header->nFlags = flags; 353 header->nTimeStamp = timestamp; 354 355 BufferMeta *buffer_meta = 356 static_cast<BufferMeta *>(header->pAppPrivate); 357 buffer_meta->CopyToOMX(header); 358 359 OMX_ERRORTYPE err = OMX_EmptyThisBuffer(mHandle, header); 360 361 return StatusFromOMXError(err); 362} 363 364status_t OMXNodeInstance::getExtensionIndex( 365 const char *parameterName, OMX_INDEXTYPE *index) { 366 Mutex::Autolock autoLock(mLock); 367 368 OMX_ERRORTYPE err = OMX_GetExtensionIndex( 369 mHandle, const_cast<char *>(parameterName), index); 370 371 return StatusFromOMXError(err); 372} 373 374void OMXNodeInstance::onMessage(const omx_message &msg) { 375 if (msg.type == omx_message::FILL_BUFFER_DONE) { 376 OMX_BUFFERHEADERTYPE *buffer = 377 static_cast<OMX_BUFFERHEADERTYPE *>( 378 msg.u.extended_buffer_data.buffer); 379 380 BufferMeta *buffer_meta = 381 static_cast<BufferMeta *>(buffer->pAppPrivate); 382 383 buffer_meta->CopyFromOMX(buffer); 384 } 385 386 mObserver->onMessage(msg); 387} 388 389void OMXNodeInstance::onObserverDied(OMXMaster *master) { 390 LOGE("!!! Observer died. Quickly, do something, ... anything..."); 391 392 // Try to force shutdown of the node and hope for the best. 393 freeNode(master); 394} 395 396void OMXNodeInstance::onGetHandleFailed() { 397 delete this; 398} 399 400// static 401OMX_ERRORTYPE OMXNodeInstance::OnEvent( 402 OMX_IN OMX_HANDLETYPE hComponent, 403 OMX_IN OMX_PTR pAppData, 404 OMX_IN OMX_EVENTTYPE eEvent, 405 OMX_IN OMX_U32 nData1, 406 OMX_IN OMX_U32 nData2, 407 OMX_IN OMX_PTR pEventData) { 408 OMXNodeInstance *instance = static_cast<OMXNodeInstance *>(pAppData); 409 return instance->owner()->OnEvent( 410 instance->nodeID(), eEvent, nData1, nData2, pEventData); 411} 412 413// static 414OMX_ERRORTYPE OMXNodeInstance::OnEmptyBufferDone( 415 OMX_IN OMX_HANDLETYPE hComponent, 416 OMX_IN OMX_PTR pAppData, 417 OMX_IN OMX_BUFFERHEADERTYPE* pBuffer) { 418 OMXNodeInstance *instance = static_cast<OMXNodeInstance *>(pAppData); 419 return instance->owner()->OnEmptyBufferDone(instance->nodeID(), pBuffer); 420} 421 422// static 423OMX_ERRORTYPE OMXNodeInstance::OnFillBufferDone( 424 OMX_IN OMX_HANDLETYPE hComponent, 425 OMX_IN OMX_PTR pAppData, 426 OMX_IN OMX_BUFFERHEADERTYPE* pBuffer) { 427 OMXNodeInstance *instance = static_cast<OMXNodeInstance *>(pAppData); 428 return instance->owner()->OnFillBufferDone(instance->nodeID(), pBuffer); 429} 430 431void OMXNodeInstance::addActiveBuffer(OMX_U32 portIndex, OMX::buffer_id id) { 432 ActiveBuffer active; 433 active.mPortIndex = portIndex; 434 active.mID = id; 435 mActiveBuffers.push(active); 436} 437 438void OMXNodeInstance::removeActiveBuffer( 439 OMX_U32 portIndex, OMX::buffer_id id) { 440 bool found = false; 441 for (size_t i = 0; i < mActiveBuffers.size(); ++i) { 442 if (mActiveBuffers[i].mPortIndex == portIndex 443 && mActiveBuffers[i].mID == id) { 444 found = true; 445 mActiveBuffers.removeItemsAt(i); 446 break; 447 } 448 } 449 450 if (!found) { 451 LOGW("Attempt to remove an active buffer we know nothing about..."); 452 } 453} 454 455void OMXNodeInstance::freeActiveBuffers() { 456 // Make sure to count down here, as freeBuffer will in turn remove 457 // the active buffer from the vector... 458 for (size_t i = mActiveBuffers.size(); i--;) { 459 freeBuffer(mActiveBuffers[i].mPortIndex, mActiveBuffers[i].mID); 460 } 461} 462 463} // namespace android 464 465