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