Opencore之文件解析

     前面我們說了文件的打開,發送數據給下一個peer,但是我們還是不明白文件的格式是 如何識別的,因爲文件的種類繁多,文件的識別就會很麻煩,並且還要考慮到可擴展性,所以這個文件的識別是以插件的形式來存在的,這裏我們簡要的說一下,這 個插件的框架。
 
由於文件的格式很多,而且標準也很多,很難 肯定某一文件就是某種的格式,因而就引入一個確信度的概念。
 
typedef Oscl_Vector<OSCL_HeapString<OsclMemAllocator>, OsclMemAllocator> PVMFRecognizerMIMEStringList;
 
typedef enum _PVMFRecognizerConfidence
{
    PVMFRecognizerConfidenceNotCertain,             // 100% sure not the format
    PVMFRecognizerConfidenceNotPossible,    // Maybe not the format
    PVMFRecognizerConfidenceUnknown,              // Not sure one way or the other
    PVMFRecognizerConfidencePossible,          // Maybe the format
    PVMFRecognizerConfidenceCertain                   // 100% sure of the format
} PVMFRecognizerConfidence;
 
然後是文件識別的結果:
class PVMFRecognizerResult
{
    public:
        PVMFRecognizerResult()
        {
        };
 
        // Copy constructor for use in Oscl_Vector
        PVMFRecognizerResult(const PVMFRecognizerResult& aSrc)
        {
            iRecognizedFormat = aSrc.iRecognizedFormat;
            iRecognitionConfidence = aSrc.iRecognitionConfidence;
            //     iRecognizerSubFormatList=aSrc.iRecognizerSubFormatList;
        };
 
        ~PVMFRecognizerResult()
        {
        };
 
        // The format of interest as a MIME string
        OSCL_HeapString<OsclMemAllocator> iRecognizedFormat;
        // The confidence level of recognition
        PVMFRecognizerConfidence iRecognitionConfidence;
        // If the format is a container format, the format of content within
//     Oscl_Vector<PVMFRecognizerResult, OsclMemAllocator> iRecognizerSubFormatList;
};
格式和確信度。
然後就是一個事件的監控者Observer。
 
/**
 * PVMFRecognizerCommmandHandler Class
 *
 * PVMFRecognizerCommmandHandler is the PVMF Recognizer observer class for notifying the
 * status of asynchronous requests. The API provides a mechanism for the status of each
 * command to be passed back along with context specific information where applicable.
 * User of the recognizer registry must have a class derived from PVMFNodeCmdStatusObserver
 * and implement the pure virtual function in order to receive event notifications from
 * PVMF Recognizer Registry.
 **/
class PVMFRecognizerCommmandHandler
{
    public:
        /**
         * Handle an event that has been generated.
         *
         * @param aResponse
         *        The response to a previously issued command
         */
        virtual void RecognizerCommandCompleted(const PVMFCmdResp& aResponse) = 0;
        virtual ~PVMFRecognizerCommmandHandler() {}
};
 
#endif // PVMF_RECOGNIZER_TYPES_H_INCLUDED
這些都只是純虛類。
 
文件識別,一 般都是讀取文件中的某些特殊的字節,然後才能做判斷的,由於不同的文件讀取的地方不同,並且識別的規則也是不同,所以定義一個基本的接口。
class PVMFRecognizerPluginInterface
{
  public:
        /**
         * Virtual destructor for the plug-in. All plug-ins should perform any clean up here
         **/
        virtual ~PVMFRecognizerPluginInterface()
        {
        };
 
        /**
         * This methods returns a list of format(s) that this plug-in can recognize. Each supported format
         * is represented by a MIME string.
         *
         * @param aSupportedFormatsList
         *        Reference to a list of MIME strings which will be filled in with list of formats that the plug-in can recognize.
         *
         * @exception This method can leave with one of the following error codes
         *         OsclErrNoMemory if memory cannot be allocated for the format list
         *
         * @returns A PVMF status code to report result of method
         **/本插件支持下面的一些 格式的識別,以一個列表的形式返回
                     注意我們的文件識別都是以 插件的形式存在的,這樣就可以保證文件識別的可擴展性,每一個插件都必須從這個接口來繼承,另外還必須有一個類統一管理這些插件,如插件的查找和註冊
        virtual PVMFStatus SupportedFormats(PVMFRecognizerMIMEStringList& aSupportedFormatsList) = 0;
 
