Skip to content

Commit

Permalink
MythVideoTexture: New class to handle OpenGL video texturing
Browse files Browse the repository at this point in the history
- move specialised video texture handling out of MythRenderOpenGL and
OpenGLVideo
- extend MythGLTexture to track source and 'target' formats as well as
plane count etc
- better support for the various details of software and hardware frame
formats and a better framework to start adding direct rendering support
for formats other than YV12/YV420P
- further changes to OpenGLVideo to come
- N.B. VideoToolBox and MediaCodec changes currently untested
  • Loading branch information
mark-kendall committed Mar 13, 2019
1 parent 2c2881e commit 0c265df
Show file tree
Hide file tree
Showing 17 changed files with 864 additions and 468 deletions.
18 changes: 12 additions & 6 deletions mythtv/libs/libmythtv/libmythtv.pro
Expand Up @@ -474,12 +474,18 @@ using_frontend {
using_opengles: DEFINES += USING_OPENGLES
}

using_opengl_video:DEFINES += USING_OPENGL_VIDEO
using_opengl_video:HEADERS += openglvideo.h videoout_opengl.h
using_opengl_video:HEADERS += openglvideoshaders.h
using_opengl_video:SOURCES += openglvideo.cpp videoout_opengl.cpp
using_opengl_video:HEADERS += mythopenglinterop.h
using_opengl_video:SOURCES += mythopenglinterop.cpp
using_opengl_video {
DEFINES += USING_OPENGL_VIDEO
HEADERS += openglvideo.h
HEADERS += videoout_opengl.h
HEADERS += openglvideoshaders.h
HEADERS += mythopenglinterop.h
HEADERS += mythvideotexture.h
SOURCES += openglvideo.cpp
SOURCES += videoout_opengl.cpp
SOURCES += mythopenglinterop.cpp
SOURCES += mythvideotexture.cpp
}

