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