Skip to content
Permalink
Browse files

mmalffmpeg: Move gpu image pool into a separate class

  • Loading branch information...
popcornmix committed Jun 29, 2016
1 parent 0b435db commit 8801d8eceabb34f897b8dd4bd8b32e78f348c534
@@ -42,26 +42,28 @@ using namespace MMAL;

#define CLASSNAME "CMMALYUVBuffer"

CMMALYUVBuffer::CMMALYUVBuffer(CDecoder *dec, unsigned int width, unsigned int height, unsigned int aligned_width, unsigned int aligned_height)
: m_dec(dec)
CMMALYUVBuffer::CMMALYUVBuffer(CGPUPool *gpu_pool, uint32_t mmal_encoding, unsigned int width, unsigned int height, unsigned int aligned_width, unsigned int aligned_height)
: m_gpu_pool(gpu_pool), m_mmal_encoding(mmal_encoding)
{
unsigned int size_pic = 0;
dec->Acquire();
m_gpu_pool->Acquire();
m_width = width;
m_height = height;
m_aligned_width = aligned_width;
m_aligned_height = aligned_height;
m_aspect_ratio = 0.0f;
mmal_buffer = nullptr;
m_interlace_mode = MMAL_InterlaceProgressive;
if (dec->m_fmt == AV_PIX_FMT_YUV420P)
if (mmal_encoding == MMAL_ENCODING_I420)
size_pic = (m_aligned_width * m_aligned_height * 3) >> 1;
else if (dec->m_fmt == AV_PIX_FMT_BGR0)
else if (mmal_encoding == MMAL_ENCODING_YUVUV128)
size_pic = (m_aligned_width * m_aligned_height * 3) >> 0; // hack: find correct size
else if (m_mmal_encoding == MMAL_ENCODING_ARGB || m_mmal_encoding == MMAL_ENCODING_RGBA || m_mmal_encoding == MMAL_ENCODING_ABGR || m_mmal_encoding == MMAL_ENCODING_BGRA)
size_pic = (m_aligned_width << 2) * m_aligned_height;
else if (dec->m_fmt == AV_PIX_FMT_RGB565LE)
else if (m_mmal_encoding == MMAL_ENCODING_RGB16)
size_pic = (m_aligned_width << 1) * m_aligned_height;
else assert(0);
gmem = m_dec->AllocateBuffer(size_pic);
gmem = m_gpu_pool->AllocateBuffer(size_pic);
if (gmem)
gmem->m_opaque = (void *)this;
if (g_advancedSettings.CanLogComponent(LOGVIDEO))
@@ -73,14 +75,46 @@ CMMALYUVBuffer::~CMMALYUVBuffer()
if (g_advancedSettings.CanLogComponent(LOGVIDEO))
CLog::Log(LOGDEBUG, "%s::%s buf:%p gmem:%p", CLASSNAME, __FUNCTION__, this, gmem);
if (gmem)
m_dec->ReleaseBuffer(gmem);
m_gpu_pool->ReleaseBuffer(gmem);
gmem = nullptr;
if (mmal_buffer)
mmal_buffer_header_release(mmal_buffer);
m_gpu_pool->Release();
}

CGPUPool::CGPUPool(CDVDVideoCodecFFmpeg::IHardwareDecoder *dec)
: m_dec(dec)
{
m_dec->Acquire();
m_closing = false;
}

CGPUPool::~CGPUPool()
{
m_dec->Release();
}

CGPUMEM *CDecoder::AllocateBuffer(unsigned int size_pic)
void CGPUPool::Close()
{
CSingleLock lock(m_section);

if (g_advancedSettings.CanLogComponent(LOGVIDEO))
CLog::Log(LOGDEBUG, "%s::%s - close %p", CLASSNAME, __FUNCTION__, this);

m_closing = true;
while (!m_freeBuffers.empty())
{
CGPUMEM *gmem = m_freeBuffers.front();
m_freeBuffers.pop_front();
delete gmem;
}
assert(m_freeBuffers.empty());

if (g_advancedSettings.CanLogComponent(LOGVIDEO))
CLog::Log(LOGDEBUG,"%s::%s", CLASSNAME, __FUNCTION__);
}

CGPUMEM *CGPUPool::AllocateBuffer(unsigned int size_pic)
{
CSingleLock lock(m_section);
CGPUMEM *gmem = nullptr;
@@ -101,7 +135,7 @@ CGPUMEM *CDecoder::AllocateBuffer(unsigned int size_pic)
return gmem;
}

void CDecoder::ReleaseBuffer(CGPUMEM *gmem)
void CGPUPool::ReleaseBuffer(CGPUMEM *gmem)
{
CSingleLock lock(m_section);
if (m_closing)
@@ -110,7 +144,7 @@ void CDecoder::ReleaseBuffer(CGPUMEM *gmem)
m_freeBuffers.push_back(gmem);
}

