omxilvideocomps/omxil3gpdemuxer/src/comxil3gpdemuxerprocessingfunction.cpp
author hgs
Fri, 08 Oct 2010 22:09:17 +0100
changeset 0 5d29cba61097
permissions -rw-r--r--
2010wk38_02

/*
* Copyright (c) 2008 - 2009 Nokia Corporation and/or its subsidiary(-ies).
* All rights reserved.
* This component and the accompanying materials are made available
* under the terms of "Eclipse Public License v1.0"
* which accompanies this distribution, and is available
* at the URL "http://www.eclipse.org/legal/epl-v10.html".
*
* Initial Contributors:
* Nokia Corporation - initial contribution.
*
* Contributors:
*
* Description:
*
*/


/**
@file
@internalComponent
*/

#include "log.h"
#include "comxil3gpdemuxerprocessingfunction.h"
#include "comxil3gpdemuxerconfigmanager.h"
#include "comxil3gpdemuxervideooutputport.h"
#include "comxil3gpdemuxeraudiooutputport.h"
#include "c3gpdemuxer.h"
#include <openmax/il/common/omxilcallbacknotificationif.h>


COmxIL3GPDemuxerProcessingFunction* COmxIL3GPDemuxerProcessingFunction::NewL(MOmxILCallbackNotificationIf& aCallbacks)
	{
	DEBUG_PRINTF(_L8("COmxIL3GPDemuxerProcessingFunction::NewL"));

	COmxIL3GPDemuxerProcessingFunction* self = new (ELeave) COmxIL3GPDemuxerProcessingFunction(aCallbacks);
	CleanupStack::PushL(self);
	self->ConstructL();
	CleanupStack::Pop(self);
	return self;
	}

COmxIL3GPDemuxerProcessingFunction::COmxIL3GPDemuxerProcessingFunction(MOmxILCallbackNotificationIf& aCallbacks) :
 COmxILProcessingFunction(aCallbacks)
 	{
	}

void COmxIL3GPDemuxerProcessingFunction::ConstructL()
	{
	DEBUG_PRINTF(_L8("COmxIL3GPDemuxerProcessingFunction::ConstructL"));

	iDemuxer = C3GPDemuxer::NewL(iCallbacks);
	
	// this is used in the Idle->Executing transition to issue the port changed events in the correct order
	// we create the callback now so it cannot fail later on
	iStreamDetectCallback = new(ELeave) CAsyncCallBack(TCallBack(StreamDetectCallBack, this), CAsyncCallBack::EPriorityHigh);

    iRequestHelper = COmxIL3GPDemuxerRequestHelper::NewL(this);
	}

COmxIL3GPDemuxerProcessingFunction::~COmxIL3GPDemuxerProcessingFunction()
	{
	DEBUG_PRINTF(_L8("COmxIL3GPDemuxerProcessingFunction::~COmxIL3GPDemuxerProcessingFunction"));

	delete iDemuxer;
	delete iStreamDetectCallback;
	delete iRequestHelper;
	}

void COmxIL3GPDemuxerProcessingFunction::SetConfigManager(COmxIL3GPDemuxerConfigManager& aConfigManager)
	{
	DEBUG_PRINTF(_L8("COmxIL3GPDemuxerProcessingFunction::SetConfigManager"));

	iConfigManager = &aConfigManager;	
	iConfigManager->SetDemuxer(*iDemuxer);	
	}

OMX_ERRORTYPE COmxIL3GPDemuxerProcessingFunction::StateTransitionIndication(TStateIndex aNewState)
	{
    DEBUG_PRINTF(_L8("COmxIL3GPDemuxerProcessingFunction::StateTransitionIndication"));
    
    return iRequestHelper->StateTransitionIndication(aNewState);
	}

