Commit 454fc21f authored by Dmitry Ermilov's avatar Dmitry Ermilov

Added sample_hevc_fei_abr

The sample demonstrates HEVC FEI in 1->N transcoding pipelines.
Signed-off-by: default avatarDmitry Ermilov <dmitry.ermilov@intel.com>
parent 8aaaaf5f
find_path( FEI_INCLUDE mfxfeihevc.h PATHS ${MFX_INCLUDE} )
if(FEI_INCLUDE MATCHES NOTFOUND)
set(skipping _force_skipping)
endif()
find_path( VA_HEVC_FEI va/va_fei_hevc.h PATHS ${PKG_LIBVA_INCLUDEDIR} )
if(VA_HEVC_FEI MATCHES NOTFOUND)
set(skipping _force_skipping)
endif()
if(NOT API_USE_LATEST)
set(skipping _force_skipping)
endif()
include_directories (
${CMAKE_CURRENT_SOURCE_DIR}/../sample_common/include
${CMAKE_CURRENT_SOURCE_DIR}/include/dso
${CMAKE_CURRENT_SOURCE_DIR}/include
)
list( APPEND LIBS_VARIANT sample_common )
set(DEPENDENCIES ${skipping} itt libmfx dl pthread)
set( defs "${API_FLAGS} ${WARNING_FLAGS}" )
make_executable( shortname universal "nosafestring" )
install( TARGETS ${target} RUNTIME DESTINATION ${MFX_SAMPLES_INSTALL_BIN_DIR} )
set( defs "" )
/******************************************************************************\
Copyright (c) 2018, 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.
\**********************************************************************************/
#pragma once
#include "task.h"
#include "brc_routines.h"
#include <cmath>
#include <algorithm>
#include <vector>
#ifdef DEBUG_OUTPUT
#include<cstdio>
#endif
namespace
{
// Magic part
constexpr mfxU32 BRC3_RATE_BLUR_LENGTH = 10;
constexpr mfxF64 BRC3_GAUSS_VARIANCE = 160.0;
constexpr mfxF64 BRC3_BLUR_STOP = 0.001;
constexpr mfxF64 BRC3_DIST_COMPL_EXPONENT = 0.5;
constexpr mfxF64 BRC3_PROPAGATION_EXPONENT = 2.0;
constexpr mfxF64 QSTEP[52] = {
0.630, 0.707, 0.794, 0.891, 1.000, 1.122, 1.260, 1.414, 1.587, 1.782, 2.000, 2.245, 2.520,
2.828, 3.175, 3.564, 4.000, 4.490, 5.040, 5.657, 6.350, 7.127, 8.000, 8.980, 10.079, 11.314,
12.699, 14.254, 16.000, 17.959, 20.159, 22.627, 25.398, 28.509, 32.000, 35.919, 40.317, 45.255, 50.797,
57.018, 64.000, 71.838, 80.635, 90.510, 101.594, 114.035, 128.000, 143.675, 161.270, 181.019, 203.187, 228.070
};
#if 0
mfxU8 QStep2QpCeil(mfxF64 qstep) // QSTEP[qp] > qstep, may return qp=52
{
return mfxU8(std::lower_bound(QSTEP, QSTEP + 52, qstep) - QSTEP);
}
#endif
mfxU8 QStep2QpFloor(mfxF64 qstep) // QSTEP[qp] <= qstep, return 0<=qp<=51
{
mfxU8 qp = mfxU8(std::upper_bound(QSTEP, QSTEP + 52, qstep) - QSTEP);
return qp > 0 ? qp - 1 : 0;
}
mfxU8 QStep2QpNearest(mfxF64 qstep) // return 0<=qp<=51
{
mfxU8 qp = QStep2QpFloor(qstep);
return (qp == 51 || qstep < (QSTEP[qp] + QSTEP[qp + 1]) / 2) ? qp : qp + 1;
}
mfxF64 Qp2QStep(mfxU8 qp)
{
return QSTEP[std::min(mfxU8(51), qp)];
}
#if 0
mfxF64 fQP2Qstep(mfxF64 fqp)
{
return std::pow(2.0, (fqp - 4.0) / 6.0);
}
#endif
}
// BRC interface
class BRC
{
public:
BRC() = default;
BRC(BRC const&) = delete;
BRC(BRC &&) = default;
BRC& operator=(BRC const&) = delete;
BRC& operator=(BRC &&) = default;
virtual ~BRC() {}
virtual void PreEnc(HevcTaskDSO& task /*FrameStatData& statData*/) = 0;
virtual void Report(mfxU32 dataLength) = 0;
virtual mfxU8 GetQP() = 0;
virtual void SubmitNewStat(FrameStatData& stat) = 0;
};
class SW_BRC : public BRC
{
public:
SW_BRC(mfxVideoParam const & video, mfxU16 TargetKbps)
{
//prepare mfxVideoParam for BRC
mfxVideoParam tmp = video;
tmp.mfx.RateControlMethod = MFX_RATECONTROL_VBR;
tmp.mfx.TargetKbps = TargetKbps;
mfxExtCodingOption CO;
MSDK_ZERO_MEMORY(CO);
CO.Header.BufferId = MFX_EXTBUFF_CODING_OPTION;
CO.Header.BufferSz = sizeof(mfxExtCodingOption);
CO.NalHrdConformance = MFX_CODINGOPTION_OFF;
mfxExtBuffer *ext = &CO.Header;
tmp.ExtParam = &ext;
tmp.NumExtParam = 1;
mfxStatus sts = m_SW_BRC.Init(&tmp);
if (MFX_ERR_NONE != sts)
throw mfxError(MFX_ERR_NOT_INITIALIZED, "m_SW_BRC.Init failed");
}
SW_BRC(SW_BRC const&) = delete;
SW_BRC(SW_BRC &&) = default;
SW_BRC& operator=(SW_BRC const&) = delete;
SW_BRC& operator=(SW_BRC &&) = default;
~SW_BRC() {}
void PreEnc(HevcTaskDSO& task /*FrameStatData& statData*/)
{
FrameStatData& statData = task.m_statData;
MSDK_ZERO_MEMORY(m_BRCPar);
MSDK_ZERO_MEMORY(m_BRCCtrl);
m_BRCPar.EncodedOrder = statData.EncodedOrder;
m_BRCPar.DisplayOrder = statData.DisplayOrder;
m_BRCPar.FrameType = statData.frame_type;
mfxStatus sts = m_SW_BRC.GetFrameCtrl(&m_BRCPar, &m_BRCCtrl);
if (MFX_ERR_NONE != sts)
throw mfxError(sts, "m_SW_BRC.GetFrameCtrl failed");
m_curQp = m_BRCCtrl.QpY;
#ifdef DEBUG_OUTPUT
std::cout << std::endl << std::endl << "Frame #" << task.m_statData.DisplayOrder << std::endl;
std::cout << "initial qp: " << mfxI32(task.m_statData.qp) << " qp set: " << mfxI32(m_curQp) << std::endl;
std::cout << "initial size: " << task.m_statData.frame_size << " result size: ";
#endif
}
void Report(mfxU32 dataLength)
{
#ifdef DEBUG_OUTPUT
std::cout << dataLength << std::endl;
#endif
m_BRCPar.CodedFrameSize = dataLength;
mfxBRCFrameStatus bsts;
mfxStatus sts = m_SW_BRC.Update(&m_BRCPar, &m_BRCCtrl, &bsts);
if (MFX_ERR_NONE != sts)
throw mfxError(sts, "m_SW_BRC.Update failed");
if (bsts.BRCStatus != MFX_BRC_OK)
throw mfxError(MFX_ERR_UNDEFINED_BEHAVIOR, "m_SW_BRC.Update failed. Re encode is not supported");
}
mfxU8 GetQP()
{
return m_curQp;
}
void SubmitNewStat(FrameStatData& /*stat*/) { return; }
private:
ExtBRC m_SW_BRC;
mfxU8 m_curQp = 0xff;
mfxU64 m_BitsEncoded = 0;
mfxF64 m_TargetBitrate = 0.0; // it is bits per frame, actually
mfxU32 m_curFrame = 0;
mfxBRCFrameParam m_BRCPar;
mfxBRCFrameCtrl m_BRCCtrl;
};
class LA_BRC : public BRC
{
public:
LA_BRC(mfxVideoParam const & video, mfxU16 TargetKbps, mfxU16 la_depth = 100, msdk_char* yuv_file = nullptr)
: m_LookAheadDepth(la_depth)
, m_TargetBitrate(mfxF64(1000 * TargetKbps * video.mfx.FrameInfo.FrameRateExtD) / video.mfx.FrameInfo.FrameRateExtN)
{
/*
for (mfxU32 j = 1; j < BRC3_RATE_BLUR_LENGTH; ++j)
{
m_normFactors[j - 1] = exp(-(mfxF64)j*j / BRC3_GAUSS_VARIANCE);
}*/
m_frameStatData.reserve(m_LookAheadDepth);
}
LA_BRC(LA_BRC const&) = delete;
LA_BRC(LA_BRC &&) = default;
LA_BRC& operator=(LA_BRC const&) = delete;
LA_BRC& operator=(LA_BRC &&) = default;
~LA_BRC() {}
void PreEnc(HevcTaskDSO& task /*FrameStatData& statData*/);
void Report(mfxU32 dataLength);
mfxU8 GetQP()
{
return m_curQp;
}
void SubmitNewStat(FrameStatData& stat)
{
// Fill some additional information
stat.propagation = 1.0 - std::pow(stat.share_intra, BRC3_PROPAGATION_EXPONENT);
stat.qstep0 = Qp2QStep(stat.qp);
stat.complexity0 = stat.qstep0*stat.frame_size;
m_frameStatData.push_back(stat);
}
private:
mfxU16 m_LookAheadDepth = 100;
mfxU8 m_curQp = 0xff;
mfxF64 m_avMSE = 0.0;
mfxF64 m_TargetBitrate = 0.0; // it is bits per frame, actually
mfxU32 m_curFrame = 0;
#ifdef SEPARATE_IP_B_PROCESSING
mfxU64 m_IP_BitsEncoded = 0;
mfxU64 m_IP_BitsPredicted = 0;
mfxU64 m_B_BitsEncoded = 0;
mfxU64 m_B_BitsPredicted = 0;
#else
mfxU64 m_BitsEncoded = 0;
mfxU64 m_BitsPredicted = 0;
#endif
//mfxF64 m_normFactors[BRC3_RATE_BLUR_LENGTH - 1];
std::vector<FrameStatData> m_frameStatData;
// Update internal state with new frame
void UpdateStatData(mfxU32 frame_number);
bool PossibleEncodeAsIs(mfxU32 start_index = 0);
};
/******************************************************************************\
Copyright (c) 2018, 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.
\**********************************************************************************/
#pragma once
#include <condition_variable>
#include "fei_buffer_allocator.h"
class FeiBufferAllocator;
template <class T, class D = std::default_delete<T>>
class BufferPool
{
private:
struct Return2Pool
{
Return2Pool() :
m_pool(nullptr) {}
explicit
Return2Pool(BufferPool<T, D> * pool) :
m_pool(pool) {}
void operator()(T* ptr)
{
m_pool->Add(std::unique_ptr<T, D>{ptr}); // return back to the pool
}
private:
BufferPool<T, D> * m_pool;
};
public:
using Type = std::unique_ptr<T, Return2Pool>;
BufferPool() {}
~BufferPool()
{
std::for_each(m_pool.begin(), m_pool.end(), [this](std::unique_ptr<T, D> & item)
{ m_allocator->Free(item.get()); }
);
}
// Weakness in design. Consider using a customer deleter for T
// instead of explicit FeiBufferAllocator
void SetDeleter(std::shared_ptr<FeiBufferAllocator> allocator)
{
m_allocator = allocator;
}
void Add(std::unique_ptr<T, D> buffer)
{
std::lock_guard<std::mutex> lock(m_mutex);
m_pool.push_back(std::move(buffer));
m_condition.notify_one();
}
Type GetBuffer()
{
std::unique_lock<std::mutex> lock(m_mutex);
if (m_pool.empty())
{
m_condition.wait(lock, [this] { return !m_pool.empty(); });
}
Type temp(m_pool.front().release(), Return2Pool(this) );
m_pool.pop_front();
return std::move(temp);
}
bool empty() const
{
return m_pool.empty();
}
size_t size() const
{
return m_pool.size();
}
private:
std::list<std::unique_ptr<T, D> > m_pool;
std::mutex m_mutex;
// Signals new free resource added to the pool.
std::condition_variable m_condition;
std::shared_ptr<FeiBufferAllocator> m_allocator;
};
using MVPPool = BufferPool<mfxExtFeiHevcEncMVPredictors>;
using CTUCtrlPool = BufferPool<mfxExtFeiHevcEncCtuCtrl>;
/******************************************************************************\
Copyright (c) 2018, 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.
\**********************************************************************************/
#pragma once
#include "sample_utils.h"
#include "sample_hevc_fei_defs.h"
class CmdProcessor
{
public:
CmdProcessor()
{}
~CmdProcessor()
{}
mfxStatus ParseCmdLine(mfxU32 argc, msdk_char *argv[]);
bool GetNextSessionParams(sInputParams &InputParams);
protected:
mfxStatus ParseParFile(FILE* file);
mfxStatus TokenizeLine(msdk_char *pLine, mfxU32 length);
mfxStatus ParseParamsForOneSession(mfxU32 argc, msdk_char* argv[]);
DISALLOW_COPY_AND_ASSIGN(CmdProcessor);
protected:
mfxU32 m_SessionParamId = 0;
std::vector<sInputParams> m_SessionArray;
msdk_char* m_parName = 0;
};
// Copyright (c) 2018 Intel Corporation
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#pragma once
//#undef __BS_TRACE__
//#define __BS_TRACE__
typedef unsigned char byte;
typedef unsigned char Bs8u;
typedef unsigned short Bs16u;
typedef unsigned int Bs32u;
typedef signed char Bs8s;
typedef signed short Bs16s;
typedef signed int Bs32s;
#ifdef __GNUC__
typedef unsigned long long Bs64u;
typedef signed long long Bs64s;
#else
typedef unsigned __int64 Bs64u;
typedef signed __int64 Bs64s;
#endif
#if defined( _WIN32 ) || defined ( _WIN64 )
#define __STDCALL __stdcall
#define __CDECL __cdecl
#define __INT64 __int64
#define __UINT64 unsigned __int64
#else
#define __STDCALL
#define __CDECL
#define __INT64 long long
#define __UINT64 unsigned long long
#endif
typedef enum {
BS_ERR_NONE = 0,
BS_ERR_UNKNOWN = -1,
BS_ERR_WRONG_UNITS_ORDER = -2,
BS_ERR_MORE_DATA = -3,
BS_ERR_INVALID_PARAMS = -4,
BS_ERR_MEM_ALLOC = -5,
BS_ERR_NOT_IMPLEMENTED = -6,
BS_ERR_NOT_ENOUGH_BUFFER = -7,
BS_ERR_BAD_HANDLE = -8,
BS_ERR_INCOMPLETE_DATA = -9
} BSErr;
#define BS_MIN(x, y) ( ((x) < (y)) ? (x) : (y) )
#define BS_MAX(x, y) ( ((x) > (y)) ? (x) : (y) )
#define BS_ABS(x) ( ((x) > 0) ? (x) : (-(x)) )
// Copyright (c) 2018 Intel Corporation
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#pragma once
#include <map>
#include <list>
#include <set>
#include <mutex>
#include <memory.h>
//#define BS_MEM_TRACE
#ifdef BS_MEM_TRACE
#include <stdio.h>
#endif
namespace BS_MEM
{
class MemBase
{
public:
virtual void* Get() = 0;
virtual ~MemBase(){}
};
template<class T> class MemObj : public MemBase
{
public:
T* m_obj;
bool m_del;
MemObj(unsigned int count, bool zero)
{
m_obj = new T[count];
m_del = true;
if (zero)
memset(m_obj, 0, sizeof(T) * count);
}
MemObj(T* obj)
: m_obj(obj)
, m_del(false)
{}
virtual ~MemObj()
{
if (m_del)
delete[] m_obj;
}
void* Get() { return m_obj; }
};
class MemD
{
public:
MemD()
: locked(0)
, to_delete(false)
, mem(nullptr)
{
}
~MemD()
{
if (mem)
delete mem;
}
unsigned int locked;
bool to_delete;
std::set<void*> base;
std::set<void*> dep;
MemBase* mem;
};
class Allocator
{
private:
std::map<void*, MemD> m_mem;
std::recursive_mutex m_mtx;
bool m_zero;
inline bool Touch(void* p) { return !!m_mem.count(p); }
inline void __notrace(const char*, ...) {}
#ifdef BS_MEM_TRACE
#define BS_MEM_TRACE_F printf
#else
#define BS_MEM_TRACE_F __notrace
#endif
public:
Allocator()
: m_zero(false)
{
}
~Allocator()
{
}
void SetZero(bool zero)
{
std::unique_lock<std::recursive_mutex> _lock(m_mtx);
m_zero = zero;
}
bool touch(void* p)
{
std::unique_lock<std::recursive_mutex> _lock(m_mtx);
BS_MEM_TRACE_F("BS_MEM::touch(%p)\n", p);
return Touch(p);
}
void bound(void* dep, void* base)
{
std::unique_lock<std::recursive_mutex> _lock(m_mtx);
BS_MEM_TRACE_F("BS_MEM::bound(%p, %p)\n", dep, base);
if (!Touch(base) || !Touch(dep))
throw std::bad_alloc();
m_mem[base].dep.insert(dep);
m_mem[dep].base.insert(base);
}
template<class T> T* alloc(void* base = nullptr, unsigned int count = 1)
{
if (count == 0)
return nullptr;
std::unique_lock<std::recursive_mutex> _lock(m_mtx);
MemBase* pObj = new MemObj<T>(count, m_zero);
T* p = (T*)pObj->Get();
m_mem[p].mem = pObj;
BS_MEM_TRACE_F("BS_MEM::alloc(%p, %d) = %p\n", base, count, p);
if (base)
bound(p, base);
return p;
}
template<class T> T* alloc_nozero(void* base = nullptr, unsigned int count = 1)
{
if (count == 0)
return nullptr;
std::unique_lock<std::recursive_mutex> _lock(m_mtx);
MemBase* pObj = new MemObj<T>(count, false);
T* p = (T*)pObj->Get();
m_mem[p].mem = pObj;