void CDecoder::AlignedSize(AVCodecContext *avctx, int &w, int &h)
void CGPUPool::AlignedSize(AVCodecContext *avctx, int &w, int &h)
{
AVFrame picture;
int unaligned;
@@ -134,14 +168,45 @@ void CDecoder::AlignedSize(AVCodecContext *avctx, int &w, int &h)
} while (unaligned);
}

CMMALYUVBuffer *CDecoder::GetBuffer(unsigned int width, unsigned int height, AVCodecContext *avctx)
CMMALYUVBuffer *CGPUPool::GetBuffer(enum AVPixelFormat fmt, unsigned int width, unsigned int height, AVCodecContext *avctx)
{
CSingleLock lock(m_section);
// ffmpeg requirements
int aligned_width = width;
int aligned_height = height;
AlignedSize(avctx, aligned_width, aligned_height);
return new CMMALYUVBuffer(this, width, height, aligned_width, aligned_height);
uint32_t mmal_format = 0;
if (fmt == AV_PIX_FMT_YUV420P)
mmal_format = MMAL_ENCODING_I420;
else if (fmt == AV_PIX_FMT_ARGB)
mmal_format = MMAL_ENCODING_ARGB;
else if (fmt == AV_PIX_FMT_RGBA)
mmal_format = MMAL_ENCODING_RGBA;
else if (fmt == AV_PIX_FMT_ABGR)
mmal_format = MMAL_ENCODING_ABGR;
else if (fmt == AV_PIX_FMT_BGRA)
mmal_format = MMAL_ENCODING_BGRA;
else if (fmt == AV_PIX_FMT_RGB565LE)
mmal_format = MMAL_ENCODING_RGB16;
if (mmal_format == 0)
return nullptr;
return new CMMALYUVBuffer(this, mmal_format, width, height, aligned_width, aligned_height);
}

MMAL_BUFFER_HEADER_T *CGPUPool::GetMmal(MMAL_POOL_T *render_pool)
{
MMAL_BUFFER_HEADER_T *mmal_buffer = mmal_queue_timedwait(render_pool->queue, 500);
if (!mmal_buffer)
{
CLog::Log(LOGERROR, "%s::%s - mmal_queue_get failed", CLASSNAME, __FUNCTION__);
return nullptr;
}
mmal_buffer_header_reset(mmal_buffer);
mmal_buffer->cmd = 0;
mmal_buffer->offset = 0;
mmal_buffer->flags = 0;
mmal_buffer->user_data = NULL;
return mmal_buffer;
}

//-----------------------------------------------------------------------------
@@ -152,13 +217,13 @@ CMMALYUVBuffer *CDecoder::GetBuffer(unsigned int width, unsigned int height, AVC
#define CLASSNAME "CDecoder"

CDecoder::CDecoder()
: m_gpu_pool(this)
{
if (g_advancedSettings.CanLogComponent(LOGVIDEO))
CLog::Log(LOGDEBUG, "%s::%s - create %p", CLASSNAME, __FUNCTION__, this);
m_shared = 0;
m_avctx = nullptr;
m_renderer = nullptr;
m_closing = false;
}

CDecoder::~CDecoder()
@@ -178,21 +243,7 @@ long CDecoder::Release()
void CDecoder::Close()
{
CSingleLock lock(m_section);

m_closing = true;
if (g_advancedSettings.CanLogComponent(LOGVIDEO))
CLog::Log(LOGDEBUG, "%s::%s - close %p", CLASSNAME, __FUNCTION__, this);

while (!m_freeBuffers.empty())
{
CGPUMEM *gmem = m_freeBuffers.front();
m_freeBuffers.pop_front();
delete gmem;
}
assert(m_freeBuffers.empty());

if (g_advancedSettings.CanLogComponent(LOGVIDEO))
CLog::Log(LOGDEBUG,"%s::%s", CLASSNAME, __FUNCTION__);
m_gpu_pool.Close();
}

void CDecoder::FFReleaseBuffer(void *opaque, uint8_t *data)
@@ -220,7 +271,7 @@ int CDecoder::FFGetBuffer(AVCodecContext *avctx, AVFrame *frame, int flags)

CSingleLock lock(dec->m_section);

CMMALYUVBuffer *YUVBuffer = dec->GetBuffer(frame->width, frame->height, dec->m_avctx);
CMMALYUVBuffer *YUVBuffer = dec->m_gpu_pool.GetBuffer(dec->m_fmt, frame->width, frame->height, dec->m_avctx);

CGPUMEM *gmem = YUVBuffer->gmem;
AVBufferRef *buf = av_buffer_create((uint8_t *)gmem->m_arm, (YUVBuffer->m_aligned_width * YUVBuffer->m_aligned_height * 3)>>1, CDecoder::FFReleaseBuffer, gmem, AV_BUFFER_FLAG_READONLY);
@@ -306,28 +357,6 @@ int CDecoder::Decode(AVCodecContext* avctx, AVFrame* frame)
return VC_BUFFER;
}

