This commit is contained in:
mofeng-git
2025-12-28 18:19:16 +08:00
commit d143d158e4
771 changed files with 220548 additions and 0 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,533 @@
/******************************************************************************\
Copyright (c) 2005-2019, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
This sample was distributed or derived from the Intel's Media Samples package.
The original version of this sample may be obtained from https://software.intel.com/en-us/intel-media-server-studio
or https://software.intel.com/en-us/media-client-solutions-support.
\**********************************************************************************/
#include "sample_defs.h"
#include "avc_structures.h"
#include "avc_nal_spl.h"
namespace ProtectedLibrary
{
static const mfxU32 MFX_TIME_STAMP_FREQUENCY = 90000; // will go to mfxdefs.h
static const mfxU64 MFX_TIME_STAMP_INVALID = (mfxU64)-1; // will go to mfxdefs.h
inline
mfxF64 GetUmcTimeStamp(mfxU64 ts)
{
return ts == MFX_TIME_STAMP_INVALID ? -1.0 : ts / (mfxF64)MFX_TIME_STAMP_FREQUENCY;
}
inline
mfxU64 GetMfxTimeStamp(mfxF64 ts)
{
return ts < 0.0 ? MFX_TIME_STAMP_INVALID : (mfxU64)(ts * MFX_TIME_STAMP_FREQUENCY + .5);
}
enum
{
AVC_NAL_UNITTYPE_BITS_MASK = 0x1f
};
inline bool IsHeaderCode(mfxI32 iCode)
{
return (NAL_UT_SPS == (iCode & AVC_NAL_UNITTYPE_BITS_MASK)) ||
(NAL_UT_SPS_EX == (iCode & AVC_NAL_UNITTYPE_BITS_MASK)) ||
(NAL_UT_PPS == (iCode & AVC_NAL_UNITTYPE_BITS_MASK));
}
inline bool IsVLCCode(mfxI32 iCode)
{
return ((NAL_UT_SLICE <= (iCode & AVC_NAL_UNITTYPE_BITS_MASK)) &&
(NAL_UT_IDR_SLICE >= (iCode & AVC_NAL_UNITTYPE_BITS_MASK))) ||
(NAL_UT_AUXILIARY == (iCode & AVC_NAL_UNITTYPE_BITS_MASK));
}
static mfxI32 FindStartCode(mfxU8 * (&pb), mfxU32 &nSize)
{
// there is no data
if (nSize < 4)
return 0;
// find start code
while ((4 <= nSize) && ((0 != pb[0]) ||
(0 != pb[1]) ||
(1 != pb[2])))
{
pb += 1;
nSize -= 1;
}
if (4 <= nSize)
return ((pb[0] << 24) | (pb[1] << 16) | (pb[2] << 8) | (pb[3]));
return 0;
}
mfxStatus MoveBitstream(mfxBitstream * source, mfxI32 moveSize)
{
if (!source)
return MFX_ERR_NULL_PTR;
if (moveSize < 0 && (mfxI32)source->DataOffset + moveSize < 0)
return MFX_ERR_UNDEFINED_BEHAVIOR;
if (moveSize > 0 && source->DataLength < (mfxU32)moveSize)
return MFX_ERR_UNDEFINED_BEHAVIOR;
source->DataOffset += moveSize;
source->DataLength -= moveSize;
return MFX_ERR_NONE;
}
StartCodeIterator::StartCodeIterator()
: m_code(0)
, m_pts(MFX_TIME_STAMP_INVALID)
, m_pSource(0)
, m_nSourceSize(0)
, m_pSourceBase(0)
, m_nSourceBaseSize(0)
, m_suggestedSize(10 * 1024)
{
Reset();
}
void StartCodeIterator::Reset()
{
m_code = 0;
m_pts = MFX_TIME_STAMP_INVALID;
m_prev.clear();
}
mfxI32 StartCodeIterator::Init(mfxBitstream * source)
{
Reset();
m_pSourceBase = m_pSource = source->Data + source->DataOffset;
m_nSourceBaseSize = m_nSourceSize = source->DataLength;
mfxI32 iCode = ProtectedLibrary::FindStartCode(m_pSource, m_nSourceSize);
return iCode;
}
void StartCodeIterator::SetSuggestedSize(mfxU32 size)
{
if (size > m_suggestedSize)
m_suggestedSize = size;
}
mfxI32 StartCodeIterator::CheckNalUnitType(mfxBitstream * source)
{
if (!source)
return 0;
if (!m_code)
m_prev.clear();
mfxU8 * src = source->Data + source->DataOffset;
mfxU32 size = source->DataLength;
mfxI32 startCodeSize;
mfxI32 iCodeNext = FindStartCode(src, size, startCodeSize);
return iCodeNext;
}
mfxI32 StartCodeIterator::GetNALUnit(mfxBitstream * src, mfxBitstream * dst)
{
if (!src)
return EndOfStream(dst);
if (!m_code)
m_prev.clear();
mfxU8 * source = src->Data + src->DataOffset;
mfxU32 size = src->DataLength;
if (!size)
return 0;
mfxI32 startCodeSize;
mfxI32 iCodeNext = FindStartCode(source, size, startCodeSize);
if (m_prev.size())
{
if (!iCodeNext)
{
size_t sz = source - (src->Data + src->DataOffset);
if (m_prev.size() + sz > m_suggestedSize)
{
m_prev.clear();
sz = std::min<size_t>(sz, m_suggestedSize);
}
m_prev.insert(m_prev.end(), src->Data + src->DataOffset, src->Data + src->DataOffset + sz);
MoveBitstream(src, (mfxI32)sz);
return 0;
}
source -= startCodeSize;
m_prev.insert(m_prev.end(), src->Data + src->DataOffset, source);
MoveBitstream(src, (mfxI32)(source - (src->Data + src->DataOffset)));
dst->Data = &(m_prev[0]);
dst->DataLength = (mfxU32)m_prev.size();
dst->DataOffset = 0;
dst->TimeStamp = m_pts;
mfxI32 code = m_code;
m_code = 0;
m_pts = MFX_TIME_STAMP_INVALID;
return code;
}
if (!iCodeNext)
{
MoveBitstream(src, (mfxI32)(source - (src->Data + src->DataOffset)));
return 0;
}
m_pts = src->TimeStamp;
m_code = iCodeNext;
// move before start code
MoveBitstream(src, (mfxI32)(source - (src->Data + src->DataOffset) - startCodeSize));
mfxI32 startCodeSize1;
iCodeNext = FindStartCode(source, size, startCodeSize1);
MoveBitstream(src, startCodeSize);
if (!iCodeNext && (src->DataFlag & MFX_BITSTREAM_COMPLETE_FRAME))
{
iCodeNext = 1;
startCodeSize1 = 0;
}
if (!iCodeNext)
{
if (m_prev.size()) // assertion: it should be
return 0;
size_t sz = source - (src->Data + src->DataOffset);
if (sz > m_suggestedSize)
{
sz = m_suggestedSize;
}
m_prev.insert(m_prev.end(), src->Data + src->DataOffset, src->Data + src->DataOffset + sz);
MoveBitstream(src, (mfxI32)sz);
return 0;
}
// fill
size_t nal_size = source - (src->Data + src->DataOffset) - startCodeSize1;
dst->Data = src->Data + src->DataOffset;
dst->DataLength = (mfxU32)nal_size;
dst->DataOffset = 0;
dst->TimeStamp = m_pts;
MoveBitstream(src, (mfxI32)nal_size);
mfxI32 code = m_code;
m_code = 0;
m_pts = MFX_TIME_STAMP_INVALID;
return code;
}
mfxI32 StartCodeIterator::EndOfStream(mfxBitstream * dst)
{
if (!m_code)
{
m_prev.clear();
return 0;
}
if (m_prev.size())
{
dst->Data = &(m_prev[0]);
dst->DataLength = (mfxU32)m_prev.size();
dst->DataOffset = 0;
dst->TimeStamp = m_pts;
mfxI32 code = m_code;
m_code = 0;
m_pts = MFX_TIME_STAMP_INVALID;
return code;
}
m_code = 0;
return 0;
}
mfxI32 StartCodeIterator::FindStartCode(mfxU8 * (&pb), mfxU32 & size, mfxI32 & startCodeSize)
{
mfxU32 zeroCount = 0;
for (mfxU32 i = 0 ; i < (mfxU32)size; i++, pb++)
{
switch(pb[0])
{
case 0x00:
zeroCount++;
break;
case 0x01:
if (zeroCount >= 2)
{
startCodeSize = std::min(zeroCount + 1, 4u);
size -= i + 1;
pb++; // remove 0x01 symbol
zeroCount = 0;
if (size >= 1)
{
return pb[0] & AVC_NAL_UNITTYPE_BITS_MASK;
}
else
{
pb -= startCodeSize;
size += startCodeSize;
startCodeSize = 0;
return 0;
}
}
zeroCount = 0;
break;
default:
zeroCount = 0;
break;
}
}
zeroCount = std::min(zeroCount, 3u);
pb -= zeroCount;
size += zeroCount;
zeroCount = 0;
startCodeSize = 0;
return 0;
}
void BytesSwapper::SwapMemory(mfxU8 *pDestination, mfxU32 &nDstSize, mfxU8 *pSource, mfxU32 nSrcSize)
{
SwapMemoryAndRemovePreventingBytes(pDestination, nDstSize, pSource, nSrcSize);
}
NALUnitSplitter::NALUnitSplitter()
{
memset(&m_bitstream, 0, sizeof(m_bitstream));
}
NALUnitSplitter::~NALUnitSplitter()
{
Release();
}
void NALUnitSplitter::Init()
{
Release();
}
void NALUnitSplitter::Reset()
{
m_pStartCodeIter.Reset();
}
void NALUnitSplitter::Release()
{
}
mfxI32 NALUnitSplitter::CheckNalUnitType(mfxBitstream * source)
{
return m_pStartCodeIter.CheckNalUnitType(source);
}
mfxI32 NALUnitSplitter::GetNalUnits(mfxBitstream * source, mfxBitstream * &destination)
{
mfxI32 iCode = m_pStartCodeIter.GetNALUnit(source, &m_bitstream);
if (iCode == 0)
{
destination = 0;
return 0;
}
destination = &m_bitstream;
return iCode;
}
/* temporal class definition */
class H264DwordPointer_
{
public:
// Default constructor
H264DwordPointer_(void)
{
m_pDest = NULL;
m_nByteNum = 0;
m_iCur = 0;
}
H264DwordPointer_ operator = (void *pDest)
{
m_pDest = (mfxU32 *) pDest;
m_nByteNum = 0;
m_iCur = 0;
return *this;
}
// Increment operator
H264DwordPointer_ &operator ++ (void)
{
if (4 == ++m_nByteNum)
{
*m_pDest = m_iCur;
m_pDest += 1;
m_nByteNum = 0;
m_iCur = 0;
}
else
m_iCur <<= 8;
return *this;
}
mfxU8 operator = (mfxU8 nByte)
{
m_iCur = (m_iCur & ~0x0ff) | ((mfxU32) nByte);
return nByte;
}
protected:
mfxU32 *m_pDest; // pointer to destination buffer
mfxU32 m_nByteNum; // number of current byte in dword
mfxU32 m_iCur; // current dword
};
class H264SourcePointer_
{
public:
// Default constructor
H264SourcePointer_(void)
{
m_pSource = NULL;
m_nRemovedBytes=0;
m_nZeros=0;
}
H264SourcePointer_ &operator = (mfxU8 *pSource)
{
m_pSource = (mfxU8 *) pSource;
m_nZeros = 0;
m_nRemovedBytes = 0;
return *this;
}
H264SourcePointer_ &operator ++ (void)
{
mfxU8 bCurByte = m_pSource[0];
if (0 == bCurByte)
m_nZeros += 1;
else
{
if ((3 == bCurByte) && (2 <= m_nZeros))
m_nRemovedBytes += 1;
m_nZeros = 0;
}
m_pSource += 1;
return *this;
}
bool IsPrevent(void)
{
if ((3 == m_pSource[0]) && (2 <= m_nZeros))
return true;
else
return false;
}
operator mfxU8 (void)
{
return m_pSource[0];
}
mfxU32 GetRemovedBytes(void)
{
return m_nRemovedBytes;
}
protected:
mfxU8 *m_pSource; // pointer to destination buffer
mfxU32 m_nZeros; // number of preceding zeros
mfxU32 m_nRemovedBytes; // number of removed bytes
};
void SwapMemoryAndRemovePreventingBytes(mfxU8 *pDestination, mfxU32 &nDstSize, mfxU8 *pSource, mfxU32 nSrcSize)
{
H264DwordPointer_ pDst;
H264SourcePointer_ pSrc;
size_t i;
// DwordPointer object is swapping written bytes
// H264SourcePointer_ removes preventing start-code bytes
// reset pointer(s)
pSrc = pSource;
pDst = pDestination;
// first two bytes
i = 0;
while (i < std::min(2u, nSrcSize))
{
pDst = (mfxU8) pSrc;
++pDst;
++pSrc;
++i;
}
// do swapping
while (i < (mfxU32) nSrcSize)
{
if (false == pSrc.IsPrevent())
{
pDst = (mfxU8) pSrc;
++pDst;
}
++pSrc;
++i;
}
// write padding bytes
nDstSize = nSrcSize - pSrc.GetRemovedBytes();
while (nDstSize & 3)
{
pDst = (mfxU8) (0);
++nDstSize;
++pDst;
}
}
} // namespace ProtectedLibrary

View File

@@ -0,0 +1,815 @@
/******************************************************************************\
Copyright (c) 2005-2019, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
This sample was distributed or derived from the Intel's Media Samples package.
The original version of this sample may be obtained from https://software.intel.com/en-us/intel-media-server-studio
or https://software.intel.com/en-us/media-client-solutions-support.
\**********************************************************************************/
#include <exception>
#include <stdio.h>
#include "avc_spl.h"
#include "sample_defs.h"
namespace ProtectedLibrary
{
AVCFrameInfo::AVCFrameInfo()
{
Reset();
}
void AVCFrameInfo::Reset()
{
m_slice = 0;
m_index = 0;
}
AVC_Spl::AVC_Spl()
: m_WaitForIDR(true)
, m_currentInfo(0)
, m_pLastSlice(0)
, m_lastNalUnit(0)
{
Init();
}
AVC_Spl::~AVC_Spl()
{
Close();
}
mfxStatus AVC_Spl::Init()
{
Close();
m_pNALSplitter.reset(new NALUnitSplitter());
m_pNALSplitter->Init();
m_WaitForIDR = true;
m_AUInfo.reset(new AVCFrameInfo());
m_currentFrame.resize(BUFFER_SIZE);
m_pLastSlice = 0;
m_lastNalUnit = 0;
m_currentInfo = 0;
m_slices.resize(128);
memset(&m_frame, 0, sizeof(m_frame));
m_frame.Data = &m_currentFrame[0];
m_frame.Slice = &m_slices[0];
return MFX_ERR_NONE;
}
void AVC_Spl::Close()
{
m_pLastSlice = 0;
m_lastNalUnit = 0;
m_currentInfo = 0;
}
mfxStatus AVC_Spl::Reset()
{
m_pNALSplitter->Reset();
m_WaitForIDR = true;
m_lastNalUnit = 0;
m_pLastSlice = 0;
m_currentInfo = 0;
return MFX_ERR_NONE;
}
mfxU8 * AVC_Spl::GetMemoryForSwapping(mfxU32 size)
{
if (m_swappingMemory.size() <= size + 8)
m_swappingMemory.resize(size + 8);
return &(m_swappingMemory[0]);
}
mfxStatus AVC_Spl::DecodeHeader(mfxBitstream * nalUnit)
{
mfxStatus umcRes = MFX_ERR_NONE;
AVCHeadersBitstream bitStream;
try
{
mfxU32 swappingSize = nalUnit->DataLength;
mfxU8 * swappingMemory = GetMemoryForSwapping(swappingSize);
BytesSwapper::SwapMemory(swappingMemory, swappingSize, nalUnit->Data + nalUnit->DataOffset, nalUnit->DataLength);
bitStream.Reset(swappingMemory, swappingSize);
NAL_Unit_Type uNALUnitType;
mfxU8 uNALStorageIDC;
bitStream.GetNALUnitType(uNALUnitType, uNALStorageIDC);
switch(uNALUnitType)
{
// sequence parameter set
case NAL_UT_SPS:
{
AVCSeqParamSet sps;
umcRes = bitStream.GetSequenceParamSet(&sps);
if (umcRes == MFX_ERR_NONE)
{
m_headers.m_SeqParams.GetHeader(sps.seq_parameter_set_id);
m_headers.m_SeqParams.AddHeader(&sps);
// Validate the incoming bitstream's image dimensions.
m_headers.m_SeqParams.GetHeader(sps.seq_parameter_set_id);
m_pNALSplitter->SetSuggestedSize(CalculateSuggestedSize(&sps));
if (umcRes != MFX_ERR_NONE)
return umcRes;
}
else
return MFX_ERR_UNDEFINED_BEHAVIOR;
}
break;
case NAL_UT_SPS_EX:
{
AVCSeqParamSetExtension sps_ex;
umcRes = bitStream.GetSequenceParamSetExtension(&sps_ex);
if (umcRes == MFX_ERR_NONE)
{
m_headers.m_SeqExParams.AddHeader(&sps_ex);
}
else
return umcRes;
}
break;
// picture parameter set
case NAL_UT_PPS:
{
AVCPicParamSet pps;
// set illegal id
pps.pic_parameter_set_id = MAX_NUM_PIC_PARAM_SETS;
// Get id
umcRes = bitStream.GetPictureParamSetPart1(&pps);
if (MFX_ERR_NONE == umcRes)
{
AVCSeqParamSet *pRefsps = m_headers.m_SeqParams.GetHeader(pps.seq_parameter_set_id);
if (!pRefsps || pRefsps ->seq_parameter_set_id >= MAX_NUM_SEQ_PARAM_SETS)
{
pRefsps = m_headers.m_SeqParamsMvcExt.GetHeader(pps.seq_parameter_set_id);
if (!pRefsps || pRefsps->seq_parameter_set_id >= MAX_NUM_SEQ_PARAM_SETS)
{
return MFX_ERR_UNDEFINED_BEHAVIOR;
}
}
// Get rest of pic param set
umcRes = bitStream.GetPictureParamSetPart2(&pps, pRefsps);
if (MFX_ERR_NONE == umcRes)
{
m_headers.m_PicParams.AddHeader(&pps);
}
m_headers.m_SeqParams.SetCurrentID(pps.seq_parameter_set_id);
}
}
break;
// subset sequence parameter set
case NAL_UNIT_SUBSET_SPS:
{
AVCSeqParamSet sps;
umcRes = bitStream.GetSequenceParamSet(&sps);
if (MFX_ERR_NONE != umcRes)
{
return MFX_ERR_UNDEFINED_BEHAVIOR;
}
// decode additional parameters
if ((AVC_PROFILE_MULTIVIEW_HIGH == sps.profile_idc) ||
(AVC_PROFILE_STEREO_HIGH == sps.profile_idc))
{
AVCSeqParamSet spsMvcExt;
AVCSeqParamSet * sps_temp = &spsMvcExt;
*sps_temp = sps;
m_headers.m_SeqParamsMvcExt.AddHeader(&spsMvcExt);
}
}
break;
// decode a prefix nal unit
case NAL_UNIT_PREFIX:
{
umcRes = bitStream.GetNalUnitPrefix(&m_headers.m_nalExtension, uNALStorageIDC);
if (MFX_ERR_NONE != umcRes)
{
return MFX_ERR_UNDEFINED_BEHAVIOR;
}
}
break;
default:
break;
}
}
catch(const AVC_exception & )
{
return MFX_ERR_UNDEFINED_BEHAVIOR;
}
catch(...)
{
return MFX_ERR_UNDEFINED_BEHAVIOR;
}
return MFX_ERR_NONE;
}
mfxStatus AVC_Spl::DecodeSEI(mfxBitstream * nalUnit)
{
if (m_headers.m_SeqParams.GetCurrrentID() == -1)
return MFX_ERR_NONE;
AVCHeadersBitstream bitStream;
try
{
mfxU32 swappingSize = nalUnit->DataLength;
mfxU8 * swappingMemory = GetMemoryForSwapping(swappingSize);
BytesSwapper::SwapMemory(swappingMemory, swappingSize, nalUnit->Data + nalUnit->DataOffset, nalUnit->DataLength);
bitStream.Reset(swappingMemory, swappingSize);
NAL_Unit_Type uNALUnitType;
mfxU8 uNALStorageIDC;
bitStream.GetNALUnitType(uNALUnitType, uNALStorageIDC);
do
{
AVCSEIPayLoad m_SEIPayLoads;
bitStream.GetSEI(m_headers.m_SeqParams,
m_headers.m_SeqParams.GetCurrrentID(), &m_SEIPayLoads);
if (m_SEIPayLoads.payLoadType == SEI_RESERVED)
continue;
m_headers.m_SEIParams.AddHeader(&m_SEIPayLoads);
} while (bitStream.More_RBSP_Data());
} catch(...)
{
// nothing to do just catch it
}
return MFX_ERR_NONE;
}
AVCSlice * AVC_Spl::DecodeSliceHeader(mfxBitstream * nalUnit)
{
m_slicesStorage.push_back(AVCSlice());
AVCSlice *pSlice = &m_slicesStorage.back();
mfxU32 swappingSize = nalUnit->DataLength;
mfxU8 * swappingMemory = GetMemoryForSwapping(swappingSize);
BytesSwapper::SwapMemory(swappingMemory, swappingSize, nalUnit->Data + nalUnit->DataOffset, nalUnit->DataLength);
mfxI32 pps_pid = pSlice->RetrievePicParamSetNumber(swappingMemory, swappingSize);
if (pps_pid == -1)
{
return 0;
}
AVCSEIPayLoad * spl = m_headers.m_SEIParams.GetHeader(SEI_RECOVERY_POINT_TYPE);
if (m_WaitForIDR)
{
if (pSlice->GetSliceHeader()->slice_type != INTRASLICE && !spl)
{
return 0;
}
}
pSlice->m_picParamSet = m_headers.m_PicParams.GetHeader(pps_pid);
if (!pSlice->m_picParamSet)
{
return 0;
}
mfxI32 seq_parameter_set_id = pSlice->m_picParamSet->seq_parameter_set_id;
if (NAL_UT_CODED_SLICE_EXTENSION == pSlice->GetSliceHeader()->nal_unit_type)
{
pSlice->m_seqParamSet = pSlice->m_seqParamSetMvcEx = m_headers.m_SeqParamsMvcExt.GetHeader(seq_parameter_set_id);
if (NULL == pSlice->m_seqParamSetMvcEx)
{
return 0;
}
m_headers.m_SeqParamsMvcExt.SetCurrentID(pSlice->m_seqParamSetMvcEx->seq_parameter_set_id);
m_headers.m_PicParams.SetCurrentID(pSlice->m_picParamSet->pic_parameter_set_id);
}
else
{
pSlice->m_seqParamSetMvcEx = m_headers.m_SeqParamsMvcExt.GetCurrentHeader();
pSlice->m_seqParamSet = m_headers.m_SeqParams.GetHeader(seq_parameter_set_id);
m_headers.m_SeqParams.SetCurrentID(pSlice->m_picParamSet->seq_parameter_set_id);
m_headers.m_PicParams.SetCurrentID(pSlice->m_picParamSet->pic_parameter_set_id);
}
pSlice->m_seqParamSetEx = m_headers.m_SeqExParams.GetHeader(seq_parameter_set_id);
pSlice->m_dTime = nalUnit->TimeStamp;
if (!pSlice->DecodeHeader(swappingMemory, swappingSize))
{
return 0;
}
if (spl && (pSlice->GetSliceHeader()->slice_type != INTRASLICE))
{
m_headers.m_SEIParams.RemoveHeader(spl->GetID());
}
m_WaitForIDR = false;
return pSlice;
}
AVCFrameInfo * AVC_Spl::GetFreeFrame()
{
return m_AUInfo.get();
}
void AVC_Spl::ResetCurrentState()
{
m_frame.DataLength = 0;
m_frame.SliceNum = 0;
m_frame.FirstFieldSliceNum = 0;
m_AUInfo->Reset();
if (m_slicesStorage.size() > 1)
{
m_slicesStorage.erase(m_slicesStorage.begin(), --m_slicesStorage.end());
}
}
bool AVC_Spl::IsFieldOfOneFrame(AVCFrameInfo * frame, const AVCSliceHeader * slice1, const AVCSliceHeader *slice2)
{
if (frame && frame->m_index)
return false;
if ((slice1->nal_ref_idc && !slice2->nal_ref_idc) ||
(!slice1->nal_ref_idc && slice2->nal_ref_idc))
return false;
if (slice1->field_pic_flag != slice2->field_pic_flag)
return false;
if (slice1->bottom_field_flag == slice2->bottom_field_flag)
return false;
return true;
}
inline bool IsSlicesOfOneAU(const AVCSliceHeader *pOne, const AVCSliceHeader *pTwo)
{
if (!pOne || !pTwo)
return true;
if (pOne->view_id != pTwo->view_id)
{
if (pOne->view_id < pTwo->view_id)
{
return true;
}
return false;
}
// this function checks two slices are from same picture or not
// 7.4.1.2.4 part of AVC standart
if ((pOne->frame_num != pTwo->frame_num) ||
(pOne->first_mb_in_slice == pTwo->first_mb_in_slice) ||
(pOne->pic_parameter_set_id != pTwo->pic_parameter_set_id) ||
(pOne->field_pic_flag != pTwo->field_pic_flag) ||
(pOne->bottom_field_flag != pTwo->bottom_field_flag))
return false;
if ((pOne->nal_ref_idc != pTwo->nal_ref_idc) &&
(0 == std::min(pOne->nal_ref_idc, pTwo->nal_ref_idc)))
return false;
if ((pOne->pic_order_cnt_lsb != pTwo->pic_order_cnt_lsb) ||
(pOne->delta_pic_order_cnt_bottom != pTwo->delta_pic_order_cnt_bottom))
return false;
if ((pOne->delta_pic_order_cnt[0] != pTwo->delta_pic_order_cnt[0]) ||
(pOne->delta_pic_order_cnt[1] != pTwo->delta_pic_order_cnt[1]))
return false;
if (pOne->nal_unit_type != pTwo->nal_unit_type)
{
if ((NAL_UT_IDR_SLICE == pOne->nal_unit_type) ||
(NAL_UT_IDR_SLICE == pTwo->nal_unit_type))
return false;
}
else if (NAL_UT_IDR_SLICE == pOne->nal_unit_type)
{
if (pOne->idr_pic_id != pTwo->idr_pic_id)
return false;
}
return true;
}
mfxStatus AVC_Spl::AddSlice(AVCSlice * pSlice)
{
m_pLastSlice = 0;
if (!pSlice)
{
// complete current frame info
return MFX_ERR_NONE;
}
if (m_currentInfo)
{
AVCSlice * pFirstFrameSlice = m_currentInfo->m_slice;
if (pFirstFrameSlice && (false == IsSlicesOfOneAU(pFirstFrameSlice->GetSliceHeader(), pSlice->GetSliceHeader())))
{
// complete frame
if (pSlice->IsField())
{
if (IsFieldOfOneFrame(m_currentInfo, pFirstFrameSlice->GetSliceHeader(), pSlice->GetSliceHeader()))
{
m_currentInfo->m_index = 1;
m_currentInfo->m_slice = pSlice;
}
else
{
m_currentInfo->m_index = 0;
m_pLastSlice = pSlice;
return MFX_ERR_NONE;
}
}
else
{
m_currentInfo->m_index = 0;
m_pLastSlice = pSlice;
return MFX_ERR_NONE;
}
}
}
else
{
m_currentInfo = GetFreeFrame();
if (!m_currentInfo)
{
m_pLastSlice = pSlice;
return MFX_ERR_NOT_ENOUGH_BUFFER;
}
m_currentInfo->m_index = 0;
}
if (!m_currentInfo->m_slice)
m_currentInfo->m_slice = pSlice;
return MFX_ERR_MORE_DATA;
}
mfxStatus AVC_Spl::AddNalUnit(mfxBitstream * nalUnit)
{
static mfxU8 start_code_prefix[] = {0, 0, 1};
if (m_frame.DataLength + nalUnit->DataLength + sizeof(start_code_prefix) >= BUFFER_SIZE)
return MFX_ERR_NOT_ENOUGH_BUFFER;
MSDK_MEMCPY_BUF(m_frame.Data, m_frame.DataLength, BUFFER_SIZE, start_code_prefix, sizeof(start_code_prefix));
MSDK_MEMCPY_BUF(m_frame.Data, m_frame.DataLength + sizeof(start_code_prefix), BUFFER_SIZE, nalUnit->Data + nalUnit->DataOffset, nalUnit->DataLength);
m_frame.DataLength += (mfxU32)(nalUnit->DataLength + sizeof(start_code_prefix));
return MFX_ERR_NONE;
}
mfxStatus AVC_Spl::AddSliceNalUnit(mfxBitstream * nalUnit, AVCSlice * slice)
{
static mfxU8 start_code_prefix[] = {0, 0, 1};
mfxU32 sliceLength = (mfxU32)(nalUnit->DataLength + sizeof(start_code_prefix));
if (m_frame.DataLength + sliceLength >= BUFFER_SIZE)
return MFX_ERR_NOT_ENOUGH_BUFFER;
MSDK_MEMCPY_BUF(m_frame.Data, m_frame.DataLength, BUFFER_SIZE, start_code_prefix, sizeof(start_code_prefix));
MSDK_MEMCPY_BUF(m_frame.Data, m_frame.DataLength + sizeof(start_code_prefix), BUFFER_SIZE, nalUnit->Data + nalUnit->DataOffset, nalUnit->DataLength);
if (!m_frame.SliceNum)
{
m_frame.TimeStamp = nalUnit->TimeStamp;
}
m_frame.SliceNum++;
if (m_slices.size() <= m_frame.SliceNum)
{
m_slices.resize(m_frame.SliceNum + 10);
m_frame.Slice = &m_slices[0];
}
SliceSplitterInfo & newSlice = m_slices[m_frame.SliceNum - 1];
AVCHeadersBitstream * bs = slice->GetBitStream();
newSlice.HeaderLength = (mfxU32)bs->BytesDecoded();
// add number of 003 sequence to HeaderLength
for(mfxU8 *ptr = nalUnit->Data + sizeof(start_code_prefix); ptr < nalUnit->Data + sizeof(start_code_prefix) + newSlice.HeaderLength; ptr++)
{
if (ptr[0]==0 && ptr[1]==0 && ptr[2]==3)
{
newSlice.HeaderLength++;
}
}
newSlice.HeaderLength += sizeof(start_code_prefix) + 1;
newSlice.DataLength = sliceLength;
newSlice.DataOffset = m_frame.DataLength;
if(IS_I_SLICE(slice->GetSliceHeader()->slice_type))
newSlice.SliceType = TYPE_I;
else if(IS_P_SLICE(slice->GetSliceHeader()->slice_type))
newSlice.SliceType = TYPE_P;
else if(IS_B_SLICE(slice->GetSliceHeader()->slice_type))
newSlice.SliceType = TYPE_B;
m_frame.DataLength += sliceLength;
if (!m_currentInfo->m_index)
m_frame.FirstFieldSliceNum++;
return MFX_ERR_NONE;
}
mfxStatus AVC_Spl::ProcessNalUnit(mfxI32 nalType, mfxBitstream * nalUnit)
{
if (!nalUnit)
return MFX_ERR_MORE_DATA;
switch (nalType)
{
case NAL_UT_IDR_SLICE:
case NAL_UT_SLICE:
case NAL_UT_CODED_SLICE_EXTENSION:
{
AVCSlice * pSlice = DecodeSliceHeader(nalUnit);
if (pSlice)
{
mfxStatus sts = AddSlice(pSlice);
if (sts == MFX_ERR_NOT_ENOUGH_BUFFER)
{
return sts;
}
if (!m_pLastSlice)
{
AddSliceNalUnit(nalUnit, pSlice);
}
else
{
m_lastNalUnit = nalUnit;
}
if (sts == MFX_ERR_NONE)
{
return sts;
}
}
}
break;
case NAL_UT_SPS:
case NAL_UT_PPS:
case NAL_UT_SPS_EX:
case NAL_UNIT_SUBSET_SPS:
case NAL_UNIT_PREFIX:
DecodeHeader(nalUnit);
AddNalUnit(nalUnit);
break;
case NAL_UT_SEI:
DecodeSEI(nalUnit);
AddNalUnit(nalUnit);
break;
case NAL_UT_AUD:
AddNalUnit(nalUnit);
break;
case NAL_UT_DPA:
case NAL_UT_DPB:
case NAL_UT_DPC:
case NAL_UT_FD:
case NAL_UT_UNSPECIFIED:
break;
case NAL_END_OF_STREAM:
case NAL_END_OF_SEQ:
{
AddNalUnit(nalUnit);
}
break;
default:
break;
};
return MFX_ERR_MORE_DATA;
}
mfxStatus AVC_Spl::GetFrame(mfxBitstream * bs_in, FrameSplitterInfo ** frame)
{
*frame = 0;
do
{
if (m_pLastSlice)
{
AVCSlice * pSlice = m_pLastSlice;
mfxStatus sts = AddSlice(pSlice);
if(!m_lastNalUnit)
{
msdk_printf(MSDK_STRING("ERROR: m_lastNalUnit=NULL\n"));
return MFX_ERR_NULL_PTR;
}
AddSliceNalUnit(m_lastNalUnit, pSlice);
m_lastNalUnit = 0;
if (sts == MFX_ERR_NONE)
return MFX_ERR_NONE;
}
mfxBitstream * destination=NULL;
mfxI32 nalType = m_pNALSplitter->GetNalUnits(bs_in, destination);
mfxStatus sts = ProcessNalUnit(nalType, destination);
if (sts == MFX_ERR_NONE || (!bs_in && m_frame.SliceNum))
{
m_currentInfo = 0;
*frame = &m_frame;
return MFX_ERR_NONE;
}
} while (bs_in && bs_in->DataLength > MINIMAL_DATA_SIZE);
return MFX_ERR_MORE_DATA;
}
AVCSlice::AVCSlice()
{
Reset();
}
void AVCSlice::Reset()
{
m_picParamSet = 0;
m_seqParamSet = 0;
m_seqParamSetMvcEx = 0;
m_seqParamSetEx = 0;
m_dTime=0;
memset(&m_sliceHeader, 0, sizeof(m_sliceHeader));
}
AVCSliceHeader * AVCSlice::GetSliceHeader()
{
return &m_sliceHeader;
}
mfxI32 AVCSlice::RetrievePicParamSetNumber(mfxU8 *pSource, mfxU32 nSourceSize)
{
if (!nSourceSize)
return -1;
m_bitStream.Reset(pSource, nSourceSize);
mfxStatus umcRes = MFX_ERR_NONE;
try
{
umcRes = m_bitStream.GetNALUnitType(m_sliceHeader.nal_unit_type, m_sliceHeader.nal_ref_idc);
if (MFX_ERR_NONE != umcRes)
return false;
// decode first part of slice header
umcRes = m_bitStream.GetSliceHeaderPart1(&m_sliceHeader);
if (MFX_ERR_NONE != umcRes)
return -1;
} catch (...)
{
return -1;
}
return m_sliceHeader.pic_parameter_set_id;
}
bool AVCSlice::DecodeHeader(mfxU8 *pSource, mfxU32 nSourceSize)
{
m_bitStream.Reset(pSource, nSourceSize);
if (!nSourceSize)
return false;
mfxStatus umcRes = MFX_ERR_NONE;
// Locals for additional slice data to be read into, the data
// was read and saved from the first slice header of the picture,
// is not supposed to change within the picture, so can be
// discarded when read again here.
try
{
memset(&m_sliceHeader, 0, sizeof(m_sliceHeader));
umcRes = m_bitStream.GetNALUnitType(m_sliceHeader.nal_unit_type, m_sliceHeader.nal_ref_idc);
if (MFX_ERR_NONE != umcRes)
return false;
// decode first part of slice header
umcRes = m_bitStream.GetSliceHeaderPart1(&m_sliceHeader);
if (MFX_ERR_NONE != umcRes)
return false;
// decode second part of slice header
umcRes = m_bitStream.GetSliceHeaderPart2(&m_sliceHeader,
m_picParamSet,
m_seqParamSet);
if (MFX_ERR_NONE != umcRes)
return false;
PredWeightTable m_PredWeight[2][MAX_NUM_REF_FRAMES];
RefPicListReorderInfo ReorderInfoL0;
RefPicListReorderInfo ReorderInfoL1;
AdaptiveMarkingInfo m_AdaptiveMarkingInfo;
// decode second part of slice header
umcRes = m_bitStream.GetSliceHeaderPart3(&m_sliceHeader,
m_PredWeight[0],
m_PredWeight[1],
&ReorderInfoL0,
&ReorderInfoL1,
&m_AdaptiveMarkingInfo,
m_picParamSet,
m_seqParamSet,
m_sliceHeader.nal_ref_idc);
if (MFX_ERR_NONE != umcRes)
return false;
if (m_picParamSet->entropy_coding_mode)
m_bitStream.AlignPointerRight();
}
catch(const AVC_exception & )
{
return false;
}
catch(...)
{
return false;
}
return (MFX_ERR_NONE == umcRes);
}
mfxStatus AVC_Spl::PostProcessing(FrameSplitterInfo *frame, mfxU32 sliceNum)
{
UNREFERENCED_PARAMETER(frame);
UNREFERENCED_PARAMETER(sliceNum);
return MFX_ERR_NONE;
}
} // namespace ProtectedLibrary

View File

