MythTV  master
mythmediacodecinterop.cpp
Go to the documentation of this file.
1 // MythTV
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  std::vector<QSize> sizes;
79  sizes.push_back(Size);
80  std::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 std::vector<MythVideoTextureOpenGL*>
118  MythVideoColourSpace *ColourSpace,
121 {
122  std::vector<MythVideoTextureOpenGL*> result;
123  if (!Frame)
124  return result;
125 
126  // Pause frame handling - we can never release the same buffer twice
127  if (!Frame->m_buffer)
128  {
129  if (!m_openglTextures.isEmpty())
131  return result;
132  }
133 
134  // Sanitise
135  if (!Context || !ColourSpace || m_openglTextures.isEmpty())
136  {
137  LOG(VB_GENERAL, LOG_ERR, LOC + "Failed");
138  return result;
139  }
140 
141  // Check colourspace on first frame
143  {
146  ColourSpace->UpdateColourSpace(Frame);
147  }
148 
149  // Retrieve buffer
150  AVMediaCodecBuffer *buffer = reinterpret_cast<AVMediaCodecBuffer*>(Frame->m_buffer);
151  if (!buffer)
152  {
153  LOG(VB_GENERAL, LOG_ERR, LOC + "No AVMediaCodecBuffer");
154  return result;
155  }
156 
157  // Render...
158  m_frameWaitLock.lock();
159  if (av_mediacodec_release_buffer(buffer, 1) < 0)
160  LOG(VB_GENERAL, LOG_ERR , LOC + "av_mediacodec_release_buffer failed");
161 
162  // Wait for completion
163  if (!m_frameWait.wait(&m_frameWaitLock, 10))
164  LOG(VB_GENERAL, LOG_WARNING, LOC + "Timed out waiting for frame update");
165  m_frameWaitLock.unlock();
166 
167  // Ensure we don't try and release it again
168  Frame->m_buffer = nullptr;
169 
170  // Update texture
171  m_surfaceTexture.callMethod<void>("updateTexImage");
172 
173  // Retrieve and set transform
174  m_surfaceTexture.callMethod<void>("getTransformMatrix", "([F)V", m_textureTransform);
175  QAndroidJniEnvironment()->GetFloatArrayRegion(m_textureTransform, 0, 16, m_transform.data());
176  m_openglTextures[DUMMY_INTEROP_ID][0]->m_transform = &m_transform;
177  m_openglTextures[DUMMY_INTEROP_ID][0]->m_flip = false;
178 
180 }
DUMMY_INTEROP_ID
static constexpr uint64_t DUMMY_INTEROP_ID
Definition: mythinteropgpu.h:18
FMT_MEDIACODEC
@ FMT_MEDIACODEC
Definition: mythframe.h:61
MythMediaCodecInterop::MythMediaCodecInterop
MythMediaCodecInterop(MythPlayerUI *Player, MythRenderOpenGL *Context)
Definition: mythmediacodecinterop.cpp:30
QAndroidJniEnvironment
#define QAndroidJniEnvironment
Definition: audiooutputaudiotrack.cpp:8
false
VERBOSE_PREAMBLE false
Definition: verbosedefs.h:89
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:321
FrameScanType
FrameScanType
Definition: videoouttypes.h:94
MythCoreContext::IsUIThread
bool IsUIThread(void)
Definition: mythcorecontext.cpp:1348
MythVideoColourSpace::SetSupportedAttributes
void SetSupportedAttributes(PictureAttributeSupported Supported)
Enable the given set of picture attributes.
Definition: mythvideocolourspace.cpp:111
LOG
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:39
MythMediaCodecInterop::m_frameWait
QWaitCondition m_frameWait
Definition: mythmediacodecinterop.h:36
kPictureAttributeSupported_None
@ kPictureAttributeSupported_None
Definition: videoouttypes.h:118
MythMediaCodecInterop::m_colourSpaceInitialised
bool m_colourSpaceInitialised
Definition: mythmediacodecinterop.h:38
GL_TEXTURE_EXTERNAL_OES
#define GL_TEXTURE_EXTERNAL_OES
Definition: mythrenderopengldefs.h:13
QAndroidJniObject
#define QAndroidJniObject
Definition: audiooutputaudiotrack.cpp:9
MythPlayerUI
Definition: mythplayerui.h:10
mythvideocolourspace.h
MythOpenGLInterop
Definition: mythopenglinterop.h:17
MythOpenGLInterop::m_openglContext
MythRenderOpenGL * m_openglContext
Definition: mythopenglinterop.h:41
MythMediaCodecInterop::~MythMediaCodecInterop
~MythMediaCodecInterop() override
Definition: mythmediacodecinterop.cpp:46
MythMediaCodecInterop::m_surfaceListener
QAndroidJniObject m_surfaceListener
Definition: mythmediacodecinterop.h:41
MythMediaCodecInterop::m_surfaceTexture
QAndroidJniObject m_surfaceTexture
Definition: mythmediacodecinterop.h:40
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:55
MythMediaCodecInterop::m_frameWaitLock
QMutex m_frameWaitLock
Definition: mythmediacodecinterop.h:37
MythMediaCodecInterop::m_surface
QAndroidJniObject m_surface
Definition: mythmediacodecinterop.h:39
MythOpenGLInterop::m_openglTextures
QHash< unsigned long long, std::vector< MythVideoTextureOpenGL * > > m_openglTextures
Definition: mythopenglinterop.h:42
MythRenderOpenGL
Definition: mythrenderopengl.h:96
MythMediaCodecInterop
Definition: mythmediacodecinterop.h:21
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:42
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:88
MythMediaCodecInterop::Acquire
virtual std::vector< MythVideoTextureOpenGL * > Acquire(MythRenderOpenGL *Context, MythVideoColourSpace *ColourSpace, MythVideoFrame *Frame, FrameScanType Scan) override
Definition: mythmediacodecinterop.cpp:117
MythVideoColourSpace
MythVideoColourSpace contains a QMatrix4x4 that can convert YCbCr data to RGB.
Definition: mythvideocolourspace.h:18
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::m_transform
QMatrix4x4 m_transform
Definition: mythmediacodecinterop.h:43
FMT_RGBA32
@ FMT_RGBA32
Definition: mythframe.h:35
OpenGLLocker
Definition: mythrenderopengl.h:255