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 m_frameWait(),
35 m_frameWaitLock(),
36 m_colourSpaceInitialised(false),
37 m_surface(),
38 m_surfaceTexture(),
39 m_surfaceListener(),
40 m_textureTransform(nullptr),
41 m_transform()
42{
43 jfloatArray transform = QAndroidJniEnvironment()->NewFloatArray(16);
44 m_textureTransform = jfloatArray(QAndroidJniEnvironment()->NewGlobalRef(transform));
45 QAndroidJniEnvironment()->DeleteLocalRef(transform);
46}
47
49{
51}
52
54{
55 return m_surface.object();
56}
57
58void Java_org_mythtv_video_SurfaceTextureListener_frameAvailable(JNIEnv*, jobject, jlong Wait, jobject)
59{
60 QWaitCondition *wait = reinterpret_cast<QWaitCondition*>(Wait);
61 if (wait)
62 wait->wakeAll();
63}
64
66{
67 if (!m_openglContext)
68 return false;
69
71 {
72 LOG(VB_GENERAL, LOG_ERR, LOC + "Must be created in UI thread");
73 return false;
74 }
75
76 // Lock
78
79 // Create texture
80 std::vector<QSize> sizes;
81 sizes.push_back(Size);
82 std::vector<MythVideoTextureOpenGL*> textures =
84 if (textures.empty())
85 {
86 LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to create texture");
87 return false;
88 }
89
90 // Set the texture type
91 MythVideoTextureOpenGL *texture = textures[0];
92 m_openglContext->glBindTexture(GL_TEXTURE_EXTERNAL_OES, texture->m_textureId);
93
94 // Create surface
95 m_surfaceTexture = QAndroidJniObject("android/graphics/SurfaceTexture", "(I)V", texture->m_textureId);
96 m_surfaceListener = QAndroidJniObject("org/mythtv/video/SurfaceTextureListener", "(J)V", jlong(&m_frameWait));
97 if (m_surfaceTexture.isValid() && m_surfaceListener.isValid())
98 {
99 m_surfaceTexture.callMethod<void>("setOnFrameAvailableListener",
100 "(Landroid/graphics/SurfaceTexture$OnFrameAvailableListener;)V",
101 m_surfaceListener.object());
102 m_surface = QAndroidJniObject("android/view/Surface",
103 "(Landroid/graphics/SurfaceTexture;)V",
104 m_surfaceTexture.object());
105 if (m_surface.isValid())
106 {
107 m_openglTextures.insert(DUMMY_INTEROP_ID, textures);
108 LOG(VB_GENERAL, LOG_INFO, LOC + "Created Android Surface");
109 return true;
110 }
111 LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to create Android Surface");
112 }
113 LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to create Android SurfaceTexture");
115 return false;
116}
117
118std::vector<MythVideoTextureOpenGL*>
120 MythVideoColourSpace *ColourSpace,
123{
124 std::vector<MythVideoTextureOpenGL*> result;
125 if (!Frame)
126 return result;
127
128 // Pause frame handling - we can never release the same buffer twice
129 if (!Frame->m_buffer)
130 {
131 if (!m_openglTextures.isEmpty())
133 return result;
134 }
135
136 // Sanitise
137 if (!Context || !ColourSpace || m_openglTextures.isEmpty())
138 {
139 LOG(VB_GENERAL, LOG_ERR, LOC + "Failed");
140 return result;
141 }
142
143 // Check colourspace on first frame
145 {
148 ColourSpace->UpdateColourSpace(Frame);
149 }
150
151 // Retrieve buffer
152 AVMediaCodecBuffer *buffer = reinterpret_cast<AVMediaCodecBuffer*>(Frame->m_buffer);
153 if (!buffer)
154 {
155 LOG(VB_GENERAL, LOG_ERR, LOC + "No AVMediaCodecBuffer");
156 return result;
157 }
158
159 // Render...
160 m_frameWaitLock.lock();
161 if (av_mediacodec_release_buffer(buffer, 1) < 0)
162 LOG(VB_GENERAL, LOG_ERR , LOC + "av_mediacodec_release_buffer failed");
163
164 // Wait for completion
165 if (!m_frameWait.wait(&m_frameWaitLock, 10))
166 LOG(VB_GENERAL, LOG_WARNING, LOC + "Timed out waiting for frame update");
167 m_frameWaitLock.unlock();
168
169 // Ensure we don't try and release it again
170 Frame->m_buffer = nullptr;
171
172 // Update texture
173 m_surfaceTexture.callMethod<void>("updateTexImage");
174
175 // Retrieve and set transform
176 m_surfaceTexture.callMethod<void>("getTransformMatrix", "([F)V", m_textureTransform);
177 QAndroidJniEnvironment()->GetFloatArrayRegion(m_textureTransform, 0, 16, m_transform.data());
179 m_openglTextures[DUMMY_INTEROP_ID][0]->m_flip = false;
180
182}
#define QAndroidJniEnvironment
#define QAndroidJniObject
MythMediaCodecInterop(MythPlayerUI *Player, MythRenderOpenGL *Context)
QAndroidJniObject m_surface
QAndroidJniObject m_surfaceTexture
virtual 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
VERBOSE_PREAMBLE false
Definition: verbosedefs.h:89
@ kPictureAttributeSupported_None
FrameScanType
Definition: videoouttypes.h:95