@@ -0,0 +1,296 @@
/******************************************************************************\
Copyright (c) 2005-2019, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
This sample was distributed or derived from the Intel's Media Samples package.
The original version of this sample may be obtained from https://software.intel.com/en-us/intel-media-server-studio
or https://software.intel.com/en-us/media-client-solutions-support.
\**********************************************************************************/
#include <assert.h>
#include <algorithm>
#include "base_allocator.h"
#include "vm/thread_defs.h"
MFXFrameAllocator::MFXFrameAllocator()
{
pthis = this;
Alloc = Alloc_;
Lock = Lock_;
Free = Free_;
Unlock = Unlock_;
GetHDL = GetHDL_;
}
MFXFrameAllocator::~MFXFrameAllocator()
{
}
mfxStatus MFXFrameAllocator::Alloc_(mfxHDL pthis, mfxFrameAllocRequest *request, mfxFrameAllocResponse *response)
{
if (0 == pthis)
return MFX_ERR_MEMORY_ALLOC;
MFXFrameAllocator& self = *(MFXFrameAllocator *)pthis;
return self.AllocFrames(request, response);
}
mfxStatus MFXFrameAllocator::Lock_(mfxHDL pthis, mfxMemId mid, mfxFrameData *ptr)
{
if (0 == pthis)
return MFX_ERR_MEMORY_ALLOC;
MFXFrameAllocator& self = *(MFXFrameAllocator *)pthis;
return self.LockFrame(mid, ptr);
}
mfxStatus MFXFrameAllocator::Unlock_(mfxHDL pthis, mfxMemId mid, mfxFrameData *ptr)
{
if (0 == pthis)
return MFX_ERR_MEMORY_ALLOC;
MFXFrameAllocator& self = *(MFXFrameAllocator *)pthis;
return self.UnlockFrame(mid, ptr);
}
mfxStatus MFXFrameAllocator::Free_(mfxHDL pthis, mfxFrameAllocResponse *response)
{
if (0 == pthis)
return MFX_ERR_MEMORY_ALLOC;
MFXFrameAllocator& self = *(MFXFrameAllocator *)pthis;
return self.FreeFrames(response);
}
mfxStatus MFXFrameAllocator::GetHDL_(mfxHDL pthis, mfxMemId mid, mfxHDL *handle)
{
if (0 == pthis)
return MFX_ERR_MEMORY_ALLOC;
MFXFrameAllocator& self = *(MFXFrameAllocator *)pthis;
return self.GetFrameHDL(mid, handle);
}
BaseFrameAllocator::BaseFrameAllocator()
{
}
BaseFrameAllocator::~BaseFrameAllocator()
{
}
mfxStatus BaseFrameAllocator::CheckRequestType(mfxFrameAllocRequest *request)
{
if (0 == request)
return MFX_ERR_NULL_PTR;
// check that Media SDK component is specified in request
if ((request->Type & MEMTYPE_FROM_MASK) != 0)
return MFX_ERR_NONE;
else
return MFX_ERR_UNSUPPORTED;
}
mfxStatus BaseFrameAllocator::ReallocFrame(mfxMemId midIn, const mfxFrameInfo *info, mfxU16 memType, mfxMemId *midOut)
{
return ReallocImpl(midIn, info, memType, midOut);
}
mfxStatus BaseFrameAllocator::AllocFrames(mfxFrameAllocRequest *request, mfxFrameAllocResponse *response)
{
if (0 == request || 0 == response || 0 == request->NumFrameSuggested)
return MFX_ERR_MEMORY_ALLOC;
if (MFX_ERR_NONE != CheckRequestType(request))
return MFX_ERR_UNSUPPORTED;
mfxStatus sts = MFX_ERR_NONE;
if ( // External Frames
((request->Type & MFX_MEMTYPE_EXTERNAL_FRAME) &&
(request->Type & (MFX_MEMTYPE_FROM_DECODE | MFX_MEMTYPE_FROM_ENC | MFX_MEMTYPE_FROM_PAK)))
// Exception: Internal Frames for FEI ENC / PAK reconstructs
||
((request->Type & MFX_MEMTYPE_INTERNAL_FRAME) &&
(request->Type & (MFX_MEMTYPE_FROM_ENC | MFX_MEMTYPE_FROM_PAK)))
)
{
bool foundInCache = false;
// external decoder allocations
std::list<UniqueResponse>::iterator
it = m_ExtResponses.begin(),
et = m_ExtResponses.end();
UniqueResponse checker(*response, request->Info.Width, request->Info.Height, request->Type);
for (; it != et; ++it)
{
// same decoder and same size
if (request->AllocId == it->AllocId && checker(*it))
{
// check if enough frames were allocated
if (request->NumFrameSuggested > it->NumFrameActual)
return MFX_ERR_MEMORY_ALLOC;
it->m_refCount++;
// return existing response
*response = (mfxFrameAllocResponse&)*it;
foundInCache = true;
}
}
if (!foundInCache)
{
sts = AllocImpl(request, response);
if (sts == MFX_ERR_NONE)
{
response->AllocId = request->AllocId;
m_ExtResponses.push_back(UniqueResponse(*response, request->Info.Width, request->Info.Height, UniqueResponse::CropMemoryTypeToStore(request->Type)));
}
}
}
else
{
// internal allocations
// reserve space before allocation to avoid memory leak
m_responses.push_back(mfxFrameAllocResponse());
sts = AllocImpl(request, response);
if (sts == MFX_ERR_NONE)
{
m_responses.back() = *response;
}
else
{
m_responses.pop_back();
}
}
return sts;
}
mfxStatus BaseFrameAllocator::FreeFrames(mfxFrameAllocResponse *response)
{
std::lock_guard<std::mutex> lock(mtx);
if (response == 0)
return MFX_ERR_INVALID_HANDLE;
mfxStatus sts = MFX_ERR_NONE;
// check whether response is an external decoder response
std::list<UniqueResponse>::iterator i =
std::find_if( m_ExtResponses.begin(), m_ExtResponses.end(), std::bind(IsSame(), *response, std::placeholders::_1));
if (i != m_ExtResponses.end())
{
if ((--i->m_refCount) == 0)
{
sts = ReleaseResponse(response);
m_ExtResponses.erase(i);
}
return sts;
}
// if not found so far, then search in internal responses
std::list<mfxFrameAllocResponse>::iterator i2 =
std::find_if(m_responses.begin(), m_responses.end(), std::bind(IsSame(), *response, std::placeholders::_1));
if (i2 != m_responses.end())
{
sts = ReleaseResponse(response);
m_responses.erase(i2);
return sts;
}
// not found anywhere, report an error
return MFX_ERR_INVALID_HANDLE;
}
mfxStatus BaseFrameAllocator::Close()
{
std::lock_guard<std::mutex> lock(mtx);
std::list<UniqueResponse> ::iterator i;
for (i = m_ExtResponses.begin(); i!= m_ExtResponses.end(); i++)
{
ReleaseResponse(&*i);
}
m_ExtResponses.clear();
std::list<mfxFrameAllocResponse> ::iterator i2;
for (i2 = m_responses.begin(); i2!= m_responses.end(); i2++)
{
ReleaseResponse(&*i2);
}
return MFX_ERR_NONE;
}
MFXBufferAllocator::MFXBufferAllocator()
{
pthis = this;
Alloc = Alloc_;
Lock = Lock_;
Free = Free_;
Unlock = Unlock_;
}
MFXBufferAllocator::~MFXBufferAllocator()
{
}
mfxStatus MFXBufferAllocator::Alloc_(mfxHDL pthis, mfxU32 nbytes, mfxU16 type, mfxMemId *mid)
{
if (0 == pthis)
return MFX_ERR_MEMORY_ALLOC;
MFXBufferAllocator& self = *(MFXBufferAllocator *)pthis;
return self.AllocBuffer(nbytes, type, mid);
}
mfxStatus MFXBufferAllocator::Lock_(mfxHDL pthis, mfxMemId mid, mfxU8 **ptr)
{
if (0 == pthis)
return MFX_ERR_MEMORY_ALLOC;
MFXBufferAllocator& self = *(MFXBufferAllocator *)pthis;
return self.LockBuffer(mid, ptr);
}
mfxStatus MFXBufferAllocator::Unlock_(mfxHDL pthis, mfxMemId mid)
{
if (0 == pthis)
return MFX_ERR_MEMORY_ALLOC;
MFXBufferAllocator& self = *(MFXBufferAllocator *)pthis;
return self.UnlockBuffer(mid);
}
mfxStatus MFXBufferAllocator::Free_(mfxHDL pthis, mfxMemId mid)
{
if (0 == pthis)
return MFX_ERR_MEMORY_ALLOC;
MFXBufferAllocator& self = *(MFXBufferAllocator *)pthis;
return self.FreeBuffer(mid);
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,600 @@
/******************************************************************************\
Copyright (c) 2005-2019, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
This sample was distributed or derived from the Intel's Media Samples package.
The original version of this sample may be obtained from https://software.intel.com/en-us/intel-media-server-studio
or https://software.intel.com/en-us/media-client-solutions-support.
\**********************************************************************************/
#include "mfx_samples_config.h"
#if defined(_WIN32) || defined(_WIN64)
#include "sample_defs.h"
#if MFX_D3D11_SUPPORT
#include <objbase.h>
#include <initguid.h>
#include <assert.h>
#include <algorithm>
#include <functional>
#include <iterator>
#include "d3d11_allocator.h"
#define D3DFMT_NV12 (DXGI_FORMAT)MAKEFOURCC('N','V','1','2')
#define D3DFMT_YV12 (DXGI_FORMAT)MAKEFOURCC('Y','V','1','2')
//for generating sequence of mfx handles
template <typename T>
struct sequence {
T x;
sequence(T seed) : x(seed) { }
};
template <>
struct sequence<mfxHDL> {
mfxHDL x;
sequence(mfxHDL seed) : x(seed) { }
mfxHDL operator ()()
{
mfxHDL y = x;
x = (mfxHDL)(1 + (size_t)(x));
return y;
}
};
D3D11FrameAllocator::D3D11FrameAllocator()
{
m_pDeviceContext = NULL;
}
D3D11FrameAllocator::~D3D11FrameAllocator()
{
Close();
}
D3D11FrameAllocator::TextureSubResource D3D11FrameAllocator::GetResourceFromMid(mfxMemId mid)
{
size_t index = (size_t)MFXReadWriteMid(mid).raw() - 1;
if(m_memIdMap.size() <= index)
return TextureSubResource();
//reverse iterator dereferencing
TextureResource * p = &(*m_memIdMap[index]);
if (!p->bAlloc)
return TextureSubResource();
return TextureSubResource(p, mid);
}
mfxStatus D3D11FrameAllocator::Init(mfxAllocatorParams *pParams)
{
D3D11AllocatorParams *pd3d11Params = 0;
pd3d11Params = dynamic_cast<D3D11AllocatorParams *>(pParams);
if (NULL == pd3d11Params ||
NULL == pd3d11Params->pDevice)
{
return MFX_ERR_NOT_INITIALIZED;
}
m_initParams = *pd3d11Params;
MSDK_SAFE_RELEASE(m_pDeviceContext);
pd3d11Params->pDevice->GetImmediateContext(&m_pDeviceContext);
return MFX_ERR_NONE;
}
mfxStatus D3D11FrameAllocator::Close()
{
mfxStatus sts = BaseFrameAllocator::Close();
for(referenceType i = m_resourcesByRequest.begin(); i != m_resourcesByRequest.end(); i++)
{
i->Release();
}
m_resourcesByRequest.clear();
m_memIdMap.clear();
MSDK_SAFE_RELEASE(m_pDeviceContext);
return sts;
}
mfxStatus D3D11FrameAllocator::LockFrame(mfxMemId mid, mfxFrameData *ptr)
{
HRESULT hRes = S_OK;
D3D11_TEXTURE2D_DESC desc = {0};
D3D11_MAPPED_SUBRESOURCE lockedRect = {0};
//check that texture exists
TextureSubResource sr = GetResourceFromMid(mid);
if (!sr.GetTexture())
return MFX_ERR_LOCK_MEMORY;
D3D11_MAP mapType = D3D11_MAP_READ;
UINT mapFlags = D3D11_MAP_FLAG_DO_NOT_WAIT;
{
if (NULL == sr.GetStaging())
{
hRes = m_pDeviceContext->Map(sr.GetTexture(), sr.GetSubResource(), D3D11_MAP_READ, D3D11_MAP_FLAG_DO_NOT_WAIT, &lockedRect);
desc.Format = DXGI_FORMAT_P8;
}
else
{
sr.GetTexture()->GetDesc(&desc);
if (DXGI_FORMAT_NV12 != desc.Format &&
DXGI_FORMAT_420_OPAQUE != desc.Format &&
DXGI_FORMAT_YUY2 != desc.Format &&
DXGI_FORMAT_P8 != desc.Format &&
DXGI_FORMAT_B8G8R8A8_UNORM != desc.Format &&
DXGI_FORMAT_R16_UINT != desc.Format &&
DXGI_FORMAT_R16_UNORM != desc.Format &&
DXGI_FORMAT_R10G10B10A2_UNORM != desc.Format &&
DXGI_FORMAT_R16G16B16A16_UNORM != desc.Format &&
DXGI_FORMAT_P010 != desc.Format &&
DXGI_FORMAT_AYUV != desc.Format
#if (MFX_VERSION >= 1027)
&& DXGI_FORMAT_Y210 != desc.Format
&& DXGI_FORMAT_Y410 != desc.Format
#endif
#if (MFX_VERSION >= 1031)
&& DXGI_FORMAT_P016 != desc.Format
&& DXGI_FORMAT_Y216 != desc.Format
&& DXGI_FORMAT_Y416 != desc.Format
#endif
)
{
return MFX_ERR_LOCK_MEMORY;
}
//coping data only in case user wants to read from stored surface
{
if (MFXReadWriteMid(mid, MFXReadWriteMid::reuse).isRead())
{
m_pDeviceContext->CopySubresourceRegion(sr.GetStaging(), 0, 0, 0, 0, sr.GetTexture(), sr.GetSubResource(), NULL);
}
do
{
hRes = m_pDeviceContext->Map(sr.GetStaging(), 0, mapType, mapFlags, &lockedRect);
if (S_OK != hRes && DXGI_ERROR_WAS_STILL_DRAWING != hRes)
{
msdk_printf(MSDK_STRING("ERROR: m_pDeviceContext->Map = 0x%08lx\n"), hRes);
}
}
while (DXGI_ERROR_WAS_STILL_DRAWING == hRes);
}
}
}
if (FAILED(hRes))
return MFX_ERR_LOCK_MEMORY;
switch (desc.Format)
{
case DXGI_FORMAT_P010:
#if (MFX_VERSION >= 1031)
case DXGI_FORMAT_P016:
#endif
case DXGI_FORMAT_NV12:
ptr->Pitch = (mfxU16)lockedRect.RowPitch;
ptr->Y = (mfxU8 *)lockedRect.pData;
ptr->U = (mfxU8 *)lockedRect.pData + desc.Height * lockedRect.RowPitch;
ptr->V = (desc.Format == DXGI_FORMAT_P010) ? ptr->U + 2 : ptr->U + 1;
break;
case DXGI_FORMAT_420_OPAQUE: // can be unsupported by standard ms guid
ptr->Pitch = (mfxU16)lockedRect.RowPitch;
ptr->Y = (mfxU8 *)lockedRect.pData;
ptr->V = ptr->Y + desc.Height * lockedRect.RowPitch;
ptr->U = ptr->V + (desc.Height * lockedRect.RowPitch) / 4;
break;
case DXGI_FORMAT_YUY2:
ptr->Pitch = (mfxU16)lockedRect.RowPitch;
ptr->Y = (mfxU8 *)lockedRect.pData;
ptr->U = ptr->Y + 1;
ptr->V = ptr->Y + 3;
break;
case DXGI_FORMAT_P8 :
ptr->Pitch = (mfxU16)lockedRect.RowPitch;
ptr->Y = (mfxU8 *)lockedRect.pData;
ptr->U = 0;
ptr->V = 0;
break;
case DXGI_FORMAT_AYUV:
ptr->Pitch = (mfxU16)lockedRect.RowPitch;
ptr->V = (mfxU8 *)lockedRect.pData;
ptr->U = ptr->V + 1;
ptr->Y = ptr->V + 2;
ptr->A = ptr->V + 3;
break;
case DXGI_FORMAT_B8G8R8A8_UNORM:
ptr->Pitch = (mfxU16)lockedRect.RowPitch;
ptr->B = (mfxU8 *)lockedRect.pData;
ptr->G = ptr->B + 1;
ptr->R = ptr->B + 2;
ptr->A = ptr->B + 3;
break;
case DXGI_FORMAT_R10G10B10A2_UNORM :
ptr->Pitch = (mfxU16)lockedRect.RowPitch;
ptr->B = (mfxU8 *)lockedRect.pData;
ptr->G = ptr->B + 1;
ptr->R = ptr->B + 2;
ptr->A = ptr->B + 3;
break;
case DXGI_FORMAT_R16G16B16A16_UNORM:
ptr->V16 = (mfxU16*)lockedRect.pData;
ptr->U16 = ptr->V16 + 1;
ptr->Y16 = ptr->V16 + 2;
ptr->A = (mfxU8*)(ptr->V16 + 3);
ptr->PitchHigh = (mfxU16)((mfxU32)lockedRect.RowPitch / (1 << 16));
ptr->PitchLow = (mfxU16)((mfxU32)lockedRect.RowPitch % (1 << 16));
break;
case DXGI_FORMAT_R16_UNORM :
case DXGI_FORMAT_R16_UINT :
ptr->Pitch = (mfxU16)lockedRect.RowPitch;
ptr->Y16 = (mfxU16 *)lockedRect.pData;
ptr->U16 = 0;
ptr->V16 = 0;
break;
#if (MFX_VERSION >= 1031)
case DXGI_FORMAT_Y416:
ptr->PitchHigh = (mfxU16)(lockedRect.RowPitch / (1 << 16));
ptr->PitchLow = (mfxU16)(lockedRect.RowPitch % (1 << 16));
ptr->U16 = (mfxU16*)lockedRect.pData;
ptr->Y16 = ptr->U16 + 1;
ptr->V16 = ptr->Y16 + 1;
ptr->A = (mfxU8 *)(ptr->V16 + 1);
break;
case DXGI_FORMAT_Y216:
#endif
#if (MFX_VERSION >= 1027)
case DXGI_FORMAT_Y210:
ptr->PitchHigh = (mfxU16)(lockedRect.RowPitch / (1 << 16));
ptr->PitchLow = (mfxU16)(lockedRect.RowPitch % (1 << 16));
ptr->Y16 = (mfxU16 *)lockedRect.pData;
ptr->U16 = ptr->Y16 + 1;
ptr->V16 = ptr->Y16 + 3;
break;
case DXGI_FORMAT_Y410:
ptr->PitchHigh = (mfxU16)(lockedRect.RowPitch / (1 << 16));
ptr->PitchLow = (mfxU16)(lockedRect.RowPitch % (1 << 16));
ptr->Y410 = (mfxY410 *)lockedRect.pData;
ptr->Y = 0;
ptr->V = 0;
ptr->A = 0;
break;
#endif
default:
return MFX_ERR_LOCK_MEMORY;
}
return MFX_ERR_NONE;
}
mfxStatus D3D11FrameAllocator::UnlockFrame(mfxMemId mid, mfxFrameData *ptr)
{
//check that texture exists
TextureSubResource sr = GetResourceFromMid(mid);
if (!sr.GetTexture())
return MFX_ERR_LOCK_MEMORY;
if (NULL == sr.GetStaging())
{
m_pDeviceContext->Unmap(sr.GetTexture(), sr.GetSubResource());
}
else
{
m_pDeviceContext->Unmap(sr.GetStaging(), 0);
//only if user wrote something to texture
if (MFXReadWriteMid(mid, MFXReadWriteMid::reuse).isWrite())
{
m_pDeviceContext->CopySubresourceRegion(sr.GetTexture(), sr.GetSubResource(), 0, 0, 0, sr.GetStaging(), 0, NULL);
}
}
if (ptr)
{
ptr->Pitch=0;
ptr->U=ptr->V=ptr->Y=0;
ptr->A=ptr->R=ptr->G=ptr->B=0;
}
return MFX_ERR_NONE;
}
mfxStatus D3D11FrameAllocator::GetFrameHDL(mfxMemId mid, mfxHDL *handle)
{
if (NULL == handle)
return MFX_ERR_INVALID_HANDLE;
TextureSubResource sr = GetResourceFromMid(mid);
if (!sr.GetTexture())
return MFX_ERR_INVALID_HANDLE;
mfxHDLPair *pPair = (mfxHDLPair*)handle;
pPair->first = sr.GetTexture();
pPair->second = (mfxHDL)(UINT_PTR)sr.GetSubResource();
return MFX_ERR_NONE;
}
mfxStatus D3D11FrameAllocator::CheckRequestType(mfxFrameAllocRequest *request)
{
mfxStatus sts = BaseFrameAllocator::CheckRequestType(request);
if (MFX_ERR_NONE != sts)
return sts;
if ((request->Type & (MFX_MEMTYPE_VIDEO_MEMORY_DECODER_TARGET | MFX_MEMTYPE_VIDEO_MEMORY_PROCESSOR_TARGET)) != 0)
return MFX_ERR_NONE;
else
return MFX_ERR_UNSUPPORTED;
}
mfxStatus D3D11FrameAllocator::ReleaseResponse(mfxFrameAllocResponse *response)
{
if (NULL == response)
return MFX_ERR_NULL_PTR;
if (response->mids && 0 != response->NumFrameActual)
{
//check whether texture exsist
TextureSubResource sr = GetResourceFromMid(response->mids[0]);
if (!sr.GetTexture())
return MFX_ERR_NULL_PTR;
sr.Release();
//if texture is last it is possible to remove also all handles from map to reduce fragmentation
//search for allocated chunk
if (m_resourcesByRequest.end() == std::find_if(m_resourcesByRequest.begin(), m_resourcesByRequest.end(), TextureResource::isAllocated))
{
m_resourcesByRequest.clear();
m_memIdMap.clear();
}
}
return MFX_ERR_NONE;
}
mfxStatus D3D11FrameAllocator::ReallocImpl(mfxMemId /*mid*/, const mfxFrameInfo *info, mfxU16 /*memType*/, mfxMemId *midOut)
{
if (!info || !midOut)
return MFX_ERR_NULL_PTR;
//TODO: Need add implementation in the future.
return MFX_ERR_UNSUPPORTED;
}
mfxStatus D3D11FrameAllocator::AllocImpl(mfxFrameAllocRequest *request, mfxFrameAllocResponse *response)
{
HRESULT hRes;
DXGI_FORMAT colorFormat = ConverColortFormat(request->Info.FourCC);
if (DXGI_FORMAT_UNKNOWN == colorFormat)
{
msdk_printf(MSDK_STRING("D3D11 Allocator: invalid fourcc is provided (%#X), exitting\n"),request->Info.FourCC);
return MFX_ERR_UNSUPPORTED;
}
TextureResource newTexture;
if (request->Info.FourCC == MFX_FOURCC_P8)
{
D3D11_BUFFER_DESC desc = { 0 };
desc.ByteWidth = request->Info.Width * request->Info.Height;
desc.Usage = D3D11_USAGE_STAGING;
desc.BindFlags = 0;
desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
desc.MiscFlags = 0;
desc.StructureByteStride = 0;
ID3D11Buffer * buffer = 0;
hRes = m_initParams.pDevice->CreateBuffer(&desc, 0, &buffer);
if (FAILED(hRes))
return MFX_ERR_MEMORY_ALLOC;
newTexture.textures.push_back(reinterpret_cast<ID3D11Texture2D *>(buffer));
}
else
{
D3D11_TEXTURE2D_DESC desc = {0};
desc.Width = request->Info.Width;
desc.Height = request->Info.Height;
desc.MipLevels = 1;
//number of subresources is 1 in case of not single texture
desc.ArraySize = m_initParams.bUseSingleTexture ? request->NumFrameSuggested : 1;
desc.Format = ConverColortFormat(request->Info.FourCC);
desc.SampleDesc.Count = 1;
desc.Usage = D3D11_USAGE_DEFAULT;
desc.MiscFlags = m_initParams.uncompressedResourceMiscFlags | D3D11_RESOURCE_MISC_SHARED;
#if (MFX_VERSION >= 1025)
if ((request->Type&MFX_MEMTYPE_VIDEO_MEMORY_ENCODER_TARGET) && (request->Type & MFX_MEMTYPE_INTERNAL_FRAME))
{
desc.BindFlags = D3D11_BIND_DECODER | D3D11_BIND_VIDEO_ENCODER;
}
else
#endif
desc.BindFlags = D3D11_BIND_DECODER;
if ( (MFX_MEMTYPE_FROM_VPPIN & request->Type) && (DXGI_FORMAT_YUY2 == desc.Format) ||
(DXGI_FORMAT_B8G8R8A8_UNORM == desc.Format) ||
(DXGI_FORMAT_R10G10B10A2_UNORM == desc.Format) ||
(DXGI_FORMAT_R16G16B16A16_UNORM == desc.Format) )
{
desc.BindFlags = D3D11_BIND_RENDER_TARGET;
if (desc.ArraySize > 2)
return MFX_ERR_MEMORY_ALLOC;
}
if ( (MFX_MEMTYPE_FROM_VPPOUT & request->Type) ||
(MFX_MEMTYPE_VIDEO_MEMORY_PROCESSOR_TARGET & request->Type))
{
desc.BindFlags = D3D11_BIND_RENDER_TARGET;
if (desc.ArraySize > 2)
return MFX_ERR_MEMORY_ALLOC;
}
if(request->Type&MFX_MEMTYPE_SHARED_RESOURCE)
{
desc.BindFlags |= D3D11_BIND_SHADER_RESOURCE;
desc.MiscFlags = D3D11_RESOURCE_MISC_SHARED;
}
if( DXGI_FORMAT_P8 == desc.Format )
{
desc.BindFlags = 0;
}
ID3D11Texture2D* pTexture2D;
for(size_t i = 0; i < request->NumFrameSuggested / desc.ArraySize; i++)
{
hRes = m_initParams.pDevice->CreateTexture2D(&desc, NULL, &pTexture2D);
if (FAILED(hRes))
{
msdk_printf(MSDK_STRING("CreateTexture2D(%lld) failed, hr = 0x%08lx\n"), (long long)i, hRes);
return MFX_ERR_MEMORY_ALLOC;
}
newTexture.textures.push_back(pTexture2D);
}
desc.ArraySize = 1;
desc.Usage = D3D11_USAGE_STAGING;
desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
desc.BindFlags = 0;
desc.MiscFlags = 0;
for(size_t i = 0; i < request->NumFrameSuggested; i++)
{
hRes = m_initParams.pDevice->CreateTexture2D(&desc, NULL, &pTexture2D);
if (FAILED(hRes))
{
msdk_printf(MSDK_STRING("Create staging texture(%lld) failed hr = 0x%X\n"), (long long)i, (unsigned int)hRes);
return MFX_ERR_MEMORY_ALLOC;
}
newTexture.stagingTexture.push_back(pTexture2D);
}
}
// mapping to self created handles array, starting from zero or from last assigned handle + 1
sequence<mfxHDL> seq_initializer(m_resourcesByRequest.empty() ? 0 : m_resourcesByRequest.back().outerMids.back());
//incrementing starting index
//1. 0(NULL) is invalid memid
//2. back is last index not new one
seq_initializer();
std::generate_n(std::back_inserter(newTexture.outerMids), request->NumFrameSuggested, seq_initializer);
//saving texture resources
m_resourcesByRequest.push_back(newTexture);
//providing pointer to mids externally
response->mids = &m_resourcesByRequest.back().outerMids.front();
response->NumFrameActual = request->NumFrameSuggested;
//iterator prior end()
std::list <TextureResource>::iterator it_last = m_resourcesByRequest.end();
//fill map
std::fill_n(std::back_inserter(m_memIdMap), request->NumFrameSuggested, --it_last);
return MFX_ERR_NONE;
}
DXGI_FORMAT D3D11FrameAllocator::ConverColortFormat(mfxU32 fourcc)
{
switch (fourcc)
{
case MFX_FOURCC_NV12:
return DXGI_FORMAT_NV12;
case MFX_FOURCC_YUY2:
return DXGI_FORMAT_YUY2;
case MFX_FOURCC_RGB4:
return DXGI_FORMAT_B8G8R8A8_UNORM;
case MFX_FOURCC_P8:
case MFX_FOURCC_P8_TEXTURE:
return DXGI_FORMAT_P8;
case MFX_FOURCC_ARGB16:
case MFX_FOURCC_ABGR16:
return DXGI_FORMAT_R16G16B16A16_UNORM;
case MFX_FOURCC_P010:
return DXGI_FORMAT_P010;
case MFX_FOURCC_A2RGB10:
return DXGI_FORMAT_R10G10B10A2_UNORM;
case DXGI_FORMAT_AYUV:
case MFX_FOURCC_AYUV:
return DXGI_FORMAT_AYUV;
#if (MFX_VERSION >= 1027)
case MFX_FOURCC_Y210:
return DXGI_FORMAT_Y210;
case MFX_FOURCC_Y410:
return DXGI_FORMAT_Y410;
#endif
#if (MFX_VERSION >= 1031)
case MFX_FOURCC_P016:
return DXGI_FORMAT_P016;
case MFX_FOURCC_Y216:
return DXGI_FORMAT_Y216;
case MFX_FOURCC_Y416:
return DXGI_FORMAT_Y416;
#endif
default:
return DXGI_FORMAT_UNKNOWN;
}
}
#endif // #if MFX_D3D11_SUPPORT
#endif // #if defined(_WIN32) || defined(_WIN64)

View File

@@ -0,0 +1,395 @@
/******************************************************************************\
Copyright (c) 2005-2019, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
This sample was distributed or derived from the Intel's Media Samples package.
The original version of this sample may be obtained from https://software.intel.com/en-us/intel-media-server-studio
or https://software.intel.com/en-us/media-client-solutions-support.
\**********************************************************************************/
#include "mfx_samples_config.h"
#if defined(_WIN32) || defined(_WIN64)
#include "sample_defs.h"
#if MFX_D3D11_SUPPORT
#include "d3d11_device.h"
CD3D11Device::CD3D11Device():
m_nViews(0),
m_bDefaultStereoEnabled(FALSE),
m_bIsA2rgb10(FALSE),
m_HandleWindow(NULL)
{
}
CD3D11Device::~CD3D11Device()
{
Close();
}
mfxStatus CD3D11Device::FillSCD(mfxHDL hWindow, DXGI_SWAP_CHAIN_DESC& scd)
{
scd.Windowed = TRUE;
scd.OutputWindow = (HWND)hWindow;
scd.SampleDesc.Count = 1;
scd.BufferDesc.Format = (m_bIsA2rgb10) ? DXGI_FORMAT_R10G10B10A2_UNORM : DXGI_FORMAT_B8G8R8A8_UNORM;
scd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
scd.BufferCount = 1;
return MFX_ERR_NONE;
}
mfxStatus CD3D11Device::FillSCD1(DXGI_SWAP_CHAIN_DESC1& scd1)
{
scd1.Width = 0; // Use automatic sizing.
scd1.Height = 0;
scd1.Format = (m_bIsA2rgb10) ? DXGI_FORMAT_R10G10B10A2_UNORM : DXGI_FORMAT_B8G8R8A8_UNORM;
scd1.Stereo = m_nViews == 2 ? TRUE : FALSE;
scd1.SampleDesc.Count = 1; // Don't use multi-sampling.
scd1.SampleDesc.Quality = 0;
scd1.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
scd1.BufferCount = 2; // Use double buffering to minimize latency.
scd1.Scaling = DXGI_SCALING_STRETCH;
scd1.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD;
scd1.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH;
return MFX_ERR_NONE;
}
mfxStatus CD3D11Device::Init(
mfxHDL hWindow,
mfxU16 nViews,
mfxU32 nAdapterNum)
{
m_HandleWindow = (HWND)hWindow;
mfxStatus sts = MFX_ERR_NONE;
HRESULT hres = S_OK;
m_nViews = nViews;
if (2 < nViews)
return MFX_ERR_UNSUPPORTED;
m_bDefaultStereoEnabled = FALSE;
static D3D_FEATURE_LEVEL FeatureLevels[] = {
D3D_FEATURE_LEVEL_11_1,
D3D_FEATURE_LEVEL_11_0,
D3D_FEATURE_LEVEL_10_1,
D3D_FEATURE_LEVEL_10_0
};
D3D_FEATURE_LEVEL pFeatureLevelsOut;
hres = CreateDXGIFactory(__uuidof(IDXGIFactory2), (void**)(&m_pDXGIFactory) );
if (FAILED(hres))
return MFX_ERR_DEVICE_FAILED;
if (m_nViews == 2)
{
hres = m_pDXGIFactory->QueryInterface(__uuidof(IDXGIDisplayControl), (void **)&m_pDisplayControl);
if (FAILED(hres))
return MFX_ERR_DEVICE_FAILED;
m_bDefaultStereoEnabled = m_pDisplayControl->IsStereoEnabled();
if (!m_bDefaultStereoEnabled)
m_pDisplayControl->SetStereoEnabled(TRUE);
}
hres = m_pDXGIFactory->EnumAdapters(nAdapterNum,&m_pAdapter);
if (FAILED(hres))
return MFX_ERR_DEVICE_FAILED;
hres = D3D11CreateDevice(m_pAdapter ,
D3D_DRIVER_TYPE_UNKNOWN,
NULL,
0,
FeatureLevels,
MSDK_ARRAY_LEN(FeatureLevels),
D3D11_SDK_VERSION,
&m_pD3D11Device,
&pFeatureLevelsOut,
&m_pD3D11Ctx);
if (FAILED(hres))
return MFX_ERR_DEVICE_FAILED;
m_pDXGIDev = m_pD3D11Device;
m_pDX11VideoDevice = m_pD3D11Device;
m_pVideoContext = m_pD3D11Ctx;
MSDK_CHECK_POINTER(m_pDXGIDev.p, MFX_ERR_NULL_PTR);
MSDK_CHECK_POINTER(m_pDX11VideoDevice.p, MFX_ERR_NULL_PTR);
MSDK_CHECK_POINTER(m_pVideoContext.p, MFX_ERR_NULL_PTR);
// turn on multithreading for the Context
CComQIPtr<ID3D10Multithread> p_mt(m_pVideoContext);
if (p_mt)
p_mt->SetMultithreadProtected(true);
else
return MFX_ERR_DEVICE_FAILED;
// create swap chain only for rendering use case (hWindow != 0)
if (hWindow)
{
MSDK_CHECK_POINTER(m_pDXGIFactory.p, MFX_ERR_NULL_PTR);
DXGI_SWAP_CHAIN_DESC1 swapChainDesc = {0};
sts = FillSCD1(swapChainDesc);
MSDK_CHECK_STATUS(sts, "FillSCD1 failed");
hres = m_pDXGIFactory->CreateSwapChainForHwnd(m_pD3D11Device,
(HWND)hWindow,
&swapChainDesc,
NULL,
NULL,
reinterpret_cast<IDXGISwapChain1**>(&m_pSwapChain));
if (FAILED(hres))
return MFX_ERR_DEVICE_FAILED;
}
return sts;
}
mfxStatus CD3D11Device::CreateVideoProcessor(mfxFrameSurface1 * pSrf)
{
HRESULT hres = S_OK;
if (m_VideoProcessorEnum.p || NULL == pSrf)
return MFX_ERR_NONE;
//create video processor
D3D11_VIDEO_PROCESSOR_CONTENT_DESC ContentDesc;
MSDK_ZERO_MEMORY( ContentDesc );
ContentDesc.InputFrameFormat = D3D11_VIDEO_FRAME_FORMAT_PROGRESSIVE;
ContentDesc.InputFrameRate.Numerator = 30000;
ContentDesc.InputFrameRate.Denominator = 1000;
ContentDesc.InputWidth = pSrf->Info.CropW;
ContentDesc.InputHeight = pSrf->Info.CropH;
ContentDesc.OutputWidth = pSrf->Info.CropW;
ContentDesc.OutputHeight = pSrf->Info.CropH;
ContentDesc.OutputFrameRate.Numerator = 30000;
ContentDesc.OutputFrameRate.Denominator = 1000;
ContentDesc.Usage = D3D11_VIDEO_USAGE_PLAYBACK_NORMAL;
hres = m_pDX11VideoDevice->CreateVideoProcessorEnumerator( &ContentDesc, &m_VideoProcessorEnum );
if (FAILED(hres))
return MFX_ERR_DEVICE_FAILED;
hres = m_pDX11VideoDevice->CreateVideoProcessor( m_VideoProcessorEnum, 0, &m_pVideoProcessor );
if (FAILED(hres))
return MFX_ERR_DEVICE_FAILED;
return MFX_ERR_NONE;
}
mfxStatus CD3D11Device::Reset()
{
// Changing video mode back to the original state
if (2 == m_nViews && !m_bDefaultStereoEnabled)
m_pDisplayControl->SetStereoEnabled(FALSE);
MSDK_CHECK_POINTER (m_pDXGIFactory.p, MFX_ERR_NULL_PTR);
DXGI_SWAP_CHAIN_DESC1 swapChainDesc = {0};
mfxStatus sts = FillSCD1(swapChainDesc);
MSDK_CHECK_STATUS(sts, "FillSCD1 failed");
HRESULT hres = S_OK;
hres = m_pDXGIFactory->CreateSwapChainForHwnd(m_pD3D11Device,
(HWND)m_HandleWindow,
&swapChainDesc,
NULL,
NULL,
reinterpret_cast<IDXGISwapChain1**>(&m_pSwapChain));
if (FAILED(hres))
{
if (swapChainDesc.Stereo)
{
MSDK_PRINT_RET_MSG(MFX_ERR_DEVICE_FAILED,"Cannot create swap chain required for rendering. Possibly stereo mode is not supported.");
}
else
{
MSDK_PRINT_RET_MSG(MFX_ERR_DEVICE_FAILED, "Cannot create swap chain required for rendering.");
}
return MFX_ERR_DEVICE_FAILED;
}
return MFX_ERR_NONE;
}
mfxStatus CD3D11Device::GetHandle(mfxHandleType type, mfxHDL *pHdl)
{
if (MFX_HANDLE_D3D11_DEVICE == type)
{
*pHdl = m_pD3D11Device.p;
return MFX_ERR_NONE;
}
return MFX_ERR_UNSUPPORTED;
}
mfxStatus CD3D11Device::SetHandle(mfxHandleType type, mfxHDL hdl)
{
if (MFX_HANDLE_DEVICEWINDOW == type && hdl != NULL) //for render window handle
{
m_HandleWindow = (HWND)hdl;
return MFX_ERR_NONE;
}
return MFX_ERR_UNSUPPORTED;
}
mfxStatus CD3D11Device::RenderFrame(mfxFrameSurface1 * pSrf, mfxFrameAllocator * pAlloc)
{
HRESULT hres = S_OK;
mfxStatus sts;
sts = CreateVideoProcessor(pSrf);
MSDK_CHECK_STATUS(sts, "CreateVideoProcessor failed");
hres = m_pSwapChain->GetBuffer(0, __uuidof( ID3D11Texture2D ), (void**)&m_pDXGIBackBuffer.p);
if (FAILED(hres))
return MFX_ERR_DEVICE_FAILED;
D3D11_VIDEO_PROCESSOR_OUTPUT_VIEW_DESC OutputViewDesc;
if (2 == m_nViews)
{
m_pVideoContext->VideoProcessorSetStreamStereoFormat(m_pVideoProcessor, 0, TRUE,D3D11_VIDEO_PROCESSOR_STEREO_FORMAT_SEPARATE,
TRUE, TRUE, D3D11_VIDEO_PROCESSOR_STEREO_FLIP_NONE, NULL);
m_pVideoContext->VideoProcessorSetOutputStereoMode(m_pVideoProcessor,TRUE);
OutputViewDesc.ViewDimension = D3D11_VPOV_DIMENSION_TEXTURE2DARRAY;
OutputViewDesc.Texture2DArray.ArraySize = 2;
OutputViewDesc.Texture2DArray.MipSlice = 0;
OutputViewDesc.Texture2DArray.FirstArraySlice = 0;
}
else
{
OutputViewDesc.ViewDimension = D3D11_VPOV_DIMENSION_TEXTURE2D;
OutputViewDesc.Texture2D.MipSlice = 0;
}
if (1 == m_nViews || 0 == pSrf->Info.FrameId.ViewId)
{
hres = m_pDX11VideoDevice->CreateVideoProcessorOutputView(
m_pDXGIBackBuffer,
m_VideoProcessorEnum,
&OutputViewDesc,
&m_pOutputView.p );
if (FAILED(hres))
return MFX_ERR_DEVICE_FAILED;
}
D3D11_VIDEO_PROCESSOR_INPUT_VIEW_DESC InputViewDesc;
InputViewDesc.FourCC = 0;
InputViewDesc.ViewDimension = D3D11_VPIV_DIMENSION_TEXTURE2D;
InputViewDesc.Texture2D.MipSlice = 0;
InputViewDesc.Texture2D.ArraySlice = 0;
mfxHDLPair pair = {NULL};
sts = pAlloc->GetHDL(pAlloc->pthis, pSrf->Data.MemId, (mfxHDL*)&pair);
MSDK_CHECK_STATUS(sts, "pAlloc->GetHDL failed");
ID3D11Texture2D *pRTTexture2D = reinterpret_cast<ID3D11Texture2D*>(pair.first);
D3D11_TEXTURE2D_DESC RTTexture2DDesc;
if(!m_pTempTexture && m_nViews == 2)
{
pRTTexture2D->GetDesc(&RTTexture2DDesc);
hres = m_pD3D11Device->CreateTexture2D(&RTTexture2DDesc,NULL,&m_pTempTexture.p);
if (FAILED(hres))
return MFX_ERR_DEVICE_FAILED;
}
// Creating input views for left and righ eyes
if (1 == m_nViews)
{
hres = m_pDX11VideoDevice->CreateVideoProcessorInputView(
pRTTexture2D,
m_VideoProcessorEnum,
&InputViewDesc,
&m_pInputViewLeft.p );
}
else if (2 == m_nViews && 0 == pSrf->Info.FrameId.ViewId)
{
m_pD3D11Ctx->CopyResource(m_pTempTexture,pRTTexture2D);
hres = m_pDX11VideoDevice->CreateVideoProcessorInputView(
m_pTempTexture,
m_VideoProcessorEnum,
&InputViewDesc,
&m_pInputViewLeft.p );
}
else
{
hres = m_pDX11VideoDevice->CreateVideoProcessorInputView(
pRTTexture2D,
m_VideoProcessorEnum,
&InputViewDesc,
&m_pInputViewRight.p );
}
if (FAILED(hres))
return MFX_ERR_DEVICE_FAILED;
// NV12 surface to RGB backbuffer
RECT rect = {0};
rect.right = pSrf->Info.CropW;
rect.bottom = pSrf->Info.CropH;
D3D11_VIDEO_PROCESSOR_STREAM StreamData;
if (1 == m_nViews || pSrf->Info.FrameId.ViewId == 1)
{
StreamData.Enable = TRUE;
StreamData.OutputIndex = 0;
StreamData.InputFrameOrField = 0;
StreamData.PastFrames = 0;
StreamData.FutureFrames = 0;
StreamData.ppPastSurfaces = NULL;
StreamData.ppFutureSurfaces = NULL;
StreamData.pInputSurface = m_pInputViewLeft;
StreamData.ppPastSurfacesRight = NULL;
StreamData.ppFutureSurfacesRight = NULL;
StreamData.pInputSurfaceRight = m_nViews == 2 ? m_pInputViewRight : NULL;
m_pVideoContext->VideoProcessorSetStreamSourceRect(m_pVideoProcessor, 0, true, &rect);
m_pVideoContext->VideoProcessorSetStreamFrameFormat( m_pVideoProcessor, 0, D3D11_VIDEO_FRAME_FORMAT_PROGRESSIVE);
hres = m_pVideoContext->VideoProcessorBlt( m_pVideoProcessor, m_pOutputView, 0, 1, &StreamData );
if (FAILED(hres))
return MFX_ERR_DEVICE_FAILED;
}
if (1 == m_nViews || 1 == pSrf->Info.FrameId.ViewId)
{
DXGI_PRESENT_PARAMETERS parameters = {0};
hres = m_pSwapChain->Present1(0, 0, &parameters);
if (FAILED(hres))
return MFX_ERR_DEVICE_FAILED;
}
return MFX_ERR_NONE;
}
void CD3D11Device::Close()
{
// Changing video mode back to the original state
if (2 == m_nViews && !m_bDefaultStereoEnabled)
m_pDisplayControl->SetStereoEnabled(FALSE);
m_HandleWindow = NULL;
}
#endif // #if MFX_D3D11_SUPPORT
#endif // #if defined(_WIN32) || defined(_WIN64)

View File

@@ -0,0 +1,475 @@
/******************************************************************************\
Copyright (c) 2005-2019, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
This sample was distributed or derived from the Intel's Media Samples package.
The original version of this sample may be obtained from https://software.intel.com/en-us/intel-media-server-studio
or https://software.intel.com/en-us/media-client-solutions-support.
\**********************************************************************************/
#include "mfx_samples_config.h"
#include "sample_defs.h"
#if defined(_WIN32) || defined(_WIN64)
#include <objbase.h>
#include <initguid.h>
#include <assert.h>
#include <d3d9.h>
#include "d3d_allocator.h"
#define D3DFMT_NV12 (D3DFORMAT)MAKEFOURCC('N','V','1','2')
#define D3DFMT_YV12 (D3DFORMAT)MAKEFOURCC('Y','V','1','2')
#define D3DFMT_NV16 (D3DFORMAT)MAKEFOURCC('N','V','1','6')
#define D3DFMT_P010 (D3DFORMAT)MAKEFOURCC('P','0','1','0')
#define D3DFMT_P210 (D3DFORMAT)MAKEFOURCC('P','2','1','0')
#define D3DFMT_IMC3 (D3DFORMAT)MAKEFOURCC('I','M','C','3')
#define D3DFMT_AYUV (D3DFORMAT)MAKEFOURCC('A','Y','U','V')
#if (MFX_VERSION >= 1027)
#define D3DFMT_Y210 (D3DFORMAT)MAKEFOURCC('Y','2','1','0')
#define D3DFMT_Y410 (D3DFORMAT)MAKEFOURCC('Y','4','1','0')
#endif
#if (MFX_VERSION >= 1031)
#define D3DFMT_P016 (D3DFORMAT)MAKEFOURCC('P','0','1','6')
#define D3DFMT_Y216 (D3DFORMAT)MAKEFOURCC('Y','2','1','6')
#define D3DFMT_Y416 (D3DFORMAT)MAKEFOURCC('Y','4','1','6')
#endif
#define MFX_FOURCC_IMC3 (MFX_MAKEFOURCC('I','M','C','3')) // This line should be moved into mfxstructures.h in new API version
D3DFORMAT ConvertMfxFourccToD3dFormat(mfxU32 fourcc)
{
switch (fourcc)
{
case MFX_FOURCC_NV12:
return D3DFMT_NV12;
case MFX_FOURCC_YV12:
return D3DFMT_YV12;
case MFX_FOURCC_NV16:
return D3DFMT_NV16;
case MFX_FOURCC_YUY2:
return D3DFMT_YUY2;
case MFX_FOURCC_RGB3:
return D3DFMT_R8G8B8;
case MFX_FOURCC_RGB4:
return D3DFMT_A8R8G8B8;
case MFX_FOURCC_P8:
return D3DFMT_P8;
case MFX_FOURCC_P010:
return D3DFMT_P010;
case MFX_FOURCC_AYUV:
return D3DFMT_AYUV;
case MFX_FOURCC_P210:
return D3DFMT_P210;
#if (MFX_VERSION >= 1027)
case MFX_FOURCC_Y210:
return D3DFMT_Y210;
case MFX_FOURCC_Y410:
return D3DFMT_Y410;
#endif
#if (MFX_VERSION >= 1031)
case MFX_FOURCC_P016:
return D3DFMT_P016;
case MFX_FOURCC_Y216:
return D3DFMT_Y216;
case MFX_FOURCC_Y416:
return D3DFMT_Y416;
#endif
case MFX_FOURCC_A2RGB10:
return D3DFMT_A2R10G10B10;
case MFX_FOURCC_ABGR16:
case MFX_FOURCC_ARGB16:
return D3DFMT_A16B16G16R16;
case MFX_FOURCC_IMC3:
return D3DFMT_IMC3;
default:
return D3DFMT_UNKNOWN;
}
}
D3DFrameAllocator::D3DFrameAllocator()
: m_decoderService(0), m_processorService(0), m_hDecoder(0), m_hProcessor(0), m_manager(0), m_surfaceUsage(0)
{
}
D3DFrameAllocator::~D3DFrameAllocator()
{
Close();
for (unsigned i = 0; i < m_midsAllocated.size(); i++)
MSDK_SAFE_FREE(m_midsAllocated[i]);
}
mfxStatus D3DFrameAllocator::Init(mfxAllocatorParams *pParams)
{
D3DAllocatorParams *pd3dParams = 0;
pd3dParams = dynamic_cast<D3DAllocatorParams *>(pParams);
if (!pd3dParams)
return MFX_ERR_NOT_INITIALIZED;
m_manager = pd3dParams->pManager;
m_surfaceUsage = pd3dParams->surfaceUsage;
return MFX_ERR_NONE;
}
mfxStatus D3DFrameAllocator::Close()
{
if (m_manager && m_hDecoder)
{
m_manager->CloseDeviceHandle(m_hDecoder);
m_manager = 0;
m_hDecoder = 0;
}
if (m_manager && m_hProcessor)
{
m_manager->CloseDeviceHandle(m_hProcessor);
m_manager = 0;
m_hProcessor = 0;
}
return BaseFrameAllocator::Close();
}
mfxStatus D3DFrameAllocator::LockFrame(mfxMemId mid, mfxFrameData *ptr)
{
if (!ptr || !mid)
return MFX_ERR_NULL_PTR;
mfxHDLPair *dxmid = (mfxHDLPair*)mid;
IDirect3DSurface9 *pSurface = static_cast<IDirect3DSurface9*>(dxmid->first);
if (pSurface == 0)
return MFX_ERR_INVALID_HANDLE;
D3DSURFACE_DESC desc;
HRESULT hr = pSurface->GetDesc(&desc);
if (FAILED(hr))
return MFX_ERR_LOCK_MEMORY;
if (desc.Format != D3DFMT_NV12 &&
desc.Format != D3DFMT_YV12 &&
desc.Format != D3DFMT_YUY2 &&
desc.Format != D3DFMT_R8G8B8 &&
desc.Format != D3DFMT_A8R8G8B8 &&
desc.Format != D3DFMT_P8 &&
desc.Format != D3DFMT_P010 &&
desc.Format != D3DFMT_A2R10G10B10 &&
desc.Format != D3DFMT_A16B16G16R16 &&
desc.Format != D3DFMT_IMC3 &&
desc.Format != D3DFMT_AYUV
#if (MFX_VERSION >= 1027)
&& desc.Format != D3DFMT_Y210
#endif
#if (MFX_VERSION >= 1031)
&& desc.Format != D3DFMT_P016
&& desc.Format != D3DFMT_Y216
&& desc.Format != D3DFMT_Y410
&& desc.Format != D3DFMT_Y416
#endif
)
return MFX_ERR_LOCK_MEMORY;
D3DLOCKED_RECT locked;
hr = pSurface->LockRect(&locked, 0, D3DLOCK_NOSYSLOCK);
if (FAILED(hr))
return MFX_ERR_LOCK_MEMORY;
switch ((DWORD)desc.Format)
{
case D3DFMT_NV12:
case D3DFMT_P010:
#if (MFX_VERSION >= 1031)
case D3DFMT_P016:
#endif
ptr->Pitch = (mfxU16)locked.Pitch;
ptr->Y = (mfxU8 *)locked.pBits;
ptr->U = (mfxU8 *)locked.pBits + desc.Height * locked.Pitch;
ptr->V = (desc.Format == D3DFMT_P010) ? ptr->U + 2 : ptr->U + 1;
break;
case D3DFMT_YV12:
ptr->Pitch = (mfxU16)locked.Pitch;
ptr->Y = (mfxU8 *)locked.pBits;
ptr->V = ptr->Y + desc.Height * locked.Pitch;
ptr->U = ptr->V + (desc.Height * locked.Pitch) / 4;
break;
case D3DFMT_YUY2:
ptr->Pitch = (mfxU16)locked.Pitch;
ptr->Y = (mfxU8 *)locked.pBits;
ptr->U = ptr->Y + 1;
ptr->V = ptr->Y + 3;
break;
case D3DFMT_R8G8B8:
ptr->Pitch = (mfxU16)locked.Pitch;
ptr->B = (mfxU8 *)locked.pBits;
ptr->G = ptr->B + 1;
ptr->R = ptr->B + 2;
break;
case D3DFMT_A8R8G8B8:
case D3DFMT_A2R10G10B10:
ptr->Pitch = (mfxU16)locked.Pitch;
ptr->B = (mfxU8 *)locked.pBits;
ptr->G = ptr->B + 1;
ptr->R = ptr->B + 2;
ptr->A = ptr->B + 3;
break;
case D3DFMT_P8:
ptr->Pitch = (mfxU16)locked.Pitch;
ptr->Y = (mfxU8 *)locked.pBits;
ptr->U = 0;
ptr->V = 0;
break;
case D3DFMT_A16B16G16R16:
ptr->V16 = (mfxU16*)locked.pBits;
ptr->U16 = ptr->V16 + 1;
ptr->Y16 = ptr->V16 + 2;
ptr->A = (mfxU8*)(ptr->V16 + 3);
ptr->PitchHigh = (mfxU16)((mfxU32)locked.Pitch / (1 << 16));
ptr->PitchLow = (mfxU16)((mfxU32)locked.Pitch % (1 << 16));
break;
case D3DFMT_IMC3:
ptr->Pitch = (mfxU16)locked.Pitch;
ptr->Y = (mfxU8 *)locked.pBits;
ptr->V = ptr->Y + desc.Height * locked.Pitch;
ptr->U = ptr->Y + desc.Height * locked.Pitch *2;
break;
case D3DFMT_AYUV:
ptr->Pitch = (mfxU16)locked.Pitch;
ptr->V = (mfxU8 *)locked.pBits;
ptr->U = ptr->V + 1;
ptr->Y = ptr->V + 2;
ptr->A = ptr->V + 3;
break;
#if (MFX_VERSION >= 1031)
case D3DFMT_Y416:
ptr->Pitch = (mfxU16)locked.Pitch;
ptr->U16 = (mfxU16*)locked.pBits;
ptr->Y16 = ptr->U16 + 1;
ptr->V16 = ptr->Y16 + 1;
ptr->A = (mfxU8 *)(ptr->V16 + 1);
break;
case D3DFMT_Y216:
#endif
#if (MFX_VERSION >= 1027)
case D3DFMT_Y210:
ptr->Pitch = (mfxU16)locked.Pitch;
ptr->Y16 = (mfxU16 *)locked.pBits;
ptr->U16 = ptr->Y16 + 1;
ptr->V16 = ptr->Y16 + 3;
break;
case D3DFMT_Y410:
ptr->Pitch = (mfxU16)locked.Pitch;
ptr->Y410 = (mfxY410 *)locked.pBits;
ptr->Y = 0;
ptr->V = 0;
ptr->A = 0;
break;
#endif
}
return MFX_ERR_NONE;
}
mfxStatus D3DFrameAllocator::UnlockFrame(mfxMemId mid, mfxFrameData *ptr)
{
if (!mid)
return MFX_ERR_NULL_PTR;
mfxHDLPair *dxmid = (mfxHDLPair*)mid;
IDirect3DSurface9 *pSurface = static_cast<IDirect3DSurface9*>(dxmid->first);
if (pSurface == 0)
return MFX_ERR_INVALID_HANDLE;
pSurface->UnlockRect();
if (NULL != ptr)
{
ptr->Pitch = 0;
ptr->Y = 0;
ptr->U = 0;
ptr->V = 0;
}
return MFX_ERR_NONE;
}
mfxStatus D3DFrameAllocator::GetFrameHDL(mfxMemId mid, mfxHDL * handle)
{
if (!mid || !handle)
return MFX_ERR_NULL_PTR;
mfxHDLPair *dxMid = (mfxHDLPair*)mid;
*handle = dxMid->first;
return MFX_ERR_NONE;
}
mfxStatus D3DFrameAllocator::CheckRequestType(mfxFrameAllocRequest *request)
{
mfxStatus sts = BaseFrameAllocator::CheckRequestType(request);
if (MFX_ERR_NONE != sts)
return sts;
if ((request->Type & (MFX_MEMTYPE_VIDEO_MEMORY_DECODER_TARGET | MFX_MEMTYPE_VIDEO_MEMORY_PROCESSOR_TARGET)) != 0)
return MFX_ERR_NONE;
else
return MFX_ERR_UNSUPPORTED;
}
mfxStatus D3DFrameAllocator::ReleaseResponse(mfxFrameAllocResponse *response)
{
if (!response)
return MFX_ERR_NULL_PTR;
mfxStatus sts = MFX_ERR_NONE;
if (response->mids) {
for (mfxU32 i = 0; i < response->NumFrameActual; i++) {
if (response->mids[i]) {
mfxHDLPair *dxMids = (mfxHDLPair*)response->mids[i];
if (dxMids->first)
{
static_cast<IDirect3DSurface9*>(dxMids->first)->Release();
}
MSDK_SAFE_FREE(dxMids);
}
}
}
return sts;
}
mfxStatus D3DFrameAllocator::ReallocImpl(mfxMemId /*mid*/, const mfxFrameInfo *info, mfxU16 /*memType*/, mfxMemId *midOut)
{
if (!info || !midOut)
return MFX_ERR_NULL_PTR;
//TODO: Need add implementation in the future.
return MFX_ERR_UNSUPPORTED;
}
mfxStatus D3DFrameAllocator::AllocImpl(mfxFrameAllocRequest *request, mfxFrameAllocResponse *response)
{
HRESULT hr;
MSDK_CHECK_POINTER(request, MFX_ERR_NULL_PTR);
if (request->NumFrameSuggested == 0)
return MFX_ERR_UNKNOWN;
D3DFORMAT format = ConvertMfxFourccToD3dFormat(request->Info.FourCC);
if (format == D3DFMT_UNKNOWN)
{
msdk_printf(MSDK_STRING("D3D Allocator: invalid fourcc is provided (%#X), exitting\n"),request->Info.FourCC);
return MFX_ERR_UNSUPPORTED;
}
DWORD target;
if (MFX_MEMTYPE_DXVA2_DECODER_TARGET & request->Type)
{
target = DXVA2_VideoDecoderRenderTarget;
}
else if (MFX_MEMTYPE_DXVA2_PROCESSOR_TARGET & request->Type)
{
target = DXVA2_VideoProcessorRenderTarget;
}
else
return MFX_ERR_UNSUPPORTED;
IDirectXVideoAccelerationService* videoService = NULL;
if (target == DXVA2_VideoProcessorRenderTarget) {
if (!m_hProcessor) {
hr = m_manager->OpenDeviceHandle(&m_hProcessor);
if (FAILED(hr))
return MFX_ERR_MEMORY_ALLOC;
hr = m_manager->GetVideoService(m_hProcessor, IID_IDirectXVideoProcessorService, (void**)&m_processorService);
if (FAILED(hr))
return MFX_ERR_MEMORY_ALLOC;
}
videoService = m_processorService;
}
else {
if (!m_hDecoder)
{
hr = m_manager->OpenDeviceHandle(&m_hDecoder);
if (FAILED(hr))
return MFX_ERR_MEMORY_ALLOC;
hr = m_manager->GetVideoService(m_hDecoder, IID_IDirectXVideoDecoderService, (void**)&m_decoderService);
if (FAILED(hr))
return MFX_ERR_MEMORY_ALLOC;
}
videoService = m_decoderService;
}
mfxHDLPair **dxMidPtrs = (mfxHDLPair**)calloc(request->NumFrameSuggested, sizeof(mfxHDLPair*));
if (!dxMidPtrs)
return MFX_ERR_MEMORY_ALLOC;
for (int i = 0; i < request->NumFrameSuggested; i++)
{
dxMidPtrs[i] = (mfxHDLPair*)calloc(1, sizeof(mfxHDLPair));
if (!dxMidPtrs[i])
{
DeallocateMids(dxMidPtrs, i);
return MFX_ERR_MEMORY_ALLOC;
}
}
response->mids = (mfxMemId*)dxMidPtrs;
response->NumFrameActual = request->NumFrameSuggested;
if (request->Type & MFX_MEMTYPE_EXTERNAL_FRAME) {
for (int i = 0; i < request->NumFrameSuggested; i++) {
hr = videoService->CreateSurface(request->Info.Width, request->Info.Height, 0, format,
D3DPOOL_DEFAULT, m_surfaceUsage, target, (IDirect3DSurface9**)&dxMidPtrs[i]->first, &dxMidPtrs[i]->second);
if (FAILED(hr)) {
ReleaseResponse(response);
return MFX_ERR_MEMORY_ALLOC;
}
}
} else {
std::unique_ptr<IDirect3DSurface9*[]> dxSrf(new (std::nothrow) IDirect3DSurface9*[request->NumFrameSuggested]);
if (!dxSrf.get())
{
DeallocateMids(dxMidPtrs, request->NumFrameSuggested);
return MFX_ERR_MEMORY_ALLOC;
}
hr = videoService->CreateSurface(request->Info.Width, request->Info.Height, request->NumFrameSuggested - 1, format,
D3DPOOL_DEFAULT, m_surfaceUsage, target, dxSrf.get(), NULL);
if (FAILED(hr))
{
DeallocateMids(dxMidPtrs, request->NumFrameSuggested);
return MFX_ERR_MEMORY_ALLOC;
}
for (int i = 0; i < request->NumFrameSuggested; i++) {
dxMidPtrs[i]->first = dxSrf[i];
}
}
m_midsAllocated.push_back(dxMidPtrs);
return MFX_ERR_NONE;
}
void D3DFrameAllocator::DeallocateMids(mfxHDLPair** pair, int n)
{
for (int i = 0; i < n; i++)
{
MSDK_SAFE_FREE(pair[i]);
}
MSDK_SAFE_FREE(pair);
}
#endif // #if defined(_WIN32) || defined(_WIN64)

View File

@@ -0,0 +1,408 @@
/******************************************************************************\
Copyright (c) 2005-2019, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
This sample was distributed or derived from the Intel's Media Samples package.
The original version of this sample may be obtained from https://software.intel.com/en-us/intel-media-server-studio
or https://software.intel.com/en-us/media-client-solutions-support.
\**********************************************************************************/
#include "mfx_samples_config.h"
#include <algorithm>
#if defined(_WIN32) || defined(_WIN64)
//prefast singnature used in combaseapi.h
#ifndef _PREFAST_
#pragma warning(disable:4068)
#endif
#include "d3d_device.h"
#include "d3d_allocator.h"
#include "sample_defs.h"
#include "atlbase.h"
CD3D9Device::CD3D9Device()
{
m_pD3D9 = NULL;
m_pD3DD9 = NULL;
m_pDeviceManager9 = NULL;
MSDK_ZERO_MEMORY(m_D3DPP);
m_resetToken = 0;
m_nViews = 0;
MSDK_ZERO_MEMORY(m_backBufferDesc);
m_pDXVAVPS = NULL;
m_pDXVAVP_Left = NULL;
m_pDXVAVP_Right = NULL;
MSDK_ZERO_MEMORY(m_targetRect);
MSDK_ZERO_MEMORY(m_VideoDesc);
MSDK_ZERO_MEMORY(m_BltParams);
MSDK_ZERO_MEMORY(m_Sample);
// Initialize DXVA structures
DXVA2_AYUVSample16 color = {
0x8000, // Cr
0x8000, // Cb
0x1000, // Y
0xffff // Alpha
};
DXVA2_ExtendedFormat format = { // DestFormat
DXVA2_SampleProgressiveFrame, // SampleFormat
DXVA2_VideoChromaSubsampling_MPEG2, // VideoChromaSubsampling
DXVA_NominalRange_0_255, // NominalRange
DXVA2_VideoTransferMatrix_BT709, // VideoTransferMatrix
DXVA2_VideoLighting_bright, // VideoLighting
DXVA2_VideoPrimaries_BT709, // VideoPrimaries
DXVA2_VideoTransFunc_709 // VideoTransferFunction
};
// init m_VideoDesc structure
MSDK_MEMCPY_VAR(m_VideoDesc.SampleFormat, &format, sizeof(DXVA2_ExtendedFormat));
m_VideoDesc.SampleWidth = 0;
m_VideoDesc.SampleHeight = 0;
m_VideoDesc.InputSampleFreq.Numerator = 60;
m_VideoDesc.InputSampleFreq.Denominator = 1;
m_VideoDesc.OutputFrameFreq.Numerator = 60;
m_VideoDesc.OutputFrameFreq.Denominator = 1;
// init m_BltParams structure
MSDK_MEMCPY_VAR(m_BltParams.DestFormat, &format, sizeof(DXVA2_ExtendedFormat));
MSDK_MEMCPY_VAR(m_BltParams.BackgroundColor, &color, sizeof(DXVA2_AYUVSample16));
// init m_Sample structure
m_Sample.Start = 0;
m_Sample.End = 1;
m_Sample.SampleFormat = format;
m_Sample.PlanarAlpha.Fraction = 0;
m_Sample.PlanarAlpha.Value = 1;
m_bIsA2rgb10 = FALSE;
}
bool CD3D9Device::CheckOverlaySupport()
{
D3DCAPS9 d3d9caps;
D3DOVERLAYCAPS d3doverlaycaps = {0};
IDirect3D9ExOverlayExtension *d3d9overlay = NULL;
bool overlaySupported = false;
memset(&d3d9caps, 0, sizeof(d3d9caps));
HRESULT hr = m_pD3D9->GetDeviceCaps(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, &d3d9caps);
if (FAILED(hr) || !(d3d9caps.Caps & D3DCAPS_OVERLAY))
{
overlaySupported = false;
}
else
{
hr = m_pD3D9->QueryInterface(IID_PPV_ARGS(&d3d9overlay));
if (FAILED(hr) || (d3d9overlay == NULL))
{
overlaySupported = false;
}
else
{
hr = d3d9overlay->CheckDeviceOverlayType(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
m_D3DPP.BackBufferWidth,
m_D3DPP.BackBufferHeight,
m_D3DPP.BackBufferFormat, NULL,
D3DDISPLAYROTATION_IDENTITY, &d3doverlaycaps);
MSDK_SAFE_RELEASE(d3d9overlay);
if (FAILED(hr))
{
overlaySupported = false;
}
else
{
overlaySupported = true;
}
}
}
return overlaySupported;
}
mfxStatus CD3D9Device::FillD3DPP(mfxHDL hWindow, mfxU16 nViews, D3DPRESENT_PARAMETERS &D3DPP)
{
mfxStatus sts = MFX_ERR_NONE;
D3DPP.Windowed = true;
D3DPP.hDeviceWindow = (HWND)hWindow;
D3DPP.Flags = D3DPRESENTFLAG_VIDEO;
D3DPP.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT;
D3DPP.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE; // note that this setting leads to an implicit timeBeginPeriod call
D3DPP.BackBufferCount = 1;
D3DPP.BackBufferFormat = (m_bIsA2rgb10) ? D3DFMT_A2R10G10B10 : D3DFMT_X8R8G8B8;
if (hWindow)
{
RECT r;
GetClientRect((HWND)hWindow, &r);
int x = GetSystemMetrics(SM_CXSCREEN);
int y = GetSystemMetrics(SM_CYSCREEN);
D3DPP.BackBufferWidth = std::min<LONG>(r.right - r.left, x);
D3DPP.BackBufferHeight = std::min<LONG>(r.bottom - r.top, y);
}
else
{
D3DPP.BackBufferWidth = GetSystemMetrics(SM_CYSCREEN);
D3DPP.BackBufferHeight = GetSystemMetrics(SM_CYSCREEN);
}
//
// Mark the back buffer lockable if software DXVA2 could be used.
// This is because software DXVA2 device requires a lockable render target
// for the optimal performance.
//
{
D3DPP.Flags |= D3DPRESENTFLAG_LOCKABLE_BACKBUFFER;
}
bool isOverlaySupported = CheckOverlaySupport();
if (2 == nViews && !isOverlaySupported)
return MFX_ERR_UNSUPPORTED;
bool needOverlay = (2 == nViews) ? true : false;
D3DPP.SwapEffect = needOverlay ? D3DSWAPEFFECT_OVERLAY : D3DSWAPEFFECT_DISCARD;
return sts;
}
mfxStatus CD3D9Device::Init(
mfxHDL hWindow,
mfxU16 nViews,
mfxU32 nAdapterNum)
{
mfxStatus sts = MFX_ERR_NONE;
if (2 < nViews)
return MFX_ERR_UNSUPPORTED;
m_nViews = nViews;
HRESULT hr = Direct3DCreate9Ex(D3D_SDK_VERSION, &m_pD3D9);
if (!m_pD3D9 || FAILED(hr))
return MFX_ERR_DEVICE_FAILED;
ZeroMemory(&m_D3DPP, sizeof(m_D3DPP));
sts = FillD3DPP(hWindow, nViews, m_D3DPP);
MSDK_CHECK_STATUS(sts, "FillD3DPP failed");
hr = m_pD3D9->CreateDeviceEx(
nAdapterNum,
D3DDEVTYPE_HAL,
(HWND)hWindow,
D3DCREATE_SOFTWARE_VERTEXPROCESSING | D3DCREATE_MULTITHREADED | D3DCREATE_FPU_PRESERVE,
&m_D3DPP,
NULL,
&m_pD3DD9);
if (FAILED(hr))
return MFX_ERR_NULL_PTR;
if(hWindow)
{
hr = m_pD3DD9->ResetEx(&m_D3DPP, NULL);
if (FAILED(hr))
return MFX_ERR_UNDEFINED_BEHAVIOR;
hr = m_pD3DD9->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0);
if (FAILED(hr))
return MFX_ERR_UNDEFINED_BEHAVIOR;
}
UINT resetToken = 0;
hr = DXVA2CreateDirect3DDeviceManager9(&resetToken, &m_pDeviceManager9);
if (FAILED(hr))
return MFX_ERR_NULL_PTR;
hr = m_pDeviceManager9->ResetDevice(m_pD3DD9, resetToken);
if (FAILED(hr))
return MFX_ERR_UNDEFINED_BEHAVIOR;
m_resetToken = resetToken;
return sts;
}
mfxStatus CD3D9Device::Reset()
{
HRESULT hr = NO_ERROR;
MSDK_CHECK_POINTER(m_pD3DD9, MFX_ERR_NULL_PTR);
if (m_D3DPP.hDeviceWindow)
{
RECT r;
hr = GetClientRect((HWND)m_D3DPP.hDeviceWindow, &r);
if (FAILED(hr))
return MFX_ERR_UNDEFINED_BEHAVIOR;
int x = GetSystemMetrics(SM_CXSCREEN);
int y = GetSystemMetrics(SM_CYSCREEN);
m_D3DPP.BackBufferWidth = std::min<LONG>(r.right - r.left, x);
m_D3DPP.BackBufferHeight = std::min<LONG>(r.bottom - r.top, y);
// Reset will change the parameters, so use a copy instead.
D3DPRESENT_PARAMETERS d3dpp = m_D3DPP;
hr = m_pD3DD9->ResetEx(&d3dpp, NULL);
if (FAILED(hr))
return MFX_ERR_UNDEFINED_BEHAVIOR;
}
else
{
m_D3DPP.BackBufferWidth = GetSystemMetrics(SM_CXSCREEN);
m_D3DPP.BackBufferHeight = GetSystemMetrics(SM_CYSCREEN);
}
hr = m_pDeviceManager9->ResetDevice(m_pD3DD9, m_resetToken);
if (FAILED(hr))
return MFX_ERR_UNDEFINED_BEHAVIOR;
return MFX_ERR_NONE;
}
void CD3D9Device::Close()
{
MSDK_SAFE_RELEASE(m_pDXVAVP_Left);
MSDK_SAFE_RELEASE(m_pDXVAVP_Right);
MSDK_SAFE_RELEASE(m_pDXVAVPS);
MSDK_SAFE_RELEASE(m_pDeviceManager9);
MSDK_SAFE_RELEASE(m_pD3DD9);
MSDK_SAFE_RELEASE(m_pD3D9);
}
CD3D9Device::~CD3D9Device()
{
Close();
}
mfxStatus CD3D9Device::GetHandle(mfxHandleType type, mfxHDL *pHdl)
{
if (MFX_HANDLE_DIRECT3D_DEVICE_MANAGER9 == type && pHdl != NULL)
{
*pHdl = m_pDeviceManager9;
return MFX_ERR_NONE;
}
return MFX_ERR_UNSUPPORTED;
}
mfxStatus CD3D9Device::SetHandle(mfxHandleType type, mfxHDL hdl)
{
if (MFX_HANDLE_DEVICEWINDOW == type && hdl != NULL) //for render window handle
{
m_D3DPP.hDeviceWindow = (HWND)hdl;
return MFX_ERR_NONE;
}
return MFX_ERR_UNSUPPORTED;
}
mfxStatus CD3D9Device::RenderFrame(mfxFrameSurface1 * pSurface, mfxFrameAllocator * pmfxAlloc)
{
HRESULT hr = S_OK;
// Rendering of MVC is not supported
if (2 == m_nViews)
return MFX_ERR_UNDEFINED_BEHAVIOR;
MSDK_CHECK_POINTER(pSurface, MFX_ERR_NULL_PTR);
MSDK_CHECK_POINTER(m_pDeviceManager9, MFX_ERR_NOT_INITIALIZED);
MSDK_CHECK_POINTER(pmfxAlloc, MFX_ERR_NULL_PTR);
hr = m_pD3DD9->TestCooperativeLevel();
switch (hr)
{
case D3D_OK :
break;
case D3DERR_DEVICELOST :
{
return MFX_ERR_DEVICE_LOST;
}
case D3DERR_DEVICENOTRESET :
{
return MFX_ERR_UNKNOWN;
}
default :
{
return MFX_ERR_UNKNOWN;
}
}
CComPtr<IDirect3DSurface9> pBackBuffer;
hr = m_pD3DD9->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, &pBackBuffer);
mfxHDLPair* dxMemId = (mfxHDLPair*)pSurface->Data.MemId;
hr = m_pD3DD9->StretchRect((IDirect3DSurface9*)dxMemId->first, NULL, pBackBuffer, NULL, D3DTEXF_LINEAR);
if (FAILED(hr))
{
return MFX_ERR_UNKNOWN;
}
if (SUCCEEDED(hr))
{
hr = m_pD3DD9->Present(NULL, NULL, NULL, NULL);
}
return SUCCEEDED(hr) ? MFX_ERR_NONE : MFX_ERR_DEVICE_FAILED;
}
mfxStatus CD3D9Device::CreateVideoProcessors()
{
if (2 == m_nViews)
return MFX_ERR_UNDEFINED_BEHAVIOR;
MSDK_SAFE_RELEASE(m_pDXVAVP_Left);
MSDK_SAFE_RELEASE(m_pDXVAVP_Right);
HRESULT hr ;
ZeroMemory(&m_backBufferDesc, sizeof(m_backBufferDesc));
IDirect3DSurface9 *backBufferTmp = NULL;
hr = m_pD3DD9->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, &backBufferTmp);
if (NULL != backBufferTmp)
backBufferTmp->GetDesc(&m_backBufferDesc);
MSDK_SAFE_RELEASE(backBufferTmp);
if (SUCCEEDED(hr))
{
// Create DXVA2 Video Processor Service.
hr = DXVA2CreateVideoService(m_pD3DD9,
IID_IDirectXVideoProcessorService,
(void**)&m_pDXVAVPS);
}
if (SUCCEEDED(hr))
{
hr = m_pDXVAVPS->CreateVideoProcessor(DXVA2_VideoProcProgressiveDevice,
&m_VideoDesc,
m_D3DPP.BackBufferFormat,
1,
&m_pDXVAVP_Right);
}
return SUCCEEDED(hr) ? MFX_ERR_NONE : MFX_ERR_DEVICE_FAILED;
}
#endif // #if defined(WIN32) || defined(WIN64)

