1 /*
2 * Copyright (C) 2007-2018 Team Kodi
3 * This file is part of Kodi - https://kodi.tv
4 *
5 * SPDX-License-Identifier: GPL-2.0-or-later
6 * See LICENSES/README.md for more information.
7 */
8
9 #include "RendererMediaCodecSurface.h"
10
11 #include "../RenderCapture.h"
12 #include "../RenderFactory.h"
13 #include "../RenderFlags.h"
14 #include "DVDCodecs/Video/DVDVideoCodecAndroidMediaCodec.h"
15 #include "rendering/RenderSystem.h"
16 #include "settings/MediaSettings.h"
17 #include "utils/TimeUtils.h"
18 #include "utils/log.h"
19 #include "windowing/GraphicContext.h"
20
21 #include "platform/android/activity/XBMCApp.h"
22
23 #include <chrono>
24 #include <thread>
25
CRendererMediaCodecSurface()26 CRendererMediaCodecSurface::CRendererMediaCodecSurface()
27 {
28 CLog::Log(LOGINFO, "Instancing CRendererMediaCodecSurface");
29 }
30
~CRendererMediaCodecSurface()31 CRendererMediaCodecSurface::~CRendererMediaCodecSurface()
32 {
33 Reset();
34 }
35
Create(CVideoBuffer * buffer)36 CBaseRenderer* CRendererMediaCodecSurface::Create(CVideoBuffer *buffer)
37 {
38 if (buffer && dynamic_cast<CMediaCodecVideoBuffer*>(buffer) && !dynamic_cast<CMediaCodecVideoBuffer*>(buffer)->HasSurfaceTexture())
39 return new CRendererMediaCodecSurface();
40 return nullptr;
41 }
42
Register()43 bool CRendererMediaCodecSurface::Register()
44 {
45 VIDEOPLAYER::CRendererFactory::RegisterRenderer("mediacodec_surface", CRendererMediaCodecSurface::Create);
46 return true;
47 }
48
Configure(const VideoPicture & picture,float fps,unsigned int orientation)49 bool CRendererMediaCodecSurface::Configure(const VideoPicture &picture, float fps, unsigned int orientation)
50 {
51 CLog::Log(LOGINFO, "CRendererMediaCodecSurface::Configure");
52
53 m_sourceWidth = picture.iWidth;
54 m_sourceHeight = picture.iHeight;
55 m_renderOrientation = orientation;
56
57 m_iFlags = GetFlagsChromaPosition(picture.chroma_position) |
58 GetFlagsColorMatrix(picture.color_space, picture.iWidth, picture.iHeight) |
59 GetFlagsColorPrimaries(picture.color_primaries) |
60 GetFlagsStereoMode(picture.stereoMode);
61
62 // Calculate the input frame aspect ratio.
63 CalculateFrameAspectRatio(picture.iDisplayWidth, picture.iDisplayHeight);
64 SetViewMode(m_videoSettings.m_ViewMode);
65
66 return true;
67 }
68
GetRenderInfo()69 CRenderInfo CRendererMediaCodecSurface::GetRenderInfo()
70 {
71 CRenderInfo info;
72 info.max_buffer_size = info.optimal_buffer_size = 4;
73 return info;
74 }
75
RenderCapture(CRenderCapture * capture)76 bool CRendererMediaCodecSurface::RenderCapture(CRenderCapture* capture)
77 {
78 capture->BeginRender();
79 capture->EndRender();
80 return true;
81 }
82
AddVideoPicture(const VideoPicture & picture,int index)83 void CRendererMediaCodecSurface::AddVideoPicture(const VideoPicture &picture, int index)
84 {
85 ReleaseBuffer(index);
86
87 BUFFER &buf(m_buffers[index]);
88 if (picture.videoBuffer)
89 {
90 buf.videoBuffer = picture.videoBuffer;
91 buf.videoBuffer->Acquire();
92 }
93 }
94
ReleaseVideoBuffer(int idx,bool render)95 void CRendererMediaCodecSurface::ReleaseVideoBuffer(int idx, bool render)
96 {
97 BUFFER &buf(m_buffers[idx]);
98 if (buf.videoBuffer)
99 {
100 CMediaCodecVideoBuffer *mcvb(dynamic_cast<CMediaCodecVideoBuffer*>(buf.videoBuffer));
101 if (mcvb)
102 {
103 if (render && m_bConfigured)
104 mcvb->RenderUpdate(m_surfDestRect, CXBMCApp::GetNextFrameTime());
105 else
106 mcvb->ReleaseOutputBuffer(render, 0);
107 }
108 buf.videoBuffer->Release();
109 buf.videoBuffer = nullptr;
110 }
111 }
112
ReleaseBuffer(int idx)113 void CRendererMediaCodecSurface::ReleaseBuffer(int idx)
114 {
115 ReleaseVideoBuffer(idx, false);
116 }
117
Supports(ERENDERFEATURE feature)118 bool CRendererMediaCodecSurface::Supports(ERENDERFEATURE feature)
119 {
120 if (feature == RENDERFEATURE_ZOOM || feature == RENDERFEATURE_STRETCH ||
121 feature == RENDERFEATURE_PIXEL_RATIO || feature == RENDERFEATURE_VERTICAL_SHIFT ||
122 feature == RENDERFEATURE_ROTATION)
123 return true;
124
125 return false;
126 }
127
Reset()128 void CRendererMediaCodecSurface::Reset()
129 {
130 for (int i = 0 ; i < 4 ; ++i)
131 ReleaseVideoBuffer(i, false);
132 m_lastIndex = -1;
133 }
134
RenderUpdate(int index,int index2,bool clear,unsigned int flags,unsigned int alpha)135 void CRendererMediaCodecSurface::RenderUpdate(int index, int index2, bool clear, unsigned int flags, unsigned int alpha)
136 {
137 m_bConfigured = true;
138
139 // this hack is needed to get the 2D mode of a 3D movie going
140 RENDER_STEREO_MODE stereo_mode = CServiceBroker::GetWinSystem()->GetGfxContext().GetStereoMode();
141 if (stereo_mode)
142 CServiceBroker::GetWinSystem()->GetGfxContext().SetStereoView(RENDER_STEREO_VIEW_LEFT);
143
144 ManageRenderArea();
145
146 if (stereo_mode)
147 CServiceBroker::GetWinSystem()->GetGfxContext().SetStereoView(RENDER_STEREO_VIEW_OFF);
148
149 m_surfDestRect = m_destRect;
150 switch (stereo_mode)
151 {
152 case RENDER_STEREO_MODE_SPLIT_HORIZONTAL:
153 m_surfDestRect.y2 *= 2.0;
154 break;
155 case RENDER_STEREO_MODE_SPLIT_VERTICAL:
156 m_surfDestRect.x2 *= 2.0;
157 break;
158 case RENDER_STEREO_MODE_MONO:
159 if (CONF_FLAGS_STEREO_MODE_MASK(m_iFlags) == CONF_FLAGS_STEREO_MODE_TAB)
160 m_surfDestRect.y2 = m_surfDestRect.y2 * 2.0;
161 else
162 m_surfDestRect.x2 = m_surfDestRect.x2 * 2.0;
163 break;
164 default:
165 break;
166 }
167
168 if (index != m_lastIndex)
169 {
170 ReleaseVideoBuffer(index, true);
171 m_lastIndex = index;
172 }
173 }
174
ReorderDrawPoints()175 void CRendererMediaCodecSurface::ReorderDrawPoints()
176 {
177 CBaseRenderer::ReorderDrawPoints();
178
179 // Handle orientation
180 switch (m_renderOrientation)
181 {
182 case 90:
183 case 270:
184 {
185 double scale = (double)m_surfDestRect.Height() / m_surfDestRect.Width();
186 int diff = (int) ((m_surfDestRect.Height()*scale - m_surfDestRect.Width()) / 2);
187 m_surfDestRect = CRect(m_surfDestRect.x1 - diff, m_surfDestRect.y1, m_surfDestRect.x2 + diff, m_surfDestRect.y2);
188 }
189 default:
190 break;
191 }
192 }
193