        /**
         * This method determines the the specified content is or is not one of the formats recognized by this plug-in
         *
         * @param aSourceDataStreamFactory
         *        A reference to a PVMFDataStreamFactory representing the content to recognize
         * @param aFormatHint
         *        An optional input parameter expressed as a list of MIME string which provides a priori hint for the format
         *        of the content specified by aSourceDataStreamFactory.
         * @param aRecognizerResult
         *        An output parameter which is a reference to a vector of PVMFRecognizerResult that will contain the recognition
         *        result if the Recognize() method succeeds.
         *
         * @exception This method can leave with one of the following error codes
         *
         * @returns A PVMF status code to report result of method
         **/
//給定一個數據源讓你去識別,有一個優先考慮的格式列表參數,返回的是 一個識別結果的列表,列出可能的格式和確信度。
        virtual PVMFStatus Recognize(PVMFDataStreamFactory& aSourceDataStreamFactory,
                                     PVMFRecognizerMIMEStringList* aFormatHint,
                                     Oscl_Vector<PVMFRecognizerResult, OsclMemAllocator>& aRecognizerResult) = 0;
 
        /**
         * This method returns the mininum required bytes in datastream for this plug-in
         * to be able to recognize its supported formats.
         *
         * @param aBytes[out]
         *        A reference to a minimum required bytes
         *
         * @returns A PVMF status code to report result of method.
         * PVMFSuccess in case of success and PVMFFailure otherwise.
         **///或者識別所需的最小字節數
 
        virtual PVMFStatus GetRequiredMinBytesForRecognition(uint32& aBytes) = 0;
};
 
每一個插件都 需要佔用一定內存,因而就有下面的定義:一個插件的工廠的基類,每一個插件都要有一個這樣的工廠接口來創建和刪除某一個插件。
/**
 * An abstract base class to create and destroy a recognizer plug-in. Every recognizer plug-in should have
 * an associated factory class to provide a standard way to create and destroy the plug-in.
 **/
class PVMFRecognizerPluginFactory: public HeapBase
{
    public:
        /**
         * Virtual destructor for the plug-in factory. All plug-in factory should perform any clean up here
         **/
        virtual ~PVMFRecognizerPluginFactory()
        {
        };
 
        /**
         * This method instantiates and returns the recognizer plug-in that the factory is associated with.
         *
         * @exception This method can leave with one of the following error codes
         *         OsclErrNoMemory if memory cannot be allocated for the recognizer plug-in
         * @returns A pointer to the recognizer plug-in instance if creation is successful.
         **/
        virtual PVMFRecognizerPluginInterface* CreateRecognizerPlugin() = 0;
 
        /**
         * This method destroys the specified recognizer plug-in pointer as the particular recognizer plug-in
         * the factory is associated with.
         *
         * @param aPlugIn
         *        A pointer to the recognizer plug-in that should be destroyed.
         *
         * @exception This method can leave with one of the following error codes
         *
         * @returns None
         **/
        virtual void DestroyRecognizerPlugin(PVMFRecognizerPluginInterface* aPlugIn) = 0;
};
然後就是一個 模板的定義,因爲插件很多,這裏我們寫一個簡單的模板:
/**
 * Basic templatized recognizer plug-in factory. Can be used if the recognizer plug-in only needs
 * to be instantiated and destroyed by just new and delete, respectively and no other functionality
 * is needed from the factory class.
 **/
template<class T>
class PVMFRecognizerPluginFactoryBasic : public PVMFRecognizerPluginFactory
{
    public:
        virtual ~PVMFRecognizerPluginFactoryBasic()
        {
        };
 
        PVMFRecognizerPluginInterface* CreateRecognizerPlugin()
        {
            T* plugin = OSCL_NEW(T, ());
            return plugin;
        };
 