View File

@@ -0,0 +1,362 @@
/******************************************************************************\
Copyright (c) 2005-2019, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
This sample was distributed or derived from the Intel's Media Samples package.
The original version of this sample may be obtained from https://software.intel.com/en-us/intel-media-server-studio
or https://software.intel.com/en-us/media-client-solutions-support.
\**********************************************************************************/
#include "mfx_samples_config.h"
#if defined(_WIN32) || defined(_WIN64)
#include <windowsx.h>
#include <dwmapi.h>
#include <mmsystem.h>
#include "sample_defs.h"
#include "decode_render.h"
#include "winUser.h"
#pragma warning(disable : 4100)
bool CDecodeD3DRender::m_bIsMonitorFound = false;
LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
#ifdef _WIN64
CDecodeD3DRender* pRender = (CDecodeD3DRender*)GetWindowLongPtr(hWnd, GWLP_USERDATA);
#else
CDecodeD3DRender* pRender = (CDecodeD3DRender*)LongToPtr(GetWindowLongPtr(hWnd, GWL_USERDATA));
#endif
if (pRender)
{
switch(message)
{
HANDLE_MSG(hWnd, WM_DESTROY, pRender->OnDestroy);
HANDLE_MSG(hWnd, WM_KEYUP, pRender->OnKey);
}
}
return DefWindowProc(hWnd, message, wParam, lParam);
}
CDecodeD3DRender::CDecodeD3DRender()
{
m_bDwmEnabled = false;
m_nMonitorCurrent = 0;
m_hwdev = NULL;
MSDK_ZERO_MEMORY(m_sWindowParams);
m_Hwnd = 0;
MSDK_ZERO_MEMORY(m_rect);
m_style = 0;
MSDK_ZERO_MEMORY(shiftedSurface);
MSDK_ZERO_MEMORY(shiftSurfaceResponse);
pAllocator=NULL;
}
BOOL CALLBACK CDecodeD3DRender::MonitorEnumProc(HMONITOR /*hMonitor*/,
HDC /*hdcMonitor*/,
LPRECT lprcMonitor,
LPARAM dwData)
{
CDecodeD3DRender * pRender = reinterpret_cast<CDecodeD3DRender *>(dwData);
RECT r = {0};
if (NULL == lprcMonitor)
lprcMonitor = &r;
if (pRender->m_nMonitorCurrent++ == pRender->m_sWindowParams.nAdapter)
{
pRender->m_RectWindow = *lprcMonitor;
m_bIsMonitorFound = true;
}
return TRUE;
}
CDecodeD3DRender::~CDecodeD3DRender()
{
Close();
}
void CDecodeD3DRender::Close()
{
if (m_Hwnd)
{
DestroyWindow(m_Hwnd);
m_Hwnd=NULL;
}
if(pAllocator)
{
pAllocator->Free(pAllocator->pthis,&shiftSurfaceResponse);
pAllocator=NULL;
}
}
mfxStatus CDecodeD3DRender::Init(sWindowParams pWParams)
{
mfxStatus sts = MFX_ERR_NONE;
// window part
m_sWindowParams = pWParams;
WNDCLASS window;
MSDK_ZERO_MEMORY(window);
window.lpfnWndProc= (WNDPROC)WindowProc;
window.hInstance= GetModuleHandle(NULL);
window.hCursor= LoadCursor(NULL, IDC_ARROW);
window.lpszClassName= m_sWindowParams.lpClassName;
if (!RegisterClass(&window))
return MFX_ERR_UNKNOWN;
EnumDisplayMonitors(NULL, NULL, &CDecodeD3DRender::MonitorEnumProc, (LPARAM)this);
if(!m_bIsMonitorFound)
return MFX_ERR_NOT_FOUND;
::RECT displayRegion = {CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT};
//right and bottom fields consist of width and height values of displayed reqion
if (0 != m_sWindowParams.nx )
{
displayRegion.right = (m_RectWindow.right - m_RectWindow.left) / m_sWindowParams.nx;
displayRegion.bottom = (m_RectWindow.bottom - m_RectWindow.top) / m_sWindowParams.ny;
displayRegion.left = displayRegion.right * (m_sWindowParams.ncell % m_sWindowParams.nx) + m_RectWindow.left;
displayRegion.top = displayRegion.bottom * (m_sWindowParams.ncell / m_sWindowParams.nx) + m_RectWindow.top;
}
else
{
displayRegion.right = pWParams.nWidth;
displayRegion.bottom = pWParams.nHeight;
displayRegion.left = m_RectWindow.left;
displayRegion.top= m_RectWindow.top;
}
//no title window style if required
DWORD dwStyle = NULL == m_sWindowParams.lpWindowName ? WS_POPUP|WS_BORDER|WS_MAXIMIZE : WS_OVERLAPPEDWINDOW;
m_Hwnd = CreateWindowEx(NULL,
m_sWindowParams.lpClassName,
m_sWindowParams.lpWindowName,
!m_sWindowParams.bFullScreen ? dwStyle : (WS_POPUP),
!m_sWindowParams.bFullScreen ? displayRegion.left : 0,
!m_sWindowParams.bFullScreen ? displayRegion.top : 0,
!m_sWindowParams.bFullScreen ? displayRegion.right : GetSystemMetrics(SM_CXSCREEN),
!m_sWindowParams.bFullScreen ? displayRegion.bottom : GetSystemMetrics(SM_CYSCREEN),
m_sWindowParams.hWndParent,
m_sWindowParams.hMenu,
m_sWindowParams.hInstance,
m_sWindowParams.lpParam);
if (!m_Hwnd)
return MFX_ERR_UNKNOWN;
ShowWindow(m_Hwnd, SW_SHOWDEFAULT);
UpdateWindow(m_Hwnd);
#ifdef _WIN64
SetWindowLongPtr(m_Hwnd, GWLP_USERDATA, (LONG_PTR)this);
#else
SetWindowLong(m_Hwnd, GWL_USERDATA, PtrToLong(this));
#endif
m_hwdev->SetHandle((mfxHandleType)MFX_HANDLE_DEVICEWINDOW, m_Hwnd);
sts = m_hwdev->Reset();
MSDK_CHECK_STATUS(sts, "m_hwdev->Reset failed");
return sts;
}
mfxStatus CDecodeD3DRender::RenderFrame(mfxFrameSurface1 *pSurface, mfxFrameAllocator *pmfxAlloc)
{
RECT rect;
mfxStatus sts = MFX_ERR_NONE;
GetClientRect(m_Hwnd, &rect);
if (IsRectEmpty(&rect))
return MFX_ERR_UNKNOWN;
//--- In case of 10 bit surfaces and SW library we have to copy it and shift its data
if(pSurface->Info.FourCC == MFX_FOURCC_P010 && !pSurface->Info.Shift)
{
sts = AllocateShiftedSurfaceIfNeeded(pSurface,pmfxAlloc);
MSDK_CHECK_STATUS(sts, "AllocateShiftedSurfaceIfNeeded failed");
sts = pAllocator->Lock(pAllocator->pthis,shiftedSurface.Data.MemId,&shiftedSurface.Data);
MSDK_CHECK_STATUS(sts, "pAllocator->Lock of shiftedSurface failed");
sts = pAllocator->Lock(pAllocator->pthis,pSurface->Data.MemId,&pSurface->Data);
MSDK_CHECK_STATUS(sts, "pAllocator->Lock of pSurface failed");
int wordsNum = pSurface->Data.Pitch*pSurface->Info.Height*3/16; // Number of 8-byte words
mfxU64* pBuf = (mfxU64*)pSurface->Data.Y16;
mfxU64* pDestBuf = (mfxU64*)shiftedSurface.Data.Y16;
for(int i=0;i<wordsNum;i++)
{
pDestBuf[i] = (pBuf[i]<<6)&0xFFC0FFC0FFC0FFC0;
}
sts = pAllocator->Unlock(pAllocator->pthis,shiftedSurface.Data.MemId,&shiftedSurface.Data);
MSDK_CHECK_STATUS(sts, "pAllocator->Unlock of shiftedSurface failed");
sts = pAllocator->Unlock(pAllocator->pthis,pSurface->Data.MemId,&pSurface->Data);
MSDK_CHECK_STATUS(sts, "pAllocator->Unlock of pSurface failed");
sts = m_hwdev->RenderFrame(&shiftedSurface, pmfxAlloc);
}
else
{
sts = m_hwdev->RenderFrame(pSurface, pmfxAlloc);
}
MSDK_CHECK_STATUS(sts, "m_hwdev->RenderFrame failed");
return sts;
}
HWND CDecodeD3DRender::GetWindowHandle()
{
if (!m_Hwnd)
{
EnumDisplayMonitors(NULL, NULL, &CDecodeD3DRender::MonitorEnumProc, (LPARAM)this);
POINT point = {m_RectWindow.left, m_RectWindow.top};
m_Hwnd = WindowFromPoint(point);
m_nMonitorCurrent = 0;
m_bIsMonitorFound = false;
}
return m_Hwnd;
}
VOID CDecodeD3DRender::UpdateTitle(double fps)
{
if (m_Hwnd)
{
MSG msg;
MSDK_ZERO_MEMORY(msg);
while (msg.message != WM_QUIT && PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
if (NULL != m_sWindowParams.lpWindowName) {
TCHAR str[20];
_stprintf_s(str, 20, MSDK_STRING("fps=%.2lf"), fps );
SetWindowText(m_Hwnd, str);
}
}
}
VOID CDecodeD3DRender::OnDestroy(HWND /*hwnd*/)
{
PostQuitMessage(0);
}
VOID CDecodeD3DRender::OnKey(HWND hwnd, UINT vk, BOOL fDown, int cRepeat, UINT flags)
{
if (TRUE == fDown)
return;
if ('1' == vk && false == m_sWindowParams.bFullScreen)
ChangeWindowSize(true);
else if (true == m_sWindowParams.bFullScreen)
ChangeWindowSize(false);
}
void CDecodeD3DRender::AdjustWindowRect(RECT *rect)
{
int cxmax = GetSystemMetrics(SM_CXMAXIMIZED);
int cymax = GetSystemMetrics(SM_CYMAXIMIZED);
int cxmin = GetSystemMetrics(SM_CXMINTRACK);
int cymin = GetSystemMetrics(SM_CYMINTRACK);
int leftmax = cxmax - cxmin;
int topmax = cymax - cxmin;
if (rect->left < 0)
rect->left = 0;
if (rect->left > leftmax)
rect->left = leftmax;
if (rect->top < 0)
rect->top = 0;
if (rect->top > topmax)
rect->top = topmax;
if (rect->right < rect->left + cxmin)
rect->right = rect->left + cxmin;
if (rect->right - rect->left > cxmax)
rect->right = rect->left + cxmax;
if (rect->bottom < rect->top + cymin)
rect->bottom = rect->top + cymin;
if (rect->bottom - rect->top > cymax)
rect->bottom = rect->top + cymax;
}
VOID CDecodeD3DRender::ChangeWindowSize(bool bFullScreen)
{
HMONITOR hMonitor = MonitorFromWindow(m_Hwnd, MONITOR_DEFAULTTONEAREST);
MONITORINFOEX mi;
mi.cbSize = sizeof(mi);
GetMonitorInfo(hMonitor, &mi);
WINDOWINFO wndInfo;
wndInfo.cbSize = sizeof(WINDOWINFO);
GetWindowInfo(m_Hwnd, &wndInfo);
if(!m_sWindowParams.bFullScreen)
{
m_rect = wndInfo.rcWindow;
m_style = wndInfo.dwStyle;
}
m_sWindowParams.bFullScreen = bFullScreen;
if(!bFullScreen)
{
AdjustWindowRectEx(&m_rect,0,0,0);
SetWindowLong(m_Hwnd, GWL_STYLE, m_style);
SetWindowPos(m_Hwnd, HWND_NOTOPMOST,
m_rect.left , m_rect.top ,
abs(m_rect.right - m_rect.left), abs(m_rect.bottom - m_rect.top),
SWP_SHOWWINDOW);
}
else
{
SetWindowLong(m_Hwnd, GWL_STYLE, WS_POPUP);
SetWindowPos(m_Hwnd, HWND_NOTOPMOST,mi.rcMonitor.left , mi.rcMonitor.top,
abs(mi.rcMonitor.left - mi.rcMonitor.right), abs(mi.rcMonitor.top - mi.rcMonitor.bottom), SWP_SHOWWINDOW);
}
}
mfxStatus CDecodeD3DRender::AllocateShiftedSurfaceIfNeeded(const mfxFrameSurface1* refSurface,mfxFrameAllocator* allocator)
{
if(!pAllocator)
{
mfxFrameAllocRequest request={};
request.AllocId = 0xF000; // Unique alloc ID
request.NumFrameMin=request.NumFrameSuggested=1;
request.Info = refSurface->Info;
request.Type = MFX_MEMTYPE_EXTERNAL_FRAME | MFX_MEMTYPE_FROM_DECODE | MFX_MEMTYPE_VIDEO_MEMORY_DECODER_TARGET;
pAllocator = allocator;
mfxStatus sts = allocator->Alloc(allocator->pthis, &request, &shiftSurfaceResponse);
MSDK_CHECK_STATUS(sts, "Renderer: Shifted Surface allocation failed");
shiftedSurface.Data.MemId=shiftSurfaceResponse.mids[0];
shiftedSurface.Info = request.Info;
}
return MFX_ERR_NONE;
}
#endif // #if defined(_WIN32) || defined(_WIN64)

View File

@@ -0,0 +1,172 @@
/******************************************************************************\
Copyright (c) 2005-2019, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
This sample was distributed or derived from the Intel's Media Samples package.
The original version of this sample may be obtained from https://software.intel.com/en-us/intel-media-server-studio
or https://software.intel.com/en-us/media-client-solutions-support.
\**********************************************************************************/
#include "mfx_samples_config.h"
#include "general_allocator.h"
#if defined(_WIN32) || defined(_WIN64)
#include "d3d_allocator.h"
#include "d3d11_allocator.h"
#else
#include <stdarg.h>
#include "vaapi_allocator.h"
#endif
#include "sysmem_allocator.h"
#include "sample_defs.h"
// Wrapper on standard allocator for concurrent allocation of
// D3D and system surfaces
GeneralAllocator::GeneralAllocator()
{
};
GeneralAllocator::~GeneralAllocator()
{
};
mfxStatus GeneralAllocator::Init(mfxAllocatorParams *pParams)
{
mfxStatus sts = MFX_ERR_NONE;
#if defined(_WIN32) || defined(_WIN64)
D3DAllocatorParams *d3dAllocParams = dynamic_cast<D3DAllocatorParams*>(pParams);
if (d3dAllocParams)
m_D3DAllocator.reset(new D3DFrameAllocator);
#if MFX_D3D11_SUPPORT
D3D11AllocatorParams *d3d11AllocParams = dynamic_cast<D3D11AllocatorParams*>(pParams);
if (d3d11AllocParams)
m_D3DAllocator.reset(new D3D11FrameAllocator);
#endif
#endif
#ifdef LIBVA_SUPPORT
vaapiAllocatorParams *vaapiAllocParams = dynamic_cast<vaapiAllocatorParams*>(pParams);
if (vaapiAllocParams)
m_D3DAllocator.reset(new vaapiFrameAllocator);
#endif
if (m_D3DAllocator.get())
{
sts = m_D3DAllocator.get()->Init(pParams);
MSDK_CHECK_STATUS(sts, "m_D3DAllocator.get failed");
}
m_SYSAllocator.reset(new SysMemFrameAllocator);
sts = m_SYSAllocator.get()->Init(0);
MSDK_CHECK_STATUS(sts, "m_SYSAllocator.get failed");
return sts;
}
mfxStatus GeneralAllocator::Close()
{
mfxStatus sts = MFX_ERR_NONE;
if (m_D3DAllocator.get())
{
sts = m_D3DAllocator.get()->Close();
MSDK_CHECK_STATUS(sts, "m_D3DAllocator.get failed");
}
sts = m_SYSAllocator.get()->Close();
MSDK_CHECK_STATUS(sts, "m_SYSAllocator.get failed");
return sts;
}
mfxStatus GeneralAllocator::LockFrame(mfxMemId mid, mfxFrameData *ptr)
{
if (isD3DMid(mid) && m_D3DAllocator.get())
return m_D3DAllocator.get()->Lock(m_D3DAllocator.get(), mid, ptr);
else
return m_SYSAllocator.get()->Lock(m_SYSAllocator.get(),mid, ptr);
}
mfxStatus GeneralAllocator::UnlockFrame(mfxMemId mid, mfxFrameData *ptr)
{
if (isD3DMid(mid) && m_D3DAllocator.get())
return m_D3DAllocator.get()->Unlock(m_D3DAllocator.get(), mid, ptr);
else
return m_SYSAllocator.get()->Unlock(m_SYSAllocator.get(),mid, ptr);
}
mfxStatus GeneralAllocator::GetFrameHDL(mfxMemId mid, mfxHDL *handle)
{
if (isD3DMid(mid) && m_D3DAllocator.get())
return m_D3DAllocator.get()->GetHDL(m_D3DAllocator.get(), mid, handle);
else
return m_SYSAllocator.get()->GetHDL(m_SYSAllocator.get(), mid, handle);
}
mfxStatus GeneralAllocator::ReleaseResponse(mfxFrameAllocResponse *response)
{
// try to ReleaseResponse via D3D allocator
if (isD3DMid(response->mids[0]) && m_D3DAllocator.get())
return m_D3DAllocator.get()->Free(m_D3DAllocator.get(),response);
else
return m_SYSAllocator.get()->Free(m_SYSAllocator.get(), response);
}
mfxStatus GeneralAllocator::ReallocImpl(mfxMemId mid, const mfxFrameInfo *info, mfxU16 memType, mfxMemId *midOut)
{
if (!info || !midOut) return MFX_ERR_NULL_PTR;
mfxStatus sts;
if ((memType & MFX_MEMTYPE_VIDEO_MEMORY_DECODER_TARGET || memType & MFX_MEMTYPE_VIDEO_MEMORY_PROCESSOR_TARGET) && m_D3DAllocator.get())
{
sts = m_D3DAllocator.get()->ReallocFrame(mid, info, memType, midOut);
MSDK_CHECK_NOT_EQUAL(MFX_ERR_NONE, sts, sts);
}
else
{
sts = m_SYSAllocator.get()->ReallocFrame(mid, info, memType, midOut);
MSDK_CHECK_NOT_EQUAL(MFX_ERR_NONE, sts, sts);
}
return sts;
}
mfxStatus GeneralAllocator::AllocImpl(mfxFrameAllocRequest *request, mfxFrameAllocResponse *response)
{
mfxStatus sts;
if ((request->Type & MFX_MEMTYPE_VIDEO_MEMORY_DECODER_TARGET || request->Type & MFX_MEMTYPE_VIDEO_MEMORY_PROCESSOR_TARGET) && m_D3DAllocator.get())
{
sts = m_D3DAllocator.get()->Alloc(m_D3DAllocator.get(), request, response);
MSDK_CHECK_NOT_EQUAL(MFX_ERR_NONE, sts, sts);
StoreFrameMids(true, response);
}
else
{
sts = m_SYSAllocator.get()->Alloc(m_SYSAllocator.get(), request, response);
MSDK_CHECK_NOT_EQUAL(MFX_ERR_NONE, sts, sts);
StoreFrameMids(false, response);
}
return sts;
}
void GeneralAllocator::StoreFrameMids(bool isD3DFrames, mfxFrameAllocResponse *response)
{
for (mfxU32 i = 0; i < response->NumFrameActual; i++)
m_Mids.insert(std::pair<mfxHDL, bool>(response->mids[i], isD3DFrames));
}
bool GeneralAllocator::isD3DMid(mfxHDL mid)
{
std::map<mfxHDL, bool>::iterator it;
it = m_Mids.find(mid);
if (it == m_Mids.end())
return false; // sys mem allocator will check validity of mid further
else
return it->second;
}

View File

@@ -0,0 +1,202 @@
/******************************************************************************\
Copyright (c) 2005-2019, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
This sample was distributed or derived from the Intel's Media Samples package.
The original version of this sample may be obtained from https://software.intel.com/en-us/intel-media-server-studio
or https://software.intel.com/en-us/media-client-solutions-support.
\**********************************************************************************/
#include "mfx_samples_config.h"
#include <stdlib.h>
#include <mfx_buffering.h>
CBuffering::CBuffering():
m_SurfacesNumber(0),
m_OutputSurfacesNumber(0),
m_pSurfaces(NULL),
m_pVppSurfaces(NULL),
m_FreeSurfacesPool(m_Mutex),
m_FreeVppSurfacesPool(m_Mutex),
m_UsedSurfacesPool(m_Mutex),
m_UsedVppSurfacesPool(m_Mutex),
m_pFreeOutputSurfaces(NULL),
m_OutputSurfacesPool(m_Mutex),
m_DeliveredSurfacesPool(m_Mutex)
{
}
CBuffering::~CBuffering()
{
}
mfxStatus
CBuffering::AllocBuffers(mfxU32 SurfaceNumber)
{
if (!SurfaceNumber) return MFX_ERR_MEMORY_ALLOC;
if (!m_OutputSurfacesNumber) { // true - if Vpp isn't enabled
m_OutputSurfacesNumber = SurfaceNumber;
}
m_SurfacesNumber = SurfaceNumber;
m_pSurfaces = (msdkFrameSurface*)calloc(m_SurfacesNumber, sizeof(msdkFrameSurface));
if (!m_pSurfaces) return MFX_ERR_MEMORY_ALLOC;
msdkOutputSurface* p = NULL;
msdkOutputSurface* tail = NULL;
m_pFreeOutputSurfaces = (msdkOutputSurface*)calloc(1, sizeof(msdkOutputSurface));
if (!m_pFreeOutputSurfaces) return MFX_ERR_MEMORY_ALLOC;
tail = m_pFreeOutputSurfaces;
for (mfxU32 i = 1; i < m_OutputSurfacesNumber; ++i) {
p = (msdkOutputSurface*)calloc(1, sizeof(msdkOutputSurface));
if (!p) return MFX_ERR_MEMORY_ALLOC;
tail->next = p;
tail = p;
}
ResetBuffers();
return MFX_ERR_NONE;
}
mfxStatus
CBuffering::AllocVppBuffers(mfxU32 VppSurfaceNumber)
{
m_OutputSurfacesNumber = VppSurfaceNumber;
m_pVppSurfaces = (msdkFrameSurface*)calloc(m_OutputSurfacesNumber, sizeof(msdkFrameSurface));
if (!m_pVppSurfaces) return MFX_ERR_MEMORY_ALLOC;
ResetVppBuffers();
return MFX_ERR_NONE;
}
void
CBuffering::AllocOutputBuffer()
{
std::lock_guard<std::mutex> lock(m_Mutex);
m_pFreeOutputSurfaces = (msdkOutputSurface*)calloc(1, sizeof(msdkOutputSurface));
}
static void
FreeList(msdkOutputSurface*& head) {
msdkOutputSurface* next;
while (head) {
next = head->next;
free(head);
head = next;
}
}
void
CBuffering::FreeBuffers()
{
if (m_pSurfaces) {
free(m_pSurfaces);
m_pSurfaces = NULL;
}
if (m_pVppSurfaces) {
free(m_pVppSurfaces);
m_pVppSurfaces = NULL;
}
FreeList(m_pFreeOutputSurfaces);
FreeList(m_OutputSurfacesPool.m_pSurfacesHead);
FreeList(m_DeliveredSurfacesPool.m_pSurfacesHead);
m_UsedSurfacesPool.m_pSurfacesHead = NULL;
m_UsedSurfacesPool.m_pSurfacesTail = NULL;
m_UsedVppSurfacesPool.m_pSurfacesHead = NULL;
m_UsedVppSurfacesPool.m_pSurfacesTail = NULL;
m_OutputSurfacesPool.m_pSurfacesHead = NULL;
m_OutputSurfacesPool.m_pSurfacesTail = NULL;
m_FreeSurfacesPool.m_pSurfaces = NULL;
m_FreeVppSurfacesPool.m_pSurfaces = NULL;
}
void
CBuffering::ResetBuffers()
{
mfxU32 i;
msdkFrameSurface* pFreeSurf = m_FreeSurfacesPool.m_pSurfaces = m_pSurfaces;
for (i = 0; i < m_SurfacesNumber; ++i) {
if (i < (m_SurfacesNumber-1)) {
pFreeSurf[i].next = &(pFreeSurf[i+1]);
pFreeSurf[i+1].prev = &(pFreeSurf[i]);
}
}
}
void
CBuffering::ResetVppBuffers()
{
mfxU32 i;
msdkFrameSurface* pFreeVppSurf = m_FreeVppSurfacesPool.m_pSurfaces = m_pVppSurfaces;
for (i = 0; i < m_OutputSurfacesNumber; ++i) {
if (i < (m_OutputSurfacesNumber-1)) {
pFreeVppSurf[i].next = &(pFreeVppSurf[i+1]);
pFreeVppSurf[i+1].prev = &(pFreeVppSurf[i]);
}
}
}
void
CBuffering::SyncFrameSurfaces()
{
std::lock_guard<std::mutex> lock(m_Mutex);
msdkFrameSurface *next = NULL;
msdkFrameSurface *cur = m_UsedSurfacesPool.m_pSurfacesHead;
while (cur) {
if (cur->frame.Data.Locked || cur->render_lock) {
// frame is still locked: just moving to the next one
cur = cur->next;
} else {
// frame was unlocked: moving it to the free surfaces array
m_UsedSurfacesPool.DetachSurfaceUnsafe(cur);
m_FreeSurfacesPool.AddSurfaceUnsafe(cur);
cur = next;
}
}
}
void
CBuffering::SyncVppFrameSurfaces()
{
std::lock_guard<std::mutex> lock(m_Mutex);
msdkFrameSurface *next = NULL;
msdkFrameSurface *cur = m_UsedVppSurfacesPool.m_pSurfacesHead;
while (cur) {
if (cur->frame.Data.Locked || cur->render_lock) {
// frame is still locked: just moving to the next one
cur = cur->next;
} else {
// frame was unlocked: moving it to the free surfaces array
m_UsedVppSurfacesPool.DetachSurfaceUnsafe(cur);
m_FreeVppSurfacesPool.AddSurfaceUnsafe(cur);
cur = next;
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,182 @@
/******************************************************************************\
Copyright (c) 2005-2019, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
This sample was distributed or derived from the Intel's Media Samples package.
The original version of this sample may be obtained from https://software.intel.com/en-us/intel-media-server-studio
or https://software.intel.com/en-us/media-client-solutions-support.
\**********************************************************************************/
#include "mfx_samples_config.h"
#include "plugin_utils.h"
#include "mfxvp8.h"
#include <sstream>
#include <map>
bool AreGuidsEqual(const mfxPluginUID& guid1, const mfxPluginUID& guid2)
{
for(size_t i = 0; i != sizeof(mfxPluginUID); i++)
{
if (guid1.Data[i] != guid2.Data[i])
return false;
}
return true;
}
mfxStatus ConvertStringToGuid(const msdk_string & strGuid, mfxPluginUID & mfxGuid)
{
mfxStatus sts = MFX_ERR_NONE;
// Check if symbolic GUID value
std::map<msdk_string, mfxPluginUID> uid;
uid[MSDK_STRING("hevcd_sw")] = MFX_PLUGINID_HEVCD_SW;
uid[MSDK_STRING("hevcd_hw")] = MFX_PLUGINID_HEVCD_HW;
uid[MSDK_STRING("hevce_sw")] = MFX_PLUGINID_HEVCE_SW;
uid[MSDK_STRING("hevce_gacc")] = MFX_PLUGINID_HEVCE_GACC;
uid[MSDK_STRING("hevce_hw")] = MFX_PLUGINID_HEVCE_HW;
uid[MSDK_STRING("vp8d_hw")] = MFX_PLUGINID_VP8D_HW;
uid[MSDK_STRING("vp8e_hw")] = MFX_PLUGINID_VP8E_HW;
uid[MSDK_STRING("vp9d_hw")] = MFX_PLUGINID_VP9D_HW;
uid[MSDK_STRING("vp9e_hw")] = MFX_PLUGINID_VP9E_HW;
uid[MSDK_STRING("camera_hw")] = MFX_PLUGINID_CAMERA_HW;
uid[MSDK_STRING("capture_hw")] = MFX_PLUGINID_CAPTURE_HW;
uid[MSDK_STRING("ptir_hw")] = MFX_PLUGINID_ITELECINE_HW;
uid[MSDK_STRING("h264_la_hw")] = MFX_PLUGINID_H264LA_HW;
uid[MSDK_STRING("aacd")] = MFX_PLUGINID_AACD;
uid[MSDK_STRING("aace")] = MFX_PLUGINID_AACE;
uid[MSDK_STRING("hevce_fei_hw")] = MFX_PLUGINID_HEVCE_FEI_HW;
if (uid.find(strGuid) == uid.end())
{
mfxGuid = MSDK_PLUGINGUID_NULL;
sts = MFX_ERR_UNKNOWN;
}
else
{
mfxGuid = uid[strGuid];
sts = MFX_ERR_NONE;
}
// Check if plain GUID value
if (sts)
{
if (strGuid.size() != 32)
{
sts = MFX_ERR_UNKNOWN;
}
else
{
for (size_t i = 0; i < 16; i++)
{
unsigned int xx = 0;
msdk_stringstream ss;
ss << std::hex << strGuid.substr(i * 2, 2);
ss >> xx;
mfxGuid.Data[i] = (mfxU8)xx;
}
sts = MFX_ERR_NONE;
}
}
return sts;
}
const mfxPluginUID & msdkGetPluginUID(mfxIMPL impl, msdkComponentType type, mfxU32 uCodecid)
{
if (impl == MFX_IMPL_SOFTWARE)
{
switch(type)
{
case MSDK_VDECODE:
switch(uCodecid)
{
case MFX_CODEC_HEVC:
return MFX_PLUGINID_HEVCD_SW;
}
break;
case MSDK_VENCODE:
switch(uCodecid)
{
case MFX_CODEC_HEVC:
return MFX_PLUGINID_HEVCE_SW;
}
break;
}
}
else
{
switch(type)
{
case MSDK_VENCODE:
switch(uCodecid)
{
case MFX_CODEC_VP8:
return MFX_PLUGINID_VP8E_HW;
}
break;
#if MFX_VERSION >= 1027
case (MSDK_VENCODE | MSDK_FEI):
switch (uCodecid)
{
case MFX_CODEC_HEVC:
return MFX_PLUGINID_HEVC_FEI_ENCODE;
}
break;
#endif
case MSDK_VENC:
switch(uCodecid)
{
case MFX_CODEC_HEVC:
return MFX_PLUGINID_HEVCE_FEI_HW; // HEVC FEI uses ENC interface
}
break;
}
}
return MSDK_PLUGINGUID_NULL;
}
sPluginParams ParsePluginGuid(msdk_char* strPluginGuid)
{
sPluginParams pluginParams;
mfxPluginUID uid;
mfxStatus sts = ConvertStringToGuid(strPluginGuid, uid);
if (sts == MFX_ERR_NONE)
{
pluginParams.type = MFX_PLUGINLOAD_TYPE_GUID;
pluginParams.pluginGuid = uid;
}
return pluginParams;
}
sPluginParams ParsePluginPath(msdk_char* strPluginGuid)
{
sPluginParams pluginParams;
msdk_char tmpVal[MSDK_MAX_FILENAME_LEN];
msdk_opt_read(strPluginGuid, tmpVal);
MSDK_MAKE_BYTE_STRING(tmpVal, pluginParams.strPluginPath);
pluginParams.type = MFX_PLUGINLOAD_TYPE_FILE;
return pluginParams;
}

View File

@@ -0,0 +1,157 @@
/******************************************************************************\
Copyright (c) 2005-2019, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
This sample was distributed or derived from the Intel's Media Samples package.
The original version of this sample may be obtained from https://software.intel.com/en-us/intel-media-server-studio
or https://software.intel.com/en-us/media-client-solutions-support.
\**********************************************************************************/
#include "preset_manager.h"
#include "mfxvideo.h"
#include "brc_routines.h"
CPresetManager CPresetManager::Inst;
msdk_string CPresetManager::modesName[PRESET_MAX_MODES] =
{
MSDK_STRING("Default"),
MSDK_STRING("DSS"),
MSDK_STRING("Conference"),
MSDK_STRING("Gaming"),
};
//GopRefDist, TargetUsage, RateControlMethod, ExtBRCType, AsyncDepth, BRefType
// AdaptiveMaxFrameSize, LowDelayBRC, IntRefType, IntRefCycleSize, IntRefQPDelta, IntRefCycleDist, WeightedPred, WeightedBiPred, EnableBPyramid, EnablePPyramid
CPresetParameters CPresetManager::presets[PRESET_MAX_MODES][PRESET_MAX_CODECS] =
{
// Default
{
{4, MFX_TARGETUSAGE_BALANCED, MFX_RATECONTROL_VBR, EXTBRC_DEFAULT, 4, MFX_B_REF_PYRAMID,
0, 0, 0, 0, 0, 0, MFX_WEIGHTED_PRED_UNKNOWN, MFX_WEIGHTED_PRED_UNKNOWN, 0, 0},
{0, MFX_TARGETUSAGE_BALANCED, MFX_RATECONTROL_VBR, EXTBRC_DEFAULT, 4, 0,
0, 0, 0, 0, 0, 0, MFX_WEIGHTED_PRED_UNKNOWN, MFX_WEIGHTED_PRED_UNKNOWN, 0, 0 }
},
// DSS
{
{1, MFX_TARGETUSAGE_BALANCED, MFX_RATECONTROL_QVBR, EXTBRC_DEFAULT, 1, 0,
0, 0, 0, 0, 0, 0, MFX_WEIGHTED_PRED_UNKNOWN, MFX_WEIGHTED_PRED_UNKNOWN, 0, 0 },
{1, MFX_TARGETUSAGE_BALANCED, MFX_RATECONTROL_QVBR, EXTBRC_DEFAULT, 1, 0,
0, 0, 0, 0, 0, 0, MFX_WEIGHTED_PRED_UNKNOWN, MFX_WEIGHTED_PRED_UNKNOWN, 1, 1 },
},
// Conference
{
{1, MFX_TARGETUSAGE_BALANCED, MFX_RATECONTROL_VCM, EXTBRC_DEFAULT, 1, 0,
0, 0, 0, 0, 0, 0, MFX_WEIGHTED_PRED_UNKNOWN, MFX_WEIGHTED_PRED_UNKNOWN, 0, 0 },
{1, MFX_TARGETUSAGE_BALANCED, MFX_RATECONTROL_VBR, EXTBRC_ON, 1, 0,
0, 0, 0, 0, 0, 0, MFX_WEIGHTED_PRED_UNKNOWN, MFX_WEIGHTED_PRED_UNKNOWN, 0, 0 },
},
// Gaming
{
{1, MFX_TARGETUSAGE_BALANCED, MFX_RATECONTROL_QVBR, EXTBRC_DEFAULT, 1, 0,
MFX_CODINGOPTION_ON, MFX_CODINGOPTION_ON, MFX_REFRESH_HORIZONTAL, 8, 0, 4, MFX_WEIGHTED_PRED_UNKNOWN, MFX_WEIGHTED_PRED_UNKNOWN, 0, 0 },
{1, MFX_TARGETUSAGE_BALANCED, MFX_RATECONTROL_VBR, EXTBRC_ON, 1, 0,
MFX_CODINGOPTION_ON, MFX_CODINGOPTION_ON, MFX_REFRESH_HORIZONTAL, 8, 0, 4, MFX_WEIGHTED_PRED_UNKNOWN, MFX_WEIGHTED_PRED_UNKNOWN, 0, 0 },
}
};
CPresetManager::CPresetManager()
{
}
CPresetManager::~CPresetManager()
{
}
COutputPresetParameters CPresetManager::GetPreset(EPresetModes mode, mfxU32 codecFourCC, mfxF64 fps, mfxU32 width, mfxU32 height, bool isHWLib)
{
COutputPresetParameters retVal = GetBasicPreset(mode, codecFourCC);
*(dynamic_cast<CDependentPresetParameters*>(&retVal)) = GetDependentPresetParameters(mode, codecFourCC, fps, width, height,retVal.TargetUsage);
if (!isHWLib)
{
// These features are unsupported in SW library
retVal.WeightedBiPred = 0;
retVal.WeightedPred = 0;
}
return retVal;
}
COutputPresetParameters CPresetManager::GetBasicPreset(EPresetModes mode, mfxU32 codecFourCC)
{
COutputPresetParameters retVal;
if (mode < 0 || mode >= PRESET_MAX_MODES)
{
mode = PRESET_DEFAULT;
}
// Reading basic preset values
switch (codecFourCC)
{
case MFX_CODEC_AVC:
retVal = presets[mode][PRESET_AVC];
break;
case MFX_CODEC_HEVC:
retVal = presets[mode][PRESET_HEVC];
break;
default:
if (mode != PRESET_DEFAULT)
{
msdk_printf(MSDK_STRING("WARNING: Presets are available for h.264 or h.265 codecs only. Request for particular preset is ignored.\n"));
}
if (codecFourCC != MFX_CODEC_JPEG)
{
retVal.TargetUsage = MFX_TARGETUSAGE_BALANCED;
retVal.RateControlMethod = MFX_RATECONTROL_CBR;
}
retVal.AsyncDepth = 4;
return retVal;
}
retVal.PresetName = modesName[mode];
return retVal;
}
CDependentPresetParameters CPresetManager::GetDependentPresetParameters(EPresetModes mode, mfxU32 codecFourCC, mfxF64 fps, mfxU32 width, mfxU32 height,mfxU16 targetUsage)
{
CDependentPresetParameters retVal = {};
retVal.TargetKbps = codecFourCC != MFX_CODEC_JPEG ? CalculateDefaultBitrate(codecFourCC, targetUsage, width, height, fps) : 0;
if (codecFourCC == MFX_CODEC_AVC || codecFourCC == MFX_CODEC_HEVC)
{
// Calculating dependent preset values
retVal.MaxKbps = (mode == PRESET_GAMING ? (mfxU16)(1.2*retVal.TargetKbps) : 0);
retVal.GopPicSize = (mode == PRESET_GAMING || mode == PRESET_DEFAULT ? 0 : (mfxU16)(2 * fps));
retVal.BufferSizeInKB = (mode == PRESET_DEFAULT ? 0 : retVal.TargetKbps); // 1 second buffers
retVal.LookAheadDepth = 0; // Enable this setting if LA BRC will be enabled
retVal.MaxFrameSize = (mode == PRESET_GAMING ? (mfxU32)(retVal.TargetKbps*0.166) : 0);
}
return retVal;
}
EPresetModes CPresetManager::PresetNameToMode(const msdk_char* name)
{
for (int i = 0; i < PRESET_MAX_MODES; i++)
{
if (!msdk_stricmp(modesName[i].c_str(), name))
{
return (EPresetModes)i;
}
}
return PRESET_MAX_MODES;
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,538 @@
/******************************************************************************\
Copyright (c) 2005-2019, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
This sample was distributed or derived from the Intel's Media Samples package.
The original version of this sample may be obtained from https://software.intel.com/en-us/intel-media-server-studio
or https://software.intel.com/en-us/media-client-solutions-support.
\**********************************************************************************/
#include "sysmem_allocator.h"
#include "sample_utils.h"
#define MSDK_ALIGN32(X) (((mfxU32)((X)+31)) & (~ (mfxU32)31))
#define ID_BUFFER MFX_MAKEFOURCC('B','U','F','F')
#define ID_FRAME MFX_MAKEFOURCC('F','R','M','E')
SysMemFrameAllocator::SysMemFrameAllocator()
: m_pBufferAllocator(0), m_bOwnBufferAllocator(false)
{
}
SysMemFrameAllocator::~SysMemFrameAllocator()
{
Close();
}
mfxStatus SysMemFrameAllocator::Init(mfxAllocatorParams *pParams)
{
// check if any params passed from application
if (pParams)
{
SysMemAllocatorParams *pSysMemParams = 0;
pSysMemParams = dynamic_cast<SysMemAllocatorParams *>(pParams);
if (!pSysMemParams)
return MFX_ERR_NOT_INITIALIZED;
m_pBufferAllocator = pSysMemParams->pBufferAllocator;
m_bOwnBufferAllocator = false;
}
// if buffer allocator wasn't passed from application create own
if (!m_pBufferAllocator)
{
m_pBufferAllocator = new SysMemBufferAllocator;
if (!m_pBufferAllocator)
return MFX_ERR_MEMORY_ALLOC;
m_bOwnBufferAllocator = true;
}
return MFX_ERR_NONE;
}
mfxStatus SysMemFrameAllocator::Close()
{
mfxStatus sts = BaseFrameAllocator::Close();
if (m_bOwnBufferAllocator)
{
delete m_pBufferAllocator;
m_pBufferAllocator = 0;
}
return sts;
}
mfxStatus SysMemFrameAllocator::LockFrame(mfxMemId mid, mfxFrameData *ptr)
{
if (!m_pBufferAllocator)
return MFX_ERR_NOT_INITIALIZED;
if (!ptr)
return MFX_ERR_NULL_PTR;
// If allocator uses pointers instead of mids, no further action is required
if (!mid && ptr->Y)
return MFX_ERR_NONE;
sFrame *fs = 0;
mfxStatus sts = m_pBufferAllocator->Lock(m_pBufferAllocator->pthis, mid,(mfxU8 **)&fs);
if (MFX_ERR_NONE != sts)
return sts;
if (ID_FRAME != fs->id)
{
m_pBufferAllocator->Unlock(m_pBufferAllocator->pthis, mid);
return MFX_ERR_INVALID_HANDLE;
}
mfxU16 Width2 = (mfxU16)MSDK_ALIGN32(fs->info.Width);
mfxU16 Height2 = (mfxU16)MSDK_ALIGN32(fs->info.Height);
ptr->B = ptr->Y = (mfxU8 *)fs + MSDK_ALIGN32(sizeof(sFrame));
switch (fs->info.FourCC)
{
case MFX_FOURCC_NV12:
ptr->U = ptr->Y + Width2 * Height2;
ptr->V = ptr->U + 1;
ptr->PitchHigh = 0;
ptr->PitchLow = (mfxU16)MSDK_ALIGN32(fs->info.Width);
break;
case MFX_FOURCC_NV16:
ptr->U = ptr->Y + Width2 * Height2;
ptr->V = ptr->U + 1;
ptr->PitchHigh = 0;
ptr->PitchLow = (mfxU16)MSDK_ALIGN32(fs->info.Width);
break;
case MFX_FOURCC_YV12:
ptr->V = ptr->Y + Width2 * Height2;
ptr->U = ptr->V + (Width2 >> 1) * (Height2 >> 1);
ptr->PitchHigh = 0;
ptr->PitchLow = (mfxU16)MSDK_ALIGN32(fs->info.Width);
break;
case MFX_FOURCC_UYVY:
ptr->U = ptr->Y;
ptr->Y = ptr->U + 1;
ptr->V = ptr->U + 2;
ptr->PitchHigh = (mfxU16)((2 * MSDK_ALIGN32(fs->info.Width)) / (1 << 16));
ptr->PitchLow = (mfxU16)((2 * MSDK_ALIGN32(fs->info.Width)) % (1 << 16));
break;
case MFX_FOURCC_YUY2:
ptr->U = ptr->Y + 1;
ptr->V = ptr->Y + 3;
ptr->PitchHigh = (mfxU16)((2 * MSDK_ALIGN32(fs->info.Width)) / (1 << 16));
ptr->PitchLow = (mfxU16)((2 * MSDK_ALIGN32(fs->info.Width)) % (1 << 16));
break;
#if (MFX_VERSION >= 1028)
case MFX_FOURCC_RGB565:
ptr->G = ptr->B;
ptr->R = ptr->B;
ptr->PitchHigh = (mfxU16)((2 * MSDK_ALIGN32(fs->info.Width)) / (1 << 16));
ptr->PitchLow = (mfxU16)((2 * MSDK_ALIGN32(fs->info.Width)) % (1 << 16));
break;
#endif
case MFX_FOURCC_RGB3:
ptr->G = ptr->B + 1;
ptr->R = ptr->B + 2;
ptr->PitchHigh = (mfxU16)((3 * MSDK_ALIGN32(fs->info.Width)) / (1 << 16));
ptr->PitchLow = (mfxU16)((3 * MSDK_ALIGN32(fs->info.Width)) % (1 << 16));
break;
#if !(defined(_WIN32) || defined(_WIN64))
case MFX_FOURCC_RGBP:
ptr->G = ptr->R + Width2 * Height2;
ptr->B = ptr->G + Width2 * Height2;
ptr->PitchHigh = (mfxU16)((MSDK_ALIGN32(fs->info.Width)) / (1 << 16));
ptr->PitchLow = (mfxU16)((MSDK_ALIGN32(fs->info.Width)) % (1 << 16));
break;
#endif
case MFX_FOURCC_RGB4:
case MFX_FOURCC_A2RGB10:
ptr->G = ptr->B + 1;
ptr->R = ptr->B + 2;
ptr->A = ptr->B + 3;
ptr->PitchHigh = (mfxU16)((4 * MSDK_ALIGN32(fs->info.Width)) / (1 << 16));
ptr->PitchLow = (mfxU16)((4 * MSDK_ALIGN32(fs->info.Width)) % (1 << 16));
break;
case MFX_FOURCC_R16:
ptr->Y16 = (mfxU16 *)ptr->B;
ptr->PitchHigh = (mfxU16)((2 * MSDK_ALIGN32(fs->info.Width)) / (1 << 16));
ptr->PitchLow = (mfxU16)((2 * MSDK_ALIGN32(fs->info.Width)) % (1 << 16));
break;
#if (MFX_VERSION >= 1031)
case MFX_FOURCC_P016:
#endif
case MFX_FOURCC_P010:
ptr->U = ptr->Y + Width2 * Height2 * 2;
ptr->V = ptr->U + 2;
ptr->PitchHigh = 0;
ptr->PitchLow = (mfxU16)MSDK_ALIGN32(fs->info.Width * 2);
break;
case MFX_FOURCC_P210:
ptr->U = ptr->Y + Width2 * Height2 * 2;
ptr->V = ptr->U + 2;
ptr->PitchHigh = 0;
ptr->PitchLow = (mfxU16)MSDK_ALIGN32(fs->info.Width * 2);
break;
case MFX_FOURCC_AYUV:
ptr->V = ptr->B;
ptr->U = ptr->V + 1;
ptr->Y = ptr->V + 2;
ptr->A = ptr->V + 3;
ptr->PitchHigh = (mfxU16)((4 * MSDK_ALIGN32(fs->info.Width)) / (1 << 16));
ptr->PitchLow = (mfxU16)((4 * MSDK_ALIGN32(fs->info.Width)) % (1 << 16));
break;
#if (MFX_VERSION >= 1031)
case MFX_FOURCC_Y416:
ptr->U16 = (mfxU16*)ptr->B;
ptr->Y16 = ptr->U16 + 1;
ptr->V16 = ptr->Y16 + 1;
ptr->A = (mfxU8 *)(ptr->V16 + 1);
ptr->PitchHigh = (mfxU16)(8 * MSDK_ALIGN32(fs->info.Width) / (1 << 16));
ptr->PitchLow = (mfxU16)(8 * MSDK_ALIGN32(fs->info.Width) % (1 << 16));
break;
case MFX_FOURCC_Y216:
#endif
#if (MFX_VERSION >= 1027)
case MFX_FOURCC_Y210:
ptr->Y16 = (mfxU16 *)ptr->B;
ptr->U16 = ptr->Y16 + 1;
ptr->V16 = ptr->Y16 + 3;
//4 words per macropixel -> 2 words per pixel -> 4 bytes per pixel
ptr->PitchHigh = (mfxU16)((4 * MSDK_ALIGN32(fs->info.Width)) / (1 << 16));
ptr->PitchLow = (mfxU16)((4 * MSDK_ALIGN32(fs->info.Width)) % (1 << 16));
break;
case MFX_FOURCC_Y410:
ptr->U = ptr->V = ptr->A = ptr->Y;
ptr->PitchHigh = (mfxU16)((4 * MSDK_ALIGN32(fs->info.Width)) / (1 << 16));
ptr->PitchLow = (mfxU16)((4 * MSDK_ALIGN32(fs->info.Width)) % (1 << 16));
break;
#endif
default:
return MFX_ERR_UNSUPPORTED;
}
return MFX_ERR_NONE;
}
mfxStatus SysMemFrameAllocator::UnlockFrame(mfxMemId mid, mfxFrameData *ptr)
{
if (!m_pBufferAllocator)
return MFX_ERR_NOT_INITIALIZED;
// If allocator uses pointers instead of mids, no further action is required
if (!mid && ptr->Y)
return MFX_ERR_NONE;
mfxStatus sts = m_pBufferAllocator->Unlock(m_pBufferAllocator->pthis, mid);
if (MFX_ERR_NONE != sts)
return sts;
if (NULL != ptr)
{
ptr->Pitch = 0;
ptr->Y = 0;
ptr->U = 0;
ptr->V = 0;
ptr->A = 0;
}
return MFX_ERR_NONE;
}
mfxStatus SysMemFrameAllocator::GetFrameHDL(mfxMemId /*mid*/, mfxHDL* /*handle*/)
{
return MFX_ERR_UNSUPPORTED;
}
mfxStatus SysMemFrameAllocator::CheckRequestType(mfxFrameAllocRequest *request)
{
mfxStatus sts = BaseFrameAllocator::CheckRequestType(request);
if (MFX_ERR_NONE != sts)
return sts;
if ((request->Type & MFX_MEMTYPE_SYSTEM_MEMORY) != 0)
return MFX_ERR_NONE;
else
return MFX_ERR_UNSUPPORTED;
}
mfxMemId *SysMemFrameAllocator::GetMidHolder(mfxMemId mid)
{
for (auto resp : m_vResp)
{
mfxMemId *it = std::find(resp->mids, resp->mids + resp->NumFrameActual, mid);
if (it != resp->mids + resp->NumFrameActual)
return it;
}
return nullptr;
}
static mfxU32 GetSurfaceSize(mfxU32 FourCC, mfxU32 Width2, mfxU32 Height2)
{
mfxU32 nbytes = 0;
switch (FourCC)
{
case MFX_FOURCC_YV12:
case MFX_FOURCC_NV12:
nbytes = Width2*Height2 + (Width2>>1)*(Height2>>1) + (Width2>>1)*(Height2>>1);
break;
case MFX_FOURCC_NV16:
nbytes = Width2*Height2 + (Width2>>1)*(Height2) + (Width2>>1)*(Height2);
break;
#if (MFX_VERSION >= 1028)
case MFX_FOURCC_RGB565:
nbytes = 2*Width2*Height2;
break;
#endif
#if !(defined(_WIN32) || defined(_WIN64))
case MFX_FOURCC_RGBP:
#endif
case MFX_FOURCC_RGB3:
nbytes = Width2*Height2 + Width2*Height2 + Width2*Height2;
break;
case MFX_FOURCC_RGB4:
case MFX_FOURCC_AYUV:
#if (MFX_VERSION >= 1027)
case MFX_FOURCC_Y410:
#endif
nbytes = Width2*Height2 + Width2*Height2 + Width2*Height2 + Width2*Height2;
break;
case MFX_FOURCC_UYVY:
case MFX_FOURCC_YUY2:
nbytes = Width2*Height2 + (Width2>>1)*(Height2) + (Width2>>1)*(Height2);
break;
case MFX_FOURCC_R16:
nbytes = 2*Width2*Height2;
break;
case MFX_FOURCC_P010:
#if (MFX_VERSION >= 1031)
case MFX_FOURCC_P016:
#endif
nbytes = Width2*Height2 + (Width2>>1)*(Height2>>1) + (Width2>>1)*(Height2>>1);
nbytes *= 2;
break;
case MFX_FOURCC_A2RGB10:
nbytes = Width2*Height2*4; // 4 bytes per pixel
break;
case MFX_FOURCC_P210:
#if (MFX_VERSION >= 1027)
case MFX_FOURCC_Y210:
#endif
#if (MFX_VERSION >= 1031)
case MFX_FOURCC_Y216:
nbytes = Width2*Height2 + (Width2>>1)*(Height2) + (Width2>>1)*(Height2);
nbytes *= 2; // 16bits
break;
case MFX_FOURCC_Y416:
nbytes = (Width2*Height2 + Width2*Height2 + Width2*Height2 + Width2*Height2) * 2;
break;
#endif
default:
break;
}
return nbytes;
}
mfxStatus SysMemFrameAllocator::ReallocImpl(mfxMemId mid, const mfxFrameInfo *info, mfxU16 /*memType*/, mfxMemId *midOut)
{
if (!info || !midOut)
return MFX_ERR_NULL_PTR;
if (!m_pBufferAllocator)
return MFX_ERR_NOT_INITIALIZED;
mfxU32 nbytes = GetSurfaceSize(info->FourCC, MSDK_ALIGN32(info->Width), MSDK_ALIGN32(info->Height));
if(!nbytes)
return MFX_ERR_UNSUPPORTED;
// pointer to the record in m_mids structure
mfxMemId *pmid = GetMidHolder(mid);
if (!pmid)
return MFX_ERR_MEMORY_ALLOC;
mfxStatus sts = m_pBufferAllocator->Free(m_pBufferAllocator->pthis, *pmid);
if (MFX_ERR_NONE != sts)
return sts;
sts = m_pBufferAllocator->Alloc(m_pBufferAllocator->pthis,
MSDK_ALIGN32(nbytes) + MSDK_ALIGN32(sizeof(sFrame)), MFX_MEMTYPE_SYSTEM_MEMORY, pmid);
if (MFX_ERR_NONE != sts)
return sts;
sFrame *fs;
sts = m_pBufferAllocator->Lock(m_pBufferAllocator->pthis, *pmid, (mfxU8 **)&fs);
if (MFX_ERR_NONE != sts)
return sts;
fs->id = ID_FRAME;
fs->info = *info;
m_pBufferAllocator->Unlock(m_pBufferAllocator->pthis, *pmid);
*midOut = *pmid;
return MFX_ERR_NONE;
}
mfxStatus SysMemFrameAllocator::AllocImpl(mfxFrameAllocRequest *request, mfxFrameAllocResponse *response)
{
if (!m_pBufferAllocator)
return MFX_ERR_NOT_INITIALIZED;
mfxU32 numAllocated = 0;
mfxU32 nbytes = GetSurfaceSize(request->Info.FourCC, MSDK_ALIGN32(request->Info.Width), MSDK_ALIGN32(request->Info.Height));
if(!nbytes)
return MFX_ERR_UNSUPPORTED;
std::unique_ptr<mfxMemId[]> mids(new mfxMemId[request->NumFrameSuggested]);
// allocate frames
for (numAllocated = 0; numAllocated < request->NumFrameSuggested; numAllocated ++)
{
mfxStatus sts = m_pBufferAllocator->Alloc(m_pBufferAllocator->pthis,
nbytes + MSDK_ALIGN32(sizeof(sFrame)), request->Type, &(mids[numAllocated]));
if (MFX_ERR_NONE != sts)
break;
sFrame *fs;
sts = m_pBufferAllocator->Lock(m_pBufferAllocator->pthis, mids[numAllocated], (mfxU8 **)&fs);
if (MFX_ERR_NONE != sts)
break;
fs->id = ID_FRAME;
fs->info = request->Info;
sts = m_pBufferAllocator->Unlock(m_pBufferAllocator->pthis, mids[numAllocated]);
if (MFX_ERR_NONE != sts)
break;
}
// check the number of allocated frames
if (numAllocated < request->NumFrameSuggested)
{
return MFX_ERR_MEMORY_ALLOC;
}
response->NumFrameActual = (mfxU16) numAllocated;
response->mids = mids.release();
m_vResp.push_back(response);
return MFX_ERR_NONE;
}
mfxStatus SysMemFrameAllocator::ReleaseResponse(mfxFrameAllocResponse *response)
{
if (!response)
return MFX_ERR_NULL_PTR;
if (!m_pBufferAllocator)
return MFX_ERR_NOT_INITIALIZED;
mfxStatus sts = MFX_ERR_NONE;
if (response->mids)
{
for (mfxU32 i = 0; i < response->NumFrameActual; i++)
{
if (response->mids[i])
{
sts = m_pBufferAllocator->Free(m_pBufferAllocator->pthis, response->mids[i]);
if (MFX_ERR_NONE != sts)
return sts;
}
}
}
m_vResp.erase(std::remove(m_vResp.begin(), m_vResp.end(), response), m_vResp.end());
delete [] response->mids;
response->mids = 0;
return sts;
}
SysMemBufferAllocator::SysMemBufferAllocator()
{
}
SysMemBufferAllocator::~SysMemBufferAllocator()
{
}
mfxStatus SysMemBufferAllocator::AllocBuffer(mfxU32 nbytes, mfxU16 type, mfxMemId *mid)
{
if (!mid)
return MFX_ERR_NULL_PTR;
if (0 == (type & MFX_MEMTYPE_SYSTEM_MEMORY))
return MFX_ERR_UNSUPPORTED;
mfxU32 header_size = MSDK_ALIGN32(sizeof(sBuffer));
mfxU8 *buffer_ptr = (mfxU8 *)calloc(header_size + nbytes + 32, 1);
if (!buffer_ptr)
return MFX_ERR_MEMORY_ALLOC;
sBuffer *bs = (sBuffer *)buffer_ptr;
bs->id = ID_BUFFER;
bs->type = type;
bs->nbytes = nbytes;
*mid = (mfxHDL) bs;
return MFX_ERR_NONE;
}
mfxStatus SysMemBufferAllocator::LockBuffer(mfxMemId mid, mfxU8 **ptr)
{
if (!ptr)
return MFX_ERR_NULL_PTR;
sBuffer *bs = (sBuffer *)mid;
if (!bs)
return MFX_ERR_INVALID_HANDLE;
if (ID_BUFFER != bs->id)
return MFX_ERR_INVALID_HANDLE;
*ptr = (mfxU8*)((size_t)((mfxU8 *)bs+MSDK_ALIGN32(sizeof(sBuffer))+31)&(~((size_t)31)));
return MFX_ERR_NONE;
}
mfxStatus SysMemBufferAllocator::UnlockBuffer(mfxMemId mid)
{
sBuffer *bs = (sBuffer *)mid;
if (!bs || ID_BUFFER != bs->id)
return MFX_ERR_INVALID_HANDLE;
return MFX_ERR_NONE;
}
mfxStatus SysMemBufferAllocator::FreeBuffer(mfxMemId mid)
{
sBuffer *bs = (sBuffer *)mid;
if (!bs || ID_BUFFER != bs->id)
return MFX_ERR_INVALID_HANDLE;
free(bs);
return MFX_ERR_NONE;
}

View File

@@ -0,0 +1,357 @@
/******************************************************************************\
Copyright (c) 2005-2019, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
This sample was distributed or derived from the Intel's Media Samples package.
The original version of this sample may be obtained from https://software.intel.com/en-us/intel-media-server-studio
or https://software.intel.com/en-us/media-client-solutions-support.
\**********************************************************************************/
#if defined (ENABLE_V4L2_SUPPORT)
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <pthread.h>
#include <poll.h>
#include <signal.h>
#include <assert.h>
#include <linux/videodev2.h>
#include "v4l2_util.h"
/* Global Declaration */
Buffer *buffers, *CurBuffers;
bool CtrlFlag = false;
int m_q[5], m_first = 0, m_last = 0, m_numInQ = 0;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t empty = PTHREAD_MUTEX_INITIALIZER;
v4l2Device::v4l2Device( const char *devname,
uint32_t width,
uint32_t height,
uint32_t num_buffers,
enum AtomISPMode MipiMode,
enum V4L2PixelFormat v4l2Format):
m_devname(devname),
m_height(height),
m_width(width),
m_num_buffers(num_buffers),
m_MipiPort(0),
m_MipiMode(MipiMode),
m_v4l2Format(v4l2Format),
m_fd(-1)
{
}
v4l2Device::~v4l2Device()
{
if (m_fd > -1)
{
BYE_ON(close(m_fd) < 0, "V4L2 device close failed: %s\n", ERRSTR);
}
}
int v4l2Device::blockIOCTL(int handle, int request, void *args)
{
int ioctlStatus;
do
{
ioctlStatus = ioctl(handle, request, args);
} while (-1 == ioctlStatus && EINTR == errno);
return ioctlStatus;
}
int v4l2Device::GetAtomISPModes(enum AtomISPMode mode)
{
switch(mode)
{
case VIDEO: return _ISP_MODE_VIDEO;
case PREVIEW: return _ISP_MODE_PREVIEW;
case CONTINUOUS: return _ISP_MODE_CONTINUOUS;
case STILL: return _ISP_MODE_STILL;
case NONE:
default:
return _ISP_MODE_NONE;
}
}
int v4l2Device::ConvertToMFXFourCC(enum V4L2PixelFormat v4l2Format)
{
switch (v4l2Format)
{
case UYVY: return MFX_FOURCC_UYVY;
case YUY2: return MFX_FOURCC_YUY2;
case NO_FORMAT:
default:
assert( !"Unsupported mfx fourcc");
return 0;
}
}
int v4l2Device::ConvertToV4L2FourCC()
{
switch (m_v4l2Format)
{
case UYVY: return V4L2_PIX_FMT_UYVY;
case YUY2: return V4L2_PIX_FMT_YUYV;
case NO_FORMAT:
default:
assert( !"Unsupported v4l2 fourcc");
return 0;
}
}
void v4l2Device::Init( const char *devname,
uint32_t width,
uint32_t height,
uint32_t num_buffers,
enum V4L2PixelFormat v4l2Format,
enum AtomISPMode MipiMode,
int MipiPort)
{
(devname != NULL)? m_devname = devname : m_devname;
(m_width != width )? m_width = width : m_width;
(m_height != height)? m_height = height : m_height;
(m_num_buffers != num_buffers)? m_num_buffers = num_buffers : m_num_buffers;
(m_v4l2Format != v4l2Format )? m_v4l2Format = v4l2Format : m_v4l2Format;
(m_MipiMode != MipiMode )? m_MipiMode = MipiMode : m_MipiMode;
(m_MipiPort != MipiPort )? m_MipiPort = MipiPort : m_MipiPort;
memset(&m_format, 0, sizeof m_format);
m_format.width = m_width;
m_format.height = m_height;
m_format.pixelformat = ConvertToV4L2FourCC();
V4L2Init();
}
void v4l2Device::V4L2Init()
{
int ret;
struct v4l2_format fmt;
struct v4l2_capability caps;
struct v4l2_streamparm parm;
struct v4l2_requestbuffers rqbufs;
CLEAR(parm);
m_fd = open(m_devname, O_RDWR);
BYE_ON(m_fd < 0, "failed to open %s: %s\n", m_devname, ERRSTR);
CLEAR(caps);
/* Specifically for setting up mipi configuration. DMABUFF is
* also enable by default here.
*/
if (m_MipiPort > -1 && m_MipiMode != NONE) {
parm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
parm.parm.capture.capturemode = GetAtomISPModes(m_MipiMode);
ret = blockIOCTL(m_fd, VIDIOC_S_INPUT, &m_MipiPort);
BYE_ON(ret < 0, "VIDIOC_S_INPUT failed: %s\n", ERRSTR);
ret = blockIOCTL(m_fd, VIDIOC_S_PARM, &parm);
BYE_ON(ret < 0, "VIDIOC_S_PARAM failed: %s\n", ERRSTR);
}
ret = blockIOCTL(m_fd, VIDIOC_QUERYCAP, &caps);
msdk_printf( "Driver Caps:\n"
" Driver: \"%s\"\n"
" Card: \"%s\"\n"
" Bus: \"%s\"\n"
" Version: %d.%d\n"
" Capabilities: %08x\n",
caps.driver,
caps.card,
caps.bus_info,
(caps.version>>16)&&0xff,
(caps.version>>24)&&0xff,
caps.capabilities);
BYE_ON(ret, "VIDIOC_QUERYCAP failed: %s\n", ERRSTR);
BYE_ON(~caps.capabilities & V4L2_CAP_VIDEO_CAPTURE,
"video: singleplanar capture is not supported\n");
CLEAR(fmt);
fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
ret = blockIOCTL(m_fd, VIDIOC_G_FMT, &fmt);
BYE_ON(ret < 0, "VIDIOC_G_FMT failed: %s\n", ERRSTR);
msdk_printf("G_FMT(start): width = %u, height = %u, 4cc = %.4s, BPP = %u sizeimage = %d field = %d\n",
fmt.fmt.pix.width, fmt.fmt.pix.height,
(char*)&fmt.fmt.pix.pixelformat,
fmt.fmt.pix.bytesperline,
fmt.fmt.pix.sizeimage,
fmt.fmt.pix.field);
fmt.fmt.pix = m_format;
msdk_printf("G_FMT(pre): width = %u, height = %u, 4cc = %.4s, BPP = %u sizeimage = %d field = %d\n",
fmt.fmt.pix.width, fmt.fmt.pix.height,
(char*)&fmt.fmt.pix.pixelformat,
fmt.fmt.pix.bytesperline,
fmt.fmt.pix.sizeimage,
fmt.fmt.pix.field);
ret = blockIOCTL(m_fd, VIDIOC_S_FMT, &fmt);
BYE_ON(ret < 0, "VIDIOC_S_FMT failed: %s\n", ERRSTR);
ret = blockIOCTL(m_fd, VIDIOC_G_FMT, &fmt);
BYE_ON(ret < 0, "VIDIOC_G_FMT failed: %s\n", ERRSTR);
msdk_printf("G_FMT(final): width = %u, height = %u, 4cc = %.4s, BPP = %u\n",
fmt.fmt.pix.width, fmt.fmt.pix.height,
(char*)&fmt.fmt.pix.pixelformat,
fmt.fmt.pix.bytesperline);
CLEAR(rqbufs);
rqbufs.count = m_num_buffers;
rqbufs.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
rqbufs.memory = V4L2_MEMORY_DMABUF;
ret = blockIOCTL(m_fd, VIDIOC_REQBUFS, &rqbufs);
BYE_ON(ret < 0, "VIDIOC_REQBUFS failed: %s\n", ERRSTR);
BYE_ON(rqbufs.count < m_num_buffers, "video node allocated only "
"%u of %u buffers\n", rqbufs.count, m_num_buffers);
m_format = fmt.fmt.pix;
}
void v4l2Device::V4L2Alloc()
{
buffers = (Buffer *)malloc(sizeof(Buffer) * (int) m_num_buffers);
}
void v4l2Device::V4L2QueueBuffer(Buffer *buffer)
{
struct v4l2_buffer buf;
int ret;
memset(&buf, 0, sizeof buf);
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_DMABUF;
buf.index = buffer->index;
buf.m.fd = buffer->fd;
ret = blockIOCTL(m_fd, VIDIOC_QBUF, &buf);
BYE_ON(ret < 0, "VIDIOC_QBUF for buffer %d failed: %s (fd %u) (i %u)\n",
buf.index, ERRSTR, buffer->fd, buffer->index);
}
Buffer *v4l2Device::V4L2DeQueueBuffer(Buffer *buffer)
{
struct v4l2_buffer buf;
int ret;
memset(&buf, 0, sizeof buf);
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_DMABUF;
ret = blockIOCTL(m_fd, VIDIOC_DQBUF, &buf);
BYE_ON(ret, "VIDIOC_DQBUF failed: %s\n", ERRSTR);
return &buffer[buf.index];
}
void v4l2Device::V4L2StartCapture()
{
int type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
int ret = 0;
ret = blockIOCTL(m_fd, VIDIOC_STREAMON, &type);
BYE_ON(ret < 0, "STREAMON failed: %s\n", ERRSTR);
}
void v4l2Device::V4L2StopCapture()
{
int type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
int ret = 0;
ret = blockIOCTL(m_fd, VIDIOC_STREAMOFF, &type);
BYE_ON(ret < 0, "STREAMOFF failed: %s\n", ERRSTR);
}
void v4l2Device::PutOnQ(int x)
{
pthread_mutex_lock(&mutex);
m_q[m_first] = x;
m_first = (m_first+1) % 5;
m_numInQ++;
pthread_mutex_unlock(&mutex);
pthread_mutex_unlock(&empty);
}
int v4l2Device::GetOffQ()
{
int thing;
/* wait if the queue is empty. */
while (m_numInQ == 0)
pthread_mutex_lock(&empty);
pthread_mutex_lock(&mutex);
thing = m_q[m_last];
m_last = (m_last+1) % 5;
m_numInQ--;
pthread_mutex_unlock(&mutex);
return thing;
}
int v4l2Device::GetV4L2TerminationSignal()
{
return (CtrlFlag && m_numInQ == 0)? 1 : 0;
}
static void CtrlCTerminationHandler(int s) { CtrlFlag = true; }
void *PollingThread(void *data)
{
v4l2Device *v4l2 = (v4l2Device *)data;
struct sigaction sigIntHandler;
sigIntHandler.sa_handler = CtrlCTerminationHandler;
sigemptyset(&sigIntHandler.sa_mask);
sigIntHandler.sa_flags = 0;
sigaction(SIGINT, &sigIntHandler, NULL);
struct pollfd fd;
fd.fd = v4l2->GetV4L2DisplayID();
fd.events = POLLIN;
while(1)
{
if (poll(&fd, 1, 5000) > 0)
{
if (fd.revents & POLLIN)
{
CurBuffers = v4l2->V4L2DeQueueBuffer(buffers);
v4l2->PutOnQ(CurBuffers->index);
if (CtrlFlag)
break;
if (CurBuffers)
v4l2->V4L2QueueBuffer(&buffers[CurBuffers->index]);
}
}
}
}
#endif // ifdef ENABLE_V4L2_SUPPORT

View File

@@ -0,0 +1,747 @@
/******************************************************************************\
Copyright (c) 2005-2019, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
This sample was distributed or derived from the Intel's Media Samples package.
The original version of this sample may be obtained from https://software.intel.com/en-us/intel-media-server-studio
or https://software.intel.com/en-us/media-client-solutions-support.
\**********************************************************************************/
#if defined(LIBVA_SUPPORT)
#include <stdio.h>
#include <assert.h>
#include "vaapi_allocator.h"
#include "vaapi_utils.h"
enum {
MFX_FOURCC_VP8_NV12 = MFX_MAKEFOURCC('V','P','8','N'),
MFX_FOURCC_VP8_MBDATA = MFX_MAKEFOURCC('V','P','8','M'),
MFX_FOURCC_VP8_SEGMAP = MFX_MAKEFOURCC('V','P','8','S'),
};
unsigned int ConvertMfxFourccToVAFormat(mfxU32 fourcc)
{
switch (fourcc)
{
case MFX_FOURCC_NV12:
return VA_FOURCC_NV12;
case MFX_FOURCC_YUY2:
return VA_FOURCC_YUY2;
case MFX_FOURCC_UYVY:
return VA_FOURCC_UYVY;
case MFX_FOURCC_YV12:
return VA_FOURCC_YV12;
#if (MFX_VERSION >= 1028)
case MFX_FOURCC_RGB565:
return VA_FOURCC_RGB565;
#endif
case MFX_FOURCC_RGB4:
return VA_FOURCC_ARGB;
case MFX_FOURCC_BGR4:
return VA_FOURCC_ABGR;
case MFX_FOURCC_RGBP:
return VA_FOURCC_RGBP;
case MFX_FOURCC_P8:
return VA_FOURCC_P208;
case MFX_FOURCC_P010:
return VA_FOURCC_P010;
case MFX_FOURCC_A2RGB10:
return VA_FOURCC_ARGB; // rt format will be VA_RT_FORMAT_RGB32_10BPP
case MFX_FOURCC_AYUV:
return VA_FOURCC_AYUV;
#if (MFX_VERSION >= 1027)
case MFX_FOURCC_Y210:
return VA_FOURCC_Y210;
case MFX_FOURCC_Y410:
return VA_FOURCC_Y410;
#endif
#if (MFX_VERSION >= 1031)
case MFX_FOURCC_P016:
return VA_FOURCC_P016;
case MFX_FOURCC_Y216:
return VA_FOURCC_Y216;
case MFX_FOURCC_Y416:
return VA_FOURCC_Y416;
#endif
default:
assert(!"unsupported fourcc");
return 0;
}
}
unsigned int ConvertVP8FourccToMfxFourcc(mfxU32 fourcc)
{
switch (fourcc)
{
case MFX_FOURCC_VP8_NV12:
case MFX_FOURCC_VP8_MBDATA:
return MFX_FOURCC_NV12;
case MFX_FOURCC_VP8_SEGMAP:
return MFX_FOURCC_P8;
default:
return fourcc;
}
}
vaapiFrameAllocator::vaapiFrameAllocator()
: m_dpy(0)
, m_libva(new MfxLoader::VA_Proxy)
, m_export_mode(vaapiAllocatorParams::DONOT_EXPORT)
, m_exporter(NULL)
{
}
vaapiFrameAllocator::~vaapiFrameAllocator()
{
Close();
delete m_libva;
}
mfxStatus vaapiFrameAllocator::Init(mfxAllocatorParams *pParams)
{
vaapiAllocatorParams* p_vaapiParams = dynamic_cast<vaapiAllocatorParams*>(pParams);
if ((NULL == p_vaapiParams) || (NULL == p_vaapiParams->m_dpy))
return MFX_ERR_NOT_INITIALIZED;
if ((p_vaapiParams->m_export_mode != vaapiAllocatorParams::DONOT_EXPORT) &&
!(p_vaapiParams->m_export_mode & vaapiAllocatorParams::FLINK) &&
!(p_vaapiParams->m_export_mode & vaapiAllocatorParams::PRIME) &&
!(p_vaapiParams->m_export_mode & vaapiAllocatorParams::CUSTOM))
return MFX_ERR_UNSUPPORTED;
if ((p_vaapiParams->m_export_mode & vaapiAllocatorParams::CUSTOM) &&
!p_vaapiParams->m_exporter)
return MFX_ERR_UNSUPPORTED;
m_dpy = p_vaapiParams->m_dpy;
m_export_mode = p_vaapiParams->m_export_mode;
m_exporter = p_vaapiParams->m_exporter;
return MFX_ERR_NONE;
}
mfxStatus vaapiFrameAllocator::CheckRequestType(mfxFrameAllocRequest *request)
{
mfxStatus sts = BaseFrameAllocator::CheckRequestType(request);
if (MFX_ERR_NONE != sts)
return sts;
if ((request->Type & (MFX_MEMTYPE_VIDEO_MEMORY_DECODER_TARGET | MFX_MEMTYPE_VIDEO_MEMORY_PROCESSOR_TARGET)) != 0)
return MFX_ERR_NONE;
else
return MFX_ERR_UNSUPPORTED;
}
mfxStatus vaapiFrameAllocator::Close()
{
return BaseFrameAllocator::Close();
}
static mfxStatus GetVAFourcc(mfxU32 fourcc, unsigned int &va_fourcc)
{
// VP8 hybrid driver has weird requirements for allocation of surfaces/buffers for VP8 encoding
// to comply with them additional logic is required to support regular and VP8 hybrid allocation pathes
mfxU32 mfx_fourcc = ConvertVP8FourccToMfxFourcc(fourcc);
va_fourcc = ConvertMfxFourccToVAFormat(mfx_fourcc);
if (!va_fourcc || ((VA_FOURCC_NV12 != va_fourcc) &&
(VA_FOURCC_YV12 != va_fourcc) &&
(VA_FOURCC_YUY2 != va_fourcc) &&
(VA_FOURCC_ARGB != va_fourcc) &&
(VA_FOURCC_ABGR != va_fourcc) &&
(VA_FOURCC_RGBP != va_fourcc) &&
(VA_FOURCC_P208 != va_fourcc) &&
(VA_FOURCC_P010 != va_fourcc) &&
(VA_FOURCC_YUY2 != va_fourcc) &&
#if (MFX_VERSION >= 1027)
(VA_FOURCC_Y210 != va_fourcc) &&
(VA_FOURCC_Y410 != va_fourcc) &&
#endif
#if (MFX_VERSION >= 1028)
(VA_FOURCC_RGB565 != va_fourcc) &&
#endif
#if (MFX_VERSION >= 1031)
(VA_FOURCC_P016 != va_fourcc) &&
(VA_FOURCC_Y216 != va_fourcc) &&
(VA_FOURCC_Y416 != va_fourcc) &&
#endif
(VA_FOURCC_AYUV != va_fourcc)))
{
return MFX_ERR_MEMORY_ALLOC;
}
return MFX_ERR_NONE;
}
mfxStatus vaapiFrameAllocator::ReallocImpl(mfxMemId mid, const mfxFrameInfo *info, mfxU16 memType, mfxMemId *midOut)
{
if (!info || !midOut) return MFX_ERR_NULL_PTR;
mfxStatus mfx_res = MFX_ERR_NONE;
VAStatus va_res = VA_STATUS_SUCCESS;
unsigned int va_fourcc = 0;
mfxU32 fourcc = info->FourCC;
mfx_res = GetVAFourcc(fourcc, va_fourcc);
if (MFX_ERR_NONE != mfx_res)
return mfx_res;
mfxU32 Width = info->Width;
mfxU32 Height = info->Height;
if (VA_FOURCC_P208 == va_fourcc)
return MFX_ERR_UNSUPPORTED;
VASurfaceID surfaces[1];
VASurfaceAttrib attrib[2];
vaapiMemId *vaapiMid = (vaapiMemId *)mid;
surfaces[0] = *vaapiMid->m_surface;
m_libva->vaDestroySurfaces(m_dpy, surfaces, 1);
unsigned int format;
int attrCnt = 0;
attrib[attrCnt].type = VASurfaceAttribPixelFormat;
attrib[attrCnt].flags = VA_SURFACE_ATTRIB_SETTABLE;
attrib[attrCnt].value.type = VAGenericValueTypeInteger;
attrib[attrCnt++].value.value.i = va_fourcc;
format = va_fourcc;
if ((fourcc == MFX_FOURCC_VP8_NV12) ||
((MFX_MEMTYPE_VIDEO_MEMORY_ENCODER_TARGET & memType)
&& ((fourcc == MFX_FOURCC_RGB4) || (fourcc == MFX_FOURCC_BGR4))))
{
/*
* special configuration for NV12 surf allocation for VP8 hybrid encoder and
* RGB32 for JPEG is required
*/
attrib[attrCnt].type = (VASurfaceAttribType)VASurfaceAttribUsageHint;
attrib[attrCnt].flags = VA_SURFACE_ATTRIB_SETTABLE;
attrib[attrCnt].value.type = VAGenericValueTypeInteger;
attrib[attrCnt++].value.value.i = VA_SURFACE_ATTRIB_USAGE_HINT_ENCODER;
}
else if (fourcc == MFX_FOURCC_VP8_MBDATA)
{
// special configuration for MB data surf allocation for VP8 hybrid encoder is required
attrib[0].value.value.i = VA_FOURCC_P208;
format = VA_FOURCC_P208;
}
else if (va_fourcc == VA_FOURCC_NV12)
{
format = VA_RT_FORMAT_YUV420;
}
va_res = m_libva->vaCreateSurfaces(m_dpy,
format,
Width, Height,
surfaces,
1,
&attrib[0], attrCnt);
*vaapiMid->m_surface = surfaces[0];
vaapiMid->m_fourcc = fourcc;
*midOut = mid;
mfx_res = va_to_mfx_status(va_res);
return mfx_res;
}
mfxStatus vaapiFrameAllocator::AllocImpl(mfxFrameAllocRequest *request, mfxFrameAllocResponse *response)
{
mfxStatus mfx_res = MFX_ERR_NONE;
VAStatus va_res = VA_STATUS_SUCCESS;
unsigned int va_fourcc = 0;
VASurfaceID* surfaces = NULL;
vaapiMemId *vaapi_mids = NULL, *vaapi_mid = NULL;
mfxMemId* mids = NULL;
mfxU32 fourcc = request->Info.FourCC;
mfxU16 surfaces_num = request->NumFrameSuggested, numAllocated = 0, i = 0;
bool bCreateSrfSucceeded = false;
memset(response, 0, sizeof(mfxFrameAllocResponse));
mfx_res = GetVAFourcc(fourcc, va_fourcc);
if (MFX_ERR_NONE != mfx_res)
return mfx_res;
if (!surfaces_num)
{
return MFX_ERR_MEMORY_ALLOC;
}
if (MFX_ERR_NONE == mfx_res)
{
surfaces = (VASurfaceID*)calloc(surfaces_num, sizeof(VASurfaceID));
vaapi_mids = (vaapiMemId*)calloc(surfaces_num, sizeof(vaapiMemId));
mids = (mfxMemId*)calloc(surfaces_num, sizeof(mfxMemId));
if ((NULL == surfaces) || (NULL == vaapi_mids) || (NULL == mids)) mfx_res = MFX_ERR_MEMORY_ALLOC;
}
if (MFX_ERR_NONE == mfx_res)
{
if( VA_FOURCC_P208 != va_fourcc )
{
unsigned int format;
VASurfaceAttrib attrib[2];
int attrCnt = 0;
attrib[attrCnt].type = VASurfaceAttribPixelFormat;
attrib[attrCnt].flags = VA_SURFACE_ATTRIB_SETTABLE;
attrib[attrCnt].value.type = VAGenericValueTypeInteger;
attrib[attrCnt++].value.value.i = va_fourcc;
format = va_fourcc;
if (fourcc == MFX_FOURCC_VP8_NV12)
{
// special configuration for NV12 surf allocation for VP8 hybrid encoder is required
attrib[attrCnt].type = (VASurfaceAttribType)VASurfaceAttribUsageHint;
attrib[attrCnt].flags = VA_SURFACE_ATTRIB_SETTABLE;
attrib[attrCnt].value.type = VAGenericValueTypeInteger;
attrib[attrCnt++].value.value.i = VA_SURFACE_ATTRIB_USAGE_HINT_ENCODER;
}
else if (fourcc == MFX_FOURCC_VP8_MBDATA)
{
// special configuration for MB data surf allocation for VP8 hybrid encoder is required
attrib[0].value.value.i = VA_FOURCC_P208;
format = VA_FOURCC_P208;
}
else if (va_fourcc == VA_FOURCC_NV12)
{
format = VA_RT_FORMAT_YUV420;
}
else if ((va_fourcc == VA_FOURCC_UYVY) || (va_fourcc == VA_FOURCC_YUY2))
{
format = VA_RT_FORMAT_YUV422;
}
else if (fourcc == MFX_FOURCC_A2RGB10)
{
format = VA_RT_FORMAT_RGB32_10BPP;
}
else if (fourcc == MFX_FOURCC_RGBP)
{
format = VA_RT_FORMAT_RGBP;
}
va_res = m_libva->vaCreateSurfaces(m_dpy,
format,
request->Info.Width, request->Info.Height,
surfaces,
surfaces_num,
&attrib[0], attrCnt);
mfx_res = va_to_mfx_status(va_res);
bCreateSrfSucceeded = (MFX_ERR_NONE == mfx_res);
}
else
{
VAContextID context_id = request->AllocId;
int codedbuf_size, codedbuf_num;
VABufferType codedbuf_type;
if (fourcc == MFX_FOURCC_VP8_SEGMAP)
{
codedbuf_size = request->Info.Width;
codedbuf_num = request->Info.Height;
codedbuf_type = VAEncMacroblockMapBufferType;
}
else
{
int width32 = 32 * ((request->Info.Width + 31) >> 5);
int height32 = 32 * ((request->Info.Height + 31) >> 5);
codedbuf_size = static_cast<int>((width32 * height32) * 400LL / (16 * 16));
codedbuf_num = 1;
codedbuf_type = VAEncCodedBufferType;
}
for (numAllocated = 0; numAllocated < surfaces_num; numAllocated++)
{
VABufferID coded_buf;
va_res = m_libva->vaCreateBuffer(m_dpy,
context_id,
codedbuf_type,
codedbuf_size,
codedbuf_num,
NULL,
&coded_buf);
mfx_res = va_to_mfx_status(va_res);
if (MFX_ERR_NONE != mfx_res) break;
surfaces[numAllocated] = coded_buf;
}
}
}
if ((MFX_ERR_NONE == mfx_res) &&
(request->Type & MFX_MEMTYPE_EXPORT_FRAME))
{
if (m_export_mode == vaapiAllocatorParams::DONOT_EXPORT) {
mfx_res = MFX_ERR_UNKNOWN;
}
for (i=0; i < surfaces_num; ++i)
{
if (m_export_mode & vaapiAllocatorParams::NATIVE_EXPORT_MASK) {
vaapi_mids[i].m_buffer_info.mem_type = (m_export_mode & vaapiAllocatorParams::PRIME)?
VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME: VA_SURFACE_ATTRIB_MEM_TYPE_KERNEL_DRM;
va_res = m_libva->vaDeriveImage(m_dpy, surfaces[i], &(vaapi_mids[i].m_image));
mfx_res = va_to_mfx_status(va_res);
if (MFX_ERR_NONE != mfx_res) break;
va_res = m_libva->vaAcquireBufferHandle(m_dpy, vaapi_mids[i].m_image.buf, &(vaapi_mids[i].m_buffer_info));
mfx_res = va_to_mfx_status(va_res);
if (MFX_ERR_NONE != mfx_res) {
m_libva->vaDestroyImage(m_dpy, vaapi_mids[i].m_image.image_id);
break;
}
}
if (m_exporter) {
vaapi_mids[i].m_fourcc = va_fourcc;
vaapi_mids[i].m_custom = m_exporter->acquire(&vaapi_mids[i]);
if (!vaapi_mids[i].m_custom) {
mfx_res = MFX_ERR_UNKNOWN;
break;
}
}
}
}
if (MFX_ERR_NONE == mfx_res)
{
for (i = 0; i < surfaces_num; ++i)
{
vaapi_mid = &(vaapi_mids[i]);
vaapi_mid->m_fourcc = fourcc;
vaapi_mid->m_surface = &(surfaces[i]);
mids[i] = vaapi_mid;
}
}
if (MFX_ERR_NONE == mfx_res)
{
response->mids = mids;
response->NumFrameActual = surfaces_num;
}
else // i.e. MFX_ERR_NONE != mfx_res
{
response->mids = NULL;
response->NumFrameActual = 0;
if (VA_FOURCC_P208 != va_fourcc
|| fourcc == MFX_FOURCC_VP8_MBDATA )
{
if (bCreateSrfSucceeded)
m_libva->vaDestroySurfaces(m_dpy, surfaces, surfaces_num);
}
else
{
for (i = 0; i < numAllocated; i++)
m_libva->vaDestroyBuffer(m_dpy, surfaces[i]);
}
if (mids)
{
free(mids);
mids = NULL;
}
if (vaapi_mids) { free(vaapi_mids); vaapi_mids = NULL; }
if (surfaces) { free(surfaces); surfaces = NULL; }
}
return mfx_res;
}
mfxStatus vaapiFrameAllocator::ReleaseResponse(mfxFrameAllocResponse *response)
{
vaapiMemId *vaapi_mids = NULL;
VASurfaceID* surfaces = NULL;
mfxU32 i = 0;
bool isBitstreamMemory=false;
if (!response) return MFX_ERR_NULL_PTR;
if (response->mids)
{
vaapi_mids = (vaapiMemId*)(response->mids[0]);
mfxU32 mfx_fourcc = ConvertVP8FourccToMfxFourcc(vaapi_mids->m_fourcc);
isBitstreamMemory = (MFX_FOURCC_P8 == mfx_fourcc)?true:false;
surfaces = vaapi_mids->m_surface;
for (i = 0; i < response->NumFrameActual; ++i)
{
if (MFX_FOURCC_P8 == vaapi_mids[i].m_fourcc) m_libva->vaDestroyBuffer(m_dpy, surfaces[i]);
else if (vaapi_mids[i].m_sys_buffer) free(vaapi_mids[i].m_sys_buffer);
if (m_export_mode != vaapiAllocatorParams::DONOT_EXPORT) {
if (m_exporter && vaapi_mids[i].m_custom) {
m_exporter->release(&vaapi_mids[i], vaapi_mids[i].m_custom);
}
if (m_export_mode & vaapiAllocatorParams::NATIVE_EXPORT_MASK) {
m_libva->vaReleaseBufferHandle(m_dpy, vaapi_mids[i].m_image.buf);
m_libva->vaDestroyImage(m_dpy, vaapi_mids[i].m_image.image_id);
}
}
}
free(vaapi_mids);
free(response->mids);
response->mids = NULL;
if (!isBitstreamMemory) m_libva->vaDestroySurfaces(m_dpy, surfaces, response->NumFrameActual);
free(surfaces);
}
response->NumFrameActual = 0;
return MFX_ERR_NONE;
}
mfxStatus vaapiFrameAllocator::LockFrame(mfxMemId mid, mfxFrameData *ptr)
{
mfxStatus mfx_res = MFX_ERR_NONE;
VAStatus va_res = VA_STATUS_SUCCESS;
vaapiMemId* vaapi_mid = (vaapiMemId*)mid;
mfxU8* pBuffer = 0;
if (!vaapi_mid || !(vaapi_mid->m_surface)) return MFX_ERR_INVALID_HANDLE;
mfxU32 mfx_fourcc = ConvertVP8FourccToMfxFourcc(vaapi_mid->m_fourcc);
if (MFX_FOURCC_P8 == mfx_fourcc) // bitstream processing
{
VACodedBufferSegment *coded_buffer_segment;
if (vaapi_mid->m_fourcc == MFX_FOURCC_VP8_SEGMAP)
va_res = m_libva->vaMapBuffer(m_dpy, *(vaapi_mid->m_surface), (void **)(&pBuffer));
else
va_res = m_libva->vaMapBuffer(m_dpy, *(vaapi_mid->m_surface), (void **)(&coded_buffer_segment));
mfx_res = va_to_mfx_status(va_res);
if (MFX_ERR_NONE == mfx_res)
{
if (vaapi_mid->m_fourcc == MFX_FOURCC_VP8_SEGMAP)
ptr->Y = pBuffer;
else
ptr->Y = (mfxU8*)coded_buffer_segment->buf;
}
}
else // Image processing
{
va_res = m_libva->vaDeriveImage(m_dpy, *(vaapi_mid->m_surface), &(vaapi_mid->m_image));
mfx_res = va_to_mfx_status(va_res);
if (MFX_ERR_NONE == mfx_res)
{
va_res = m_libva->vaMapBuffer(m_dpy, vaapi_mid->m_image.buf, (void **)&pBuffer);
mfx_res = va_to_mfx_status(va_res);
}
if (MFX_ERR_NONE == mfx_res)
{
switch (vaapi_mid->m_image.format.fourcc)
{
case VA_FOURCC_NV12:
if (mfx_fourcc != vaapi_mid->m_image.format.fourcc) return MFX_ERR_LOCK_MEMORY;
{
ptr->Y = pBuffer + vaapi_mid->m_image.offsets[0];
ptr->U = pBuffer + vaapi_mid->m_image.offsets[1];
ptr->V = ptr->U + 1;
}
break;
case VA_FOURCC_YV12:
if (mfx_fourcc != vaapi_mid->m_image.format.fourcc) return MFX_ERR_LOCK_MEMORY;
{
ptr->Y = pBuffer + vaapi_mid->m_image.offsets[0];
ptr->V = pBuffer + vaapi_mid->m_image.offsets[1];
ptr->U = pBuffer + vaapi_mid->m_image.offsets[2];
}
break;
case VA_FOURCC_YUY2:
if (mfx_fourcc != vaapi_mid->m_image.format.fourcc) return MFX_ERR_LOCK_MEMORY;
{
ptr->Y = pBuffer + vaapi_mid->m_image.offsets[0];
ptr->U = ptr->Y + 1;
ptr->V = ptr->Y + 3;
}
break;
case VA_FOURCC_UYVY:
if (mfx_fourcc != vaapi_mid->m_image.format.fourcc) return MFX_ERR_LOCK_MEMORY;
{
ptr->U = pBuffer + vaapi_mid->m_image.offsets[0];
ptr->Y = ptr->U + 1;
ptr->V = ptr->U + 2;
}
break;
#if (MFX_VERSION >= 1028)
case VA_FOURCC_RGB565:
if (mfx_fourcc == MFX_FOURCC_RGB565)
{
ptr->B = pBuffer + vaapi_mid->m_image.offsets[0];
ptr->G = ptr->B;
ptr->R = ptr->B;
}
else return MFX_ERR_LOCK_MEMORY;
break;
#endif
case VA_FOURCC_ARGB:
if (mfx_fourcc == MFX_FOURCC_RGB4)
{
ptr->B = pBuffer + vaapi_mid->m_image.offsets[0];
ptr->G = ptr->B + 1;
ptr->R = ptr->B + 2;
ptr->A = ptr->B + 3;
}
else return MFX_ERR_LOCK_MEMORY;
break;
#ifndef ANDROID
case VA_FOURCC_A2R10G10B10:
if (mfx_fourcc == MFX_FOURCC_A2RGB10)
{
ptr->B = pBuffer + vaapi_mid->m_image.offsets[0];
ptr->G = ptr->B;
ptr->R = ptr->B;
ptr->A = ptr->B;
}
else return MFX_ERR_LOCK_MEMORY;
break;
#endif
case VA_FOURCC_ABGR:
if (mfx_fourcc == MFX_FOURCC_BGR4)
{
ptr->R = pBuffer + vaapi_mid->m_image.offsets[0];
ptr->G = pBuffer + vaapi_mid->m_image.offsets[1];
ptr->B = pBuffer + vaapi_mid->m_image.offsets[2];
ptr->A = ptr->R + 3;
}
else return MFX_ERR_LOCK_MEMORY;
break;
case VA_FOURCC_RGBP:
if (mfx_fourcc != vaapi_mid->m_image.format.fourcc) return MFX_ERR_LOCK_MEMORY;
{
ptr->B = pBuffer + vaapi_mid->m_image.offsets[0];
ptr->G = pBuffer + vaapi_mid->m_image.offsets[1];
ptr->R = pBuffer + vaapi_mid->m_image.offsets[2];
}
break;
case VA_FOURCC_P208:
if (mfx_fourcc == MFX_FOURCC_NV12)
{
ptr->Y = pBuffer + vaapi_mid->m_image.offsets[0];
}
else return MFX_ERR_LOCK_MEMORY;
break;
case VA_FOURCC_P010:
#if (MFX_VERSION >= 1031)
case VA_FOURCC_P016:
#endif
if (mfx_fourcc != vaapi_mid->m_image.format.fourcc) return MFX_ERR_LOCK_MEMORY;
{
ptr->Y16 = (mfxU16 *) (pBuffer + vaapi_mid->m_image.offsets[0]);
ptr->U16 = (mfxU16 *) (pBuffer + vaapi_mid->m_image.offsets[1]);
ptr->V16 = ptr->U16 + 1;
}
break;
case VA_FOURCC_AYUV:
if (mfx_fourcc != vaapi_mid->m_image.format.fourcc) return MFX_ERR_LOCK_MEMORY;
{
ptr->V = pBuffer + vaapi_mid->m_image.offsets[0];
ptr->U = ptr->V + 1;
ptr->Y = ptr->V + 2;
ptr->A = ptr->V + 3;
}
break;
#if (MFX_VERSION >= 1027)
case VA_FOURCC_Y210:
#if (MFX_VERSION >= 1031)
case VA_FOURCC_Y216:
#endif
if (mfx_fourcc != vaapi_mid->m_image.format.fourcc) return MFX_ERR_LOCK_MEMORY;
{
ptr->Y16 = (mfxU16 *) (pBuffer + vaapi_mid->m_image.offsets[0]);
ptr->U16 = ptr->Y16 + 1;
ptr->V16 = ptr->Y16 + 3;
}
break;
case VA_FOURCC_Y410:
if (mfx_fourcc != vaapi_mid->m_image.format.fourcc) return MFX_ERR_LOCK_MEMORY;
{
ptr->Y410 = (mfxY410 *)(pBuffer + vaapi_mid->m_image.offsets[0]);
ptr->Y = 0;
ptr->V = 0;
ptr->A = 0;
}
break;
#endif
#if (MFX_VERSION >= 1031)
case VA_FOURCC_Y416:
if (mfx_fourcc != vaapi_mid->m_image.format.fourcc) return MFX_ERR_LOCK_MEMORY;
{
ptr->U16 = (mfxU16 *) (pBuffer + vaapi_mid->m_image.offsets[0]);
ptr->Y16 = ptr->U16 + 1;
ptr->V16 = ptr->Y16 + 1;
ptr->A = (mfxU8 *)(ptr->V16 + 1);
}
break;
#endif
default:
return MFX_ERR_LOCK_MEMORY;
}
}
ptr->PitchHigh = (mfxU16)(vaapi_mid->m_image.pitches[0] / (1 << 16));
ptr->PitchLow = (mfxU16)(vaapi_mid->m_image.pitches[0] % (1 << 16));
}
return mfx_res;
}
mfxStatus vaapiFrameAllocator::UnlockFrame(mfxMemId mid, mfxFrameData *ptr)
{
vaapiMemId* vaapi_mid = (vaapiMemId*)mid;
if (!vaapi_mid || !(vaapi_mid->m_surface)) return MFX_ERR_INVALID_HANDLE;
mfxU32 mfx_fourcc = ConvertVP8FourccToMfxFourcc(vaapi_mid->m_fourcc);
if (MFX_FOURCC_P8 == mfx_fourcc) // bitstream processing
{
m_libva->vaUnmapBuffer(m_dpy, *(vaapi_mid->m_surface));
}
else // Image processing
{
m_libva->vaUnmapBuffer(m_dpy, vaapi_mid->m_image.buf);
m_libva->vaDestroyImage(m_dpy, vaapi_mid->m_image.image_id);
if (NULL != ptr)
{
ptr->PitchLow = 0;
ptr->PitchHigh = 0;
ptr->Y = NULL;
ptr->U = NULL;
ptr->V = NULL;
ptr->A = NULL;
}
}
return MFX_ERR_NONE;
}
mfxStatus vaapiFrameAllocator::GetFrameHDL(mfxMemId mid, mfxHDL *handle)
{
vaapiMemId* vaapi_mid = (vaapiMemId*)mid;
if (!handle || !vaapi_mid || !(vaapi_mid->m_surface)) return MFX_ERR_INVALID_HANDLE;
*handle = vaapi_mid->m_surface; //VASurfaceID* <-> mfxHDL
return MFX_ERR_NONE;
}
#endif // #if defined(LIBVA_SUPPORT)

View File

@@ -0,0 +1,538 @@
/******************************************************************************\
Copyright (c) 2005-2019, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
This sample was distributed or derived from the Intel's Media Samples package.
The original version of this sample may be obtained from https://software.intel.com/en-us/intel-media-server-studio
or https://software.intel.com/en-us/media-client-solutions-support.
\**********************************************************************************/
#if defined(LIBVA_DRM_SUPPORT) || defined(LIBVA_X11_SUPPORT) || defined(LIBVA_ANDROID_SUPPORT)
#include "vaapi_device.h"
#if defined(LIBVA_WAYLAND_SUPPORT)
#include "class_wayland.h"
#endif
#if defined(LIBVA_X11_SUPPORT)
#include <va/va_x11.h>
#include <X11/Xlib.h>
#include "vaapi_allocator.h"
#if defined(X11_DRI3_SUPPORT)
#include <fcntl.h>
#define ALIGN(x, y) (((x) + (y) - 1) & -(y))
#define PAGE_ALIGN(x) ALIGN(x, 4096)
#endif // X11_DRI3_SUPPORT
#define VAAPI_GET_X_DISPLAY(_display) (Display*)(_display)
#define VAAPI_GET_X_WINDOW(_window) (Window*)(_window)
CVAAPIDeviceX11::~CVAAPIDeviceX11(void)
{
Close();
}
mfxStatus CVAAPIDeviceX11::Init(mfxHDL hWindow, mfxU16 nViews, mfxU32 nAdapterNum)
{
mfxStatus mfx_res = MFX_ERR_NONE;
Window* window = NULL;
if (nViews)
{
if (MFX_ERR_NONE == mfx_res)
{
m_window = window = (Window*)malloc(sizeof(Window));
if (!m_window) mfx_res = MFX_ERR_MEMORY_ALLOC;
}
if (MFX_ERR_NONE == mfx_res)
{
Display* display = VAAPI_GET_X_DISPLAY(m_X11LibVA.GetXDisplay());
MfxLoader::XLib_Proxy & x11lib = m_X11LibVA.GetX11();
mfxU32 screen_number = DefaultScreen(display);
*window = x11lib.XCreateSimpleWindow(
display,
RootWindow(display, screen_number),
m_bRenderWin ? m_nRenderWinX : 0,
m_bRenderWin ? m_nRenderWinY : 0,
100,
100,
0,
0,
BlackPixel(display, screen_number));
if (!(*window)) mfx_res = MFX_ERR_UNKNOWN;
else
{
x11lib.XMapWindow(display, *window);
x11lib.XSync(display, False);
}
}
}
#if defined(X11_DRI3_SUPPORT)
MfxLoader::DrmIntel_Proxy & drmintellib = m_X11LibVA.GetDrmIntelX11();
MfxLoader::X11_Xcb_Proxy & x11xcblib = m_X11LibVA.GetX11XcbX11();
m_xcbconn = x11xcblib.XGetXCBConnection(VAAPI_GET_X_DISPLAY(m_X11LibVA.GetXDisplay()));
// it's enough to pass render node, because we only request
// information from kernel via m_dri_fd
m_dri_fd = open("/dev/dri/renderD128", O_RDWR);
if (m_dri_fd < 0) {
msdk_printf(MSDK_STRING("Failed to open dri device\n"));
return MFX_ERR_NOT_INITIALIZED;
}
m_bufmgr = drmintellib.drm_intel_bufmgr_gem_init(m_dri_fd, 4096);
if (!m_bufmgr){
msdk_printf(MSDK_STRING("Failed to get buffer manager\n"));
return MFX_ERR_NOT_INITIALIZED;
}
#endif
return mfx_res;
}
void CVAAPIDeviceX11::Close(void)
{
if (m_window)
{
Display* display = VAAPI_GET_X_DISPLAY(m_X11LibVA.GetXDisplay());
Window* window = VAAPI_GET_X_WINDOW(m_window);
MfxLoader::XLib_Proxy & x11lib = m_X11LibVA.GetX11();
x11lib.XDestroyWindow(display, *window);
free(m_window);
m_window = NULL;
}
#if defined(X11_DRI3_SUPPORT)
if (m_dri_fd)
{
close(m_dri_fd);
}
#endif
}
mfxStatus CVAAPIDeviceX11::Reset(void)
{
return MFX_ERR_NONE;
}
mfxStatus CVAAPIDeviceX11::GetHandle(mfxHandleType type, mfxHDL *pHdl)
{
if ((MFX_HANDLE_VA_DISPLAY == type) && (NULL != pHdl))
{
*pHdl = m_X11LibVA.GetVADisplay();
return MFX_ERR_NONE;
}
return MFX_ERR_UNSUPPORTED;
}
mfxStatus CVAAPIDeviceX11::SetHandle(mfxHandleType type, mfxHDL hdl)
{
return MFX_ERR_UNSUPPORTED;
}
mfxStatus CVAAPIDeviceX11::RenderFrame(mfxFrameSurface1 * pSurface, mfxFrameAllocator * /*pmfxAlloc*/)
{
mfxStatus mfx_res = MFX_ERR_NONE;
vaapiMemId * memId = NULL;
#if !defined(X11_DRI3_SUPPORT)
VAStatus va_res = VA_STATUS_SUCCESS;
VASurfaceID surface;
Display* display = VAAPI_GET_X_DISPLAY(m_X11LibVA.GetXDisplay());
Window* window = VAAPI_GET_X_WINDOW(m_window);
if(!window || !(*window)) mfx_res = MFX_ERR_NOT_INITIALIZED;
// should MFX_ERR_NONE be returned below considering situation as EOS?
if ((MFX_ERR_NONE == mfx_res) && NULL == pSurface) mfx_res = MFX_ERR_NULL_PTR;
if (MFX_ERR_NONE == mfx_res)
{
memId = (vaapiMemId*)(pSurface->Data.MemId);
if (!memId || !memId->m_surface) mfx_res = MFX_ERR_NULL_PTR;
}
if (MFX_ERR_NONE == mfx_res)
{
VADisplay dpy = m_X11LibVA.GetVADisplay();
VADisplay rnddpy = m_X11LibVA.GetVADisplay();
VASurfaceID rndsrf;
void* ctx;
surface = *memId->m_surface;
va_res = m_X11LibVA.AcquireVASurface(&ctx, dpy, surface, rnddpy, &rndsrf);
mfx_res = va_to_mfx_status(va_res);
if (MFX_ERR_NONE != mfx_res) return mfx_res;
MfxLoader::XLib_Proxy & x11lib = m_X11LibVA.GetX11();
x11lib.XResizeWindow(display, *window, pSurface->Info.CropW, pSurface->Info.CropH);
MfxLoader::VA_X11Proxy & vax11lib = m_X11LibVA.GetVAX11();
va_res = vax11lib.vaPutSurface(rnddpy,
rndsrf,
*window,
pSurface->Info.CropX,
pSurface->Info.CropY,
pSurface->Info.CropX + pSurface->Info.CropW,
pSurface->Info.CropY + pSurface->Info.CropH,
pSurface->Info.CropX,
pSurface->Info.CropY,
pSurface->Info.CropX + pSurface->Info.CropW,
pSurface->Info.CropY + pSurface->Info.CropH,
NULL,
0,
VA_FRAME_PICTURE);
mfx_res = va_to_mfx_status(va_res);
x11lib.XSync(display, False);
m_X11LibVA.ReleaseVASurface(ctx, dpy, surface, rnddpy, rndsrf);
}
return mfx_res;
#else //\/ X11_DRI3_SUPPORT
Window* window = VAAPI_GET_X_WINDOW(m_window);
Window root;
drm_intel_bo *bo = NULL;
unsigned int border, depth, stride, size,
width, height;
int fd = 0, bpp = 0, x, y;
MfxLoader::Xcb_Proxy & xcblib = m_X11LibVA.GetXcbX11();
MfxLoader::XLib_Proxy & x11lib = m_X11LibVA.GetX11();
MfxLoader::DrmIntel_Proxy & drmintellib = m_X11LibVA.GetDrmIntelX11();
MfxLoader::Xcbpresent_Proxy & xcbpresentlib = m_X11LibVA.GetXcbpresentX11();
MfxLoader::XCB_Dri3_Proxy & dri3lib= m_X11LibVA.GetXCBDri3X11();
if(!window || !(*window)) mfx_res = MFX_ERR_NOT_INITIALIZED;
// should MFX_ERR_NONE be returned below considering situation as EOS?
if ((MFX_ERR_NONE == mfx_res) && NULL == pSurface) mfx_res = MFX_ERR_NULL_PTR;
if (MFX_ERR_NONE == mfx_res)
{
memId = (vaapiMemId*)(pSurface->Data.MemId);
if (!memId || !memId->m_surface) mfx_res = MFX_ERR_NULL_PTR;
}
if(memId && memId->m_buffer_info.mem_type != VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME){
msdk_printf(MSDK_STRING("Memory type invalid!\n"));
return MFX_ERR_UNSUPPORTED;
}
if (MFX_ERR_NONE == mfx_res)
{
x11lib.XResizeWindow(VAAPI_GET_X_DISPLAY(m_X11LibVA.GetXDisplay()),
*window, pSurface->Info.CropW, pSurface->Info.CropH);
x11lib.XGetGeometry(VAAPI_GET_X_DISPLAY(m_X11LibVA.GetXDisplay()),
*window, &root, &x, &y, &width, &height, &border, &depth);
switch (depth) {
case 8: bpp = 8; break;
case 15: case 16: bpp = 16; break;
case 24: case 32: bpp = 32; break;
default: msdk_printf(MSDK_STRING("Invalid depth\n"));
}
width = pSurface->Info.CropX + pSurface->Info.CropW;
height = pSurface->Info.CropY + pSurface->Info.CropH;
stride = width * bpp/8;
size = PAGE_ALIGN(stride * height);
bo = drmintellib.drm_intel_bo_gem_create_from_prime(m_bufmgr, memId->m_buffer_info.handle, size);
if (!bo) {
msdk_printf(MSDK_STRING("Failed to create buffer object\n"));
return MFX_ERR_MEMORY_ALLOC;
}
drmintellib.drm_intel_bo_gem_export_to_prime(bo, &fd);
if (!fd) {
msdk_printf(MSDK_STRING("Invalid fd\n"));
return MFX_ERR_INVALID_HANDLE;
}
xcb_pixmap_t pixmap = xcblib.xcb_generate_id(m_xcbconn);
xcb_void_cookie_t cookie;
xcb_generic_error_t *error;
cookie = dri3lib.xcb_dri3_pixmap_from_buffer_checked(m_xcbconn, pixmap, root, size, width, height, stride, depth, bpp, fd);
if ((error = xcblib.xcb_request_check(m_xcbconn, cookie))) {
msdk_printf(MSDK_STRING("Failed to create xcb pixmap from the %s surface: try another color format (e.g. RGB4)\n"),
ColorFormatToStr(pSurface->Info.FourCC));
free(error);
return MFX_ERR_INVALID_HANDLE;
}
cookie = xcbpresentlib.xcb_present_pixmap_checked(m_xcbconn,
*window, pixmap,
0,
0,
0,
0,
0,
None,
None,
None,
XCB_PRESENT_OPTION_NONE,
0,
0,
0,
0, NULL);
if ((error = xcblib.xcb_request_check(m_xcbconn, cookie))) {
msdk_printf(MSDK_STRING("Failed to present pixmap\n"));
free(error);
return MFX_ERR_UNKNOWN;
}
xcblib.xcb_free_pixmap(m_xcbconn, pixmap);
xcblib.xcb_flush(m_xcbconn);
}
return mfx_res;
#endif // X11_DRI3_SUPPORT
}
#endif
#if defined(LIBVA_WAYLAND_SUPPORT)
#include "wayland-drm-client-protocol.h"
CVAAPIDeviceWayland::~CVAAPIDeviceWayland(void)
{
Close();
}
mfxStatus CVAAPIDeviceWayland::Init(mfxHDL hWindow, mfxU16 nViews, mfxU32 nAdapterNum)
{
mfxStatus mfx_res = MFX_ERR_NONE;
if(nViews)
{
m_Wayland = (Wayland*)m_WaylandClient.WaylandCreate();
if(!m_Wayland->InitDisplay()) {
return MFX_ERR_DEVICE_FAILED;
}
if(NULL == m_Wayland->GetDisplay())
{
mfx_res = MFX_ERR_UNKNOWN;
return mfx_res;
}
if(-1 == m_Wayland->DisplayRoundtrip())
{
mfx_res = MFX_ERR_UNKNOWN;
return mfx_res;
}
if(!m_Wayland->CreateSurface())
{
mfx_res = MFX_ERR_UNKNOWN;
return mfx_res;
}
}
return mfx_res;
}
mfxStatus CVAAPIDeviceWayland::RenderFrame(mfxFrameSurface1 * pSurface, mfxFrameAllocator * /*pmfxAlloc*/)
{
uint32_t drm_format = 0;
int offsets[3], pitches[3];
mfxStatus mfx_res = MFX_ERR_NONE;
vaapiMemId * memId = NULL;
struct wl_buffer *m_wl_buffer = NULL;
if(NULL==pSurface) {
mfx_res = MFX_ERR_UNKNOWN;
return mfx_res;
}
m_Wayland->Sync();
memId = (vaapiMemId*)(pSurface->Data.MemId);
if (pSurface->Info.FourCC == MFX_FOURCC_NV12)
{
drm_format = WL_DRM_FORMAT_NV12;
} else if(pSurface->Info.FourCC == MFX_FOURCC_RGB4)
{
drm_format = WL_DRM_FORMAT_ARGB8888;
if (m_isMondelloInputEnabled)
{
drm_format = WL_DRM_FORMAT_XBGR8888;
}
}
offsets[0] = memId->m_image.offsets[0];
offsets[1] = memId->m_image.offsets[1];
offsets[2] = memId->m_image.offsets[2];
pitches[0] = memId->m_image.pitches[0];
pitches[1] = memId->m_image.pitches[1];
pitches[2] = memId->m_image.pitches[2];
m_wl_buffer = m_Wayland->CreatePrimeBuffer(memId->m_buffer_info.handle
, pSurface->Info.CropW
, pSurface->Info.CropH
, drm_format
, offsets
, pitches);
if(NULL == m_wl_buffer)
{
msdk_printf("\nCan't wrap flink to wl_buffer\n");
mfx_res = MFX_ERR_UNKNOWN;
return mfx_res;
}
m_Wayland->RenderBuffer(m_wl_buffer, pSurface);
return mfx_res;
}
void CVAAPIDeviceWayland::Close(void)
{
m_Wayland->FreeSurface();
}
CHWDevice* CreateVAAPIDevice(void)
{
return new CVAAPIDeviceWayland();
}
#endif // LIBVA_WAYLAND_SUPPORT
#if defined(LIBVA_DRM_SUPPORT)
CVAAPIDeviceDRM::CVAAPIDeviceDRM(const std::string& devicePath, int type)
: m_DRMLibVA(devicePath, type)
, m_rndr(NULL)
{
}
CVAAPIDeviceDRM::~CVAAPIDeviceDRM(void)
{
MSDK_SAFE_DELETE(m_rndr);
}
mfxStatus CVAAPIDeviceDRM::Init(mfxHDL hWindow, mfxU16 nViews, mfxU32 nAdapterNum)
{
if (0 == nViews) {
return MFX_ERR_NONE;
}
if (1 == nViews) {
if (m_DRMLibVA.getBackendType() == MFX_LIBVA_DRM_RENDERNODE) {
return MFX_ERR_NONE;
}
mfxI32 * monitorType = (mfxI32*)hWindow;
if (!monitorType) return MFX_ERR_INVALID_VIDEO_PARAM;
try {
m_rndr = new drmRenderer(m_DRMLibVA.getFD(), *monitorType);
} catch(...) {
msdk_printf(MSDK_STRING("vaapi_device: failed to initialize drmrender\n"));
return MFX_ERR_UNKNOWN;
}
return MFX_ERR_NONE;
}
return MFX_ERR_UNSUPPORTED;
}
mfxStatus CVAAPIDeviceDRM::RenderFrame(mfxFrameSurface1 * pSurface, mfxFrameAllocator * pmfxAlloc)
{
return (m_rndr)? m_rndr->render(pSurface): MFX_ERR_NONE;
}
#endif
#if defined(LIBVA_DRM_SUPPORT) || defined(LIBVA_X11_SUPPORT) || defined (LIBVA_WAYLAND_SUPPORT)
CHWDevice* CreateVAAPIDevice(const std::string& devicePath, int type)
{
CHWDevice * device = NULL;
switch (type)
{
case MFX_LIBVA_DRM_RENDERNODE:
case MFX_LIBVA_DRM_MODESET:
#if defined(LIBVA_DRM_SUPPORT)
try
{
device = new CVAAPIDeviceDRM(devicePath, type);
}
catch (std::exception&)
{
device = NULL;
}
#endif
break;
case MFX_LIBVA_X11:
#if defined(LIBVA_X11_SUPPORT)
try
{
device = new CVAAPIDeviceX11;
}
catch (std::exception&)
{
device = NULL;
}
#endif
break;
case MFX_LIBVA_WAYLAND:
#if defined(LIBVA_WAYLAND_SUPPORT)
device = new CVAAPIDeviceWayland;
#endif
break;
case MFX_LIBVA_AUTO:
#if defined(LIBVA_X11_SUPPORT)
try
{
device = new CVAAPIDeviceX11;
}
catch (std::exception&)
{
device = NULL;
}
#endif
#if defined(LIBVA_DRM_SUPPORT)
if (!device)
{
try
{
device = new CVAAPIDeviceDRM(devicePath, type);
}
catch (std::exception&)
{
device = NULL;
}
}
#endif
break;
} // switch(type)
return device;
}
#elif defined(LIBVA_ANDROID_SUPPORT)
static AndroidLibVA g_LibVA;
CHWDevice* CreateVAAPIDevice(const std::string& devicePath, int type)
{
return new CVAAPIDeviceAndroid(&g_LibVA);
}
#endif
#endif //#if defined(LIBVA_DRM_SUPPORT) || defined(LIBVA_X11_SUPPORT) || defined(LIBVA_ANDROID_SUPPORT)

View File

@@ -0,0 +1,462 @@
/******************************************************************************\
Copyright (c) 2005-2019, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
This sample was distributed or derived from the Intel's Media Samples package.
The original version of this sample may be obtained from https://software.intel.com/en-us/intel-media-server-studio
or https://software.intel.com/en-us/media-client-solutions-support.
\**********************************************************************************/
#ifdef LIBVA_SUPPORT
#include "vaapi_utils.h"
#include <dlfcn.h>
#include <stdexcept>
//#if defined(LIBVA_DRM_SUPPORT)
#include "vaapi_utils_drm.h"
//#elif defined(LIBVA_X11_SUPPORT)
#include "vaapi_utils_x11.h"
//#endif
#if defined(LIBVA_WAYLAND_SUPPORT)
#include "class_wayland.h"
#endif
namespace MfxLoader
{
SimpleLoader::SimpleLoader(const char * name)
{
dlerror();
so_handle = dlopen(name, RTLD_GLOBAL | RTLD_NOW);
if (NULL == so_handle)
{
std::cerr << dlerror() << std::endl;
throw std::runtime_error("Can't load library");
}
}
void * SimpleLoader::GetFunction(const char * name)
{
void * fn_ptr = dlsym(so_handle, name);
if (!fn_ptr)
throw std::runtime_error("Can't find function");
return fn_ptr;
}
SimpleLoader::~SimpleLoader()
{
dlclose(so_handle);
}
#define SIMPLE_LOADER_STRINGIFY1( x) #x
#define SIMPLE_LOADER_STRINGIFY(x) SIMPLE_LOADER_STRINGIFY1(x)
#define SIMPLE_LOADER_DECORATOR1(fun,suffix) fun ## _ ## suffix
#define SIMPLE_LOADER_DECORATOR(fun,suffix) SIMPLE_LOADER_DECORATOR1(fun,suffix)
// Following macro applied on vaInitialize will give: vaInitialize((vaInitialize_type)lib.GetFunction("vaInitialize"))
#define SIMPLE_LOADER_FUNCTION(name) name( (SIMPLE_LOADER_DECORATOR(name, type)) lib.GetFunction(SIMPLE_LOADER_STRINGIFY(name)) )
#if defined(LIBVA_SUPPORT)
VA_Proxy::VA_Proxy()
#ifdef ANDROID
: lib("libva-android.so")
#else
: lib("libva.so.2")
#endif
, SIMPLE_LOADER_FUNCTION(vaInitialize)
, SIMPLE_LOADER_FUNCTION(vaTerminate)
, SIMPLE_LOADER_FUNCTION(vaCreateSurfaces)
, SIMPLE_LOADER_FUNCTION(vaDestroySurfaces)
, SIMPLE_LOADER_FUNCTION(vaCreateBuffer)
, SIMPLE_LOADER_FUNCTION(vaDestroyBuffer)
, SIMPLE_LOADER_FUNCTION(vaMapBuffer)
, SIMPLE_LOADER_FUNCTION(vaUnmapBuffer)
, SIMPLE_LOADER_FUNCTION(vaSyncSurface)
, SIMPLE_LOADER_FUNCTION(vaDeriveImage)
, SIMPLE_LOADER_FUNCTION(vaDestroyImage)
, SIMPLE_LOADER_FUNCTION(vaGetLibFunc)
, SIMPLE_LOADER_FUNCTION(vaAcquireBufferHandle)
, SIMPLE_LOADER_FUNCTION(vaReleaseBufferHandle)
, SIMPLE_LOADER_FUNCTION(vaMaxNumEntrypoints)
, SIMPLE_LOADER_FUNCTION(vaQueryConfigEntrypoints)
, SIMPLE_LOADER_FUNCTION(vaGetConfigAttributes)
, SIMPLE_LOADER_FUNCTION(vaCreateConfig)
, SIMPLE_LOADER_FUNCTION(vaCreateContext)
, SIMPLE_LOADER_FUNCTION(vaDestroyConfig)
, SIMPLE_LOADER_FUNCTION(vaDestroyContext)
{
}
VA_Proxy::~VA_Proxy()
{}
#endif
#if defined(LIBVA_DRM_SUPPORT)
DRM_Proxy::DRM_Proxy()
: lib("libdrm.so.2")
, SIMPLE_LOADER_FUNCTION(drmIoctl)
, SIMPLE_LOADER_FUNCTION(drmModeAddFB)
, SIMPLE_LOADER_FUNCTION(drmModeAddFB2WithModifiers)
, SIMPLE_LOADER_FUNCTION(drmModeFreeConnector)
, SIMPLE_LOADER_FUNCTION(drmModeFreeCrtc)
, SIMPLE_LOADER_FUNCTION(drmModeFreeEncoder)
, SIMPLE_LOADER_FUNCTION(drmModeFreePlane)
, SIMPLE_LOADER_FUNCTION(drmModeFreePlaneResources)
, SIMPLE_LOADER_FUNCTION(drmModeFreeResources)
, SIMPLE_LOADER_FUNCTION(drmModeGetConnector)
, SIMPLE_LOADER_FUNCTION(drmModeGetCrtc)
, SIMPLE_LOADER_FUNCTION(drmModeGetEncoder)
, SIMPLE_LOADER_FUNCTION(drmModeGetPlane)
, SIMPLE_LOADER_FUNCTION(drmModeGetPlaneResources)
, SIMPLE_LOADER_FUNCTION(drmModeGetResources)
, SIMPLE_LOADER_FUNCTION(drmModeRmFB)
, SIMPLE_LOADER_FUNCTION(drmModeSetCrtc)
, SIMPLE_LOADER_FUNCTION(drmSetMaster)
, SIMPLE_LOADER_FUNCTION(drmDropMaster)
, SIMPLE_LOADER_FUNCTION(drmModeSetPlane)
{
}
DrmIntel_Proxy::~DrmIntel_Proxy()
{}
DrmIntel_Proxy::DrmIntel_Proxy()
: lib("libdrm_intel.so.1")
, SIMPLE_LOADER_FUNCTION(drm_intel_bo_gem_create_from_prime)
, SIMPLE_LOADER_FUNCTION(drm_intel_bo_unreference)
, SIMPLE_LOADER_FUNCTION(drm_intel_bufmgr_gem_init)
, SIMPLE_LOADER_FUNCTION(drm_intel_bufmgr_destroy)
#if defined(X11_DRI3_SUPPORT)
, SIMPLE_LOADER_FUNCTION(drm_intel_bo_gem_export_to_prime)
#endif
{
}
DRM_Proxy::~DRM_Proxy()
{}
VA_DRMProxy::VA_DRMProxy()
: lib("libva-drm.so.2")
, SIMPLE_LOADER_FUNCTION(vaGetDisplayDRM)
{
}
VA_DRMProxy::~VA_DRMProxy()
{}
#if defined(X11_DRI3_SUPPORT)
XCB_Dri3_Proxy::XCB_Dri3_Proxy()
: lib("libxcb-dri3.so.0")
, SIMPLE_LOADER_FUNCTION(xcb_dri3_pixmap_from_buffer_checked)
{
}
XCB_Dri3_Proxy::~XCB_Dri3_Proxy()
{}
Xcb_Proxy::Xcb_Proxy()
: lib("libxcb.so.1")
, SIMPLE_LOADER_FUNCTION(xcb_generate_id)
, SIMPLE_LOADER_FUNCTION(xcb_free_pixmap)
, SIMPLE_LOADER_FUNCTION(xcb_flush)
, SIMPLE_LOADER_FUNCTION(xcb_request_check)
{
}
Xcb_Proxy::~Xcb_Proxy()
{}
X11_Xcb_Proxy::X11_Xcb_Proxy()
: lib("libX11-xcb.so.1")
, SIMPLE_LOADER_FUNCTION(XGetXCBConnection)
{
}
X11_Xcb_Proxy::~X11_Xcb_Proxy()
{}
Xcbpresent_Proxy::Xcbpresent_Proxy()
: lib("libxcb-present.so.0")
, SIMPLE_LOADER_FUNCTION(xcb_present_pixmap_checked)
{
}
Xcbpresent_Proxy::~Xcbpresent_Proxy()
{}
#endif // X11_DRI3_SUPPORT
#endif
#if defined(LIBVA_WAYLAND_SUPPORT)
VA_WaylandClientProxy::VA_WaylandClientProxy()
: lib("libmfx_wayland.so")
, SIMPLE_LOADER_FUNCTION(WaylandCreate)
{
}
VA_WaylandClientProxy::~VA_WaylandClientProxy()
{}
#endif // LIBVA_WAYLAND_SUPPORT
#if defined(LIBVA_X11_SUPPORT)
VA_X11Proxy::VA_X11Proxy()
: lib("libva-x11.so.2")
, SIMPLE_LOADER_FUNCTION(vaGetDisplay)
, SIMPLE_LOADER_FUNCTION(vaPutSurface)
{
}
VA_X11Proxy::~VA_X11Proxy()
{}
XLib_Proxy::XLib_Proxy()
: lib("libX11.so.6")
, SIMPLE_LOADER_FUNCTION(XOpenDisplay)
, SIMPLE_LOADER_FUNCTION(XCloseDisplay)
, SIMPLE_LOADER_FUNCTION(XCreateSimpleWindow)
, SIMPLE_LOADER_FUNCTION(XMapWindow)
, SIMPLE_LOADER_FUNCTION(XSync)
, SIMPLE_LOADER_FUNCTION(XDestroyWindow)
, SIMPLE_LOADER_FUNCTION(XResizeWindow)
#if defined(X11_DRI3_SUPPORT)
, SIMPLE_LOADER_FUNCTION(XGetGeometry)
#endif // X11_DRI3_SUPPORT
{}
XLib_Proxy::~XLib_Proxy()
{}
#endif
#undef SIMPLE_LOADER_FUNCTION
} // MfxLoader
mfxStatus va_to_mfx_status(VAStatus va_res)
{
mfxStatus mfxRes = MFX_ERR_NONE;
switch (va_res)
{
case VA_STATUS_SUCCESS:
mfxRes = MFX_ERR_NONE;
break;
case VA_STATUS_ERROR_ALLOCATION_FAILED:
mfxRes = MFX_ERR_MEMORY_ALLOC;
break;
case VA_STATUS_ERROR_ATTR_NOT_SUPPORTED:
case VA_STATUS_ERROR_UNSUPPORTED_PROFILE:
case VA_STATUS_ERROR_UNSUPPORTED_ENTRYPOINT:
case VA_STATUS_ERROR_UNSUPPORTED_RT_FORMAT:
case VA_STATUS_ERROR_UNSUPPORTED_BUFFERTYPE:
case VA_STATUS_ERROR_FLAG_NOT_SUPPORTED:
case VA_STATUS_ERROR_RESOLUTION_NOT_SUPPORTED:
mfxRes = MFX_ERR_UNSUPPORTED;
break;
case VA_STATUS_ERROR_INVALID_DISPLAY:
case VA_STATUS_ERROR_INVALID_CONFIG:
case VA_STATUS_ERROR_INVALID_CONTEXT:
case VA_STATUS_ERROR_INVALID_SURFACE:
case VA_STATUS_ERROR_INVALID_BUFFER:
case VA_STATUS_ERROR_INVALID_IMAGE:
case VA_STATUS_ERROR_INVALID_SUBPICTURE:
mfxRes = MFX_ERR_NOT_INITIALIZED;
break;
case VA_STATUS_ERROR_INVALID_PARAMETER:
mfxRes = MFX_ERR_INVALID_VIDEO_PARAM;
default:
mfxRes = MFX_ERR_UNKNOWN;
break;
}
return mfxRes;
}
#if defined(LIBVA_DRM_SUPPORT) || defined(LIBVA_X11_SUPPORT)
CLibVA* CreateLibVA(const std::string& devicePath, int type)
{
CLibVA * libva = NULL;
switch (type)
{
case MFX_LIBVA_DRM:
#if defined(LIBVA_DRM_SUPPORT)
try
{
libva = new DRMLibVA(devicePath, type);
}
catch (std::exception&)
{
libva = 0;
}
#endif
break;
case MFX_LIBVA_X11:
#if defined(LIBVA_X11_SUPPORT)
try
{
libva = new X11LibVA;
}
catch (std::exception&)
{
libva = NULL;
}
#endif
break;
case MFX_LIBVA_AUTO:
#if defined(LIBVA_X11_SUPPORT)
try
{
libva = new X11LibVA;
}
catch (std::exception&)
{
libva = NULL;
}
#endif
#if defined(LIBVA_DRM_SUPPORT)
if (!libva)
{
try
{
libva = new DRMLibVA(devicePath, type);
}
catch (std::exception&)
{
libva = NULL;
}
}
#endif
break;
} // switch(type)
return libva;
}
#endif // #if defined(LIBVA_DRM_SUPPORT) || defined(LIBVA_X11_SUPPORT)
#if defined(LIBVA_X11_SUPPORT)
struct AcquireCtx
{
VAImage image;
};
VAStatus CLibVA::AcquireVASurface(
void** pctx,
VADisplay dpy1,
VASurfaceID srf1,
VADisplay dpy2,
VASurfaceID* srf2)
{
if (!pctx || !srf2) return VA_STATUS_ERROR_OPERATION_FAILED;
if (dpy1 == dpy2) {
*srf2 = srf1;
return VA_STATUS_SUCCESS;
}
AcquireCtx* ctx;
uintptr_t handle=0;
VAStatus va_res;
VASurfaceAttrib attribs[2];
VASurfaceAttribExternalBuffers extsrf;
VABufferInfo bufferInfo;
uint32_t memtype = VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME;
MSDK_ZERO_MEMORY(attribs);
MSDK_ZERO_MEMORY(extsrf);
MSDK_ZERO_MEMORY(bufferInfo);
extsrf.num_buffers = 1;
extsrf.buffers = &handle;
attribs[0].type = (VASurfaceAttribType)VASurfaceAttribMemoryType;
attribs[0].flags = VA_SURFACE_ATTRIB_SETTABLE;
attribs[0].value.type = VAGenericValueTypeInteger;
attribs[0].value.value.i = memtype;
attribs[1].type = (VASurfaceAttribType)VASurfaceAttribExternalBufferDescriptor;
attribs[1].flags = VA_SURFACE_ATTRIB_SETTABLE;
attribs[1].value.type = VAGenericValueTypePointer;
attribs[1].value.value.p = &extsrf;
ctx = (AcquireCtx*)calloc(1, sizeof(AcquireCtx));
if (!ctx) return VA_STATUS_ERROR_OPERATION_FAILED;
va_res = m_libva.vaDeriveImage(dpy1, srf1, &ctx->image);
if (VA_STATUS_SUCCESS != va_res) {
free(ctx);
return va_res;
}
va_res = m_libva.vaAcquireBufferHandle(dpy1, ctx->image.buf, &bufferInfo);
if (VA_STATUS_SUCCESS != va_res) {
m_libva.vaDestroyImage(dpy1, ctx->image.image_id);
free(ctx);
return va_res;
}
extsrf.width = ctx->image.width;
extsrf.height = ctx->image.height;
extsrf.num_planes = ctx->image.num_planes;
extsrf.pixel_format = ctx->image.format.fourcc;
for (int i=0; i < 3; ++i) {
extsrf.pitches[i] = ctx->image.pitches[i];
extsrf.offsets[i] = ctx->image.offsets[i];
}
extsrf.data_size = ctx->image.data_size;
extsrf.flags = memtype;
extsrf.buffers[0] = bufferInfo.handle;
va_res = m_libva.vaCreateSurfaces(dpy2,
VA_RT_FORMAT_YUV420,
extsrf.width, extsrf.height,
srf2, 1, attribs, 2);
if (VA_STATUS_SUCCESS != va_res) {
m_libva.vaDestroyImage(dpy1, ctx->image.image_id);
free(ctx);
return va_res;
}
*pctx = ctx;
return VA_STATUS_SUCCESS;
}
void CLibVA::ReleaseVASurface(
void* actx,
VADisplay dpy1,
VASurfaceID /*srf1*/,
VADisplay dpy2,
VASurfaceID srf2)
{
if (dpy1 != dpy2) {
AcquireCtx* ctx = (AcquireCtx*)actx;
if (ctx) {
m_libva.vaDestroySurfaces(dpy2, &srf2, 1);
m_libva.vaReleaseBufferHandle(dpy1, ctx->image.buf);
m_libva.vaDestroyImage(dpy1, ctx->image.image_id);
free(ctx);
}
}
}
#endif //LIBVA_X11_SUPPORT
#endif // #ifdef LIBVA_SUPPORT

View File

@@ -0,0 +1,84 @@
/******************************************************************************\
Copyright (c) 2005-2019, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
This sample was distributed or derived from the Intel's Media Samples package.
The original version of this sample may be obtained from https://software.intel.com/en-us/intel-media-server-studio
or https://software.intel.com/en-us/media-client-solutions-support.
\**********************************************************************************/
#ifdef LIBVA_ANDROID_SUPPORT
#ifdef ANDROID
#include "vaapi_utils_android.h"
CLibVA* CreateLibVA(int)
{
return new AndroidLibVA;
}
/*------------------------------------------------------------------------------*/
typedef unsigned int vaapiAndroidDisplay;
#define VAAPI_ANDROID_DEFAULT_DISPLAY 0x18c34078
AndroidLibVA::AndroidLibVA(void)
: CLibVA(MFX_LIBVA_AUTO)
, m_display(NULL)
{
VAStatus va_res = VA_STATUS_SUCCESS;
mfxStatus sts = MFX_ERR_NONE;
int major_version = 0, minor_version = 0;
vaapiAndroidDisplay* display = NULL;
m_display = display = (vaapiAndroidDisplay*)malloc(sizeof(vaapiAndroidDisplay));
if (NULL == m_display) sts = MFX_ERR_NOT_INITIALIZED;
else *display = VAAPI_ANDROID_DEFAULT_DISPLAY;
if (MFX_ERR_NONE == sts)
{
m_va_dpy = vaGetDisplay(m_display);
if (!m_va_dpy)
{
free(m_display);
sts = MFX_ERR_NULL_PTR;
}
}
if (MFX_ERR_NONE == sts)
{
va_res = vaInitialize(m_va_dpy, &major_version, &minor_version);
sts = va_to_mfx_status(va_res);
if (MFX_ERR_NONE != sts)
{
free(display);
m_display = NULL;
}
}
if (MFX_ERR_NONE != sts) throw std::bad_alloc();
}
AndroidLibVA::~AndroidLibVA(void)
{
if (m_va_dpy)
{
vaTerminate(m_va_dpy);
}
if (m_display)
{
free(m_display);
}
}
#endif // #ifdef ANDROID
#endif // #ifdef LIBVA_ANDROID_SUPPORT

View File

@@ -0,0 +1,542 @@
/******************************************************************************\
Copyright (c) 2005-2019, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
This sample was distributed or derived from the Intel's Media Samples package.
The original version of this sample may be obtained from https://software.intel.com/en-us/intel-media-server-studio
or https://software.intel.com/en-us/media-client-solutions-support.
\**********************************************************************************/
#if defined(LIBVA_DRM_SUPPORT) || defined(LIBVA_WAYLAND_SUPPORT)
#include "vaapi_utils_drm.h"
#include "vaapi_allocator.h"
#include <fcntl.h>
#include <sys/ioctl.h>
#include <stdexcept>
#include "vaapi_utils_drm.h"
#include <drm_fourcc.h>
#include "i915_drm.h"
constexpr mfxU32 MFX_DRI_MAX_NODES_NUM = 16;
constexpr mfxU32 MFX_DRI_RENDER_START_INDEX = 128;
constexpr mfxU32 MFX_DRI_CARD_START_INDEX = 0;
constexpr mfxU32 MFX_DRM_DRIVER_NAME_LEN = 4;
const char* MFX_DRM_INTEL_DRIVER_NAME = "i915";
const char* MFX_DRI_PATH = "/dev/dri/";
const char* MFX_DRI_NODE_RENDER = "renderD";
const char* MFX_DRI_NODE_CARD = "card";
int get_drm_driver_name(int fd, char *name, int name_size)
{
drm_version_t version = {};
version.name_len = name_size;
version.name = name;
return ioctl(fd, DRM_IOWR(0, drm_version), &version);
}
int open_first_intel_adapter(int type)
{
std::string adapterPath = MFX_DRI_PATH;
char driverName[MFX_DRM_DRIVER_NAME_LEN + 1] = {};
mfxU32 nodeIndex;
switch (type) {
case MFX_LIBVA_DRM:
case MFX_LIBVA_AUTO:
adapterPath += MFX_DRI_NODE_RENDER;
nodeIndex = MFX_DRI_RENDER_START_INDEX;
break;
case MFX_LIBVA_DRM_MODESET:
adapterPath += MFX_DRI_NODE_CARD;
nodeIndex = MFX_DRI_CARD_START_INDEX;
break;
default:
throw std::invalid_argument("Wrong libVA backend type");
}
for (mfxU32 i = 0; i < MFX_DRI_MAX_NODES_NUM; ++i) {
std::string curAdapterPath = adapterPath + std::to_string(nodeIndex + i);
int fd = open(curAdapterPath.c_str(), O_RDWR);
if (fd < 0) continue;
if (!get_drm_driver_name(fd, driverName, MFX_DRM_DRIVER_NAME_LEN) &&
!strcmp(driverName, MFX_DRM_INTEL_DRIVER_NAME)) {
return fd;
}
close(fd);
}
return -1;
}
int open_intel_adapter(const std::string& devicePath, int type)
{
if(devicePath.empty())
return open_first_intel_adapter(type);
int fd = open(devicePath.c_str(), O_RDWR);
if (fd < 0) {
msdk_printf(MSDK_STRING("Failed to open specified device\n"));
return -1;
}
char driverName[MFX_DRM_DRIVER_NAME_LEN + 1] = {};
if (!get_drm_driver_name(fd, driverName, MFX_DRM_DRIVER_NAME_LEN) &&
!strcmp(driverName, MFX_DRM_INTEL_DRIVER_NAME)) {
return fd;
}
else {
close(fd);
msdk_printf(MSDK_STRING("Specified device is not Intel one\n"));
return -1;
}
}
DRMLibVA::DRMLibVA(const std::string& devicePath, int type)
: CLibVA(type)
, m_fd(-1)
{
mfxStatus sts = MFX_ERR_NONE;
m_fd = open_intel_adapter(devicePath, type);
if (m_fd < 0) throw std::range_error("Intel GPU was not found");
m_va_dpy = m_vadrmlib.vaGetDisplayDRM(m_fd);
if (m_va_dpy)
{
int major_version = 0, minor_version = 0;
VAStatus va_res = m_libva.vaInitialize(m_va_dpy, &major_version, &minor_version);
sts = va_to_mfx_status(va_res);
}
else {
sts = MFX_ERR_NULL_PTR;
}
if (MFX_ERR_NONE != sts)
{
if (m_va_dpy) m_libva.vaTerminate(m_va_dpy);
close(m_fd);
throw std::runtime_error("Loading of VA display was failed");
}
}
DRMLibVA::~DRMLibVA(void)
{
if (m_va_dpy)
{
m_libva.vaTerminate(m_va_dpy);
}
if (m_fd >= 0)
{
close(m_fd);
}
}
struct drmMonitorsTable {
mfxI32 mfx_type;
uint32_t drm_type;
const msdk_char * type_name;
};
drmMonitorsTable g_drmMonitorsTable[] = {
#define __DECLARE(type) { MFX_MONITOR_ ## type, DRM_MODE_CONNECTOR_ ## type, MSDK_STRING(#type) }
__DECLARE(Unknown),
__DECLARE(VGA),
__DECLARE(DVII),
__DECLARE(DVID),
__DECLARE(DVIA),
__DECLARE(Composite),
__DECLARE(SVIDEO),
__DECLARE(LVDS),
__DECLARE(Component),
__DECLARE(9PinDIN),
__DECLARE(HDMIA),
__DECLARE(HDMIB),
__DECLARE(eDP),
__DECLARE(TV),
__DECLARE(DisplayPort),
#if defined(DRM_MODE_CONNECTOR_VIRTUAL) // from libdrm 2.4.59
__DECLARE(VIRTUAL),
#endif
#if defined(DRM_MODE_CONNECTOR_DSI) // from libdrm 2.4.59
__DECLARE(DSI)
#endif
#undef __DECLARE
};
uint32_t drmRenderer::getConnectorType(mfxI32 monitor_type)
{
for (size_t i=0; i < sizeof(g_drmMonitorsTable)/sizeof(g_drmMonitorsTable[0]); ++i) {
if (g_drmMonitorsTable[i].mfx_type == monitor_type) {
return g_drmMonitorsTable[i].drm_type;
}
}
return DRM_MODE_CONNECTOR_Unknown;
}
const msdk_char* drmRenderer::getConnectorName(uint32_t connector_type)
{
for (size_t i=0; i < sizeof(g_drmMonitorsTable)/sizeof(g_drmMonitorsTable[0]); ++i) {
if (g_drmMonitorsTable[i].drm_type == connector_type) {
return g_drmMonitorsTable[i].type_name;
}
}
return MSDK_STRING("Unknown");
}
drmRenderer::drmRenderer(int fd, mfxI32 monitorType)
: m_fd(fd)
, m_bufmgr(NULL)
, m_overlay_wrn(true)
, m_pCurrentRenderTargetSurface(NULL)
{
bool res = false;
uint32_t connectorType = getConnectorType(monitorType);
if (monitorType == MFX_MONITOR_AUTO) {
connectorType = DRM_MODE_CONNECTOR_Unknown;
} else if (connectorType == DRM_MODE_CONNECTOR_Unknown) {
throw std::invalid_argument("Unsupported monitor type");
}
drmModeRes *resource = m_drmlib.drmModeGetResources(m_fd);
if (resource) {
if (getConnector(resource, connectorType) &&
getPlane()) {
res = true;
}
m_drmlib.drmModeFreeResources(resource);
}
if (!res) {
throw std::invalid_argument("Failed to allocate renderer");
}
msdk_printf(MSDK_STRING("drmrender: connected via %s to %dx%d@%d capable display\n"),
getConnectorName(m_connector_type), m_mode.hdisplay, m_mode.vdisplay, m_mode.vrefresh);
}
drmRenderer::~drmRenderer()
{
m_drmlib.drmModeFreeCrtc(m_crtc);
if (m_bufmgr)
{
m_drmintellib.drm_intel_bufmgr_destroy(m_bufmgr);
m_bufmgr = NULL;
}
}
bool drmRenderer::getConnector(drmModeRes *resource, uint32_t connector_type)
{
bool found = false;
drmModeConnectorPtr connector = NULL;
for (int i = 0; i < resource->count_connectors; ++i) {
connector = m_drmlib.drmModeGetConnector(m_fd, resource->connectors[i]);
if (connector) {
if ((connector->connector_type == connector_type) ||
(connector_type == DRM_MODE_CONNECTOR_Unknown)) {
if (connector->connection == DRM_MODE_CONNECTED) {
msdk_printf(MSDK_STRING("drmrender: trying connection: %s\n"), getConnectorName(connector->connector_type));
m_connector_type = connector->connector_type;
m_connectorID = connector->connector_id;
found = setupConnection(resource, connector);
if (found) msdk_printf(MSDK_STRING("drmrender: succeeded...\n"));
else msdk_printf(MSDK_STRING("drmrender: failed...\n"));
} else if ((connector_type != DRM_MODE_CONNECTOR_Unknown)) {
msdk_printf(MSDK_STRING("drmrender: error: requested monitor not connected\n"));
}
}
m_drmlib.drmModeFreeConnector(connector);
if (found) return true;
}
}
msdk_printf(MSDK_STRING("drmrender: error: requested monitor not available\n"));
return false;
}
bool drmRenderer::setupConnection(drmModeRes *resource, drmModeConnector* connector)
{
bool ret = false;
drmModeEncoderPtr encoder;
if (!connector->count_modes) {
msdk_printf(MSDK_STRING("drmrender: error: no valid modes for %s connector\n"),
getConnectorName(connector->connector_type));
return false;
}
// we will use the first available mode - that's always mode with the highest resolution
m_mode = connector->modes[0];
// trying encoder+crtc which are currently attached to connector
m_encoderID = connector->encoder_id;
encoder = m_drmlib.drmModeGetEncoder(m_fd, m_encoderID);
if (encoder) {
m_crtcID = encoder->crtc_id;
for (int j = 0; j < resource->count_crtcs; ++j)
{
if (m_crtcID == resource->crtcs[j])
{
m_crtcIndex = j;
break;
}
}
ret = true;
msdk_printf(MSDK_STRING("drmrender: selected crtc already attached to connector\n"));
m_drmlib.drmModeFreeEncoder(encoder);
}
// if previous attempt to get crtc failed, let performs global search
// searching matching encoder+crtc globally
if (!ret) {
for (int i = 0; i < connector->count_encoders; ++i) {
encoder = m_drmlib.drmModeGetEncoder(m_fd, connector->encoders[i]);
if (encoder) {
for (int j = 0; j < resource->count_crtcs; ++j) {
// check whether this CRTC works with the encoder
if ( !((encoder->possible_crtcs & (1 << j)) &&
(encoder->crtc_id == resource->crtcs[j])) )
continue;
m_encoderID = connector->encoders[i];
m_crtcIndex = j;
m_crtcID = resource->crtcs[j];
ret = true;
msdk_printf(MSDK_STRING("drmrender: found crtc with global search\n"));
break;
}
m_drmlib.drmModeFreeEncoder(encoder);
if (ret)
break;
}
}
}
if (ret) {
m_crtc = m_drmlib.drmModeGetCrtc(m_fd, m_crtcID);
if (!m_crtc)
ret = false;
} else {
msdk_printf(MSDK_STRING("drmrender: failed to select crtc\n"));
}
return ret;
}
bool drmRenderer::getPlane()
{
drmModePlaneResPtr planes = m_drmlib.drmModeGetPlaneResources(m_fd);
if (!planes) {
return false;
}
for (uint32_t i = 0; i < planes->count_planes; ++i) {
drmModePlanePtr plane = m_drmlib.drmModeGetPlane(m_fd, planes->planes[i]);
if (plane) {
if (plane->possible_crtcs & (1 << m_crtcIndex)) {
for (uint32_t j = 0; j < plane->count_formats; ++j) {
if ((plane->formats[j] == DRM_FORMAT_XRGB8888)
|| (plane->formats[j] == DRM_FORMAT_NV12)) {
m_planeID = plane->plane_id;
m_drmlib.drmModeFreePlane(plane);
m_drmlib.drmModeFreePlaneResources(planes);
return true;
}
}
}
m_drmlib.drmModeFreePlane(plane);
}
}
m_drmlib.drmModeFreePlaneResources(planes);
return false;
}
bool drmRenderer::setMaster()
{
int wait_count = 0;
do {
if (!m_drmlib.drmSetMaster(m_fd)) return true;
usleep(100);
++wait_count;
} while(wait_count < 30000);
msdk_printf(MSDK_STRING("drmrender: error: failed to get drm mastership during 3 seconds - aborting\n"));
return false;
}
void drmRenderer::dropMaster()
{
m_drmlib.drmDropMaster(m_fd);
}
bool drmRenderer::restore()
{
if (!setMaster()) return false;
int ret = m_drmlib.drmModeSetCrtc(m_fd, m_crtcID, m_crtc->buffer_id, m_crtc->x, m_crtc->y, &m_connectorID, 1, &m_mode);
if (ret) {
msdk_printf(MSDK_STRING("drmrender: failed to restore original mode\n"));
return false;
}
dropMaster();
return true;
}
void* drmRenderer::acquire(mfxMemId mid)
{
vaapiMemId* vmid = (vaapiMemId*)mid;
uint32_t fbhandle=0;
if (vmid->m_buffer_info.mem_type == VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME) {
if (!m_bufmgr) {
m_bufmgr = m_drmintellib.drm_intel_bufmgr_gem_init(m_fd, 4096);
if (!m_bufmgr) return NULL;
}
drm_intel_bo* bo = m_drmintellib.drm_intel_bo_gem_create_from_prime(
m_bufmgr, (int)vmid->m_buffer_info.handle, vmid->m_buffer_info.mem_size);
if (!bo) return NULL;
int ret = m_drmlib.drmModeAddFB(m_fd,
vmid->m_image.width, vmid->m_image.height,
24, 32, vmid->m_image.pitches[0],
bo->handle, &fbhandle);
if (ret) {
return NULL;
}
m_drmintellib.drm_intel_bo_unreference(bo);
} else if (vmid->m_buffer_info.mem_type == VA_SURFACE_ATTRIB_MEM_TYPE_KERNEL_DRM) {
struct drm_gem_open flink_open;
struct drm_gem_close flink_close;
MSDK_ZERO_MEMORY(flink_open);
flink_open.name = vmid->m_buffer_info.handle;
int ret = m_drmlib.drmIoctl(m_fd, DRM_IOCTL_GEM_OPEN, &flink_open);
if (ret) return NULL;
uint32_t handles[4], pitches[4], offsets[4], pixel_format, flags = 0;
uint64_t modifiers[4];
memset(&handles, 0, sizeof(handles));
memset(&pitches, 0, sizeof(pitches));
memset(&offsets, 0, sizeof(offsets));
memset(&modifiers, 0, sizeof(modifiers));
handles[0] = flink_open.handle;
pitches[0] = vmid->m_image.pitches[0];
offsets[0] = vmid->m_image.offsets[0];
if (VA_FOURCC_NV12 == vmid->m_fourcc) {
struct drm_i915_gem_set_tiling set_tiling;
pixel_format = DRM_FORMAT_NV12;
memset(&set_tiling, 0, sizeof(set_tiling));
set_tiling.handle = flink_open.handle;
set_tiling.tiling_mode = I915_TILING_Y;
set_tiling.stride = vmid->m_image.pitches[0];
ret = m_drmlib.drmIoctl(m_fd, DRM_IOCTL_I915_GEM_SET_TILING, &set_tiling);
if (ret) {
msdk_printf(MSDK_STRING("DRM_IOCTL_I915_GEM_SET_TILING Failed ret = %d\n"),ret);
return NULL;
}
handles[1] = flink_open.handle;
pitches[1] = vmid->m_image.pitches[1];
offsets[1] = vmid->m_image.offsets[1];
modifiers[0] = modifiers[1] = I915_FORMAT_MOD_Y_TILED;
flags = 2; // DRM_MODE_FB_MODIFIERS (1<<1) /* enables ->modifer[]
}
else {
pixel_format = DRM_FORMAT_XRGB8888;
}
ret = m_drmlib.drmModeAddFB2WithModifiers(m_fd, vmid->m_image.width, vmid->m_image.height,
pixel_format, handles, pitches, offsets, modifiers, &fbhandle, flags);
if (ret) return NULL;
MSDK_ZERO_MEMORY(flink_close);
flink_close.handle = flink_open.handle;
ret = m_drmlib.drmIoctl(m_fd, DRM_IOCTL_GEM_CLOSE, &flink_close);
if (ret) return NULL;
} else {
return NULL;
}
try {
uint32_t* hdl = new uint32_t;
*hdl = fbhandle;
return hdl;
} catch(...) {
return NULL;
}
}
void drmRenderer::release(mfxMemId mid, void * mem)
{
uint32_t* hdl = (uint32_t*)mem;
if (!hdl) return;
if (!restore()) {
msdk_printf(MSDK_STRING("drmrender: warning: failure to restore original mode may lead to application segfault!\n"));
}
m_drmlib.drmModeRmFB(m_fd, *hdl);
delete(hdl);
}
mfxStatus drmRenderer::render(mfxFrameSurface1 * pSurface)
{
int ret;
vaapiMemId * memid;
uint32_t fbhandle;
if (!pSurface || !pSurface->Data.MemId) return MFX_ERR_INVALID_HANDLE;
memid = (vaapiMemId*)(pSurface->Data.MemId);
if (!memid->m_custom) return MFX_ERR_INVALID_HANDLE;
fbhandle = *(uint32_t*)memid->m_custom;
// rendering on the screen
if (!setMaster()) {
return MFX_ERR_UNKNOWN;
}
if ((m_mode.hdisplay == memid->m_image.width) &&
(m_mode.vdisplay == memid->m_image.height)) {
// surface in the framebuffer exactly matches crtc scanout port, so we
// can scanout from this framebuffer for the whole crtc
ret = m_drmlib.drmModeSetCrtc(m_fd, m_crtcID, fbhandle, 0, 0, &m_connectorID, 1, &m_mode);
if (ret) {
return MFX_ERR_UNKNOWN;
}
} else {
if (m_overlay_wrn) {
m_overlay_wrn = false;
msdk_printf(MSDK_STRING("drmrender: warning: rendering via OVERLAY plane\n"));
}
// surface in the framebuffer exactly does NOT match crtc scanout port,
// and we can only use overlay technique with possible resize (depending on the driver))
ret = m_drmlib.drmModeSetPlane(m_fd, m_planeID, m_crtcID, fbhandle, 0,
0, 0, m_crtc->width, m_crtc->height,
pSurface->Info.CropX << 16, pSurface->Info.CropY << 16, pSurface->Info.CropW << 16, pSurface->Info.CropH << 16);
if (ret) {
return MFX_ERR_UNKNOWN;
}
}
dropMaster();
/* Unlock previous Render Target Surface (if exists) */
if (NULL != m_pCurrentRenderTargetSurface)
msdk_atomic_dec16((volatile mfxU16*)&m_pCurrentRenderTargetSurface->Data.Locked);
/* new Render target */
m_pCurrentRenderTargetSurface = pSurface;
/* And lock it */
msdk_atomic_inc16((volatile mfxU16*)&m_pCurrentRenderTargetSurface->Data.Locked);
return MFX_ERR_NONE;
}
#endif // #if defined(LIBVA_DRM_SUPPORT)

View File

@@ -0,0 +1,130 @@
/******************************************************************************\
Copyright (c) 2005-2019, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
This sample was distributed or derived from the Intel's Media Samples package.
The original version of this sample may be obtained from https://software.intel.com/en-us/intel-media-server-studio
or https://software.intel.com/en-us/media-client-solutions-support.
\**********************************************************************************/
#if defined(LIBVA_X11_SUPPORT)
#include "sample_defs.h"
#include "vaapi_utils_x11.h"
#include <dlfcn.h>
#if defined(X11_DRI3_SUPPORT)
#include <fcntl.h>
#endif
#define VAAPI_X_DEFAULT_DISPLAY ":0.0"
X11LibVA::X11LibVA(void)
: CLibVA(MFX_LIBVA_X11)
, m_display(0)
, m_configID(VA_INVALID_ID)
, m_contextID(VA_INVALID_ID)
{
char* currentDisplay = getenv("DISPLAY");
m_display = (currentDisplay)?
m_x11lib.XOpenDisplay(currentDisplay) :
m_x11lib.XOpenDisplay(VAAPI_X_DEFAULT_DISPLAY);
if (!m_display)
{
msdk_printf(MSDK_STRING("Failed to open X Display: try to check/set DISPLAY environment variable.\n"));
throw std::bad_alloc();
}
m_va_dpy = m_vax11lib.vaGetDisplay(m_display);
if (!m_va_dpy)
{
m_x11lib.XCloseDisplay(m_display);
msdk_printf(MSDK_STRING("Failed to get VA Display\n"));
throw std::bad_alloc();
}
int major_version = 0, minor_version = 0;
VAStatus sts = m_libva.vaInitialize(m_va_dpy, &major_version, &minor_version);
if (VA_STATUS_SUCCESS != sts)
{
m_x11lib.XCloseDisplay(m_display);
msdk_printf(MSDK_STRING("Failed to initialize VAAPI: %d\n"), sts);
throw std::bad_alloc();
}
#if !defined(X11_DRI3_SUPPORT)
VAConfigAttrib cfgAttrib{};
if (VA_STATUS_SUCCESS == sts)
{
cfgAttrib.type = VAConfigAttribRTFormat;
sts = m_libva.vaGetConfigAttributes(
m_va_dpy,
VAProfileNone, VAEntrypointVideoProc,
&cfgAttrib, 1);
}
if (VA_STATUS_SUCCESS == sts)
{
sts = m_libva.vaCreateConfig(
m_va_dpy,
VAProfileNone, VAEntrypointVideoProc,
&cfgAttrib, 1,
&m_configID);
}
if (VA_STATUS_SUCCESS == sts)
{
sts = m_libva.vaCreateContext(
m_va_dpy,
m_configID, 0, 0, VA_PROGRESSIVE, 0, 0,
&m_contextID);
}
if (VA_STATUS_SUCCESS != sts)
{
Close();
msdk_printf(MSDK_STRING("Failed to initialize VP: %d\n"), sts);
throw std::bad_alloc();
}
#endif // X11_DRI3_SUPPORT
}
X11LibVA::~X11LibVA(void)
{
Close();
}
void X11LibVA::Close()
{
VAStatus sts;
if (m_contextID != VA_INVALID_ID)
{
sts = m_libva.vaDestroyContext(m_va_dpy, m_contextID);
if (sts != VA_STATUS_SUCCESS)
msdk_printf(MSDK_STRING("Failed to destroy VA context: %d\n"), sts);
}
if (m_configID != VA_INVALID_ID)
{
sts = m_libva.vaDestroyConfig(m_va_dpy, m_configID);
if (sts != VA_STATUS_SUCCESS)
msdk_printf(MSDK_STRING("Failed to destroy VA config: %d\n"), sts);
}
sts = m_libva.vaTerminate(m_va_dpy);
if (sts != VA_STATUS_SUCCESS)
msdk_printf(MSDK_STRING("Failed to close VAAPI library: %d\n"), sts);
m_x11lib.XCloseDisplay(m_display);
}
#endif // #if defined(LIBVA_X11_SUPPORT)

View File

@@ -0,0 +1,60 @@
/******************************************************************************\
Copyright (c) 2005-2019, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
This sample was distributed or derived from the Intel's Media Samples package.
The original version of this sample may be obtained from https://software.intel.com/en-us/intel-media-server-studio
or https://software.intel.com/en-us/media-client-solutions-support.
\**********************************************************************************/
#if defined(_WIN32) || defined(_WIN64)
#include "vm/atomic_defs.h"
//#define _interlockedbittestandset fake_set
//#define _interlockedbittestandreset fake_reset
//#define _interlockedbittestandset64 fake_set64
//#define _interlockedbittestandreset64 fake_reset64
#include <intrin.h>
//#undef _interlockedbittestandset
//#undef _interlockedbittestandreset
//#undef _interlockedbittestandset64
//#undef _interlockedbittestandreset64
#pragma intrinsic (_InterlockedIncrement16)
#pragma intrinsic (_InterlockedDecrement16)
#pragma intrinsic (_InterlockedIncrement)
#pragma intrinsic (_InterlockedDecrement)
mfxU16 msdk_atomic_inc16(volatile mfxU16 *pVariable)
{
return _InterlockedIncrement16((volatile short*)pVariable);
}
/* Thread-safe 16-bit variable decrementing */
mfxU16 msdk_atomic_dec16(volatile mfxU16 *pVariable)
{
return _InterlockedDecrement16((volatile short*)pVariable);
}
mfxU32 msdk_atomic_inc32(volatile mfxU32 *pVariable)
{
return _InterlockedIncrement((volatile long*)pVariable);
}
/* Thread-safe 16-bit variable decrementing */
mfxU32 msdk_atomic_dec32(volatile mfxU32 *pVariable)
{
return _InterlockedDecrement((volatile long*)pVariable);
}
#endif // #if defined(_WIN32) || defined(_WIN64)

View File

@@ -0,0 +1,64 @@
/******************************************************************************\
Copyright (c) 2005-2019, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
This sample was distributed or derived from the Intel's Media Samples package.
The original version of this sample may be obtained from https://software.intel.com/en-us/intel-media-server-studio
or https://software.intel.com/en-us/media-client-solutions-support.
\**********************************************************************************/
#if !defined(_WIN32) && !defined(_WIN64)
#include "vm/atomic_defs.h"
static mfxU16 msdk_atomic_add16(volatile mfxU16 *mem, mfxU16 val)
{
asm volatile ("lock; xaddw %0,%1"
: "=r" (val), "=m" (*mem)
: "0" (val), "m" (*mem)
: "memory", "cc");
return val;
}
static mfxU32 msdk_atomic_add32(volatile mfxU32 *mem, mfxU32 val)
{
asm volatile ("lock; xaddl %0,%1"
: "=r" (val), "=m" (*mem)
: "0" (val), "m" (*mem)
: "memory", "cc");
return val;
}
mfxU16 msdk_atomic_inc16(volatile mfxU16 *pVariable)
{
return msdk_atomic_add16(pVariable, 1) + 1;
}
/* Thread-safe 16-bit variable decrementing */
mfxU16 msdk_atomic_dec16(volatile mfxU16 *pVariable)
{
return msdk_atomic_add16(pVariable, (mfxU16)-1) + 1;
}
mfxU32 msdk_atomic_inc32(volatile mfxU32 *pVariable)
{
return msdk_atomic_add32(pVariable, 1) + 1;
}
/* Thread-safe 16-bit variable decrementing */
mfxU32 msdk_atomic_dec32(volatile mfxU32 *pVariable)
{
return msdk_atomic_add32(pVariable, (mfxU32)-1) + 1;
}
#endif // #if !defined(_WIN32) && !defined(_WIN64)

View File

@@ -0,0 +1,46 @@
/******************************************************************************\
Copyright (c) 2005-2019, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
This sample was distributed or derived from the Intel's Media Samples package.
The original version of this sample may be obtained from https://software.intel.com/en-us/intel-media-server-studio
or https://software.intel.com/en-us/media-client-solutions-support.
\**********************************************************************************/
#include "mfx_samples_config.h"
#if defined(_WIN32) || defined(_WIN64)
#include "vm/so_defs.h"
#include <windows.h>
msdk_so_handle msdk_so_load(const msdk_char *file_name)
{
if (!file_name) return NULL;
return (msdk_so_handle) LoadLibrary((LPCTSTR)file_name);
}
msdk_func_pointer msdk_so_get_addr(msdk_so_handle handle, const char *func_name)
{
if (!handle) return NULL;
return (msdk_func_pointer)GetProcAddress((HMODULE)handle, /*(LPCSTR)*/func_name);
}
void msdk_so_free(msdk_so_handle handle)
{
if (!handle) return;
FreeLibrary((HMODULE)handle);
}
#endif // #if defined(_WIN32) || defined(_WIN64)

View File

@@ -0,0 +1,43 @@
/******************************************************************************\
Copyright (c) 2005-2019, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
This sample was distributed or derived from the Intel's Media Samples package.
The original version of this sample may be obtained from https://software.intel.com/en-us/intel-media-server-studio
or https://software.intel.com/en-us/media-client-solutions-support.
\**********************************************************************************/
#if !defined(_WIN32) && !defined(_WIN64)
#include "vm/so_defs.h"
#include <dlfcn.h>
msdk_so_handle msdk_so_load(const msdk_char *file_name)
{
if (!file_name) return NULL;
return (msdk_so_handle) dlopen(file_name, RTLD_LAZY);
}
msdk_func_pointer msdk_so_get_addr(msdk_so_handle handle, const char *func_name)
{
if (!handle) return NULL;
return (msdk_func_pointer)dlsym(handle, func_name);
}
void msdk_so_free(msdk_so_handle handle)
{
if (!handle) return;
dlclose(handle);
}
#endif // #if !defined(_WIN32) && !defined(_WIN64)

View File

@@ -0,0 +1,293 @@
/******************************************************************************\
Copyright (c) 2005-2019, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
This sample was distributed or derived from the Intel's Media Samples package.
The original version of this sample may be obtained from https://software.intel.com/en-us/intel-media-server-studio
or https://software.intel.com/en-us/media-client-solutions-support.
\**********************************************************************************/
#if !defined(_WIN32) && !defined(_WIN64)
#include <new> // std::bad_alloc
#include <stdio.h> // setrlimit
#include <sched.h>
#include <unistd.h>
#include <sys/syscall.h>
#include "vm/thread_defs.h"
#include "sample_utils.h"
/* ****************************************************************************** */
MSDKSemaphore::MSDKSemaphore(mfxStatus &sts, mfxU32 count):
msdkSemaphoreHandle(count)
{
sts = MFX_ERR_NONE;
int res = pthread_cond_init(&m_semaphore, NULL);
if (!res) {
res = pthread_mutex_init(&m_mutex, NULL);
if (res) {
pthread_cond_destroy(&m_semaphore);
}
}
if (res) throw std::bad_alloc();
}
MSDKSemaphore::~MSDKSemaphore(void)
{
pthread_mutex_destroy(&m_mutex);
pthread_cond_destroy(&m_semaphore);
}
mfxStatus MSDKSemaphore::Post(void)
{
int res = pthread_mutex_lock(&m_mutex);
if (!res) {
if (0 == m_count++) res = pthread_cond_signal(&m_semaphore);
}
int sts = pthread_mutex_unlock(&m_mutex);
if (!res) res = sts;
return (res)? MFX_ERR_UNKNOWN: MFX_ERR_NONE;
}
mfxStatus MSDKSemaphore::Wait(void)
{
int res = pthread_mutex_lock(&m_mutex);
if (!res) {
while(!m_count) {
res = pthread_cond_wait(&m_semaphore, &m_mutex);
}
if (!res) --m_count;
int sts = pthread_mutex_unlock(&m_mutex);
if (!res) res = sts;
}
return (res)? MFX_ERR_UNKNOWN: MFX_ERR_NONE;
}
/* ****************************************************************************** */
MSDKEvent::MSDKEvent(mfxStatus &sts, bool manual, bool state):
msdkEventHandle(manual, state)
{
sts = MFX_ERR_NONE;
int res = pthread_cond_init(&m_event, NULL);
if (!res) {
res = pthread_mutex_init(&m_mutex, NULL);
if (res) {
pthread_cond_destroy(&m_event);
}
}
if (res) throw std::bad_alloc();
}
MSDKEvent::~MSDKEvent(void)
{
pthread_mutex_destroy(&m_mutex);
pthread_cond_destroy(&m_event);
}
mfxStatus MSDKEvent::Signal(void)
{
int res = pthread_mutex_lock(&m_mutex);
if (!res) {
if (!m_state) {
m_state = true;
if (m_manual) res = pthread_cond_broadcast(&m_event);
else res = pthread_cond_signal(&m_event);
}
int sts = pthread_mutex_unlock(&m_mutex);
if (!res) res = sts;
}
return (res)? MFX_ERR_UNKNOWN: MFX_ERR_NONE;
}
mfxStatus MSDKEvent::Reset(void)
{
int res = pthread_mutex_lock(&m_mutex);
if (!res)
{
if (m_state) m_state = false;
res = pthread_mutex_unlock(&m_mutex);
}
return (res)? MFX_ERR_UNKNOWN: MFX_ERR_NONE;
}
mfxStatus MSDKEvent::Wait(void)
{
int res = pthread_mutex_lock(&m_mutex);
if (!res)
{
while(!m_state) res = pthread_cond_wait(&m_event, &m_mutex);
if (!m_manual) m_state = false;
int sts = pthread_mutex_unlock(&m_mutex);
if (!res) res = sts;
}
return (res)? MFX_ERR_UNKNOWN: MFX_ERR_NONE;
}
mfxStatus MSDKEvent::TimedWait(mfxU32 msec)
{
if (MFX_INFINITE == msec) return MFX_ERR_UNSUPPORTED;
mfxStatus mfx_res = MFX_ERR_NOT_INITIALIZED;
int res = pthread_mutex_lock(&m_mutex);
if (!res)
{
if (!m_state)
{
struct timeval tval;
struct timespec tspec;
mfxI32 res;
gettimeofday(&tval, NULL);
msec = 1000 * msec + tval.tv_usec;
tspec.tv_sec = tval.tv_sec + msec / 1000000;
tspec.tv_nsec = (msec % 1000000) * 1000;
res = pthread_cond_timedwait(&m_event,
&m_mutex,
&tspec);
if (!res) mfx_res = MFX_ERR_NONE;
else if (ETIMEDOUT == res) mfx_res = MFX_TASK_WORKING;
else mfx_res = MFX_ERR_UNKNOWN;
}
else mfx_res = MFX_ERR_NONE;
if (!m_manual)
m_state = false;
res = pthread_mutex_unlock(&m_mutex);
if (res) mfx_res = MFX_ERR_UNKNOWN;
}
else mfx_res = MFX_ERR_UNKNOWN;
return mfx_res;
}
/* ****************************************************************************** */
void* msdk_thread_start(void* arg)
{
if (arg) {
MSDKThread* thread = (MSDKThread*)arg;
if (thread->m_func) thread->m_func(thread->m_arg);
thread->m_event->Signal();
}
return NULL;
}
/* ****************************************************************************** */
MSDKThread::MSDKThread(mfxStatus &sts, msdk_thread_callback func, void* arg):
msdkThreadHandle(func, arg)
{
m_event = new MSDKEvent(sts, false, false);
if (pthread_create(&(m_thread), NULL, msdk_thread_start, this)) {
delete(m_event);
throw std::bad_alloc();
}
}
MSDKThread::~MSDKThread(void)
{
delete m_event;
}
mfxStatus MSDKThread::Wait(void)
{
int res = pthread_join(m_thread, NULL);
return (res)? MFX_ERR_UNKNOWN: MFX_ERR_NONE;
}
mfxStatus MSDKThread::TimedWait(mfxU32 msec)
{
if (MFX_INFINITE == msec) return MFX_ERR_UNSUPPORTED;
mfxStatus mfx_res = m_event->TimedWait(msec);
if (MFX_ERR_NONE == mfx_res) {
return (pthread_join(m_thread, NULL))? MFX_ERR_UNKNOWN: MFX_ERR_NONE;
}
return mfx_res;
}
mfxStatus MSDKThread::GetExitCode()
{
if (!m_event) return MFX_ERR_NOT_INITIALIZED;
/** @todo: Need to add implementation. */
return MFX_ERR_NONE;
}
/* ****************************************************************************** */
mfxStatus msdk_setrlimit_vmem(mfxU64 size)
{
struct rlimit limit;
limit.rlim_cur = size;
limit.rlim_max = size;
if (setrlimit(RLIMIT_AS, &limit)) return MFX_ERR_UNKNOWN;
return MFX_ERR_NONE;
}
mfxStatus msdk_thread_get_schedtype(const msdk_char* str, mfxI32 &type)
{
if (!msdk_strcmp(str, MSDK_STRING("fifo"))) {
type = SCHED_FIFO;
}
else if (!msdk_strcmp(str, MSDK_STRING("rr"))) {
type = SCHED_RR;
}
else if (!msdk_strcmp(str, MSDK_STRING("other"))) {
type = SCHED_OTHER;
}
else if (!msdk_strcmp(str, MSDK_STRING("batch"))) {
type = SCHED_BATCH;
}
else if (!msdk_strcmp(str, MSDK_STRING("idle"))) {
type = SCHED_IDLE;
}
// else if (!msdk_strcmp(str, MSDK_STRING("deadline"))) {
// type = SCHED_DEADLINE;
// }
else {
return MFX_ERR_UNSUPPORTED;
}
return MFX_ERR_NONE;
}
void msdk_thread_printf_scheduling_help()
{
msdk_printf(MSDK_STRING("Note on the scheduling types and priorities:\n"));
msdk_printf(MSDK_STRING(" - <sched_type>: <priority_min> .. <priority_max> (notes)\n"));
msdk_printf(MSDK_STRING("The following scheduling types requires root privileges:\n"));
msdk_printf(MSDK_STRING(" - fifo: %d .. %d (static priority: low .. high)\n"), sched_get_priority_min(SCHED_FIFO), sched_get_priority_max(SCHED_FIFO));
msdk_printf(MSDK_STRING(" - rr: %d .. %d (static priority: low .. high)\n"), sched_get_priority_min(SCHED_RR), sched_get_priority_max(SCHED_RR));
msdk_printf(MSDK_STRING("The following scheduling types can be used by non-privileged users:\n"));
msdk_printf(MSDK_STRING(" - other: 0 .. 0 (static priority always 0)\n"));
msdk_printf(MSDK_STRING(" - batch: 0 .. 0 (static priority always 0)\n"));
msdk_printf(MSDK_STRING(" - idle: n/a\n"));
msdk_printf(MSDK_STRING("If you want to adjust priority for the other or batch scheduling type,\n"));
msdk_printf(MSDK_STRING("you can do that process-wise using dynamic priority - so called nice value.\n"));
msdk_printf(MSDK_STRING("Range for the nice value is: %d .. %d (high .. low)\n"), PRIO_MIN, PRIO_MAX);
msdk_printf(MSDK_STRING("Please, see 'man(1) nice' for details.\n"));
}
mfxU32 msdk_get_current_pid()
{
return syscall(SYS_getpid);
}
#endif // #if !defined(_WIN32) && !defined(_WIN64)

View File

@@ -0,0 +1,142 @@
/******************************************************************************\
Copyright (c) 2005-2019, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
This sample was distributed or derived from the Intel's Media Samples package.
The original version of this sample may be obtained from https://software.intel.com/en-us/intel-media-server-studio
or https://software.intel.com/en-us/media-client-solutions-support.
\**********************************************************************************/
#include "mfx_samples_config.h"
#if defined(_WIN32) || defined(_WIN64)
#include "vm/thread_defs.h"
#include <new>
MSDKSemaphore::MSDKSemaphore(mfxStatus &sts, mfxU32 count)
{
sts = MFX_ERR_NONE;
m_semaphore = CreateSemaphore(NULL, count, LONG_MAX, 0);
if (!m_semaphore) throw std::bad_alloc();
}
MSDKSemaphore::~MSDKSemaphore(void)
{
CloseHandle(m_semaphore);
}
mfxStatus MSDKSemaphore::Post(void)
{
return (ReleaseSemaphore(m_semaphore, 1, NULL) == false) ? MFX_ERR_UNKNOWN : MFX_ERR_NONE;
}
mfxStatus MSDKSemaphore::Wait(void)
{
return (WaitForSingleObject(m_semaphore, INFINITE) != WAIT_OBJECT_0) ? MFX_ERR_UNKNOWN : MFX_ERR_NONE;
}
/* ****************************************************************************** */
MSDKEvent::MSDKEvent(mfxStatus &sts, bool manual, bool state)
{
sts = MFX_ERR_NONE;
m_event = CreateEvent(NULL, manual, state, NULL);
if (!m_event) throw std::bad_alloc();
}
MSDKEvent::~MSDKEvent(void)
{
CloseHandle(m_event);
}
mfxStatus MSDKEvent::Signal(void)
{
return (SetEvent(m_event) == false) ? MFX_ERR_UNKNOWN : MFX_ERR_NONE;
}
mfxStatus MSDKEvent::Reset(void)
{
return (ResetEvent(m_event) == false) ? MFX_ERR_UNKNOWN : MFX_ERR_NONE;
}
mfxStatus MSDKEvent::Wait(void)
{
return (WaitForSingleObject(m_event, INFINITE) != WAIT_OBJECT_0) ? MFX_ERR_UNKNOWN : MFX_ERR_NONE;
}
mfxStatus MSDKEvent::TimedWait(mfxU32 msec)
{
if(MFX_INFINITE == msec) return MFX_ERR_UNSUPPORTED;
mfxStatus mfx_res = MFX_ERR_NOT_INITIALIZED;
DWORD res = WaitForSingleObject(m_event, msec);
if(WAIT_OBJECT_0 == res) mfx_res = MFX_ERR_NONE;
else if (WAIT_TIMEOUT == res) mfx_res = MFX_TASK_WORKING;
else mfx_res = MFX_ERR_UNKNOWN;
return mfx_res;
}
MSDKThread::MSDKThread(mfxStatus &sts, msdk_thread_callback func, void* arg)
{
sts = MFX_ERR_NONE;
m_thread = (void*)_beginthreadex(NULL, 0, func, arg, 0, NULL);
if (!m_thread) throw std::bad_alloc();
}
MSDKThread::~MSDKThread(void)
{
CloseHandle(m_thread);
}
mfxStatus MSDKThread::Wait(void)
{
return (WaitForSingleObject(m_thread, INFINITE) != WAIT_OBJECT_0) ? MFX_ERR_UNKNOWN : MFX_ERR_NONE;
}
mfxStatus MSDKThread::TimedWait(mfxU32 msec)
{
if(MFX_INFINITE == msec) return MFX_ERR_UNSUPPORTED;
mfxStatus mfx_res = MFX_ERR_NONE;
DWORD res = WaitForSingleObject(m_thread, msec);
if(WAIT_OBJECT_0 == res) mfx_res = MFX_ERR_NONE;
else if (WAIT_TIMEOUT == res) mfx_res = MFX_TASK_WORKING;
else mfx_res = MFX_ERR_UNKNOWN;
return mfx_res;
}
mfxStatus MSDKThread::GetExitCode()
{
mfxStatus mfx_res = MFX_ERR_NOT_INITIALIZED;
DWORD code = 0;
int sts = 0;
sts = GetExitCodeThread(m_thread, &code);
if (sts == 0) mfx_res = MFX_ERR_UNKNOWN;
else if (STILL_ACTIVE == code) mfx_res = MFX_TASK_WORKING;
else mfx_res = MFX_ERR_NONE;
return mfx_res;
}
mfxU32 msdk_get_current_pid()
{
return GetCurrentProcessId();
}
#endif // #if defined(_WIN32) || defined(_WIN64)

View File

@@ -0,0 +1,46 @@
/******************************************************************************\
Copyright (c) 2005-2019, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
This sample was distributed or derived from the Intel's Media Samples package.
The original version of this sample may be obtained from https://software.intel.com/en-us/intel-media-server-studio
or https://software.intel.com/en-us/media-client-solutions-support.
\**********************************************************************************/
#include "mfx_samples_config.h"
#if defined(_WIN32) || defined(_WIN64)
#include "vm/time_defs.h"
msdk_tick msdk_time_get_tick(void)
{
LARGE_INTEGER t1;
QueryPerformanceCounter(&t1);
return t1.QuadPart;
}
msdk_tick msdk_time_get_frequency(void)
{
LARGE_INTEGER t1;
QueryPerformanceFrequency(&t1);
return t1.QuadPart;
}
mfxU64 rdtsc(){
return __rdtsc();
}
#endif // #if defined(_WIN32) || defined(_WIN64)

View File

@@ -0,0 +1,47 @@
/******************************************************************************\
Copyright (c) 2005-2019, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
This sample was distributed or derived from the Intel's Media Samples package.
The original version of this sample may be obtained from https://software.intel.com/en-us/intel-media-server-studio
or https://software.intel.com/en-us/media-client-solutions-support.
\**********************************************************************************/
#if !defined(_WIN32) && !defined(_WIN64)
#include "vm/time_defs.h"
#include <sys/time.h>
#define MSDK_TIME_MHZ 1000000
msdk_tick msdk_time_get_tick(void)
{
struct timeval tv;
gettimeofday(&tv, NULL);
return (msdk_tick)tv.tv_sec * (msdk_tick)MSDK_TIME_MHZ + (msdk_tick)tv.tv_usec;
}
msdk_tick msdk_time_get_frequency(void)
{
return (msdk_tick)MSDK_TIME_MHZ;
}
mfxU64 rdtsc(void){
unsigned int lo,hi;
__asm__ __volatile__ ("rdtsc" : "=a" (lo), "=d" (hi));
return ((mfxU64)hi << 32) | lo;
}
#endif // #if !defined(_WIN32) && !defined(_WIN64)

View File

@@ -0,0 +1,275 @@
/******************************************************************************\
Copyright (c) 2005-2019, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
This sample was distributed or derived from the Intel's Media Samples package.
The original version of this sample may be obtained from https://software.intel.com/en-us/intel-media-server-studio
or https://software.intel.com/en-us/media-client-solutions-support.
\**********************************************************************************/
#include "mfx_samples_config.h"
#include "sample_defs.h"
#include "vpp_ex.h"
#include "vm/atomic_defs.h"
MFXVideoVPPEx::MFXVideoVPPEx(mfxSession session) :
MFXVideoVPP(session)
#if !defined (USE_VPP_EX)
{};
#else
, m_nCurrentPTS(0)
, m_nIncreaseTime(0)
, m_nInputTimeStamp(0)
, m_nArraySize(0)
{
memset(&m_VideoParams, 0, sizeof(m_VideoParams));
};
mfxStatus MFXVideoVPPEx::Close(void)
{
for(std::vector<mfxFrameSurface1*>::iterator it = m_LockedSurfacesList.begin(); it != m_LockedSurfacesList.end(); ++it)
{
try {
msdk_atomic_dec16((volatile mfxU16*)(&(*it)->Data.Locked));
} catch (...) { // improve robustness by try/catch
}
}
m_LockedSurfacesList.clear();
return MFXVideoVPP::Close();
};
mfxStatus MFXVideoVPPEx::QueryIOSurf(mfxVideoParam *par, mfxFrameAllocRequest request[2])
{
mfxVideoParam params;
if (NULL == par)
{
return MFX_ERR_NULL_PTR;
};
MSDK_MEMCPY_VAR(params, par, sizeof(mfxVideoParam));
params.vpp.In.FrameRateExtD = params.vpp.Out.FrameRateExtD;
params.vpp.In.FrameRateExtN = params.vpp.Out.FrameRateExtN;
return MFXVideoVPP::QueryIOSurf(&params, request);
};
mfxStatus MFXVideoVPPEx::Query(mfxVideoParam *in, mfxVideoParam *out)
{
mfxVideoParam params;
if (NULL == out)
{
return MFX_ERR_NULL_PTR;
}
if (in)
{
MSDK_MEMCPY_VAR(params, in, sizeof(mfxVideoParam));
params.vpp.In.FrameRateExtD = params.vpp.Out.FrameRateExtD;
params.vpp.In.FrameRateExtN = params.vpp.Out.FrameRateExtN;
}
return MFXVideoVPP::Query((in) ? &params : NULL, out);
};
mfxStatus MFXVideoVPPEx::Init(mfxVideoParam *par)
{
mfxStatus sts = MFX_ERR_NONE;
if (NULL == par)
{
return MFX_ERR_NULL_PTR;
};
m_nCurrentPTS = 0;
m_nArraySize = 0;
m_nInputTimeStamp = 0;
for(std::vector<mfxFrameSurface1*>::iterator it = m_LockedSurfacesList.begin(); it != m_LockedSurfacesList.end(); ++it)
{
msdk_atomic_dec16((volatile mfxU16*)(&(*it)->Data.Locked));
}
m_LockedSurfacesList.clear();
m_nIncreaseTime = (mfxU64)((mfxF64)MFX_TIME_STAMP_FREQUENCY * par->vpp.Out.FrameRateExtD / par->vpp.Out.FrameRateExtN);
MSDK_MEMCPY_VAR(m_VideoParams, par, sizeof(mfxVideoParam));
m_VideoParams.vpp.In.FrameRateExtD = m_VideoParams.vpp.Out.FrameRateExtD;
m_VideoParams.vpp.In.FrameRateExtN = m_VideoParams.vpp.Out.FrameRateExtN;
sts = MFXVideoVPP::Init(&m_VideoParams);
m_VideoParams.vpp.In.FrameRateExtD = par->vpp.In.FrameRateExtD;
m_VideoParams.vpp.In.FrameRateExtN = par->vpp.In.FrameRateExtN;
return sts;
}
mfxStatus MFXVideoVPPEx::GetVideoParam(mfxVideoParam *par)
{
mfxStatus sts = MFXVideoVPP::GetVideoParam(par);
if (MFX_ERR_NONE == sts)
{
par->vpp.In.FrameRateExtD = m_VideoParams.vpp.In.FrameRateExtD;
par->vpp.In.FrameRateExtN = m_VideoParams.vpp.In.FrameRateExtN;
par->vpp.Out.FrameRateExtD = m_VideoParams.vpp.Out.FrameRateExtD;
par->vpp.Out.FrameRateExtN = m_VideoParams.vpp.Out.FrameRateExtN;
};
return sts;
};
mfxStatus MFXVideoVPPEx::RunFrameVPPAsync(mfxFrameSurface1 *in, mfxFrameSurface1 *out, mfxExtVppAuxData *aux, mfxSyncPoint *syncp)
{
mfxStatus sts = MFX_ERR_NONE;
if (NULL == out || NULL == syncp)
{
return MFX_ERR_NULL_PTR;
};
if (!in)
{
if (!m_LockedSurfacesList.empty())
{
// subtract 1 to handle minimal difference between input and expected timestamps
if (m_nCurrentPTS - 1 <= m_LockedSurfacesList[0]->Data.TimeStamp)
{
mfxU64 nPTS = m_LockedSurfacesList[0]->Data.TimeStamp;
m_LockedSurfacesList[0]->Data.TimeStamp = m_nCurrentPTS;
sts = MFXVideoVPP::RunFrameVPPAsync(m_LockedSurfacesList[0], out, aux, syncp);
m_LockedSurfacesList[0]->Data.TimeStamp = nPTS;
if (MFX_WRN_DEVICE_BUSY != sts)
{
m_nCurrentPTS += m_nIncreaseTime;
}
}
else
{
for(std::vector<mfxFrameSurface1*>::iterator it = m_LockedSurfacesList.begin(); it != m_LockedSurfacesList.end(); ++it)
{
msdk_atomic_dec16((volatile mfxU16*)(&(*it)->Data.Locked));
}
m_LockedSurfacesList.clear();
return MFXVideoVPP::RunFrameVPPAsync(in, out, aux, syncp);
}
}
else
{
return MFXVideoVPP::RunFrameVPPAsync(in, out, aux, syncp);
}
}
else
{
m_nArraySize = m_LockedSurfacesList.size();
if (!m_nArraySize)
{
m_nCurrentPTS = (mfxU64)in->Data.TimeStamp;
msdk_atomic_inc16((volatile mfxU16*)&in->Data.Locked);
m_LockedSurfacesList.push_back(in);
return MFX_ERR_MORE_DATA;
}
if (1 == m_nArraySize)
{
if (in->Data.TimeStamp < m_nCurrentPTS)
{
return MFX_ERR_MORE_DATA;
}
if (in->Data.TimeStamp > m_LockedSurfacesList[0]->Data.TimeStamp && (in->Data.TimeStamp < m_nCurrentPTS + m_nIncreaseTime/2))
{
return MFX_ERR_MORE_DATA;
}
}
{
mfxStatus stsRunFrame = MFX_ERR_NONE;
m_nInputTimeStamp = m_LockedSurfacesList[0]->Data.TimeStamp;
if (m_nCurrentPTS <= m_LockedSurfacesList[0]->Data.TimeStamp ||
m_nCurrentPTS < (in->Data.TimeStamp - (mfxF64)m_nIncreaseTime/2))
{
m_nInputTimeStamp = m_LockedSurfacesList[0]->Data.TimeStamp;
m_LockedSurfacesList[0]->Data.TimeStamp = m_nCurrentPTS;
stsRunFrame = sts = MFXVideoVPP::RunFrameVPPAsync(m_LockedSurfacesList[0], out, aux, syncp);
m_LockedSurfacesList[0]->Data.TimeStamp = m_nInputTimeStamp;
if (MFX_WRN_DEVICE_BUSY != stsRunFrame)
{
m_nCurrentPTS += m_nIncreaseTime;
}
if (MFX_ERR_NONE == stsRunFrame)
{
sts = MFX_ERR_MORE_SURFACE;
}
}
if (MFX_WRN_DEVICE_BUSY != stsRunFrame)
{
if (1 == m_nArraySize)
{
msdk_atomic_inc16((volatile mfxU16*)&in->Data.Locked);
m_LockedSurfacesList.push_back(in);
}
if (m_nCurrentPTS > m_LockedSurfacesList[0]->Data.TimeStamp &&
m_nCurrentPTS >= (m_LockedSurfacesList[1]->Data.TimeStamp - (mfxF64)m_nIncreaseTime/2))
{
msdk_atomic_dec16((volatile mfxU16*)&m_LockedSurfacesList[0]->Data.Locked);
m_LockedSurfacesList.erase(m_LockedSurfacesList.begin());
if (MFX_ERR_NONE == stsRunFrame)
{
if (stsRunFrame != sts)
{
sts = MFX_ERR_NONE;
}
else
{
sts = MFX_ERR_MORE_DATA;
}
}
}
}
}
}
return sts;
};
#endif