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