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