1
0
Fork 0
qsdecoder/sysmem_allocator.cpp

348 lines
10 KiB
C++

/*
* Copyright (c) 2013, 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:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 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.
* Neither the name of INTEL CORPORATION 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.
*/
#include "stdafx.h"
#include "QuickSync_defs.h"
#include "sysmem_allocator.h"
#define ID_BUFFER MFX_MAKEFOURCC('B','U','F','F')
#define ID_FRAME MFX_MAKEFOURCC('F','R','M','E')
#pragma warning(disable : 4100)
//////////////////////////////////////////////////////////////////////////////////////////
// SysMemFrameAllocator
//////////////////////////////////////////////////////////////////////////////////////////
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()
{
if (m_bOwnBufferAllocator)
{
delete m_pBufferAllocator;
m_pBufferAllocator = 0;
}
return BaseFrameAllocator::Close();
}
mfxStatus SysMemFrameAllocator::LockFrame(mfxMemId mid, mfxFrameData *ptr)
{
if (!m_pBufferAllocator)
return MFX_ERR_NOT_INITIALIZED;
if (!ptr)
return MFX_ERR_NULL_PTR;
sFrame *fs = 0;
mfxStatus sts = m_pBufferAllocator->Lock(m_pBufferAllocator->pthis, mid,(mfxU8 **)&fs);
if (MSDK_FAILED(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->Pitch = Width2;
break;
case MFX_FOURCC_YV12:
ptr->V = ptr->Y + Width2 * Height2;
ptr->U = ptr->V + (Width2 >> 1) * (Height2 >> 1);
ptr->Pitch = Width2;
break;
case MFX_FOURCC_YUY2:
ptr->U = ptr->Y + 1;
ptr->V = ptr->Y + 3;
ptr->Pitch = 2 * Width2;
break;
case MFX_FOURCC_RGB3:
ptr->G = ptr->B + 1;
ptr->R = ptr->B + 2;
ptr->Pitch = 3 * Width2;
break;
case MFX_FOURCC_RGB4:
ptr->G = ptr->B + 1;
ptr->R = ptr->B + 2;
ptr->A = ptr->B + 3;
ptr->Pitch = 4 * Width2;
break;
default:
return MFX_ERR_UNSUPPORTED;
}
return MFX_ERR_NONE;
}
mfxStatus SysMemFrameAllocator::UnlockFrame(mfxMemId mid, mfxFrameData *ptr)
{
if (!m_pBufferAllocator)
return MFX_ERR_NOT_INITIALIZED;
mfxStatus sts = m_pBufferAllocator->Unlock(m_pBufferAllocator->pthis, mid);
if (MSDK_FAILED(sts))
return sts;
if (NULL != ptr)
{
ptr->Pitch = 0;
ptr->Y = 0;
ptr->U = 0;
ptr->V = 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 (MSDK_FAILED(sts))
return sts;
if ((request->Type & MFX_MEMTYPE_SYSTEM_MEMORY) != 0)
return MFX_ERR_NONE;
else
return MFX_ERR_UNSUPPORTED;
}
mfxStatus SysMemFrameAllocator::AllocImpl(mfxFrameAllocRequest *request, mfxFrameAllocResponse *response)
{
if (!m_pBufferAllocator)
return MFX_ERR_NOT_INITIALIZED;
mfxU32 numAllocated = 0;
mfxU32 Width2 = MSDK_ALIGN32(request->Info.Width);
mfxU32 Height2 = MSDK_ALIGN32(request->Info.Height);
mfxU32 nbytes;
switch (request->Info.FourCC)
{
case MFX_FOURCC_YV12:
case MFX_FOURCC_NV12:
nbytes = Width2*Height2 + (Width2>>1)*(Height2>>1) + (Width2>>1)*(Height2>>1);
break;
case MFX_FOURCC_RGB3:
nbytes = Width2*Height2 + Width2*Height2 + Width2*Height2;
break;
case MFX_FOURCC_RGB4:
nbytes = Width2*Height2 + Width2*Height2 + Width2*Height2 + Width2*Height2;
break;
case MFX_FOURCC_YUY2:
nbytes = Width2*Height2 + (Width2>>1)*(Height2) + (Width2>>1)*(Height2);
break;
default:
return MFX_ERR_UNSUPPORTED;
}
safe_array<mfxMemId> mids(new mfxMemId[request->NumFrameSuggested]);
if (!mids.get())
return MFX_ERR_MEMORY_ALLOC;
// 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.get()[numAllocated]));
if (MSDK_FAILED(sts))
break;
sFrame *fs;
sts = m_pBufferAllocator->Lock(m_pBufferAllocator->pthis, mids.get()[numAllocated], (mfxU8 **)&fs);
if (MSDK_FAILED(sts))
break;
fs->id = ID_FRAME;
fs->info = request->Info;
m_pBufferAllocator->Unlock(m_pBufferAllocator->pthis, mids.get()[numAllocated]);
}
// check the number of allocated frames
if (numAllocated < request->NumFrameMin)
{
return MFX_ERR_MEMORY_ALLOC;
}
response->NumFrameActual = (mfxU16) numAllocated;
response->mids = mids.release();
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 (MSDK_FAILED(sts))
return sts;
}
}
}
MSDK_SAFE_DELETE_ARRAY(response->mids);
return sts;
}
//////////////////////////////////////////////////////////////////////////////////////////
// SysMemBufferAllocator
//////////////////////////////////////////////////////////////////////////////////////////
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, 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 *)bs + MSDK_ALIGN32(sizeof(sBuffer));
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;
}