using_vaapi:using_opengl_video {
DEFINES += USING_VAAPI
Expand Down
12 changes: 0 additions & 12 deletions mythtv/libs/libmythtv/mythframe.cpp
Expand Up @@ -286,18 +286,6 @@ static inline void SSE_splitplanes(uint8_t* dstu, int dstu_pitch,
}
#endif /* ARCH_X86 */

static inline void copyplane(uint8_t* dst, int dst_pitch,
const uint8_t* src, int src_pitch,
int width, int height)
{
for (int y = 0; y < height; y++)
{
memcpy(dst, src, width);
src += src_pitch;
dst += dst_pitch;
}
}

static void splitplanes(uint8_t* dstu, int dstu_pitch,
uint8_t* dstv, int dstv_pitch,
const uint8_t* src, int src_pitch,
Expand Down
44 changes: 44 additions & 0 deletions mythtv/libs/libmythtv/mythframe.h
Expand Up @@ -26,6 +26,7 @@ typedef enum FrameType_
FMT_BGRA,
FMT_YUY2,
FMT_NV12,
FMT_YUYVHQ, // temporary
// these are all endian dependent and higher bit depth
FMT_YUV420P10,
FMT_YUV420P12,
Expand All @@ -40,6 +41,14 @@ typedef enum FrameType_
FMT_NVDEC
} VideoFrameType;

static inline int format_is_hw(VideoFrameType Type)
{
return (Type == FMT_VDPAU) || (Type == FMT_VAAPI) ||
(Type == FMT_DXVA2) || (Type == FMT_OMXEGL) ||
(Type == FMT_MEDIACODEC) || (Type == FMT_VTB) ||
(Type == FMT_NVDEC);
}

typedef struct VideoFrame_
{
VideoFrameType codec;
Expand Down Expand Up @@ -269,6 +278,28 @@ static inline void copy(VideoFrame *dst, const VideoFrame *src)
framecopy(dst, src, true);
}

static inline uint planes(VideoFrameType Type)
{
switch (Type)
{
case FMT_YV12:
case FMT_YUV422P:
case FMT_YUV420P10:
case FMT_YUV420P12:
case FMT_YUV420P16: return 3;
case FMT_NV12: return 2;
case FMT_YUY2:
case FMT_YUYVHQ:
case FMT_BGRA:
case FMT_ARGB32:
case FMT_RGB24:
case FMT_RGB32:
case FMT_RGBA32: return 1;
default: break;
}
return 0;
}

static inline int bitsperpixel(VideoFrameType type)
{
int res = 8;
Expand All @@ -278,6 +309,7 @@ static inline int bitsperpixel(VideoFrameType type)
case FMT_RGBA32:
case FMT_ARGB32:
case FMT_RGB32:
case FMT_YUYVHQ:
res = 32;
break;
case FMT_RGB24:
Expand Down Expand Up @@ -393,6 +425,18 @@ static inline void copybuffer(uint8_t *dstbuffer, const VideoFrame *src,
copy(&frameout, src);
}
}

static inline void copyplane(uint8_t* dst, int dst_pitch,
const uint8_t* src, int src_pitch,
int width, int height)
{
for (int y = 0; y < height; y++)
{
memcpy(dst, src, width);
src += src_pitch;
dst += dst_pitch;
}
}
#endif /* __cplusplus */

#endif
27 changes: 14 additions & 13 deletions mythtv/libs/libmythtv/mythmediacodecinterop.cpp
Expand Up @@ -65,16 +65,20 @@ bool MythMediaCodecInterop::Initialise(QSize Size)
OpenGLLocker locker(m_context);

// Create texture
MythGLTexture *texture = m_context->CreateExternalTexture(Size, false);
if (!texture)
vector<QSize> sizes;
sizes.push_back(Size);
vector<MythVideoTexture*> textures = MythVideoTexture::CreateTextures(m_context, FMT_MEDIACODEC, FMT_RGBA32, sizes);
if (textures.empty())
{
LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to create texture");
return false;
}

// Set the texture type
// N.B. CreateTextures is not GL_TEXTURE_EXTERNAL_OES aware (no Qt enum)
MythVideoTexture *texture = textures[0];
texture->m_target = GL_TEXTURE_EXTERNAL_OES;
m_context->SetTextureFilters(texture, QOpenGLTexture::Linear, QOpenGLTexture::ClampToEdge);
MythVideoTexture::SetTextureFilters(m_context, textures, QOpenGLTexture::Linear, QOpenGLTexture::ClampToEdge);
glBindTexture(GL_TEXTURE_EXTERNAL_OES, texture->m_textureId);

// Create surface
Expand All @@ -91,26 +95,23 @@ bool MythMediaCodecInterop::Initialise(QSize Size)
m_surfaceTexture.object());
if (m_surface.isValid())
{
vector<MythGLTexture*> result;
result.push_back(texture);
m_openglTextures.insert(DUMMY_INTEROP_ID, result);
m_openglTextures.insert(DUMMY_INTEROP_ID, textures);
LOG(VB_GENERAL, LOG_INFO, LOC + "Created Android Surface");
return true;
}
LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to create Android Surface");
}
LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to create Android SurfaceTexture");
m_context->glDeleteTextures(1, &(texture->m_textureId));
m_context->DeleteTexture(texture);
MythVideoTexture::DeleteTextures(m_context, textures);
return false;
}

vector<MythGLTexture*> MythMediaCodecInterop::Acquire(MythRenderOpenGL *Context,
VideoColourSpace *ColourSpace,
VideoFrame *Frame,
FrameScanType)
vector<MythVideoTexture*> MythMediaCodecInterop::Acquire(MythRenderOpenGL *Context,
VideoColourSpace *ColourSpace,
VideoFrame *Frame,
FrameScanType)
{
vector<MythGLTexture*> result;
vector<MythVideoTexture*> result;
if (!Frame)
return result;

Expand Down
6 changes: 3 additions & 3 deletions mythtv/libs/libmythtv/mythmediacodecinterop.h
Expand Up @@ -16,9 +16,9 @@ class MythMediaCodecInterop : public MythOpenGLInterop
public:
static MythMediaCodecInterop* Create(MythRenderOpenGL *Context, QSize Size);
~MythMediaCodecInterop() override;
virtual vector<MythGLTexture*> Acquire (MythRenderOpenGL *Context,
VideoColourSpace *ColourSpace,
VideoFrame *Frame, FrameScanType Scan) override;
virtual vector<MythVideoTexture*> Acquire (MythRenderOpenGL *Context,
VideoColourSpace *ColourSpace,
VideoFrame *Frame, FrameScanType Scan) override;
void* GetSurface(void);

protected:
Expand Down
18 changes: 9 additions & 9 deletions mythtv/libs/libmythtv/mythopenglinterop.cpp
Expand Up @@ -77,12 +77,12 @@ MythOpenGLInterop::Type MythOpenGLInterop::GetInteropType(MythCodecID CodecId)
return supported;
}

