blob: 787f731a66d879c82d7ea276af54dffea00cf4c1 [file] [log] [blame]
/* ------------------------------------------------------------------
* Copyright (C) 2008 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 "pvmf_omx_videodec_factory.h"
#include "pvmf_omx_audiodec_factory.h"
#include "pvmf_amrffparser_factory.h"
#include "pvmf_aacffparser_factory.h"
#include "pvmf_wavffparser_factory.h"
#include "pvmf_mp3ffparser_factory.h"
#include "pv_player_node_registry.h"
// For recognizer registry
#include "pvmf_recognizer_registry.h"
#include "pvmi_datastreamsyncinterface_ref_factory.h"
#include "pvmf_recognizer_plugin.h"
#include "pvmp3ffrec_factory.h"
#include "pvwavffrec_factory.h"
#include "pvamrffrec_factory.h"
#ifdef HAS_OSCL_LIB_SUPPORT
#include "oscl_shared_library.h"
#include "pvmf_node_shared_lib_interface.h"
#endif
PVPlayerNodeRegistry::PVPlayerNodeRegistry()
{
PVPlayerNodeInfo nodeinfo;
iType.reserve(20);
//For PVMFOMXVideoDecNode
nodeinfo.iInputTypes.clear();
nodeinfo.iInputTypes.push_back(PVMF_H263);
nodeinfo.iInputTypes.push_back(PVMF_M4V);
nodeinfo.iInputTypes.push_back(PVMF_H264);
nodeinfo.iInputTypes.push_back(PVMF_H264_RAW);
nodeinfo.iInputTypes.push_back(PVMF_H264_MP4);
nodeinfo.iInputTypes.push_back(PVMF_WMV);
nodeinfo.iNodeUUID = KPVMFOMXVideoDecNodeUuid;
nodeinfo.iOutputType.clear();
nodeinfo.iOutputType.push_back(PVMF_YUV420);
nodeinfo.iNodeCreateFunc = PVMFOMXVideoDecNodeFactory::CreatePVMFOMXVideoDecNode;
nodeinfo.iNodeReleaseFunc = PVMFOMXVideoDecNodeFactory::DeletePVMFOMXVideoDecNode;
iType.push_back(nodeinfo);
nodeinfo.iInputTypes.clear();
// AAC FORMATS
nodeinfo.iInputTypes.push_back(PVMF_MPEG4_AUDIO);
nodeinfo.iInputTypes.push_back(PVMF_ADIF);
nodeinfo.iInputTypes.push_back(PVMF_ADTS);
nodeinfo.iInputTypes.push_back(PVMF_LATM);
nodeinfo.iInputTypes.push_back(PVMF_ASF_MPEG4_AUDIO);
// AMR FORMATS
nodeinfo.iInputTypes.push_back(PVMF_AMR_IETF);
nodeinfo.iInputTypes.push_back(PVMF_AMR_IETF_COMBINED);
nodeinfo.iInputTypes.push_back(PVMF_AMRWB_IETF);
nodeinfo.iInputTypes.push_back(PVMF_AMRWB_IETF_PAYLOAD);
nodeinfo.iInputTypes.push_back(PVMF_AMR_IF2);
// MP3 FORMAT
nodeinfo.iInputTypes.push_back(PVMF_MP3);
nodeinfo.iNodeUUID = KPVMFOMXAudioDecNodeUuid;;
nodeinfo.iOutputType.clear();
nodeinfo.iOutputType.push_back(PVMF_PCM16);
nodeinfo.iNodeCreateFunc = PVMFOMXAudioDecNodeFactory::CreatePVMFOMXAudioDecNode;
nodeinfo.iNodeReleaseFunc = PVMFOMXAudioDecNodeFactory::DeletePVMFOMXAudioDecNode;
iType.push_back(nodeinfo);
//For PVMFMP3FFParserNode
nodeinfo.iInputTypes.clear();
nodeinfo.iInputTypes.push_back(PVMF_MP3FF);
nodeinfo.iNodeUUID = KPVMFMP3FFParserNodeUuid;
nodeinfo.iOutputType.clear();
nodeinfo.iOutputType.push_back(PVMF_FORMAT_UNKNOWN);
nodeinfo.iNodeCreateFunc = PVMFMP3FFParserNodeFactory::CreatePVMFMP3FFParserNode;
nodeinfo.iNodeReleaseFunc = PVMFMP3FFParserNodeFactory::DeletePVMFMP3FFParserNode;
iType.push_back(nodeinfo);
//For PVMFAMRFFParserNode
nodeinfo.iInputTypes.clear();
nodeinfo.iInputTypes.push_back(PVMF_AMRFF);
nodeinfo.iNodeUUID = KPVMFAmrFFParserNodeUuid;
nodeinfo.iOutputType.clear();
nodeinfo.iOutputType.push_back(PVMF_FORMAT_UNKNOWN);
nodeinfo.iNodeCreateFunc = PVMFAMRFFParserNodeFactory::CreatePVMFAMRFFParserNode;
nodeinfo.iNodeReleaseFunc = PVMFAMRFFParserNodeFactory::DeletePVMFAMRFFParserNode;
iType.push_back(nodeinfo);
//For PVMFAACFFParserNode
nodeinfo.iInputTypes.clear();
nodeinfo.iInputTypes.push_back(PVMF_AACFF);
nodeinfo.iNodeUUID = KPVMFAacFFParserNodeUuid;
nodeinfo.iOutputType.clear();
nodeinfo.iOutputType.push_back(PVMF_FORMAT_UNKNOWN);
nodeinfo.iNodeCreateFunc = PVMFAACFFParserNodeFactory::CreatePVMFAACFFParserNode;
nodeinfo.iNodeReleaseFunc = PVMFAACFFParserNodeFactory::DeletePVMFAACFFParserNode;
iType.push_back(nodeinfo);
//For PVMFWAVFFParserNode
nodeinfo.iInputTypes.clear();
nodeinfo.iInputTypes.push_back(PVMF_WAVFF);
nodeinfo.iNodeUUID = KPVMFWavFFParserNodeUuid;
nodeinfo.iOutputType.clear();
nodeinfo.iOutputType.push_back(PVMF_FORMAT_UNKNOWN);
nodeinfo.iNodeCreateFunc = PVMFWAVFFParserNodeFactory::CreatePVMFWAVFFParserNode;
nodeinfo.iNodeReleaseFunc = PVMFWAVFFParserNodeFactory::DeletePVMFWAVFFParserNode;
iType.push_back(nodeinfo);
}
PVPlayerNodeRegistry::~PVPlayerNodeRegistry()
{
iType.clear();
}
PVMFStatus PVPlayerNodeRegistry::QueryRegistry(PVMFFormatType& aInputType, PVMFFormatType& aOutputType, Oscl_Vector<PVUuid, OsclMemAllocator>& aUuids)
{
uint32 SearchCount = 0;
bool matchfound = false;
// Find all nodes that support the specified input and ouput format pair
while (SearchCount < iType.size())
{
uint32 inputsearchcount = 0, outputsearchcount = 0;
bool iInputFoundFlag = false, iOutputFoundFlag = false;
while (inputsearchcount < iType[SearchCount].iInputTypes.size())
{
// Check if the input format matches
if (iType[SearchCount].iInputTypes[inputsearchcount] == aInputType)
{
// Set the the input flag to true since we found the match in the search
iInputFoundFlag = true;
break;
}
inputsearchcount++;
}
//Check the flag of input format if it is true check for the output format, if not return failure
if (iInputFoundFlag)
{
while (outputsearchcount < iType[SearchCount].iOutputType.size())
{
if (iType[SearchCount].iOutputType[outputsearchcount] == aOutputType)
{
//set the the output flag to true since we found the match in the search
iOutputFoundFlag = true;
break;
}
outputsearchcount++;
}
if (iOutputFoundFlag)
{
// There's a match so add this node UUID to the list.
aUuids.push_back(iType[SearchCount].iNodeUUID);
matchfound = true;
}
}
SearchCount++;
}
if (matchfound)
{
return PVMFSuccess;
}
else
{
return PVMFFailure;
}
}
PVMFNodeInterface* PVPlayerNodeRegistry::CreateNode(PVUuid& aUuid)
{
PVMFNodeInterface* nodeInterface = NULL;
bool iFoundFlag = false;
uint32 NodeSearchCount = 0;
while (NodeSearchCount < iType.size())
{
//Search if the UUID's will match
if (iType[NodeSearchCount].iNodeUUID == aUuid)
{
//Since the UUID's match set the flag to true
iFoundFlag = true;
break;
}
NodeSearchCount++;
}
if (iFoundFlag)
{
OsclActiveObject::OsclActivePriority priority = OsclActiveObject::EPriorityNominal;
PVPlayerNodeInfo* nodeInfo = &iType[NodeSearchCount];
//Call the appropriate Node creation function & return Node pointer
if (KPVMFOMXVideoDecNodeUuid == aUuid)
{
priority = OsclActiveObject::EPriorityLow;
}
else
{
priority = OsclActiveObject::EPriorityNominal;
}
#ifdef HAS_OSCL_LIB_SUPPORT
// If the node has a corresponding shared library, load that
// first. If not, the node is assumed to be already completely
// linked.
if (NULL != nodeInfo->iSharedLibrary
&& (OsclLibSuccess == (nodeInfo->iSharedLibrary)->LoadLib()))
{
// Need to load the library for the node and query for the
// create and release functions. If the library is already
// loaded, the system should avoid opening the same library
// again on its own.
OsclAny* interfacePtr = NULL;
(nodeInfo->iSharedLibrary)->QueryInterface(PV_NODE_INTERFACE,
(OsclAny*&)interfacePtr);
NodeSharedLibraryInterface* nodeIntPtr =
OSCL_DYNAMIC_CAST(NodeSharedLibraryInterface*, interfacePtr);
OsclAny* createFuncTemp =
nodeIntPtr->QueryNodeInterface(nodeInfo->iNodeUUID, PV_CREATE_NODE_INTERFACE);
OsclAny* releaseFuncTemp =
nodeIntPtr->QueryNodeInterface(nodeInfo->iNodeUUID, PV_RELEASE_NODE_INTERFACE);
nodeInfo->iNodeCreateFunc =
OSCL_DYNAMIC_CAST(PVMFNodeInterface * (*)(int32), createFuncTemp);
nodeInfo->iNodeReleaseFunc =
OSCL_DYNAMIC_CAST(bool (*)(PVMFNodeInterface*), releaseFuncTemp);
}
#endif
if (NULL != nodeInfo->iNodeCreateFunc)
{
nodeInterface = (*(iType[NodeSearchCount].iNodeCreateFunc))(priority);
}
}
return nodeInterface;
}
bool PVPlayerNodeRegistry::ReleaseNode(PVUuid& aUuid, PVMFNodeInterface* aNode)
{
bool iFoundFlag = false;
uint32 NodeSearchCount = 0;
while (NodeSearchCount < iType.size())
{
//Search if the UUID's will match
if (iType[NodeSearchCount].iNodeUUID == aUuid)
{
//Since the UUID's match set the flag to true
iFoundFlag = true;
break;
}
NodeSearchCount++;
}
if (iFoundFlag)
{
//Call the appropriate Node delete function
bool del_stat = (*(iType[NodeSearchCount].iNodeReleaseFunc))(aNode);
#ifdef HAS_OSCL_LIB_SUPPORT
// If a library needs to be loaded to use this node, close the library
if (NULL != iType[NodeSearchCount].iSharedLibrary)
{
(iType[NodeSearchCount].iSharedLibrary)->Close();
}
#endif
return del_stat;
}
return false;
}
// Player engine with recognizers for MP3, MP4, WAV, and AMR
PVPlayerRecognizerRegistry::PVPlayerRecognizerRegistry()
: OsclTimerObject(OsclActiveObject::EPriorityNominal, "PVPlayerRecognizerRegistry")
{
AddToScheduler();
iRecSessionId = 0;
iRecognizerResult.reserve(4);
iFileDataStreamFactory = NULL;
iSourceFormatType = PVMF_FORMAT_UNKNOWN;
iObserver = NULL;
iCmdContext = NULL;
iCancelQuery = false;
iCancelCmdContext = NULL;
if (PVMFRecognizerRegistry::Init() != PVMFSuccess)
{
OSCL_ASSERT(false);
return;
}
PVMFRecognizerPluginFactory* tmpfac = NULL;
tmpfac = OSCL_STATIC_CAST(PVMFRecognizerPluginFactory*, OSCL_NEW(PVMP3FFRecognizerFactory, ()));
if (PVMFRecognizerRegistry::RegisterPlugin(*tmpfac) == PVMFSuccess)
{
iRecognizerList.push_back(tmpfac);
}
else
{
OSCL_DELETE(((PVMP3FFRecognizerFactory*)tmpfac));
tmpfac = NULL;
return;
}
tmpfac = OSCL_STATIC_CAST(PVMFRecognizerPluginFactory*, OSCL_NEW(PVWAVFFRecognizerFactory, ()));
if (PVMFRecognizerRegistry::RegisterPlugin(*tmpfac) == PVMFSuccess)
{
iRecognizerList.push_back(tmpfac);
}
else
{
OSCL_DELETE(((PVWAVFFRecognizerFactory*)tmpfac));
tmpfac = NULL;
return;
}
tmpfac = OSCL_STATIC_CAST(PVMFRecognizerPluginFactory*, OSCL_NEW(PVAMRFFRecognizerFactory, ()));
if (PVMFRecognizerRegistry::RegisterPlugin(*tmpfac) == PVMFSuccess)
{
iRecognizerList.push_back(tmpfac);
}
else
{
OSCL_DELETE(((PVAMRFFRecognizerFactory*)tmpfac));
tmpfac = NULL;
return;
}
}
PVPlayerRecognizerRegistry::~PVPlayerRecognizerRegistry()
{
if (iFileDataStreamFactory)
{
OSCL_DELETE(OSCL_STATIC_CAST(PVMIDataStreamSyncInterfaceRefFactory*, iFileDataStreamFactory));
iFileDataStreamFactory = NULL;
}
PVMFRecognizerPluginFactory* tmpfac = NULL;
if (iRecognizerList.empty() == false)
{
tmpfac = iRecognizerList[0];
iRecognizerList.erase(iRecognizerList.begin());
PVMFRecognizerRegistry::RemovePlugin(*tmpfac);
OSCL_DELETE(((PVMP3FFRecognizerFactory*)tmpfac));
}
if (iRecognizerList.empty() == false)
{
tmpfac = iRecognizerList[0];
iRecognizerList.erase(iRecognizerList.begin());
PVMFRecognizerRegistry::RemovePlugin(*tmpfac);
OSCL_DELETE(((PVWAVFFRecognizerFactory*)tmpfac));
}
if (iRecognizerList.empty() == false)
{
tmpfac = iRecognizerList[0];
iRecognizerList.erase(iRecognizerList.begin());
PVMFRecognizerRegistry::RemovePlugin(*tmpfac);
OSCL_DELETE(((PVAMRFFRecognizerFactory*)tmpfac));
}
PVMFRecognizerRegistry::Cleanup();
}
PVMFStatus PVPlayerRecognizerRegistry::QueryFormatType(OSCL_wString& aSourceURL, PVPlayerRecognizerRegistryObserver& aObserver, OsclAny* aCmdContext)
{
if (iObserver != NULL)
{
// Previous query still ongoing
return PVMFErrBusy;
}
iObserver = &aObserver;
iCmdContext = aCmdContext;
// Create a datastream wrapper factory for standard file
if (iFileDataStreamFactory)
{
OSCL_DELETE(OSCL_STATIC_CAST(PVMIDataStreamSyncInterfaceRefFactory*, iFileDataStreamFactory));
iFileDataStreamFactory = NULL;
}
int32 leavecode = 0;
OSCL_TRY(leavecode, iFileDataStreamFactory = OSCL_STATIC_CAST(PVMFDataStreamFactory*, OSCL_NEW(PVMIDataStreamSyncInterfaceRefFactory, (aSourceURL))));
OSCL_FIRST_CATCH_ANY(leavecode,
return PVMFErrNoMemory;
);
// Open the session with recognizer
PVMFRecognizerRegistry::OpenSession(iRecSessionId, *this);
// Request file recognition
iRecognizerResult.clear();
iRecognizeCmdId = PVMFRecognizerRegistry::Recognize(iRecSessionId, *iFileDataStreamFactory, NULL, iRecognizerResult, NULL);
return PVMFSuccess;
}
void PVPlayerRecognizerRegistry::CancelQuery(OsclAny* aContext)
{
if (iObserver == NULL)
{
// No pending recognize request
OSCL_LEAVE(OsclErrInvalidState);
return;
}
iCancelQuery = true;
iCancelCmdContext = aContext;
if (!IsBusy())
{
// The recognition pending so cancel it
PVMFRecognizerRegistry::CancelCommand(iRecSessionId, iRecognizeCmdId);
}
// Else the recognition already completed so just cancel it in the Run()
}
void PVPlayerRecognizerRegistry::Run()
{
// Close the session with recognizer
PVMFRecognizerRegistry::CloseSession(iRecSessionId);
// Destroy the data stream wrapper factory for standard file
if (iFileDataStreamFactory)
{
OSCL_DELETE(OSCL_STATIC_CAST(PVMIDataStreamSyncInterfaceRefFactory*, iFileDataStreamFactory));
iFileDataStreamFactory = NULL;
}
// Tell the engine the result
if (iObserver)
{
iObserver->RecognizeCompleted(iSourceFormatType, iCmdContext);
if (iCancelQuery)
{
iObserver->RecognizeCompleted(iSourceFormatType, iCancelCmdContext);
iCancelQuery = false;
iCancelCmdContext = NULL;
}
}
iObserver = NULL;
iCmdContext = NULL;
}
void PVPlayerRecognizerRegistry::RecognizerCommandCompleted(const PVMFCmdResp& aResponse)
{
iSourceFormatType = PVMF_FORMAT_UNKNOWN;
if (aResponse.GetCmdId() == iRecognizeCmdId)
{
// Recognize() command completed
if (aResponse.GetCmdStatus() == PVMFSuccess)
{
Oscl_Vector<PVMFRecognizerResult, OsclMemAllocator>::iterator it;
for (it = iRecognizerResult.begin(); it != iRecognizerResult.end(); it++)
{
if (it->iRecognitionConfidence == PVMFRecognizerConfidenceCertain)
{
// Current implementation does not support the case where multiple
// recognizer plugins can recognize the file with certainty
iSourceFormatType = GetFormatIndex(it->iRecognizedFormat.get_str());
break;
}
if (it->iRecognitionConfidence == PVMFRecognizerConfidencePossible)
{
iSourceFormatType = GetFormatIndex(it->iRecognizedFormat.get_str());
}
}
}
if (aResponse.GetCmdStatus() == PVMFErrCancelled)
{
// If cancelled, need to wait for the cancel command to complete before
// calling Run
return;
}
}
RunIfNotReady();
}