mp4vpyld.cpp
来自「symbian 下的helix player源代码」· C++ 代码 · 共 1,393 行 · 第 1/2 页
CPP
1,393 行
/* ***** 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 _APPEND_VOL_HEADER
// #define _DONOT_SEGMENT
// #define _ASSERT_ON_LOSS
// #define _DUMP_FIRST_NFRAMES 5
#define _OVERALLOC_CODEC_DATA 3
#define MP4V_RN_PAYLOAD_MIME_TYPE "video/X-RN-MP4"
#define MP4V_3016_PAYLOAD_MIME_TYPE "video/MP4V-ES"
#define MP4V_RN_3GPP_H263_PAYLOAD_MIME_TYPE "video/X-RN-3GPP-H263"
#define FLUSH_ALL_PACKETS 0xFFFFFFFF
#define MAX_FRAME_SEGMENTS 1024
#define NUM_OVERLAP_SEGMENTS 256
#define DLFT_MAX_PACKET_DATA_SIZE 0x7FFFFFFF
#define CHAR_LF 0x0a
#define CHAR_CR 0x0d
#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 "sdptools.h"
#include "mp4desc.h"
#include "mp4vpyld.h"
#include "mp4pyldutil.h"
MP4VPayloadFormat::MP4VPayloadFormat(CHXBufferMemoryAllocator* pAllocator)
: m_lRefCount (0)
, m_pClassFactory (NULL)
, m_pStreamHeader (NULL)
, m_pVOLHeader (NULL)
, m_ulVOLHeaderSize (0)
, m_ulSamplesPerSecond(1000)
, m_bFlushed (FALSE)
, m_bFirstPacket (TRUE)
, m_bFirstFrame (TRUE)
, m_bUsesRTPPackets (FALSE)
, m_bRTPPacketTested(FALSE)
, m_pAllocator (pAllocator)
, m_bPacketize (FALSE)
, m_ulFrameCount (0)
, m_uSeqNumber (0)
, m_bPictureStarted (FALSE)
, m_ulMaxPacketDataSize(DLFT_MAX_PACKET_DATA_SIZE)
, m_PayloadID (PYID_X_HX_MP4)
{
if (m_pAllocator)
{
m_pAllocator->AddRef();
}
}
MP4VPayloadFormat::~MP4VPayloadFormat()
{
FlushPackets(FLUSH_ALL_PACKETS);
HX_VECTOR_DELETE(m_pVOLHeader);
if (m_pAllocator)
{
m_pAllocator->Release();
m_pAllocator = NULL;
}
HX_RELEASE(m_pClassFactory);
HX_RELEASE(m_pStreamHeader);
}
// *** IUnknown methods ***
/////////////////////////////////////////////////////////////////////////
// Method:
// IUnknown::QueryInterface
// Purpose:
// Implement this to export the interfaces supported by your
// object.
//
STDMETHODIMP
MP4VPayloadFormat::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)
MP4VPayloadFormat::AddRef()
{
return InterlockedIncrement(&m_lRefCount);
}
/////////////////////////////////////////////////////////////////////////
// Method:
// IUnknown::Release
// Purpose:
// Everyone usually implements this the same... feel free to use
// this implementation.
//
STDMETHODIMP_(ULONG32)
MP4VPayloadFormat::Release()
{
if (InterlockedDecrement(&m_lRefCount) > 0)
{
return m_lRefCount;
}
delete this;
return 0;
}
STDMETHODIMP
MP4VPayloadFormat::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);
}
return retVal;
}
STDMETHODIMP
MP4VPayloadFormat::Reset()
{
// Release all input packets we have stored
FlushPackets(FLUSH_ALL_PACKETS);
m_bFlushed = FALSE;
m_bFirstPacket = TRUE;
m_bFirstFrame = TRUE;
m_bPictureStarted = FALSE;
m_bUsesRTPPackets = FALSE;
m_bRTPPacketTested = FALSE;
m_ulFrameCount = 0;
m_uSeqNumber = 0;
m_TSConverter.Reset();
return HXR_OK;
}
STDMETHODIMP
MP4VPayloadFormat::SetStreamHeader(IHXValues* pHeader)
{
HX_RESULT retVal = HXR_OK;
HX_ASSERT(pHeader);
HX_RELEASE(m_pStreamHeader);
m_pStreamHeader = pHeader;
if (m_pStreamHeader)
{
m_pStreamHeader->AddRef();
}
if (m_bPacketize)
{
retVal = SetPacketizerHeader(pHeader);
}
else
{
retVal = SetAssemblerHeader(pHeader);
}
return retVal;
}
HX_RESULT MP4VPayloadFormat::SetPacketizerHeader(IHXValues* pHeader)
{
IHXBuffer* pMimeType = NULL;
const char* pMimeTypeData = NULL;
HX_RESULT 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;
}
}
if (SUCCEEDED(retVal))
{
if (strcasecmp(pMimeTypeData, MP4V_3016_PAYLOAD_MIME_TYPE) == 0)
{
m_PayloadID = PYID_MP4V_ES;
if (DLFT_MAX_PACKET_DATA_SIZE != m_ulMaxPacketDataSize)
{
retVal = pHeader->SetPropertyULONG32
("MaxPacketSize", m_ulMaxPacketDataSize);
}
}
else if (strcasecmp(pMimeTypeData, MP4V_RN_PAYLOAD_MIME_TYPE) == 0)
{
m_PayloadID = PYID_X_HX_MP4;
}
else if (strcasecmp(pMimeTypeData, MP4V_RN_3GPP_H263_PAYLOAD_MIME_TYPE) == 0)
{
m_PayloadID = PYID_X_HX_3GPP_H263;
}
}
HX_RELEASE(pMimeType);
return retVal;
}
HX_RESULT MP4VPayloadFormat::SetAssemblerHeader(IHXValues* pHeader)
{
IHXBuffer* pMimeType = NULL;
const char* pMimeTypeData = NULL;
HX_RESULT retVal = HXR_OK;
HX_VECTOR_DELETE(m_pVOLHeader);
m_ulVOLHeaderSize = 0;
if (SUCCEEDED(retVal))
{
retVal = pHeader->GetPropertyCString("MimeType", pMimeType);
}
if (SUCCEEDED(retVal))
{
pMimeTypeData = (char*) pMimeType->GetBuffer();
retVal = HXR_FAIL;
if (pMimeTypeData)
{
retVal = HXR_OK;
}
}
if (SUCCEEDED(retVal))
{
if (strcasecmp(pMimeTypeData, MP4V_3016_PAYLOAD_MIME_TYPE) == 0)
{
m_PayloadID = PYID_MP4V_ES;
retVal = SetAssembler3016Header(pHeader);
}
else if (strcasecmp(pMimeTypeData, MP4V_RN_PAYLOAD_MIME_TYPE) == 0)
{
m_PayloadID = PYID_X_HX_MP4;
retVal = SetAssemblerHXHeader(pHeader);
}
else if (strcasecmp(pMimeTypeData, MP4V_RN_3GPP_H263_PAYLOAD_MIME_TYPE) == 0)
{
m_PayloadID = PYID_X_HX_3GPP_H263;
retVal = SetAssemblerHX3GPPH263Header(pHeader);
}
}
if (SUCCEEDED(retVal))
{
m_ulSamplesPerSecond = 0;
m_pStreamHeader->GetPropertyULONG32("SamplesPerSecond",
m_ulSamplesPerSecond);
}
HX_RELEASE(pMimeType);
return retVal;
}
HX_RESULT MP4VPayloadFormat::SetAssembler3016Header(IHXValues* pHeader)
{
ULONG32 ulTryIdx = 0;
char *pData = NULL;
IHXBuffer* pConfigBuffer = NULL;
char* pConfigStringData;
HX_RESULT retVal = HXR_NO_DATA;
retVal = CHXMP4PayloadUtil::GetFMTPConfig(pHeader, m_pClassFactory,
pConfigBuffer);
if (retVal == HXR_OK)
{
m_ulVOLHeaderSize = pConfigBuffer->GetSize();
if (m_ulVOLHeaderSize > 0)
{
m_pVOLHeader = new UINT8 [m_ulVOLHeaderSize];
if (m_pVOLHeader)
{
memcpy(m_pVOLHeader, pConfigBuffer->GetBuffer(),
m_ulVOLHeaderSize);
}
else
{
m_ulVOLHeaderSize = 0;
retVal = HXR_OUTOFMEMORY;
}
}
}
HX_RELEASE(pConfigBuffer);
return retVal;
}
HX_RESULT MP4VPayloadFormat::SetAssemblerHXHeader(IHXValues* pHeader)
{
ES_Descriptor ESDesc;
DecoderConfigDescriptor* pDCDesc = NULL;
DecoderSpecifcInfo* pDSIDesc = NULL;
IHXBuffer* pESDescriptor = NULL;
UINT8* pESDescData;
ULONG32 ulESDescSize;
HX_RESULT retVal = HXR_OK;
HX_VECTOR_DELETE(m_pVOLHeader);
m_ulVOLHeaderSize = 0;
retVal = m_pStreamHeader->GetPropertyBuffer("OpaqueData",
pESDescriptor);
if (SUCCEEDED(retVal))
{
retVal = HXR_INVALID_PARAMETER;
if (pESDescriptor)
{
retVal = HXR_OK;
}
}
if (SUCCEEDED(retVal))
{
pESDescData = pESDescriptor->GetBuffer();
ulESDescSize = pESDescriptor->GetSize();
retVal = ESDesc.Unpack(pESDescData, ulESDescSize);
}
HX_RELEASE(pESDescriptor);
if (SUCCEEDED(retVal))
{
retVal = HXR_FAIL;
pDCDesc = ESDesc.m_pDecConfigDescr;
if (pDCDesc)
{
pDSIDesc = pDCDesc->m_pDecSpecificInfo;
retVal = HXR_OK;
}
}
if (SUCCEEDED(retVal) && pDSIDesc)
{
m_ulVOLHeaderSize = pDSIDesc->m_ulLength;
if (m_ulVOLHeaderSize > 0)
{
m_pVOLHeader = new UINT8 [m_ulVOLHeaderSize];
if (m_pVOLHeader == NULL)
{
m_ulVOLHeaderSize = 0;
retVal = HXR_OUTOFMEMORY;
}
}
}
if (SUCCEEDED(retVal))
{
if (m_ulVOLHeaderSize > 0)
{
memcpy(m_pVOLHeader, pDSIDesc->m_pData, m_ulVOLHeaderSize); /* Flawfinder: ignore */
}
}
return retVal;
}
HX_RESULT MP4VPayloadFormat::SetAssemblerHX3GPPH263Header(IHXValues* pHeader)
{
HX_RESULT retVal = HXR_OK;
// We'll let H263 decoder initialize with in-band bitstream
HX_VECTOR_DELETE(m_pVOLHeader);
m_ulVOLHeaderSize = 0;
return retVal;
}
STDMETHODIMP
MP4VPayloadFormat::GetStreamHeader(REF(IHXValues*) pHeader)
{
HX_ASSERT(m_pStreamHeader);
pHeader = m_pStreamHeader;
pHeader->AddRef();
return HXR_OK;
}
STDMETHODIMP
MP4VPayloadFormat::SetPacket(IHXPacket* pPacket)
{
HX_RESULT retVal;
HX_ASSERT(pPacket);
if (!m_bRTPPacketTested)
{
IHXRTPPacket* pRTPPacket = NULL;
m_bUsesRTPPackets = (pPacket->QueryInterface(
IID_IHXRTPPacket,
(void**) &pRTPPacket)
== HXR_OK);
m_bRTPPacketTested = TRUE;
HX_RELEASE(pRTPPacket);
if (!m_bUsesRTPPackets)
{
m_ulSamplesPerSecond = 1000; // RDT time stamp
}
HX_ASSERT(m_ulSamplesPerSecond != 0);
m_TSConverter.SetBase(m_ulSamplesPerSecond,
1000);
}
// Add this packet to our list of input packets
pPacket->AddRef();
m_InputPackets.AddTail(pPacket);
if (m_bPacketize)
{
retVal = SetPacketizerPacket(pPacket);
}
else
{
retVal = SetAssemblerPacket(pPacket);
}
return retVal;
}
HX_RESULT MP4VPayloadFormat::SetPacketizerPacket(IHXPacket* pPacket)
{
if (m_bFirstFrame)
{
m_bFirstFrame = FALSE;
}
return HXR_OK;
}
HX_RESULT MP4VPayloadFormat::SetAssemblerPacket(IHXPacket* pPacket)
{
BOOL bNewPictureStart;
if (!pPacket->IsLost())
{
bNewPictureStart = IsPictureStart(pPacket);
if (m_bFirstPacket)
{
m_bFirstPacket = FALSE;
m_ulFrameTime = GetPacketTime(pPacket);
}
if ((GetPacketTime(pPacket) != m_ulFrameTime) ||
(bNewPictureStart && m_bPictureStarted))
{
m_ulFrameCount++;
m_ulFrameTime = GetPacketTime(pPacket);
}
if (pPacket->GetASMRuleNumber() == 1)
{
m_ulFrameCount++;
m_bFirstPacket = TRUE;
m_bPictureStarted = FALSE;
}
else if (!m_bPictureStarted)
{
m_bPictureStarted = bNewPictureStart;
}
}
return HXR_OK;
}
STDMETHODIMP
MP4VPayloadFormat::GetPacket(REF(IHXPacket*) pOutPacket)
{
HX_RESULT retVal = HXR_OK;
IHXPacket* pPacket = NULL;
if (m_InputPackets.IsEmpty())
{
if (m_bFlushed)
{
// We have used up all available input
retVal = HXR_STREAM_DONE;
}
else
{
// We don't have enough input
// data to produce a packet
retVal = HXR_INCOMPLETE;
}
}
else
{
if (m_bPacketize)
{
retVal = GetPacketizerPacket(pOutPacket);
}
else
{
retVal = GetAssemblerPacket(pOutPacket);
}
}
return retVal;
}
HX_RESULT MP4VPayloadFormat::GetPacketizerPacket(IHXPacket* &pOutPacket)
{
HX_RESULT retVal = HXR_INCOMPLETE;
if (m_OutputPackets.GetCount() > 0)
{
pOutPacket = (IHXPacket*) m_OutputPackets.RemoveHead();
retVal = HXR_OK;
}
if (retVal == HXR_INCOMPLETE)
{
IHXPacket* pRawPacket = NULL;
do
{
HX_RELEASE(pRawPacket);
retVal = GetRawPacketizerPacket(pRawPacket);
} while ((retVal == HXR_OK) && (!IsValidPacket(pRawPacket)));
if (retVal == HXR_OK)
{
retVal = FragmentPacket(pRawPacket);
pRawPacket->Release();
}
if (retVal == HXR_OK)
{
HX_ASSERT(m_OutputPackets.GetCount() > 0);
retVal = HXR_INCOMPLETE;
if (m_OutputPackets.GetCount() > 0)
{
pOutPacket = (IHXPacket*) m_OutputPackets.RemoveHead();
retVal = HXR_OK;
}
}
}
return retVal;
}
HX_RESULT MP4VPayloadFormat::FragmentPacket(IHXPacket* pPacket)
{
HX_RESULT retVal = HXR_OK;
IHXBuffer* pPacketBuffer = pPacket->GetBuffer();
ULONG32 ulRemainingSize = pPacketBuffer->GetSize();
if (ulRemainingSize > m_ulMaxPacketDataSize)
{
UINT8* pRemainingData = pPacketBuffer->GetBuffer();
ULONG32 ulFragmentSize = m_ulMaxPacketDataSize;
IHXPacket* pNewPacket = NULL;
IHXBuffer* pNewBuffer = NULL;
IHXRTPPacket* pRTPPacket = NULL;
if (m_bUsesRTPPackets)
{
if (SUCCEEDED(retVal))
{
retVal = pPacket->QueryInterface(IID_IHXRTPPacket,
(void**) &pRTPPacket);
}
}
do
{
// Create new packet
if (SUCCEEDED(retVal))
{
if (m_bUsesRTPPackets)
{
retVal = m_pClassFactory->CreateInstance(CLSID_IHXRTPPacket,
(void**) &pNewPacket);
}
else
{
retVal = m_pClassFactory->CreateInstance(CLSID_IHXPacket,
(void**) &pNewPacket);
}
}
// Create new buffer
if (SUCCEEDED(retVal))
{
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?