        void DestroyRecognizerPlugin(PVMFRecognizerPluginInterface* aPlugIn)
        {
            T* plugin = (T*)aPlugIn;
            OSCL_DELETE(plugin);
        };
};
這樣關於插件的基類,我們基本搞定,下面的就是這麼多插件在一起如何去管理。這裏就是一個靜態類(static)。負責插件的註冊和註銷,並且負責文件的的尋找,來了文件,歷遍所有註冊過的插件來找到最匹配的格式。這和微軟的DirectShow框架極爲相似,不過微軟的Filter是這側到註冊表裏面去了,並且,微軟Filter的概念不僅僅是文件的識別,在微軟的註冊表中,有一項就是Media Type,規定了系統所能夠識別的文件類型,每一個類型都要有匹配碼,例如前面 八個字節是什麼,後面四個字節是什麼,這些都是在註冊表中,註冊的另外的一個就是打開這個文件所需的Source Filter的ID,這樣要播放的文件的時候按照一定優先級匹配這些註冊信息就行了。
 
這裏關於插件 的管理有一個單獨的靜態類,靜態類的特點就是不管類是不是存在,這個東西都是存在的,並且全局可訪問。這纔是我們識別的關鍵代碼:
/**
 * A class of static methods that provides the interface to the PVMF recognizer registry..
 * With these static methods, the recognizer registry can be initialized and shutdown, recognizer
 * plug-ins can be registered and unregistered, and format of a content can be recognized.
 **/
class PVMFRecognizerRegistry
{
    public:
        /**
                     格式的註冊信息的初始化, 因爲我們知道,一種格式的識別,都會註冊相應的信息,識別器就是通過這些信息的歷遍,找出對應的文件。在使用識別器之前,最先就是初始化。
         * This static method initializes the recognizer registry for use. This method must be called once
         * and succeed before calling any other methods from PVMFRecognizerRegistry.
         *
         * @exception This method can leave with one of the following error codes
         *         OsclErrNoMemory if memory cannot be allocated for the registry implementation
         * @returns A PVMF status code to report result of method
         **/
        OSCL_IMPORT_REF static PVMFStatus Init();
 
        /**
使用完之後, 就要清空
         * This static methods shuts down and cleans up the recognizer registry. This method must be called once
         * after there is no more use for the recognizer registry to properly release the memory allocated for the
         * registry
         **/
        OSCL_IMPORT_REF static void Cleanup();
 
        /**
              一種媒體格式識別信息的添 加,實際上就是添加一個PVMFRecognizerPluginFactory,前面我們說過每一種格式都會有其對應的PVMFRecognizerPluginFactory。
         * This static method adds the specified recognizer plug-in factory to the list of available recognizers.
         * The passed-in plug-in factory would be used to create and destroy the recognizer plug-in in the Recognize() methods.
         * The passed-in plug-in factory reference must be valid until it is removed from the list by the RemovePlugin() method.
         *
         * @param aPluginFactory
         *        A reference to a recognizer plug-in factory to add to the list of registered recognizers
         *
         * @exception This method can leave with one of the following error codes
         *         OsclErrNoMemory if memory cannot be allocated for vector holding the plug-in factory pointers
         * @returns A PVMF status code to report result of method
         **/
        OSCL_IMPORT_REF static PVMFStatus RegisterPlugin(PVMFRecognizerPluginFactory& aPluginFactory);
 
        /**  註銷某一種格式,將某一種識別的信息從註冊信息列表中剔除
         * This static method removes the specified recognizer plug-in factory from the list of available recognizers.
         * The passed-in plug-in factory must have been added before with RegisterPlugin() for this method to succeed.
         * After the plug-in factory is successfully removed, the factory instance can be deleted.
         *
         * @param aPluginFactory
         *        A reference to a recognizer plug-in factory to remove from the list of registered recognizers
         *
         * @returns A PVMF status code to report result of method
         **/
        OSCL_IMPORT_REF static PVMFStatus RemovePlugin(PVMFRecognizerPluginFactory& aPluginFactory);
 
        /**
         * This static method creates a recognition session with the recognizer framework.
         *創建一個識別的會話,
         * @param aSessionId  返回一個會話的ID
         *        A reference to a PVMFSessionId which will be set to the session's unique identifier when this method
         *        completes successfully.
         * @param aCmdHandler   給它一個識別的觀察者,也就是消息的監控者
         *        A reference to a PVMFRecognizerCommmandHandler which will receive asynchronous command completion notification.
         *
         * @returns A PVMF status code to report result of method
         **/
        OSCL_IMPORT_REF static PVMFStatus OpenSession(PVMFSessionId& aSessionId, PVMFRecognizerCommmandHandler& aCmdHandler);
 
