MythTV master
mythmediacodecinterop.cpp
Go to the documentation of this file.
1// MythTV
4
7
8// FFmpeg
9extern "C" {
10#include "libavutil/hwcontext_mediacodec.h"
11#include "libavcodec/mediacodec.h"
12}
13
14#define LOC QString("MediaCodecInterop: ")
15
17 MythRenderOpenGL* Context,
18 QSize Size)
19{
20 if (Player && Context)
21 {
22 if (auto * result = new MythMediaCodecInterop(Player, Context); result != nullptr)
23 {
24 if (result->Initialise(Size))
25 return result;
26 delete result;
27 }
28 }
29 return nullptr;
30}
31
33 : MythOpenGLInterop(Context, GL_MEDIACODEC, Player)
34{
35 jfloatArray transform = QAndroidJniEnvironment()->NewFloatArray(16);
36 m_textureTransform = jfloatArray(QAndroidJniEnvironment()->NewGlobalRef(transform));
37 QAndroidJniEnvironment()->DeleteLocalRef(transform);
38}
39
41{
43}
44
46{
47 return m_surface.object();
48}
49
50void Java_org_mythtv_video_SurfaceTextureListener_frameAvailable(JNIEnv* /*env*/, jobject /*listener*/, jlong Wait, jobject /*texture*/)
51{
52 // NOLINTNEXTLINE(performance-no-int-to-ptr)
53 auto *wait = reinterpret_cast<QWaitCondition*>(Wait);
54 if (wait)
55 wait->wakeAll();
56}
57
59{
60 if (!m_openglContext)
61 return false;
62
64 {
65 LOG(VB_GENERAL, LOG_ERR, LOC + "Must be created in UI thread");
66 return false;
67 }
68
69 // Lock
71
72 // Create texture
73 std::vector<QSize> sizes;
74 sizes.push_back(Size);
75 std::vector<MythVideoTextureOpenGL*> textures =
77 if (textures.empty())
78 {
79 LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to create texture");
80 return false;
81 }
82
83 // Set the texture type
84 MythVideoTextureOpenGL *texture = textures[0];
85 m_openglContext->glBindTexture(GL_TEXTURE_EXTERNAL_OES, texture->m_textureId);
86
87 // Create surface
88 m_surfaceTexture = QAndroidJniObject("android/graphics/SurfaceTexture", "(I)V", texture->m_textureId);
89 m_surfaceListener = QAndroidJniObject("org/mythtv/video/SurfaceTextureListener", "(J)V", jlong(&m_frameWait));
90 if (m_surfaceTexture.isValid() && m_surfaceListener.isValid())
91 {
92 m_surfaceTexture.callMethod<void>("setOnFrameAvailableListener",
93 "(Landroid/graphics/SurfaceTexture$OnFrameAvailableListener;)V",
94 m_surfaceListener.object());
95 m_surface = QAndroidJniObject("android/view/Surface",
96 "(Landroid/graphics/SurfaceTexture;)V",
97 m_surfaceTexture.object());
98 if (m_surface.isValid())
99 {
100 m_openglTextures.insert(DUMMY_INTEROP_ID, textures);
101 LOG(VB_GENERAL, LOG_INFO, LOC + "Created Android Surface");
102 return true;
103 }
104 LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to create Android Surface");
105 }
106 LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to create Android SurfaceTexture");
108 return false;
109}
110
111std::vector<MythVideoTextureOpenGL*>
113 MythVideoColourSpace *ColourSpace,
115 FrameScanType /*Scan*/)
116{
117 std::vector<MythVideoTextureOpenGL*> result;
118 if (!Frame)
119 return result;
120
121 // Pause frame handling - we can never release the same buffer twice
122 if (!Frame->m_buffer)
123 {
124 if (!m_openglTextures.isEmpty())
126 return result;
127 }
128
129 // Sanitise
130 if (!Context || !ColourSpace || 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 auto *buffer = reinterpret_cast<AVMediaCodecBuffer*>(Frame->m_buffer);
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->m_buffer = 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());
172 m_openglTextures[DUMMY_INTEROP_ID][0]->m_flip = false;
173
175}
#define QAndroidJniEnvironment
#define QAndroidJniObject
MythMediaCodecInterop(MythPlayerUI *Player, MythRenderOpenGL *Context)
QAndroidJniObject m_surface
QAndroidJniObject m_surfaceTexture
std::vector< MythVideoTextureOpenGL * > Acquire(MythRenderOpenGL *Context, MythVideoColourSpace *ColourSpace, MythVideoFrame *Frame, FrameScanType Scan) override
static MythMediaCodecInterop * CreateMediaCodec(MythPlayerUI *Player, MythRenderOpenGL *Context, QSize Size)
QAndroidJniObject m_surfaceListener
MythRenderOpenGL * m_openglContext
QHash< unsigned long long, std::vector< MythVideoTextureOpenGL * > > m_openglTextures
MythVideoColourSpace contains a QMatrix4x4 that can convert YCbCr data to RGB.
void SetSupportedAttributes(PictureAttributeSupported Supported)
Enable the given set of picture attributes.
bool UpdateColourSpace(const MythVideoFrame *Frame)
Set the current colourspace to use.
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.
static void DeleteTextures(MythRenderOpenGL *Context, std::vector< MythVideoTextureOpenGL * > &Textures)
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
@ FMT_RGBA32
Definition: mythframe.h:34
@ FMT_MEDIACODEC
Definition: mythframe.h:60
static constexpr uint64_t DUMMY_INTEROP_ID
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:39
#define LOC
void Java_org_mythtv_video_SurfaceTextureListener_frameAvailable(JNIEnv *, jobject, jlong Wait, jobject)
#define GL_TEXTURE_EXTERNAL_OES
@ kPictureAttributeSupported_None
FrameScanType
Definition: videoouttypes.h:95