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