📄 smlffpln.cpp
字号:
m_ulCurrentBufferPos = 0;
m_ulCurrentPacket = 0;
// This file format is not a container type, so it only supports one
// stream and therefore one header, but before we do that, we want to
// make sure the file object is initialized; we can't actually return
// the header count until the file init is done... (See InitDone).
m_state = InitPending;
// Note, we need to pass ourself to the FileObject, because this is its
// first opportunity to know that we implement the IHXFileResponse
// interface it will call for completed pending operations
return m_pFileObject->Init( HX_FILE_READ, this);
}
STDMETHODIMP CSmilFileFormat::Close()
{
HX_RELEASE(m_pContext);
if (m_pFileObject)
{
m_pFileObject->Close();
HX_RELEASE(m_pFileObject);
}
if ( m_pArrayOfPackets )
{
int s = m_pArrayOfPackets->GetSize();
for ( int i = s; i > 0; --i )
{
PacketData* pckt = (PacketData*)(*m_pArrayOfPackets)[i-1];
HX_RELEASE(pckt->pBuffer);
HX_DELETE(pckt);
(*m_pArrayOfPackets)[i-1] = NULL;
m_pArrayOfPackets->RemoveAt(i-1);
}
HX_DELETE(m_pArrayOfPackets);
}
if ( m_pCurrentPacketData )
{
HX_RELEASE(m_pCurrentPacketData->pBuffer);
m_pCurrentPacketData->pNumPos = NULL;
HX_DELETE(m_pCurrentPacketData);
}
HX_RELEASE(m_pFFResponse);
HX_RELEASE(m_pRequest);
HX_RELEASE(m_pCommonClassFactory);
HX_RELEASE(m_pStartOfFile);
return HXR_OK;
}
/////////////////////////////////////////////////////////////////////////
// Method:
// IHXFileFormatObject::GetFileHeader
// Purpose:
// Called by controller to ask the file format for the number of
// headers in the file. The file format should call the
// IHXFileFormatSession::HeaderCountReady() for the IHXFileFormat-
// Session object that was passed in during initialization, when the
// header count is available.
//
STDMETHODIMP CSmilFileFormat::GetFileHeader()
{
// If we are not ready then something has gone wrong
if (m_state != Ready) return HXR_UNEXPECTED;
IHXValues* pHeader = 0;
if (HXR_OK != m_pCommonClassFactory->CreateInstance(CLSID_IHXValues,
(void**)&pHeader))
{
return HXR_UNEXPECTED;
}
pHeader->SetPropertyULONG32("StreamCount", 1);
m_pFFResponse->FileHeaderReady(HXR_OK, pHeader);
HX_RELEASE(pHeader);
return HXR_OK;
}
/////////////////////////////////////////////////////////////////////////
// Method:
// IHXFileFormatObject::GetStreamHeader
// Purpose:
// Called by controller to ask the file format for the header for
// a particular stream in the file. The file format should call
// IHXFileFormatSession::StreamHeaderReady() for IHXFileFormatSession
// object that was passed in during initialization, when the header
// is available.
//
STDMETHODIMP CSmilFileFormat::GetStreamHeader(UINT16 unStreamNumber)
{
// If we are not ready then something has gone wrong
if (m_state != Ready) return HXR_UNEXPECTED;
IHXBuffer* pASM = 0;
char pBook[256]; /* Flawfinder: ignore */
IHXValues* pHeader = 0;
IHXBuffer* pBuffer = 0;
if (HXR_OK != m_pCommonClassFactory->CreateInstance(CLSID_IHXValues,
(void**)&pHeader))
{
return HXR_UNEXPECTED;
}
if (HXR_OK != m_pCommonClassFactory->CreateInstance(CLSID_IHXBuffer,
(void**)&pBuffer))
{
return HXR_UNEXPECTED;
}
BOOL bBeta1Player = ::IsBeta1Player(m_pRequest);
HX_RESULT pnrver = GetSMILFileVersion();
if (HXR_OK != pnrver ||
SMILFileVersionSmil10 == m_smilFileVersion)
{
if(bBeta1Player)
{
pBuffer->Set((const BYTE*)
zm_pStreamMimeTypes[SMILFileVersionSmilBeta10],
strlen(zm_pStreamMimeTypes[SMILFileVersionSmilBeta10])+1);
}
else
{
pBuffer->Set(
(const BYTE*)zm_pStreamMimeTypes[SMILFileVersionSmil10],
strlen(zm_pStreamMimeTypes[SMILFileVersionSmil10])+1);
}
}
else if (SMILFileVersionSmil10Strict == m_smilFileVersion)
{
// /Send strictly-declared SMIL 1.0 streams to the SMIL 2.0 renderer
pBuffer->Set((const BYTE*)
zm_pStreamMimeTypes[SMILFileVersionSmil10Strict],
strlen(zm_pStreamMimeTypes[SMILFileVersionSmil10Strict])+1);
}
else if (SMILFileVersionSmil20PreRec == m_smilFileVersion)
{
pBuffer->Set((const BYTE*)
zm_pStreamMimeTypes[SMILFileVersionSmil20PreRec],
strlen(zm_pStreamMimeTypes[SMILFileVersionSmil20PreRec])+1);
}
else if (SMILFileVersionSmil20 == m_smilFileVersion)
{
pBuffer->Set((const BYTE*)
zm_pStreamMimeTypes[SMILFileVersionSmil20],
strlen(zm_pStreamMimeTypes[SMILFileVersionSmil20])+1);
}
else // /Too high a version number as far as this ff is concerned:
// /XXXEH: should we use the namespace (if there is one) to determine
// the mime type and, if there is one, send it and let the player deal
// with the auto update (if needed)? Or, should we encourage server
// (hence smil ff) updating by just not serving the stream? That's
// what I'm doing here:
{
pBuffer->Set((const BYTE*)
zm_pStreamMimeTypes[SMILFileVersionUnknown],
strlen(zm_pStreamMimeTypes[SMILFileVersionUnknown])+1);
}
pHeader->SetPropertyCString("MimeType", pBuffer);
HX_RELEASE(pBuffer);
pHeader->SetPropertyULONG32("StreamNumber", unStreamNumber);
//XXXEH- removed 20000 (20sec) duration that BAB put in "to avoid problem
// in core" in 1998(?). 0 milliseconds seems to work fine now (3/2000):
pHeader->SetPropertyULONG32("Duration", 0);
pHeader->SetPropertyULONG32("PreRoll", 1000); //XXXBAB 'cause Rahul told me to
pHeader->SetPropertyULONG32("AvgBitRate", 1000);
pHeader->SetPropertyULONG32("StreamVersion", m_ulStreamVersion);
pHeader->SetPropertyULONG32("ContentVersion", m_ulContentVersion);
//
// set ASM rule book
//
sprintf(pBook, "TimestampDelivery=TRUE,priority=10;"); /* Flawfinder: ignore */
if(HXR_OK == m_pCommonClassFactory->CreateInstance(CLSID_IHXBuffer,
(void**)&pASM))
{
pASM->Set((BYTE*)pBook, strlen(pBook)+1);
pHeader->SetPropertyCString("ASMRuleBook", pASM);
HX_RELEASE(pASM);
}
m_bHeaderSent = TRUE;
m_pFFResponse->StreamHeaderReady(HXR_OK, pHeader);
HX_RELEASE(pHeader);
return HXR_OK;
}
/////////////////////////////////////////////////////////////////////////
// Method:
// IHXFileFormatObject::GetPacket
// Purpose:
// Called by controller to ask the file format for the next packet
// for a particular stream in the file. The file format should call
// IHXFileFormatSession::PacketReady() for the IHXFileFormatSession
// object that was passed in during initialization, when the packet
// is available.
//
STDMETHODIMP CSmilFileFormat::GetPacket(UINT16 unStreamNumber)
{
HX_RESULT result = HXR_OK;
// If we are not ready then something has gone wrong
if (m_state != Ready) return HXR_UNEXPECTED;
if (!m_bHeaderSent)
{
return HXR_UNEXPECTED;
}
IHXPacket* pPacket = NULL;
result = m_pCommonClassFactory->CreateInstance(CLSID_IHXPacket,
(void**)&pPacket);
if( SUCCEEDED(result) )
{
if(m_ulCurrentPacket >= m_ulPacketCount)
{
m_pFFResponse->StreamDone(unStreamNumber);
}
else
{
PacketData* pckt = (PacketData*)(*m_pArrayOfPackets)[m_ulCurrentPacket++];
if ( pckt->pNumPos )
{
char buf[10]; /* Flawfinder: ignore */
sprintf(buf, "%u", m_ulPacketCount); /* Flawfinder: ignore */
HX_ASSERT(strlen(buf) < 7);
strncpy(pckt->pNumPos, buf, strlen(buf)); /* Flawfinder: ignore */
pckt->pNumPos = NULL;
}
#ifdef DUMPFILEFORMATOUTPUT
FILE* stream = fopen( "C:\\PacketData.smil", "a" );
fprintf( stream, "%s\n", (const char*)pckt->pBuffer->GetBuffer());
fclose( stream );
#endif
pPacket->Set(pckt->pBuffer, 0, unStreamNumber, HX_ASM_SWITCH_ON, 0);
m_pFFResponse->PacketReady(HXR_OK, pPacket);
}
}
HX_RELEASE(pPacket);
return result;
}
/////////////////////////////////////////////////////////////////////////
// Method:
// IHXFileFormatObject::Seek
// Purpose:
// Called by controller to tell the file format to seek to the
// nearest packet to the requested offset. The file format should
// call IHXFileFormatSession::SeekDone() for the IHXFileFormat-
// Session object that was passed in during initialization, when
// the seek has completed.
//
STDMETHODIMP CSmilFileFormat::Seek(ULONG32 ulOffset)
{
m_pFFResponse->SeekDone(HXR_OK);
return HXR_OK;
}
/////////////////////////////////////////////////////////////////////////
// Method:
// IHXFileResponse::InitDone
// Purpose:
// Notification interface provided by users of the IHXFileObject
// interface. This method is called by the IHXFileObject when the
// initialization of the file is complete, and the Mime type is
// available for the request file. If the URL is not valid for the
// file system, the status HXR_FAILED should be returned,
// with a mime type of NULL. If the URL is valid but the mime type
// is unknown, then the status HXR_OK should be returned with
// a mime type of NULL.
//
STDMETHODIMP CSmilFileFormat::InitDone
(
HX_RESULT status
)
{
HX_RESULT rc = HXR_OK;
// If we are not ready then something has gone wrong
if (m_state != InitPending) return HXR_UNEXPECTED;
// Now it's time to read the file
m_state = ReadPending;
if (status != HXR_OK)
{
rc = m_pFFResponse->InitDone(status);
}
else
{
// check to see if we have logged an error for this file
// in the last hour. If we have we will not log an error.
UpdateErrorCaching();
rc = m_pFileObject->Read(FileChunkSize);
}
return rc;
}
HX_RESULT CSmilFileFormat::UpdateErrorCaching()
{
IHXValues* pRequestHeaders = NULL;
UINT32 ulID = 0, ulSes = 0;
IHXRegistry* pReg = NULL;
m_pContext->QueryInterface(IID_IHXRegistry, (void**)&pReg);
HX_RESULT ret = m_pRequest->GetRequestHeaders(pRequestHeaders);
if (!pRequestHeaders)
{
// succeeds even when there are no request headers.
ret = HXR_FAIL;
}
if (SUCCEEDED(ret))
{
IHXBuffer* pID = NULL;
ret = pRequestHeaders->GetPropertyCString("ConnID", pID);
if (SUCCEEDED(ret) && pID)
{
ulID = atoi((char*)pID->GetBuffer());
}
HX_RELEASE(pID);
}
if (SUCCEEDED(ret))
{
IHXBuffer* pSes = NULL;
if (SUCCEEDED(pRequestHeaders->GetPropertyCString("SessionNumber", pSes)))
{
ulSes = atoi((char*)pSes->GetBuffer());
}
else
{
// assume 0
ulSes = 0;
}
HX_RELEASE(pSes);
}
IHXBuffer* pURL = NULL;
if (SUCCEEDED(ret))
{
const char form[] = "client.%u.session.%u.URL";
char pRegkey[sizeof(form) + 20]; /* Flawfinder: ignore */
sprintf(pRegkey, form, ulID, ulSes); /* Flawfinder: ignore */
ret = pReg->GetStrByName(pRegkey, pURL);
}
char* buf = NULL;
const char regtemp[] = "server.smilerrorlog.";
if ( SUCCEEDED(ret) )
{
buf = new char[sizeof(regtemp) + pURL->GetSize()];
if (!buf)
{
ret = HXR_OUTOFMEMORY;
}
}
if (SUCCEEDED(ret))
{
strcpy(buf, regtemp); /* Flawfinder: ignore */
char* pos = buf + sizeof(regtemp) - 1;
const char* url = (const char*)pURL->GetBuffer();
// escape the '.'s
while (*url && pos < buf + sizeof(regtemp) + pURL->GetSize())
{
if (*url == '.' || *url == '/')
{
*pos++ = '%';
++url;
}
else
{
*pos++ = *url++;
}
}
*pos = '\0';
}
if (SUCCEEDED(ret))
{
INT32 lTime = 0;
INT32 lNow = time(NULL);
if (SUCCEEDED(pReg->GetIntByName(buf, lTime)))
{
if ((lNow - lTime) > 3600)
{
m_bLogErrors = TRUE;
ret = pReg->SetIntByName(buf, lNow);
}
else
{
m_bLogErrors = FALSE;
}
}
else
{
m_bLogErrors = TRUE;
pReg->AddInt(buf, lNow);
}
}
HX_RELEASE(pReg);
HX_RELEASE(pRequestHeaders);
HX_VECTOR_DELETE(buf);
HX_RELEASE(pURL);
return ret;
}
/////////////////////////////////////////////////////////////////////////
// Method:
// IHXFileResponse::CloseDone
// Purpose:
// Notification interface provided by users of the IHXFileObject
// interface. This method is called by the IHXFileObject when the
// close of the file is complete.
//
STDMETHODIMP CSmilFileFormat::CloseDone(HX_RESULT status)
{
return HXR_OK;
}
/////////////////////////////////////////////////////////////////////////
// Method:
// IHXFileResponse::ReadDone
// Purpose:
// Notification interface provided by users of the IHXFileObject
// interface. This method is called by the IHXFileObject when the
// last read from the file is complete and a buffer is available.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -