OMX.cpp revision 408b8e1073385d0d09bb96b9952f84731a0b4aeb
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 "OMX" 19#include <utils/Log.h> 20 21#include <sys/socket.h> 22 23#undef NDEBUG 24#include <assert.h> 25 26#include "OMX.h" 27#include "OMXRenderer.h" 28 29#include "pv_omxcore.h" 30 31#include <binder/IMemory.h> 32#include <media/stagefright/QComHardwareRenderer.h> 33#include <media/stagefright/SoftwareRenderer.h> 34#include <media/stagefright/TIHardwareRenderer.h> 35#include <media/stagefright/VideoRenderer.h> 36 37#include <OMX_Component.h> 38 39namespace android { 40 41class NodeMeta { 42public: 43 NodeMeta(OMX *owner) 44 : mOwner(owner), 45 mHandle(NULL) { 46 } 47 48 OMX *owner() const { 49 return mOwner; 50 } 51 52 void setHandle(OMX_HANDLETYPE handle) { 53 assert(mHandle == NULL); 54 mHandle = handle; 55 } 56 57 OMX_HANDLETYPE handle() const { 58 return mHandle; 59 } 60 61 void setObserver(const sp<IOMXObserver> &observer) { 62 mObserver = observer; 63 } 64 65 sp<IOMXObserver> observer() { 66 return mObserver; 67 } 68 69private: 70 OMX *mOwner; 71 OMX_HANDLETYPE mHandle; 72 sp<IOMXObserver> mObserver; 73 74 NodeMeta(const NodeMeta &); 75 NodeMeta &operator=(const NodeMeta &); 76}; 77 78class BufferMeta { 79public: 80 BufferMeta(OMX *owner, const sp<IMemory> &mem, bool is_backup = false) 81 : mOwner(owner), 82 mMem(mem), 83 mIsBackup(is_backup) { 84 } 85 86 BufferMeta(OMX *owner, size_t size) 87 : mOwner(owner), 88 mSize(size), 89 mIsBackup(false) { 90 } 91 92 void CopyFromOMX(const OMX_BUFFERHEADERTYPE *header) { 93 if (!mIsBackup) { 94 return; 95 } 96 97 memcpy((OMX_U8 *)mMem->pointer() + header->nOffset, 98 header->pBuffer + header->nOffset, 99 header->nFilledLen); 100 } 101 102 void CopyToOMX(const OMX_BUFFERHEADERTYPE *header) { 103 if (!mIsBackup) { 104 return; 105 } 106 107 memcpy(header->pBuffer + header->nOffset, 108 (const OMX_U8 *)mMem->pointer() + header->nOffset, 109 header->nFilledLen); 110 } 111 112private: 113 OMX *mOwner; 114 sp<IMemory> mMem; 115 size_t mSize; 116 bool mIsBackup; 117 118 BufferMeta(const BufferMeta &); 119 BufferMeta &operator=(const BufferMeta &); 120}; 121 122// static 123OMX_CALLBACKTYPE OMX::kCallbacks = { 124 &OnEvent, &OnEmptyBufferDone, &OnFillBufferDone 125}; 126 127// static 128OMX_ERRORTYPE OMX::OnEvent( 129 OMX_IN OMX_HANDLETYPE hComponent, 130 OMX_IN OMX_PTR pAppData, 131 OMX_IN OMX_EVENTTYPE eEvent, 132 OMX_IN OMX_U32 nData1, 133 OMX_IN OMX_U32 nData2, 134 OMX_IN OMX_PTR pEventData) { 135 NodeMeta *meta = static_cast<NodeMeta *>(pAppData); 136 return meta->owner()->OnEvent(meta, eEvent, nData1, nData2, pEventData); 137} 138 139// static 140OMX_ERRORTYPE OMX::OnEmptyBufferDone( 141 OMX_IN OMX_HANDLETYPE hComponent, 142 OMX_IN OMX_PTR pAppData, 143 OMX_IN OMX_BUFFERHEADERTYPE* pBuffer) { 144 NodeMeta *meta = static_cast<NodeMeta *>(pAppData); 145 return meta->owner()->OnEmptyBufferDone(meta, pBuffer); 146} 147 148// static 149OMX_ERRORTYPE OMX::OnFillBufferDone( 150 OMX_IN OMX_HANDLETYPE hComponent, 151 OMX_IN OMX_PTR pAppData, 152 OMX_IN OMX_BUFFERHEADERTYPE* pBuffer) { 153 NodeMeta *meta = static_cast<NodeMeta *>(pAppData); 154 return meta->owner()->OnFillBufferDone(meta, pBuffer); 155} 156 157OMX::OMX() { 158} 159 160status_t OMX::list_nodes(List<String8> *list) { 161 OMX_MasterInit(); // XXX Put this somewhere else. 162 163 list->clear(); 164 165 OMX_U32 index = 0; 166 char componentName[256]; 167 while (OMX_MasterComponentNameEnum(componentName, sizeof(componentName), index) 168 == OMX_ErrorNone) { 169 list->push_back(String8(componentName)); 170 171 ++index; 172 } 173 174 return OK; 175} 176 177status_t OMX::allocate_node(const char *name, node_id *node) { 178 Mutex::Autolock autoLock(mLock); 179 180 *node = 0; 181 182 OMX_MasterInit(); // XXX Put this somewhere else. 183 184 NodeMeta *meta = new NodeMeta(this); 185 186 OMX_HANDLETYPE handle; 187 OMX_ERRORTYPE err = OMX_MasterGetHandle( 188 &handle, const_cast<char *>(name), meta, &kCallbacks); 189 190 if (err != OMX_ErrorNone) { 191 LOGE("FAILED to allocate omx component '%s'", name); 192 193 delete meta; 194 meta = NULL; 195 196 return UNKNOWN_ERROR; 197 } 198 199 meta->setHandle(handle); 200 201 *node = meta; 202 203 return OK; 204} 205 206status_t OMX::free_node(node_id node) { 207 Mutex::Autolock autoLock(mLock); 208 209 NodeMeta *meta = static_cast<NodeMeta *>(node); 210 211 OMX_ERRORTYPE err = OMX_MasterFreeHandle(meta->handle()); 212 213 delete meta; 214 meta = NULL; 215 216 return (err != OMX_ErrorNone) ? UNKNOWN_ERROR : OK; 217} 218 219status_t OMX::send_command( 220 node_id node, OMX_COMMANDTYPE cmd, OMX_S32 param) { 221 Mutex::Autolock autoLock(mLock); 222 223 NodeMeta *meta = static_cast<NodeMeta *>(node); 224 OMX_ERRORTYPE err = OMX_SendCommand(meta->handle(), cmd, param, NULL); 225 226 return (err != OMX_ErrorNone) ? UNKNOWN_ERROR : OK; 227} 228 229status_t OMX::get_parameter( 230 node_id node, OMX_INDEXTYPE index, 231 void *params, size_t size) { 232 Mutex::Autolock autoLock(mLock); 233 234 NodeMeta *meta = static_cast<NodeMeta *>(node); 235 OMX_ERRORTYPE err = OMX_GetParameter(meta->handle(), index, params); 236 237 return (err != OMX_ErrorNone) ? UNKNOWN_ERROR : OK; 238} 239 240status_t OMX::set_parameter( 241 node_id node, OMX_INDEXTYPE index, 242 const void *params, size_t size) { 243 Mutex::Autolock autoLock(mLock); 244 245 NodeMeta *meta = static_cast<NodeMeta *>(node); 246 OMX_ERRORTYPE err = 247 OMX_SetParameter(meta->handle(), index, const_cast<void *>(params)); 248 249 return (err != OMX_ErrorNone) ? UNKNOWN_ERROR : OK; 250} 251 252status_t OMX::use_buffer( 253 node_id node, OMX_U32 port_index, const sp<IMemory> ¶ms, 254 buffer_id *buffer) { 255 Mutex::Autolock autoLock(mLock); 256 257 BufferMeta *buffer_meta = new BufferMeta(this, params); 258 259 OMX_BUFFERHEADERTYPE *header; 260 261 NodeMeta *node_meta = static_cast<NodeMeta *>(node); 262 OMX_ERRORTYPE err = 263 OMX_UseBuffer(node_meta->handle(), &header, port_index, buffer_meta, 264 params->size(), static_cast<OMX_U8 *>(params->pointer())); 265 266 if (err != OMX_ErrorNone) { 267 LOGE("OMX_UseBuffer failed with error %d (0x%08x)", err, err); 268 269 delete buffer_meta; 270 buffer_meta = NULL; 271 272 *buffer = 0; 273 return UNKNOWN_ERROR; 274 } 275 276 *buffer = header; 277 278 return OK; 279} 280 281status_t OMX::allocate_buffer( 282 node_id node, OMX_U32 port_index, size_t size, 283 buffer_id *buffer) { 284 Mutex::Autolock autoLock(mLock); 285 286 BufferMeta *buffer_meta = new BufferMeta(this, size); 287 288 OMX_BUFFERHEADERTYPE *header; 289 290 NodeMeta *node_meta = static_cast<NodeMeta *>(node); 291 OMX_ERRORTYPE err = 292 OMX_AllocateBuffer(node_meta->handle(), &header, port_index, 293 buffer_meta, size); 294 295 if (err != OMX_ErrorNone) { 296 delete buffer_meta; 297 buffer_meta = NULL; 298 299 *buffer = 0; 300 return UNKNOWN_ERROR; 301 } 302 303 *buffer = header; 304 305 return OK; 306} 307 308status_t OMX::allocate_buffer_with_backup( 309 node_id node, OMX_U32 port_index, const sp<IMemory> ¶ms, 310 buffer_id *buffer) { 311 Mutex::Autolock autoLock(mLock); 312 313 BufferMeta *buffer_meta = new BufferMeta(this, params, true); 314 315 OMX_BUFFERHEADERTYPE *header; 316 317 NodeMeta *node_meta = static_cast<NodeMeta *>(node); 318 OMX_ERRORTYPE err = 319 OMX_AllocateBuffer( 320 node_meta->handle(), &header, port_index, buffer_meta, 321 params->size()); 322 323 if (err != OMX_ErrorNone) { 324 delete buffer_meta; 325 buffer_meta = NULL; 326 327 *buffer = 0; 328 return UNKNOWN_ERROR; 329 } 330 331 *buffer = header; 332 333 return OK; 334} 335 336status_t OMX::free_buffer(node_id node, OMX_U32 port_index, buffer_id buffer) { 337 OMX_BUFFERHEADERTYPE *header = (OMX_BUFFERHEADERTYPE *)buffer; 338 BufferMeta *buffer_meta = static_cast<BufferMeta *>(header->pAppPrivate); 339 340 NodeMeta *node_meta = static_cast<NodeMeta *>(node); 341 OMX_ERRORTYPE err = 342 OMX_FreeBuffer(node_meta->handle(), port_index, header); 343 344 delete buffer_meta; 345 buffer_meta = NULL; 346 347 return (err != OMX_ErrorNone) ? UNKNOWN_ERROR : OK; 348} 349 350OMX_ERRORTYPE OMX::OnEvent( 351 NodeMeta *meta, 352 OMX_IN OMX_EVENTTYPE eEvent, 353 OMX_IN OMX_U32 nData1, 354 OMX_IN OMX_U32 nData2, 355 OMX_IN OMX_PTR pEventData) { 356 LOGV("OnEvent(%d, %ld, %ld)", eEvent, nData1, nData2); 357 358 omx_message msg; 359 msg.type = omx_message::EVENT; 360 msg.u.event_data.node = meta; 361 msg.u.event_data.event = eEvent; 362 msg.u.event_data.data1 = nData1; 363 msg.u.event_data.data2 = nData2; 364 365 sp<IOMXObserver> observer = meta->observer(); 366 if (observer.get() != NULL) { 367 observer->on_message(msg); 368 } 369 370 return OMX_ErrorNone; 371} 372 373OMX_ERRORTYPE OMX::OnEmptyBufferDone( 374 NodeMeta *meta, OMX_IN OMX_BUFFERHEADERTYPE *pBuffer) { 375 LOGV("OnEmptyBufferDone buffer=%p", pBuffer); 376 377 omx_message msg; 378 msg.type = omx_message::EMPTY_BUFFER_DONE; 379 msg.u.buffer_data.node = meta; 380 msg.u.buffer_data.buffer = pBuffer; 381 382 sp<IOMXObserver> observer = meta->observer(); 383 if (observer.get() != NULL) { 384 observer->on_message(msg); 385 } 386 387 return OMX_ErrorNone; 388} 389 390OMX_ERRORTYPE OMX::OnFillBufferDone( 391 NodeMeta *meta, OMX_IN OMX_BUFFERHEADERTYPE *pBuffer) { 392 LOGV("OnFillBufferDone buffer=%p", pBuffer); 393 BufferMeta *buffer_meta = static_cast<BufferMeta *>(pBuffer->pAppPrivate); 394 buffer_meta->CopyFromOMX(pBuffer); 395 396 omx_message msg; 397 msg.type = omx_message::FILL_BUFFER_DONE; 398 msg.u.extended_buffer_data.node = meta; 399 msg.u.extended_buffer_data.buffer = pBuffer; 400 msg.u.extended_buffer_data.range_offset = pBuffer->nOffset; 401 msg.u.extended_buffer_data.range_length = pBuffer->nFilledLen; 402 msg.u.extended_buffer_data.flags = pBuffer->nFlags; 403 msg.u.extended_buffer_data.timestamp = pBuffer->nTimeStamp; 404 msg.u.extended_buffer_data.platform_private = pBuffer->pPlatformPrivate; 405 406 sp<IOMXObserver> observer = meta->observer(); 407 if (observer.get() != NULL) { 408 observer->on_message(msg); 409 } 410 411 return OMX_ErrorNone; 412} 413 414status_t OMX::observe_node( 415 node_id node, const sp<IOMXObserver> &observer) { 416 NodeMeta *node_meta = static_cast<NodeMeta *>(node); 417 418 node_meta->setObserver(observer); 419 420 return OK; 421} 422 423void OMX::fill_buffer(node_id node, buffer_id buffer) { 424 OMX_BUFFERHEADERTYPE *header = (OMX_BUFFERHEADERTYPE *)buffer; 425 header->nFilledLen = 0; 426 header->nOffset = 0; 427 header->nFlags = 0; 428 429 NodeMeta *node_meta = static_cast<NodeMeta *>(node); 430 431 OMX_ERRORTYPE err = 432 OMX_FillThisBuffer(node_meta->handle(), header); 433 assert(err == OMX_ErrorNone); 434} 435 436void OMX::empty_buffer( 437 node_id node, 438 buffer_id buffer, 439 OMX_U32 range_offset, OMX_U32 range_length, 440 OMX_U32 flags, OMX_TICKS timestamp) { 441 OMX_BUFFERHEADERTYPE *header = (OMX_BUFFERHEADERTYPE *)buffer; 442 header->nFilledLen = range_length; 443 header->nOffset = range_offset; 444 header->nFlags = flags; 445 header->nTimeStamp = timestamp; 446 447 BufferMeta *buffer_meta = 448 static_cast<BufferMeta *>(header->pAppPrivate); 449 buffer_meta->CopyToOMX(header); 450 451 NodeMeta *node_meta = static_cast<NodeMeta *>(node); 452 453 OMX_ERRORTYPE err = 454 OMX_EmptyThisBuffer(node_meta->handle(), header); 455 assert(err == OMX_ErrorNone); 456} 457 458//////////////////////////////////////////////////////////////////////////////// 459 460sp<IOMXRenderer> OMX::createRenderer( 461 const sp<ISurface> &surface, 462 const char *componentName, 463 OMX_COLOR_FORMATTYPE colorFormat, 464 size_t encodedWidth, size_t encodedHeight, 465 size_t displayWidth, size_t displayHeight) { 466 VideoRenderer *impl = NULL; 467 468 static const int OMX_QCOM_COLOR_FormatYVU420SemiPlanar = 0x7FA30C00; 469 470 if (colorFormat == OMX_QCOM_COLOR_FormatYVU420SemiPlanar 471 && !strncmp(componentName, "OMX.qcom.video.decoder.", 23)) { 472 LOGW("Using QComHardwareRenderer."); 473 impl = 474 new QComHardwareRenderer( 475 surface, 476 displayWidth, displayHeight, 477 encodedWidth, encodedHeight); 478 } else if (colorFormat == OMX_COLOR_FormatCbYCrY 479 && !strcmp(componentName, "OMX.TI.Video.Decoder")) { 480 LOGW("Using TIHardwareRenderer."); 481 impl = 482 new TIHardwareRenderer( 483 surface, 484 displayWidth, displayHeight, 485 encodedWidth, encodedHeight); 486 } else { 487 LOGW("Using software renderer."); 488 impl = new SoftwareRenderer( 489 surface, 490 displayWidth, displayHeight, 491 encodedWidth, encodedHeight); 492 } 493 494 return new OMXRenderer(impl); 495} 496 497OMXRenderer::OMXRenderer(VideoRenderer *impl) 498 : mImpl(impl) { 499} 500 501OMXRenderer::~OMXRenderer() { 502 delete mImpl; 503 mImpl = NULL; 504} 505 506void OMXRenderer::render(IOMX::buffer_id buffer) { 507 OMX_BUFFERHEADERTYPE *header = (OMX_BUFFERHEADERTYPE *)buffer; 508 509 mImpl->render( 510 header->pBuffer + header->nOffset, 511 header->nFilledLen, 512 header->pPlatformPrivate); 513} 514 515} // namespace android 516 517