OMXNodeInstance.cpp revision 570a3cb7582daa030cb38eedc5eb6a06f86ecc7f
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 void **buffer_data) { 263 Mutex::Autolock autoLock(mLock); 264 265 BufferMeta *buffer_meta = new BufferMeta(size); 266 267 OMX_BUFFERHEADERTYPE *header; 268 269 OMX_ERRORTYPE err = OMX_AllocateBuffer( 270 mHandle, &header, portIndex, buffer_meta, size); 271 272 if (err != OMX_ErrorNone) { 273 LOGE("OMX_AllocateBuffer failed with error %d (0x%08x)", err, err); 274 275 delete buffer_meta; 276 buffer_meta = NULL; 277 278 *buffer = 0; 279 280 return UNKNOWN_ERROR; 281 } 282 283 *buffer = header; 284 *buffer_data = header->pBuffer; 285 286 addActiveBuffer(portIndex, *buffer); 287 288 return OK; 289} 290 291status_t OMXNodeInstance::allocateBufferWithBackup( 292 OMX_U32 portIndex, const sp<IMemory> ¶ms, 293 OMX::buffer_id *buffer) { 294 Mutex::Autolock autoLock(mLock); 295 296 BufferMeta *buffer_meta = new BufferMeta(params, true); 297 298 OMX_BUFFERHEADERTYPE *header; 299 300 OMX_ERRORTYPE err = OMX_AllocateBuffer( 301 mHandle, &header, portIndex, buffer_meta, params->size()); 302 303 if (err != OMX_ErrorNone) { 304 LOGE("OMX_AllocateBuffer failed with error %d (0x%08x)", err, err); 305 306 delete buffer_meta; 307 buffer_meta = NULL; 308 309 *buffer = 0; 310 311 return UNKNOWN_ERROR; 312 } 313 314 *buffer = header; 315 316 addActiveBuffer(portIndex, *buffer); 317 318 return OK; 319} 320 321status_t OMXNodeInstance::freeBuffer( 322 OMX_U32 portIndex, OMX::buffer_id buffer) { 323 Mutex::Autolock autoLock(mLock); 324 325 removeActiveBuffer(portIndex, buffer); 326 327 OMX_BUFFERHEADERTYPE *header = (OMX_BUFFERHEADERTYPE *)buffer; 328 BufferMeta *buffer_meta = static_cast<BufferMeta *>(header->pAppPrivate); 329 330 OMX_ERRORTYPE err = OMX_FreeBuffer(mHandle, portIndex, header); 331 332 delete buffer_meta; 333 buffer_meta = NULL; 334 335 return StatusFromOMXError(err); 336} 337 338status_t OMXNodeInstance::fillBuffer(OMX::buffer_id buffer) { 339 Mutex::Autolock autoLock(mLock); 340 341 OMX_BUFFERHEADERTYPE *header = (OMX_BUFFERHEADERTYPE *)buffer; 342 header->nFilledLen = 0; 343 header->nOffset = 0; 344 header->nFlags = 0; 345 346 OMX_ERRORTYPE err = OMX_FillThisBuffer(mHandle, header); 347 348 return StatusFromOMXError(err); 349} 350 351status_t OMXNodeInstance::emptyBuffer( 352 OMX::buffer_id buffer, 353 OMX_U32 rangeOffset, OMX_U32 rangeLength, 354 OMX_U32 flags, OMX_TICKS timestamp) { 355 Mutex::Autolock autoLock(mLock); 356 357 OMX_BUFFERHEADERTYPE *header = (OMX_BUFFERHEADERTYPE *)buffer; 358 header->nFilledLen = rangeLength; 359 header->nOffset = rangeOffset; 360 header->nFlags = flags; 361 header->nTimeStamp = timestamp; 362 363 BufferMeta *buffer_meta = 364 static_cast<BufferMeta *>(header->pAppPrivate); 365 buffer_meta->CopyToOMX(header); 366 367 OMX_ERRORTYPE err = OMX_EmptyThisBuffer(mHandle, header); 368 369 return StatusFromOMXError(err); 370} 371 372status_t OMXNodeInstance::getExtensionIndex( 373 const char *parameterName, OMX_INDEXTYPE *index) { 374 Mutex::Autolock autoLock(mLock); 375 376 OMX_ERRORTYPE err = OMX_GetExtensionIndex( 377 mHandle, const_cast<char *>(parameterName), index); 378 379 return StatusFromOMXError(err); 380} 381 382void OMXNodeInstance::onMessage(const omx_message &msg) { 383 if (msg.type == omx_message::FILL_BUFFER_DONE) { 384 OMX_BUFFERHEADERTYPE *buffer = 385 static_cast<OMX_BUFFERHEADERTYPE *>( 386 msg.u.extended_buffer_data.buffer); 387 388 BufferMeta *buffer_meta = 389 static_cast<BufferMeta *>(buffer->pAppPrivate); 390 391 buffer_meta->CopyFromOMX(buffer); 392 } 393 394 mObserver->onMessage(msg); 395} 396 397void OMXNodeInstance::onObserverDied(OMXMaster *master) { 398 LOGE("!!! Observer died. Quickly, do something, ... anything..."); 399 400 // Try to force shutdown of the node and hope for the best. 401 freeNode(master); 402} 403 404void OMXNodeInstance::onGetHandleFailed() { 405 delete this; 406} 407 408// static 409OMX_ERRORTYPE OMXNodeInstance::OnEvent( 410 OMX_IN OMX_HANDLETYPE hComponent, 411 OMX_IN OMX_PTR pAppData, 412 OMX_IN OMX_EVENTTYPE eEvent, 413 OMX_IN OMX_U32 nData1, 414 OMX_IN OMX_U32 nData2, 415 OMX_IN OMX_PTR pEventData) { 416 OMXNodeInstance *instance = static_cast<OMXNodeInstance *>(pAppData); 417 if (instance->mDying) { 418 return OMX_ErrorNone; 419 } 420 return instance->owner()->OnEvent( 421 instance->nodeID(), eEvent, nData1, nData2, pEventData); 422} 423 424// static 425OMX_ERRORTYPE OMXNodeInstance::OnEmptyBufferDone( 426 OMX_IN OMX_HANDLETYPE hComponent, 427 OMX_IN OMX_PTR pAppData, 428 OMX_IN OMX_BUFFERHEADERTYPE* pBuffer) { 429 OMXNodeInstance *instance = static_cast<OMXNodeInstance *>(pAppData); 430 if (instance->mDying) { 431 return OMX_ErrorNone; 432 } 433 return instance->owner()->OnEmptyBufferDone(instance->nodeID(), pBuffer); 434} 435 436// static 437OMX_ERRORTYPE OMXNodeInstance::OnFillBufferDone( 438 OMX_IN OMX_HANDLETYPE hComponent, 439 OMX_IN OMX_PTR pAppData, 440 OMX_IN OMX_BUFFERHEADERTYPE* pBuffer) { 441 OMXNodeInstance *instance = static_cast<OMXNodeInstance *>(pAppData); 442 if (instance->mDying) { 443 return OMX_ErrorNone; 444 } 445 return instance->owner()->OnFillBufferDone(instance->nodeID(), pBuffer); 446} 447 448void OMXNodeInstance::addActiveBuffer(OMX_U32 portIndex, OMX::buffer_id id) { 449 ActiveBuffer active; 450 active.mPortIndex = portIndex; 451 active.mID = id; 452 mActiveBuffers.push(active); 453} 454 455void OMXNodeInstance::removeActiveBuffer( 456 OMX_U32 portIndex, OMX::buffer_id id) { 457 bool found = false; 458 for (size_t i = 0; i < mActiveBuffers.size(); ++i) { 459 if (mActiveBuffers[i].mPortIndex == portIndex 460 && mActiveBuffers[i].mID == id) { 461 found = true; 462 mActiveBuffers.removeItemsAt(i); 463 break; 464 } 465 } 466 467 if (!found) { 468 LOGW("Attempt to remove an active buffer we know nothing about..."); 469 } 470} 471 472void OMXNodeInstance::freeActiveBuffers() { 473 // Make sure to count down here, as freeBuffer will in turn remove 474 // the active buffer from the vector... 475 for (size_t i = mActiveBuffers.size(); i--;) { 476 freeBuffer(mActiveBuffers[i].mPortIndex, mActiveBuffers[i].mID); 477 } 478} 479 480} // namespace android 481 482