        /**
         * This static method shuts down a recognition session with the recognizer framework.
         *關閉一個會話
         * @param aSessionId
         *        The unique identifier of the session to close
         *
         * @returns A PVMF status code to report result of method
         **/
        OSCL_IMPORT_REF static PVMFStatus CloseSession(PVMFSessionId aSessionId);
 
        /**開始識別,開始識別的開始就需要一個數據的來源、然後是優先考慮的格 式、識別結果的存儲、
         * This static method asynchronously determines the format of the specified content using the currently registered
         * recognizer plug-ins. When the recognizer request completes, the user would be notified via the PVMFRecognizerCommandHandler
         * callback handler set when opening the session.
         *
         * @param aSessionId
         *        The unique identifier for the recognizer session
         * @param aSourceDataStreamFactory  數據的來源
         *        A reference to a PVMFDataStreamFactory representing the content to recognize
         * @param aFormatHintList優先考慮的格式
         *        An optional input parameter expressed as a list of MIME string which provides a priori hint for the format
         *        of the content specified by aSourceDataStreamFactory.
         * @param aRecognizerResult結果的存儲
         *        An output parameter which is a reference to a vector of PVMFRecognizerResult that will contain the recognition
         *        result if the Recognize() method succeeds.
         * @param aCmdContext
         *        Optional pointer to opaque data that will be returned in the command completion response,識別上下文的返回
         * @param aTimeout  識別的時間限制
         *        Optional timeout value for the recognition request. If the recognition operation takes more time than the timeout
         *        value, the operation will be cancelled with PVMFErrTimeout status code. If the timeout value is set to 0, the
         *        recognition operation will go to completion.
         *
         * @exception This method can leave with one of the following error codes
         *         OsclErrNoMemory if memory cannot allocated to process this request
         *         OsclErrArgument if one or more of the passed-in parameters is invalid
         *
         * @returns A PVMF command ID for the recognize request
         **/
        OSCL_IMPORT_REF static PVMFCommandId Recognize(PVMFSessionId aSessionId, PVMFDataStreamFactory& aSourceDataStreamFactory, PVMFRecognizerMIMEStringList* aFormatHintList,
                Oscl_Vector<PVMFRecognizerResult, OsclMemAllocator>& aRecognizerResult, OsclAny* aCmdContext = NULL, uint32 aTimeout = 0);
 
        /**取消前一個異步的識別操作
         * This static method cancels a previously issued asynchronous request that hasn't completed yet.
         *
         * @param aSessionId
         *        The unique identifier for the recognizer session
         * @param aCommandToCancelId
         *        Unique identifier for the asynchronous request to cancel.
         * @param aCmdContext
         *        Optional pointer to opaque data that will be returned in the command completion response
         *
         * @exception This method can leave with one of the following error codes
         *         OsclErrNoMemory if memory cannot allocated to process this request
         *         OsclErrArgument if one or more of the passed-in parameters is invalid
         *
         * @returns A PVMF command ID for the cancel request
         **/
        OSCL_IMPORT_REF static PVMFCommandId CancelCommand(PVMFSessionId aSessionId, PVMFCommandId aCommandToCancelId, OsclAny* aCmdContext = NULL);
};
這樣我們的識 別文件格式的框架就完成了。下面看一些具體的實現。
很遺憾,在OSDL中,我們已經定義好了一個類似於微軟註冊表的東西,它存在與OSDL中,在OSDL之上的任何代碼都是可以訪問的。
class OsclTLSRegistry
{
    public:
        /*
        ** Get an entry
        ** @param ID: identifier
        ** @param error (output) 0 for success or an error from TPVBasePanicEnum
        ** @returns: the entry value
        */
        OSCL_IMPORT_REF static OsclAny* getInstance(uint32 ID, int32 &error);
        /*
        ** Set an entry
        ** @param ID: identifier
        ** @param error (output) 0 for success or an error from TPVBasePanicEnum
        ** @returns: the entry value
        */
        OSCL_IMPORT_REF static void registerInstance(OsclAny* ptr, uint32 ID, int32 &error);
 
