| /* ------------------------------------------------------------------ |
| * Copyright (C) 1998-2009 PacketVideo |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either |
| * express or implied. |
| * See the License for the specific language governing permissions |
| * and limitations under the License. |
| * ------------------------------------------------------------------- |
| */ |
| #include "pv_frame_metadata_mio_video.h" |
| #include "pvlogger.h" |
| #include "pv_mime_string_utils.h" |
| #include "oscl_snprintf.h" |
| #include "cczoomrotationbase.h" |
| |
| PVFMVideoMIO::PVFMVideoMIO() : |
| OsclTimerObject(OsclActiveObject::EPriorityNominal, "PVFMVideoMIO") |
| { |
| InitData(); |
| } |
| |
| |
| void PVFMVideoMIO::InitData() |
| { |
| iVideoFormat = PVMF_MIME_FORMAT_UNKNOWN; |
| iVideoSubFormat = PVMF_MIME_FORMAT_UNKNOWN; |
| iVideoHeightValid = false; |
| iVideoWidthValid = false; |
| iVideoDisplayHeightValid = false; |
| iVideoDisplayWidthValid = false; |
| iIsMIOConfigured = false; |
| iWriteBusy = false; |
| iVideoHeight = 0; |
| iVideoWidth = 0; |
| iVideoDisplayHeight = 0; |
| iVideoDisplayWidth = 0; |
| |
| iThumbnailWidth = 320; |
| iThumbnailHeight = 240; |
| |
| |
| iColorConverter = NULL; |
| iCCRGBFormatType = PVMF_MIME_FORMAT_UNKNOWN; |
| |
| iCommandCounter = 0; |
| iLogger = NULL; |
| iCommandResponseQueue.reserve(5); |
| iWriteResponseQueue.reserve(5); |
| iObserver = NULL; |
| iLogger = NULL; |
| iPeer = NULL; |
| iState = STATE_IDLE; |
| |
| iFrameRetrievalInfo.iRetrievalRequested = false; |
| iFrameRetrievalInfo.iGetFrameObserver = NULL; |
| iFrameRetrievalInfo.iUseFrameIndex = false; |
| iFrameRetrievalInfo.iUseTimeOffset = false; |
| iFrameRetrievalInfo.iFrameIndex = 0; |
| iFrameRetrievalInfo.iTimeOffset = 0; |
| iFrameRetrievalInfo.iFrameBuffer = NULL; |
| iFrameRetrievalInfo.iBufferSize = NULL; |
| |
| // Init the input format capabilities vector |
| iInputFormatCapability.clear(); |
| iInputFormatCapability.push_back(PVMF_MIME_YUV420); |
| iInputFormatCapability.push_back(PVMF_MIME_YUV422); |
| iInputFormatCapability.push_back(PVMF_MIME_YUV422_INTERLEAVED_UYVY); |
| iInputFormatCapability.push_back(PVMF_MIME_RGB8); |
| iInputFormatCapability.push_back(PVMF_MIME_RGB12); |
| iInputFormatCapability.push_back(PVMF_MIME_RGB16); |
| iInputFormatCapability.push_back(PVMF_MIME_RGB24); |
| |
| iYUV422toYUV420ColorConvert = NULL; |
| } |
| |
| |
| void PVFMVideoMIO::ResetData() |
| { |
| Cleanup(); |
| |
| // Reset all the received media parameters. |
| iVideoFormat = PVMF_MIME_FORMAT_UNKNOWN; |
| iVideoSubFormat = PVMF_MIME_FORMAT_UNKNOWN; |
| iVideoHeightValid = false; |
| iVideoWidthValid = false; |
| iVideoDisplayHeightValid = false; |
| iVideoDisplayWidthValid = false; |
| iVideoHeight = 0; |
| iVideoWidth = 0; |
| iVideoDisplayHeight = 0; |
| iVideoDisplayWidth = 0; |
| iIsMIOConfigured = false; |
| iWriteBusy = false; |
| } |
| |
| |
| void PVFMVideoMIO::Cleanup() |
| { |
| while (!iCommandResponseQueue.empty()) |
| { |
| if (iObserver) |
| { |
| iObserver->RequestCompleted(PVMFCmdResp(iCommandResponseQueue[0].iCmdId, iCommandResponseQueue[0].iContext, iCommandResponseQueue[0].iStatus)); |
| } |
| iCommandResponseQueue.erase(&iCommandResponseQueue[0]); |
| } |
| |
| while (!iWriteResponseQueue.empty()) |
| { |
| if (iPeer) |
| { |
| iPeer->writeComplete(iWriteResponseQueue[0].iStatus, iWriteResponseQueue[0].iCmdId, (OsclAny*)iWriteResponseQueue[0].iContext); |
| } |
| iWriteResponseQueue.erase(&iWriteResponseQueue[0]); |
| } |
| } |
| |
| |
| PVFMVideoMIO::~PVFMVideoMIO() |
| { |
| Cleanup(); |
| |
| if (iColorConverter) |
| { |
| DestroyYUVToRGBColorConverter(iColorConverter, iCCRGBFormatType); |
| } |
| |
| if (iYUV422toYUV420ColorConvert) |
| { |
| DestroyYUV422toYUV420ColorConvert(); |
| } |
| } |
| |
| void PVFMVideoMIO::setThumbnailDimensions(uint32 aWidth, uint32 aHeight) |
| { |
| iThumbnailWidth = aWidth; |
| iThumbnailHeight = aHeight; |
| } |
| |
| PVMFStatus PVFMVideoMIO::GetFrameByFrameNumber(uint32 aFrameIndex, uint8* aFrameBuffer, uint32& aBufferSize, |
| PVMFFormatType aFormatType, PVFMVideoMIOGetFrameObserver& aObserver) |
| { |
| if (iFrameRetrievalInfo.iRetrievalRequested) |
| { |
| // Get frame request is already pending so don't accept this request |
| return PVMFErrBusy; |
| } |
| |
| if (aFrameBuffer == NULL || aBufferSize == 0) |
| { |
| // Bad parameters |
| return PVMFErrArgument; |
| } |
| |
| // Signal for frame retrieval by frame number |
| iFrameRetrievalInfo.iRetrievalRequested = true; |
| iFrameRetrievalInfo.iGetFrameObserver = &aObserver; |
| iFrameRetrievalInfo.iUseFrameIndex = true; |
| iFrameRetrievalInfo.iUseTimeOffset = false; |
| iFrameRetrievalInfo.iFrameIndex = aFrameIndex; |
| iFrameRetrievalInfo.iFrameBuffer = aFrameBuffer; |
| iFrameRetrievalInfo.iBufferSize = &aBufferSize; |
| iFrameRetrievalInfo.iFrameFormatType = aFormatType; |
| |
| iFrameRetrievalInfo.iReceivedFrameCount = 0; |
| iFrameRetrievalInfo.iStartingTSSet = false; |
| iFrameRetrievalInfo.iStartingTS = 0; |
| |
| return PVMFPending; |
| } |
| |
| |
| PVMFStatus PVFMVideoMIO::GetFrameByTimeoffset(uint32 aTimeOffset, uint8* aFrameBuffer, uint32& aBufferSize, |
| PVMFFormatType aFormatType, PVFMVideoMIOGetFrameObserver& aObserver) |
| { |
| if (iFrameRetrievalInfo.iRetrievalRequested) |
| { |
| // Get frame request is already pending don't accept this request |
| return PVMFErrBusy; |
| } |
| |
| if (aFrameBuffer == NULL || aBufferSize == 0) |
| { |
| // Bad parameters |
| return PVMFErrArgument; |
| } |
| |
| // Signal for frame retrieval by time offset |
| iFrameRetrievalInfo.iRetrievalRequested = true; |
| iFrameRetrievalInfo.iGetFrameObserver = &aObserver; |
| iFrameRetrievalInfo.iUseFrameIndex = false; |
| iFrameRetrievalInfo.iUseTimeOffset = true; |
| iFrameRetrievalInfo.iTimeOffset = aTimeOffset; |
| iFrameRetrievalInfo.iFrameBuffer = aFrameBuffer; |
| iFrameRetrievalInfo.iBufferSize = &aBufferSize; |
| iFrameRetrievalInfo.iFrameFormatType = aFormatType; |
| |
| iFrameRetrievalInfo.iReceivedFrameCount = 0; |
| iFrameRetrievalInfo.iStartingTSSet = false; |
| iFrameRetrievalInfo.iStartingTS = 0; |
| |
| return PVMFPending; |
| } |
| |
| |
| PVMFStatus PVFMVideoMIO::CancelGetFrame(void) |
| { |
| // Cancel any pending frame retrieval and reset variables |
| iFrameRetrievalInfo.iRetrievalRequested = false; |
| iFrameRetrievalInfo.iUseFrameIndex = false; |
| iFrameRetrievalInfo.iUseTimeOffset = false; |
| |
| return PVMFSuccess; |
| } |
| |
| |
| PVMFStatus PVFMVideoMIO::GetFrameProperties(uint32& aFrameWidth, uint32& aFrameHeight, uint32& aDisplayWidth, uint32& aDisplayHeight) |
| { |
| if (iVideoWidthValid == false || iVideoHeightValid == false || |
| iVideoDisplayWidthValid == false || iVideoDisplayHeightValid == false) |
| { |
| return PVMFErrNotReady; |
| } |
| |
| aFrameWidth = iVideoWidth; |
| aFrameHeight = iVideoHeight; |
| aDisplayWidth = iVideoDisplayWidth; |
| aDisplayHeight = iVideoDisplayHeight; |
| |
| return PVMFSuccess; |
| } |
| |
| |
| PVMFStatus PVFMVideoMIO::connect(PvmiMIOSession& aSession, PvmiMIOObserver* aObserver) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVFMVideoMIO::connect() called")); |
| |
| // Currently supports only one session |
| OSCL_UNUSED_ARG(aSession); |
| |
| if (iObserver) |
| { |
| return PVMFFailure; |
| } |
| |
| iObserver = aObserver; |
| return PVMFSuccess; |
| } |
| |
| |
| PVMFStatus PVFMVideoMIO::disconnect(PvmiMIOSession aSession) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVFMVideoMIO::disconnect() called")); |
| |
| // Currently supports only one session |
| OSCL_UNUSED_ARG(aSession); |
| |
| iObserver = NULL; |
| return PVMFSuccess; |
| } |
| |
| |
| PvmiMediaTransfer* PVFMVideoMIO::createMediaTransfer(PvmiMIOSession& aSession, PvmiKvp* read_formats, int32 read_flags, |
| PvmiKvp* write_formats, int32 write_flags) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVFMVideoMIO::createMediaTransfer() called")); |
| |
| OSCL_UNUSED_ARG(aSession); |
| OSCL_UNUSED_ARG(read_formats); |
| OSCL_UNUSED_ARG(read_flags); |
| OSCL_UNUSED_ARG(write_formats); |
| OSCL_UNUSED_ARG(write_flags); |
| |
| return (PvmiMediaTransfer*)this; |
| } |
| |
| |
| void PVFMVideoMIO::QueueCommandResponse(CommandResponse& aResp) |
| { |
| // Queue a command response and schedule processing. |
| iCommandResponseQueue.push_back(aResp); |
| |
| // Cancel any timer delay so the command response will happen ASAP. |
| if (IsBusy()) |
| { |
| Cancel(); |
| } |
| |
| RunIfNotReady(); |
| } |
| |
| |
| PVMFCommandId PVFMVideoMIO::QueryUUID(const PvmfMimeString& aMimeType, Oscl_Vector<PVUuid, OsclMemAllocator>& aUuids, |
| bool aExactUuidsOnly, const OsclAny* aContext) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVFMVideoMIO::QueryUUID() called")); |
| |
| OSCL_UNUSED_ARG(aMimeType); |
| OSCL_UNUSED_ARG(aExactUuidsOnly); |
| |
| PVMFCommandId cmdid = iCommandCounter++; |
| |
| PVMFStatus status = PVMFFailure; |
| int32 err ; |
| OSCL_TRY(err, |
| aUuids.push_back(PVMI_CAPABILITY_AND_CONFIG_PVUUID); |
| PVUuid uuid; |
| iActiveTiming.queryUuid(uuid); |
| aUuids.push_back(uuid); |
| ); |
| |
| if (err == OsclErrNone) |
| { |
| status = PVMFSuccess; |
| } |
| |
| CommandResponse resp(status, cmdid, aContext); |
| QueueCommandResponse(resp); |
| return cmdid; |
| } |
| |
| |
| PVMFCommandId PVFMVideoMIO::QueryInterface(const PVUuid& aUuid, PVInterface*& aInterfacePtr, const OsclAny* aContext) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVFMVideoMIO::QueryInterface() called")); |
| |
| PVMFCommandId cmdid = iCommandCounter++; |
| |
| PVMFStatus status = PVMFFailure; |
| if (aUuid == PVMI_CAPABILITY_AND_CONFIG_PVUUID) |
| { |
| PvmiCapabilityAndConfig* myInterface = OSCL_STATIC_CAST(PvmiCapabilityAndConfig*, this); |
| aInterfacePtr = OSCL_STATIC_CAST(PVInterface*, myInterface); |
| status = PVMFSuccess; |
| } |
| else if (aUuid == PvmiClockExtensionInterfaceUuid) |
| { |
| PvmiClockExtensionInterface* myInterface = OSCL_STATIC_CAST(PvmiClockExtensionInterface*, &iActiveTiming); |
| aInterfacePtr = OSCL_STATIC_CAST(PVInterface*, myInterface); |
| status = PVMFSuccess; |
| iActiveTiming.addRef(); |
| } |
| else |
| { |
| status = PVMFFailure; |
| } |
| |
| CommandResponse resp(status, cmdid, aContext); |
| QueueCommandResponse(resp); |
| return cmdid; |
| } |
| |
| |
| void PVFMVideoMIO::deleteMediaTransfer(PvmiMIOSession& aSession, PvmiMediaTransfer* media_transfer) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVFMVideoMIO::deleteMediaTransfer() called")); |
| |
| OSCL_UNUSED_ARG(aSession); |
| OSCL_UNUSED_ARG(media_transfer); |
| |
| // This class is implementing the media transfer, so no cleanup is needed |
| } |
| |
| |
| PVMFCommandId PVFMVideoMIO::Init(const OsclAny* aContext) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVFMVideoMIO::Init() called")); |
| |
| PVMFCommandId cmdid = iCommandCounter++; |
| |
| PVMFStatus status = PVMFFailure; |
| |
| switch (iState) |
| { |
| case STATE_LOGGED_ON: |
| status = PVMFSuccess; |
| iState = STATE_INITIALIZED; |
| break; |
| |
| default: |
| status = PVMFErrInvalidState; |
| break; |
| } |
| |
| CommandResponse resp(status, cmdid, aContext); |
| QueueCommandResponse(resp); |
| return cmdid; |
| } |
| |
| PVMFCommandId PVFMVideoMIO::Reset(const OsclAny* aContext) |
| { |
| ResetData(); |
| |
| PVMFCommandId cmdid = iCommandCounter++; |
| PVMFStatus status = PVMFSuccess; |
| |
| CommandResponse resp(status, cmdid, aContext); |
| QueueCommandResponse(resp); |
| return cmdid; |
| } |
| |
| PVMFCommandId PVFMVideoMIO::Start(const OsclAny* aContext) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVFMVideoMIO::Start() called")); |
| |
| PVMFCommandId cmdid = iCommandCounter++; |
| |
| PVMFStatus status = PVMFFailure; |
| |
| switch (iState) |
| { |
| case STATE_INITIALIZED: |
| case STATE_PAUSED: |
| iState = STATE_STARTED; |
| status = PVMFSuccess; |
| if (iPeer && iWriteBusy) |
| { |
| iWriteBusy = false; |
| iPeer->statusUpdate(PVMI_MEDIAXFER_STATUS_WRITE); |
| } |
| break; |
| |
| default: |
| status = PVMFErrInvalidState; |
| break; |
| } |
| |
| CommandResponse resp(status, cmdid, aContext); |
| QueueCommandResponse(resp); |
| return cmdid; |
| } |
| |
| |
| PVMFCommandId PVFMVideoMIO::Pause(const OsclAny* aContext) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVFMVideoMIO::Pause() called")); |
| |
| PVMFCommandId cmdid = iCommandCounter++; |
| |
| PVMFStatus status = PVMFFailure; |
| |
| switch (iState) |
| { |
| case STATE_STARTED: |
| iState = STATE_PAUSED; |
| status = PVMFSuccess; |
| break; |
| |
| default: |
| status = PVMFErrInvalidState; |
| break; |
| } |
| |
| CommandResponse resp(status, cmdid, aContext); |
| QueueCommandResponse(resp); |
| return cmdid; |
| } |
| |
| |
| PVMFCommandId PVFMVideoMIO::Flush(const OsclAny* aContext) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVFMVideoMIO::Flush() called")); |
| |
| PVMFCommandId cmdid = iCommandCounter++; |
| |
| PVMFStatus status = PVMFFailure; |
| |
| switch (iState) |
| { |
| case STATE_STARTED: |
| iState = STATE_INITIALIZED; |
| status = PVMFSuccess; |
| break; |
| |
| default: |
| status = PVMFErrInvalidState; |
| break; |
| } |
| |
| CommandResponse resp(status, cmdid, aContext); |
| QueueCommandResponse(resp); |
| return cmdid; |
| } |
| |
| |
| PVMFCommandId PVFMVideoMIO::DiscardData(const OsclAny* aContext) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVFMVideoMIO::DiscardData() called")); |
| |
| PVMFCommandId cmdid = iCommandCounter++; |
| |
| // This component doesn't buffer data, so there's nothing needed here. |
| PVMFStatus status = PVMFSuccess; |
| |
| CommandResponse resp(status, cmdid, aContext); |
| QueueCommandResponse(resp); |
| return cmdid; |
| } |
| |
| ////////////////////////////////////////////////////////////////////////////////// |
| PVMFCommandId PVFMVideoMIO::DiscardData(PVMFTimestamp aTimestamp, const OsclAny* aContext) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVFMVideoMIO::DiscardData(timestamp,context) called")); |
| |
| OSCL_UNUSED_ARG(aTimestamp); |
| return DiscardData(aContext); |
| } |
| |
| |
| PVMFCommandId PVFMVideoMIO::Stop(const OsclAny* aContext) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVFMVideoMIO::Stop() called")); |
| |
| PVMFCommandId cmdid = iCommandCounter++; |
| |
| PVMFStatus status = PVMFFailure; |
| |
| switch (iState) |
| { |
| case STATE_STARTED: |
| case STATE_PAUSED: |
| iState = STATE_INITIALIZED; |
| status = PVMFSuccess; |
| break; |
| |
| default: |
| status = PVMFErrInvalidState; |
| break; |
| } |
| |
| CommandResponse resp(status, cmdid, aContext); |
| QueueCommandResponse(resp); |
| return cmdid; |
| } |
| |
| |
| PVMFCommandId PVFMVideoMIO::CancelAllCommands(const OsclAny* aContext) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVFMVideoMIO::CancelAllCommands() called")); |
| |
| PVMFCommandId cmdid = iCommandCounter++; |
| |
| // Commands are executed immediately upon being received, so it isn't really possible to cancel them. |
| |
| PVMFStatus status = PVMFSuccess; |
| |
| CommandResponse resp(status, cmdid, aContext); |
| QueueCommandResponse(resp); |
| return cmdid; |
| } |
| |
| |
| PVMFCommandId PVFMVideoMIO::CancelCommand(PVMFCommandId aCmdId, const OsclAny* aContext) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVFMVideoMIO::CancelCommand() called")); |
| |
| PVMFCommandId cmdid = iCommandCounter++; |
| |
| // Commands are executed immediately upon being received, so it isn't really possible to cancel them. |
| |
| // See if the response is still queued. |
| PVMFStatus status = PVMFFailure; |
| for (uint32 i = 0; i < iCommandResponseQueue.size(); i++) |
| { |
| if (iCommandResponseQueue[i].iCmdId == aCmdId) |
| { |
| status = PVMFSuccess; |
| break; |
| } |
| } |
| |
| CommandResponse resp(status, cmdid, aContext); |
| QueueCommandResponse(resp); |
| return cmdid; |
| } |
| |
| |
| void PVFMVideoMIO::ThreadLogon() |
| { |
| if (iState == STATE_IDLE) |
| { |
| iLogger = PVLogger::GetLoggerObject("PVFMVideoMIO"); |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVFMVideoMIO::ThreadLogon() called")); |
| AddToScheduler(); |
| iState = STATE_LOGGED_ON; |
| } |
| } |
| |
| |
| void PVFMVideoMIO::ThreadLogoff() |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVFMVideoMIO::ThreadLogoff() called")); |
| |
| if (iState != STATE_IDLE) |
| { |
| RemoveFromScheduler(); |
| iLogger = NULL; |
| iState = STATE_IDLE; |
| } |
| } |
| |
| |
| void PVFMVideoMIO::setPeer(PvmiMediaTransfer* aPeer) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVFMVideoMIO::setPeer() called")); |
| |
| // Set the observer |
| iPeer = aPeer; |
| } |
| |
| |
| void PVFMVideoMIO::useMemoryAllocators(OsclMemAllocator* write_alloc) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVFMVideoMIO::useMemoryAllocators() called")); |
| |
| OSCL_UNUSED_ARG(write_alloc); |
| |
| // Not supported. |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_INFO, (0, "PVFMVideoMIO::useMemoryAllocators() NOT SUPPORTED")); |
| } |
| |
| |
| PVMFCommandId PVFMVideoMIO::writeAsync(uint8 aFormatType, int32 aFormatIndex, uint8* aData, uint32 aDataLen, |
| const PvmiMediaXferHeader& data_header_info, OsclAny* aContext) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVFMVideoMIO::writeAsync() seqnum %d ts %d context %d", data_header_info.seq_num, data_header_info.timestamp, aContext)); |
| |
| PVMFStatus status = PVMFFailure; |
| |
| // Do a leave if MIO is not configured except when it is an EOS |
| if (!iIsMIOConfigured && |
| !((PVMI_MEDIAXFER_FMT_TYPE_NOTIFICATION == aFormatType) && |
| (PVMI_MEDIAXFER_FMT_INDEX_END_OF_STREAM == aFormatIndex))) |
| { |
| iWriteBusy = true; |
| OSCL_LEAVE(OsclErrInvalidState); |
| return -1; |
| } |
| |
| switch (aFormatType) |
| { |
| case PVMI_MEDIAXFER_FMT_TYPE_COMMAND : |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVFMVideoMIO::writeAsync() called with Command info.")); |
| // Ignore |
| status = PVMFSuccess; |
| break; |
| |
| case PVMI_MEDIAXFER_FMT_TYPE_NOTIFICATION : |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVFMVideoMIO::writeAsync() called with Notification info.")); |
| switch (aFormatIndex) |
| { |
| case PVMI_MEDIAXFER_FMT_INDEX_END_OF_STREAM: |
| // If waiting for frame then return errMaxReached |
| if (iFrameRetrievalInfo.iRetrievalRequested) |
| { |
| iFrameRetrievalInfo.iRetrievalRequested = false; |
| iFrameRetrievalInfo.iUseFrameIndex = false; |
| iFrameRetrievalInfo.iUseTimeOffset = false; |
| iFrameRetrievalInfo.iGetFrameObserver->HandleFrameReadyEvent(PVMFErrMaxReached); |
| } |
| break; |
| |
| default: |
| break; |
| } |
| // Ignore |
| status = PVMFSuccess; |
| break; |
| |
| case PVMI_MEDIAXFER_FMT_TYPE_DATA : |
| switch (aFormatIndex) |
| { |
| case PVMI_MEDIAXFER_FMT_INDEX_FMT_SPECIFIC_INFO: |
| // Format-specific info contains codec headers. |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVFMVideoMIO::writeAsync() called with format-specific info.")); |
| |
| if (iState < STATE_INITIALIZED) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_REL, iLogger, PVLOGMSG_ERR, (0, "PVFMVideoMIO::writeAsync: Error - Invalid state")); |
| iWriteBusy = true; |
| OSCL_LEAVE(OsclErrInvalidState); |
| return -1; |
| } |
| else |
| { |
| if (aDataLen > 0) |
| { |
| status = PVMFSuccess; |
| } |
| else |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_INFO, (0, "PVFMVideoMIO::writeAsync() called aDataLen==0.")); |
| status = PVMFSuccess; |
| } |
| } |
| break; |
| |
| case PVMI_MEDIAXFER_FMT_INDEX_DATA: |
| // Data contains the media bitstream. |
| |
| // Verify the state |
| if (iState != STATE_STARTED) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_REL, iLogger, PVLOGMSG_ERR, (0, "PVFMVideoMIO::writeAsync: Error - Invalid state")); |
| iWriteBusy = true; |
| OSCL_LEAVE(OsclErrInvalidState); |
| return -1; |
| } |
| else |
| { |
| if (iFrameRetrievalInfo.iRetrievalRequested) |
| { |
| if (iFrameRetrievalInfo.iUseFrameIndex) |
| { |
| ++iFrameRetrievalInfo.iReceivedFrameCount; |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVFMVideoMIO::writeAsync() Received frames %d", iFrameRetrievalInfo.iReceivedFrameCount)); |
| } |
| else if (iFrameRetrievalInfo.iUseTimeOffset && iFrameRetrievalInfo.iStartingTSSet == false) |
| { |
| iFrameRetrievalInfo.iStartingTSSet = true; |
| iFrameRetrievalInfo.iStartingTS = data_header_info.timestamp; |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVFMVideoMIO::writeAsync() Starting timestamp set %d", iFrameRetrievalInfo.iStartingTS)); |
| } |
| } |
| |
| if (aDataLen > 0) |
| { |
| // Check if a frame retrieval was requested |
| if (iFrameRetrievalInfo.iRetrievalRequested) |
| { |
| |
| // scale down output proportionally if smaller thumbnail requested |
| if (iVideoDisplayWidth > iThumbnailWidth || iVideoDisplayHeight > iThumbnailHeight) |
| { |
| |
| float fScaleWidth = (float)iThumbnailWidth / iVideoDisplayWidth; |
| float fScaleHeight = (float)iThumbnailHeight / iVideoDisplayHeight; |
| float fScale = (fScaleWidth > fScaleHeight) ? fScaleHeight : fScaleWidth; |
| iVideoDisplayWidth = (uint32)(iVideoDisplayWidth * fScale); |
| iVideoDisplayHeight = (uint32)(iVideoDisplayHeight * fScale); |
| |
| // It is possible that width and height becomes odd numbers after |
| // scaling them down. These values might be used by ColorConverter |
| // for ColorConversion which expects even parameters. Make these |
| // parameters multiple of 2. |
| iVideoDisplayWidth = ((iVideoDisplayWidth + 1) & (~1)); |
| iVideoDisplayHeight = ((iVideoDisplayHeight + 1) & (~1)); |
| } |
| |
| if (iFrameRetrievalInfo.iUseFrameIndex == true && |
| iFrameRetrievalInfo.iReceivedFrameCount > iFrameRetrievalInfo.iFrameIndex) |
| { |
| PVMFStatus evstatus = PVMFFailure; |
| // Copy the frame data |
| evstatus = CopyVideoFrameData(aData, aDataLen, iVideoFormat, |
| iFrameRetrievalInfo.iFrameBuffer, *(iFrameRetrievalInfo.iBufferSize), iFrameRetrievalInfo.iFrameFormatType, |
| iVideoWidth, iVideoHeight, iVideoDisplayWidth, iVideoDisplayHeight); |
| |
| iFrameRetrievalInfo.iRetrievalRequested = false; |
| iFrameRetrievalInfo.iUseFrameIndex = false; |
| iFrameRetrievalInfo.iUseTimeOffset = false; |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVFMVideoMIO::writeAsync() Retrieved requested frame by frame index(%d) Status %d", iFrameRetrievalInfo.iFrameIndex, evstatus)); |
| iFrameRetrievalInfo.iGetFrameObserver->HandleFrameReadyEvent(evstatus); |
| } |
| else if (iFrameRetrievalInfo.iUseTimeOffset == true && |
| iFrameRetrievalInfo.iStartingTSSet == true && |
| (data_header_info.timestamp - iFrameRetrievalInfo.iStartingTS) >= iFrameRetrievalInfo.iTimeOffset) |
| { |
| PVMFStatus evstatus = PVMFFailure; |
| |
| // Copy the frame data |
| evstatus = CopyVideoFrameData(aData, aDataLen, iVideoFormat, |
| iFrameRetrievalInfo.iFrameBuffer, *(iFrameRetrievalInfo.iBufferSize), iFrameRetrievalInfo.iFrameFormatType, |
| iVideoWidth, iVideoHeight, iVideoDisplayWidth, iVideoDisplayHeight); |
| |
| iFrameRetrievalInfo.iRetrievalRequested = false; |
| iFrameRetrievalInfo.iUseFrameIndex = false; |
| iFrameRetrievalInfo.iUseTimeOffset = false; |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVFMVideoMIO::writeAsync() Retrieved requested frame by time(%d) Actual TS %d Status %d", iFrameRetrievalInfo.iTimeOffset, data_header_info.timestamp, evstatus)); |
| iFrameRetrievalInfo.iGetFrameObserver->HandleFrameReadyEvent(evstatus); |
| } |
| } |
| |
| status = PVMFSuccess; |
| } |
| else |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_INFO, (0, "PVFMVideoMIO::writeAsync() called aDataLen==0.")); |
| status = PVMFSuccess; |
| } |
| } |
| break; |
| |
| default: |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_REL, iLogger, PVLOGMSG_ERR, (0, "PVFMVideoMIO::writeAsync: Error - unrecognized format index")); |
| status = PVMFFailure; |
| break; |
| } |
| break; |
| |
| default: |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_REL, iLogger, PVLOGMSG_ERR, (0, "PVFMVideoMIO::writeAsync: Error - unrecognized format type")); |
| status = PVMFFailure; |
| break; |
| } |
| |
| //Schedule asynchronous response |
| PVMFCommandId cmdid = iCommandCounter++; |
| WriteResponse resp(status, cmdid, aContext, data_header_info.timestamp); |
| iWriteResponseQueue.push_back(resp); |
| RunIfNotReady(); |
| return cmdid; |
| |
| } |
| |
| |
| PVMFStatus PVFMVideoMIO::CopyVideoFrameData(uint8* aSrcBuffer, uint32 aSrcSize, PVMFFormatType aSrcFormat, |
| uint8* aDestBuffer, uint32& aDestSize, PVMFFormatType aDestFormat, |
| uint32 aSrcWidth, uint32 aSrcHeight, uint32 aDestWidth, uint32 aDestHeight) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVFMVideoMIO::CopyVideoFrameData() In")); |
| |
| if (aSrcBuffer == NULL || aSrcSize == 0 || aSrcFormat == PVMF_MIME_FORMAT_UNKNOWN || |
| aDestBuffer == NULL || aDestSize == 0 || aDestFormat == PVMF_MIME_FORMAT_UNKNOWN) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVFMVideoMIO::CopyVideoFrameData() bad input arguments.")); |
| return PVMFErrArgument; |
| } |
| |
| if ((iVideoSubFormat == PVMF_MIME_YUV422_INTERLEAVED_UYVY) && |
| (aDestFormat == PVMF_MIME_YUV420)) |
| { |
| // Source is YUV 4:2:2 and dest is YUV 4:2:0 |
| |
| PVMFStatus status; |
| uint32 yuvbufsize; |
| if (!iYUV422toYUV420ColorConvert) |
| { |
| status = CreateYUV422toYUV420ColorConvert(); |
| if (status != PVMFSuccess) |
| { |
| // Failed to create the CC! |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVFMVideoMIO::CopyVideoFrameData() Failed to create iYUV422toYUV420ColorConvert.")); |
| return status; |
| } |
| } |
| |
| // Init CC |
| status = InitYUV422toYUV420ColorConvert(aSrcWidth, aSrcHeight, aSrcWidth, aSrcHeight); |
| if (status != PVMFSuccess) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVFMVideoMIO::CopyVideoFrameData() iYUV422toYUV420ColorConvert Init failed")); |
| return status; |
| } |
| |
| yuvbufsize = (uint32)(iYUV422toYUV420ColorConvert->GetOutputBufferSize()); |
| |
| // Is the CC destination buffer smaller that the expected destination buffer size? |
| if (yuvbufsize > aDestSize) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVFMVideoMIO::CopyVideoFrameData() Specified output YUV buffer does not have enough space. Needed %d Available %d.", yuvbufsize, aDestSize)); |
| return PVMFErrResource; |
| } |
| |
| // Convert |
| if (iYUV422toYUV420ColorConvert->Convert(aSrcBuffer, aDestBuffer) == 0) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVFMVideoMIO::CopyVideoFrameData() YUV Color conversion failed")); |
| return PVMFErrResource; |
| } |
| |
| // Save the YUV frame size |
| aDestSize = yuvbufsize; |
| } |
| else if (aSrcFormat == aDestFormat) |
| { |
| // Same format so direct copy |
| if (aDestSize < aSrcSize) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVFMVideoMIO::CopyVideoFrameData() destination and source size differ")); |
| return PVMFErrArgument; |
| } |
| |
| if (iVideoSubFormat == PVMF_MIME_YUV420_SEMIPLANAR_YVU) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, |
| (0, "PVFMVideoMIO::CopyVideoFrameData() SubFormat is YUV SemiPlanar, Convert to YUV planar first")); |
| convertYUV420SPtoYUV420(aSrcBuffer, aDestBuffer, aSrcSize); |
| } |
| else |
| { |
| oscl_memcpy(aDestBuffer, aSrcBuffer, aSrcSize); |
| } |
| aDestSize = aSrcSize; |
| } |
| else if (aSrcFormat == PVMF_MIME_YUV420 && |
| (aDestFormat == PVMF_MIME_RGB12 || aDestFormat == PVMF_MIME_RGB16 || aDestFormat == PVMF_MIME_RGB24)) |
| { |
| // Source is YUV 4:2:0 and dest is RGB 12, 16, or 24 bit |
| |
| // Validate the source and dest dimensions |
| if (aSrcWidth == 0 || aSrcHeight == 0 || aDestWidth == 0 || aDestHeight == 0) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVFMVideoMIO::CopyVideoFrameData() Invalid frame dimensions Src(WxH): %dx%d Dest(WxH): %dx%d", |
| aSrcWidth, aSrcHeight, aDestWidth, aDestHeight)); |
| return PVMFErrArgument; |
| } |
| |
| // Check if the proper color converter is available |
| if (iColorConverter && iCCRGBFormatType != aDestFormat) |
| { |
| DestroyYUVToRGBColorConverter(iColorConverter, iCCRGBFormatType); |
| iCCRGBFormatType = PVMF_MIME_FORMAT_UNKNOWN; |
| } |
| |
| // Instantiate a new color converter if needed |
| if (iColorConverter == NULL) |
| { |
| PVMFStatus retval = CreateYUVToRGBColorConverter(iColorConverter, aDestFormat); |
| if (retval != PVMFSuccess) |
| { |
| // Color converter could not be instantiated |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVFMVideoMIO::CopyVideoFrameData() Appropriate YUV to RGB color converter could not be instantiated")); |
| return retval; |
| } |
| iCCRGBFormatType = aDestFormat; |
| } |
| |
| if (!(iColorConverter->Init((aSrcWidth + 1)&(~1), (aSrcHeight + 1)&(~1), (aSrcWidth + 1)&(~1), aDestWidth, (aDestHeight + 1)&(~1), (aDestWidth + 1)&(~1), CCROTATE_NONE))) |
| { |
| // Color converter failed Init |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVFMVideoMIO::CopyVideoFrameData() iColorConverter failed init.")); |
| return PVMFFailure; |
| } |
| |
| |
| iColorConverter->SetMemHeight((iVideoHeight + 1)&(~1)); |
| iColorConverter->SetMode(1); // Do scaling if needed. |
| |
| uint32 rgbbufsize = (uint32)(iColorConverter->GetOutputBufferSize()); |
| if (rgbbufsize > aDestSize) |
| { |
| // Specified buffer does not have enough space |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVFMVideoMIO::CopyVideoFrameData() Specified output RGB buffer does not have enough space. Needed %d Available %d", rgbbufsize, aDestSize)); |
| return PVMFErrResource; |
| } |
| |
| // Do the color conversion |
| if (iColorConverter->Convert(aSrcBuffer, aDestBuffer) == 0) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVFMVideoMIO::CopyVideoFrameData() Color conversion failed")); |
| return PVMFErrResource; |
| } |
| // Save the RGB frame size |
| aDestSize = rgbbufsize; |
| } |
| else |
| { |
| // Other conversions not supported yet |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVFMVideoMIO::CopyVideoFrameData() Unsupported conversion mode.")); |
| return PVMFErrNotSupported; |
| } |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVFMVideoMIO::CopyVideoFrameData() Out")); |
| return PVMFSuccess; |
| } |
| |
| |
| void PVFMVideoMIO::writeComplete(PVMFStatus aStatus, PVMFCommandId write_cmd_id, OsclAny* aContext) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVFMVideoMIO::writeComplete() called")); |
| |
| OSCL_UNUSED_ARG(aStatus); |
| OSCL_UNUSED_ARG(write_cmd_id); |
| OSCL_UNUSED_ARG(aContext); |
| |
| // Won't be called since this component is a sink. |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_INFO, (0, "PVFMVideoMIO::writeComplete() Should not be called since this MIO is a sink")); |
| } |
| |
| |
| PVMFCommandId PVFMVideoMIO::readAsync(uint8* data, uint32 max_data_len, OsclAny* aContext, int32* formats, uint16 num_formats) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVFMVideoMIO::readAsync() called")); |
| |
| OSCL_UNUSED_ARG(data); |
| OSCL_UNUSED_ARG(max_data_len); |
| OSCL_UNUSED_ARG(aContext); |
| OSCL_UNUSED_ARG(formats); |
| OSCL_UNUSED_ARG(num_formats); |
| |
| // Read not supported. |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_INFO, (0, "PVFMVideoMIO::readAsync() NOT SUPPORTED")); |
| OsclError::Leave(OsclErrNotSupported); |
| return -1; |
| } |
| |
| |
| void PVFMVideoMIO::readComplete(PVMFStatus aStatus, PVMFCommandId read_cmd_id, int32 format_index, |
| const PvmiMediaXferHeader& data_header_info, OsclAny* aContext) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVFMVideoMIO::readComplete() called")); |
| |
| OSCL_UNUSED_ARG(aStatus); |
| OSCL_UNUSED_ARG(read_cmd_id); |
| OSCL_UNUSED_ARG(format_index); |
| OSCL_UNUSED_ARG(data_header_info); |
| OSCL_UNUSED_ARG(aContext); |
| |
| // Won't be called since this component is a sink. |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_INFO, (0, "PVFMVideoMIO::readComplete() Should not be called since this MIO is a sink")); |
| } |
| |
| |
| void PVFMVideoMIO::statusUpdate(uint32 status_flags) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVFMVideoMIO::statusUpdate() called")); |
| |
| OSCL_UNUSED_ARG(status_flags); |
| |
| // Won't be called since this component is a sink. |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_INFO, (0, "PVFMVideoMIO::statusUpdate() Should not be called since this MIO is a sink")); |
| } |
| |
| |
| void PVFMVideoMIO::cancelCommand(PVMFCommandId command_id) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVFMVideoMIO::cancelCommand() called")); |
| |
| // The purpose of this API is to cancel a writeAsync command and report completion ASAP. |
| |
| // In this implementation, the write commands are executed immediately when received so it isn't |
| // really possible to cancel. Just report completion immediately. |
| |
| for (uint32 i = 0; i < iWriteResponseQueue.size(); i++) |
| { |
| if (iWriteResponseQueue[i].iCmdId == command_id) |
| { |
| //report completion |
| if (iPeer) |
| { |
| iPeer->writeComplete(iWriteResponseQueue[i].iStatus, iWriteResponseQueue[i].iCmdId, (OsclAny*)iWriteResponseQueue[i].iContext); |
| } |
| iWriteResponseQueue.erase(&iWriteResponseQueue[i]); |
| break; |
| } |
| } |
| } |
| |
| |
| void PVFMVideoMIO::cancelAllCommands() |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVFMVideoMIO::cancelAllCommands() called")); |
| |
| // The purpose of this API is to cancel all writeAsync commands and report completion ASAP. |
| |
| // In this implementaiton, the write commands are executed immediately when received so it isn't |
| // really possible to cancel. Just report completion immediately. |
| |
| for (uint32 i = 0; i < iWriteResponseQueue.size(); i++) |
| { |
| //report completion |
| if (iPeer) |
| { |
| iPeer->writeComplete(iWriteResponseQueue[i].iStatus, iWriteResponseQueue[i].iCmdId, (OsclAny*)iWriteResponseQueue[i].iContext); |
| } |
| iWriteResponseQueue.erase(&iWriteResponseQueue[i]); |
| } |
| } |
| |
| |
| void PVFMVideoMIO::setObserver(PvmiConfigAndCapabilityCmdObserver* aObserver) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVFMVideoMIO::setObserver() called")); |
| |
| OSCL_UNUSED_ARG(aObserver); |
| |
| // Not needed since this component only supports synchronous capability & config APIs. |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_INFO, (0, "PVFMVideoMIO::setObserver() NOT SUPPORTED")); |
| } |
| |
| |
| PVMFStatus PVFMVideoMIO::getParametersSync(PvmiMIOSession aSession, PvmiKeyType aIdentifier, PvmiKvp*& aParameters, |
| int& num_parameter_elements, PvmiCapabilityContext aContext) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVFMVideoMIO::getParametersSync() called")); |
| |
| OSCL_UNUSED_ARG(aSession); |
| OSCL_UNUSED_ARG(aContext); |
| |
| aParameters = NULL; |
| num_parameter_elements = 0; |
| |
| if (pv_mime_strcmp(aIdentifier, MOUT_VIDEO_FORMAT_KEY) == 0) |
| { |
| //query for video format string |
| aParameters = (PvmiKvp*)oscl_malloc(sizeof(PvmiKvp)); |
| aParameters->value.pChar_value = (char*)iVideoFormat.getMIMEStrPtr(); |
| //don't bother to set the key string. |
| return PVMFSuccess; |
| } |
| |
| else if (pv_mime_strcmp(aIdentifier, INPUT_FORMATS_CAP_QUERY) == 0) |
| { |
| // This is a query for the list of supported formats. |
| // This component supports all uncompressed video format |
| // Generate a list of all the PVMF video formats... |
| int32 count = iInputFormatCapability.size(); |
| |
| aParameters = (PvmiKvp*)oscl_malloc(count * sizeof(PvmiKvp)); |
| |
| if (aParameters) |
| { |
| num_parameter_elements = 0; |
| Oscl_Vector<PVMFFormatType, OsclMemAllocator>::iterator it; |
| for (it = iInputFormatCapability.begin(); it != iInputFormatCapability.end(); it++) |
| { |
| aParameters[num_parameter_elements++].value.pChar_value = OSCL_STATIC_CAST(char*, it->getMIMEStrPtr()); |
| } |
| return PVMFSuccess; |
| } |
| return PVMFErrNoMemory; |
| } |
| |
| // Other queries are not currently supported so report as unrecognized key. |
| return PVMFFailure; |
| } |
| |
| |
| PVMFStatus PVFMVideoMIO::releaseParameters(PvmiMIOSession aSession, PvmiKvp* aParameters, int num_elements) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVFMVideoMIO::releaseParameters() called")); |
| |
| OSCL_UNUSED_ARG(aSession); |
| OSCL_UNUSED_ARG(num_elements); |
| |
| // Release parameters that were allocated by this component. |
| if (aParameters) |
| { |
| oscl_free(aParameters); |
| return PVMFSuccess; |
| } |
| return PVMFFailure; |
| } |
| |
| |
| void PVFMVideoMIO::createContext(PvmiMIOSession aSession, PvmiCapabilityContext& aContext) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVFMVideoMIO::createContext() called")); |
| |
| OSCL_UNUSED_ARG(aSession); |
| OSCL_UNUSED_ARG(aContext); |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_INFO, (0, "PVFMVideoMIO::createContext() NOT SUPPORTED")); |
| OsclError::Leave(OsclErrNotSupported); |
| } |
| |
| |
| void PVFMVideoMIO::setContextParameters(PvmiMIOSession aSession, PvmiCapabilityContext& aContext, |
| PvmiKvp* aParameters, int num_parameter_elements) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVFMVideoMIO::setContextParameters() called")); |
| |
| OSCL_UNUSED_ARG(aSession); |
| OSCL_UNUSED_ARG(aContext); |
| OSCL_UNUSED_ARG(aParameters); |
| OSCL_UNUSED_ARG(num_parameter_elements); |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_INFO, (0, "PVFMVideoMIO::setContextParameters() NOT SUPPORTED")); |
| OsclError::Leave(OsclErrNotSupported); |
| } |
| |
| |
| void PVFMVideoMIO::DeleteContext(PvmiMIOSession aSession, PvmiCapabilityContext& aContext) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVFMVideoMIO::DeleteContext() called")); |
| |
| OSCL_UNUSED_ARG(aSession); |
| OSCL_UNUSED_ARG(aContext); |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_INFO, (0, "PVFMVideoMIO::DeleteContext() NOT SUPPORTED")); |
| OsclError::Leave(OsclErrNotSupported); |
| } |
| |
| |
| void PVFMVideoMIO::setParametersSync(PvmiMIOSession aSession, PvmiKvp* aParameters, int num_elements, PvmiKvp*& aRet_kvp) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVFMVideoMIO::setParametersSync() called")); |
| |
| OSCL_UNUSED_ARG(aSession); |
| |
| aRet_kvp = NULL; |
| |
| for (int32 i = 0; i < num_elements; i++) |
| { |
| //Check against known video parameter keys... |
| if (pv_mime_strcmp(aParameters[i].key, MOUT_VIDEO_FORMAT_KEY) == 0) |
| { |
| iVideoFormat = aParameters[i].value.pChar_value; |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVFMVideoMIO::setParametersSync() Video Format Key, Value %s", iVideoFormat.getMIMEStrPtr())); |
| } |
| else if (pv_mime_strcmp(aParameters[i].key, MOUT_VIDEO_WIDTH_KEY) == 0) |
| { |
| iVideoWidth = (int32)aParameters[i].value.uint32_value; |
| iVideoWidthValid = true; |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVFMVideoMIO::setParametersSync() Video Width Key, Value %d", iVideoWidth)); |
| } |
| else if (pv_mime_strcmp(aParameters[i].key, MOUT_VIDEO_HEIGHT_KEY) == 0) |
| { |
| iVideoHeight = (int32)aParameters[i].value.uint32_value; |
| iVideoHeightValid = true; |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVFMVideoMIO::setParametersSync() Video Height Key, Value %d", iVideoHeight)); |
| } |
| else if (pv_mime_strcmp(aParameters[i].key, MOUT_VIDEO_DISPLAY_HEIGHT_KEY) == 0) |
| { |
| iVideoDisplayHeight = (int32)aParameters[i].value.uint32_value; |
| iVideoDisplayHeightValid = true; |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVFMVideoMIO::setParametersSync() Video Display Height Key, Value %d", iVideoDisplayHeight)); |
| } |
| else if (pv_mime_strcmp(aParameters[i].key, MOUT_VIDEO_DISPLAY_WIDTH_KEY) == 0) |
| { |
| iVideoDisplayWidth = (int32)aParameters[i].value.uint32_value; |
| iVideoDisplayWidthValid = true; |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVFMVideoMIO::setParametersSync() Video Display Width Key, Value %d", iVideoDisplayWidth)); |
| } |
| else if (pv_mime_strcmp(aParameters[i].key, PVMF_FORMAT_SPECIFIC_INFO_KEY) == 0) |
| { |
| // iOutputFile.Write(aParameters[i].value.pChar_value, sizeof(uint8), (int32)aParameters[i].capacity); |
| } |
| else if (pv_mime_strcmp(aParameters[i].key, MOUT_VIDEO_SUBFORMAT_KEY) == 0) |
| { |
| iVideoSubFormat = aParameters[i].value.pChar_value; |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, |
| (0, "PVFMVideoMIO::setParametersSync() Video SubFormat Key, Value %s", iVideoSubFormat.getMIMEStrPtr())); |
| } |
| else |
| { |
| if (iVideoWidthValid && iVideoHeightValid && iVideoDisplayHeightValid && iVideoDisplayHeightValid && !iIsMIOConfigured) |
| { |
| if (iObserver) |
| { |
| iIsMIOConfigured = true; |
| iObserver->ReportInfoEvent(PVMFMIOConfigurationComplete); |
| if (iPeer && iWriteBusy) |
| { |
| iWriteBusy = false; |
| iPeer->statusUpdate(PVMI_MEDIAXFER_STATUS_WRITE); |
| } |
| } |
| } |
| |
| // If we get here the key is unrecognized. |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVFMVideoMIO::setParametersSync() Error, unrecognized key ")); |
| |
| // Set the return value to indicate the unrecognized key and return. |
| aRet_kvp = &aParameters[i]; |
| return; |
| } |
| } |
| if (iVideoWidthValid && iVideoHeightValid && iVideoDisplayHeightValid && iVideoDisplayHeightValid && !iIsMIOConfigured) |
| { |
| if (iObserver) |
| { |
| iIsMIOConfigured = true; |
| iObserver->ReportInfoEvent(PVMFMIOConfigurationComplete); |
| if (iPeer && iWriteBusy) |
| { |
| iWriteBusy = false; |
| iPeer->statusUpdate(PVMI_MEDIAXFER_STATUS_WRITE); |
| } |
| } |
| } |
| } |
| |
| |
| PVMFCommandId PVFMVideoMIO::setParametersAsync(PvmiMIOSession aSession, PvmiKvp* aParameters, int num_elements, PvmiKvp*& aRet_kvp, OsclAny* context) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVFMVideoMIO::setParametersAsync() called")); |
| |
| OSCL_UNUSED_ARG(aSession); |
| OSCL_UNUSED_ARG(aParameters); |
| OSCL_UNUSED_ARG(num_elements); |
| OSCL_UNUSED_ARG(aRet_kvp); |
| OSCL_UNUSED_ARG(context); |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_INFO, (0, "PVFMVideoMIO::setParamaetersAsync() NOT SUPPORTED")); |
| OsclError::Leave(OsclErrNotSupported); |
| return -1; |
| } |
| |
| |
| uint32 PVFMVideoMIO::getCapabilityMetric(PvmiMIOSession aSession) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVFMVideoMIO::getCapabilityMetric() called")); |
| |
| OSCL_UNUSED_ARG(aSession); |
| |
| return 0; |
| } |
| |
| |
| PVMFStatus PVFMVideoMIO::verifyParametersSync(PvmiMIOSession aSession, PvmiKvp* aParameters, int num_elements) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVFMVideoMIO::verifyParametersSync() called")); |
| |
| OSCL_UNUSED_ARG(aSession); |
| |
| // Go through each parameter |
| for (int32 paramind = 0; paramind < num_elements; ++paramind) |
| { |
| // Retrieve the first component from the key string |
| char* compstr = NULL; |
| pv_mime_string_extract_type(0, aParameters[paramind].key, compstr); |
| |
| if (pv_mime_strcmp(compstr, _STRLIT_CHAR("x-pvmf/media/format-type")) == 0) |
| { |
| //This component supports only uncompressed formats |
| Oscl_Vector<PVMFFormatType, OsclMemAllocator>::iterator it; |
| for (it = iInputFormatCapability.begin(); it != iInputFormatCapability.end(); it++) |
| { |
| if (pv_mime_strcmp(aParameters[paramind].value.pChar_value, it->getMIMEStrPtr()) == 0) |
| { |
| return PVMFSuccess; |
| } |
| } |
| // Not found on the list of supported input formats |
| return PVMFErrNotSupported; |
| } |
| } |
| // For all other parameters return success. |
| return PVMFSuccess; |
| } |
| |
| |
| // |
| // For active timing support |
| // |
| PVMFStatus PVFMVideoMIOActiveTimingSupport::SetClock(PVMFMediaClock *clockVal) |
| { |
| iClock = clockVal; |
| return PVMFSuccess; |
| } |
| |
| |
| void PVFMVideoMIOActiveTimingSupport::addRef() |
| { |
| } |
| |
| |
| void PVFMVideoMIOActiveTimingSupport::removeRef() |
| { |
| } |
| |
| |
| bool PVFMVideoMIOActiveTimingSupport::queryInterface(const PVUuid& aUuid, PVInterface*& aInterface) |
| { |
| aInterface = NULL; |
| PVUuid uuid; |
| queryUuid(uuid); |
| if (uuid == aUuid) |
| { |
| PvmiClockExtensionInterface* myInterface = OSCL_STATIC_CAST(PvmiClockExtensionInterface*, this); |
| aInterface = OSCL_STATIC_CAST(PVInterface*, myInterface); |
| return true; |
| } |
| return false; |
| } |
| |
| |
| void PVFMVideoMIOActiveTimingSupport::queryUuid(PVUuid& uuid) |
| { |
| uuid = PvmiClockExtensionInterfaceUuid; |
| } |
| |
| |
| // |
| // Private section |
| // |
| void PVFMVideoMIO::Run() |
| { |
| // Send async command responses |
| while (!iCommandResponseQueue.empty()) |
| { |
| if (iObserver) |
| { |
| iObserver->RequestCompleted(PVMFCmdResp(iCommandResponseQueue[0].iCmdId, iCommandResponseQueue[0].iContext, iCommandResponseQueue[0].iStatus)); |
| } |
| iCommandResponseQueue.erase(&iCommandResponseQueue[0]); |
| } |
| |
| // Send async write completion |
| while (!iWriteResponseQueue.empty()) |
| { |
| // Report write complete |
| if (iPeer) |
| { |
| iPeer->writeComplete(iWriteResponseQueue[0].iStatus, iWriteResponseQueue[0].iCmdId, (OsclAny*)iWriteResponseQueue[0].iContext); |
| } |
| iWriteResponseQueue.erase(&iWriteResponseQueue[0]); |
| } |
| } |
| |
| static inline void* byteOffset(void* p, uint32 offset) |
| { |
| return (void*)((uint8*)p + offset); |
| } |
| |
| // convert a frame in YUV420 semiplanar format with VU ordering to YUV420 planar format |
| void PVFMVideoMIO::convertYUV420SPtoYUV420(void* src, void* dst, uint32 len) |
| { |
| // copy the Y plane |
| uint32 y_plane_size = iVideoWidth * iVideoHeight; |
| memcpy(dst, src, y_plane_size + iVideoWidth); |
| |
| // re-arrange U's and V's |
| uint32* p = (uint32*)byteOffset(src, y_plane_size); |
| uint16* pu = (uint16*)byteOffset(dst, y_plane_size); |
| uint16* pv = (uint16*)byteOffset(pu, y_plane_size / 4); |
| |
| int count = y_plane_size / 8; |
| do |
| { |
| uint32 uvuv = *p++; |
| *pu++ = (uint16)(((uvuv >> 8) & 0xff) | ((uvuv >> 16) & 0xff00)); |
| *pv++ = (uint16)((uvuv & 0xff) | ((uvuv >> 8) & 0xff00)); |
| } |
| while (--count); |
| } |
| |
| PVMFStatus PVFMVideoMIO::CreateYUV422toYUV420ColorConvert() |
| { |
| int32 leavecode = 0; |
| OSCL_TRY(leavecode, iYUV422toYUV420ColorConvert = (CCYUV422toYUV420*) CCYUV422toYUV420::New()); |
| |
| OSCL_FIRST_CATCH_ANY(leavecode, |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVFMVideoMIO::CreateYUV422toYUV420ColorConvert() YUV Color converter instantiation did a leave")); |
| return PVMFErrNoResources; |
| ); |
| return PVMFSuccess; |
| } |
| |
| PVMFStatus PVFMVideoMIO::InitYUV422toYUV420ColorConvert(uint32 aSrcWidth, uint32 aSrcHeight, uint32 aDestWidth, uint32 aDestHeight) |
| { |
| if (!(iYUV422toYUV420ColorConvert->Init((aSrcWidth + 1)&(~1), (aSrcHeight + 1)&(~1), |
| (aSrcWidth + 1)&(~1),(aDestWidth + 1)&(~1), (aDestHeight + 1)&(~1), |
| (aDestWidth + 1)&(~1), CCROTATE_NONE))) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVFMVideoMIO::InitYUV422toYUV420ColorConvert: YUV Color converter Init failed")); |
| return PVMFFailure; |
| } |
| return PVMFSuccess; |
| } |
| |
| void PVFMVideoMIO::DestroyYUV422toYUV420ColorConvert() |
| { |
| OSCL_DELETE(iYUV422toYUV420ColorConvert); |
| iYUV422toYUV420ColorConvert = NULL; |
| } |
| |