OMX_ERRORTYPE COmxIL3GPDemuxerProcessingFunction::DoStateTransitionIndication(TStateIndex aNewState)
    {
    DEBUG_PRINTF(_L8("COmxIL3GPDemuxerProcessingFunction::DoStateTransitionIndication"));
    
    OMX_ERRORTYPE omxError = OMX_ErrorNone;

    switch(aNewState)
        {
        case EStateExecuting:
            {
            DEBUG_PRINTF(_L8("StateTransitionIndication : OMX_StateExecuting"));

            // Cause PortFormatDetected and PortSettingsChanged with
            // the format detected from the file.
            
            // However, we want this to occur after the idle->executing
            // completion notification, which FsmTransition() will queue
            // after this function completes. So we use a CAsyncCallBack
            // to create the events at some time after FsmTransition()
            // completes. A high priority is chosen to avoid being starved
            // by other busy AOs, in particular the callback manager(s).
            
            if(!iStreamsDetected)
                {
                iStreamDetectCallback->CallBack();
                }
            else
                {
                iDemuxer->Start();
                iExecuting = ETrue;
                }

            break;
            }

        case ESubStateLoadedToIdle:
            {
            DEBUG_PRINTF(_L8("StateTransitionIndication : OMX_StateLoadedToIdle"));

            const HBufC* filename = iConfigManager->Filename();
            if(filename)
                {
                // get the maximum buffer count for a port
                omxError = iDemuxer->AcquireResources(*filename);
                }
            else
                {
                // no file name has been set
                omxError = OMX_ErrorUnsupportedSetting;
                }
            break;
            }

        case EStateIdle:
            {
            DEBUG_PRINTF(_L8("StateTransitionIndication : OMX_StateIdle"));

            if (iExecuting)
                {
                iExecuting = EFalse;
                iDemuxer->Stop();
                }
            break;
            }

        case EStateLoaded:
            {
            DEBUG_PRINTF(_L8("StateTransitionIndication : OMX_StateLoaded"));

            iDemuxer->ReleaseResources();
            iStreamsDetected = EFalse;
            break;
            }

        case EStatePause:
            {
            DEBUG_PRINTF(_L8("StateTransitionIndication : OMX_StatePause"));

            iDemuxer->Pause();
            break;
            }

        default:
            {
            break;
            }
        }
    
    return omxError;        
    }

OMX_ERRORTYPE COmxIL3GPDemuxerProcessingFunction::BufferFlushingIndication(TUint32 aPortIndex,
                                                                           OMX_DIRTYPE aDirection)
    {
    DEBUG_PRINTF2(_L8("COmxIL3GPDemuxerProcessingFunction::BufferFlushingIndication : aPortIndex[%d]"), aPortIndex);
    
    return iRequestHelper->BufferFlushingIndication(aPortIndex, aDirection);
    }

OMX_ERRORTYPE COmxIL3GPDemuxerProcessingFunction::DoBufferFlushingIndication(TUint32 aPortIndex,
                                                                           OMX_DIRTYPE /*aDirection*/)
	{
	DEBUG_PRINTF2(_L8("COmxIL3GPDemuxerProcessingFunction::DoBufferFlushingIndication : aPortIndex[%d]"), aPortIndex);

	iDemuxer->FlushBuffers(aPortIndex);
	return OMX_ErrorNone;
	}

OMX_ERRORTYPE COmxIL3GPDemuxerProcessingFunction::ParamIndication(OMX_INDEXTYPE /*aParamIndex*/,
                                                                      const TAny* /*apComponentParameterStructure*/)
	{
	return OMX_ErrorNone;
	}

OMX_ERRORTYPE COmxIL3GPDemuxerProcessingFunction::ConfigIndication(OMX_INDEXTYPE /*aConfigIndex*/,
                                                                       const TAny* /*apComponentConfigStructure*/)
	{
	return OMX_ErrorNone;
	}
 
