mp4vpyld.cpp
上传用户:zhongxx05
上传日期:2007-06-06
资源大小:33641k
文件大小:29k
- /* ***** 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))
- {
- retVal = m_pClassFactory->CreateInstance(CLSID_IHXBuffer,
- (void**) &pNewBuffer);
- }
- // Set Buffer
- if (SUCCEEDED(retVal))
- {
- retVal = pNewBuffer->Set(pRemainingData, ulFragmentSize);
- }
- // Set the new packet
- if (SUCCEEDED(retVal))
- {
- if (SUCCEEDED(retVal))
- {
- if (m_bUsesRTPPackets)
- {
- retVal = ((IHXRTPPacket*) pNewPacket)->SetRTP(
- pNewBuffer,
- pRTPPacket->GetTime(),
- pRTPPacket->GetRTPTime(),
- pRTPPacket->GetStreamNumber(),
- pRTPPacket->GetASMFlags(),
- (ulRemainingSize > m_ulMaxPacketDataSize) ?
- 0 : pRTPPacket->GetASMRuleNumber());
- }
- else
- {
- retVal = ((IHXRTPPacket*) pNewPacket)->Set(
- pNewBuffer,
- pPacket->GetTime(),
- pPacket->GetStreamNumber(),
- pPacket->GetASMFlags(),
- (ulRemainingSize > m_ulMaxPacketDataSize) ?
- 0 : pPacket->GetASMRuleNumber());
- }
- }
- }
- pRemainingData += ulFragmentSize;
- ulRemainingSize -= ulFragmentSize;
- if (ulRemainingSize < ulFragmentSize)
- {
- ulFragmentSize = ulRemainingSize;
- }
- if (SUCCEEDED(retVal))
- {
- pNewPacket->AddRef();
- m_OutputPackets.AddTail(pNewPacket);
- }
- HX_RELEASE(pNewBuffer);
- HX_RELEASE(pNewPacket);
- } while (SUCCEEDED(retVal) && (ulRemainingSize > 0));
- HX_RELEASE(pRTPPacket);
- }
- else
- {
- pPacket->AddRef();
- m_OutputPackets.AddTail(pPacket);
- }
- HX_RELEASE(pPacketBuffer);
- return retVal;
- }
- HX_RESULT MP4VPayloadFormat::GetRawPacketizerPacket(IHXPacket* &pOutPacket)
- {
- IHXPacket* pPacket;
- IHXPacket* pAfterPacket = NULL;
- IHXRTPPacket* pRTPPacket = NULL;
- UINT16 uASMRuleNumber;
- BOOL bMarker = TRUE;
- BOOL bNewPictureStart = TRUE;
- HX_RESULT retVal = HXR_INCOMPLETE;
- if ((m_InputPackets.GetCount() > 1) ||
- m_bFlushed)
- {
- retVal = HXR_OK;
- pPacket = (IHXPacket*) m_InputPackets.RemoveHead();
- if (!m_bPictureStarted)
- {
- m_bPictureStarted = IsPictureStart(pPacket);
- }
- if (m_bFirstPacket)
- {
- m_bFirstPacket = FALSE;
- }
- // Determine marker usage
- if (m_InputPackets.GetCount() > 0)
- {
- pAfterPacket = (IHXPacket*) m_InputPackets.GetHead();
- }
- if (pAfterPacket)
- {
- bNewPictureStart = IsPictureStart(pAfterPacket);
- bMarker = ((GetPacketTime(pPacket) != GetPacketTime(pAfterPacket)) ||
- (bNewPictureStart && m_bPictureStarted));
- if (bMarker)
- {
- m_bPictureStarted = bNewPictureStart;
- }
- }
- else
- {
- bMarker = m_bFlushed;
- }
- uASMRuleNumber = bMarker ? 1 : 0;
- // If rule number must change, create new packet
- if (uASMRuleNumber != pPacket->GetASMRuleNumber())
- {
- IHXPacket* pNewPacket = NULL;
- if (m_bUsesRTPPackets)
- {
- retVal = m_pClassFactory->CreateInstance(CLSID_IHXRTPPacket,
- (void**) &pNewPacket);
- if (SUCCEEDED(retVal))
- {
- retVal = pPacket->QueryInterface(IID_IHXRTPPacket,
- (void**) &pRTPPacket);
- }
- }
- else
- {
- retVal = m_pClassFactory->CreateInstance(CLSID_IHXPacket,
- (void**) &pNewPacket);
- }
- if (SUCCEEDED(retVal))
- {
- IHXBuffer* pBuffer = pPacket->GetBuffer();
- if (m_bUsesRTPPackets)
- {
- retVal = ((IHXRTPPacket*) pNewPacket)->SetRTP(
- pBuffer,
- pRTPPacket->GetTime(),
- pRTPPacket->GetRTPTime(),
- pRTPPacket->GetStreamNumber(),
- pRTPPacket->GetASMFlags(),
- uASMRuleNumber);
- }
- else
- {
- retVal = ((IHXRTPPacket*) pNewPacket)->Set(
- pBuffer,
- pPacket->GetTime(),
- pPacket->GetStreamNumber(),
- pPacket->GetASMFlags(),
- uASMRuleNumber);
- }
- HX_RELEASE(pBuffer);
- }
- pPacket->Release();
- pPacket = NULL;
- if (SUCCEEDED(retVal))
- {
- pPacket = pNewPacket;
- pNewPacket = NULL;
- }
- HX_RELEASE(pNewPacket);
- HX_RELEASE(pRTPPacket);
- }
- if (SUCCEEDED(retVal))
- {
- pOutPacket = pPacket;
- }
- }
- return retVal;
- }
- HX_RESULT MP4VPayloadFormat::GetAssemblerPacket(IHXPacket* &pOutPacket)
- {
- HX_RESULT retVal = HXR_NOTIMPL;
- return retVal;
- }
- void MP4VPayloadFormat::FlushPackets(ULONG32 ulCount)
- {
- IHXPacket* pDeadPacket;
- while ((ulCount > 0) && (!m_InputPackets.IsEmpty()))
- {
- pDeadPacket = (IHXPacket*) m_InputPackets.RemoveHead();
- HX_RELEASE(pDeadPacket);
- if (ulCount != FLUSH_ALL_PACKETS)
- {
- ulCount--;
- }
- }
- }
- ULONG32 MP4VPayloadFormat::CountValidPackets(ULONG32 ulCount)
- {
- IHXPacket* pPacket;
- LISTPOSITION listPos;
- ULONG32 ulValidCount = 0;
- listPos = m_InputPackets.GetHeadPosition();
- while ((ulCount > 0) && (listPos != NULL))
- {
- pPacket = (IHXPacket*) m_InputPackets.GetNext(listPos);
- HX_ASSERT(pPacket);
- if (!pPacket->IsLost())
- {
- ulValidCount++;
- }
- ulCount--;
- }
- return ulValidCount;
- }
- ULONG32 MP4VPayloadFormat::SumPacketSizes(ULONG32 ulCount)
- {
- IHXPacket* pPacket;
- IHXBuffer* pBuffer;
- LISTPOSITION listPos;
- ULONG32 ulSize = 0;
- listPos = m_InputPackets.GetHeadPosition();
- while ((ulCount > 0) && (listPos != NULL))
- {
- pPacket = (IHXPacket*) m_InputPackets.GetNext(listPos);
- HX_ASSERT(pPacket);
- if (!pPacket->IsLost())
- {
- pBuffer = pPacket->GetBuffer();
- if (pBuffer)
- {
- ulSize += pBuffer->GetSize();
- pBuffer->Release();
- }
- }
- ulCount--;
- }
- return ulSize;
- }
- HX_RESULT MP4VPayloadFormat::CreateHXCodecPacket(UINT32* &pHXCodecDataOut)
- {
- HX_RESULT retVal = HXR_INCOMPLETE;
- if (m_ulFrameCount > 0)
- {
- // Compute frame size and count segments
- ULONG32 ulFrameSize = 0;
- ULONG32 ulSegmentCount = 0;
- ULONG32 ulSegmentSize;
- ULONG32 ulFrameTime = 0;
- ULONG32 ulValidSegmentCount = 0;
- IHXPacket* pPacket;
- IHXBuffer* pBuffer = NULL;
- LISTPOSITION listPos;
- ULONG32 ulIdx;
- BOOL bIsLost;
- BOOL bPictureStarted = FALSE;
- BOOL bNewPictureStart;
- HXCODEC_DATA* pHXCodecData = NULL;
- HXCODEC_SEGMENTINFO* pHXCodecSegmentInfo;
- ULONG32* pData = NULL;
- retVal = HXR_OK;
- // Gather Frame Information - until valid frame detected
- do
- {
- listPos = m_InputPackets.GetHeadPosition();
- if( listPos == NULL )
- {
- return HXR_OUTOFMEMORY;
- }
- do
- {
- if (ulSegmentCount >= MAX_FRAME_SEGMENTS)
- {
- HX_ASSERT(pPacket);
- FlushPackets(ulSegmentCount - NUM_OVERLAP_SEGMENTS);
- ulSegmentCount = NUM_OVERLAP_SEGMENTS;
- ulFrameSize = SumPacketSizes(NUM_OVERLAP_SEGMENTS);
- ulValidSegmentCount = CountValidPackets(NUM_OVERLAP_SEGMENTS);
- }
- pPacket = (IHXPacket*) m_InputPackets.GetNext(listPos);
- if (!pPacket->IsLost())
- {
- bNewPictureStart = IsPictureStart(pPacket);
- if (ulValidSegmentCount > 0)
- {
- if ((GetPacketTime(pPacket) != ulFrameTime) ||
- (bPictureStarted && bNewPictureStart))
- {
- break;
- }
- }
- else
- {
- ulFrameTime = GetPacketTime(pPacket);
- }
- if (!bPictureStarted)
- {
- bPictureStarted = bNewPictureStart;
- }
- ulValidSegmentCount++;
- pBuffer = pPacket->GetBuffer();
- }
- if (pBuffer)
- {
- ulFrameSize += pBuffer->GetSize();
- pBuffer->Release();
- pBuffer = NULL;
- }
- ulSegmentCount++;
- } while (pPacket->GetASMRuleNumber() != 1);
- m_ulFrameCount--;
- } while ((ulValidSegmentCount == 0) &&
- (m_ulFrameCount > 0));
- if (ulValidSegmentCount == 0)
- {
- retVal = HXR_INCOMPLETE;
- }
- // Allocate codec data header
- if (retVal == HXR_OK)
- {
- HX_ASSERT(ulSegmentCount != 0);
- HX_ASSERT(ulValidSegmentCount != 0);
- #ifdef _APPEND_VOL_HEADER
- if (m_bFirstFrame)
- {
- ulFrameSize += m_ulVOLHeaderSize;
- }
- #endif // _APPEND_VOL_HEADER
- pData = new ULONG32[(sizeof(HXCODEC_DATA) +
- sizeof(HXCODEC_SEGMENTINFO) *
- (ulSegmentCount - 1)) / 4 + 1];
- retVal = HXR_OUTOFMEMORY;
- if (pData)
- {
- retVal = HXR_OK;
- }
- }
- // Init. codec data header
- if (retVal == HXR_OK)
- {
- pHXCodecData = (HXCODEC_DATA*) pData;
- pHXCodecData->dataLength = ulFrameSize;
- pHXCodecData->timestamp = ulFrameTime;
- pHXCodecData->sequenceNum = m_uSeqNumber;
- pHXCodecData->flags = 0;
- pHXCodecData->lastPacket = FALSE;
- pHXCodecData->numSegments = ulSegmentCount;
- pHXCodecData->data = NULL;
- if ((ulFrameSize > 0)
- #ifndef _OVERALLOC_CODEC_DATA
- &&
- (
- (ulValidSegmentCount > 1) ||
- (m_pAllocator == NULL)
- #ifdef _APPEND_VOL_HEADER
- || m_bFirstFrame
- #endif // _APPEND_VOL_HEADER
- )
- #endif // _OVERALLOC_CODEC_DATA
- )
- {
- #ifdef _OVERALLOC_CODEC_DATA
- ulFrameSize += _OVERALLOC_CODEC_DATA; // over allocate since codec reads 24bits at a time
- #endif // _OVERALLOC_CODEC_DATA
- if (m_pAllocator)
- {
- IHXUnknown* pIUnkn = NULL;
- HX20ALLOCPROPS allocRequest;
- HX20ALLOCPROPS allocActual;
- allocRequest.uBufferSize = ulFrameSize;
- allocRequest.nNumBuffers = 0;
- m_pAllocator->SetProperties(&allocRequest, &allocActual);
- pHXCodecData->data = m_pAllocator->GetPacketBuffer(&pIUnkn);
- }
- else
- {
- pHXCodecData->data = (UINT8*) new ULONG32 [ulFrameSize / 4 + 1];
- }
- if (pHXCodecData->data == NULL)
- {
- retVal = HXR_OUTOFMEMORY;
- }
- }
- }
- // Build Codec Data
- if (retVal == HXR_OK)
- {
- BOOL bNoneLost = TRUE;
- pHXCodecSegmentInfo = (HXCODEC_SEGMENTINFO*) &(pHXCodecData->Segments[0]);
- ulFrameSize = 0;
- for (ulIdx = 0; ulIdx < ulSegmentCount; ulIdx++)
- {
- HX_ASSERT(!m_InputPackets.IsEmpty());
- pPacket = (IHXPacket*) m_InputPackets.RemoveHead();
- HX_ASSERT(pPacket);
- ulSegmentSize = 0;
- pHXCodecSegmentInfo[ulIdx].ulSegmentOffset = ulFrameSize;
- bIsLost = pPacket->IsLost();
- if (!bIsLost)
- {
- pBuffer = pPacket->GetBuffer();
- if (pHXCodecData->data)
- {
- if (m_bFirstFrame)
- {
- #ifdef _APPEND_VOL_HEADER
- memcpy(pHXCodecData->data, m_pVOLHeader, m_ulVOLHeaderSize); /* Flawfinder: ignore */
- ulFrameSize += m_ulVOLHeaderSize;
- #endif // _APPEND_VOL_HEADER
- m_bFirstFrame = FALSE;
- }
- if (pBuffer)
- {
- ulSegmentSize = pBuffer->GetSize();
- HX_ASSERT(pHXCodecData->dataLength >= (ulFrameSize + ulSegmentSize));
- memcpy(pHXCodecData->data + ulFrameSize, /* Flawfinder: ignore */
- pBuffer->GetBuffer(),
- ulSegmentSize);
- pBuffer->Release();
- }
- }
- else
- {
- HX_ASSERT(m_pAllocator);
- HX_ASSERT(ulValidSegmentCount == 1);
- #ifdef _APPEND_VOL_HEADER
- HX_ASSERT(m_bFirstFrame == FALSE);
- #endif // _APPEND_VOL_HEADER
- if (pBuffer)
- {
- ulSegmentSize = pBuffer->GetSize();
- pHXCodecData->data = m_pAllocator->AddBuffer(pBuffer);
- pBuffer->Release();
- }
- }
- ulFrameSize += ulSegmentSize;
- }
- pHXCodecSegmentInfo[ulIdx].bIsValid = !bIsLost;
- bNoneLost = (bNoneLost && (!bIsLost));
- pPacket->Release();
- }
- if (bNoneLost)
- {
- pHXCodecData->numSegments = 1;
- }
- #ifdef _ASSERT_ON_LOSS
- else
- {
- HX_ASSERT(FALSE);
- }
- #endif // _ASSERT_ON_LOSS
- #ifdef _DONOT_SEGMENT
- pHXCodecData->numSegments = 1;
- pHXCodecSegmentInfo[0].bIsValid = bNoneLost;
- #endif // _DONOT_SEGMENT
- }
- // Finalize Results
- if (retVal == HXR_OK)
- {
- pHXCodecDataOut = pData;
- }
- else
- {
- if (pHXCodecData && pHXCodecData->data)
- {
- m_pAllocator->ReleasePacketPtr(pHXCodecData->data);
- }
- HX_VECTOR_DELETE(pData);
- }
- #ifdef _DUMP_FIRST_NFRAMES
- if (m_uSeqNumber < _DUMP_FIRST_NFRAMES)
- {
- char pFileName[100]; /* Flawfinder: ignore */
- SafeSprintf(pFileName, 100, "%s%d", "c:\fframe.bin", m_uSeqNumber);
- FILE* pFile = fopen(pFileName, "wb");
- if (pFile)
- {
- fprintf(pFile, "T=%ld;B=%ld:", pHXCodecData->timestamp, pHXCodecData->dataLength);
- fwrite(pHXCodecData->data, sizeof(UINT8), pHXCodecData->dataLength, pFile);
- fclose(pFile);
- }
- }
- #endif // _DUMP_FIRST_NFRAMES
- m_uSeqNumber++;
- }
- return retVal;
- }
- STDMETHODIMP
- MP4VPayloadFormat::Flush()
- {
- m_bFlushed = TRUE;
- return HXR_OK;
- }
- BOOL MP4VPayloadFormat::IsPictureStart(IHXPacket* pPacket)
- {
- if (m_PayloadID == PYID_X_HX_MP4)
- {
- ULONG32 ulIdx;
- ULONG32 ulSize = 0;
- UINT8* pData = NULL;
- IHXBuffer* pBuffer;
- pBuffer = pPacket->GetBuffer();
- if (pBuffer)
- {
- ulSize = pBuffer->GetSize();
- if (ulSize >= 4)
- {
- ulSize -= 4;
- pData = pBuffer->GetBuffer();
- }
- pBuffer->Release();
- }
- if (pData)
- {
- ulIdx = 0;
- do
- {
- if (pData[ulIdx++] == 0x00)
- {
- if (pData[ulIdx++] == 0x00)
- {
- if (pData[ulIdx] == 0x01)
- {
- ulIdx++;
- if (pData[ulIdx] == 0xb6)
- {
- return TRUE;
- }
- }
- else
- {
- ulIdx--;
- }
- }
- }
- } while (ulIdx < ulSize);
- }
- }
- return FALSE;
- }
- BOOL MP4VPayloadFormat::IsValidPacket(IHXPacket* pPacket)
- {
- if (m_PayloadID == PYID_X_HX_MP4)
- {
- ULONG32 ulSize;
- UINT8* pData = NULL;
- IHXBuffer* pBuffer = pPacket->GetBuffer();
- if (pBuffer)
- {
- ulSize = pBuffer->GetSize();
- if (ulSize >= 4)
- {
- ulSize -= 4;
- pData = pBuffer->GetBuffer();
- }
- pBuffer->Release();
- }
- if (pData)
- {
- // Should be more sophisiticated here and fully parse the
- // headeres and make sure there is no data of substance
- // following the headers - for this prototype code it
- // is good enough
- if ((pData[0] == 0x00) &&
- (pData[1] == 0x00) &&
- (pData[2] == 0x01) &&
- ((pData[3] == 0x00) ||
- (pData[3] == 0x20)))
- {
- return FALSE;
- }
- }
- }
- return TRUE;
- }
- ULONG32 MP4VPayloadFormat::GetPacketTime(IHXPacket* pPacket)
- {
- ULONG32 ulTime;
- HX_ASSERT(pPacket);
- if (m_bUsesRTPPackets && (m_ulSamplesPerSecond != 0))
- {
- ulTime = ((IHXRTPPacket*) pPacket)->GetRTPTime();
- ulTime = m_TSConverter.Convert(ulTime);
- }
- else
- {
- ulTime = pPacket->GetTime();
- }
- return ulTime;
- }