IOMX.cpp revision 318ad9c1d9d6515026dfc2c021359d27decaa7a1
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<String8> *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 String8 s = reply.readString8(); 88 89 list->push_back(s); 90 } 91 92 return OK; 93 } 94 95 virtual status_t allocateNode( 96 const char *name, const sp<IOMXObserver> &observer, node_id *node) { 97 Parcel data, reply; 98 data.writeInterfaceToken(IOMX::getInterfaceDescriptor()); 99 data.writeCString(name); 100 data.writeStrongBinder(observer->asBinder()); 101 remote()->transact(ALLOCATE_NODE, data, &reply); 102 103 status_t err = reply.readInt32(); 104 if (err == OK) { 105 *node = (void*)reply.readIntPtr(); 106 } else { 107 *node = 0; 108 } 109 110 return err; 111 } 112 113 virtual status_t freeNode(node_id node) { 114 Parcel data, reply; 115 data.writeInterfaceToken(IOMX::getInterfaceDescriptor()); 116 data.writeIntPtr((intptr_t)node); 117 remote()->transact(FREE_NODE, data, &reply); 118 119 return reply.readInt32(); 120 } 121 122 virtual status_t sendCommand( 123 node_id node, OMX_COMMANDTYPE cmd, OMX_S32 param) { 124 Parcel data, reply; 125 data.writeInterfaceToken(IOMX::getInterfaceDescriptor()); 126 data.writeIntPtr((intptr_t)node); 127 data.writeInt32(cmd); 128 data.writeInt32(param); 129 remote()->transact(SEND_COMMAND, data, &reply); 130 131 return reply.readInt32(); 132 } 133 134 virtual status_t getParameter( 135 node_id node, OMX_INDEXTYPE index, 136 void *params, size_t size) { 137 Parcel data, reply; 138 data.writeInterfaceToken(IOMX::getInterfaceDescriptor()); 139 data.writeIntPtr((intptr_t)node); 140 data.writeInt32(index); 141 data.writeInt32(size); 142 data.write(params, size); 143 remote()->transact(GET_PARAMETER, data, &reply); 144 145 status_t err = reply.readInt32(); 146 if (err != OK) { 147 return err; 148 } 149 150 reply.read(params, size); 151 152 return OK; 153 } 154 155 virtual status_t setParameter( 156 node_id node, OMX_INDEXTYPE index, 157 const void *params, size_t size) { 158 Parcel data, reply; 159 data.writeInterfaceToken(IOMX::getInterfaceDescriptor()); 160 data.writeIntPtr((intptr_t)node); 161 data.writeInt32(index); 162 data.writeInt32(size); 163 data.write(params, size); 164 remote()->transact(SET_PARAMETER, data, &reply); 165 166 return reply.readInt32(); 167 } 168 169 virtual status_t getConfig( 170 node_id node, OMX_INDEXTYPE index, 171 void *params, size_t size) { 172 Parcel data, reply; 173 data.writeInterfaceToken(IOMX::getInterfaceDescriptor()); 174 data.writeIntPtr((intptr_t)node); 175 data.writeInt32(index); 176 data.writeInt32(size); 177 data.write(params, size); 178 remote()->transact(GET_CONFIG, data, &reply); 179 180 status_t err = reply.readInt32(); 181 if (err != OK) { 182 return err; 183 } 184 185 reply.read(params, size); 186 187 return OK; 188 } 189 190 virtual status_t setConfig( 191 node_id node, OMX_INDEXTYPE index, 192 const void *params, size_t size) { 193 Parcel data, reply; 194 data.writeInterfaceToken(IOMX::getInterfaceDescriptor()); 195 data.writeIntPtr((intptr_t)node); 196 data.writeInt32(index); 197 data.writeInt32(size); 198 data.write(params, size); 199 remote()->transact(SET_CONFIG, data, &reply); 200 201 return reply.readInt32(); 202 } 203 204 virtual status_t useBuffer( 205 node_id node, OMX_U32 port_index, const sp<IMemory> ¶ms, 206 buffer_id *buffer) { 207 Parcel data, reply; 208 data.writeInterfaceToken(IOMX::getInterfaceDescriptor()); 209 data.writeIntPtr((intptr_t)node); 210 data.writeInt32(port_index); 211 data.writeStrongBinder(params->asBinder()); 212 remote()->transact(USE_BUFFER, data, &reply); 213 214 status_t err = reply.readInt32(); 215 if (err != OK) { 216 *buffer = 0; 217 218 return err; 219 } 220 221 *buffer = (void*)reply.readIntPtr(); 222 223 return err; 224 } 225 226 virtual status_t allocateBuffer( 227 node_id node, OMX_U32 port_index, size_t size, 228 buffer_id *buffer) { 229 Parcel data, reply; 230 data.writeInterfaceToken(IOMX::getInterfaceDescriptor()); 231 data.writeIntPtr((intptr_t)node); 232 data.writeInt32(port_index); 233 data.writeInt32(size); 234 remote()->transact(ALLOC_BUFFER, data, &reply); 235 236 status_t err = reply.readInt32(); 237 if (err != OK) { 238 *buffer = 0; 239 240 return err; 241 } 242 243 *buffer = (void*)reply.readIntPtr(); 244 245 return err; 246 } 247 248 virtual status_t allocateBufferWithBackup( 249 node_id node, OMX_U32 port_index, const sp<IMemory> ¶ms, 250 buffer_id *buffer) { 251 Parcel data, reply; 252 data.writeInterfaceToken(IOMX::getInterfaceDescriptor()); 253 data.writeIntPtr((intptr_t)node); 254 data.writeInt32(port_index); 255 data.writeStrongBinder(params->asBinder()); 256 remote()->transact(ALLOC_BUFFER_WITH_BACKUP, data, &reply); 257 258 status_t err = reply.readInt32(); 259 if (err != OK) { 260 *buffer = 0; 261 262 return err; 263 } 264 265 *buffer = (void*)reply.readIntPtr(); 266 267 return err; 268 } 269 270 virtual status_t freeBuffer( 271 node_id node, OMX_U32 port_index, buffer_id buffer) { 272 Parcel data, reply; 273 data.writeInterfaceToken(IOMX::getInterfaceDescriptor()); 274 data.writeIntPtr((intptr_t)node); 275 data.writeInt32(port_index); 276 data.writeIntPtr((intptr_t)buffer); 277 remote()->transact(FREE_BUFFER, data, &reply); 278 279 return reply.readInt32(); 280 } 281 282 virtual status_t fillBuffer(node_id node, buffer_id buffer) { 283 Parcel data, reply; 284 data.writeInterfaceToken(IOMX::getInterfaceDescriptor()); 285 data.writeIntPtr((intptr_t)node); 286 data.writeIntPtr((intptr_t)buffer); 287 remote()->transact(FILL_BUFFER, data, &reply); 288 289 return reply.readInt32(); 290 } 291 292 virtual status_t emptyBuffer( 293 node_id node, 294 buffer_id buffer, 295 OMX_U32 range_offset, OMX_U32 range_length, 296 OMX_U32 flags, OMX_TICKS timestamp) { 297 Parcel data, reply; 298 data.writeInterfaceToken(IOMX::getInterfaceDescriptor()); 299 data.writeIntPtr((intptr_t)node); 300 data.writeIntPtr((intptr_t)buffer); 301 data.writeInt32(range_offset); 302 data.writeInt32(range_length); 303 data.writeInt32(flags); 304 data.writeInt64(timestamp); 305 remote()->transact(EMPTY_BUFFER, data, &reply); 306 307 return reply.readInt32(); 308 } 309 310 virtual status_t getExtensionIndex( 311 node_id node, 312 const char *parameter_name, 313 OMX_INDEXTYPE *index) { 314 Parcel data, reply; 315 data.writeInterfaceToken(IOMX::getInterfaceDescriptor()); 316 data.writeIntPtr((intptr_t)node); 317 data.writeCString(parameter_name); 318 319 remote()->transact(GET_EXTENSION_INDEX, data, &reply); 320 321 status_t err = reply.readInt32(); 322 if (err == OK) { 323 *index = static_cast<OMX_INDEXTYPE>(reply.readInt32()); 324 } else { 325 *index = OMX_IndexComponentStartUnused; 326 } 327 328 return err; 329 } 330 331 virtual sp<IOMXRenderer> createRenderer( 332 const sp<ISurface> &surface, 333 const char *componentName, 334 OMX_COLOR_FORMATTYPE colorFormat, 335 size_t encodedWidth, size_t encodedHeight, 336 size_t displayWidth, size_t displayHeight) { 337 Parcel data, reply; 338 data.writeInterfaceToken(IOMX::getInterfaceDescriptor()); 339 340 data.writeStrongBinder(surface->asBinder()); 341 data.writeCString(componentName); 342 data.writeInt32(colorFormat); 343 data.writeInt32(encodedWidth); 344 data.writeInt32(encodedHeight); 345 data.writeInt32(displayWidth); 346 data.writeInt32(displayHeight); 347 348 remote()->transact(CREATE_RENDERER, data, &reply); 349 350 return interface_cast<IOMXRenderer>(reply.readStrongBinder()); 351 } 352}; 353 354IMPLEMENT_META_INTERFACE(OMX, "android.hardware.IOMX"); 355 356//////////////////////////////////////////////////////////////////////////////// 357 358#define CHECK_INTERFACE(interface, data, reply) \ 359 do { if (!data.enforceInterface(interface::getInterfaceDescriptor())) { \ 360 LOGW("Call incorrectly routed to " #interface); \ 361 return PERMISSION_DENIED; \ 362 } } while (0) 363 364status_t BnOMX::onTransact( 365 uint32_t code, const Parcel &data, Parcel *reply, uint32_t flags) { 366 switch (code) { 367 case LIST_NODES: 368 { 369 CHECK_INTERFACE(IOMX, data, reply); 370 371 List<String8> list; 372 listNodes(&list); 373 374 reply->writeInt32(list.size()); 375 for (List<String8>::iterator it = list.begin(); 376 it != list.end(); ++it) { 377 reply->writeString8(*it); 378 } 379 380 return NO_ERROR; 381 } 382 383 case ALLOCATE_NODE: 384 { 385 CHECK_INTERFACE(IOMX, data, reply); 386 387 const char *name = data.readCString(); 388 389 sp<IOMXObserver> observer = 390 interface_cast<IOMXObserver>(data.readStrongBinder()); 391 392 node_id node; 393 394 status_t err = allocateNode(name, observer, &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(freeNode(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(sendCommand(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 = getParameter(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(setParameter(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 = getConfig(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(setConfig(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 = useBuffer(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 = allocateBuffer(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 = allocateBufferWithBackup( 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(freeBuffer(node, port_index, buffer)); 582 583 return NO_ERROR; 584 } 585 586 case FILL_BUFFER: 587 { 588 CHECK_INTERFACE(IOMX, data, reply); 589 590 node_id node = (void*)data.readIntPtr(); 591 buffer_id buffer = (void*)data.readIntPtr(); 592 reply->writeInt32(fillBuffer(node, buffer)); 593 594 return NO_ERROR; 595 } 596 597 case EMPTY_BUFFER: 598 { 599 CHECK_INTERFACE(IOMX, data, reply); 600 601 node_id node = (void*)data.readIntPtr(); 602 buffer_id buffer = (void*)data.readIntPtr(); 603 OMX_U32 range_offset = data.readInt32(); 604 OMX_U32 range_length = data.readInt32(); 605 OMX_U32 flags = data.readInt32(); 606 OMX_TICKS timestamp = data.readInt64(); 607 608 reply->writeInt32( 609 emptyBuffer( 610 node, buffer, range_offset, range_length, 611 flags, timestamp)); 612 613 return NO_ERROR; 614 } 615 616 case GET_EXTENSION_INDEX: 617 { 618 CHECK_INTERFACE(IOMX, data, reply); 619 620 node_id node = (void*)data.readIntPtr(); 621 const char *parameter_name = data.readCString(); 622 623 OMX_INDEXTYPE index; 624 status_t err = getExtensionIndex(node, parameter_name, &index); 625 626 reply->writeInt32(err); 627 628 if (err == OK) { 629 reply->writeInt32(index); 630 } 631 632 return OK; 633 } 634 635 case CREATE_RENDERER: 636 { 637 CHECK_INTERFACE(IOMX, data, reply); 638 639 sp<ISurface> isurface = 640 interface_cast<ISurface>(data.readStrongBinder()); 641 642 const char *componentName = data.readCString(); 643 644 OMX_COLOR_FORMATTYPE colorFormat = 645 static_cast<OMX_COLOR_FORMATTYPE>(data.readInt32()); 646 647 size_t encodedWidth = (size_t)data.readInt32(); 648 size_t encodedHeight = (size_t)data.readInt32(); 649 size_t displayWidth = (size_t)data.readInt32(); 650 size_t displayHeight = (size_t)data.readInt32(); 651 652 sp<IOMXRenderer> renderer = 653 createRenderer(isurface, componentName, colorFormat, 654 encodedWidth, encodedHeight, 655 displayWidth, displayHeight); 656 657 reply->writeStrongBinder(renderer->asBinder()); 658 659 return OK; 660 } 661 662 default: 663 return BBinder::onTransact(code, data, reply, flags); 664 } 665} 666 667//////////////////////////////////////////////////////////////////////////////// 668 669class BpOMXObserver : public BpInterface<IOMXObserver> { 670public: 671 BpOMXObserver(const sp<IBinder> &impl) 672 : BpInterface<IOMXObserver>(impl) { 673 } 674 675 virtual void onMessage(const omx_message &msg) { 676 Parcel data, reply; 677 data.writeInterfaceToken(IOMXObserver::getInterfaceDescriptor()); 678 data.write(&msg, sizeof(msg)); 679 680 remote()->transact(OBSERVER_ON_MSG, data, &reply, IBinder::FLAG_ONEWAY); 681 } 682}; 683 684IMPLEMENT_META_INTERFACE(OMXObserver, "android.hardware.IOMXObserver"); 685 686status_t BnOMXObserver::onTransact( 687 uint32_t code, const Parcel &data, Parcel *reply, uint32_t flags) { 688 switch (code) { 689 case OBSERVER_ON_MSG: 690 { 691 CHECK_INTERFACE(IOMXObserver, data, reply); 692 693 omx_message msg; 694 data.read(&msg, sizeof(msg)); 695 696 // XXX Could use readInplace maybe? 697 onMessage(msg); 698 699 return NO_ERROR; 700 } 701 702 default: 703 return BBinder::onTransact(code, data, reply, flags); 704 } 705} 706 707//////////////////////////////////////////////////////////////////////////////// 708 709class BpOMXRenderer : public BpInterface<IOMXRenderer> { 710public: 711 BpOMXRenderer(const sp<IBinder> &impl) 712 : BpInterface<IOMXRenderer>(impl) { 713 } 714 715 virtual void render(IOMX::buffer_id buffer) { 716 Parcel data, reply; 717 data.writeInterfaceToken(IOMXRenderer::getInterfaceDescriptor()); 718 data.writeIntPtr((intptr_t)buffer); 719 720 // NOTE: Do NOT make this a ONE_WAY call, it must be synchronous 721 // so that the caller knows when to recycle the buffer. 722 remote()->transact(RENDERER_RENDER, data, &reply); 723 } 724}; 725 726IMPLEMENT_META_INTERFACE(OMXRenderer, "android.hardware.IOMXRenderer"); 727 728status_t BnOMXRenderer::onTransact( 729 uint32_t code, const Parcel &data, Parcel *reply, uint32_t flags) { 730 switch (code) { 731 case RENDERER_RENDER: 732 { 733 CHECK_INTERFACE(IOMXRenderer, data, reply); 734 735 IOMX::buffer_id buffer = (void*)data.readIntPtr(); 736 737 render(buffer); 738 739 return NO_ERROR; 740 } 741 742 default: 743 return BBinder::onTransact(code, data, reply, flags); 744 } 745} 746 747} // namespace android 748