    private:
        OsclTLSRegistry()
        {}
        typedef OsclAny* registry_type;
        typedef registry_type* registry_pointer_type;
 
#if ( OSCL_TLS_IS_KEYED)
        class TKeyItem
        {
            public:
                TKeyItem(): iTlsKey(NULL), iThreadId(0)
                {}
                TOsclTlsKey *iTlsKey;
                TOsclTlsThreadId iThreadId;
        };
        class TlsKeyTable
        {
            public:
                TlsKeyTable(): iNumKeys(0)
                {}
                _OsclBasicLock iLock;
                uint32 iNumKeys;
                TKeyItem iKeys[OSCL_TLS_MAX_THREADS];
        };
 
        //The key table is a global variable.
        static TlsKeyTable* iTlsKeyTable;
 
        static void GetThreadId(TOsclTlsThreadId &threadId, int32&);
        static TOsclTlsKey* LookupTlsKey(int32&);
        static bool SaveTlsKey(TOsclTlsKey* key, int32&);
        static bool RemoveTlsKey(Oscl_DefAlloc& alloc, TOsclTlsKey* key, int32&);
#endif
 
    private:
        OSCL_IMPORT_REF static void initialize(Oscl_DefAlloc &alloc, int32 &error);
        OSCL_IMPORT_REF static void cleanup(Oscl_DefAlloc &alloc, int32 &error);
        friend class OsclBase;
 
};
這個類的實現 可以參見具體的代碼,所以這裏我們就不去多說。這裏我們在註冊信息中填入的是一個什麼呢?
我們看靜態的 初始化函數。
OSCL_EXPORT_REF PVMFStatus PVMFRecognizerRegistry::Init()
{
    // Check that there is no existing registry
PVMFRecognizerRegistryImpl* pvrecregimpl = OSCL_STATIC_CAST(PVMFRecognizerRegistryImpl*, PVMFRECOGNIZER_REGISTRY::getInstance(PVMFRECOGNIZER_REGISTRY_ID));
// 如果存在,那麼我就不用註冊這個一項了
    if (pvrecregimpl != NULL)
    {
        // Registry is already present so no need to instantiate again
        // Just increment the refcount
        (pvrecregimpl->iRefCount)++;
        return PVMFSuccess;
    }
 
    // Instantiate the registry implementation,否則就開始分配新的空間開始註冊
    Oscl_TAlloc<PVMFRecognizerRegistryImpl, OsclMemAllocator> talloc;
    pvrecregimpl = OSCL_ALLOC_NEW(talloc, PVMFRecognizerRegistryImpl, ());
    // Save it on singleton or TLS
    PVMFRECOGNIZER_REGISTRY::registerInstance(pvrecregimpl, PVMFRECOGNIZER_REGISTRY_ID);
    return PVMFSuccess;
}
 
繼續往下面講之前,我覺得我們可以看一下PVMFRecognizerRegistryImpl,這個是怎麼實現的,PVMFRecognizerRegistryImpl是我們註冊表中保存的一個東東。主要實現文件的識別,包含很多的信息。我以前以爲只有變量才能註冊 的,其實函數也能註冊的,函數代碼的空間也是數據,是數據就有指針,所以整個類也是可以註冊的。註冊後,如果要清空,那麼就要調用Cleanup,
OSCL_EXPORT_REF void PVMFRecognizerRegistry::Cleanup()
{
// Retrieve the registry implementation instance from singleton or TLS and destroy it
首先單件模式,返回我們註冊的PVMFRecognizerRegistryImpl指針,這個指針指向的內容是存在的,因爲我們前面在初始化的時候就分 配了內存
    PVMFRecognizerRegistryImpl* pvrecregimpl = OSCL_STATIC_CAST(PVMFRecognizerRegistryImpl*, PVMFRECOGNIZER_REGISTRY::getInstance(PVMFRECOGNIZER_REGISTRY_ID));
    if (pvrecregimpl != NULL)
    {
        // First decrement the refcount, 直接自減就行了,自身負責分配
        --(pvrecregimpl->iRefCount);
        // If the resulting refcount is 0, then delete the instance
        if ((pvrecregimpl->iRefCount) <= 0)
        {
            Oscl_TAlloc<PVMFRecognizerRegistryImpl, OsclMemAllocator> talloc;
            OSCL_ALLOC_DELETE(pvrecregimpl, talloc, PVMFRecognizerRegistryImpl);
            // Unregister by putting NULL pointer in singleton or TLS  釋放後,注意把註冊表中的信息清空
            PVMFRECOGNIZER_REGISTRY::registerInstance(NULL, PVMFRECOGNIZER_REGISTRY_ID);
        }
    }
    else
    {
        // Registry has already been cleaned up so nothing to do
    }
}
 
