IOMX.cpp revision 134ee6a324c35f39e3576172e4eae4c6de6eb9dc
1//#define LOG_NDEBUG 0 2#define LOG_TAG "IOMX" 3#include <utils/Log.h> 4 5#include <binder/IMemory.h> 6#include <binder/Parcel.h> 7#include <media/IOMX.h> 8#include <ui/ISurface.h> 9#include <ui/Surface.h> 10 11namespace android { 12 13enum { 14 CONNECT = IBinder::FIRST_CALL_TRANSACTION, 15 LIST_NODES, 16 ALLOCATE_NODE, 17 FREE_NODE, 18 SEND_COMMAND, 19 GET_PARAMETER, 20 SET_PARAMETER, 21 GET_CONFIG, 22 SET_CONFIG, 23 USE_BUFFER, 24 ALLOC_BUFFER, 25 ALLOC_BUFFER_WITH_BACKUP, 26 FREE_BUFFER, 27 FILL_BUFFER, 28 EMPTY_BUFFER, 29 GET_EXTENSION_INDEX, 30 CREATE_RENDERER, 31 OBSERVER_ON_MSG, 32 RENDERER_RENDER, 33}; 34 35sp<IOMXRenderer> IOMX::createRenderer( 36 const sp<Surface> &surface, 37 const char *componentName, 38 OMX_COLOR_FORMATTYPE colorFormat, 39 size_t encodedWidth, size_t encodedHeight, 40 size_t displayWidth, size_t displayHeight) { 41 return createRenderer( 42 surface->getISurface(), 43 componentName, colorFormat, encodedWidth, encodedHeight, 44 displayWidth, displayHeight); 45} 46 47sp<IOMXRenderer> IOMX::createRendererFromJavaSurface( 48 JNIEnv *env, jobject javaSurface, 49 const char *componentName, 50 OMX_COLOR_FORMATTYPE colorFormat, 51 size_t encodedWidth, size_t encodedHeight, 52 size_t displayWidth, size_t displayHeight) { 53 jclass surfaceClass = env->FindClass("android/view/Surface"); 54 if (surfaceClass == NULL) { 55 LOGE("Can't find android/view/Surface"); 56 return NULL; 57 } 58 59 jfieldID surfaceID = env->GetFieldID(surfaceClass, "mSurface", "I"); 60 if (surfaceID == NULL) { 61 LOGE("Can't find Surface.mSurface"); 62 return NULL; 63 } 64 65 sp<Surface> surface = (Surface *)env->GetIntField(javaSurface, surfaceID); 66 67 return createRenderer( 68 surface, componentName, colorFormat, encodedWidth, 69 encodedHeight, displayWidth, displayHeight); 70} 71 72class BpOMX : public BpInterface<IOMX> { 73public: 74 BpOMX(const sp<IBinder> &impl) 75 : BpInterface<IOMX>(impl) { 76 } 77 78 virtual status_t listNodes(List<ComponentInfo> *list) { 79 list->clear(); 80 81 Parcel data, reply; 82 data.writeInterfaceToken(IOMX::getInterfaceDescriptor()); 83 remote()->transact(LIST_NODES, data, &reply); 84 85 int32_t n = reply.readInt32(); 86 for (int32_t i = 0; i < n; ++i) { 87 list->push_back(ComponentInfo()); 88 ComponentInfo &info = *--list->end(); 89 90 info.mName = reply.readString8(); 91 int32_t numRoles = reply.readInt32(); 92 for (int32_t j = 0; j < numRoles; ++j) { 93 info.mRoles.push_back(reply.readString8()); 94 } 95 } 96 97 return OK; 98 } 99 100 virtual status_t allocateNode( 101 const char *name, const sp<IOMXObserver> &observer, node_id *node) { 102 Parcel data, reply; 103 data.writeInterfaceToken(IOMX::getInterfaceDescriptor()); 104 data.writeCString(name); 105 data.writeStrongBinder(observer->asBinder()); 106 remote()->transact(ALLOCATE_NODE, data, &reply); 107 108 status_t err = reply.readInt32(); 109 if (err == OK) { 110 *node = (void*)reply.readIntPtr(); 111 } else { 112 *node = 0; 113 } 114 115 return err; 116 } 117 118 virtual status_t freeNode(node_id node) { 119 Parcel data, reply; 120 data.writeInterfaceToken(IOMX::getInterfaceDescriptor()); 121 data.writeIntPtr((intptr_t)node); 122 remote()->transact(FREE_NODE, data, &reply); 123 124 return reply.readInt32(); 125 } 126 127 virtual status_t sendCommand( 128 node_id node, OMX_COMMANDTYPE cmd, OMX_S32 param) { 129 Parcel data, reply; 130 data.writeInterfaceToken(IOMX::getInterfaceDescriptor()); 131 data.writeIntPtr((intptr_t)node); 132 data.writeInt32(cmd); 133 data.writeInt32(param); 134 remote()->transact(SEND_COMMAND, data, &reply); 135 136 return reply.readInt32(); 137 } 138 139 virtual status_t getParameter( 140 node_id node, OMX_INDEXTYPE index, 141 void *params, size_t size) { 142 Parcel data, reply; 143 data.writeInterfaceToken(IOMX::getInterfaceDescriptor()); 144 data.writeIntPtr((intptr_t)node); 145 data.writeInt32(index); 146 data.writeInt32(size); 147 data.write(params, size); 148 remote()->transact(GET_PARAMETER, data, &reply); 149 150 status_t err = reply.readInt32(); 151 if (err != OK) { 152 return err; 153 } 154 155 reply.read(params, size); 156 157 return OK; 158 } 159 160 virtual status_t setParameter( 161 node_id node, OMX_INDEXTYPE index, 162 const void *params, size_t size) { 163 Parcel data, reply; 164 data.writeInterfaceToken(IOMX::getInterfaceDescriptor()); 165 data.writeIntPtr((intptr_t)node); 166 data.writeInt32(index); 167 data.writeInt32(size); 168 data.write(params, size); 169 remote()->transact(SET_PARAMETER, data, &reply); 170 171 return reply.readInt32(); 172 } 173 174 virtual status_t getConfig( 175 node_id node, OMX_INDEXTYPE index, 176 void *params, size_t size) { 177 Parcel data, reply; 178 data.writeInterfaceToken(IOMX::getInterfaceDescriptor()); 179 data.writeIntPtr((intptr_t)node); 180 data.writeInt32(index); 181 data.writeInt32(size); 182 data.write(params, size); 183 remote()->transact(GET_CONFIG, data, &reply); 184 185 status_t err = reply.readInt32(); 186 if (err != OK) { 187 return err; 188 } 189 190 reply.read(params, size); 191 192 return OK; 193 } 194 195 virtual status_t setConfig( 196 node_id node, OMX_INDEXTYPE index, 197 const void *params, size_t size) { 198 Parcel data, reply; 199 data.writeInterfaceToken(IOMX::getInterfaceDescriptor()); 200 data.writeIntPtr((intptr_t)node); 201 data.writeInt32(index); 202 data.writeInt32(size); 203 data.write(params, size); 204 remote()->transact(SET_CONFIG, data, &reply); 205 206 return reply.readInt32(); 207 } 208 209 virtual status_t useBuffer( 210 node_id node, OMX_U32 port_index, const sp<IMemory> ¶ms, 211 buffer_id *buffer) { 212 Parcel data, reply; 213 data.writeInterfaceToken(IOMX::getInterfaceDescriptor()); 214 data.writeIntPtr((intptr_t)node); 215 data.writeInt32(port_index); 216 data.writeStrongBinder(params->asBinder()); 217 remote()->transact(USE_BUFFER, data, &reply); 218 219 status_t err = reply.readInt32(); 220 if (err != OK) { 221 *buffer = 0; 222 223 return err; 224 } 225 226 *buffer = (void*)reply.readIntPtr(); 227 228 return err; 229 } 230 231 virtual status_t allocateBuffer( 232 node_id node, OMX_U32 port_index, size_t size, 233 buffer_id *buffer) { 234 Parcel data, reply; 235 data.writeInterfaceToken(IOMX::getInterfaceDescriptor()); 236 data.writeIntPtr((intptr_t)node); 237 data.writeInt32(port_index); 238 data.writeInt32(size); 239 remote()->transact(ALLOC_BUFFER, data, &reply); 240 241 status_t err = reply.readInt32(); 242 if (err != OK) { 243 *buffer = 0; 244 245 return err; 246 } 247 248 *buffer = (void*)reply.readIntPtr(); 249 250 return err; 251 } 252 253 virtual status_t allocateBufferWithBackup( 254 node_id node, OMX_U32 port_index, const sp<IMemory> ¶ms, 255 buffer_id *buffer) { 256 Parcel data, reply; 257 data.writeInterfaceToken(IOMX::getInterfaceDescriptor()); 258 data.writeIntPtr((intptr_t)node); 259 data.writeInt32(port_index); 260 data.writeStrongBinder(params->asBinder()); 261 remote()->transact(ALLOC_BUFFER_WITH_BACKUP, data, &reply); 262 263 status_t err = reply.readInt32(); 264 if (err != OK) { 265 *buffer = 0; 266 267 return err; 268 } 269 270 *buffer = (void*)reply.readIntPtr(); 271 272 return err; 273 } 274 275 virtual status_t freeBuffer( 276 node_id node, OMX_U32 port_index, buffer_id buffer) { 277 Parcel data, reply; 278 data.writeInterfaceToken(IOMX::getInterfaceDescriptor()); 279 data.writeIntPtr((intptr_t)node); 280 data.writeInt32(port_index); 281 data.writeIntPtr((intptr_t)buffer); 282 remote()->transact(FREE_BUFFER, data, &reply); 283 284 return reply.readInt32(); 285 } 286 287 virtual status_t fillBuffer(node_id node, buffer_id buffer) { 288 Parcel data, reply; 289 data.writeInterfaceToken(IOMX::getInterfaceDescriptor()); 290 data.writeIntPtr((intptr_t)node); 291 data.writeIntPtr((intptr_t)buffer); 292 remote()->transact(FILL_BUFFER, data, &reply); 293 294 return reply.readInt32(); 295 } 296 297 virtual status_t emptyBuffer( 298 node_id node, 299 buffer_id buffer, 300 OMX_U32 range_offset, OMX_U32 range_length, 301 OMX_U32 flags, OMX_TICKS timestamp) { 302 Parcel data, reply; 303 data.writeInterfaceToken(IOMX::getInterfaceDescriptor()); 304 data.writeIntPtr((intptr_t)node); 305 data.writeIntPtr((intptr_t)buffer); 306 data.writeInt32(range_offset); 307 data.writeInt32(range_length); 308 data.writeInt32(flags); 309 data.writeInt64(timestamp); 310 remote()->transact(EMPTY_BUFFER, data, &reply); 311 312 return reply.readInt32(); 313 } 314 315 virtual status_t getExtensionIndex( 316 node_id node, 317 const char *parameter_name, 318 OMX_INDEXTYPE *index) { 319 Parcel data, reply; 320 data.writeInterfaceToken(IOMX::getInterfaceDescriptor()); 321 data.writeIntPtr((intptr_t)node); 322 data.writeCString(parameter_name); 323 324 remote()->transact(GET_EXTENSION_INDEX, data, &reply); 325 326 status_t err = reply.readInt32(); 327 if (err == OK) { 328 *index = static_cast<OMX_INDEXTYPE>(reply.readInt32()); 329 } else { 330 *index = OMX_IndexComponentStartUnused; 331 } 332 333 return err; 334 } 335 336 virtual sp<IOMXRenderer> createRenderer( 337 const sp<ISurface> &surface, 338 const char *componentName, 339 OMX_COLOR_FORMATTYPE colorFormat, 340 size_t encodedWidth, size_t encodedHeight, 341 size_t displayWidth, size_t displayHeight) { 342 Parcel data, reply; 343 data.writeInterfaceToken(IOMX::getInterfaceDescriptor()); 344 345 data.writeStrongBinder(surface->asBinder()); 346 data.writeCString(componentName); 347 data.writeInt32(colorFormat); 348 data.writeInt32(encodedWidth); 349 data.writeInt32(encodedHeight); 350 data.writeInt32(displayWidth); 351 data.writeInt32(displayHeight); 352 353 remote()->transact(CREATE_RENDERER, data, &reply); 354 355 return interface_cast<IOMXRenderer>(reply.readStrongBinder()); 356 } 357}; 358 359IMPLEMENT_META_INTERFACE(OMX, "android.hardware.IOMX"); 360 361//////////////////////////////////////////////////////////////////////////////// 362 363#define CHECK_INTERFACE(interface, data, reply) \ 364 do { if (!data.enforceInterface(interface::getInterfaceDescriptor())) { \ 365 LOGW("Call incorrectly routed to " #interface); \ 366 return PERMISSION_DENIED; \ 367 } } while (0) 368 369status_t BnOMX::onTransact( 370 uint32_t code, const Parcel &data, Parcel *reply, uint32_t flags) { 371 switch (code) { 372 case LIST_NODES: 373 { 374 CHECK_INTERFACE(IOMX, data, reply); 375 376 List<ComponentInfo> list; 377 listNodes(&list); 378 379 reply->writeInt32(list.size()); 380 for (List<ComponentInfo>::iterator it = list.begin(); 381 it != list.end(); ++it) { 382 ComponentInfo &cur = *it; 383 384 reply->writeString8(cur.mName); 385 reply->writeInt32(cur.mRoles.size()); 386 for (List<String8>::iterator role_it = cur.mRoles.begin(); 387 role_it != cur.mRoles.end(); ++role_it) { 388 reply->writeString8(*role_it); 389 } 390 } 391 392 return NO_ERROR; 393 } 394 395 case ALLOCATE_NODE: 396 { 397 CHECK_INTERFACE(IOMX, data, reply); 398 399 const char *name = data.readCString(); 400 401 sp<IOMXObserver> observer = 402 interface_cast<IOMXObserver>(data.readStrongBinder()); 403 404 node_id node; 405 406 status_t err = allocateNode(name, observer, &node); 407 reply->writeInt32(err); 408 if (err == OK) { 409 reply->writeIntPtr((intptr_t)node); 410 } 411 412 return NO_ERROR; 413 } 414 415 case FREE_NODE: 416 { 417 CHECK_INTERFACE(IOMX, data, reply); 418 419 node_id node = (void*)data.readIntPtr(); 420 421 reply->writeInt32(freeNode(node)); 422 423 return NO_ERROR; 424 } 425 426 case SEND_COMMAND: 427 { 428 CHECK_INTERFACE(IOMX, data, reply); 429 430 node_id node = (void*)data.readIntPtr(); 431 432 OMX_COMMANDTYPE cmd = 433 static_cast<OMX_COMMANDTYPE>(data.readInt32()); 434 435 OMX_S32 param = data.readInt32(); 436 reply->writeInt32(sendCommand(node, cmd, param)); 437 438 return NO_ERROR; 439 } 440 441 case GET_PARAMETER: 442 { 443 CHECK_INTERFACE(IOMX, data, reply); 444 445 node_id node = (void*)data.readIntPtr(); 446 OMX_INDEXTYPE index = static_cast<OMX_INDEXTYPE>(data.readInt32()); 447 448 size_t size = data.readInt32(); 449 450 // XXX I am not happy with this but Parcel::readInplace didn't work. 451 void *params = malloc(size); 452 data.read(params, size); 453 454 status_t err = getParameter(node, index, params, size); 455 456 reply->writeInt32(err); 457 458 if (err == OK) { 459 reply->write(params, size); 460 } 461 462 free(params); 463 params = NULL; 464 465 return NO_ERROR; 466 } 467 468 case SET_PARAMETER: 469 { 470 CHECK_INTERFACE(IOMX, data, reply); 471 472 node_id node = (void*)data.readIntPtr(); 473 OMX_INDEXTYPE index = static_cast<OMX_INDEXTYPE>(data.readInt32()); 474 475 size_t size = data.readInt32(); 476 void *params = const_cast<void *>(data.readInplace(size)); 477 478 reply->writeInt32(setParameter(node, index, params, size)); 479 480 return NO_ERROR; 481 } 482 483 case GET_CONFIG: 484 { 485 CHECK_INTERFACE(IOMX, data, reply); 486 487 node_id node = (void*)data.readIntPtr(); 488 OMX_INDEXTYPE index = static_cast<OMX_INDEXTYPE>(data.readInt32()); 489 490 size_t size = data.readInt32(); 491 492 // XXX I am not happy with this but Parcel::readInplace didn't work. 493 void *params = malloc(size); 494 data.read(params, size); 495 496 status_t err = getConfig(node, index, params, size); 497 498 reply->writeInt32(err); 499 500 if (err == OK) { 501 reply->write(params, size); 502 } 503 504 free(params); 505 params = NULL; 506 507 return NO_ERROR; 508 } 509 510 case SET_CONFIG: 511 { 512 CHECK_INTERFACE(IOMX, data, reply); 513 514 node_id node = (void*)data.readIntPtr(); 515 OMX_INDEXTYPE index = static_cast<OMX_INDEXTYPE>(data.readInt32()); 516 517 size_t size = data.readInt32(); 518 void *params = const_cast<void *>(data.readInplace(size)); 519 520 reply->writeInt32(setConfig(node, index, params, size)); 521 522 return NO_ERROR; 523 } 524 525 case USE_BUFFER: 526 { 527 CHECK_INTERFACE(IOMX, data, reply); 528 529 node_id node = (void*)data.readIntPtr(); 530 OMX_U32 port_index = data.readInt32(); 531 sp<IMemory> params = 532 interface_cast<IMemory>(data.readStrongBinder()); 533 534 buffer_id buffer; 535 status_t err = useBuffer(node, port_index, params, &buffer); 536 reply->writeInt32(err); 537 538 if (err == OK) { 539 reply->writeIntPtr((intptr_t)buffer); 540 } 541 542 return NO_ERROR; 543 } 544 545 case ALLOC_BUFFER: 546 { 547 CHECK_INTERFACE(IOMX, data, reply); 548 549 node_id node = (void*)data.readIntPtr(); 550 OMX_U32 port_index = data.readInt32(); 551 size_t size = data.readInt32(); 552 553 buffer_id buffer; 554 status_t err = allocateBuffer(node, port_index, size, &buffer); 555 reply->writeInt32(err); 556 557 if (err == OK) { 558 reply->writeIntPtr((intptr_t)buffer); 559 } 560 561 return NO_ERROR; 562 } 563 564 case ALLOC_BUFFER_WITH_BACKUP: 565 { 566 CHECK_INTERFACE(IOMX, data, reply); 567 568 node_id node = (void*)data.readIntPtr(); 569 OMX_U32 port_index = data.readInt32(); 570 sp<IMemory> params = 571 interface_cast<IMemory>(data.readStrongBinder()); 572 573 buffer_id buffer; 574 status_t err = allocateBufferWithBackup( 575 node, port_index, params, &buffer); 576 577 reply->writeInt32(err); 578 579 if (err == OK) { 580 reply->writeIntPtr((intptr_t)buffer); 581 } 582 583 return NO_ERROR; 584 } 585 586 case FREE_BUFFER: 587 { 588 CHECK_INTERFACE(IOMX, data, reply); 589 590 node_id node = (void*)data.readIntPtr(); 591 OMX_U32 port_index = data.readInt32(); 592 buffer_id buffer = (void*)data.readIntPtr(); 593 reply->writeInt32(freeBuffer(node, port_index, buffer)); 594 595 return NO_ERROR; 596 } 597 598 case FILL_BUFFER: 599 { 600 CHECK_INTERFACE(IOMX, data, reply); 601 602 node_id node = (void*)data.readIntPtr(); 603 buffer_id buffer = (void*)data.readIntPtr(); 604 reply->writeInt32(fillBuffer(node, buffer)); 605 606 return NO_ERROR; 607 } 608 609 case EMPTY_BUFFER: 610 { 611 CHECK_INTERFACE(IOMX, data, reply); 612 613 node_id node = (void*)data.readIntPtr(); 614 buffer_id buffer = (void*)data.readIntPtr(); 615 OMX_U32 range_offset = data.readInt32(); 616 OMX_U32 range_length = data.readInt32(); 617 OMX_U32 flags = data.readInt32(); 618 OMX_TICKS timestamp = data.readInt64(); 619 620 reply->writeInt32( 621 emptyBuffer( 622 node, buffer, range_offset, range_length, 623 flags, timestamp)); 624 625 return NO_ERROR; 626 } 627 628 case GET_EXTENSION_INDEX: 629 { 630 CHECK_INTERFACE(IOMX, data, reply); 631 632 node_id node = (void*)data.readIntPtr(); 633 const char *parameter_name = data.readCString(); 634 635 OMX_INDEXTYPE index; 636 status_t err = getExtensionIndex(node, parameter_name, &index); 637 638 reply->writeInt32(err); 639 640 if (err == OK) { 641 reply->writeInt32(index); 642 } 643 644 return OK; 645 } 646 647 case CREATE_RENDERER: 648 { 649 CHECK_INTERFACE(IOMX, data, reply); 650 651 sp<ISurface> isurface = 652 interface_cast<ISurface>(data.readStrongBinder()); 653 654 const char *componentName = data.readCString(); 655 656 OMX_COLOR_FORMATTYPE colorFormat = 657 static_cast<OMX_COLOR_FORMATTYPE>(data.readInt32()); 658 659 size_t encodedWidth = (size_t)data.readInt32(); 660 size_t encodedHeight = (size_t)data.readInt32(); 661 size_t displayWidth = (size_t)data.readInt32(); 662 size_t displayHeight = (size_t)data.readInt32(); 663 664 sp<IOMXRenderer> renderer = 665 createRenderer(isurface, componentName, colorFormat, 666 encodedWidth, encodedHeight, 667 displayWidth, displayHeight); 668 669 reply->writeStrongBinder(renderer->asBinder()); 670 671 return OK; 672 } 673 674 default: 675 return BBinder::onTransact(code, data, reply, flags); 676 } 677} 678 679//////////////////////////////////////////////////////////////////////////////// 680 681class BpOMXObserver : public BpInterface<IOMXObserver> { 682public: 683 BpOMXObserver(const sp<IBinder> &impl) 684 : BpInterface<IOMXObserver>(impl) { 685 } 686 687 virtual void onMessage(const omx_message &msg) { 688 Parcel data, reply; 689 data.writeInterfaceToken(IOMXObserver::getInterfaceDescriptor()); 690 data.write(&msg, sizeof(msg)); 691 692 remote()->transact(OBSERVER_ON_MSG, data, &reply, IBinder::FLAG_ONEWAY); 693 } 694}; 695 696IMPLEMENT_META_INTERFACE(OMXObserver, "android.hardware.IOMXObserver"); 697 698status_t BnOMXObserver::onTransact( 699 uint32_t code, const Parcel &data, Parcel *reply, uint32_t flags) { 700 switch (code) { 701 case OBSERVER_ON_MSG: 702 { 703 CHECK_INTERFACE(IOMXObserver, data, reply); 704 705 omx_message msg; 706 data.read(&msg, sizeof(msg)); 707 708 // XXX Could use readInplace maybe? 709 onMessage(msg); 710 711 return NO_ERROR; 712 } 713 714 default: 715 return BBinder::onTransact(code, data, reply, flags); 716 } 717} 718 719//////////////////////////////////////////////////////////////////////////////// 720 721class BpOMXRenderer : public BpInterface<IOMXRenderer> { 722public: 723 BpOMXRenderer(const sp<IBinder> &impl) 724 : BpInterface<IOMXRenderer>(impl) { 725 } 726 727 virtual void render(IOMX::buffer_id buffer) { 728 Parcel data, reply; 729 data.writeInterfaceToken(IOMXRenderer::getInterfaceDescriptor()); 730 data.writeIntPtr((intptr_t)buffer); 731 732 // NOTE: Do NOT make this a ONE_WAY call, it must be synchronous 733 // so that the caller knows when to recycle the buffer. 734 remote()->transact(RENDERER_RENDER, data, &reply); 735 } 736}; 737 738IMPLEMENT_META_INTERFACE(OMXRenderer, "android.hardware.IOMXRenderer"); 739 740status_t BnOMXRenderer::onTransact( 741 uint32_t code, const Parcel &data, Parcel *reply, uint32_t flags) { 742 switch (code) { 743 case RENDERER_RENDER: 744 { 745 CHECK_INTERFACE(IOMXRenderer, data, reply); 746 747 IOMX::buffer_id buffer = (void*)data.readIntPtr(); 748 749 render(buffer); 750 751 return NO_ERROR; 752 } 753 754 default: 755 return BBinder::onTransact(code, data, reply, flags); 756 } 757} 758 759} // namespace android 760