RDK Documentation (Open Sourced RDK Components)
All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
nwvidtex.cpp
1 #include <stdlib.h>
2 #include <stdio.h>
3 #include <string.h>
4 #include <errno.h>
5 #include <math.h>
6 #include <signal.h>
7 #include <pthread.h>
8 #include <poll.h>
9 #include <sys/ioctl.h>
10 #include <sys/socket.h>
11 #include <linux/input.h>
12 #include <net/if.h>
13 #include <arpa/inet.h>
14 #include <sys/time.h>
15 #include <unistd.h>
16 #include <gst/gst.h>
17 
18 #include <GLES2/gl2.h>
19 #include <GLES2/gl2ext.h>
20 
21 #include "essos.h"
22 
23 #define DEFAULT_WIDTH (1920)
24 #define DEFAULT_HEIGHT (1080)
25 #define WINDOW_BORDER_COLOR (0xFFFFFFFF)
26 #define WINDOW_BORDER_THICKNESS (4)
27 
28 #ifndef DRM_FORMAT_R8
29 #define DRM_FORMAT_R8 (0x20203852)
30 #endif
31 
32 #ifndef DRM_FORMAT_GR88
33 #define DRM_FORMAT_GR88 (0x38385247)
34 #endif
35 
36 #ifndef DRM_FORMAT_RG88
37 #define DRM_FORMAT_RG88 (0x38384752)
38 #endif
39 
40 #ifndef DRM_FORMAT_RGBA8888
41 #define DRM_FORMAT_RGBA8888 (0x34324152)
42 #endif
43 
44 typedef struct AppCtx_ AppCtx;
45 
46 #define MAX_TEXTURES (2)
47 typedef struct _Surface
48 {
49  int x;
50  int y;
51  int w;
52  int h;
53  bool dirty;
54  bool haveYUVTextures;
55  bool externalImage;
56  int frameBufferCapacity;
57  int frameWidth;
58  int frameHeight;
59  unsigned char *frameBuffer;
60  int textureCount;
61  GLuint textureId[MAX_TEXTURES];
62  EGLImageKHR eglImage[MAX_TEXTURES];
63  pthread_mutex_t mutex;
64 } Surface;
65 
66 typedef struct _GLCtx
67 {
68  AppCtx *appCtx;
69  bool initialized;
70 
71  PFNEGLCREATEIMAGEKHRPROC eglCreateImageKHR;
72  PFNEGLDESTROYIMAGEKHRPROC eglDestroyImageKHR;
73  PFNGLEGLIMAGETARGETTEXTURE2DOESPROC glEGLImageTargetTexture2DOES;
74 
75  GLuint fragColor;
76  GLuint vertColor;
77  GLuint progColor;
78  GLint locPosColor;
79  GLint locColorColor;
80  GLint locOffsetColor;
81  GLint locMatrixColor;
82 
83  bool haveYUVTextures;
84  bool haveYUVShaders;
85  GLuint fragTex;
86  GLuint vertTex;
87  GLuint progTex;
88  GLint locPosTex;
89  GLint locTC;
90  GLint locTCUV;
91  GLint locResTex;
92  GLint locMatrixTex;
93  GLint locTexture;
94  GLint locTextureUV;
95 
96  GLuint fragFill;
97  GLuint vertFill;
98  GLuint progFill;
99  GLint locPosFill;
100  GLint locResFill;
101  GLint locMatrixFill;
102  GLint locColorFill;
103 } GLCtx;
104 
105 typedef struct AppCtx_
106 {
107  EssCtx *essCtx;
108  int windowWidth;
109  int windowHeight;
110  int videoX;
111  int videoY;
112  int videoWidth;
113  int videoHeight;
114  bool dirty;
115  float matrix[16];
116  float alpha;
117  EGLDisplay eglDisplay;
118  bool haveDmaBufImport;
119  bool haveExternalImage;
120  GLCtx gl;
121  Surface surface;
122  GLuint shaderVertFill;
123  GLuint shaderFragFill;
124  GLuint progFill;
125  GLuint attrFillVertex;
126  GLuint uniFillMatrix;
127  GLuint uniFillTarget;
128  GLuint uniFillColor;
129  long long frameTimePrev;
130  long long frameTime;
131  GstElement *pipeline;
132  GstElement *playbin;
133  GstElement *vidsink;
134  GstBus *bus;
135  GMainLoop *loop;
136  bool quit;
137 } AppCtx;
138 
139 static void signalHandler(int signum);
140 static bool createShaders( AppCtx *ctx,
141  const char *vertSrc, GLuint *vShader,
142  const char *fragSrc, GLuint *fShader );
143 static bool linkProgram( AppCtx *ctx, GLuint prog );
144 static bool setupFill( AppCtx *ctx );
145 static bool setupGL( AppCtx *ctx );
146 static void fillRect( AppCtx *ctx, int x, int y, int w, int h, unsigned argb );
147 static void terminated( void * );
148 static void keyPressed( void *userData, unsigned int key );
149 static void keyReleased( void *userData, unsigned int );
150 static void pointerMotion( void *userData, int, int );
151 static void pointerButtonPressed( void *userData, int button, int x, int y );
152 static void pointerButtonReleased( void *userData, int, int, int );
153 static void showUsage();
154 
155 static bool gRunning;
156 static int gDisplayWidth;
157 static int gDisplayHeight;
158 
159 static long long getMonotonicTimeMicros( void )
160 {
161  int rc;
162  struct timespec tm;
163  long long timeMicro;
164  static bool reportedError= false;
165  if ( !reportedError )
166  {
167  rc= clock_gettime( CLOCK_MONOTONIC, &tm );
168  }
169  if ( reportedError || rc )
170  {
171  struct timeval tv;
172  if ( !reportedError )
173  {
174  reportedError= true;
175  printf("clock_gettime failed rc %d - using timeofday\n", rc);
176  }
177  gettimeofday(&tv,0);
178  timeMicro= tv.tv_sec*1000000LL+tv.tv_usec;
179  }
180  else
181  {
182  timeMicro= tm.tv_sec*1000000LL+(tm.tv_nsec/1000LL);
183  }
184  return timeMicro;
185 }
186 
187 static void signalHandler(int signum)
188 {
189  printf("signalHandler: signum %d\n", signum);
190  gRunning= false;
191 }
192 
193 static const char *vertFillSrc=
194  "uniform mat4 matrix;\n"
195  "uniform vec2 targetSize;\n"
196  "attribute vec2 vertex;\n"
197  "void main()\n"
198  "{\n"
199  " vec4 pos= matrix * vec4(vertex, 0, 1);\n"
200  " vec4 scale= vec4( targetSize, 1, 1) * vec4( 0.5, -0.5, 1, 1);\n"
201  " pos= pos / scale;\n"
202  " pos= pos - vec4( 1, -1, 0, 0 );\n"
203  " gl_Position= pos;\n"
204  "}\n";
205 static const char *fragFillSrc=
206  "#ifdef GL_ES\n"
207  "precision mediump float;\n"
208  "#endif\n"
209  "uniform vec4 color;\n"
210  "void main()\n"
211  "{\n"
212  " gl_FragColor= color;\n"
213  "}\n";
214 
215 static bool createShaders( AppCtx *ctx,
216  const char *vertSrc, GLuint *vShader,
217  const char *fragSrc, GLuint *fShader )
218 {
219  bool result= false;
220  int pass;
221  GLint status;
222  GLuint shader, type, vshader, fshader;
223  GLsizei length;
224  const char *src, *typeName;
225  char log[1000];
226  for( pass= 0; pass < 2; ++pass )
227  {
228  type= (pass == 0) ? GL_VERTEX_SHADER : GL_FRAGMENT_SHADER;
229  src= (pass == 0) ? vertSrc : fragSrc;
230  typeName= (pass == 0) ? "vertex" : "fragment";
231  shader= glCreateShader( type );
232  if ( !shader )
233  {
234  printf("Error: glCreateShader failed for %s shader\n", typeName);
235  goto exit;
236  }
237  glShaderSource( shader, 1, (const char **)&src, NULL );
238  glCompileShader( shader );
239  glGetShaderiv( shader, GL_COMPILE_STATUS, &status );
240  if ( !status )
241  {
242  glGetShaderInfoLog( shader, sizeof(log), &length, log );
243  printf("Error compiling %s shader: %*s\n",
244  typeName,
245  length,
246  log );
247  }
248  if ( pass == 0 )
249  *vShader= shader;
250  else
251  *fShader= shader;
252  }
253  result= true;
254 exit:
255 
256  return result;
257 }
258 
259 static bool linkProgram( AppCtx *ctx, GLuint prog )
260 {
261  bool result= false;
262  GLint status;
263  glLinkProgram(prog);
264  glGetProgramiv(prog, GL_LINK_STATUS, &status);
265  if (!status)
266  {
267  char log[1000];
268  GLsizei len;
269  glGetProgramInfoLog(prog, 1000, &len, log);
270  printf("Error: linking:\n%*s\n", len, log);
271  goto exit;
272  }
273  result= true;
274 exit:
275  return result;
276 }
277 
278 static bool setupFill( AppCtx *ctx )
279 {
280  bool result= true;
281  if ( !createShaders( ctx, vertFillSrc, &ctx->shaderVertFill, fragFillSrc, &ctx->shaderFragFill ) )
282  {
283  goto exit;
284  }
285  ctx->progFill= glCreateProgram();
286  glAttachShader( ctx->progFill, ctx->shaderVertFill );
287  glAttachShader( ctx->progFill, ctx->shaderFragFill );
288  ctx->attrFillVertex= 0;
289  glBindAttribLocation(ctx->progFill, ctx->attrFillVertex, "vertex");
290  if ( !linkProgram( ctx, ctx->progFill ) )
291  {
292  goto exit;
293  }
294  ctx->uniFillMatrix= glGetUniformLocation( ctx->progFill, "matrix" );
295  if ( ctx->uniFillTarget == -1 )
296  {
297  printf("Error: uniform 'natrix' error\n");
298  goto exit;
299  }
300  ctx->uniFillTarget= glGetUniformLocation( ctx->progFill, "targetSize" );
301  if ( ctx->uniFillTarget == -1 )
302  {
303  printf("Error: uniform 'targetSize' error\n");
304  goto exit;
305  }
306  ctx->uniFillColor= glGetUniformLocation( ctx->progFill, "color" );
307  if ( ctx->uniFillColor == -1 )
308  {
309  printf("Error: uniform 'color' error\n");
310  goto exit;
311  }
312 exit:
313  return result;
314 }
315 
316 static bool setupGL( AppCtx *ctx )
317 {
318  bool result= false;
319  if ( !setupFill( ctx ) )
320  {
321  goto exit;
322  }
323  result= true;
324 exit:
325  return result;
326 }
327 
328 static void fillRect( AppCtx *ctx, int x, int y, int w, int h, unsigned argb )
329 {
330  GLfloat verts[4][2]= {
331  { (float)x, (float)y },
332  { (float)x+w, (float)y },
333  { (float)x, (float)y+h },
334  { (float)x+w, (float)y+h }
335  };
336  float color[4]=
337  {
338  ((float)((argb>>16)&0xFF))/255.0f,
339  ((float)((argb>>8)&0xFF))/255.0f,
340  ((float)((argb)&0xFF))/255.0f,
341  ((float)((argb>>24)&0xFF))/255.0f,
342  };
343  float matrix[4][4]=
344  {
345  {1, 0, 0, 0},
346  {0, 1, 0, 0},
347  {0, 0, 1, 0},
348  {0, 0, 0, 1}
349  };
350 
351  glGetError();
352  glUseProgram( ctx->progFill );
353  glUniformMatrix4fv( ctx->uniFillMatrix, 1, GL_FALSE, (GLfloat*)matrix );
354  glUniform2f( ctx->uniFillTarget, ctx->windowWidth, ctx->windowHeight );
355  glUniform4fv( ctx->uniFillColor, 1, color );
356  glVertexAttribPointer( ctx->attrFillVertex, 2, GL_FLOAT, GL_FALSE, 0, verts );
357  glEnableVertexAttribArray( ctx->attrFillVertex );
358  glDrawArrays( GL_TRIANGLE_STRIP, 0, 4 );
359  glDisableVertexAttribArray( ctx->attrFillVertex );
360  int err= glGetError();
361  if ( err )
362  {
363  printf("glError: %d\n", err);
364  }
365 }
366 
367 static void terminated( void * )
368 {
369  printf("terminated event\n");
370  gRunning= false;
371 }
372 
373 static EssTerminateListener terminateListener=
374 {
375  terminated
376 };
377 
378 static void keyPressed( void *userData, unsigned int key )
379 {
380  AppCtx *ctx= (AppCtx*)userData;
381  if ( ctx )
382  {
383  switch( key )
384  {
385  default:
386  break;
387  }
388  }
389 }
390 
391 static void keyReleased( void *userData, unsigned int key )
392 {
393  AppCtx *ctx= (AppCtx*)userData;
394  if ( ctx )
395  {
396  }
397 }
398 
399 static EssKeyListener keyListener=
400 {
401  keyPressed,
402  keyReleased
403 };
404 
405 static void pointerMotion( void *userData, int, int )
406 {
407  AppCtx *ctx= (AppCtx*)userData;
408 }
409 
410 static void pointerButtonPressed( void *userData, int button, int x, int y )
411 {
412  AppCtx *ctx= (AppCtx*)userData;
413  if ( ctx )
414  {
415  }
416 }
417 
418 static void pointerButtonReleased( void *userData, int, int, int )
419 {
420  AppCtx *ctx= (AppCtx*)userData;
421 }
422 
423 static EssPointerListener pointerListener=
424 {
425  pointerMotion,
426  pointerButtonPressed,
427  pointerButtonReleased
428 };
429 
430 void displaySize( void *userData, int width, int height )
431 {
432  AppCtx *ctx= (AppCtx*)userData;
433 
434  if ( (gDisplayWidth != width) || (gDisplayHeight != height) )
435  {
436  printf("nwvidtex: display size changed: %dx%d\n", width, height);
437 
438  gDisplayWidth= width;
439  gDisplayHeight= height;
440 
441  EssContextResizeWindow( ctx->essCtx, width, height );
442  ctx->dirty= true;
443  }
444 }
445 
446 static EssSettingsListener settingsListener=
447 {
448  displaySize
449 };
450 
451 static void showUsage()
452 {
453  printf("usage:\n");
454  printf(" nwvidtex [options] <streamURI>\n" );
455  printf(" streamURI - input media stream URI\n");
456  printf("where [options] are:\n" );
457  printf(" --window-size <width>x<height> (eg --window-size 640x480)\n");
458  printf(" --video-rect <x>,<y>,<w>,<h> (eg --video-rect 100,100,320,200)\n");
459  printf(" -? : show usage\n" );
460  printf("\n" );
461 }
462 
463 static const char *vertColor=
464  "uniform mat4 u_matrix;\n"
465  "uniform vec4 u_offset;\n"
466  "attribute vec4 pos;\n"
467  "attribute vec4 color;\n"
468  "varying vec4 v_color;\n"
469  "void main()\n"
470  "{\n"
471  " gl_Position= u_matrix * pos + u_offset;\n"
472  " v_color= color;\n"
473  "}\n";
474 
475 static const char *fragColor=
476  "#ifdef GL_ES\n"
477  "precision mediump float;\n"
478  "#endif\n"
479  "varying vec4 v_color;\n"
480  "void main()\n"
481  "{\n"
482  " gl_FragColor= v_color;\n"
483  "}\n";
484 
485 static const char *vertTexture=
486  "attribute vec2 pos;\n"
487  "attribute vec2 texcoord;\n"
488  "uniform mat4 u_matrix;\n"
489  "uniform vec2 u_resolution;\n"
490  "varying vec2 tx;\n"
491  "void main()\n"
492  "{\n"
493  " vec4 v1= u_matrix * vec4(pos, 0, 1);\n"
494  " vec4 v2= v1 / vec4(u_resolution, u_resolution.x, 1);\n"
495  " vec4 v3= v2 * vec4(2.0, 2.0, 1, 1);\n"
496  " vec4 v4= v3 - vec4(1.0, 1.0, 0, 0);\n"
497  " v4.w= 1.0+v4.z;\n"
498  " gl_Position= v4 * vec4(1, -1, 1, 1);\n"
499  " tx= texcoord;\n"
500  "}\n";
501 
502 static const char *fragTexture=
503  "#ifdef GL_ES\n"
504  "precision mediump float;\n"
505  "#endif\n"
506  "uniform sampler2D texture;\n"
507  "varying vec2 tx;\n"
508  "void main()\n"
509  "{\n"
510  " gl_FragColor= texture2D(texture, tx);\n"
511  "}\n";
512 
513 static const char *fragTextureExternal=
514  "#extension GL_OES_EGL_image_external : require\n"
515  "#ifdef GL_ES\n"
516  "precision mediump float;\n"
517  "#endif\n"
518  "uniform samplerExternalOES texture;\n"
519  "varying vec2 tx;\n"
520  "void main()\n"
521  "{\n"
522  " gl_FragColor= texture2D(texture, tx);\n"
523  "}\n";
524 
525 static const char *vertTextureYUV=
526  "attribute vec2 pos;\n"
527  "attribute vec2 texcoord;\n"
528  "attribute vec2 texcoorduv;\n"
529  "uniform mat4 u_matrix;\n"
530  "uniform vec2 u_resolution;\n"
531  "varying vec2 tx;\n"
532  "varying vec2 txuv;\n"
533  "void main()\n"
534  "{\n"
535  " vec4 v1= u_matrix * vec4(pos, 0, 1);\n"
536  " vec4 v2= v1 / vec4(u_resolution, u_resolution.x, 1);\n"
537  " vec4 v3= v2 * vec4(2.0, 2.0, 1, 1);\n"
538  " vec4 v4= v3 - vec4(1.0, 1.0, 0, 0);\n"
539  " v4.w= 1.0+v4.z;\n"
540  " gl_Position= v4 * vec4(1, -1, 1, 1);\n"
541  " tx= texcoord;\n"
542  " txuv= texcoorduv;\n"
543  "}\n";
544 
545 static const char *fragTextureYUV=
546  "#ifdef GL_ES\n"
547  "precision mediump float;\n"
548  "#endif\n"
549  "uniform sampler2D texture;\n"
550  "uniform sampler2D textureuv;\n"
551  "const vec3 cc_r= vec3(1.0, -0.8604, 1.59580);\n"
552  "const vec4 cc_g= vec4(1.0, 0.539815, -0.39173, -0.81290);\n"
553  "const vec3 cc_b= vec3(1.0, -1.071, 2.01700);\n"
554  "varying vec2 tx;\n"
555  "varying vec2 txuv;\n"
556  "void main()\n"
557  "{\n"
558  " vec4 y_vec= texture2D(texture, tx);\n"
559  " vec4 c_vec= texture2D(textureuv, txuv);\n"
560  " vec4 temp_vec= vec4(y_vec.r, 1.0, c_vec.r, c_vec.g);\n"
561  " gl_FragColor= vec4( dot(cc_r,temp_vec.xyw), dot(cc_g,temp_vec), dot(cc_b,temp_vec.xyz), 1 );\n"
562  "}\n";
563 
564 static bool initGL( GLCtx *ctx )
565 {
566  bool result= false;
567  GLint status;
568  GLsizei length;
569  char infoLog[512];
570  const char *fragSrc, *vertSrc;
571 
572  ctx->eglCreateImageKHR= (PFNEGLCREATEIMAGEKHRPROC)eglGetProcAddress("eglCreateImageKHR");
573  if ( !ctx->eglCreateImageKHR )
574  {
575  printf("Error: initGL: no eglCreateImageKHR\n");
576  goto exit;
577  }
578 
579  ctx->eglDestroyImageKHR= (PFNEGLDESTROYIMAGEKHRPROC)eglGetProcAddress("eglDestroyImageKHR");
580  if ( !ctx->eglDestroyImageKHR )
581  {
582  printf("Error: initGL: no eglDestroyImageKHR\n");
583  goto exit;
584  }
585 
586  ctx->glEGLImageTargetTexture2DOES= (PFNGLEGLIMAGETARGETTEXTURE2DOESPROC)eglGetProcAddress("glEGLImageTargetTexture2DOES");
587  if ( !ctx->glEGLImageTargetTexture2DOES )
588  {
589  printf("Error: initGL: no glEGLImageTargetTexture2DOES\n");
590  goto exit;
591  }
592 
593 
594  ctx->fragColor= glCreateShader( GL_FRAGMENT_SHADER );
595  if ( !ctx->fragColor )
596  {
597  printf("Error: initGL: failed to create color fragment shader\n");
598  goto exit;
599  }
600 
601  glShaderSource( ctx->fragColor, 1, (const char **)&fragColor, NULL );
602  glCompileShader( ctx->fragColor );
603  glGetShaderiv( ctx->fragColor, GL_COMPILE_STATUS, &status );
604  if ( !status )
605  {
606  glGetShaderInfoLog( ctx->fragColor, sizeof(infoLog), &length, infoLog );
607  printf("Error: initGL: compiling color fragment shader: %*s\n", length, infoLog );
608  goto exit;
609  }
610 
611  ctx->vertColor= glCreateShader( GL_VERTEX_SHADER );
612  if ( !ctx->vertColor )
613  {
614  printf("Error: initGL: failed to create color vertex shader\n");
615  goto exit;
616  }
617 
618  glShaderSource( ctx->vertColor, 1, (const char **)&vertColor, NULL );
619  glCompileShader( ctx->vertColor );
620  glGetShaderiv( ctx->vertColor, GL_COMPILE_STATUS, &status );
621  if ( !status )
622  {
623  glGetShaderInfoLog( ctx->vertColor, sizeof(infoLog), &length, infoLog );
624  printf("Error: initGL: compiling color vertex shader: \n%*s\n", length, infoLog );
625  goto exit;
626  }
627 
628  ctx->progColor= glCreateProgram();
629  glAttachShader(ctx->progColor, ctx->fragColor);
630  glAttachShader(ctx->progColor, ctx->vertColor);
631 
632  ctx->locPosColor= 0;
633  ctx->locColorColor= 1;
634  glBindAttribLocation(ctx->progColor, ctx->locPosColor, "pos");
635  glBindAttribLocation(ctx->progColor, ctx->locColorColor, "color");
636 
637  glLinkProgram(ctx->progColor);
638  glGetProgramiv(ctx->progColor, GL_LINK_STATUS, &status);
639  if (!status)
640  {
641  glGetProgramInfoLog(ctx->progColor, sizeof(infoLog), &length, infoLog);
642  printf("Error: initGL: linking:\n%*s\n", length, infoLog);
643  goto exit;
644  }
645 
646  ctx->locOffsetColor= glGetUniformLocation(ctx->progColor, "u_offset");
647  ctx->locMatrixColor= glGetUniformLocation(ctx->progColor, "u_matrix");
648 
649 
650 
651  if ( ctx->haveYUVShaders )
652  {
653  fragSrc= fragTextureYUV;
654  vertSrc= vertTextureYUV;
655  }
656  else
657  {
658  fragSrc= (ctx->appCtx->haveExternalImage ? fragTextureExternal : fragTexture);
659  vertSrc= vertTexture;
660  }
661 
662  ctx->fragTex= glCreateShader( GL_FRAGMENT_SHADER );
663  if ( !ctx->fragTex )
664  {
665  printf("Error: initGL: failed to create texture fragment shader\n");
666  goto exit;
667  }
668 
669  glShaderSource( ctx->fragTex, 1, (const char **)&fragSrc, NULL );
670  glCompileShader( ctx->fragTex );
671  glGetShaderiv( ctx->fragTex, GL_COMPILE_STATUS, &status );
672  if ( !status )
673  {
674  glGetShaderInfoLog( ctx->fragTex, sizeof(infoLog), &length, infoLog );
675  printf("Error: initGL: compiling texture fragment shader: %*s\n", length, infoLog );
676  goto exit;
677  }
678 
679  ctx->vertTex= glCreateShader( GL_VERTEX_SHADER );
680  if ( !ctx->vertTex )
681  {
682  printf("Error: initGL: failed to create texture vertex shader\n");
683  goto exit;
684  }
685 
686  glShaderSource( ctx->vertTex, 1, (const char **)&vertSrc, NULL );
687  glCompileShader( ctx->vertTex );
688  glGetShaderiv( ctx->vertTex, GL_COMPILE_STATUS, &status );
689  if ( !status )
690  {
691  glGetShaderInfoLog( ctx->vertTex, sizeof(infoLog), &length, infoLog );
692  printf("Error: initGL: compiling texture vertex shader: \n%*s\n", length, infoLog );
693  goto exit;
694  }
695 
696  ctx->progTex= glCreateProgram();
697  glAttachShader(ctx->progTex, ctx->fragTex);
698  glAttachShader(ctx->progTex, ctx->vertTex);
699 
700  ctx->locPosTex= 0;
701  ctx->locTC= 1;
702  glBindAttribLocation(ctx->progTex, ctx->locPosTex, "pos");
703  glBindAttribLocation(ctx->progTex, ctx->locTC, "texcoord");
704  if ( ctx->haveYUVShaders )
705  {
706  ctx->locTCUV= 2;
707  glBindAttribLocation(ctx->progTex, ctx->locTCUV, "texcoorduv");
708  }
709 
710  glLinkProgram(ctx->progTex);
711  glGetProgramiv(ctx->progTex, GL_LINK_STATUS, &status);
712  if (!status)
713  {
714  glGetProgramInfoLog(ctx->progTex, sizeof(infoLog), &length, infoLog);
715  printf("Error: initGL: linking:\n%*s\n", length, infoLog);
716  goto exit;
717  }
718 
719  ctx->locResTex= glGetUniformLocation(ctx->progTex,"u_resolution");
720  ctx->locMatrixTex= glGetUniformLocation(ctx->progTex,"u_matrix");
721  ctx->locTexture= glGetUniformLocation(ctx->progTex,"texture");
722  if ( ctx->haveYUVShaders )
723  {
724  ctx->locTextureUV= glGetUniformLocation(ctx->progTex,"textureuv");
725  }
726 
727  result= true;
728 
729 exit:
730 
731  return result;
732 }
733 
734 static void termGL( GLCtx *glCtx )
735 {
736  if ( glCtx->fragTex )
737  {
738  glDeleteShader( glCtx->fragTex );
739  glCtx->fragTex= 0;
740  }
741  if ( glCtx->vertTex )
742  {
743  glDeleteShader( glCtx->vertTex );
744  glCtx->vertTex= 0;
745  }
746  if ( glCtx->progTex )
747  {
748  glDeleteProgram( glCtx->progTex );
749  glCtx->progTex= 0;
750  }
751 }
752 
753 static void drawSurface( GLCtx *glCtx, Surface *surface )
754 {
755  AppCtx *appCtx= glCtx->appCtx;
756  int x, y, w, h;
757  GLenum glerr;
758 
759  x= surface->x;
760  y= surface->y;
761  w= surface->w;
762  h= surface->h;
763 
764  const float verts[4][2]=
765  {
766  { float(x), float(y) },
767  { float(x+w), float(y) },
768  { float(x), float(y+h) },
769  { float(x+w), float(y+h) }
770  };
771 
772  const float uv[4][2]=
773  {
774  { 0, 0 },
775  { 1, 0 },
776  { 0, 1 },
777  { 1, 1 }
778  };
779 
780  const float identityMatrix[4][4]=
781  {
782  {1, 0, 0, 0},
783  {0, 1, 0, 0},
784  {0, 0, 1, 0},
785  {0, 0, 0, 1}
786  };
787 
788  if ( glCtx->haveYUVShaders != surface->haveYUVTextures )
789  {
790  termGL( glCtx );
791  glCtx->haveYUVShaders= surface->haveYUVTextures;
792  if ( !initGL( glCtx ) )
793  {
794  printf("Error: drawSurface: initGL failed while changing shaders\n");
795  }
796  }
797 
798  if ( (surface->textureId[0] == GL_NONE) || surface->dirty || surface->externalImage )
799  {
800  for( int i= 0; i < surface->textureCount; ++i )
801  {
802  if ( surface->textureId[i] == GL_NONE )
803  {
804  glGenTextures(1, &surface->textureId[i] );
805  }
806 
807  glActiveTexture(GL_TEXTURE0+i);
808  glBindTexture(GL_TEXTURE_2D, surface->textureId[i] );
809  if ( surface->eglImage[i] )
810  {
811  if ( surface->externalImage )
812  {
813  glCtx->glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES, surface->eglImage[i]);
814  }
815  else
816  {
817  glCtx->glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, surface->eglImage[i]);
818  }
819  }
820  else if ( surface->frameBuffer )
821  {
822  #ifdef GL_BGRA_EXT
823  glTexImage2D( GL_TEXTURE_2D, 0, GL_BGRA_EXT, surface->frameWidth, surface->frameHeight,
824  0, GL_BGRA_EXT, GL_UNSIGNED_BYTE, surface->frameBuffer );
825  #else
826  glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, surface->frameWidth, surface->frameHeight,
827  0, GL_RGBA, GL_UNSIGNED_BYTE, surface->frameBuffer );
828  #endif
829  surface->dirty= false;
830 
831  }
832  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
833  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
834  glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
835  glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
836  }
837  }
838 
839  glUseProgram(glCtx->progTex);
840  glUniform2f(glCtx->locResTex, appCtx->windowWidth, appCtx->windowHeight);
841  glUniformMatrix4fv(glCtx->locMatrixTex, 1, GL_FALSE, (GLfloat*)identityMatrix);
842 
843  glActiveTexture(GL_TEXTURE0);
844  glBindTexture(GL_TEXTURE_2D, surface->textureId[0]);
845  glUniform1i(glCtx->locTexture, 0);
846  glVertexAttribPointer(glCtx->locPosTex, 2, GL_FLOAT, GL_FALSE, 0, verts);
847  glVertexAttribPointer(glCtx->locTC, 2, GL_FLOAT, GL_FALSE, 0, uv);
848  glEnableVertexAttribArray(glCtx->locPosTex);
849  glEnableVertexAttribArray(glCtx->locTC);
850  if ( surface->haveYUVTextures )
851  {
852  glActiveTexture(GL_TEXTURE1);
853  glBindTexture(GL_TEXTURE_2D, surface->textureId[1]);
854  glUniform1i(glCtx->locTextureUV, 1);
855  glVertexAttribPointer(glCtx->locTCUV, 2, GL_FLOAT, GL_FALSE, 0, uv);
856  glEnableVertexAttribArray(glCtx->locTCUV);
857  }
858  glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
859  glDisableVertexAttribArray(glCtx->locPosTex);
860  glDisableVertexAttribArray(glCtx->locTC);
861  if ( surface->haveYUVTextures )
862  {
863  glDisableVertexAttribArray(glCtx->locTCUV);
864  }
865 
866  glerr= glGetError();
867  if ( glerr != GL_NO_ERROR )
868  {
869  printf("Warning: drawSurface: glGetError: %X\n", glerr);
870  }
871 }
872 
873 static void newVideoTexture( GstElement *elmnt, guint format, guint width, guint height,
874  gint fd0, guint p0l, guint p0s, gpointer p0d,
875  gint fd1, guint p1l, guint p1s, gpointer p1d,
876  gint fd2, guint p2l, guint p2s, gpointer p2d,
877  void *userData )
878 {
879  AppCtx *appCtx= (AppCtx*)userData;
880  GLCtx *gl= &appCtx->gl;
881  Surface *surface= &appCtx->surface;
882  EGLint attr[28];
883  pthread_mutex_lock( &surface->mutex );
884  if ( fd0 >= 0 )
885  {
886  #ifdef EGL_LINUX_DMA_BUF_EXT
887  for( int i= 0; i < MAX_TEXTURES; ++i )
888  {
889  if ( surface->eglImage[i] )
890  {
891  gl->eglDestroyImageKHR( appCtx->eglDisplay, surface->eglImage[i] );
892  surface->eglImage[i]= 0;
893  }
894  }
895 
896  #ifdef GL_OES_EGL_image_external
897  int i= 0;
898  attr[i++]= EGL_WIDTH;
899  attr[i++]= width;
900  attr[i++]= EGL_HEIGHT;
901  attr[i++]= height;
902  attr[i++]= EGL_LINUX_DRM_FOURCC_EXT;
903  attr[i++]= format;
904  attr[i++]= EGL_DMA_BUF_PLANE0_FD_EXT;
905  attr[i++]= fd0;
906  attr[i++]= EGL_DMA_BUF_PLANE0_OFFSET_EXT;
907  attr[i++]= 0;
908  attr[i++]= EGL_DMA_BUF_PLANE0_PITCH_EXT;
909  attr[i++]= p0s;
910  attr[i++]= EGL_DMA_BUF_PLANE1_FD_EXT;
911  attr[i++]= fd1;
912  attr[i++]= EGL_DMA_BUF_PLANE1_OFFSET_EXT;
913  attr[i++]= (fd0 != fd1 ? 0 : width*height);
914  attr[i++]= EGL_DMA_BUF_PLANE1_PITCH_EXT;
915  attr[i++]= p1s;
916  attr[i++]= EGL_YUV_COLOR_SPACE_HINT_EXT;
917  attr[i++]= EGL_ITU_REC709_EXT;
918  attr[i++]= EGL_SAMPLE_RANGE_HINT_EXT;
919  attr[i++]= EGL_YUV_FULL_RANGE_EXT;
920  attr[i++]= EGL_NONE;
921 
922  surface->eglImage[0]= gl->eglCreateImageKHR( appCtx->eglDisplay,
923  EGL_NO_CONTEXT,
924  EGL_LINUX_DMA_BUF_EXT,
925  (EGLClientBuffer)NULL,
926  attr );
927  if ( surface->eglImage[0] == 0 )
928  {
929  printf("Error: updateFrame: eglCreateImageKHR failed for fd %d: errno %X\n", fd0, eglGetError());
930  }
931  if ( surface->textureId[0] != GL_NONE )
932  {
933  glDeleteTextures( 1, &surface->textureId[0] );
934  surface->textureId[0]= GL_NONE;
935  }
936 
937  surface->textureCount= 1;
938  surface->haveYUVTextures= false;
939  surface->externalImage= true;
940  #else
941  attr[0]= EGL_WIDTH;
942  attr[1]= width;
943  attr[2]= EGL_HEIGHT;
944  attr[3]= height;
945  attr[4]= EGL_LINUX_DRM_FOURCC_EXT;
946  attr[5]= DRM_FORMAT_R8;
947  attr[6]= EGL_DMA_BUF_PLANE0_FD_EXT;
948  attr[7]= fd0;
949  attr[8]= EGL_DMA_BUF_PLANE0_OFFSET_EXT;
950  attr[9]= 0;
951  attr[10]= EGL_DMA_BUF_PLANE0_PITCH_EXT;
952  attr[11]= p0s;
953  attr[12]= EGL_NONE;
954 
955  surface->eglImage[0]= gl->eglCreateImageKHR( appCtx->eglDisplay,
956  EGL_NO_CONTEXT,
957  EGL_LINUX_DMA_BUF_EXT,
958  (EGLClientBuffer)NULL,
959  attr );
960  if ( surface->eglImage[0] == 0 )
961  {
962  printf("Error: updateFrame: eglCreateImageKHR failed for fd %d: errno %X\n", fd0, eglGetError());
963  }
964  if ( surface->textureId[0] != GL_NONE )
965  {
966  glDeleteTextures( 1, &surface->textureId[0] );
967  surface->textureId[0]= GL_NONE;
968  }
969 
970  attr[0]= EGL_WIDTH;
971  attr[1]= width/2;
972  attr[2]= EGL_HEIGHT;
973  attr[3]= height/2;
974  attr[4]= EGL_LINUX_DRM_FOURCC_EXT;
975  attr[5]= DRM_FORMAT_GR88;
976  attr[6]= EGL_DMA_BUF_PLANE0_FD_EXT;
977  attr[7]= fd0;
978  attr[8]= EGL_DMA_BUF_PLANE0_OFFSET_EXT;
979  attr[9]= width*height;
980  attr[10]= EGL_DMA_BUF_PLANE0_PITCH_EXT;
981  attr[11]= p1s;
982  attr[12]= EGL_NONE;
983 
984  surface->eglImage[1]= gl->eglCreateImageKHR( appCtx->eglDisplay,
985  EGL_NO_CONTEXT,
986  EGL_LINUX_DMA_BUF_EXT,
987  (EGLClientBuffer)NULL,
988  attr );
989  if ( surface->eglImage[1] == 0 )
990  {
991  printf("Error: updateFrame: eglCreateImageKHR failed for fd %d: errno %X\n", fd0, eglGetError());
992  }
993  if ( surface->textureId[1] != GL_NONE )
994  {
995  glDeleteTextures( 1, &surface->textureId[1] );
996  surface->textureId[1]= GL_NONE;
997  }
998  surface->textureCount= 2;
999  surface->haveYUVTextures= true;
1000  surface->externalImage= false;
1001  #endif
1002  #endif
1003  }
1004  else
1005  {
1006  if ( format == DRM_FORMAT_RGBA8888 )
1007  {
1008  if ( !surface->frameBuffer ||
1009  (width != surface->frameWidth) ||
1010  (height != surface->frameHeight) )
1011  {
1012  if ( surface->frameBuffer )
1013  {
1014  free( surface->frameBuffer );
1015  surface->frameBuffer= 0;
1016  }
1017  surface->frameBuffer= (unsigned char*)malloc( p0l );
1018  if ( surface->frameBuffer )
1019  {
1020  surface->frameBufferCapacity= p0l;
1021  surface->frameWidth= width;
1022  surface->frameHeight= height;
1023  }
1024  }
1025  if ( surface->frameBuffer )
1026  {
1027  #ifdef GL_BGRA_EXT
1028  memcpy( surface->frameBuffer, p0d, p0l );
1029  #else
1030  unsigned char a, r, g, b;
1031  unsigned char *s= (unsigned char *)p0d;
1032  unsigned char *d= surface->frameBuffer;
1033  for( int i= 0; i < height; ++i )
1034  {
1035  for( int j= 0; j < width; ++j )
1036  {
1037  b= *(s++);
1038  g= *(s++);
1039  r= *(s++);
1040  a= *(s++);
1041  *(d++)= r;
1042  *(d++)= g;
1043  *(d++)= b;
1044  *(d++)= a;
1045  }
1046  }
1047  #endif
1048  surface->textureCount= 1;
1049  surface->haveYUVTextures= false;
1050  surface->externalImage= false;
1051  surface->dirty= true;
1052  }
1053  }
1054  }
1055  appCtx->dirty= true;
1056  pthread_mutex_unlock( &surface->mutex );
1057 }
1058 
1059 static gboolean busCallback(GstBus *bus, GstMessage *message, gpointer data)
1060 {
1061  AppCtx *ctx= (AppCtx*)data;
1062 
1063  switch ( GST_MESSAGE_TYPE(message) )
1064  {
1065  case GST_MESSAGE_ERROR:
1066  {
1067  GError *error;
1068  gchar *debug;
1069 
1070  gst_message_parse_error(message, &error, &debug);
1071  g_print("Error: %s\n", error->message);
1072  if ( debug )
1073  {
1074  g_print("Debug info: %s\n", debug);
1075  }
1076  g_error_free(error);
1077  g_free(debug);
1078  ctx->quit= true;
1079  g_main_loop_quit( ctx->loop );
1080  }
1081  break;
1082  case GST_MESSAGE_EOS:
1083  g_print( "EOS ctx %p\n", ctx );
1084  ctx->quit= true;
1085  g_main_loop_quit( ctx->loop );
1086  break;
1087  default:
1088  break;
1089  }
1090  return TRUE;
1091 }
1092 
1093 static bool createPipeline( AppCtx *ctx )
1094 {
1095  bool result= false;
1096  int argc= 0;
1097  char **argv= 0;
1098 
1099  gst_init( &argc, &argv );
1100 
1101  ctx->pipeline= gst_pipeline_new("pipeline");
1102  if ( !ctx->pipeline )
1103  {
1104  printf("Error: unable to create pipeline instance\n" );
1105  goto exit;
1106  }
1107 
1108  ctx->bus= gst_pipeline_get_bus( GST_PIPELINE(ctx->pipeline) );
1109  if ( !ctx->bus )
1110  {
1111  printf("Error: unable to get pipeline bus\n");
1112  goto exit;
1113  }
1114  gst_bus_add_watch( ctx->bus, busCallback, ctx );
1115 
1116  ctx->playbin= gst_element_factory_make( "playbin", "playbin" );
1117  if ( !ctx->playbin )
1118  {
1119  printf("Error: unable to create playbin instance\n" );
1120  goto exit;
1121  }
1122  gst_object_ref( ctx->playbin );
1123 
1124  if ( !gst_bin_add( GST_BIN(ctx->pipeline), ctx->playbin) )
1125  {
1126  printf("Error: unable to add playbin to pipeline\n");
1127  goto exit;
1128  }
1129 
1130  ctx->vidsink= gst_element_factory_make( "westerossink", "vidsink" );
1131  if ( !ctx->vidsink )
1132  {
1133  printf("Error: unable to create westerossink instance\n" );
1134  goto exit;
1135  }
1136  gst_object_ref( ctx->vidsink );
1137 
1138  g_object_set(G_OBJECT(ctx->playbin), "video-sink", ctx->vidsink, NULL );
1139 
1140  result= true;
1141 
1142 exit:
1143 
1144  return result;
1145 }
1146 
1147 static void destroyPipeline( AppCtx *ctx )
1148 {
1149  if ( ctx->pipeline )
1150  {
1151  gst_element_set_state(ctx->pipeline, GST_STATE_NULL);
1152  }
1153  if ( ctx->vidsink )
1154  {
1155  gst_object_unref( ctx->vidsink );
1156  ctx->vidsink= 0;
1157  }
1158  if ( ctx->playbin )
1159  {
1160  gst_object_unref( ctx->playbin );
1161  ctx->playbin= 0;
1162  }
1163  if ( ctx->bus )
1164  {
1165  gst_object_unref( ctx->bus );
1166  ctx->bus= 0;
1167  }
1168  if ( ctx->pipeline )
1169  {
1170  gst_object_unref( GST_OBJECT(ctx->pipeline) );
1171  ctx->pipeline= 0;
1172  }
1173 }
1174 
1175 void render( AppCtx *ctx )
1176 {
1177  Surface *surface;
1178  int boundsX, boundsY, boundsW, boundsH;
1179 
1180  glViewport( 0, 0, gDisplayWidth, gDisplayHeight );
1181  //glClearColor(0.2f, 0.2f, 0.5f, 1.0f);
1182  glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
1183  glClear(GL_COLOR_BUFFER_BIT);
1184  glFrontFace( GL_CW );
1185  glBlendFuncSeparate( GL_ONE, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE );
1186  glEnable(GL_BLEND);
1187 
1188  boundsX= 0;
1189  boundsY= 0;
1190  boundsW= ctx->windowWidth;
1191  boundsH= ctx->windowHeight;
1192  fillRect( ctx, boundsX, boundsY, boundsW, WINDOW_BORDER_THICKNESS, WINDOW_BORDER_COLOR );
1193  fillRect( ctx, boundsX, boundsY+boundsH-WINDOW_BORDER_THICKNESS, boundsW, WINDOW_BORDER_THICKNESS, WINDOW_BORDER_COLOR );
1194  fillRect( ctx, boundsX, boundsY, WINDOW_BORDER_THICKNESS, boundsH, WINDOW_BORDER_COLOR );
1195  fillRect( ctx, boundsX+boundsW-WINDOW_BORDER_THICKNESS, boundsY, WINDOW_BORDER_THICKNESS, boundsH, WINDOW_BORDER_COLOR );
1196 
1197  surface= &ctx->surface;
1198  pthread_mutex_lock( &surface->mutex );
1199  if ( surface->eglImage[0] || surface->frameBuffer )
1200  {
1201  drawSurface( &ctx->gl, surface );
1202  }
1203  pthread_mutex_unlock( &surface->mutex );
1204 }
1205 
1206 int main( int argc, char **argv )
1207 {
1208  int nRC= 0;
1209  AppCtx *ctx= 0;
1210  int argidx, len;
1211  bool error= false;
1212  const char *streamURI= 0;
1213 
1214  printf("nwvidtex v1.0\n");
1215  ctx= (AppCtx*)calloc( 1, sizeof(AppCtx) );
1216  if ( !ctx )
1217  {
1218  printf("Error: no memory for app context\n");
1219  goto exit;
1220  }
1221 
1222  ctx->windowWidth= DEFAULT_WIDTH;
1223  ctx->windowHeight= DEFAULT_HEIGHT;
1224  ctx->videoX= 0;
1225  ctx->videoY= 0;
1226  ctx->videoWidth= DEFAULT_WIDTH;
1227  ctx->videoHeight= DEFAULT_HEIGHT;
1228  ctx->dirty= true;
1229 
1230  ctx->essCtx= EssContextCreate();
1231  if ( !ctx->essCtx )
1232  {
1233  printf("Error: EssContextCreate failed\n");
1234  goto exit;
1235  }
1236 
1237  argidx= 1;
1238  while ( argidx < argc )
1239  {
1240  if ( argv[argidx][0] == '-' )
1241  {
1242  len= strlen(argv[argidx]);
1243  if ( (len == 13) && !strncmp( argv[argidx], "--window-size", len) )
1244  {
1245  if ( argidx+1 < argc )
1246  {
1247  int w, h;
1248  ++argidx;
1249  if ( sscanf( argv[argidx], "%dx%d", &w, &h ) == 2 )
1250  {
1251  if ( (w > 0) && (h > 0) )
1252  {
1253  ctx->windowWidth= w;
1254  ctx->windowHeight= h;
1255  }
1256  }
1257  }
1258  }
1259  else if ( (len == 12) && !strncmp( argv[argidx], "--video-rect", len) )
1260  {
1261  ++argidx;
1262  if ( argidx < argc )
1263  {
1264  int x, y, w, h;
1265  if ( sscanf( argv[argidx], "%d,%d,%d,%d", &x, &y, &w, &h ) == 4 )
1266  {
1267  ctx->videoX= x;
1268  ctx->videoY= y;
1269  ctx->videoWidth= w;
1270  ctx->videoHeight= h;
1271  }
1272  }
1273  }
1274  else if ( (len == 2) && !strncmp( (const char*)argv[argidx], "-?", len ) )
1275  {
1276  showUsage();
1277  }
1278  else
1279  {
1280  printf("Unrecognized option: (%s)\n", argv[argidx] );
1281  }
1282  }
1283  else
1284  {
1285  if ( !streamURI )
1286  {
1287  streamURI= argv[argidx];
1288  }
1289  else
1290  {
1291  printf( "ignoring extra argument: %s\n", argv[argidx] );
1292  }
1293  }
1294  ++argidx;
1295  }
1296 
1297  if ( !EssContextSetInitialWindowSize( ctx->essCtx, ctx->windowWidth, ctx->windowHeight) )
1298  {
1299  error= true;
1300  }
1301 
1302  if ( !EssContextSetName( ctx->essCtx, "nwvidtex" ) )
1303  {
1304  error= true;
1305  }
1306 
1307  if ( !EssContextSetTerminateListener( ctx->essCtx, ctx, &terminateListener ) )
1308  {
1309  error= true;
1310  }
1311 
1312  if ( !EssContextSetKeyListener( ctx->essCtx, ctx, &keyListener ) )
1313  {
1314  error= true;
1315  }
1316 
1317  if ( !EssContextSetPointerListener( ctx->essCtx, ctx, &pointerListener ) )
1318  {
1319  error= true;
1320  }
1321 
1322  if ( !EssContextSetSettingsListener( ctx->essCtx, ctx, &settingsListener ) )
1323  {
1324  error= true;
1325  }
1326 
1327  if ( !error )
1328  {
1329  struct sigaction sigint;
1330 
1331  sigint.sa_handler= signalHandler;
1332  sigemptyset(&sigint.sa_mask);
1333  sigint.sa_flags= SA_RESETHAND;
1334  sigaction(SIGINT, &sigint, NULL);
1335 
1336  if ( !EssContextStart( ctx->essCtx ) )
1337  {
1338  error= true;
1339  }
1340  else
1341  if ( !EssContextGetDisplaySize( ctx->essCtx, &gDisplayWidth, &gDisplayHeight ) )
1342  {
1343  error= true;
1344  }
1345  else
1346  if ( !setupGL( ctx ) )
1347  {
1348  error= true;
1349  }
1350 
1351  if ( !error )
1352  {
1353  char work[128];
1354  const char *eglExtensions= 0;
1355  const char *glExtensions= 0;
1356  Surface *surface;
1357 
1358  ctx->eglDisplay= eglGetCurrentDisplay();
1359  if ( ctx->eglDisplay == EGL_NO_DISPLAY )
1360  {
1361  printf("unable to get EGL display\n");
1362  goto exit;
1363  }
1364 
1365  eglExtensions= eglQueryString( ctx->eglDisplay, EGL_EXTENSIONS );
1366  if ( eglExtensions )
1367  {
1368  if ( strstr( eglExtensions, "EGL_EXT_image_dma_buf_import" ) )
1369  {
1370  ctx->haveDmaBufImport= true;
1371  }
1372  }
1373 
1374  glExtensions= (const char *)glGetString(GL_EXTENSIONS);
1375  if ( glExtensions )
1376  {
1377  #ifdef GL_OES_EGL_image_external
1378  if ( strstr( glExtensions, "GL_OES_EGL_image_external" ) )
1379  {
1380  ctx->haveExternalImage= ctx->haveDmaBufImport;
1381  }
1382  #endif
1383  }
1384 
1385  printf("Have dmabuf import: %d\n", ctx->haveDmaBufImport );
1386  printf("Have external image: %d\n", ctx->haveExternalImage );
1387 
1388  surface= &ctx->surface;
1389  memset( surface, 0, sizeof(Surface) );
1390  surface->x= ctx->videoX;
1391  surface->y= ctx->videoY;
1392  surface->w= ctx->videoWidth;
1393  surface->h= ctx->videoHeight;
1394  pthread_mutex_init( &surface->mutex, 0 );
1395 
1396  ctx->gl.appCtx= ctx;
1397  if ( !initGL( &ctx->gl ) )
1398  {
1399  printf("Error: failed to setup GL\n");
1400  goto exit;
1401  }
1402 
1403  ctx->alpha= 1.0;
1404  memset( ctx->matrix, 0, sizeof(ctx->matrix) );
1405  ctx->matrix[0]= ctx->matrix[5]= ctx->matrix[10]= ctx->matrix[15]= 1.0;
1406 
1407  if ( !createPipeline( ctx ) )
1408  {
1409  goto exit;
1410  }
1411 
1412  printf("pipeline created\n");
1413 
1414  g_object_set(G_OBJECT(ctx->playbin), "uri", streamURI, NULL );
1415 
1416  sprintf( work, "%d,%d,%d,%d", ctx->videoX, ctx->videoY, ctx->videoWidth, ctx->videoHeight );
1417  g_object_set(G_OBJECT(ctx->vidsink), "rectangle", work, NULL );
1418 
1419  g_signal_connect( G_OBJECT(ctx->vidsink), "new-video-texture-callback", G_CALLBACK(newVideoTexture), ctx );
1420 
1421  g_object_set(G_OBJECT(ctx->vidsink), "enable-texture", 1, NULL );
1422 
1423  g_object_set(G_OBJECT(ctx->vidsink), "show-video-window", 0, NULL );
1424 
1425  ctx->loop= g_main_loop_new(NULL,FALSE);
1426  if ( ctx->loop )
1427  {
1428  if ( GST_STATE_CHANGE_FAILURE != gst_element_set_state(ctx->pipeline, GST_STATE_PLAYING) )
1429  {
1430  gRunning= true;
1431  while( gRunning )
1432  {
1433  g_main_context_iteration( NULL, FALSE );
1434 
1435  EssContextRunEventLoopOnce( ctx->essCtx );
1436 
1437  if ( ctx->dirty )
1438  {
1439  ctx->dirty= false;
1440 
1441  render( ctx );
1442 
1443  EssContextUpdateDisplay( ctx->essCtx );
1444  }
1445  if ( ctx->quit )
1446  {
1447  gRunning= false;
1448  }
1449  }
1450  }
1451  }
1452  }
1453  }
1454 
1455  if ( error )
1456  {
1457  const char *detail= EssContextGetLastErrorDetail( ctx->essCtx );
1458  printf("Essos error: (%s)\n", detail );
1459  }
1460 
1461 exit:
1462 
1463  if ( ctx )
1464  {
1465  Surface *surface;
1466 
1467  destroyPipeline( ctx );
1468 
1469  if ( ctx->loop )
1470  {
1471  g_main_loop_unref(ctx->loop);
1472  ctx->loop= 0;
1473  }
1474 
1475  surface= &ctx->surface;
1476  for( int i= 0; i < MAX_TEXTURES; ++i )
1477  {
1478  if ( surface->eglImage[i] )
1479  {
1480  ctx->gl.eglDestroyImageKHR( ctx->eglDisplay, surface->eglImage[i] );
1481  surface->eglImage[i]= 0;
1482  }
1483  }
1484 
1485  termGL( &ctx->gl );
1486 
1487  if ( ctx->essCtx )
1488  {
1489  EssContextDestroy( ctx->essCtx );
1490  }
1491 
1492  pthread_mutex_destroy( &ctx->surface.mutex );
1493 
1494  free( ctx );
1495  }
1496 
1497  return nRC;
1498 }
1499 
_GLCtx
Definition: nwvidtex.cpp:66
_Surface
Definition: nwvidtex.cpp:47
AppCtx_
Definition: nwvidtex.cpp:105
TRUE
#define TRUE
Defines for TRUE/FALSE/ENABLE flags.
Definition: wifi_common_hal.h:199
_AppCtx
Definition: rne-triangle.cpp:136