然後就是註冊我們的文件識別組件
OSCL_EXPORT_REF PVMFStatus PVMFRecognizerRegistry::RegisterPlugin(PVMFRecognizerPluginFactory& aPluginFactory)
{
    PVMFRecognizerRegistryImpl* pvrecregimpl = OSCL_STATIC_CAST(PVMFRecognizerRegistryImpl*, PVMFRECOGNIZER_REGISTRY::getInstance(PVMFRECOGNIZER_REGISTRY_ID));
    if (pvrecregimpl != NULL)
    {
        return pvrecregimpl->RegisterPlugin(aPluginFactory);
    }
    else
    {
        // Registry hasn't been initialized yet. Assert
        OSCL_ASSERT(false);
        return PVMFErrNotReady;
    }
}
其實很簡單,調用對應的成員就行了。
下面的幾個函數基本上都是這樣子了,RemovePlugin、OpenSession、CloseSession、Recognize、CancelCommand。
 
下面我們看看
PVMFRecognizerRegistryImpl的實現。
因爲文件的識別是一個比較“卡”的過程,爲 了不讓我們的軟件給人很卡的感官,我們這裏把這個類另闢一個線程來進行,並且以異步的方式來調用,通過命令。
 
識別的命令有下面的兩種類型:
/**
 * PVMFRecRegImplCommandType enum
 *
 *  Enumeration of commands that can be issued to the PVMF Recognizer Registry
 *
 **/
typedef enum
{
    PVMFRECREG_COMMAND_RECOGNIZE = 1,
    PVMFRECREG_COMMAND_CANCELCOMMAND,
} PVMFRecRegImplCommandType;
一個就是開始識別,一個就是取消識別。
class PVMFRecRegSessionInfo
{
    public:
        PVMFRecRegSessionInfo()
        {
        };
 
        PVMFRecRegSessionInfo(const PVMFRecRegSessionInfo& aSrc)
        {
            iRecRegSessionId = aSrc.iRecRegSessionId;
            iRecRegCmdHandler = aSrc.iRecRegCmdHandler;
        };
 
        ~PVMFRecRegSessionInfo()
        {
        };
 
        PVMFSessionId iRecRegSessionId;
        PVMFRecognizerCommmandHandler* iRecRegCmdHandler;
};
識別的一個信 息的保存,一個事識別的sessionID,一個事事件處理。
下面就是一個 命令的具體的封裝,包含一個參數的列表/**
 * PVMFRecRegImplCommand Class
 *
 * PVMFRecRegImplCommand class is a data class to hold issued commands inside the recognizer registry impl
 **/
class PVMFRecRegImplCommand
{
    public:
        /**
         * The constructor for PVMFRecRegImplCommand which allows the data values to be set.
         *
         * @param aCmdType The command type value for this command.
         * @param aCmdId The command ID assigned for this command.
         * @param aContextData The pointer to the passed-in context data for this command.
         * @param aParamVector The optional pointer to a list of parameters
         *
         * @returns None
         **/初始化就是一個參數 列表
        PVMFRecRegImplCommand(PVMFSessionId aSessionId, int32 aCmdType, PVMFCommandId aCmdId, OsclAny* aContextData = NULL,
                              Oscl_Vector<PVMFRecRegImplCommandParamUnion, OsclMemAllocator>* aParamVector = NULL, bool aAPICommand = true) :
                iSessionId(aSessionId), iCmdType(aCmdType), iCmdId(aCmdId), iContextData(aContextData), iAPICommand(aAPICommand)
        {
            iParamVector.clear();
            if (aParamVector)
            {
                iParamVector = *aParamVector;
            }
        }
 
        /**
         * The copy constructor for PVMFRecRegImplCommand. Used mainly for Oscl_Vector.
         *
         * @param aCmd The reference to the source PVMFRecRegImplCommand to copy the data values from.
         *
         * @returns None
         **/
        PVMFRecRegImplCommand(const PVMFRecRegImplCommand& aCmd)
        {
            iSessionId = aCmd.iSessionId;
            iCmdType = aCmd.iCmdType;
            iCmdId = aCmd.iCmdId;
            iContextData = aCmd.iContextData;
            iAPICommand = aCmd.iAPICommand;
            iParamVector = aCmd.iParamVector;
        }
 
