OMXNodeInstance.cpp revision 2d6d6e9a3d569eda4555c4eb68cec452be958bb1
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 23#include "pv_omxcore.h" 24 25#include <binder/IMemory.h> 26#include <media/stagefright/MediaDebug.h> 27 28namespace android { 29 30struct BufferMeta { 31 BufferMeta(const sp<IMemory> &mem, bool is_backup = false) 32 : mMem(mem), 33 mIsBackup(is_backup) { 34 } 35 36 BufferMeta(size_t size) 37 : mSize(size), 38 mIsBackup(false) { 39 } 40 41 void CopyFromOMX(const OMX_BUFFERHEADERTYPE *header) { 42 if (!mIsBackup) { 43 return; 44 } 45 46 memcpy((OMX_U8 *)mMem->pointer() + header->nOffset, 47 header->pBuffer + header->nOffset, 48 header->nFilledLen); 49 } 50 51 void CopyToOMX(const OMX_BUFFERHEADERTYPE *header) { 52 if (!mIsBackup) { 53 return; 54 } 55 56 memcpy(header->pBuffer + header->nOffset, 57 (const OMX_U8 *)mMem->pointer() + header->nOffset, 58 header->nFilledLen); 59 } 60 61private: 62 sp<IMemory> mMem; 63 size_t mSize; 64 bool mIsBackup; 65 66 BufferMeta(const BufferMeta &); 67 BufferMeta &operator=(const BufferMeta &); 68}; 69 70// static 71OMX_CALLBACKTYPE OMXNodeInstance::kCallbacks = { 72 &OnEvent, &OnEmptyBufferDone, &OnFillBufferDone 73}; 74 75OMXNodeInstance::OMXNodeInstance( 76 OMX *owner, const sp<IOMXObserver> &observer) 77 : mOwner(owner), 78 mNodeID(NULL), 79 mHandle(NULL), 80 mObserver(observer) { 81} 82 83OMXNodeInstance::~OMXNodeInstance() { 84 CHECK_EQ(mHandle, NULL); 85} 86 87void OMXNodeInstance::setHandle(OMX::node_id node_id, OMX_HANDLETYPE handle) { 88 CHECK_EQ(mHandle, NULL); 89 mNodeID = node_id; 90 mHandle = handle; 91} 92 93OMX *OMXNodeInstance::owner() { 94 return mOwner; 95} 96 97sp<IOMXObserver> OMXNodeInstance::observer() { 98 return mObserver; 99} 100 101OMX::node_id OMXNodeInstance::nodeID() { 102 return mNodeID; 103} 104 105static status_t StatusFromOMXError(OMX_ERRORTYPE err) { 106 return (err == OMX_ErrorNone) ? OK : UNKNOWN_ERROR; 107} 108 109status_t OMXNodeInstance::freeNode() { 110 Mutex::Autolock autoLock(mLock); 111 112 OMX_ERRORTYPE err = OMX_MasterFreeHandle(mHandle); 113 mHandle = NULL; 114 115 if (err != OMX_ErrorNone) { 116 LOGE("FreeHandle FAILED with error 0x%08x.", err); 117 } 118 119 mOwner->invalidateNodeID(mNodeID); 120 mNodeID = NULL; 121 122 LOGI("OMXNodeInstance going away."); 123 mObserver.clear(); 124 // delete this; // leads to heap-corruption??? 125 126 return StatusFromOMXError(err); 127} 128 129status_t OMXNodeInstance::sendCommand( 130 OMX_COMMANDTYPE cmd, OMX_S32 param) { 131 Mutex::Autolock autoLock(mLock); 132 133 OMX_ERRORTYPE err = OMX_SendCommand(mHandle, cmd, param, NULL); 134 return StatusFromOMXError(err); 135} 136 137status_t OMXNodeInstance::getParameter( 138 OMX_INDEXTYPE index, void *params, size_t size) { 139 Mutex::Autolock autoLock(mLock); 140 141 OMX_ERRORTYPE err = OMX_GetParameter(mHandle, index, params); 142 return StatusFromOMXError(err); 143} 144 145status_t OMXNodeInstance::setParameter( 146 OMX_INDEXTYPE index, const void *params, size_t size) { 147 Mutex::Autolock autoLock(mLock); 148 149 OMX_ERRORTYPE err = OMX_SetParameter( 150 mHandle, index, const_cast<void *>(params)); 151 152 return StatusFromOMXError(err); 153} 154 155status_t OMXNodeInstance::getConfig( 156 OMX_INDEXTYPE index, void *params, size_t size) { 157 Mutex::Autolock autoLock(mLock); 158 159 OMX_ERRORTYPE err = OMX_GetConfig(mHandle, index, params); 160 return StatusFromOMXError(err); 161} 162 163status_t OMXNodeInstance::setConfig( 164 OMX_INDEXTYPE index, const void *params, size_t size) { 165 Mutex::Autolock autoLock(mLock); 166 167 OMX_ERRORTYPE err = OMX_SetConfig( 168 mHandle, index, const_cast<void *>(params)); 169 170 return StatusFromOMXError(err); 171} 172 173status_t OMXNodeInstance::useBuffer( 174 OMX_U32 portIndex, const sp<IMemory> ¶ms, 175 OMX::buffer_id *buffer) { 176 Mutex::Autolock autoLock(mLock); 177 178 BufferMeta *buffer_meta = new BufferMeta(params); 179 180 OMX_BUFFERHEADERTYPE *header; 181 182 OMX_ERRORTYPE err = OMX_UseBuffer( 183 mHandle, &header, portIndex, buffer_meta, 184 params->size(), static_cast<OMX_U8 *>(params->pointer())); 185 186 if (err != OMX_ErrorNone) { 187 LOGE("OMX_UseBuffer failed with error %d (0x%08x)", err, err); 188 189 delete buffer_meta; 190 buffer_meta = NULL; 191 192 *buffer = 0; 193 194 return UNKNOWN_ERROR; 195 } 196 197 *buffer = header; 198 199 return OK; 200} 201 202status_t OMXNodeInstance::allocateBuffer( 203 OMX_U32 portIndex, size_t size, OMX::buffer_id *buffer) { 204 Mutex::Autolock autoLock(mLock); 205 206 BufferMeta *buffer_meta = new BufferMeta(size); 207 208 OMX_BUFFERHEADERTYPE *header; 209 210 OMX_ERRORTYPE err = OMX_AllocateBuffer( 211 mHandle, &header, portIndex, buffer_meta, size); 212 213 if (err != OMX_ErrorNone) { 214 LOGE("OMX_AllocateBuffer failed with error %d (0x%08x)", err, err); 215 216 delete buffer_meta; 217 buffer_meta = NULL; 218 219 *buffer = 0; 220 221 return UNKNOWN_ERROR; 222 } 223 224 *buffer = header; 225 226 return OK; 227} 228 229status_t OMXNodeInstance::allocateBufferWithBackup( 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, true); 235 236 OMX_BUFFERHEADERTYPE *header; 237 238 OMX_ERRORTYPE err = OMX_AllocateBuffer( 239 mHandle, &header, portIndex, buffer_meta, params->size()); 240 241 if (err != OMX_ErrorNone) { 242 LOGE("OMX_AllocateBuffer failed with error %d (0x%08x)", err, err); 243 244 delete buffer_meta; 245 buffer_meta = NULL; 246 247 *buffer = 0; 248 249 return UNKNOWN_ERROR; 250 } 251 252 *buffer = header; 253 254 return OK; 255} 256 257status_t OMXNodeInstance::freeBuffer( 258 OMX_U32 portIndex, OMX::buffer_id buffer) { 259 Mutex::Autolock autoLock(mLock); 260 261 OMX_BUFFERHEADERTYPE *header = (OMX_BUFFERHEADERTYPE *)buffer; 262 BufferMeta *buffer_meta = static_cast<BufferMeta *>(header->pAppPrivate); 263 264 OMX_ERRORTYPE err = OMX_FreeBuffer(mHandle, portIndex, header); 265 266 delete buffer_meta; 267 buffer_meta = NULL; 268 269 return StatusFromOMXError(err); 270} 271 272status_t OMXNodeInstance::fillBuffer(OMX::buffer_id buffer) { 273 Mutex::Autolock autoLock(mLock); 274 275 OMX_BUFFERHEADERTYPE *header = (OMX_BUFFERHEADERTYPE *)buffer; 276 header->nFilledLen = 0; 277 header->nOffset = 0; 278 header->nFlags = 0; 279 280 OMX_ERRORTYPE err = OMX_FillThisBuffer(mHandle, header); 281 282 return StatusFromOMXError(err); 283} 284 285status_t OMXNodeInstance::emptyBuffer( 286 OMX::buffer_id buffer, 287 OMX_U32 rangeOffset, OMX_U32 rangeLength, 288 OMX_U32 flags, OMX_TICKS timestamp) { 289 Mutex::Autolock autoLock(mLock); 290 291 OMX_BUFFERHEADERTYPE *header = (OMX_BUFFERHEADERTYPE *)buffer; 292 header->nFilledLen = rangeLength; 293 header->nOffset = rangeOffset; 294 header->nFlags = flags; 295 header->nTimeStamp = timestamp; 296 297 BufferMeta *buffer_meta = 298 static_cast<BufferMeta *>(header->pAppPrivate); 299 buffer_meta->CopyToOMX(header); 300 301 OMX_ERRORTYPE err = OMX_EmptyThisBuffer(mHandle, header); 302 303 return StatusFromOMXError(err); 304} 305 306status_t OMXNodeInstance::getExtensionIndex( 307 const char *parameterName, OMX_INDEXTYPE *index) { 308 Mutex::Autolock autoLock(mLock); 309 310 OMX_ERRORTYPE err = OMX_GetExtensionIndex( 311 mHandle, const_cast<char *>(parameterName), index); 312 313 return StatusFromOMXError(err); 314} 315 316void OMXNodeInstance::onMessage(const omx_message &msg) { 317 if (msg.type == omx_message::FILL_BUFFER_DONE) { 318 OMX_BUFFERHEADERTYPE *buffer = 319 static_cast<OMX_BUFFERHEADERTYPE *>( 320 msg.u.extended_buffer_data.buffer); 321 322 BufferMeta *buffer_meta = 323 static_cast<BufferMeta *>(buffer->pAppPrivate); 324 325 buffer_meta->CopyFromOMX(buffer); 326 } 327 328 mObserver->onMessage(msg); 329} 330 331void OMXNodeInstance::onObserverDied() { 332 LOGE("!!! Observer died. Quickly, do something, ... anything..."); 333 334 // Try to force shutdown of the node and hope for the best. 335 freeNode(); 336} 337 338void OMXNodeInstance::onGetHandleFailed() { 339 delete this; 340} 341 342// static 343OMX_ERRORTYPE OMXNodeInstance::OnEvent( 344 OMX_IN OMX_HANDLETYPE hComponent, 345 OMX_IN OMX_PTR pAppData, 346 OMX_IN OMX_EVENTTYPE eEvent, 347 OMX_IN OMX_U32 nData1, 348 OMX_IN OMX_U32 nData2, 349 OMX_IN OMX_PTR pEventData) { 350 OMXNodeInstance *instance = static_cast<OMXNodeInstance *>(pAppData); 351 return instance->owner()->OnEvent( 352 instance->nodeID(), eEvent, nData1, nData2, pEventData); 353} 354 355// static 356OMX_ERRORTYPE OMXNodeInstance::OnEmptyBufferDone( 357 OMX_IN OMX_HANDLETYPE hComponent, 358 OMX_IN OMX_PTR pAppData, 359 OMX_IN OMX_BUFFERHEADERTYPE* pBuffer) { 360 OMXNodeInstance *instance = static_cast<OMXNodeInstance *>(pAppData); 361 return instance->owner()->OnEmptyBufferDone(instance->nodeID(), pBuffer); 362} 363 364// static 365OMX_ERRORTYPE OMXNodeInstance::OnFillBufferDone( 366 OMX_IN OMX_HANDLETYPE hComponent, 367 OMX_IN OMX_PTR pAppData, 368 OMX_IN OMX_BUFFERHEADERTYPE* pBuffer) { 369 OMXNodeInstance *instance = static_cast<OMXNodeInstance *>(pAppData); 370 return instance->owner()->OnFillBufferDone(instance->nodeID(), pBuffer); 371} 372 373} // namespace android 374 375