RDK Documentation (Open Sourced RDK Components)
AampcliShader.cpp
Go to the documentation of this file.
1 /*
2  * If not stated otherwise in this file or this component's license file the
3  * following copyright and licenses apply:
4  *
5  * Copyright 2022 RDK Management
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  * http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  */
19 
20 /**
21  * @file AampcliShader.cpp
22  * @brief Aampcli shader file.
23  */
24 
25 #include "AampcliShader.h"
26 #include "AampUtils.h"
27 
28 #ifdef RENDER_FRAMES_IN_APP_CONTEXT
29 
30 static const char *VSHADER =
31 "attribute vec2 vertexIn;"
32 "attribute vec2 textureIn;"
33 "varying vec2 textureOut;"
34 "uniform mat4 trans;"
35 "void main() {"
36 "gl_Position = trans * vec4(vertexIn,0, 1);"
37 "textureOut = textureIn;"
38 "}";
39 
40 static const char *FSHADER =
41 "#ifdef GL_ES \n"
42 " precision mediump float; \n"
43 "#endif \n"
44 "varying vec2 textureOut;"
45 "uniform sampler2D tex_y;"
46 "uniform sampler2D tex_u;"
47 "uniform sampler2D tex_v;"
48 "void main() {"
49 "vec3 yuv;"
50 "vec3 rgb;"
51 "yuv.x = texture2D(tex_y, textureOut).r;"
52 "yuv.y = texture2D(tex_u, textureOut).r - 0.5;"
53 "yuv.z = texture2D(tex_v, textureOut).r - 0.5;"
54 "rgb = mat3( 1, 1, 1, 0, -0.39465, 2.03211, 1.13983, -0.58060, 0) * yuv;"
55 "gl_FragColor = vec4(rgb, 1);"
56 "}";
57 
58 AppsinkData Shader::appsinkData = AppsinkData();
59 std::mutex Shader::appsinkData_mutex;
60 GLuint Shader::mProgramID = 0;
61 GLuint Shader::id_y = 0;
62 GLuint Shader::id_u = 0;
63 GLuint Shader::id_v = 0;
64 GLuint Shader::textureUniformY = 0;
65 GLuint Shader::textureUniformU = 0;
66 GLuint Shader::textureUniformV = 0;
67 GLuint Shader::_vertexArray = 0;
68 GLuint Shader::_vertexBuffer[2] = {0};
69 GLfloat Shader::currentAngleOfRotation = 0;
70 
71 GLuint Shader::LoadShader( GLenum type )
72 {
73  GLuint shaderHandle = 0;
74  const char *sources[1];
75 
76  if(GL_VERTEX_SHADER == type)
77  {
78  sources[0] = VSHADER;
79  }
80  else
81  {
82  sources[0] = FSHADER;
83  }
84 
85  if( sources[0] )
86  {
87  shaderHandle = glCreateShader(type);
88  glShaderSource(shaderHandle, 1, sources, 0);
89  glCompileShader(shaderHandle);
90  GLint compileSuccess;
91  glGetShaderiv(shaderHandle, GL_COMPILE_STATUS, &compileSuccess);
92  if (compileSuccess == GL_FALSE)
93  {
94  GLchar msg[1024];
95  glGetShaderInfoLog(shaderHandle, sizeof(msg), 0, &msg[0]);
96  printf("[AAMPCLI] %s\n", msg );
97  }
98  }
99 
100  return shaderHandle;
101 }
102 
103 void Shader::InitShaders()
104 {
105  GLint linked;
106 
107  GLint vShader = LoadShader(GL_VERTEX_SHADER);
108  GLint fShader = LoadShader(GL_FRAGMENT_SHADER);
109  mProgramID = glCreateProgram();
110  glAttachShader(mProgramID,vShader);
111  glAttachShader(mProgramID,fShader);
112 
113  glBindAttribLocation(mProgramID, ATTRIB_VERTEX, "vertexIn");
114  glBindAttribLocation(mProgramID, ATTRIB_TEXTURE, "textureIn");
115  glLinkProgram(mProgramID);
116  glValidateProgram(mProgramID);
117 
118  glGetProgramiv(mProgramID, GL_LINK_STATUS, &linked);
119  if( linked == GL_FALSE )
120  {
121  GLint logLen;
122  glGetProgramiv(mProgramID, GL_INFO_LOG_LENGTH, &logLen);
123  GLchar *msg = (GLchar *)malloc(sizeof(GLchar)*logLen);
124  glGetProgramInfoLog(mProgramID, logLen, &logLen, msg );
125  printf( "%s\n", msg );
126  free( msg );
127  }
128  glUseProgram(mProgramID);
129  glDeleteShader(vShader);
130  glDeleteShader(fShader);
131 
132  //Get Uniform Variables Location
133  textureUniformY = glGetUniformLocation(mProgramID, "tex_y");
134  textureUniformU = glGetUniformLocation(mProgramID, "tex_u");
135  textureUniformV = glGetUniformLocation(mProgramID, "tex_v");
136 
137  typedef struct _vertex
138  {
139  float p[2];
140  float uv[2];
141  } Vertex;
142 
143  static const Vertex vertexPtr[4] =
144  {
145  {{-1,-1}, {0.0,1 } },
146  {{ 1,-1}, {1,1 } },
147  {{ 1, 1}, {1,0.0 } },
148  {{-1, 1}, {0.0,0.0} }
149  };
150  static const unsigned short index[6] =
151  {
152  0,1,2, 2,3,0
153  };
154 
155  glGenVertexArrays(1, &_vertexArray);
156  glBindVertexArray(_vertexArray);
157  glGenBuffers(2, _vertexBuffer);
158  glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer[0]);
159  glBufferData(GL_ARRAY_BUFFER, sizeof(vertexPtr), vertexPtr, GL_STATIC_DRAW );
160  glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _vertexBuffer[1]);
161  glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(index), index, GL_STATIC_DRAW );
162  glVertexAttribPointer(ATTRIB_VERTEX, 2, GL_FLOAT, GL_FALSE,
163  sizeof(Vertex), (const GLvoid *)offsetof(Vertex,p) );
164  glEnableVertexAttribArray(ATTRIB_VERTEX);
165 
166  glVertexAttribPointer(ATTRIB_TEXTURE, 2, GL_FLOAT, GL_FALSE,
167  sizeof(Vertex), (const GLvoid *)offsetof(Vertex, uv ) );
168  glEnableVertexAttribArray(ATTRIB_TEXTURE);
169  glBindVertexArray(0);
170 
171  glGenTextures(1, &id_y);
172  glBindTexture(GL_TEXTURE_2D, id_y);
173  glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
174  glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
175  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
176  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
177 
178  glGenTextures(1, &id_u);
179  glBindTexture(GL_TEXTURE_2D, id_u);
180  glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
181  glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
182  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
183  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
184 
185  glGenTextures(1, &id_v);
186  glBindTexture(GL_TEXTURE_2D, id_v);
187  glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
188  glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
189  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
190  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
191 }
192 
193 void Shader::glRender(void){
194  /** Input in I420 (YUV420) format.
195  * Buffer structure:
196  * ----------
197  * | |
198  * | Y | size = w*h
199  * | |
200  * |________|
201  * | U |size = w*h/4
202  * |--------|
203  * | V |size = w*h/4
204  * ----------*
205  */
206  int pixel_w = 0;
207  int pixel_h = 0;
208  uint8_t *yuvBuffer = NULL;
209  unsigned char *yPlane, *uPlane, *vPlane;
210 
211  {
212  std::lock_guard<std::mutex> lock(appsinkData_mutex);
213  yuvBuffer = appsinkData.yuvBuffer;
214  appsinkData.yuvBuffer = NULL;
215  pixel_w = appsinkData.width;
216  pixel_h = appsinkData.height;
217  }
218  if(yuvBuffer)
219  {
220  yPlane = yuvBuffer;
221  uPlane = yPlane + (pixel_w*pixel_h);
222  vPlane = uPlane + (pixel_w*pixel_h)/4;
223 
224  glClearColor(0.0,0.0,0.0,0.0);
225  glClear(GL_COLOR_BUFFER_BIT);
226 
227  //Y
228  glActiveTexture(GL_TEXTURE0);
229  glBindTexture(GL_TEXTURE_2D, id_y);
230  glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, pixel_w, pixel_h, 0, GL_RED, GL_UNSIGNED_BYTE, yPlane);
231  glUniform1i(textureUniformY, 0);
232 
233  //U
234  glActiveTexture(GL_TEXTURE1);
235  glBindTexture(GL_TEXTURE_2D, id_u);
236  glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, pixel_w/2, pixel_h/2, 0, GL_RED, GL_UNSIGNED_BYTE, uPlane);
237  glUniform1i(textureUniformU, 1);
238 
239  //V
240  glActiveTexture(GL_TEXTURE2);
241  glBindTexture(GL_TEXTURE_2D, id_v);
242  glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, pixel_w/2, pixel_h/2, 0, GL_RED, GL_UNSIGNED_BYTE, vPlane);
243  glUniform1i(textureUniformV, 2);
244 
245  //Rotate
246  glm::mat4 trans = glm::rotate(
247  glm::mat4(1.0f),
248  currentAngleOfRotation * 360,
249  glm::vec3(1.0f, 1.0f, 1.0f)
250  );
251  GLint uniTrans = glGetUniformLocation(mProgramID, "trans");
252  glUniformMatrix4fv(uniTrans, 1, GL_FALSE, glm::value_ptr(trans));
253 
254  glBindVertexArray(_vertexArray);
255  glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, 0 );
256  glBindVertexArray(0);
257 
258  glutSwapBuffers();
259  SAFE_DELETE(yuvBuffer);
260  }
261 }
262 
263 void Shader::updateYUVFrame(uint8_t *buffer, int size, int width, int height)
264 {
265  uint8_t* frameBuf = new uint8_t[size];
266  memcpy(frameBuf, buffer, size);
267 
268  {
269  std::lock_guard<std::mutex> lock(appsinkData_mutex);
270  if(appsinkData.yuvBuffer)
271  {
272  printf("[AAMPCLI] Drops frame.\n");
273  SAFE_DELETE(appsinkData.yuvBuffer);
274  }
275  appsinkData.yuvBuffer = frameBuf;
276  appsinkData.width = width;
277  appsinkData.height = height;
278  }
279 }
280 
281 void Shader::timer(int v)
282 {
283  currentAngleOfRotation += 0.0001;
284  if (currentAngleOfRotation >= 1.0)
285  {
286  currentAngleOfRotation = 0.0;
287  }
288  glutPostRedisplay();
289 
290  glutTimerFunc(1000/FPS, timer, v);
291 }
292 #endif
AampcliShader.h
AampcliShader header file.