MMAL_BUFFER_HEADER_T *CDecoder::GetMmal()
{
if (!m_pool)
m_pool = m_renderer->GetPool(RENDER_FMT_MMAL, m_fmt, false);

assert(m_pool);
MMAL_POOL_T *render_pool = m_pool->Get();
assert(render_pool);
MMAL_BUFFER_HEADER_T *mmal_buffer = mmal_queue_timedwait(render_pool->queue, 500);
if (!mmal_buffer)
{
CLog::Log(LOGERROR, "%s::%s - mmal_queue_get failed", CLASSNAME, __FUNCTION__);
return nullptr;
}
mmal_buffer_header_reset(mmal_buffer);
mmal_buffer->cmd = 0;
mmal_buffer->offset = 0;
mmal_buffer->flags = 0;
mmal_buffer->user_data = NULL;
return mmal_buffer;
}

bool CDecoder::GetPicture(AVCodecContext* avctx, AVFrame* frame, DVDVideoPicture* picture)
{
CDVDVideoCodecFFmpeg* ctx = (CDVDVideoCodecFFmpeg*)avctx->opaque;
@@ -339,7 +368,13 @@ bool CDecoder::GetPicture(AVCodecContext* avctx, AVFrame* frame, DVDVideoPicture
frame->buf[1] != nullptr || frame->buf[0] == nullptr)
return false;

MMAL_BUFFER_HEADER_T *mmal_buffer = GetMmal();
if (!m_pool)
m_pool = m_renderer->GetPool(RENDER_FMT_MMAL, m_fmt, false);
assert(m_pool);
MMAL_POOL_T *render_pool = m_pool->Get();
assert(render_pool);

MMAL_BUFFER_HEADER_T *mmal_buffer = m_gpu_pool.GetMmal(render_pool);
if (!mmal_buffer)
return false;

@@ -34,17 +34,38 @@ class CGPUMEM;
namespace MMAL {

class CDecoder;
class CGPUPool;

// a mmal video frame
class CMMALYUVBuffer : public CMMALBuffer
{
public:
CMMALYUVBuffer(CDecoder *dec, unsigned int width, unsigned int height, unsigned int aligned_width, unsigned int aligned_height);
CMMALYUVBuffer(CGPUPool *gpu_pool, uint32_t mmal_encoding, unsigned int width, unsigned int height, unsigned int aligned_width, unsigned int aligned_height);
virtual ~CMMALYUVBuffer();

CGPUMEM *gmem;
private:
CDecoder *m_dec;
CGPUPool *m_gpu_pool;
uint32_t m_mmal_encoding;
};

class CGPUPool : public IDVDResourceCounted<CGPUPool>
{
public:
CGPUPool(CDVDVideoCodecFFmpeg::IHardwareDecoder *dec);
virtual ~CGPUPool();
static void AlignedSize(AVCodecContext *avctx, int &w, int &h);
CMMALYUVBuffer *GetBuffer(enum AVPixelFormat fmt, unsigned int width, unsigned int height, AVCodecContext *avctx);
CGPUMEM *AllocateBuffer(unsigned int numbytes);
void ReleaseBuffer(CGPUMEM *gmem);
unsigned sizeFree() { return m_freeBuffers.size(); }
void Close();
MMAL_BUFFER_HEADER_T *GetMmal(MMAL_POOL_T *render_pool);
protected:
CCriticalSection m_section;
std::deque<CGPUMEM *> m_freeBuffers;
CDVDVideoCodecFFmpeg::IHardwareDecoder *m_dec;
bool m_closing;
};

class CDecoder
@@ -65,21 +86,14 @@ class CDecoder
static void FFReleaseBuffer(void *opaque, uint8_t *data);
static int FFGetBuffer(AVCodecContext *avctx, AVFrame *pic, int flags);

static void AlignedSize(AVCodecContext *avctx, int &w, int &h);
CMMALYUVBuffer *GetBuffer(unsigned int width, unsigned int height, AVCodecContext *avctx);
CGPUMEM *AllocateBuffer(unsigned int numbytes);
void ReleaseBuffer(CGPUMEM *gmem);
unsigned sizeFree() { return m_freeBuffers.size(); }
enum AVPixelFormat m_fmt;
protected:
MMAL_BUFFER_HEADER_T *GetMmal();
AVCodecContext *m_avctx;
unsigned int m_shared;
CCriticalSection m_section;
CMMALRenderer *m_renderer;
std::shared_ptr<CMMALPool> m_pool;
std::deque<CGPUMEM *> m_freeBuffers;
bool m_closing;
CGPUPool m_gpu_pool;
enum AVPixelFormat m_fmt;
};

};

0 comments on commit 8801d8e

Please sign in to comment.
You can’t perform that action at this time.