OMX_ERRORTYPE COmxIL3GPDemuxerProcessingFunction::BufferIndication(OMX_BUFFERHEADERTYPE* apBufferHeader,
                                                                   OMX_DIRTYPE /*aDirection*/)
	{
	DEBUG_PRINTF2(_L8("COmxIL3GPDemuxerProcessingFunction::BufferIndication >: [%X]"), apBufferHeader);

	// Check if the previous buffer processing invalidated the demuxer 
	if (iDemuxer->Invalid())
		{	
		return OMX_ErrorInvalidState;
		}	
	
	TUint32 portIndex;
	portIndex = apBufferHeader->nOutputPortIndex;

	if (portIndex >= COmxIL3GPDemuxer::EPortIndexMax)
		{
		return OMX_ErrorBadPortIndex;
		}

	TRAPD(err, iDemuxer->ProcessThisBufferL(apBufferHeader, portIndex));

	DEBUG_PRINTF2(_L8("COmxIL3GPDemuxerProcessingFunction::BufferIndication :< size [%d]"), apBufferHeader->nFilledLen);

	if (err == KErrNone)
		{
		return OMX_ErrorNone;
		}
	else
		{
		return OMX_ErrorUndefined;		
		}	
	}

OMX_BOOL COmxIL3GPDemuxerProcessingFunction::BufferRemovalIndication(OMX_BUFFERHEADERTYPE* apBufferHeader,
                                                                   OMX_DIRTYPE aDirection)
    {
    DEBUG_PRINTF2(_L8("COmxIL3GPDemuxerProcessingFunction::BufferRemovalIndication >: [%X]"), apBufferHeader);
    
    return iRequestHelper->BufferRemovalIndication(apBufferHeader, aDirection);
    }

OMX_BOOL COmxIL3GPDemuxerProcessingFunction::DoBufferRemovalIndication(OMX_BUFFERHEADERTYPE* apBufferHeader, OMX_DIRTYPE aDirection)
	{
	DEBUG_PRINTF2(_L8("COmxIL3GPDemuxerProcessingFunction::DoBufferRemovalIndication : BUFFER [%X]"), apBufferHeader);

	if (iDemuxer->RemoveBuffer(apBufferHeader, aDirection))
		{
		return OMX_TRUE;
		}

	return OMX_FALSE;
	}

OMX_U32 COmxIL3GPDemuxerProcessingFunction::NumAvailableStreams(COmxIL3GPDemuxer::TPortIndex aPortType)
	{
	switch(aPortType)
		{
	case COmxIL3GPDemuxer::EPortIndexVideoOutput:
			{
			TSize frameSize;
			TVideoFormat format;
			TBool videoAvailable = iDemuxer->GetVideoFormat(frameSize, format);
			return videoAvailable ? 1 : 0;
			}
			
	case COmxIL3GPDemuxer::EPortIndexAudioOutput:
		{
		TAudioFormat format;
		return iDemuxer->GetAudioFormat(format) ? 1 : 0;
		}

	default:
		User::Invariant();
		return 0;
		}
	}

OMX_U32 COmxIL3GPDemuxerProcessingFunction::ActiveStream(COmxIL3GPDemuxer::TPortIndex /*aPortType*/)
	{
	//TODO
	return 0;
	}

OMX_ERRORTYPE COmxIL3GPDemuxerProcessingFunction::SetActiveStream(COmxIL3GPDemuxer::TPortIndex aPortType, OMX_U32 aActiveStream)
	{
	switch(aPortType)
		{
	case COmxIL3GPDemuxer::EPortIndexVideoOutput:
			{
			TSize frameSize;
			TVideoFormat format;
				TBool videoAvailable = iDemuxer->GetVideoFormat(frameSize, format);
			if(videoAvailable && aActiveStream == 0)
				{
				return OMX_ErrorNone;
				}
			else
				{
				return OMX_ErrorUnsupportedSetting;
				}
			}
	case COmxIL3GPDemuxer::EPortIndexAudioOutput:
		// TODO
//ZK		return OMX_ErrorNotImplemented;
		return OMX_ErrorNone;
		
	default:
		return OMX_ErrorUnsupportedIndex;
		}
	}

void COmxIL3GPDemuxerProcessingFunction::SetVideoPort(COmxIL3GPDemuxerVideoOutputPort& aVideoPort)
	{
	iVideoPort = &aVideoPort;
	}

void COmxIL3GPDemuxerProcessingFunction::SetAudioPort(COmxIL3GPDemuxerAudioOutputPort& aAudioPort)
	{
	iAudioPort = &aAudioPort;
	}

