mp4vdec.cpp
来自「symbian 下的helix player源代码」· C++ 代码 · 共 549 行
CPP
549 行
/* ***** 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 ***** */
// #define _DRY_RUN
/****************************************************************************
* Includes
*/
#include "hxtypes.h"
#include "hxresult.h"
#include "hxassert.h"
#include "hxwintyp.h"
#include "hxcom.h"
#include "hxmtypes.h"
#include "hxcomm.h"
#include "ihxpckts.h"
#include "hxplugn.h"
#include "hxengin.h"
#include "hxerror.h"
#include "hxformt.h"
#include "hxprefs.h"
#include "mp4vdec.h"
#include "mp4vdfmt.h"
#include "mp4video.h"
#include "addupcol.h"
#include "hlxclib/string.h"
#include "hxheap.h"
#ifdef _DEBUG
#undef HX_THIS_FILE
static char HX_THIS_FILE[] = __FILE__;
#endif
/****************************************************************************
* Statics
*/
/****************************************************************************
* Method:
* CMP4VDecoder::CMP4VDecoder
*/
/****************************************************************************
* Constructor/Destructor
*/
CMP4VDecoder::CMP4VDecoder()
: m_pContext(NULL)
, m_pVideoFormat(NULL)
, m_pCodecLib(NULL)
, m_pCodec(NULL)
, m_pStream(NULL)
, m_pCodecId(NULL)
, m_pInputAllocator(NULL)
, m_pOutputAllocator(NULL)
, m_moftagOut(0)
, m_ulLastTimeStamp(0)
{
;
}
CMP4VDecoder::~CMP4VDecoder()
{
Close();
}
/****************************************************************************
* Method:
* CMP4VDecoder::Close
*/
HX_RESULT CMP4VDecoder::Close(void)
{
if (m_pStream != NULL)
{
m_pCodecLib->PNStream_Close(m_pStream);
m_pStream = NULL;
}
if (m_pCodec != NULL)
{
m_pCodecLib->PNCodec_Close(m_pCodec);
m_pCodec = NULL;
}
HX_DELETE(m_pCodecLib);
HX_RELEASE(m_pInputAllocator);
HX_RELEASE(m_pOutputAllocator);
return HXR_OK;
}
/****************************************************************************
* Method:
* CMP4VDecoder::CMP4VDecoder
*/
HX_RESULT CMP4VDecoder::Init(IUnknown* pContext,
CMP4VideoFormat* pVideoFormat,
HXxSize* pSize,
IHX20MemoryAllocator* pInputAllocator,
IHX20MemoryAllocator* pOutputAllocator)
{
HX_RESULT retVal = HXR_INVALID_PARAMETER;
m_pCodecId = "MP4V";
HX_RELEASE(m_pContext);
m_pContext = pContext;
HX_ASSERT(m_pContext);
if (m_pContext)
{
retVal = HXR_OK;
}
if (SUCCEEDED(retVal))
{
m_pVideoFormat = pVideoFormat;
retVal = HXR_INVALID_PARAMETER;
if (m_pVideoFormat)
{
retVal = HXR_OK;
}
}
if (SUCCEEDED(retVal))
{
m_pInputAllocator = pInputAllocator;
if (m_pInputAllocator)
{
m_pInputAllocator->AddRef();
}
m_pOutputAllocator = pOutputAllocator;
if (m_pOutputAllocator)
{
m_pOutputAllocator->AddRef();
}
retVal = HXR_INVALID_PARAMETER;
if (m_pInputAllocator && m_pOutputAllocator)
{
retVal = HXR_OK;
}
}
#ifndef _DRY_RUN
// Open the codec
if (SUCCEEDED(retVal))
{
retVal = OpenCodec(STRINGTOMOFTAG(m_pCodecId));
}
if (SUCCEEDED(retVal))
{
retVal = OpenStream();
}
#endif // _DRY_RUN
return retVal;
}
/****************************************************************************
* Method:
* CMP4VDecoder::Decode()
*/
HX_RESULT CMP4VDecoder::Decode(CMediaPacket* pFrameToDecode,
ULONG32 ulQuality)
{
ULONG32 ulFirstTimeStamp = 0;
HX_OQS2 theOutputQueueStatus;
HX_RESULT retVal = HXR_OK;
// tell the stream about renderer status so it can scale its processing
theOutputQueueStatus.queueDepth = m_pVideoFormat->GetDecodedFrameQueueDepth();
theOutputQueueStatus.newestQueueElementTimeStamp = m_ulLastTimeStamp;
m_pVideoFormat->GetNextFrameTime(ulFirstTimeStamp);
theOutputQueueStatus.oldestQueueElementTimeStamp = ulFirstTimeStamp;
theOutputQueueStatus.maxQueueDepth = m_pVideoFormat->m_ulMaxDecodedFrames;
theOutputQueueStatus.currentTimeStamp = -m_pVideoFormat->m_pMP4VideoRenderer->ComputeTimeAhead(0, 0);
theOutputQueueStatus.nonFRUDroppedFrames = 0;
theOutputQueueStatus.TotalDroppedFrames = 0;
// this is for Beta 2 codecs
#ifdef _DRY_RUN
m_pInputAllocator->ReleasePacketPtr(((HXCODEC_DATA*) pFrameToDecode->m_pData)->data);
((HXCODEC_DATA*) pFrameToDecode->m_pData)->data = NULL;
retVal = DecodeDone(NULL);
#else // _DRY_RUN
m_pCodecLib->PNStream_SetProperty(m_pStream,
SP_OUPUT_QUEUE_STATUS,
&theOutputQueueStatus);
// this is for > beta 2 codecs
m_pCodecLib->PNStream_SetProperty(m_pStream,
SP_OUPUT_QUEUE_STATUS2,
&theOutputQueueStatus);
m_pCodecLib->PNStream_Input(m_pStream,
NULL,
(HXCODEC_DATA*) pFrameToDecode->m_pData);
((HXCODEC_DATA*) pFrameToDecode->m_pData)->data = NULL;
#endif // _DRY_RUN
return retVal;
}
/****************************************************************************
* Method:
* CRVDecoder::DecodeDone
*/
HX_RESULT CMP4VDecoder::DecodeDone(HXCODEC_DATA* pData)
{
if (pData)
{
m_ulLastTimeStamp = pData->timestamp;
}
return m_pVideoFormat->DecodeDone(pData);
}
/****************************************************************************
* Method:
* CRVDecoder::GetImageInfo
*/
HX_RESULT CMP4VDecoder::GetImageInfo(HX_FORMAT_IMAGE &imageInfo)
{
ULONG32 ulSize;
ULONG32* pMofBuf = NULL;
HX_RESULT retVal = HXR_OK;
retVal = m_pCodecLib->PNStream_GetStreamHeaderSize(m_pStream,
&ulSize);
if (retVal == HXR_OK)
{
HX_ASSERT((ulSize == sizeof(HX_FORMAT_IMAGE)) ||
(ulSize == sizeof(HX_FORMAT_IMAGE2)));
pMofBuf = new ULONG32[ulSize / 4 + 1];
retVal = HXR_OUTOFMEMORY;
if (pMofBuf)
{
retVal = HXR_OK;
}
}
if (retVal == HXR_OK)
{
retVal = m_pCodecLib->PNStream_GetStreamHeader(m_pStream,
(HX_MOF *) pMofBuf);
}
if (retVal == HXR_OK)
{
memcpy(&imageInfo, pMofBuf, sizeof(imageInfo));
}
HX_VECTOR_DELETE(pMofBuf);
return retVal;
}
/****************************************************************************
* Method:
* CRVDecoder::OnNewImage
*/
HX_RESULT CMP4VDecoder::OnNewImage(HXSTREAM streamRef,
HXSTREAM fromStreamRef,
HXCODEC_DATA* pData)
{
CMP4VDecoder* pDecoder = (CMP4VDecoder*) streamRef;
return pDecoder->DecodeDone(pData);
}
CRADynamicCodecLibrary* CMP4VDecoder::CreateCodecLibrary()
{
return new CRADynamicCodecLibrary(m_pContext);
}
/****************************************************************************
* Private Methods
*/
/****************************************************************************
* Method:
* CMP4VDecoder::OpenCodec()
*/
HX_RESULT CMP4VDecoder::OpenCodec(HX_MOFTAG mofTag)
{
HX_RESULT retVal = HXR_OK;
HX_DELETE(m_pCodecLib);
// Create Codec Library
m_pCodecLib = CreateCodecLibrary();
retVal = HXR_OUTOFMEMORY;
if (m_pCodecLib != NULL)
{
retVal = HXR_OK;
}
// Load Codec into library
if (SUCCEEDED(retVal))
{
retVal = m_pCodecLib->LoadCodecLib(mofTag);
if (FAILED(retVal))
{
// Generate the string
// XXXMEH - we really should centralize this code
// into CRADynamicCodecLibrary
char szAUStr[5]; /* Flawfinder: ignore */
szAUStr[0] = (char) ((mofTag >> 24) & 0x000000FF);
szAUStr[1] = (char) ((mofTag >> 16) & 0x000000FF);
szAUStr[2] = (char) ((mofTag >> 8) & 0x000000FF);
szAUStr[3] = (char) ( mofTag & 0x000000FF);
szAUStr[4] = '\0';
// Make sure it's lower-case
strlwr(szAUStr);
// We failed to load the codec binary, so
// we need to add the string to the upgrade collection
AddToAutoUpgradeCollection(szAUStr, m_pContext);
// Make sure we return HXR_REQUEST_UPGRADE
// so that we know we failed due to not being able
// to load the codec as opposed to some other reason
retVal = HXR_REQUEST_UPGRADE;
}
}
// Open the codec
if (SUCCEEDED(retVal))
{
retVal = m_pCodecLib->PNCodec_Open(mofTag, &m_pCodec);
if (FAILED(retVal))
{
retVal = HXR_REQUEST_UPGRADE;
}
}
return retVal;
}
/****************************************************************************
* Method:
* CMP4VDecoder::OpenStream
*/
HX_RESULT CMP4VDecoder::OpenStream(void)
{
ULONG32 ulMofInDataSize = 0;
ULONG32* pMofInData = NULL;
HX_FORMAT_NATIVE* pMofIn;
HX_FORMAT_IMAGE2 mofOut;
HXCODEC_INIT codecInit;
HX_RESULT retVal = HXR_OK;
if (SUCCEEDED(retVal))
{
ulMofInDataSize = (m_pVideoFormat->GetBitstreamHeaderSize() / 4) + 1;
ulMofInDataSize += sizeof(HX_FORMAT_NATIVE);
pMofInData = new ULONG32 [ulMofInDataSize];
retVal = HXR_OUTOFMEMORY;
if (pMofInData)
{
retVal = HXR_OK;
}
}
if (SUCCEEDED(retVal))
{
pMofIn = (HX_FORMAT_NATIVE*) pMofInData;
pMofIn->cbLength = m_pVideoFormat->GetBitstreamHeaderSize() +
(pMofIn->data - ((UINT8*) pMofIn));
pMofIn->moftag = HX_MEDIA_NATIVE;
pMofIn->submoftag = STRINGTOMOFTAG(m_pCodecId);
memcpy(pMofIn->data,
m_pVideoFormat->GetBitstreamHeader(),
m_pVideoFormat->GetBitstreamHeaderSize());
}
if (SUCCEEDED(retVal))
{
mofOut.cbLength = sizeof(HX_FORMAT_IMAGE2);
mofOut.moftag = HX_MEDIA_IMAGE2;
mofOut.submoftag = HX_YUV420_ID;
m_moftagOut = HX_YUV420_ID;
}
if (SUCCEEDED(retVal))
{
codecInit.pInMof = (HX_MOF*) pMofIn;
codecInit.pOutMof = (HX_MOF*) &mofOut;
codecInit.memoryRef = (HXMEMORY) m_pInputAllocator;
codecInit.pContext = m_pContext;
}
if (retVal == HXR_OK)
{
retVal = m_pCodecLib->PNCodec_StreamOpen(m_pCodec,
&m_pStream,
&codecInit);
}
if (retVal == HXR_OK)
{
retVal = m_pCodecLib->PNStream_SetDataCallback(
m_pStream,
this,
(HXMEMORY) m_pOutputAllocator,
OnNewImage);
}
if (retVal == HXR_OK)
{
SetCodecQuality();
}
if (retVal == HXR_OK)
{
BOOL bAllowDifferentOutputSizes = TRUE;
// tell codec we can handle different output sizes
m_pCodecLib->PNStream_SetProperty(m_pStream,
SP_ALLOW_DIFFERENT_OUPUT_SIZES,
&bAllowDifferentOutputSizes);
}
HX_VECTOR_DELETE(pMofInData);
return retVal;
}
/****************************************************************************
* Method:
* CMP4VDecoder::GetQualityPreference
*/
HX_RESULT CMP4VDecoder::GetQualityPreference(UINT16 &usQuality)
{
HX_RESULT pnr = HXR_OK;
IHXBuffer* pBuffer = NULL;
IHXPreferences* pPreferences = 0;
if (!m_pContext ||
(m_pContext->QueryInterface(IID_IHXPreferences, (void**) &pPreferences) !=
HXR_OK))
{
pnr = HXR_INVALID_PARAMETER;
}
else
{
if (pPreferences->ReadPref("Quality", pBuffer) == HXR_OK)
{
usQuality = ::atoi((const char*) pBuffer->GetBuffer());
HX_RELEASE(pBuffer);
}
}
HX_RELEASE(pPreferences);
return pnr;
}
/****************************************************************************
* Method:
* CMP4VDecoder::GetQualityPreference
*/
void CMP4VDecoder::SetCodecQuality(void)
{
UINT16 usQualityPreference = 4;
GetQualityPreference(usQualityPreference);
// Turn on or off post filter based on flags in source URL
// if the URL turns off post filter or the TLC quality
// preference is < 2 we turn off the post filter
BOOL bPostFilter = (usQualityPreference >= 2);
m_pCodecLib->PNStream_SetProperty(m_pStream,
SP_POSTFILTER,
&bPostFilter);
// Turn on or off FRU based on flags in source URL
// BOOL bTemporalInterp = (usQualityPreference >= 2);
BOOL bTemporalInterp = FALSE;
m_pCodecLib->PNStream_SetProperty(m_pStream,
SP_TEMPORALINTERP,
&bTemporalInterp);
// Turn on or off decode of B-frames based on flags in source URL
// BOOL bDecodeBFrames = (usQualityPreference >= 2);
BOOL bDecodeBFrames = FALSE;
m_pCodecLib->PNStream_SetProperty(m_pStream,
SP_DECODE_B_FRAMES,
&bDecodeBFrames);
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?