mp4vdfmt.cpp
上传用户:dangjiwu
上传日期:2013-07-19
资源大小:42019k
文件大小:17k
- /* ***** BEGIN LICENSE BLOCK *****
- * Version: RCSL 1.0 and Exhibits.
- * REALNETWORKS CONFIDENTIAL--NOT FOR DISTRIBUTION IN SOURCE CODE FORM
- * 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 Community Source
- * License Version 1.0 (the "RCSL"), including Attachments A though H,
- * all available at http://www.helixcommunity.org/content/rcsl.
- * You may also obtain the license terms directly from RealNetworks.
- * You may not use this file except in compliance with the RCSL and
- * its Attachments. There are no redistribution rights for the source
- * code of this file. Please see the applicable 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:
- * https://rarvcode-tck.helixcommunity.org
- *
- * Contributor(s):
- *
- * ***** END LICENSE BLOCK ***** */
- /****************************************************************************
- * Defines
- */
- #define _IGNORE_UNSUPPORTED
- #define NON_KEYFRM_DCDE_FALLBEHIND_THRSHLD 33 // in milliseconds
- #if defined(HELIX_FEATURE_MIN_HEAP)
- #define MP4V_DEFAULT_PREROLL 2000 // in milliseconds
- #else
- #define MP4V_DEFAULT_PREROLL 3500 // in milliseconds
- #endif
- #define MAX_NONKEY_CODED_FRAME_FALLBEHIND -800
- /****************************************************************************
- * Includes
- */
- #include "mp4vdfmt.h"
- #include "hxasm.h"
- #include "hxwin.h"
- #include "hxvsurf.h"
- #include "hxvctrl.h"
- #include "hxsite2.h"
- #include "hxthread.h"
- #include "hxtick.h"
- #include "hxassert.h"
- #include "hxstrutl.h"
- #include "unkimp.h"
- #include "timeval.h"
- #include "cttime.h"
- #include "hxcodec.h"
- #include "mp4video.h"
- /****************************************************************************
- * Locals
- */
- /****************************************************************************
- * Method:
- * CMP4VideoFormat::CQTVideoFormat
- *
- */
- CMP4VideoFormat::CMP4VideoFormat(IHXCommonClassFactory* pCommonClassFactory,
- CMP4VideoRenderer* pMP4VideoRenderer,
- BOOL bSecure)
- : CVideoFormat(pCommonClassFactory, pMP4VideoRenderer)
- , m_pMP4VideoRenderer(pMP4VideoRenderer)
- , m_pRssm(NULL)
- , m_pDecoder(NULL)
- , m_pInputAllocator(NULL)
- , m_ulMaxDecodedFrames(0)
- {
- HX_ASSERT(m_pCommonClassFactory);
- HX_ASSERT(pMP4VideoRenderer);
- m_DecodedPacket.dataLength = 0;
- m_DecodedPacket.data = NULL;
- m_DecoderDims.cx = 0;
- m_DecoderDims.cy = 0;
- m_pMP4VideoRenderer->AddRef();
- }
- /****************************************************************************
- * Method:
- * CMP4VideoFormat::~CQTVideoFormat
- *
- */
- CMP4VideoFormat::~CMP4VideoFormat()
- {
- CVideoFormat::Reset();
- HX_RELEASE(m_pMP4VideoRenderer);
- if (m_pRssm)
- {
- m_pRssm->Close();
- m_pRssm->Release();
- m_pRssm = NULL;
- }
- HX_DELETE(m_pDecoder);
- _Reset();
- HX_DELETE(m_pInputAllocator);
- }
- /****************************************************************************
- * Method:
- * CMP4VideoFormat::Init
- */
- HX_RESULT CMP4VideoFormat::Init(IHXValues* pHeader)
- {
- HX_RESULT retVal = CVideoFormat::Init(pHeader);
- // Create memory allocators
- if (SUCCEEDED(retVal))
- {
- retVal = CreateAllocators();
- }
- // Create Packet Assembler
- if (SUCCEEDED(retVal))
- {
- retVal = HXR_OUTOFMEMORY;
- m_pRssm = new MP4VPayloadFormat(m_pInputAllocator);
- if (m_pRssm)
- {
- m_pRssm->AddRef();
- retVal = HXR_OK;
- }
- }
-
- // Create Decoder
- if (SUCCEEDED(retVal))
- {
- retVal = HXR_OUTOFMEMORY;
- m_pDecoder = CreateDecoder();
- if (m_pDecoder)
- {
- retVal = HXR_OK;
- }
- }
- // Initialize Assembler
- if (SUCCEEDED(retVal) && m_pRssm)
- {
- retVal = m_pRssm->Init(m_pCommonClassFactory, FALSE);
- }
-
- if (SUCCEEDED(retVal) && m_pRssm)
- {
- retVal = m_pRssm->SetStreamHeader(pHeader);
- if (retVal == HXR_NO_DATA)
- {
- retVal = HXR_OK;
- }
- #ifdef _IGNORE_UNSUPPORTED
- if (FAILED(retVal))
- {
- HXxSize nullViewFrame = {1, 1};
- m_pMP4VideoRenderer->ResizeViewFrame(nullViewFrame);
- HX_RELEASE(m_pRssm);
- retVal = HXR_OK;
- }
- #endif // _IGNORE_UNSUPPORTED
- }
- // Initialize Decoder
- if (SUCCEEDED(retVal) && m_pRssm)
- {
- retVal = m_pDecoder->Init(m_pMP4VideoRenderer->GetContext(),
- this,
- NULL,
- m_pInputAllocator,
- m_pMP4VideoRenderer->m_pOutputAllocator);
-
- #ifdef _IGNORE_UNSUPPORTED
- if (FAILED(retVal))
- {
- HXxSize nullViewFrame = {1, 1};
- m_pMP4VideoRenderer->ResizeViewFrame(nullViewFrame);
- HX_RELEASE(m_pRssm);
- retVal = HXR_OK;
- }
- #endif // _IGNORE_UNSUPPORTED
- }
- m_DecoderDims.cx = 0;
- m_DecoderDims.cy = 0;
- m_ulMaxDecodedFrames = GetMaxDecodedFrames();
- return retVal;
- }
- /****************************************************************************
- * Method:
- * CVideoFormat::GetDefaultPreroll
- *
- */
- ULONG32 CMP4VideoFormat::GetDefaultPreroll(IHXValues* pValues)
- {
- return MP4V_DEFAULT_PREROLL;
- }
- /****************************************************************************
- * Method:
- * CQTVideoFormat::GetBitstreamHeaderSize
- */
- ULONG32 CMP4VideoFormat::GetBitstreamHeaderSize(void)
- {
- ULONG32 ulSize = 0;
- if (m_pRssm)
- {
- ulSize = m_pRssm->GetBitstreamHeaderSize();
- }
- return ulSize;
- }
- /****************************************************************************
- * Method:
- * CQTVideoFormat::GetBitstreamHeader
- */
- const UINT8* CMP4VideoFormat::GetBitstreamHeader(void)
- {
- const UINT8* pHeader = NULL;
- if (m_pRssm)
- {
- pHeader = m_pRssm->GetBitstreamHeader();
- }
- return pHeader;
- }
- /****************************************************************************
- * Method:
- * CQTVideoFormat::CreateAssembledPacket
- */
- CMediaPacket* CMP4VideoFormat::CreateAssembledPacket(IHXPacket* pCodecData)
- {
- ULONG32* pCodecPacketRaw = NULL;
- HXCODEC_DATA* pCodecPacket;
- CMediaPacket* pFramePacket = NULL;
- IHXPacket* pPacket = NULL;
- #ifdef _IGNORE_UNSUPPORTED
- if (!m_pRssm)
- {
- return NULL;
- }
- #endif // _IGNORE_UNSUPPORTED
- m_pMP4VideoRenderer->BltIfNeeded();
- m_LastError = m_pRssm->SetPacket(pCodecData);
- if( m_LastError == HXR_OUTOFMEMORY )
- {
- return NULL;
- }
- m_pRssm->CreateHXCodecPacket(pCodecPacketRaw);
- pCodecPacket = (HXCODEC_DATA*) pCodecPacketRaw;
-
- if (pCodecPacket)
- {
- pFramePacket = new CMediaPacket(
- pCodecPacket,
- (UINT8*) pCodecPacket,
- pCodecPacket->dataLength,
- pCodecPacket->dataLength,
- pCodecPacket->timestamp,
- pCodecPacket->flags, //0,
- NULL);
-
- if (pFramePacket == NULL)
- {
- HX_ASSERT(HXR_OUTOFMEMORY == HXR_OK);
- KillInputBuffer(pCodecPacket, this);
- m_LastError == HXR_OUTOFMEMORY;
- return NULL;
- }
- else
- {
- pFramePacket->SetBufferKiller(KillInputBuffer);
- pFramePacket->m_pUserData = this;
- }
-
- m_pMP4VideoRenderer->BltIfNeeded();
- }
-
- return pFramePacket;
- }
- /****************************************************************************
- * Method:
- * CMP4VideoFormat::Reset
- */
- void CMP4VideoFormat::Reset()
- {
- _Reset();
- CVideoFormat::Reset();
- }
- void CMP4VideoFormat::_Reset(void)
- {
- ReleaseDecodedPacket(&m_DecodedPacket);
- if (m_pRssm)
- {
- m_pRssm->Reset();
- m_pRssm->SetTimeAnchor(GetStartTime());
- }
- m_DecoderDims.cx = 0;
- m_DecoderDims.cy = 0;
- }
- void CMP4VideoFormat::ReleaseDecodedPacket(HXCODEC_DATA* pDecodedPacket)
- {
- HX_ASSERT(pDecodedPacket);
- if (pDecodedPacket->data &&
- m_pMP4VideoRenderer &&
- m_pMP4VideoRenderer->m_pOutputAllocator)
- {
- m_pMP4VideoRenderer->m_pOutputAllocator->ReleasePacketPtr(pDecodedPacket->data);
- pDecodedPacket->data = NULL;
- pDecodedPacket->dataLength = NULL;
- }
- }
- /****************************************************************************
- * Method:
- * CMP4VideoFormat::CreateDecodedPacket
- *
- */
- CMediaPacket* CMP4VideoFormat::CreateDecodedPacket(CMediaPacket* pFrameToDecode)
- {
- HXCODEC_DATA oldDecodedPacket;
- HXCODEC_DATA* pDecodedPacket = NULL;
- CMediaPacket* pDecodedFrame = NULL;
- UINT8* pData = NULL;
-
- HX_ASSERT(pFrameToDecode);
- #if defined(HELIX_FEATURE_VIDEO_MPEG4_DISCARD_LATE_ENCODED_FRAMES)
- // discard late frames before they are decoded
- if (m_pMP4VideoRenderer->IsActive())
- {
- LONG32 lTimeAhead;
- lTimeAhead = m_pMP4VideoRenderer->ComputeTimeAhead(
- pFrameToDecode->m_ulTime,
- 0);
- if (lTimeAhead < MAX_NONKEY_CODED_FRAME_FALLBEHIND)
- {
- // Throw away this frame
- pFrameToDecode->Clear();
- delete pFrameToDecode;
- pFrameToDecode = NULL;
- #if defined(HELIX_FEATURE_STATS)
- m_pMP4VideoRenderer->ReportDroppedFrame();
- #endif /* #if defined(HELIX_FEATURE_STATS) */
- }
- }
- #endif // HELIX_FEATURE_VIDEO_MPEG4_DISCARD_LATE_ENCODED_FRAMES
- if (m_DecodedPacket.data)
- {
- oldDecodedPacket = m_DecodedPacket;
- m_DecodedPacket.data = NULL;
- m_DecodedPacket.dataLength = 0;
- pDecodedPacket = &oldDecodedPacket;
- }
- m_pMP4VideoRenderer->BltIfNeeded();
- if (pFrameToDecode)
- ProcessAssembledFrame(pFrameToDecode);
- if (pFrameToDecode &&
- m_pDecoder->Decode(pFrameToDecode, MAX_DECODE_QUALITY) == HXR_OK)
- {
- if ((pDecodedPacket == NULL) && (m_DecodedPacket.data))
- {
- pDecodedPacket = &m_DecodedPacket;
- }
- #if !defined(HELIX_FEATURE_VIDEO_MPEG4_DISCARD_LATE_ENCODED_FRAMES)
- if (pDecodedPacket)
- {
- if (m_pMP4VideoRenderer->ComputeTimeAhead(
- pDecodedPacket->timestamp,
- 0)
- < NON_KEYFRM_DCDE_FALLBEHIND_THRSHLD)
- {
- ReleaseDecodedPacket(pDecodedPacket);
- pDecodedPacket = NULL;
- }
- }
- #endif // HELIX_FEATURE_VIDEO_MPEG4_DISCARD_LATE_ENCODED_FRAMES
- if (pDecodedPacket)
- {
- CMediaPacket* pVideoPacket = NULL;
- HXxSize* pSampleDesc = NULL;
- // Obtain frame dimensions if not set
- if (m_DecoderDims.cx == 0)
- {
- HX_FORMAT_IMAGE imageInfo;
- if (m_pDecoder->GetImageInfo(imageInfo) == HXR_OK)
- {
- pSampleDesc = new HXxSize;
- if (pSampleDesc)
- {
- pSampleDesc->cx = m_DecoderDims.cx = imageInfo.uiWidth;
- pSampleDesc->cy = m_DecoderDims.cy = imageInfo.uiHeight;
- m_pMP4VideoRenderer->ResizeViewFrame(m_DecoderDims);
- }
- }
- }
- // Form decoded media packets if dimensions set
- if (m_DecoderDims.cx != 0)
- {
- pVideoPacket = (CMediaPacket*) m_pFramePool->Get(0);
- if (pVideoPacket == NULL)
- {
- pVideoPacket = pFrameToDecode;
- pFrameToDecode = NULL;
- }
- if (pVideoPacket)
- {
- pVideoPacket->SetBuffer(pDecodedPacket->data,
- pDecodedPacket->data,
- pDecodedPacket->dataLength,
- pDecodedPacket->dataLength,
- FALSE);
- pVideoPacket->Init(pDecodedPacket->data,
- pDecodedPacket->dataLength,
- pDecodedPacket->timestamp,
- pDecodedPacket->flags,
- pSampleDesc);
- pVideoPacket->SetSampleDescKiller(KillMP4VSampleDesc);
- pVideoPacket->SetBufferKiller(KillOutputBuffer);
- pVideoPacket->m_pUserData = m_pMP4VideoRenderer;
- pDecodedPacket->data = NULL;
- pDecodedPacket->dataLength = 0;
- pDecodedPacket = NULL;
- pSampleDesc = NULL;
- pDecodedFrame = pVideoPacket;
- pVideoPacket = NULL;
- }
- }
- if (pVideoPacket)
- {
- delete pVideoPacket;
- }
- if (pSampleDesc)
- {
- delete pSampleDesc;
- }
- }
- }
- if (pFrameToDecode != NULL)
- {
- pFrameToDecode->Clear();
- delete pFrameToDecode;
- }
- if (pDecodedPacket)
- {
- ReleaseDecodedPacket(pDecodedPacket);
- }
- return pDecodedFrame;
- }
- CMP4VDecoder* CMP4VideoFormat::CreateDecoder()
- {
- return new CMP4VDecoder();
- }
- /****************************************************************************
- * Method:
- * CMP4VideoFormat::DecodeDone
- */
- HX_RESULT CMP4VideoFormat::DecodeDone(HXCODEC_DATA* pData)
- {
- HX_RESULT retVal = HXR_OK;
- m_pMP4VideoRenderer->BltIfNeeded();
- if (pData)
- {
- HX_ASSERT(m_DecodedPacket.data == NULL);
- retVal = HXR_UNEXPECTED;
- if (m_DecodedPacket.data == NULL)
- {
- m_DecodedPacket = *pData;
- retVal = HXR_OK;
- }
- }
- return retVal;
- }
- /****************************************************************************
- * Method:
- * CMP4VideoFormat::IsBitmapFormatChanged
- *
- */
- BOOL CMP4VideoFormat::IsBitmapFormatChanged(
- HXBitmapInfoHeader &BitmapInfoHeader,
- CMediaPacket* pVideoPacket)
- {
- if (pVideoPacket->m_pSampleDesc != NULL)
- {
- HXxSize* pDims = (HXxSize*) pVideoPacket->m_pSampleDesc;
- if ((BitmapInfoHeader.biWidth != pDims->cx) ||
- (BitmapInfoHeader.biHeight != pDims->cy))
- {
- return TRUE;
- }
- }
- return FALSE;
- }
- /****************************************************************************
- * Method:
- * CMP4VideoFormat::InitBitmapInfoHeader
- */
- HX_RESULT CMP4VideoFormat::InitBitmapInfoHeader(
- HXBitmapInfoHeader &bitmapInfoHeader,
- CMediaPacket* pVideoPacket)
- {
- HXxSize* pDims = (HXxSize*) pVideoPacket->m_pSampleDesc;
- if (pDims)
- {
- bitmapInfoHeader.biWidth = pDims->cx;
- bitmapInfoHeader.biHeight = pDims->cy;
- bitmapInfoHeader.biSizeImage = bitmapInfoHeader.biWidth *
- bitmapInfoHeader.biHeight *
- bitmapInfoHeader.biBitCount /
- 8;
- }
- return HXR_OK;
- }
- /****************************************************************************
- * Method:
- * CMP4VideoFormat::CreateAllocators()
- */
- HX_RESULT CMP4VideoFormat::CreateAllocators(void)
- {
- HX_RESULT retVal = HXR_OK;
- HX20ALLOCPROPS allocRequest, allocActual;
- HX_RELEASE(m_pInputAllocator);
- HX_DELETE(m_pMP4VideoRenderer->m_pOutputAllocator);
-
- // setup the input allocator for the codec
- if (retVal == HXR_OK)
- {
- m_pInputAllocator = new CHXBufferMemoryAllocator(TRUE);
- retVal = HXR_OUTOFMEMORY;
- if (m_pInputAllocator)
- {
- m_pInputAllocator->AddRef();
- m_pInputAllocator->GetProperties(&allocRequest);
- allocRequest.nNumBuffers = 0; // No retention
- m_pInputAllocator->SetProperties(&allocRequest,
- &allocActual);
- retVal = HXR_OK;
- }
- }
- // setup the output allocator for the codec
- if (retVal == HXR_OK)
- {
- m_pMP4VideoRenderer->m_pOutputAllocator = new CHXMemoryAllocator(TRUE);
- retVal = HXR_OUTOFMEMORY;
- if (m_pMP4VideoRenderer->m_pOutputAllocator)
- {
- m_pMP4VideoRenderer->m_pOutputAllocator->AddRef();
- m_pMP4VideoRenderer->m_pOutputAllocator->GetProperties(&allocRequest);
- allocRequest.nNumBuffers = GetMaxDecodedFrames() * 2;
- m_pMP4VideoRenderer->m_pOutputAllocator->SetProperties(&allocRequest,
- &allocActual);
- retVal = HXR_OK;
- }
- }
- #if _MACINTOSH
- // TODO: we want to pre-allocate the output buffers here so they come
- // from the standard memory pools instead of the interrupt memory
- // pools.
- #endif // _MACINTOSH
- return retVal;
- }
- /****************************************************************************
- * Method:
- * CMP4VideoFormat::KillMP4VSampleDesc
- *
- */
- void CMP4VideoFormat::KillMP4VSampleDesc(void* pSampleDesc, void* pUserData)
- {
- if (pSampleDesc)
- {
- HXxSize* pFrameDims = (HXxSize*) pSampleDesc;
- delete pFrameDims;
- }
- }
- /****************************************************************************
- * Method:
- * CMP4VideoFormat::KillInputBuffer
- *
- */
- void CMP4VideoFormat::KillInputBuffer(void* pBuffer, void* pUserData)
- {
- if (pBuffer)
- {
- HXCODEC_DATA* pDeadData = (HXCODEC_DATA*) pBuffer;
- CMP4VideoFormat* pVidFmt = (CMP4VideoFormat*) pUserData;
- HX_ASSERT(pUserData);
- if (pDeadData->data)
- {
- pVidFmt->m_pInputAllocator->ReleasePacketPtr(pDeadData->data);
- }
- delete[] ((ULONG32*) pDeadData);
- }
- }
- /****************************************************************************
- * Method:
- * CMP4VideoFormat::KillOutputBuffer
- *
- */
- void CMP4VideoFormat::KillOutputBuffer(void* pBuffer, void* pUserData)
- {
- if (pBuffer)
- {
- CMP4VideoRenderer* pVidRnd = (CMP4VideoRenderer*) pUserData;
- HX_ASSERT(pUserData);
- pVidRnd->m_pOutputAllocator->ReleasePacketPtr((UINT8*) pBuffer);
- }
- }