1/* ------------------------------------------------------------------ 2 * Copyright (C) 2008 PacketVideo 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 13 * express or implied. 14 * See the License for the specific language governing permissions 15 * and limitations under the License. 16 * ------------------------------------------------------------------- 17 */ 18 19//#define LOG_NDEBUG 0 20#define LOG_TAG "VideoMIO" 21#include <utils/Log.h> 22#include <surfaceflinger/ISurface.h> 23 24#include "android_surface_output.h" 25#include <media/PVPlayer.h> 26 27#include "pvlogger.h" 28#include "pv_mime_string_utils.h" 29#include "oscl_snprintf.h" 30 31#include "oscl_dll.h" 32 33// Define entry point for this DLL 34OSCL_DLL_ENTRY_POINT_DEFAULT() 35 36//The factory functions. 37#include "oscl_mem.h" 38 39using namespace android; 40 41OSCL_EXPORT_REF AndroidSurfaceOutput::AndroidSurfaceOutput() : 42 OsclTimerObject(OsclActiveObject::EPriorityNominal, "androidsurfaceoutput") 43{ 44 initData(); 45 46 iColorConverter = NULL; 47 mInitialized = false; 48 mPvPlayer = NULL; 49 mEmulation = false; 50 iEosReceived = false; 51 mNumberOfFramesToHold = 1; 52} 53 54status_t AndroidSurfaceOutput::set(PVPlayer* pvPlayer, const sp<ISurface>& surface, bool emulation) 55{ 56 mPvPlayer = pvPlayer; 57 mEmulation = emulation; 58 setVideoSurface(surface); 59 return NO_ERROR; 60} 61 62status_t AndroidSurfaceOutput::setVideoSurface(const sp<ISurface>& surface) 63{ 64 LOGV("setVideoSurface(%p)", surface.get()); 65 // unregister buffers for the old surface 66 if (mSurface != NULL) { 67 LOGV("unregisterBuffers from old surface"); 68 mSurface->unregisterBuffers(); 69 } 70 mSurface = surface; 71 // register buffers for the new surface 72 if ((mSurface != NULL) && (mBufferHeap.heap != NULL)) { 73 LOGV("registerBuffers from old surface"); 74 mSurface->registerBuffers(mBufferHeap); 75 } 76 return NO_ERROR; 77} 78 79void AndroidSurfaceOutput::initData() 80{ 81 iVideoHeight = iVideoWidth = iVideoDisplayHeight = iVideoDisplayWidth = 0; 82 iVideoFormat=PVMF_MIME_FORMAT_UNKNOWN; 83 resetVideoParameterFlags(); 84 85 iCommandCounter=0; 86 iLogger=NULL; 87 iCommandResponseQueue.reserve(5); 88 iWriteResponseQueue.reserve(5); 89 iObserver=NULL; 90 iLogger=NULL; 91 iPeer=NULL; 92 iState=STATE_IDLE; 93 iIsMIOConfigured = false; 94} 95 96void AndroidSurfaceOutput::ResetData() 97 //reset all data from this session. 98{ 99 Cleanup(); 100 101 //reset all the received media parameters. 102 iVideoFormatString=""; 103 iVideoFormat=PVMF_MIME_FORMAT_UNKNOWN; 104 resetVideoParameterFlags(); 105 iIsMIOConfigured = false; 106} 107 108void AndroidSurfaceOutput::resetVideoParameterFlags() 109{ 110 iVideoParameterFlags = VIDEO_PARAMETERS_INVALID; 111} 112 113bool AndroidSurfaceOutput::checkVideoParameterFlags() 114{ 115 return (iVideoParameterFlags & VIDEO_PARAMETERS_MASK) == VIDEO_PARAMETERS_VALID; 116} 117 118/* 119 * process the write response queue by sending writeComplete to the peer 120 * (nominally the decoder node). 121 * 122 * numFramesToHold is the number of frames to be held in the MIO. During 123 * playback, we hold the last frame which is used by SurfaceFlinger 124 * to composite the final output. 125 */ 126void AndroidSurfaceOutput::processWriteResponseQueue(int numFramesToHold) 127{ 128 LOGV("processWriteResponseQueue: queued = %d, numFramesToHold = %d", 129 iWriteResponseQueue.size(), numFramesToHold); 130 while (iWriteResponseQueue.size() > numFramesToHold) { 131 if (iPeer) { 132 iPeer->writeComplete(iWriteResponseQueue[0].iStatus, 133 iWriteResponseQueue[0].iCmdId, 134 (OsclAny*)iWriteResponseQueue[0].iContext); 135 } 136 iWriteResponseQueue.erase(&iWriteResponseQueue[0]); 137 } 138} 139 140void AndroidSurfaceOutput::Cleanup() 141//cleanup all allocated memory and release resources. 142{ 143 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0,"AndroidSurfaceOutput::Cleanup() In")); 144 while (!iCommandResponseQueue.empty()) 145 { 146 if (iObserver) 147 iObserver->RequestCompleted(PVMFCmdResp(iCommandResponseQueue[0].iCmdId, iCommandResponseQueue[0].iContext, iCommandResponseQueue[0].iStatus)); 148 iCommandResponseQueue.erase(&iCommandResponseQueue[0]); 149 } 150 151 processWriteResponseQueue(0); 152 153 // We'll close frame buf and delete here for now. 154 closeFrameBuf(); 155 156 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0,"AndroidSurfaceOutput::Cleanup() Out")); 157 } 158 159OSCL_EXPORT_REF AndroidSurfaceOutput::~AndroidSurfaceOutput() 160{ 161 Cleanup(); 162} 163 164 165PVMFStatus AndroidSurfaceOutput::connect(PvmiMIOSession& aSession, PvmiMIOObserver* aObserver) 166{ 167 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0,"AndroidSurfaceOutput::connect() called")); 168 // Each Session could have its own set of Configuration parameters 169 //in an array of structures and the session ID could be an index to that array. 170 171 //currently supports only one session 172 if (iObserver) 173 return PVMFFailure; 174 175 iObserver=aObserver; 176 return PVMFSuccess; 177} 178 179 180PVMFStatus AndroidSurfaceOutput::disconnect(PvmiMIOSession aSession) 181{ 182 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0,"AndroidSurfaceOutput::disconnect() called")); 183 //currently supports only one session 184 iObserver=NULL; 185 return PVMFSuccess; 186} 187 188 189PvmiMediaTransfer* AndroidSurfaceOutput::createMediaTransfer(PvmiMIOSession& aSession, 190 PvmiKvp* read_formats, int32 read_flags, 191 PvmiKvp* write_formats, int32 write_flags) 192{ 193 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0,"AndroidSurfaceOutput::createMediaTransfer() called")); 194 return (PvmiMediaTransfer*)this; 195} 196 197void AndroidSurfaceOutput::QueueCommandResponse(CommandResponse& aResp) 198{ 199 //queue a command response and schedule processing. 200 201 iCommandResponseQueue.push_back(aResp); 202 203 //cancel any timer delay so the command response will happen ASAP. 204 if (IsBusy()) 205 Cancel(); 206 207 RunIfNotReady(); 208} 209 210PVMFCommandId AndroidSurfaceOutput::QueryUUID(const PvmfMimeString& aMimeType, 211 Oscl_Vector<PVUuid, OsclMemAllocator>& aUuids, 212 bool aExactUuidsOnly, const OsclAny* aContext) 213{ 214 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0,"AndroidSurfaceOutput::QueryUUID() called")); 215 216 OSCL_UNUSED_ARG(aMimeType); 217 OSCL_UNUSED_ARG(aExactUuidsOnly); 218 219 PVMFCommandId cmdid=iCommandCounter++; 220 221 PVMFStatus status=PVMFFailure; 222 int32 err ; 223 OSCL_TRY(err, aUuids.push_back(PVMI_CAPABILITY_AND_CONFIG_PVUUID);); 224 if (err==OsclErrNone) 225 status= PVMFSuccess; 226 227 CommandResponse resp(status,cmdid,aContext); 228 QueueCommandResponse(resp); 229 return cmdid; 230} 231 232 233PVMFCommandId AndroidSurfaceOutput::QueryInterface(const PVUuid& aUuid, PVInterface*& aInterfacePtr, const OsclAny* aContext) 234{ 235 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0,"AndroidSurfaceOutput::QueryInterface() called")); 236 237 PVMFCommandId cmdid=iCommandCounter++; 238 239 PVMFStatus status=PVMFFailure; 240 if(aUuid == PVMI_CAPABILITY_AND_CONFIG_PVUUID) 241 { 242 PvmiCapabilityAndConfig* myInterface = OSCL_STATIC_CAST(PvmiCapabilityAndConfig*,this); 243 aInterfacePtr = OSCL_STATIC_CAST(PVInterface*, myInterface); 244 status= PVMFSuccess; 245 } 246 else 247 { 248 status=PVMFFailure; 249 } 250 251 CommandResponse resp(status,cmdid,aContext); 252 QueueCommandResponse(resp); 253 return cmdid; 254} 255 256 257void AndroidSurfaceOutput::deleteMediaTransfer(PvmiMIOSession& aSession, PvmiMediaTransfer* media_transfer) 258{ 259 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0,"AndroidSurfaceOutput::deleteMediaTransfer() called")); 260 // This class is implementing the media transfer, so no cleanup is needed 261} 262 263 264PVMFCommandId AndroidSurfaceOutput:: Init(const OsclAny* aContext) 265{ 266 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0,"AndroidSurfaceOutput::Init() called")); 267 268 PVMFCommandId cmdid=iCommandCounter++; 269 270 PVMFStatus status=PVMFFailure; 271 272 switch(iState) 273 { 274 case STATE_LOGGED_ON: 275 status=PVMFSuccess; 276 iState=STATE_INITIALIZED; 277 break; 278 279 default: 280 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0,"AndroidSurfaceOutput::Invalid State")); 281 status=PVMFErrInvalidState; 282 break; 283 } 284 285 CommandResponse resp(status,cmdid,aContext); 286 QueueCommandResponse(resp); 287 return cmdid; 288} 289 290PVMFCommandId AndroidSurfaceOutput::Reset(const OsclAny* aContext) 291{ 292 ResetData(); 293 PVMFCommandId cmdid=iCommandCounter++; 294 CommandResponse resp(PVMFSuccess,cmdid,aContext); 295 QueueCommandResponse(resp); 296 return cmdid; 297} 298 299 300PVMFCommandId AndroidSurfaceOutput::Start(const OsclAny* aContext) 301{ 302 iEosReceived = false; 303 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0,"AndroidSurfaceOutput::Start() called")); 304 305 PVMFCommandId cmdid=iCommandCounter++; 306 307 PVMFStatus status=PVMFFailure; 308 309 switch(iState) 310 { 311 case STATE_INITIALIZED: 312 case STATE_PAUSED: 313 314 iState=STATE_STARTED; 315 processWriteResponseQueue(0); 316 status=PVMFSuccess; 317 break; 318 319 default: 320 status=PVMFErrInvalidState; 321 break; 322 } 323 324 CommandResponse resp(status,cmdid,aContext); 325 QueueCommandResponse(resp); 326 return cmdid; 327} 328 329// post the last video frame to refresh screen after pause 330void AndroidSurfaceOutput::postLastFrame() 331{ 332 // ignore if no surface or heap 333 if ((mSurface == NULL) || (mBufferHeap.heap == NULL)) return; 334 mSurface->postBuffer(mFrameBuffers[mFrameBufferIndex]); 335} 336 337PVMFCommandId AndroidSurfaceOutput::Pause(const OsclAny* aContext) 338{ 339 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0,"AndroidSurfaceOutput::Pause() called")); 340 341 PVMFCommandId cmdid=iCommandCounter++; 342 343 PVMFStatus status=PVMFFailure; 344 345 switch(iState) 346 { 347 case STATE_STARTED: 348 349 iState=STATE_PAUSED; 350 status=PVMFSuccess; 351 352 // post last buffer to prevent stale data 353 // if not configured, PVMFMIOConfigurationComplete is not sent 354 // there should not be any media data. 355 if(iIsMIOConfigured) { 356 postLastFrame(); 357 } 358 break; 359 360 default: 361 status=PVMFErrInvalidState; 362 break; 363 } 364 365 CommandResponse resp(status,cmdid,aContext); 366 QueueCommandResponse(resp); 367 return cmdid; 368} 369 370 371PVMFCommandId AndroidSurfaceOutput::Flush(const OsclAny* aContext) 372{ 373 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0,"AndroidSurfaceOutput::Flush() called")); 374 375 PVMFCommandId cmdid=iCommandCounter++; 376 377 PVMFStatus status=PVMFFailure; 378 379 switch(iState) 380 { 381 case STATE_STARTED: 382 383 iState=STATE_INITIALIZED; 384 status=PVMFSuccess; 385 break; 386 387 default: 388 status=PVMFErrInvalidState; 389 break; 390 } 391 392 CommandResponse resp(status,cmdid,aContext); 393 QueueCommandResponse(resp); 394 return cmdid; 395} 396 397PVMFCommandId AndroidSurfaceOutput::DiscardData(const OsclAny* aContext) 398{ 399 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0,"AndroidSurfaceOutput::DiscardData() called")); 400 401 PVMFCommandId cmdid=iCommandCounter++; 402 403 //this component doesn't buffer data, so there's nothing 404 //needed here. 405 406 PVMFStatus status=PVMFSuccess; 407 processWriteResponseQueue(0); 408 409 CommandResponse resp(status,cmdid,aContext); 410 QueueCommandResponse(resp); 411 return cmdid; 412} 413 414PVMFCommandId AndroidSurfaceOutput::DiscardData(PVMFTimestamp aTimestamp, const OsclAny* aContext) 415{ 416 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0,"AndroidSurfaceOutput::DiscardData() called")); 417 418 PVMFCommandId cmdid=iCommandCounter++; 419 420 aTimestamp = 0; 421 422 //this component doesn't buffer data, so there's nothing 423 //needed here. 424 425 PVMFStatus status=PVMFSuccess; 426 processWriteResponseQueue(0); 427 428 CommandResponse resp(status,cmdid,aContext); 429 QueueCommandResponse(resp); 430 return cmdid; 431} 432 433PVMFCommandId AndroidSurfaceOutput::Stop(const OsclAny* aContext) 434{ 435 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0,"AndroidSurfaceOutput::Stop() called")); 436 437 PVMFCommandId cmdid=iCommandCounter++; 438 439 PVMFStatus status=PVMFFailure; 440 441 switch(iState) 442 { 443 case STATE_STARTED: 444 case STATE_PAUSED: 445 446#ifdef PERFORMANCE_MEASUREMENTS_ENABLED 447 // FIXME: This should be moved to OMAP library 448 PVOmapVideoProfile.MarkEndTime(); 449 PVOmapVideoProfile.PrintStats(); 450 PVOmapVideoProfile.Reset(); 451#endif 452 453 iState=STATE_INITIALIZED; 454 status=PVMFSuccess; 455 break; 456 457 default: 458 status=PVMFErrInvalidState; 459 break; 460 } 461 462 CommandResponse resp(status,cmdid,aContext); 463 QueueCommandResponse(resp); 464 return cmdid; 465} 466 467PVMFCommandId AndroidSurfaceOutput::CancelAllCommands(const OsclAny* aContext) 468{ 469 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0,"AndroidSurfaceOutput::CancelAllCommands() called")); 470 471 PVMFCommandId cmdid=iCommandCounter++; 472 473 //commands are executed immediately upon being received, so 474 //it isn't really possible to cancel them. 475 476 PVMFStatus status=PVMFSuccess; 477 478 CommandResponse resp(status,cmdid,aContext); 479 QueueCommandResponse(resp); 480 return cmdid; 481} 482 483PVMFCommandId AndroidSurfaceOutput::CancelCommand(PVMFCommandId aCmdId, const OsclAny* aContext) 484{ 485 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0,"AndroidSurfaceOutput::CancelCommand() called")); 486 487 PVMFCommandId cmdid=iCommandCounter++; 488 489 //commands are executed immediately upon being received, so 490 //it isn't really possible to cancel them. 491 492 //see if the response is still queued. 493 PVMFStatus status=PVMFFailure; 494 for (uint32 i=0;i<iCommandResponseQueue.size();i++) 495 { 496 if (iCommandResponseQueue[i].iCmdId==aCmdId) 497 { 498 status=PVMFSuccess; 499 break; 500 } 501 } 502 503 CommandResponse resp(status,cmdid,aContext); 504 QueueCommandResponse(resp); 505 return cmdid; 506} 507 508void AndroidSurfaceOutput::ThreadLogon() 509{ 510 if(iState==STATE_IDLE) 511 { 512 iLogger = PVLogger::GetLoggerObject("PVOmapVideo"); 513 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0,"AndroidSurfaceOutput::ThreadLogon() called")); 514 AddToScheduler(); 515 iState=STATE_LOGGED_ON; 516 } 517} 518 519 520void AndroidSurfaceOutput::ThreadLogoff() 521{ 522 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0,"AndroidSurfaceOutput::ThreadLogoff() called")); 523 524 if(iState!=STATE_IDLE) 525 { 526 RemoveFromScheduler(); 527 iLogger=NULL; 528 iState=STATE_IDLE; 529 } 530} 531 532 533void AndroidSurfaceOutput::setPeer(PvmiMediaTransfer* aPeer) 534{ 535 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0,"AndroidSurfaceOutput::setPeer() called")); 536 // Set the observer 537 iPeer = aPeer; 538} 539 540 541void AndroidSurfaceOutput::useMemoryAllocators(OsclMemAllocator* write_alloc) 542{ 543 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0,"AndroidSurfaceOutput::useMemoryAllocators() called")); 544 //not supported. 545} 546 547// This routine will determine whether data can be accepted in a writeAsync 548// call and if not, will return true; 549bool AndroidSurfaceOutput::CheckWriteBusy(uint32 aSeqNum) 550{ 551 // for all other cases, accept data now. 552 return false; 553} 554 555PVMFCommandId AndroidSurfaceOutput::writeAsync(uint8 aFormatType, int32 aFormatIndex, uint8* aData, uint32 aDataLen, 556 const PvmiMediaXferHeader& data_header_info, OsclAny* aContext) 557{ 558 // Do a leave if MIO is not configured except when it is an EOS 559 if (!iIsMIOConfigured 560 && 561 !((PVMI_MEDIAXFER_FMT_TYPE_NOTIFICATION == aFormatType) 562 && (PVMI_MEDIAXFER_FMT_INDEX_END_OF_STREAM == aFormatIndex))) 563 { 564 LOGE("data is pumped in before MIO is configured"); 565 OSCL_LEAVE(OsclErrInvalidState); 566 return -1; 567 } 568 569 uint32 aSeqNum=data_header_info.seq_num; 570 PVMFTimestamp aTimestamp=data_header_info.timestamp; 571 uint32 flags=data_header_info.flags; 572 573 if (aSeqNum < 6) 574 { 575 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 576 (0,"AndroidSurfaceOutput::writeAsync() seqnum %d ts %d context %d",aSeqNum,aTimestamp,aContext)); 577 578 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 579 (0,"AndroidSurfaceOutput::writeAsync() Format Type %d Format Index %d length %d",aFormatType,aFormatIndex,aDataLen)); 580 } 581 582 PVMFStatus status=PVMFFailure; 583 584 switch(aFormatType) 585 { 586 case PVMI_MEDIAXFER_FMT_TYPE_COMMAND : 587 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 588 (0,"AndroidSurfaceOutput::writeAsync() called with Command info.")); 589 //ignore 590 status= PVMFSuccess; 591 break; 592 593 case PVMI_MEDIAXFER_FMT_TYPE_NOTIFICATION : 594 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 595 (0,"AndroidSurfaceOutput::writeAsync() called with Notification info.")); 596 switch(aFormatIndex) 597 { 598 case PVMI_MEDIAXFER_FMT_INDEX_END_OF_STREAM: 599 iEosReceived = true; 600 break; 601 default: 602 break; 603 } 604 //ignore 605 status= PVMFSuccess; 606 break; 607 608 case PVMI_MEDIAXFER_FMT_TYPE_DATA : 609 switch(aFormatIndex) 610 { 611 case PVMI_MEDIAXFER_FMT_INDEX_FMT_SPECIFIC_INFO: 612 //format-specific info contains codec headers. 613 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 614 (0,"AndroidSurfaceOutput::writeAsync() called with format-specific info.")); 615 616 if (iState<STATE_INITIALIZED) 617 { 618 PVLOGGER_LOGMSG(PVLOGMSG_INST_REL, iLogger, PVLOGMSG_ERR, 619 (0,"AndroidSurfaceOutput::writeAsync: Error - Invalid state")); 620 status=PVMFErrInvalidState; 621 } 622 else 623 { 624 status= PVMFSuccess; 625 } 626 627 break; 628 629 case PVMI_MEDIAXFER_FMT_INDEX_DATA: 630 //data contains the media bitstream. 631 632 //Verify the state 633 if (iState!=STATE_STARTED) 634 { 635 PVLOGGER_LOGMSG(PVLOGMSG_INST_REL, iLogger, PVLOGMSG_ERR, 636 (0,"AndroidSurfaceOutput::writeAsync: Error - Invalid state")); 637 status=PVMFErrInvalidState; 638 } 639 else 640 { 641 642 //printf("V WriteAsync { seq=%d, ts=%d }\n", data_header_info.seq_num, data_header_info.timestamp); 643 644 // Call playback to send data to IVA for Color Convert 645 status = writeFrameBuf(aData, aDataLen, data_header_info); 646 647 PVLOGGER_LOGMSG(PVLOGMSG_INST_REL, iLogger, PVLOGMSG_ERR, 648 (0,"AndroidSurfaceOutput::writeAsync: Playback Progress - frame %d",iFrameNumber++)); 649 } 650 break; 651 652 default: 653 PVLOGGER_LOGMSG(PVLOGMSG_INST_REL, iLogger, PVLOGMSG_ERR, 654 (0,"AndroidSurfaceOutput::writeAsync: Error - unrecognized format index")); 655 status= PVMFFailure; 656 break; 657 } 658 break; 659 660 default: 661 PVLOGGER_LOGMSG(PVLOGMSG_INST_REL, iLogger, PVLOGMSG_ERR, 662 (0,"AndroidSurfaceOutput::writeAsync: Error - unrecognized format type")); 663 status= PVMFFailure; 664 break; 665 } 666 667 //Schedule asynchronous response 668 PVMFCommandId cmdid=iCommandCounter++; 669 WriteResponse resp(status,cmdid,aContext,aTimestamp); 670 iWriteResponseQueue.push_back(resp); 671 RunIfNotReady(); 672 673 return cmdid; 674} 675 676void AndroidSurfaceOutput::writeComplete(PVMFStatus aStatus, PVMFCommandId write_cmd_id, OsclAny* aContext) 677{ 678 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0,"AndroidSurfaceOutput::writeComplete() called")); 679 //won't be called since this component is a sink. 680} 681 682 683PVMFCommandId AndroidSurfaceOutput::readAsync(uint8* data, uint32 max_data_len, OsclAny* aContext, 684 int32* formats, uint16 num_formats) 685{ 686 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0,"AndroidSurfaceOutput::readAsync() called")); 687 //read not supported. 688 OsclError::Leave(OsclErrNotSupported); 689 return -1; 690} 691 692 693void AndroidSurfaceOutput::readComplete(PVMFStatus aStatus, PVMFCommandId read_cmd_id, int32 format_index, 694 const PvmiMediaXferHeader& data_header_info, OsclAny* aContext) 695{ 696 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0,"AndroidSurfaceOutput::readComplete() called")); 697 //won't be called since this component is a sink. 698} 699 700 701void AndroidSurfaceOutput::statusUpdate(uint32 status_flags) 702{ 703 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0,"AndroidSurfaceOutput::statusUpdate() called")); 704 //won't be called since this component is a sink. 705} 706 707 708void AndroidSurfaceOutput::cancelCommand(PVMFCommandId command_id) 709{ 710 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0,"AndroidSurfaceOutput::cancelCommand() called")); 711 712 //the purpose of this API is to cancel a writeAsync command and report 713 //completion ASAP. 714 715 //in this implementation, the write commands are executed immediately 716 //when received so it isn't really possible to cancel. 717 //just report completion immediately. 718 processWriteResponseQueue(0); 719} 720 721void AndroidSurfaceOutput::cancelAllCommands() 722{ 723 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0,"AndroidSurfaceOutput::cancelAllCommands() called")); 724 725 //the purpose of this API is to cancel all writeAsync commands and report 726 //completion ASAP. 727 728 //in this implementaiton, the write commands are executed immediately 729 //when received so it isn't really possible to cancel. 730 //just report completion immediately. 731 732 for (uint32 i=0;i<iWriteResponseQueue.size();i++) 733 { 734 //report completion 735 if (iPeer) 736 iPeer->writeComplete(iWriteResponseQueue[i].iStatus,iWriteResponseQueue[i].iCmdId,(OsclAny*)iWriteResponseQueue[i].iContext); 737 iWriteResponseQueue.erase(&iWriteResponseQueue[i]); 738 } 739} 740 741void AndroidSurfaceOutput::setObserver (PvmiConfigAndCapabilityCmdObserver* aObserver) 742{ 743 OSCL_UNUSED_ARG(aObserver); 744 //not needed since this component only supports synchronous capability & config 745 //APIs. 746} 747 748PVMFStatus AndroidSurfaceOutput::getParametersSync(PvmiMIOSession aSession, PvmiKeyType aIdentifier, 749 PvmiKvp*& aParameters, int& num_parameter_elements, 750 PvmiCapabilityContext aContext) 751{ 752 OSCL_UNUSED_ARG(aSession); 753 OSCL_UNUSED_ARG(aContext); 754 aParameters=NULL; 755 756 // This is a query for the list of supported formats. 757 if(pv_mime_strcmp(aIdentifier, INPUT_FORMATS_CAP_QUERY) == 0) 758 { 759 aParameters=(PvmiKvp*)oscl_malloc(sizeof(PvmiKvp)); 760 if (aParameters == NULL) return PVMFErrNoMemory; 761 aParameters[num_parameter_elements++].value.pChar_value=(char*) PVMF_MIME_YUV420; 762 763 return PVMFSuccess; 764 } 765 766 //unrecognized key. 767 return PVMFFailure; 768} 769 770PVMFStatus AndroidSurfaceOutput::releaseParameters(PvmiMIOSession aSession, PvmiKvp* aParameters, int num_elements) 771{ 772 //release parameters that were allocated by this component. 773 if (aParameters) 774 { 775 oscl_free(aParameters); 776 return PVMFSuccess; 777 } 778 return PVMFFailure; 779} 780 781void AndroidSurfaceOutput ::createContext(PvmiMIOSession aSession, PvmiCapabilityContext& aContext) 782{ 783 OsclError::Leave(OsclErrNotSupported); 784} 785 786void AndroidSurfaceOutput::setContextParameters(PvmiMIOSession aSession, PvmiCapabilityContext& aContext, 787 PvmiKvp* aParameters, int num_parameter_elements) 788{ 789 OsclError::Leave(OsclErrNotSupported); 790} 791 792void AndroidSurfaceOutput::DeleteContext(PvmiMIOSession aSession, PvmiCapabilityContext& aContext) 793{ 794 OsclError::Leave(OsclErrNotSupported); 795} 796 797 798void AndroidSurfaceOutput::setParametersSync(PvmiMIOSession aSession, PvmiKvp* aParameters, 799 int num_elements, PvmiKvp * & aRet_kvp) 800{ 801 OSCL_UNUSED_ARG(aSession); 802 803 aRet_kvp = NULL; 804 805 LOGV("setParametersSync"); 806 for (int32 i=0;i<num_elements;i++) 807 { 808 //Check against known video parameter keys... 809 if (pv_mime_strcmp(aParameters[i].key, MOUT_VIDEO_FORMAT_KEY) == 0) 810 { 811 iVideoFormatString=aParameters[i].value.pChar_value; 812 iVideoFormat=iVideoFormatString.get_str(); 813 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 814 (0,"AndroidSurfaceOutput::setParametersSync() Video Format Key, Value %s",iVideoFormatString.get_str())); 815 } 816 else if (pv_mime_strcmp(aParameters[i].key, MOUT_VIDEO_WIDTH_KEY) == 0) 817 { 818 iVideoWidth=(int32)aParameters[i].value.uint32_value; 819 iVideoParameterFlags |= VIDEO_WIDTH_VALID; 820 LOGV("iVideoWidth=%d", iVideoWidth); 821 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 822 (0,"AndroidSurfaceOutput::setParametersSync() Video Width Key, Value %d",iVideoWidth)); 823 } 824 else if (pv_mime_strcmp(aParameters[i].key, MOUT_VIDEO_HEIGHT_KEY) == 0) 825 { 826 iVideoHeight=(int32)aParameters[i].value.uint32_value; 827 iVideoParameterFlags |= VIDEO_HEIGHT_VALID; 828 LOGV("iVideoHeight=%d", iVideoHeight); 829 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 830 (0,"AndroidSurfaceOutput::setParametersSync() Video Height Key, Value %d",iVideoHeight)); 831 } 832 else if (pv_mime_strcmp(aParameters[i].key, MOUT_VIDEO_DISPLAY_HEIGHT_KEY) == 0) 833 { 834 iVideoDisplayHeight=(int32)aParameters[i].value.uint32_value; 835 iVideoParameterFlags |= DISPLAY_HEIGHT_VALID; 836 LOGV("iVideoDisplayHeight=%d", iVideoDisplayHeight); 837 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 838 (0,"AndroidSurfaceOutput::setParametersSync() Video Display Height Key, Value %d",iVideoDisplayHeight)); 839 } 840 else if (pv_mime_strcmp(aParameters[i].key, MOUT_VIDEO_DISPLAY_WIDTH_KEY) == 0) 841 { 842 iVideoDisplayWidth=(int32)aParameters[i].value.uint32_value; 843 iVideoParameterFlags |= DISPLAY_WIDTH_VALID; 844 LOGV("iVideoDisplayWidth=%d", iVideoDisplayWidth); 845 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 846 (0,"AndroidSurfaceOutput::setParametersSync() Video Display Width Key, Value %d",iVideoDisplayWidth)); 847 } 848 else if (pv_mime_strcmp(aParameters[i].key, MOUT_VIDEO_SUBFORMAT_KEY) == 0) 849 { 850 iVideoSubFormat=aParameters[i].value.pChar_value; 851 iVideoParameterFlags |= VIDEO_SUBFORMAT_VALID; 852 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 853 (0,"AndroidSurfaceOutput::setParametersSync() Video SubFormat Key, Value %s",iVideoSubFormat.getMIMEStrPtr())); 854 855LOGV("VIDEO SUBFORMAT SET TO %s\n",iVideoSubFormat.getMIMEStrPtr()); 856 } 857 else 858 { 859 //if we get here the key is unrecognized. 860 861 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 862 (0,"AndroidSurfaceOutput::setParametersSync() Error, unrecognized key = %s", aParameters[i].key)); 863 864 //set the return value to indicate the unrecognized key 865 //and return. 866 aRet_kvp = &aParameters[i]; 867 return; 868 } 869 } 870 uint32 mycache = iVideoParameterFlags ; 871 // if initialization is complete, update the app display info 872 if( checkVideoParameterFlags() ) 873 initCheck(); 874 iVideoParameterFlags = mycache; 875 876 // when all necessary parameters are received, send 877 // PVMFMIOConfigurationComplete event to observer 878 if(!iIsMIOConfigured && checkVideoParameterFlags() ) 879 { 880 iIsMIOConfigured = true; 881 if(iObserver) 882 { 883 iObserver->ReportInfoEvent(PVMFMIOConfigurationComplete); 884 } 885 } 886} 887 888PVMFCommandId AndroidSurfaceOutput::setParametersAsync(PvmiMIOSession aSession, PvmiKvp* aParameters, 889 int num_elements, PvmiKvp*& aRet_kvp, OsclAny* context) 890{ 891 OsclError::Leave(OsclErrNotSupported); 892 return -1; 893} 894 895uint32 AndroidSurfaceOutput::getCapabilityMetric (PvmiMIOSession aSession) 896{ 897 return 0; 898} 899 900PVMFStatus AndroidSurfaceOutput::verifyParametersSync (PvmiMIOSession aSession, PvmiKvp* aParameters, int num_elements) 901{ 902 OSCL_UNUSED_ARG(aSession); 903 904 // Go through each parameter 905 for (int32 i=0; i<num_elements; i++) { 906 char* compstr = NULL; 907 pv_mime_string_extract_type(0, aParameters[i].key, compstr); 908 if (pv_mime_strcmp(compstr, _STRLIT_CHAR("x-pvmf/media/format-type")) == 0) { 909 if (pv_mime_strcmp(aParameters[i].value.pChar_value, PVMF_MIME_YUV420) == 0) { 910 return PVMFSuccess; 911 } 912 else { 913 return PVMFErrNotSupported; 914 } 915 } 916 } 917 return PVMFSuccess; 918} 919 920// 921// Private section 922// 923 924void AndroidSurfaceOutput::Run() 925{ 926 //send async command responses 927 while (!iCommandResponseQueue.empty()) 928 { 929 if (iObserver) 930 iObserver->RequestCompleted(PVMFCmdResp(iCommandResponseQueue[0].iCmdId, iCommandResponseQueue[0].iContext, iCommandResponseQueue[0].iStatus)); 931 iCommandResponseQueue.erase(&iCommandResponseQueue[0]); 932 } 933 934 //send async write completion 935 if (iEosReceived) { 936 LOGV("Flushing buffers after EOS"); 937 processWriteResponseQueue(0); 938 } else { 939 processWriteResponseQueue(mNumberOfFramesToHold); 940 } 941} 942 943// create a frame buffer for software codecs 944OSCL_EXPORT_REF bool AndroidSurfaceOutput::initCheck() 945{ 946 947 // initialize only when we have all the required parameters 948 if (!checkVideoParameterFlags()) 949 return mInitialized; 950 951 // release resources if previously initialized 952 closeFrameBuf(); 953 954 // reset flags in case display format changes in the middle of a stream 955 resetVideoParameterFlags(); 956 957 // copy parameters in case we need to adjust them 958 int displayWidth = iVideoDisplayWidth; 959 int displayHeight = iVideoDisplayHeight; 960 int frameWidth = iVideoWidth; 961 int frameHeight = iVideoHeight; 962 int frameSize; 963 964 // RGB-565 frames are 2 bytes/pixel 965 displayWidth = (displayWidth + 1) & -2; 966 displayHeight = (displayHeight + 1) & -2; 967 frameWidth = (frameWidth + 1) & -2; 968 frameHeight = (frameHeight + 1) & -2; 969 frameSize = frameWidth * frameHeight * 2; 970 971 // create frame buffer heap and register with surfaceflinger 972 sp<MemoryHeapBase> heap = new MemoryHeapBase(frameSize * kBufferCount); 973 if (heap->heapID() < 0) { 974 LOGE("Error creating frame buffer heap"); 975 return false; 976 } 977 978 mBufferHeap = ISurface::BufferHeap(displayWidth, displayHeight, 979 frameWidth, frameHeight, PIXEL_FORMAT_RGB_565, heap); 980 mSurface->registerBuffers(mBufferHeap); 981 982 // create frame buffers 983 for (int i = 0; i < kBufferCount; i++) { 984 mFrameBuffers[i] = i * frameSize; 985 } 986 987 // initialize software color converter 988 iColorConverter = ColorConvert16::NewL(); 989 iColorConverter->Init(displayWidth, displayHeight, frameWidth, displayWidth, displayHeight, displayWidth, CCROTATE_NONE); 990 iColorConverter->SetMemHeight(frameHeight); 991 iColorConverter->SetMode(1); 992 993 LOGV("video = %d x %d", displayWidth, displayHeight); 994 LOGV("frame = %d x %d", frameWidth, frameHeight); 995 LOGV("frame #bytes = %d", frameSize); 996 997 // register frame buffers with SurfaceFlinger 998 mFrameBufferIndex = 0; 999 mInitialized = true; 1000 mPvPlayer->sendEvent(MEDIA_SET_VIDEO_SIZE, iVideoDisplayWidth, iVideoDisplayHeight); 1001 1002 return mInitialized; 1003} 1004 1005OSCL_EXPORT_REF PVMFStatus AndroidSurfaceOutput::writeFrameBuf(uint8* aData, uint32 aDataLen, const PvmiMediaXferHeader& data_header_info) 1006{ 1007 // post to SurfaceFlinger 1008 if ((mSurface != NULL) && (mBufferHeap.heap != NULL)) { 1009 if (++mFrameBufferIndex == kBufferCount) mFrameBufferIndex = 0; 1010 iColorConverter->Convert(aData, static_cast<uint8*>(mBufferHeap.heap->base()) + mFrameBuffers[mFrameBufferIndex]); 1011 mSurface->postBuffer(mFrameBuffers[mFrameBufferIndex]); 1012 } 1013 return PVMFSuccess; 1014} 1015 1016OSCL_EXPORT_REF void AndroidSurfaceOutput::closeFrameBuf() 1017{ 1018 LOGV("closeFrameBuf"); 1019 if (!mInitialized) return; 1020 1021 mInitialized = false; 1022 if (mSurface.get()) { 1023 LOGV("unregisterBuffers"); 1024 mSurface->unregisterBuffers(); 1025 } 1026 1027 // free frame buffers 1028 LOGV("free frame buffers"); 1029 for (int i = 0; i < kBufferCount; i++) { 1030 mFrameBuffers[i] = 0; 1031 } 1032 1033 // free heaps 1034 LOGV("free frame heap"); 1035 mBufferHeap.heap.clear(); 1036 1037 // free color converter 1038 if (iColorConverter != 0) 1039 { 1040 LOGV("free color converter"); 1041 delete iColorConverter; 1042 iColorConverter = 0; 1043 } 1044} 1045 1046OSCL_EXPORT_REF bool AndroidSurfaceOutput::GetVideoSize(int *w, int *h) { 1047 1048 *w = iVideoDisplayWidth; 1049 *h = iVideoDisplayHeight; 1050 return iVideoDisplayWidth != 0 && iVideoDisplayHeight != 0; 1051} 1052