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