TInt COmxIL3GPDemuxerProcessingFunction::StreamDetectCallBack(TAny* aPtr)
	{
	reinterpret_cast<COmxIL3GPDemuxerProcessingFunction*>(aPtr)->DoStreamDetect();
	return KErrNone;
	}

void COmxIL3GPDemuxerProcessingFunction::DoStreamDetect()
	{
	OMX_ERRORTYPE error = iDemuxer->DetectStreams();
	if(error)
		{
		iCallbacks.EventNotification(OMX_EventError, (TUint32)OMX_ErrorFormatNotDetected, 0, NULL);
		return;
		}

	// video format has been discovered
	// check against port definition
	// if autodetect, cause a PortSettingsChanged event
	// if not autodetect and detected format is different, cause an error event
	TSize size;
	TVideoFormat format;
	TBool videoAvailable = iDemuxer->GetVideoFormat(size, format);
	// errors from EventNotification are ignored - these will be
	// OMX_ErrorInsufficientResources if the callback could not be
	// created or added to the queue. In this case, we probably want
	// the callback manager to send an out-of-band error event to the
	// IL client but this does not happen in 1509 yet
	if(format.iCoding == OMX_VIDEO_CodingMax)
		{
		// format could not be mapped, and so is unsupported
		iCallbacks.EventNotification(OMX_EventError, (TUint32) OMX_ErrorFormatNotDetected, 0, NULL);
		// only send FormatNotDetected once for the component, not for both ports
		return;
		}
	else
		{
		if (iVideoPort->IsEnabled())
			{
			iStreamsDetected = ETrue;
			if (iVideoPort->VideoFormat() == OMX_VIDEO_CodingAutoDetect)
				{
				if(videoAvailable)
					{
					iVideoPort->FormatDetected(size, format);
					}
				// TODO spec doesn't say what the params should be for PortFormatDetected
				iCallbacks.EventNotification(OMX_EventPortFormatDetected, COmxIL3GPDemuxer::EPortIndexVideoOutput, 0, NULL);
				iCallbacks.EventNotification(OMX_EventPortSettingsChanged, OMX_IndexParamPortDefinition, COmxIL3GPDemuxer::EPortIndexVideoOutput, NULL);
				}
			else
				{
				if (iVideoPort->VideoFormat() != format.iCoding)
					{
					iStreamsDetected = EFalse;
					iCallbacks.EventNotification(OMX_EventError, (TUint32)OMX_ErrorFormatNotDetected, 0, NULL);
					return;
					}
				}
			}
		}

	TAudioFormat audioFormat;
	TBool audioAvailable = iDemuxer->GetAudioFormat(audioFormat);

	if(audioFormat.iCoding == OMX_AUDIO_CodingMax)
		{
		// format could not be mapped, and so is unsupported
		iCallbacks.EventNotification(OMX_EventError, (TUint32)OMX_ErrorFormatNotDetected, 0, NULL);
		return;
		}
	else
		{
		if (iAudioPort->IsEnabled())
			{
			iStreamsDetected = ETrue;
			if (iAudioPort->AudioFormat() == OMX_AUDIO_CodingAutoDetect)
				{
				if (audioAvailable)
					{
					iAudioPort->FormatDetected(audioFormat);
					}
				iCallbacks.EventNotification(OMX_EventPortFormatDetected, COmxIL3GPDemuxer::EPortIndexAudioOutput, 0, NULL);
				iCallbacks.EventNotification(OMX_EventPortSettingsChanged, OMX_IndexParamPortDefinition, COmxIL3GPDemuxer::EPortIndexAudioOutput, NULL);
				}
			else
				{
				if (iAudioPort->AudioFormat() != audioFormat.iCoding)
					{
					iStreamsDetected = EFalse;
					iCallbacks.EventNotification(OMX_EventError, (TUint32)OMX_ErrorFormatNotDetected, 0, NULL);
					return;
					}
				}
			}
		}
	//Only start the demuxer if one of its ports is enabled.
	if (iStreamsDetected)
		{
		iDemuxer->Start();
		iExecuting = ETrue;
		}
	}