mp4gpyld.cpp
来自「symbian 下的helix player源代码」· C++ 代码 · 共 1,691 行 · 第 1/3 页
CPP
1,691 行
/* ***** 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 _OVERALLOC_CODEC_DATA 3
#define FLUSH_ALL_PACKETS 0xFFFFFFFF
#define CHAR_LF 0x0a
#define CHAR_CR 0x0d
#define FORMAT_PARAMETERS_PREFIX "a=fmtp:0 "
#define FORMAT_PARAMETERS_PREFIX_SIZE (sizeof(FORMAT_PARAMETERS_PREFIX) - 1)
#define MAX_AUPACKETS_IN_RTPPACKET 50
#define MAX_PACKET_FRAGMENTS 256
#define MAX_AU_FRAGMENTS 256
#define MAX_AU_PACKETS 256
#define MAX_INT_TEXT_LENGTH 10
/****************************************************************************
* Includes
*/
#include "hxtypes.h"
#include "hxwintyp.h"
#include "hxcom.h"
#include "hxcomm.h"
#include "hxassert.h"
#include "hxslist.h"
#include "hxstrutl.h"
#include "hxcomm.h"
#include "ihxpckts.h"
#include "hxformt.h"
#include "hxrendr.h"
#include "hxformt.h"
#include "hxengin.h"
#include "bitstuff.h"
#include "sdpchunk.h"
#include "sdptools.h"
#include "mp4gpyld.h"
MP4GPayloadFormat::MP4GPayloadFormat()
: m_lRefCount (0)
, m_pClassFactory (NULL)
, m_pStreamHeader (NULL)
, m_bFlushed (FALSE)
, m_bUsesRTPPackets (FALSE)
, m_bRTPPacketTested (FALSE)
, m_bPacketize (FALSE)
, m_ulSamplesPerSecond (1000)
, m_ulRTPSamplesPerSecond(0)
, m_bPriorLoss (FALSE)
, m_pPacketFragments (NULL)
, m_pAUFragments (NULL)
, m_pAUPackets (NULL)
, m_ulMaxPacketFragments(MAX_PACKET_FRAGMENTS)
, m_ulMaxAUFragments (MAX_AU_FRAGMENTS)
, m_ulMaxAUPackets (MAX_AU_PACKETS)
, m_ulNumPacketFragments(0)
, m_ulNumAUFragments (0)
, m_ulNumAUPackets (0)
, m_bStartPacket (TRUE)
, m_ulAUDuration (0)
, m_ulFrameCount (0)
, m_bLastReapedSet (FALSE)
, m_bEarliestDeintTimeKnown(FALSE)
{
;
}
MP4GPayloadFormat::~MP4GPayloadFormat()
{
Reset();
HX_VECTOR_DELETE(m_pPacketFragments);
HX_VECTOR_DELETE(m_pAUFragments);
HX_VECTOR_DELETE(m_pAUPackets);
HX_RELEASE(m_pClassFactory);
HX_RELEASE(m_pStreamHeader);
}
HX_RESULT MP4GPayloadFormat::Build(REF(IMP4APayloadFormat*) pFmt)
{
pFmt = new MP4GPayloadFormat();
HX_RESULT res = HXR_OUTOFMEMORY;
if (pFmt)
{
pFmt->AddRef();
res = HXR_OK;
}
return res;
}
// *** IUnknown methods ***
/////////////////////////////////////////////////////////////////////////
// Method:
// IUnknown::QueryInterface
// Purpose:
// Implement this to export the interfaces supported by your
// object.
//
STDMETHODIMP
MP4GPayloadFormat::QueryInterface(REFIID riid, void** ppvObj)
{
QInterfaceList qiList[] =
{
{ GET_IIDHANDLE(IID_IUnknown), this },
{ GET_IIDHANDLE(IID_IHXPayloadFormatObject), (IHXPayloadFormatObject*) this },
};
return ::QIFind(qiList, QILISTSIZE(qiList), riid, ppvObj);
}
/////////////////////////////////////////////////////////////////////////
// Method:
// IUnknown::AddRef
// Purpose:
// Everyone usually implements this the same... feel free to use
// this implementation.
//
STDMETHODIMP_(ULONG32)
MP4GPayloadFormat::AddRef()
{
return InterlockedIncrement(&m_lRefCount);
}
/////////////////////////////////////////////////////////////////////////
// Method:
// IUnknown::Release
// Purpose:
// Everyone usually implements this the same... feel free to use
// this implementation.
//
STDMETHODIMP_(ULONG32)
MP4GPayloadFormat::Release()
{
if (InterlockedDecrement(&m_lRefCount) > 0)
{
return m_lRefCount;
}
delete this;
return 0;
}
STDMETHODIMP
MP4GPayloadFormat::Init(IUnknown* pContext,
BOOL bPacketize)
{
HX_RESULT retVal = HXR_OK;
HX_RELEASE(m_pClassFactory);
m_bPacketize = bPacketize;
if (SUCCEEDED(retVal))
{
retVal = pContext->QueryInterface(IID_IHXCommonClassFactory,
(void**) &m_pClassFactory);
}
if (SUCCEEDED(retVal))
{
retVal = HXR_OUTOFMEMORY;
m_pPacketFragments = new IHXPacket* [m_ulMaxPacketFragments];
m_pAUFragments = new CAUPacket* [m_ulMaxAUFragments];
m_pAUPackets = new CAUPacket* [m_ulMaxAUPackets];
if (m_pPacketFragments &&
m_pAUFragments &&
m_pAUPackets)
{
memset(m_pPacketFragments, 0, sizeof(IHXPacket*) * m_ulMaxPacketFragments);
memset(m_pAUFragments, 0, sizeof(CAUPacket*) * m_ulMaxAUFragments);
memset(m_pAUPackets, 0, sizeof(CAUPacket*) * m_ulMaxAUPackets);
retVal = HXR_OK;
}
}
return retVal;
}
STDMETHODIMP
MP4GPayloadFormat::Reset()
{
// Release all input packets we have stored
FlushQueues();
FlushArrays();
m_bFlushed = FALSE;
m_bPriorLoss = FALSE;
m_bStartPacket = TRUE;
m_ulFrameCount = 0;
m_TSConverter.Reset();
return HXR_OK;
}
STDMETHODIMP
MP4GPayloadFormat::SetStreamHeader(IHXValues* pHeader)
{
HX_RESULT retVal;
if (pHeader)
{
m_pStreamHeader = pHeader;
m_pStreamHeader->AddRef();
}
if (m_bPacketize)
{
retVal = SetPacketizerHeader(pHeader);
}
else
{
retVal = SetAssemblerHeader(pHeader);
}
return retVal;
}
HX_RESULT MP4GPayloadFormat::SetPacketizerHeader(IHXValues* pHeader)
{
return HXR_OK;
}
HX_RESULT MP4GPayloadFormat::SetAssemblerHeader(IHXValues* pHeader)
{
IHXBuffer* pMimeType = NULL;
const char* pMimeTypeData = NULL;
HX_RESULT retVal = HXR_INVALID_PARAMETER;
if (pHeader)
{
retVal = HXR_OK;
}
if (SUCCEEDED(retVal))
{
retVal = pHeader->GetPropertyCString("MimeType", pMimeType);
}
if (SUCCEEDED(retVal))
{
pMimeTypeData = (char*) pMimeType->GetBuffer();
retVal = HXR_FAIL;
if (pMimeTypeData)
{
retVal = HXR_OK;
}
}
// Determine payload type here based on mime type
if (SUCCEEDED(retVal))
{
retVal = HXR_FAIL;
if ((strcasecmp(pMimeTypeData, "audio/mpeg4-simple-A2") == 0) ||
(strcasecmp(pMimeTypeData, "audio/x-ralf-mpeg4-generic") == 0) ||
(strcasecmp(pMimeTypeData, "audio/mpeg4-generic") == 0) ||
(strcasecmp(pMimeTypeData, "video/mpeg4-generic") == 0))
{
retVal = HXR_OK;
}
}
if (SUCCEEDED(retVal))
{
char *pData = NULL;
char* pAllocData = NULL;
IHXBuffer* pSDPData = NULL;
IHXValues* pValues = NULL;
ULONG32 ulTryIdx = 0;
do
{
if (ulTryIdx == 0)
{
retVal = pHeader->GetPropertyCString("SDPData", pSDPData);
if (SUCCEEDED(retVal))
{
pData = (char*) pSDPData->GetBuffer();
retVal = HXR_FAIL;
if (pData)
{
retVal = HXR_OK;
}
}
}
else
{
retVal = pHeader->GetPropertyCString("PayloadParameters", pSDPData);
if (SUCCEEDED(retVal))
{
ULONG32 ulDataLen;
pData = (char*) pSDPData->GetBuffer();
ulDataLen = strlen(pData);
pAllocData = new char [ulDataLen +
FORMAT_PARAMETERS_PREFIX_SIZE +
2];
retVal = HXR_OUTOFMEMORY;
if (pAllocData)
{
strcpy(pAllocData, FORMAT_PARAMETERS_PREFIX); /* Flawfinder: ignore */
strcpy(pAllocData + FORMAT_PARAMETERS_PREFIX_SIZE, pData); /* Flawfinder: ignore */
pAllocData[FORMAT_PARAMETERS_PREFIX_SIZE + ulDataLen] =
CHAR_LF;
pAllocData[FORMAT_PARAMETERS_PREFIX_SIZE + 1 + ulDataLen] =
'\0';
pData = pAllocData;
retVal = HXR_OK;
}
}
}
if (SUCCEEDED(retVal))
{
retVal = SDPParseChunk(pData,
strlen(pData),
pValues,
m_pClassFactory,
SDPCTX_Renderer);
}
HX_VECTOR_DELETE(pAllocData);
if (SUCCEEDED(retVal))
{
retVal = SetAssemblerConfig(pValues);
}
if (SUCCEEDED(retVal))
{
m_ulAUDuration = m_Config.m_ulConstantDuration;
}
HX_RELEASE(pSDPData);
HX_RELEASE(pValues);
ulTryIdx++;
} while (FAILED(retVal) && (ulTryIdx < 2));
}
if (SUCCEEDED(retVal))
{
m_pStreamHeader->GetPropertyULONG32("SamplesPerSecond",
m_ulRTPSamplesPerSecond);
}
HX_RELEASE(pMimeType);
return retVal;
}
HX_RESULT MP4GPayloadFormat::SetAssemblerConfig(IHXValues* pFMTParams)
{
return m_Config.Init(pFMTParams, m_pClassFactory);
}
HX_RESULT MP4GPayloadFormat::CFormatConfig::Init(IHXValues* pFMTParams,
IHXCommonClassFactory* pClassFactory)
{
IHXBuffer* pConfigString = NULL;
IHXBuffer* pModeString = NULL;
HX_RESULT retVal = HXR_OK;
HX_ASSERT(pFMTParams);
// Obtain Required parameters
retVal = pFMTParams->GetPropertyULONG32("FMTPstreamtype",
m_ulStreamType);
if (SUCCEEDED(retVal))
{
retVal = pFMTParams->GetPropertyULONG32("FMTPprofile-level-id",
m_ulProfileLevelID);
}
if (SUCCEEDED(retVal))
{
retVal = pFMTParams->GetPropertyCString("FMTPconfig",
pConfigString);
if (FAILED(retVal))
{
ULONG32 ulConfigVal = 0;
retVal = pFMTParams->GetPropertyULONG32("FMTPconfig",
ulConfigVal);
if (SUCCEEDED(retVal))
{
retVal = pClassFactory->CreateInstance(IID_IHXBuffer,
(void**) &pConfigString);
}
if (SUCCEEDED(retVal))
{
retVal = pConfigString->SetSize(MAX_INT_TEXT_LENGTH + 1);
}
if (SUCCEEDED(retVal))
{
SafeSprintf((char*) pConfigString->GetBuffer(), MAX_INT_TEXT_LENGTH + 1, "%ld",
ulConfigVal);
}
}
}
// Obtain optional parameters
if (SUCCEEDED(retVal))
{
pFMTParams->GetPropertyCString("FMTPmode", pModeString);
pFMTParams->GetPropertyULONG32("FMTPConstantSize", m_ulConstantSize);
pFMTParams->GetPropertyULONG32("FMTPConstantDuration", m_ulConstantDuration);
pFMTParams->GetPropertyULONG32("FMTPSizeLength", m_ulSizeLength);
pFMTParams->GetPropertyULONG32("FMTPIndexLength", m_ulIndexLength);
pFMTParams->GetPropertyULONG32("FMTPIndexDeltaLength", m_ulIndexDeltaLength);
pFMTParams->GetPropertyULONG32("FMTPCTSDeltaLength", m_ulCTSDeltaLength);
pFMTParams->GetPropertyULONG32("FMTPDTSDeltaLength", m_ulDTSDeltaLength);
pFMTParams->GetPropertyULONG32("FMTPAuxDataSizeLength", m_ulAuxDataSizeLength);
pFMTParams->GetPropertyULONG32("FMTPProfile", m_ulProfile);
}
// Perform any needed translations
if (SUCCEEDED(retVal))
{
// Determine Mode from Mode String
if (pModeString)
{
const char* pMode = (char*) pModeString->GetBuffer();
if (pMode)
{
if (strcasecmp(pMode, "A0") == 0)
{
m_Mode = MODE_A0;
}
else if (strcasecmp(pMode, "A1") == 0)
{
m_Mode = MODE_A1;
}
else if (strcasecmp(pMode, "A2") == 0)
{
m_Mode = MODE_A2;
}
}
}
// Convert decoder configuration from ascii hex to binary
if (pConfigString)
{
ULONG32 ulConfigSize;
const char* pConfig = (char*) pConfigString->GetBuffer();
IHXBuffer* pConfigBuffer = NULL;
if (pConfig)
{
ulConfigSize = strlen(pConfig) / 2;
if (ulConfigSize > 0)
{
retVal = pClassFactory->CreateInstance(IID_IHXBuffer,
(void**) &pConfigBuffer);
if (SUCCEEDED(retVal))
{
retVal = pConfigBuffer->SetSize(ulConfigSize);
}
if (SUCCEEDED(retVal))
{
retVal = HexStringToBinary(pConfigBuffer->GetBuffer(),
pConfig);
}
}
}
if (SUCCEEDED(retVal))
{
m_pConfig = pConfigBuffer;
if (m_pConfig)
{
m_pConfig->AddRef();
}
}
HX_RELEASE(pConfigBuffer);
}
}
// Compute dervied parameter
if (SUCCEEDED(retVal))
{
m_bHasAUHeaders = ((m_ulSizeLength != 0) ||
(m_ulIndexLength != 0) ||
(m_ulIndexDeltaLength != 0) ||
(m_ulCTSDeltaLength != 0) ||
(m_ulDTSDeltaLength != 0));
}
HX_RELEASE(pModeString);
HX_RELEASE(pConfigString);
return retVal;
}
STDMETHODIMP
MP4GPayloadFormat::GetStreamHeader(REF(IHXValues*) pHeader)
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?