        /**
         * This function returns the session ID for the command
         *
         * @returns The session ID value for this command.
         **/
        PVMFSessionId GetSessionId()const
        {
            return iSessionId;
        }
 
        /**
         * This function returns the stored command type value.
         *
         * @returns The signed 32-bit command type value for this command.
         **/
        int32 GetCmdType()const
        {
            return iCmdType;
        }
 
        /**
         * This function returns the stored command ID value.
         *
         * @returns The PVMFCommandId value for this command.
         **/
        PVMFCommandId GetCmdId()const
        {
            return iCmdId;
        }
 
        /**
         * This function returns the stored context data pointer.
         *
         * @returns The pointer to the context data for this command
         **/
        OsclAny* GetContext()const
        {
            return iContextData;
        }
 
        /**
         * This function tells whether the command is an API command or not
         *
         * @returns true if API command, false if not.
         **/
        bool IsAPICommand()const
        {
            return iAPICommand;
        }
 
        /**
         * This function returns the command parameter from the specified index.
         * If the specified index is not available, empty parameter will be returned
         *
         * @param aIndex The index of the parameter to return
         *
         * @returns The stored parameter for this command
         **/
        PVMFRecRegImplCommandParamUnion GetParam(uint32 aIndex)const
        {
            if (aIndex >= iParamVector.size())
            {
                PVMFRecRegImplCommandParamUnion param;
                oscl_memset(&param, 0, sizeof(PVMFRecRegImplCommandParamUnion));
                return param;
            }
            else
            {
                return iParamVector[aIndex];
            }
        }
 
        bool operator==(const PVMFRecRegImplCommand& x)const
        {
            return iCmdId == x.iCmdId;
        }
 
        PVMFSessionId iSessionId;
        int32 iCmdType;
        PVMFCommandId iCmdId;
        OsclAny* iContextData;
        bool iAPICommand;
        Oscl_Vector<PVMFRecRegImplCommandParamUnion, OsclMemAllocator> iParamVector;
};
上面就是一個帶參數的識別命令。
然後有一個優先級的比較:
class PVMFRecRegImplCommandCompareLess
{
    public:
        /**
        * The algorithm used in OsclPriorityQueue needs a compare function
        * that returns true when A's priority is less than B's
        * @return true if A's priority is less than B's, else false
        */
        int compare(PVMFRecRegImplCommand& a, PVMFRecRegImplCommand& b) const
        {
            int a_pri = PVMFRecRegImplCommandCompareLess::GetPriority(a);
            int b_pri = PVMFRecRegImplCommandCompareLess::GetPriority(b);
            if (a_pri < b_pri)
            {
                // Higher priority
                return true;
            }
            else if (a_pri == b_pri)
            {
                // Same priority so look at the command ID to maintain FIFO
                return (a.GetCmdId() > b.GetCmdId());
            }
            else
            {
                // Lower priority
                return false;
            }
        }
 
        /**
        * Returns the priority of each command
        * @return A 0-based priority number. A lower number indicates lower priority.
        */
        static int GetPriority(PVMFRecRegImplCommand& aCmd)
        {
            switch (aCmd.GetCmdType())
            {
                case PVMFRECREG_COMMAND_RECOGNIZE:
                    return 5;
                case PVMFRECREG_COMMAND_CANCELCOMMAND:
                    return 3;
                default:
                    return 0;
            }
        }
};
 
如何識別的?
/**
 * Implementation of the recognizer registry. The recognizer interface class should only
 * use this class.
 **/
