MythTV  master
mythmediacodecinterop.cpp
Go to the documentation of this file.
1 // MythTV
2 #include "mythcorecontext.h"
3 #include "mythvideocolourspace.h"
5 
6 // FFmpeg
7 extern "C" {
8 #include "libavutil/hwcontext_mediacodec.h"
9 #include "libavcodec/mediacodec.h"
10 }
11 
12 #define LOC QString("MediaCodecInterop: ")
13 
15  MythRenderOpenGL* Context,
16  QSize Size)
17 {
18  if (Player && Context)
19  {
20  if (auto * result = new MythMediaCodecInterop(Player, Context); result != nullptr)
21  {
22  if (result->Initialise(Size))
23  return result;
24  delete result;
25  }
26  }
27  return nullptr;
28 }
29 
31  : MythOpenGLInterop(Context, GL_MEDIACODEC, Player),
32  m_frameWait(),
33  m_frameWaitLock(),
34  m_colourSpaceInitialised(false),
35  m_surface(),
36  m_surfaceTexture(),
37  m_surfaceListener(),
38  m_textureTransform(nullptr),
39  m_transform()
40 {
41  jfloatArray transform = QAndroidJniEnvironment()->NewFloatArray(16);
42  m_textureTransform = jfloatArray(QAndroidJniEnvironment()->NewGlobalRef(transform));
43  QAndroidJniEnvironment()->DeleteLocalRef(transform);
44 }
45 
47 {
48  QAndroidJniEnvironment()->DeleteGlobalRef(m_textureTransform);
49 }
50 
52 {
53  return m_surface.object();
54 }
55 
56 void Java_org_mythtv_video_SurfaceTextureListener_frameAvailable(JNIEnv*, jobject, jlong Wait, jobject)
57 {
58  QWaitCondition *wait = reinterpret_cast<QWaitCondition*>(Wait);
59  if (wait)
60  wait->wakeAll();
61 }
62 
64 {
65  if (!m_openglContext)
66  return false;
67 
68  if (!gCoreContext->IsUIThread())
69  {
70  LOG(VB_GENERAL, LOG_ERR, LOC + "Must be created in UI thread");
71  return false;
72  }
73 
74  // Lock
76 
77  // Create texture
78  vector<QSize> sizes;
79  sizes.push_back(Size);
80  vector<MythVideoTextureOpenGL*> textures =
82  if (textures.empty())
83  {
84  LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to create texture");
85  return false;
86  }
87 
88  // Set the texture type
89  MythVideoTextureOpenGL *texture = textures[0];
90  m_openglContext->glBindTexture(GL_TEXTURE_EXTERNAL_OES, texture->m_textureId);
91 
92  // Create surface
93  m_surfaceTexture = QAndroidJniObject("android/graphics/SurfaceTexture", "(I)V", texture->m_textureId);
94  m_surfaceListener = QAndroidJniObject("org/mythtv/video/SurfaceTextureListener", "(J)V", jlong(&m_frameWait));
95  if (m_surfaceTexture.isValid() && m_surfaceListener.isValid())
96  {
97  m_surfaceTexture.callMethod<void>("setOnFrameAvailableListener",
98  "(Landroid/graphics/SurfaceTexture$OnFrameAvailableListener;)V",
99  m_surfaceListener.object());
100  m_surface = QAndroidJniObject("android/view/Surface",
101  "(Landroid/graphics/SurfaceTexture;)V",
102  m_surfaceTexture.object());
103  if (m_surface.isValid())
104  {
105  m_openglTextures.insert(DUMMY_INTEROP_ID, textures);
106  LOG(VB_GENERAL, LOG_INFO, LOC + "Created Android Surface");
107  return true;
108  }
109  LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to create Android Surface");
110  }
111  LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to create Android SurfaceTexture");
113  return false;
114 }
115 
116 vector<MythVideoTextureOpenGL*> MythMediaCodecInterop::Acquire(MythRenderOpenGL *Context,
117  MythVideoColourSpace *ColourSpace,
120 {
121  vector<MythVideoTextureOpenGL*> result;
122  if (!Frame)
123  return result;
124 
125  // Pause frame handling - we can never release the same buffer twice
126  if (!Frame->m_buffer)
127  {
128  if (!m_openglTextures.isEmpty())
130  return result;
131  }
132 
133  // Sanitise
134  if (!Context || !ColourSpace || m_openglTextures.isEmpty())
135  {
136  LOG(VB_GENERAL, LOG_ERR, LOC + "Failed");
137  return result;
138  }
139 
140  // Check colourspace on first frame
142  {
145  ColourSpace->UpdateColourSpace(Frame);
146  }
147 
148  // Retrieve buffer
149  AVMediaCodecBuffer *buffer = reinterpret_cast<AVMediaCodecBuffer*>(Frame->m_buffer);
150  if (!buffer)
151  {
152  LOG(VB_GENERAL, LOG_ERR, LOC + "No AVMediaCodecBuffer");
153  return result;
154  }
155 
156  // Render...
157  m_frameWaitLock.lock();
158  if (av_mediacodec_release_buffer(buffer, 1) < 0)
159  LOG(VB_GENERAL, LOG_ERR , LOC + "av_mediacodec_release_buffer failed");
160 
161  // Wait for completion
162  if (!m_frameWait.wait(&m_frameWaitLock, 10))
163  LOG(VB_GENERAL, LOG_WARNING, LOC + "Timed out waiting for frame update");
164  m_frameWaitLock.unlock();
165 
166  // Ensure we don't try and release it again
167  Frame->m_buffer = nullptr;
168 
169  // Update texture
170  m_surfaceTexture.callMethod<void>("updateTexImage");
171 
172  // Retrieve and set transform
173  m_surfaceTexture.callMethod<void>("getTransformMatrix", "([F)V", m_textureTransform);
174  QAndroidJniEnvironment()->GetFloatArrayRegion(m_textureTransform, 0, 16, m_transform.data());
175  m_openglTextures[DUMMY_INTEROP_ID][0]->m_transform = &m_transform;
176  m_openglTextures[DUMMY_INTEROP_ID][0]->m_flip = false;
177 
179 }
FMT_MEDIACODEC
@ FMT_MEDIACODEC
Definition: mythframe.h:59
MythMediaCodecInterop::MythMediaCodecInterop
MythMediaCodecInterop(MythPlayerUI *Player, MythRenderOpenGL *Context)
Definition: mythmediacodecinterop.cpp:30
false
VERBOSE_PREAMBLE false
Definition: verbosedefs.h:85
MythVideoTextureOpenGL
Definition: mythvideotextureopengl.h:21
mythmediacodecinterop.h
Frame
Definition: zmdefines.h:93
MythMediaCodecInterop::Initialise
bool Initialise(QSize Size)
Definition: mythmediacodecinterop.cpp:63
MythVideoColourSpace::UpdateColourSpace
bool UpdateColourSpace(const MythVideoFrame *Frame)
Set the current colourspace to use.
Definition: mythvideocolourspace.cpp:338
FrameScanType
FrameScanType
Definition: videoouttypes.h:94
MythCoreContext::IsUIThread
bool IsUIThread(void)
Definition: mythcorecontext.cpp:1357
MythVideoColourSpace::SetSupportedAttributes
void SetSupportedAttributes(PictureAttributeSupported Supported)
Enable the given set of picture attributes.
Definition: mythvideocolourspace.cpp:128
LOG
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:23
MythMediaCodecInterop::m_frameWait
QWaitCondition m_frameWait
Definition: mythmediacodecinterop.h:29
kPictureAttributeSupported_None
@ kPictureAttributeSupported_None
Definition: videoouttypes.h:118
MythMediaCodecInterop::m_colourSpaceInitialised
bool m_colourSpaceInitialised
Definition: mythmediacodecinterop.h:31
GL_TEXTURE_EXTERNAL_OES
#define GL_TEXTURE_EXTERNAL_OES
Definition: mythrenderopengldefs.h:13
MythPlayerUI
Definition: mythplayerui.h:10
mythvideocolourspace.h
MythOpenGLInterop
Definition: mythopenglinterop.h:17
MythOpenGLInterop::m_openglTextures
QHash< unsigned long long, vector< MythVideoTextureOpenGL * > > m_openglTextures
Definition: mythopenglinterop.h:39
MythOpenGLInterop::m_openglContext
MythRenderOpenGL * m_openglContext
Definition: mythopenglinterop.h:38
DUMMY_INTEROP_ID
#define DUMMY_INTEROP_ID
Definition: mythinteropgpu.h:19
MythMediaCodecInterop::~MythMediaCodecInterop
~MythMediaCodecInterop() override
Definition: mythmediacodecinterop.cpp:46
MythMediaCodecInterop::m_surfaceListener
QAndroidJniObject m_surfaceListener
Definition: mythmediacodecinterop.h:34
MythMediaCodecInterop::m_surfaceTexture
QAndroidJniObject m_surfaceTexture
Definition: mythmediacodecinterop.h:33
MythMediaCodecInterop::GetSurface
void * GetSurface(void)
Definition: mythmediacodecinterop.cpp:51
gCoreContext
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
Definition: mythcorecontext.cpp:60
MythMediaCodecInterop::m_frameWaitLock
QMutex m_frameWaitLock
Definition: mythmediacodecinterop.h:30
MythMediaCodecInterop::m_surface
QAndroidJniObject m_surface
Definition: mythmediacodecinterop.h:32
MythRenderOpenGL
Definition: mythrenderopengl.h:96
MythMediaCodecInterop
Definition: mythmediacodecinterop.h:14
MythGLTexture::m_textureId
GLuint m_textureId
Definition: mythrenderopengl.h:65
mythcorecontext.h
MythVideoTextureOpenGL::DeleteTextures
static void DeleteTextures(MythRenderOpenGL *Context, std::vector< MythVideoTextureOpenGL * > &Textures)
Definition: mythvideotextureopengl.cpp:31
MythMediaCodecInterop::m_textureTransform
jfloatArray m_textureTransform
Definition: mythmediacodecinterop.h:35
Java_org_mythtv_video_SurfaceTextureListener_frameAvailable
void Java_org_mythtv_video_SurfaceTextureListener_frameAvailable(JNIEnv *, jobject, jlong Wait, jobject)
Definition: mythmediacodecinterop.cpp:56
LOC
#define LOC
Definition: mythmediacodecinterop.cpp:12
Player
Definition: zmliveplayer.h:34
MythVideoFrame
Definition: mythframe.h:85
MythVideoColourSpace
MythVideoColourSpace contains a QMatrix4x4 that can convert YCbCr data to RGB.
Definition: mythvideocolourspace.h:20
MythVideoTextureOpenGL::CreateTextures
static std::vector< MythVideoTextureOpenGL * > CreateTextures(MythRenderOpenGL *Context, VideoFrameType Type, VideoFrameType Format, std::vector< QSize > Sizes, GLenum Target=QOpenGLTexture::Target2D)
Create a set of textures suitable for the given Type and Format.
Definition: mythvideotextureopengl.cpp:57
MythMediaCodecInterop::CreateMediaCodec
static MythMediaCodecInterop * CreateMediaCodec(MythPlayerUI *Player, MythRenderOpenGL *Context, QSize Size)
Definition: mythmediacodecinterop.cpp:14
MythMediaCodecInterop::Acquire
virtual vector< MythVideoTextureOpenGL * > Acquire(MythRenderOpenGL *Context, MythVideoColourSpace *ColourSpace, MythVideoFrame *Frame, FrameScanType Scan) override
Definition: mythmediacodecinterop.cpp:116
MythMediaCodecInterop::m_transform
QMatrix4x4 m_transform
Definition: mythmediacodecinterop.h:36
FMT_RGBA32
@ FMT_RGBA32
Definition: mythframe.h:33
OpenGLLocker
Definition: mythrenderopengl.h:252