qtffplin.cpp
来自「symbian 下的helix player源代码」· C++ 代码 · 共 2,308 行 · 第 1/4 页
CPP
2,308 行
/* ***** BEGIN LICENSE BLOCK *****
* Version: RCSL 1.0/RPSL 1.0
*
* Portions Copyright (c) 1995-2002 RealNetworks, Inc. All Rights Reserved.
*
* The contents of this file, and the files included with this file, are
* subject to the current version of the RealNetworks Public Source License
* Version 1.0 (the "RPSL") available at
* http://www.helixcommunity.org/content/rpsl unless you have licensed
* the file under the RealNetworks Community Source License Version 1.0
* (the "RCSL") available at http://www.helixcommunity.org/content/rcsl,
* in which case the RCSL will apply. You may also obtain the license terms
* directly from RealNetworks. You may not use this file except in
* compliance with the RPSL or, if you have a valid RCSL with RealNetworks
* applicable to this file, the RCSL. Please see the applicable RPSL or
* RCSL for the rights, obligations and limitations governing use of the
* contents of the file.
*
* This file is part of the Helix DNA Technology. RealNetworks is the
* developer of the Original Code and owns the copyrights in the portions
* it created.
*
* This file, and the files included with this file, is distributed and made
* available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
*
* Technology Compatibility Kit Test Suite(s) Location:
* http://www.helixcommunity.org/content/tck
*
* Contributor(s):
*
* ***** END LICENSE BLOCK ***** */
/****************************************************************************
* Defines
*/
#define NO_STREAM_SET 0xFFFF
#define FSWCHR_MAX_CHILD_COUNT 20
/****************************************************************************
* Includes
*/
#include "qtffplin.ver"
#include "hxtypes.h"
#include "hxcom.h"
#include "hxstrutl.h"
#include "hxcomm.h"
#include "ihxpckts.h"
#include "hxfiles.h"
#include "hxformt.h"
#include "hxplugn.h"
#include "hxpends.h"
#include "hxengin.h"
#include "hxerror.h"
#include "hxupgrd.h"
#include "hxmon.h"
#include "hxbrdcst.h"
#include "hxcore.h"
#include "hxprefs.h"
#include "defslice.h"
#include "qtres.h"
#include "hxsdesc.h"
#include "hxstring.h"
#include "qtffplin.h"
#include "netbyte.h"
#include "hxver.h"
#include "hxxres.h"
#include "hxxrsmg.h"
#include "dbcs.h"
#include "sdpchunk.h"
#include "sdppyldinfo.h"
#include "qtffrefcounter.h"
#include "qttrack.h"
#include "qtpktasm.h"
/****************************************************************************
* Constants
*/
#define QTFF_AU_PREFIX "FileFormat/"
#define QTFF_AU_PREFIX_SIZE (sizeof(QTFF_AU_PREFIX) - 1)
#define MAX_EXTENSION_SIZE 256
#define QTBUFFERFRAGMENT_POOL_SIZE 50
#define QTBUFFERFRAGMENT_INITIAL_POOL_SIZE 5
const char* const CQTFileFormat::zm_pDescription = "RealNetworks Mpeg4 File Format Plugin";
const char* const CQTFileFormat::zm_pCopyright = HXVER_COPYRIGHT;
const char* const CQTFileFormat::zm_pMoreInfoURL = HXVER_MOREINFO;
#define EXT_3GP "3gp"
#define EXT_3G2 "3g2"
#define EXT_MP4 "mp4"
#define EXT_M4A "m4a"
#define EXT_MOV "mov", "qt"
#define ONM_3GP "3GPP-MP4 Files (*.3gp, *.3g2)"
#define ONM_MP4 "MP4 Files (*.mp4)"
#define ONM_MOV "QuickTime Files (*.mov, *.qt)"
const char* const CQTFileFormat::zm_pFileMimeTypes[] = {"application/x-pn-quicktime-stream", "audio/3gpp", "video/3gpp", NULL};
const char* const CQTFileFormat::zm_pFileExtensions[] = {EXT_MOV, EXT_MP4, EXT_3GP, EXT_3G2, EXT_M4A, NULL};
const char* const CQTFileFormat::zm_pFileOpenNames[] = {ONM_MOV, ONM_MP4, ONM_3GP, NULL};
const char* const CQTFileFormat::zm_pPacketFormats[] = {"rtp", "rdt", NULL};
#define WIDTH_METANAME "Width"
#define HEIGHT_METANAME "Height"
/****************************************************************************
* Globals
*/
g_base_nRefCount_qtff_TypeModifier INT32 g_base_nRefCount_qtff = 0;
/****************************************************************************
* Constructor/Destructor
*/
CQTFileFormat::CQTFileFormat()
: m_lRefCount(0)
, m_pContext(NULL)
, m_pFFResponse(NULL)
, m_pClassFactory(NULL)
, m_pScheduler(NULL)
, m_pRequest(NULL)
, m_pFileSwitcher(NULL)
, m_pAtomizer(NULL)
, m_pPacketAssembler(NULL)
, m_State(QTFF_Offline)
, m_pPacketCache(NULL)
, m_uNextPacketStreamNum(NO_STREAM_SET)
, m_ulPendingSeekTime(0)
, m_pErrorMessages(NULL)
, m_bQTLicensed(FALSE)
, m_bMP4Licensed(FALSE)
, m_uFormatFlavor(MAX_QTFORMAT_FLAVOR)
, m_bViewSourceRequest(FALSE)
#ifdef QTCONFIG_BFRAG_FACTORY
, m_pBufferFragmentFactory(NULL)
#endif // QTCONFIG_BFRAG_FACTORY
, m_ulStreamMetaInfoMask(META_INFO_NONE)
{
g_nRefCount_qtff++;
}
CQTFileFormat::~CQTFileFormat()
{
Close();
g_nRefCount_qtff--;
}
/************************************************************************
* IHXPlugin methods
*/
/************************************************************************
* IHXPlugin::InitPlugin
* Purpose:
* Initializes the plugin for use. This interface must always be
* called before any other method is called. This is primarily needed
* so that the plugin can have access to the context for creation of
* IHXBuffers and IMalloc.
*/
STDMETHODIMP CQTFileFormat::InitPlugin(IUnknown* /*IN*/ pContext)
{
HX_RESULT retVal = HXR_OK;
if (pContext)
{
m_pContext = pContext;
m_pContext->AddRef();
}
else
{
retVal = HXR_INVALID_PARAMETER;
}
/*
* Check for license
*/
if (SUCCEEDED(retVal))
{
retVal = CheckLicense();
}
if (SUCCEEDED(retVal))
{
HX_ASSERT(!m_pErrorMessages);
pContext->QueryInterface(IID_IHXErrorMessages,
(void**) &m_pErrorMessages);
retVal = pContext->QueryInterface(IID_IHXCommonClassFactory,
(void**)&m_pClassFactory);
}
if (SUCCEEDED(retVal))
{
retVal = pContext->QueryInterface(IID_IHXScheduler,
(void**)&m_pScheduler);
}
return retVal;
}
/************************************************************************
* IHXPlugin::GetPluginInfo
* Purpose:
* Returns the basic information about this plugin. Including:
*
* bLoadMultiple whether or not this plugin DLL can be loaded
* multiple times. All File Formats must set
* this value to TRUE.
* pDescription which is used in about UIs (can be NULL)
* pCopyright which is used in about UIs (can be NULL)
* pMoreInfoURL which is used in about UIs (can be NULL)
*/
STDMETHODIMP CQTFileFormat::GetPluginInfo
(
REF(BOOL) bLoadMultiple,
REF(const char*) pDescription,
REF(const char*) pCopyright,
REF(const char*) pMoreInfoURL,
REF(ULONG32) ulVersionNumber
)
{
bLoadMultiple = TRUE; // Must be true for file formats.
pDescription = (const char*) zm_pDescription;
pCopyright = (const char*) zm_pCopyright;
pMoreInfoURL = (const char*) zm_pMoreInfoURL;
ulVersionNumber = TARVER_ULONG32_VERSION;
return HXR_OK;
}
/************************************************************************
* IHXFileFormatObject methods
*/
/************************************************************************
* GetFileFormatInfo
* Purpose:
* If this object is a file format object this method returns
* information vital to the instantiation of file format plugins.
* If this object is not a file format object, it should return
* HXR_UNEXPECTED.
*/
STDMETHODIMP CQTFileFormat::GetFileFormatInfo
(
REF(const char**) /*OUT*/ pFileMimeTypes,
REF(const char**) /*OUT*/ pFileExtensions,
REF(const char**) /*OUT*/ pFileOpenNames
)
{
pFileMimeTypes = (const char**) zm_pFileMimeTypes;
pFileExtensions = (const char**) zm_pFileExtensions;
pFileOpenNames = (const char**) zm_pFileOpenNames;
return HXR_OK;
}
/************************************************************************
* InitFileFormat
*/
STDMETHODIMP CQTFileFormat::InitFileFormat
(
IHXRequest* /*IN*/ pRequest,
IHXFormatResponse* /*IN*/ pFileFormatResponse,
IHXFileObject* /*IN*/ pFileObject
)
{
HX_RESULT retVal = HXR_OK;
if (m_State != QTFF_Offline)
{
return HXR_UNEXPECTED;
}
m_State = QTFF_Init;
if ((pFileFormatResponse == NULL) ||
(pFileObject == NULL))
{
retVal = HXR_FAIL;
}
HX_RELEASE(m_pFFResponse);
m_pFFResponse = pFileFormatResponse;
m_pFFResponse->AddRef();
HX_RELEASE(m_pRequest);
m_pRequest = pRequest;
if (m_pRequest)
{
m_pRequest->AddRef();
}
if (SUCCEEDED(retVal) && m_pRequest)
{
IHXValues* pRequestHeaders = NULL;
if (SUCCEEDED(m_pRequest->GetRequestHeaders(pRequestHeaders)) &&
pRequestHeaders)
{
ULONG32 ulVal = 0;
if (SUCCEEDED(pRequestHeaders->GetPropertyULONG32(
"ViewSourceInfoHeaders",
ulVal)))
{
m_bViewSourceRequest = ((ulVal == 0) ? FALSE : TRUE);
}
IHXBuffer* pBuffer = NULL;
retVal = pRequestHeaders->GetPropertyCString("AcceptMetaInfo",
pBuffer);
if(SUCCEEDED(retVal))
{
retVal = ExtractAcceptMetaInfo(pBuffer);
}
// We want to proceed even if metadata fails.
retVal = HXR_OK;
HX_RELEASE(pBuffer);
}
HX_RELEASE(pRequestHeaders);
}
if (SUCCEEDED(retVal))
{
HX_RELEASE(m_pFileSwitcher);
HX_RELEASE(m_pAtomizer);
#ifdef QTCONFIG_FSWITCHER
m_pFileSwitcher = (IHXFileSwitcher*) new CFileSwitcher();
#else // QTCONFIG_FSWITCHER
m_pFileSwitcher = (IHXFileSwitcher*) new CFileSwitcherPassthrough();
#endif // QTCONFIG_FSWITCHER
if (m_pFileSwitcher)
{
m_pFileSwitcher->AddRef();
}
else
{
retVal = HXR_OUTOFMEMORY;
}
}
if (SUCCEEDED(retVal))
{
m_pAtomizer = new CAtomizer();
if (m_pAtomizer)
{
m_pAtomizer->AddRef();
}
else
{
retVal = HXR_OUTOFMEMORY;
}
}
if (SUCCEEDED(retVal))
{
m_pPacketAssembler = new CQTPacketAssembler();
if (m_pPacketAssembler)
{
m_pPacketAssembler->AddRef();
retVal = m_pPacketAssembler->Init(this);
}
else
{
retVal = HXR_OUTOFMEMORY;
}
}
if (SUCCEEDED(retVal))
{
retVal = m_pFileSwitcher->Init(pFileObject,
HX_FILE_READ | HX_FILE_BINARY,
(IHXFileResponse*) this,
m_pContext,
FSWCHR_MAX_CHILD_COUNT);
}
if (FAILED(retVal))
{
m_State = QTFF_Error;
}
return retVal;
}
HX_RESULT
CQTFileFormat::ExtractAcceptMetaInfo(IHXBuffer* pRequestedInfoBuffer)
{
HX_RESULT res = HXR_OK;
if(!pRequestedInfoBuffer)
{
res = HXR_POINTER;
HX_ASSERT(FALSE);
return res;
}
const char* pRequestedInfo = NULL;
if (pRequestedInfoBuffer)
{
pRequestedInfo = (const char*) pRequestedInfoBuffer->GetBuffer();
}
if(*pRequestedInfo == '*')
{
m_ulStreamMetaInfoMask |= META_INFO_ALL;
}
#ifdef QTCONFIG_SERVER
else if (pRequestedInfo)
{
const char* pName;
ULONG32 ulNameLength;
// Set requested Meta Info
do
{
pName = pRequestedInfo;
while ((*pRequestedInfo != '\0') &&
(*pRequestedInfo != ','))
{
pRequestedInfo++;
}
ulNameLength = (ULONG32) (pRequestedInfo - pName);
if (ulNameLength > 0)
{
if ((strlen(WIDTH_METANAME) == ulNameLength) &&
(strncmp(pName, WIDTH_METANAME, ulNameLength) == 0))
{
m_ulStreamMetaInfoMask |= META_INFO_WIDTH;
}
else if ((strlen(HEIGHT_METANAME) == ulNameLength) &&
(strncmp(pName, HEIGHT_METANAME, ulNameLength) == 0))
{
m_ulStreamMetaInfoMask |= META_INFO_HEIGHT;
}
}
if (*pRequestedInfo == '\0')
{
break;
}
pRequestedInfo++;
} while (TRUE);
}
#endif // QTCONFIG_SERVER
return res;
}
HX_RESULT CQTFileFormat::MakeFileHeader(HX_RESULT status)
{
HX_RESULT retVal;
IHXValues* pHeader = NULL;
IHXBuffer* pTitle = NULL;
// Check the license
#ifdef QTCONFIG_SERVER
if(SUCCEEDED(status))
{
switch(m_TrackManager.GetFType())
{
case QT_FTYPE_QT:
case QT_FTYPE_UNKNOWN:
{
if(!m_bQTLicensed)
{
ReportError(IDS_ERR_QT_NOTLICENSED, HXR_NOT_LICENSED);
return m_pFFResponse->FileHeaderReady(
HXR_NOT_LICENSED, NULL);
}
break;
}
case QT_FTYPE_MP4:
{
if(!m_bMP4Licensed)
{
ReportError(IDS_ERR_MP4_NOTLICENSED, HXR_NOT_LICENSED);
return m_pFFResponse->FileHeaderReady(
HXR_NOT_LICENSED, NULL);
}
break;
}
}
}
#endif // QTCONFIG_SERVER
// Create needed buffers
if (SUCCEEDED(status))
{
status = m_pClassFactory->CreateInstance(CLSID_IHXValues,
(void**) &pHeader);
}
if (SUCCEEDED(status))
{
status = m_pClassFactory->CreateInstance(CLSID_IHXBuffer,
(void**) &pTitle);
}
// Set Title
if (SUCCEEDED(status) && (m_MovieInfo.GetNameLength() > 0))
{
UCHAR* pTitleMem;
ULONG32 ulTitleMemLength = 0;
status = pTitle->SetSize(m_MovieInfo.GetNameLength() + 1);
if (SUCCEEDED(status))
{
pTitle->Get(pTitleMem, ulTitleMemLength);
memcpy(pTitleMem, m_MovieInfo.GetName(), ulTitleMemLength - 1); /* Flawfinder: ignore */
pTitleMem[ulTitleMemLength - 1] = '\0';
pHeader->SetPropertyBuffer("Title", pTitle);
}
}
HX_RELEASE(pTitle);
if (SUCCEEDED(status))
{
status = GetSessionIdentity(pHeader, &m_MovieInfo);
}
#ifdef QTCONFIG_ALTERNATE_STREAMS
// Set stream groupings
if (SUCCEEDED(status))
{
UINT16 uStrmIdx;
ULONG32 ulGroupID;
ULONG32 ulGroupBitrate;
CQTTrack* pTrack;
IHXValues* pGroupInfo = NULL;
for (uStrmIdx = 0;
uStrmIdx < m_TrackManager.GetNumStreams();
uStrmIdx++)
{
pTrack = m_TrackManager.GetStreamTrack(uStrmIdx);
if (pTrack->m_TrackInfo.GetSDPLength() > 0)
{
retVal = SDPParseChunk(
(char*) pTrack->m_TrackInfo.GetSDP(),
pTrack->m_TrackInfo.GetSDPLength(),
pGroupInfo,
m_pClassFactory,
SDPCTX_Group,
FALSE);
if (pGroupInfo &&
(pGroupInfo->GetPropertyULONG32("AlternateGroupID",
ulGroupID)
== HXR_OK))
{
if (pGroupInfo->GetPropertyULONG32("AlternateGroupBitrate",
ulGroupBitrate)
!= HXR_OK)
{
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?