這裏爲什麼要 從PvmiDataStreamObserver來繼承,因爲我們的識別就必須讀取一部分的字節,必然會有相關的data數據流的操作,這裏是一個簡單的事件監控。爲什麼要從OsclTimerObject,因爲我們識別是單開線程的,並且識別有一個時間的上線。
class PVMFRecognizerRegistryImpl : public OsclTimerObject,
            public PvmiDataStreamObserver
{
    public:
        PVMFRecognizerRegistryImpl();
        ~PVMFRecognizerRegistryImpl();
註冊和註銷識 別插件
        PVMFStatus RegisterPlugin(PVMFRecognizerPluginFactory& aPluginFactory);
        PVMFStatus RemovePlugin(PVMFRecognizerPluginFactory& aPluginFactory);
        PVMFStatus OpenSession(PVMFSessionId& aSessionId, PVMFRecognizerCommmandHandler& aCmdHandler);
        PVMFStatus CloseSession(PVMFSessionId aSessionId);
識別
        PVMFCommandId Recognize(PVMFSessionId aSessionId, PVMFDataStreamFactory& aSourceDataStreamFactory, PVMFRecognizerMIMEStringList* aFormatHint,
                                Oscl_Vector<PVMFRecognizerResult, OsclMemAllocator>& aRecognizerResult, OsclAny* aCmdContext, uint32 aTimeout);
        PVMFCommandId CancelCommand(PVMFSessionId aSessionId, PVMFCommandId aCommandToCancelId, OsclAny* aCmdContext);
 
        // Reference count for the registry implementation
        int32 iRefCount;  註冊的Plug個數
 
private:
這個我懷疑是這樣的,同時可能有多個識別的操作,那麼就需要列表處理
        PVMFSessionId iNextSessionId;
        PVMFCommandId iNextCommandId;
 
        // From OsclTimerObject
        void Run();
 
        // Vector to hold the active sessions
        Oscl_Vector<PVMFRecRegSessionInfo, OsclMemAllocator> iRecognizerSessionList;
 
        // Vector to hold the available recognizer plug-in
        Oscl_Vector<PVMFRecognizerPluginFactory*, OsclMemAllocator> iRecognizerPluginFactoryList;
 
        int32 FindPluginFactory(PVMFRecognizerPluginFactory& aFactory);
        PVMFRecognizerPluginInterface* CreateRecognizerPlugin(PVMFRecognizerPluginFactory& aFactory);
        void DestroyRecognizerPlugin(PVMFRecognizerPluginFactory& aFactory, PVMFRecognizerPluginInterface* aPlugin);
 
        // Vector to hold pending, current, and to-cancel commands
        OsclPriorityQueue<PVMFRecRegImplCommand, OsclMemAllocator, Oscl_Vector<PVMFRecRegImplCommand, OsclMemAllocator>, PVMFRecRegImplCommandCompareLess> iRecognizerPendingCmdList;
        Oscl_Vector<PVMFRecRegImplCommand, OsclMemAllocator> iRecognizerCurrentCmd;
        Oscl_Vector<PVMFRecRegImplCommand, OsclMemAllocator> iRecognizerCmdToCancel;
 
        PVMFCommandId AddRecRegCommand(PVMFSessionId aSessionId, int32 aCmdType, OsclAny* aContextData = NULL, Oscl_Vector<PVMFRecRegImplCommandParamUnion, OsclMemAllocator>* aParamVector = NULL, bool aAPICommand = true);
        void CompleteCurrentRecRegCommand(PVMFStatus aStatus, const uint32 aCurrCmdIndex = 0, PVInterface* aExtInterface = NULL);
        bool FindCommandByID(Oscl_Vector<PVMFRecRegImplCommand, OsclMemAllocator> &aCmdQueue, const PVMFCommandId aCmdId);
 
        // Command handling functions
        void DoRecognize();
        void CompleteRecognize(PVMFStatus aStatus);
        void DoCancelCommand(PVMFRecRegImplCommand& aCmd);
 
        PVMFDataStreamFactory* iDataStreamFactory;
        PVMIDataStreamSyncInterface* iDataStream;
        PvmiDataStreamSession iDataStreamSessionID;
        PvmiDataStreamCommandId iRequestReadCapacityNotificationID;
 
        PVMFStatus GetMaxRequiredSizeForRecognition(uint32& aMaxSize);
        PVMFStatus GetMinRequiredSizeForRecognition(uint32& aMinSize);
        PVMFStatus CheckForDataAvailability();
 
        //logger
        PVLogger* iLogger;
 
        /* From PvmiDataStreamObserver */
        void DataStreamCommandCompleted(const PVMFCmdResp& aResponse);
        void DataStreamInformationalEvent(const PVMFAsyncEvent& aEvent);
        void DataStreamErrorEvent(const PVMFAsyncEvent& aEvent);
 
        bool oRecognizePending;
        PVMFStatus iDataStreamCallBackStatus;
};
 
這個函數具體是如何實現的,有興趣的可以繼續看一下,我小看了一下,基本上就是一個for循環識別文件的格式。並且這種框架 很容易擴展新的文件格式。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章