vector<MythGLTexture*> MythOpenGLInterop::Retrieve(MythRenderOpenGL *Context,
VideoColourSpace *ColourSpace,
VideoFrame *Frame,
FrameScanType Scan)
vector<MythVideoTexture*> MythOpenGLInterop::Retrieve(MythRenderOpenGL *Context,
VideoColourSpace *ColourSpace,
VideoFrame *Frame,
FrameScanType Scan)
{
vector<MythGLTexture*> result;
vector<MythVideoTexture*> result;
if (!(Context && Frame))
return result;

Expand Down Expand Up @@ -146,16 +146,16 @@ MythOpenGLInterop::~MythOpenGLInterop()
{
OpenGLLocker locker(m_context);
LOG(VB_GENERAL, LOG_INFO, LOC + "Deleting textures");
QHash<GLuint, vector<MythGLTexture*> >::const_iterator it = m_openglTextures.constBegin();
QHash<GLuint, vector<MythVideoTexture*> >::const_iterator it = m_openglTextures.constBegin();
for ( ; it != m_openglTextures.constEnd(); ++it)
{
vector<MythGLTexture*> textures = it.value();
vector<MythGLTexture*>::iterator it2 = textures.begin();
vector<MythVideoTexture*> textures = it.value();
vector<MythVideoTexture*>::iterator it2 = textures.begin();
for ( ; it2 != textures.end(); ++it2)
{
if ((*it2)->m_textureId)
m_context->glDeleteTextures(1, &(*it2)->m_textureId);
m_context->DeleteTexture(*it2);
MythVideoTexture::DeleteTexture(m_context, *it2);
}
textures.clear();
}
Expand Down
23 changes: 12 additions & 11 deletions mythtv/libs/libmythtv/mythopenglinterop.h
Expand Up @@ -7,6 +7,7 @@
#include "videoouttypes.h"
#include "mythcodecid.h"
#include "mythframe.h"
#include "mythvideotexture.h"

// Std
#include "vector"
Expand All @@ -31,18 +32,18 @@ class MythOpenGLInterop : public ReferenceCounter
MEDIACODEC = 6
};

static QStringList GetAllowedRenderers (MythCodecID CodecId);
static Type GetInteropType (MythCodecID CodecId);
static vector<MythGLTexture*> Retrieve (MythRenderOpenGL *Context,
VideoColourSpace *ColourSpace,
VideoFrame *Frame,
FrameScanType Scan);
static QString TypeToString (Type InteropType);
static QStringList GetAllowedRenderers (MythCodecID CodecId);
static Type GetInteropType (MythCodecID CodecId);
static vector<MythVideoTexture*> Retrieve(MythRenderOpenGL *Context,
VideoColourSpace *ColourSpace,
VideoFrame *Frame,
FrameScanType Scan);
static QString TypeToString (Type InteropType);

virtual ~MythOpenGLInterop();
virtual vector<MythGLTexture*> Acquire (MythRenderOpenGL *Context,
VideoColourSpace *ColourSpace,
VideoFrame *Frame, FrameScanType Scan) = 0;
virtual vector<MythVideoTexture*> Acquire(MythRenderOpenGL *Context,
VideoColourSpace *ColourSpace,
VideoFrame *Frame, FrameScanType Scan) = 0;
Type GetType(void);

protected:
Expand All @@ -51,7 +52,7 @@ class MythOpenGLInterop : public ReferenceCounter
protected:
MythRenderOpenGL *m_context;
Type m_type;
QHash<GLuint, vector<MythGLTexture*> > m_openglTextures;
QHash<GLuint, vector<MythVideoTexture*> > m_openglTextures;
QSize m_openglTextureSize;
};

Expand Down

0 comments on commit 0c265df

Please sign in to comment.