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