blob: cf9345f0710d6d921a07f0e4be25efb15d2c8934 [file] [log] [blame]
/* ------------------------------------------------------------------
* 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.
* -------------------------------------------------------------------
*/
/**
*
* @file pvmf_loopback_ioport.h
* @brief Input/Output port for simple loopback node
*
*/
#include "oscl_mem_basic_functions.h"
#include "pv_mime_string_utils.h"
#include "pvmf_node_interface.h"
#ifndef PVMF_LOOPBACK_IOPORT_H_INCLUDED
#include "pvmf_loopback_ioport.h"
#endif
#ifndef PVMF_LOOPBACK_NODE_H_INCLUDED
#include "pvmf_loopback_node.h"
#endif
#include "pvlogger.h"
#include "oscl_tickcount.h"
////////////////////////////////////////////////////////////////////////////
PVMFLoopbackIOPort::PVMFLoopbackIOPort(int32 aTag, PVMFLoopbackNode* aNode)
: PvmfPortBaseImpl(aTag, this)
, OsclActiveObject(OsclActiveObject::EPriorityNominal, "PVMFLoopbackPort")
{
Construct(aNode);
}
////////////////////////////////////////////////////////////////////////////
PVMFLoopbackIOPort::PVMFLoopbackIOPort(int32 aTag, PVMFLoopbackNode* aNode
, uint32 aInCapacity
, uint32 aInReserve
, uint32 aInThreshold
, uint32 aOutCapacity
, uint32 aOutReserve
, uint32 aOutThreshold)
: PvmfPortBaseImpl(aTag, this, aInCapacity, aInReserve, aInThreshold, aOutCapacity, aOutReserve, aOutThreshold)
, OsclActiveObject(OsclActiveObject::EPriorityNominal, "PVMFLoopbackPort")
{
Construct(aNode);
}
////////////////////////////////////////////////////////////////////////////
void PVMFLoopbackIOPort::Construct(PVMFLoopbackNode*aNode)
{
iNode = aNode;
iWaiting = false;
iLogger = PVLogger::GetLoggerObject("PVMFLoopbackPort");
PvmiCapabilityAndConfigPortFormatImpl::Construct(
PVMF_LOOPBACK_PORT_INPUT_FORMATS
, PVMF_LOOPBACK_PORT_INPUT_FORMATS_VALTYPE);
AddToScheduler();
}
////////////////////////////////////////////////////////////////////////////
PVMFLoopbackIOPort::~PVMFLoopbackIOPort()
{
Disconnect();
Reset();
if (IsAdded())
RemoveFromScheduler();
}
////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
bool PVMFLoopbackIOPort::IsFormatSupported(PVMFFormatType aFmt)
{
OSCL_UNUSED_ARG(aFmt);
return true;
}
////////////////////////////////////////////////////////////////////////////
void PVMFLoopbackIOPort::FormatUpdated()
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_MLDBG, iLogger, PVLOGMSG_INFO
, (0, "PVMFLoopbackPort::FormatUpdated %s", iFormat.getMIMEStrPtr()));
}
////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////
void PVMFLoopbackIOPort::HandlePortActivity(const PVMFPortActivity &aActivity)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
(0, "0x%x PVMFLoopbackPort::PortActivity: port=0x%x, type=%d",
this, aActivity.iPort, aActivity.iType));
//A port is reporting some activity or state change. This code
//figures out whether we need to queue a processing event
//for the AO, and/or report a node event to the observer.
switch (aActivity.iType)
{
case PVMF_PORT_ACTIVITY_CREATED:
break;
case PVMF_PORT_ACTIVITY_DELETED:
break;
case PVMF_PORT_ACTIVITY_CONNECT:
//nothing needed.
break;
case PVMF_PORT_ACTIVITY_DISCONNECT:
//nothing needed.
break;
case PVMF_PORT_ACTIVITY_OUTGOING_MSG:
//An outgoing message was queued on this port.
//Wakeup the AO on the first message only-- after
//that it re-schedules itself as needed.
if (aActivity.iPort->OutgoingMsgQueueSize() == 1)
RunIfNotReady();
break;
case PVMF_PORT_ACTIVITY_INCOMING_MSG:
//An incoming message was queued on this port.
//Wakeup the AO on the first message only-- after
//that it re-schedules itself as needed.
if (aActivity.iPort->IncomingMsgQueueSize() == 1)
RunIfNotReady();
break;
case PVMF_PORT_ACTIVITY_OUTGOING_QUEUE_BUSY:
//Outgoing queue is now busy.
//No action is needed here-- the node checks for
//outgoing queue busy as needed during data processing.
break;
case PVMF_PORT_ACTIVITY_OUTGOING_QUEUE_READY:
//the loopback port may be waiting on this event.
if (iWaiting)
{
iWaiting = false;
RunIfNotReady();
}
break;
case PVMF_PORT_ACTIVITY_CONNECTED_PORT_BUSY:
// The connected port has become busy (its incoming queue is
// busy).
// No action is needed here-- the port processing code
// checks for connected port busy during data processing.
break;
case PVMF_PORT_ACTIVITY_CONNECTED_PORT_READY:
// The connected port has transitioned from Busy to Ready.
if (OutgoingMsgQueueSize() > 0)
RunIfNotReady();
break;
default:
break;
}
}
////////////////////////////////////////////////////////////////////////////
void PVMFLoopbackIOPort::Reset()
{
Cancel();
ClearMsgQueues();
iWaiting = false;
}
////////////////////////////////////////////////////////////////////////////
void PVMFLoopbackIOPort::Run()
{
//data should move through the ports only
//when the node is active or flushing
if (iNode->GetState() != EPVMFNodeStarted
&& !iNode->FlushPending())
return;
//Process incoming messages
if (!iWaiting
&& IncomingMsgQueueSize() > 0)
{
//dispatch the incoming data.
if (ProcessIncomingMsg() != PVMFSuccess)
iNode->ReportErrorEvent(PVMF_NODE_ERROR_EVENT_LAST, (OsclAny*)this);
//re-schedule if more data
if (!iWaiting
&& IncomingMsgQueueSize() > 0)
{
RunIfNotReady();
}
}
//Process outgoing messages
if (OutgoingMsgQueueSize() > 0
&& !IsConnectedPortBusy())
{
//Send data to connected port
PVMFStatus status = Send();
if (status != PVMFSuccess)
iNode->ReportErrorEvent(PVMF_NODE_ERROR_EVENT_LAST, (OsclAny*)this);
//Reschedule if there's more data to process...
if (OutgoingMsgQueueSize() > 0
&& !IsConnectedPortBusy())
{
RunIfNotReady();
}
}
}
////////////////////////////////////////////////////////////////////////////////
PVMFStatus PVMFLoopbackIOPort::ProcessIncomingMsg()
{
if (IsOutgoingQueueBusy())
{
iWaiting = true;
return PVMFSuccess;
}
//Move the incoming message from the input queue
//to the output queue...
PVMFSharedMediaMsgPtr msg;
PVMFStatus status = DequeueIncomingMsg(msg);
if (status != PVMFSuccess)
return status;
status = QueueOutgoingMsg(msg);
if (status != PVMFSuccess)
return status;
return PVMFSuccess;
}