FFmpeg
opengl_enc.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2014 Lukasz Marek
3  *
4  * This file is part of FFmpeg.
5  *
6  * FFmpeg is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * FFmpeg is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with FFmpeg; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19  */
20 
21 //TODO: support for more formats
22 //TODO: support for more systems.
23 //TODO: implement X11, Windows, Mac OS native default window. SDL 1.2 doesn't allow to render to custom thread.
24 
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <stddef.h>
29 
30 #include "config.h"
31 
32 #if HAVE_WINDOWS_H
33 #define WIN32_LEAN_AND_MEAN
34 #include <windows.h>
35 #endif
36 #if HAVE_OPENGL_GL3_H
37 #include <OpenGL/gl3.h>
38 #elif HAVE_ES2_GL_H
39 #include <ES2/gl.h>
40 #else
41 #include <GL/gl.h>
42 #include <GL/glext.h>
43 #endif
44 #if HAVE_GLXGETPROCADDRESS
45 #include <GL/glx.h>
46 #endif
47 
48 #if CONFIG_SDL2
49 #include <SDL.h>
50 #endif
51 
52 #include "libavutil/common.h"
53 #include "libavutil/pixdesc.h"
54 #include "libavutil/log.h"
55 #include "libavutil/opt.h"
56 #include "libavutil/avassert.h"
57 #include "libavutil/avstring.h"
58 #include "libavformat/avformat.h"
59 #include "libavformat/internal.h"
60 #include "libavdevice/avdevice.h"
61 #include "opengl_enc_shaders.h"
62 
63 #ifndef APIENTRY
64 #define APIENTRY
65 #endif
66 
67 /* FF_GL_RED_COMPONENT is used for planar pixel types.
68  * Only red component is sampled in shaders.
69  * On some platforms GL_RED is not available and GL_LUMINANCE have to be used,
70  * but since OpenGL 3.0 GL_LUMINANCE is deprecated.
71  * GL_RED produces RGBA = value, 0, 0, 1.
72  * GL_LUMINANCE produces RGBA = value, value, value, 1.
73  * Note: GL_INTENSITY may also be used which produce RGBA = value, value, value, value. */
74 #if defined(GL_RED)
75 #define FF_GL_RED_COMPONENT GL_RED
76 #elif defined(GL_LUMINANCE)
77 #define FF_GL_RED_COMPONENT GL_LUMINANCE
78 #else
79 #define FF_GL_RED_COMPONENT 0x1903; //GL_RED
80 #endif
81 
82 /* Constants not defined for iOS */
83 #define FF_GL_UNSIGNED_BYTE_3_3_2 0x8032
84 #define FF_GL_UNSIGNED_BYTE_2_3_3_REV 0x8362
85 #define FF_GL_UNSIGNED_SHORT_1_5_5_5_REV 0x8366
86 #define FF_GL_UNPACK_ROW_LENGTH 0x0CF2
87 
88 /* MinGW exposes only OpenGL 1.1 API */
89 #define FF_GL_ARRAY_BUFFER 0x8892
90 #define FF_GL_ELEMENT_ARRAY_BUFFER 0x8893
91 #define FF_GL_STATIC_DRAW 0x88E4
92 #define FF_GL_FRAGMENT_SHADER 0x8B30
93 #define FF_GL_VERTEX_SHADER 0x8B31
94 #define FF_GL_COMPILE_STATUS 0x8B81
95 #define FF_GL_LINK_STATUS 0x8B82
96 #define FF_GL_INFO_LOG_LENGTH 0x8B84
97 typedef void (APIENTRY *FF_PFNGLACTIVETEXTUREPROC) (GLenum texture);
98 typedef void (APIENTRY *FF_PFNGLGENBUFFERSPROC) (GLsizei n, GLuint *buffers);
99 typedef void (APIENTRY *FF_PFNGLDELETEBUFFERSPROC) (GLsizei n, const GLuint *buffers);
100 typedef void (APIENTRY *FF_PFNGLBUFFERDATAPROC) (GLenum target, ptrdiff_t size, const GLvoid *data, GLenum usage);
101 typedef void (APIENTRY *FF_PFNGLBINDBUFFERPROC) (GLenum target, GLuint buffer);
102 typedef GLint (APIENTRY *FF_PFNGLGETATTRIBLOCATIONPROC) (GLuint program, const char *name);
103 typedef void (APIENTRY *FF_PFNGLENABLEVERTEXATTRIBARRAYPROC) (GLuint index);
104 typedef void (APIENTRY *FF_PFNGLVERTEXATTRIBPOINTERPROC) (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, uintptr_t pointer);
105 typedef GLint (APIENTRY *FF_PFNGLGETUNIFORMLOCATIONPROC) (GLuint program, const char *name);
106 typedef void (APIENTRY *FF_PFNGLUNIFORM1FPROC) (GLint location, GLfloat v0);
107 typedef void (APIENTRY *FF_PFNGLUNIFORM1IPROC) (GLint location, GLint v0);
108 typedef void (APIENTRY *FF_PFNGLUNIFORMMATRIX4FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
109 typedef GLuint (APIENTRY *FF_PFNGLCREATEPROGRAMPROC) (void);
110 typedef void (APIENTRY *FF_PFNGLDELETEPROGRAMPROC) (GLuint program);
111 typedef void (APIENTRY *FF_PFNGLUSEPROGRAMPROC) (GLuint program);
112 typedef void (APIENTRY *FF_PFNGLLINKPROGRAMPROC) (GLuint program);
113 typedef void (APIENTRY *FF_PFNGLGETPROGRAMIVPROC) (GLuint program, GLenum pname, GLint *params);
114 typedef void (APIENTRY *FF_PFNGLGETPROGRAMINFOLOGPROC) (GLuint program, GLsizei bufSize, GLsizei *length, char *infoLog);
115 typedef void (APIENTRY *FF_PFNGLATTACHSHADERPROC) (GLuint program, GLuint shader);
116 typedef GLuint (APIENTRY *FF_PFNGLCREATESHADERPROC) (GLenum type);
117 typedef void (APIENTRY *FF_PFNGLDELETESHADERPROC) (GLuint shader);
118 typedef void (APIENTRY *FF_PFNGLCOMPILESHADERPROC) (GLuint shader);
119 typedef void (APIENTRY *FF_PFNGLSHADERSOURCEPROC) (GLuint shader, GLsizei count, const char* *string, const GLint *length);
120 typedef void (APIENTRY *FF_PFNGLGETSHADERIVPROC) (GLuint shader, GLenum pname, GLint *params);
121 typedef void (APIENTRY *FF_PFNGLGETSHADERINFOLOGPROC) (GLuint shader, GLsizei bufSize, GLsizei *length, char *infoLog);
122 
123 typedef struct FFOpenGLFunctions {
124  FF_PFNGLACTIVETEXTUREPROC glActiveTexture; //Require GL ARB multitexture
125  FF_PFNGLGENBUFFERSPROC glGenBuffers; //Require GL_ARB_vertex_buffer_object
126  FF_PFNGLDELETEBUFFERSPROC glDeleteBuffers; //Require GL_ARB_vertex_buffer_object
127  FF_PFNGLBUFFERDATAPROC glBufferData; //Require GL_ARB_vertex_buffer_object
128  FF_PFNGLBINDBUFFERPROC glBindBuffer; //Require GL_ARB_vertex_buffer_object
129  FF_PFNGLGETATTRIBLOCATIONPROC glGetAttribLocation; //Require GL_ARB_vertex_shader
130  FF_PFNGLENABLEVERTEXATTRIBARRAYPROC glEnableVertexAttribArray; //Require GL_ARB_vertex_shader
131  FF_PFNGLVERTEXATTRIBPOINTERPROC glVertexAttribPointer; //Require GL_ARB_vertex_shader
132  FF_PFNGLGETUNIFORMLOCATIONPROC glGetUniformLocation; //Require GL_ARB_shader_objects
133  FF_PFNGLUNIFORM1FPROC glUniform1f; //Require GL_ARB_shader_objects
134  FF_PFNGLUNIFORM1IPROC glUniform1i; //Require GL_ARB_shader_objects
135  FF_PFNGLUNIFORMMATRIX4FVPROC glUniformMatrix4fv; //Require GL_ARB_shader_objects
136  FF_PFNGLCREATEPROGRAMPROC glCreateProgram; //Require GL_ARB_shader_objects
137  FF_PFNGLDELETEPROGRAMPROC glDeleteProgram; //Require GL_ARB_shader_objects
138  FF_PFNGLUSEPROGRAMPROC glUseProgram; //Require GL_ARB_shader_objects
139  FF_PFNGLLINKPROGRAMPROC glLinkProgram; //Require GL_ARB_shader_objects
140  FF_PFNGLGETPROGRAMIVPROC glGetProgramiv; //Require GL_ARB_shader_objects
141  FF_PFNGLGETPROGRAMINFOLOGPROC glGetProgramInfoLog; //Require GL_ARB_shader_objects
142  FF_PFNGLATTACHSHADERPROC glAttachShader; //Require GL_ARB_shader_objects
143  FF_PFNGLCREATESHADERPROC glCreateShader; //Require GL_ARB_shader_objects
144  FF_PFNGLDELETESHADERPROC glDeleteShader; //Require GL_ARB_shader_objects
145  FF_PFNGLCOMPILESHADERPROC glCompileShader; //Require GL_ARB_shader_objects
146  FF_PFNGLSHADERSOURCEPROC glShaderSource; //Require GL_ARB_shader_objects
147  FF_PFNGLGETSHADERIVPROC glGetShaderiv; //Require GL_ARB_shader_objects
148  FF_PFNGLGETSHADERINFOLOGPROC glGetShaderInfoLog; //Require GL_ARB_shader_objects
150 
151 #define OPENGL_ERROR_CHECK(ctx) \
152 {\
153  GLenum err_code; \
154  if ((err_code = glGetError()) != GL_NO_ERROR) { \
155  av_log(ctx, AV_LOG_ERROR, "OpenGL error occurred in '%s', line %d: %d\n", __FUNCTION__, __LINE__, err_code); \
156  goto fail; \
157  } \
158 }\
159 
160 typedef struct OpenGLVertexInfo
161 {
162  float x, y, z; ///<Position
163  float s0, t0; ///<Texture coords
165 
166 /* defines 2 triangles to display */
167 static const GLushort g_index[6] =
168 {
169  0, 1, 2,
170  0, 3, 2,
171 };
172 
173 typedef struct OpenGLContext {
174  AVClass *class; ///< class for private options
175 
176 #if CONFIG_SDL2
177  SDL_Window *window;
178  SDL_GLContext glcontext;
179 #endif
181 
182  int inited; ///< Set to 1 when write_header was successfully called.
183  uint8_t background[4]; ///< Background color
184  int no_window; ///< 0 for create default window
185  char *window_title; ///< Title of the window
186 
187  /* OpenGL implementation limits */
188  GLint max_texture_size; ///< Maximum texture size
189  GLint max_viewport_width; ///< Maximum viewport size
190  GLint max_viewport_height; ///< Maximum viewport size
191  int non_pow_2_textures; ///< 1 when non power of 2 textures are supported
192  int unpack_subimage; ///< 1 when GL_EXT_unpack_subimage is available
193 
194  /* Current OpenGL configuration */
195  GLuint program; ///< Shader program
196  GLuint vertex_shader; ///< Vertex shader
197  GLuint fragment_shader; ///< Fragment shader for current pix_pmt
198  GLuint texture_name[4]; ///< Textures' IDs
199  GLuint index_buffer; ///< Index buffer
200  GLuint vertex_buffer; ///< Vertex buffer
201  OpenGLVertexInfo vertex[4]; ///< VBO
202  GLint projection_matrix_location; ///< Uniforms' locations
207  GLint texture_location[4];
208  GLint position_attrib; ///< Attibutes' locations
210 
211  GLfloat projection_matrix[16]; ///< Projection matrix
212  GLfloat model_view_matrix[16]; ///< Modev view matrix
213  GLfloat color_map[16]; ///< RGBA color map matrix
214  GLfloat chroma_div_w; ///< Chroma subsampling w ratio
215  GLfloat chroma_div_h; ///< Chroma subsampling h ratio
216 
217  /* Stream information */
218  GLenum format;
219  GLenum type;
220  int width; ///< Stream width
221  int height; ///< Stream height
222  enum AVPixelFormat pix_fmt; ///< Stream pixel format
223  int picture_width; ///< Rendered width
224  int picture_height; ///< Rendered height
227 } OpenGLContext;
228 
229 static const struct OpenGLFormatDesc {
230  enum AVPixelFormat fixel_format;
231  const char * const * fragment_shader;
232  GLenum format;
233  GLenum type;
234 } opengl_format_desc[] = {
250  { AV_PIX_FMT_RGB24, &FF_OPENGL_FRAGMENT_SHADER_RGB_PACKET, GL_RGB, GL_UNSIGNED_BYTE },
251  { AV_PIX_FMT_BGR24, &FF_OPENGL_FRAGMENT_SHADER_RGB_PACKET, GL_RGB, GL_UNSIGNED_BYTE },
252  { AV_PIX_FMT_0RGB, &FF_OPENGL_FRAGMENT_SHADER_RGB_PACKET, GL_RGBA, GL_UNSIGNED_BYTE },
253  { AV_PIX_FMT_RGB0, &FF_OPENGL_FRAGMENT_SHADER_RGB_PACKET, GL_RGBA, GL_UNSIGNED_BYTE },
254  { AV_PIX_FMT_0BGR, &FF_OPENGL_FRAGMENT_SHADER_RGB_PACKET, GL_RGBA, GL_UNSIGNED_BYTE },
255  { AV_PIX_FMT_BGR0, &FF_OPENGL_FRAGMENT_SHADER_RGB_PACKET, GL_RGBA, GL_UNSIGNED_BYTE },
256  { AV_PIX_FMT_RGB565, &FF_OPENGL_FRAGMENT_SHADER_RGB_PACKET, GL_RGB, GL_UNSIGNED_SHORT_5_6_5 },
257  { AV_PIX_FMT_BGR565, &FF_OPENGL_FRAGMENT_SHADER_RGB_PACKET, GL_RGB, GL_UNSIGNED_SHORT_5_6_5 },
259  { AV_PIX_FMT_BGR555, &FF_OPENGL_FRAGMENT_SHADER_RGB_PACKET, GL_RGBA, FF_GL_UNSIGNED_SHORT_1_5_5_5_REV },
262  { AV_PIX_FMT_RGB48, &FF_OPENGL_FRAGMENT_SHADER_RGB_PACKET, GL_RGB, GL_UNSIGNED_SHORT },
263  { AV_PIX_FMT_BGR48, &FF_OPENGL_FRAGMENT_SHADER_RGB_PACKET, GL_RGB, GL_UNSIGNED_SHORT },
264  { AV_PIX_FMT_ARGB, &FF_OPENGL_FRAGMENT_SHADER_RGBA_PACKET, GL_RGBA, GL_UNSIGNED_BYTE },
265  { AV_PIX_FMT_RGBA, &FF_OPENGL_FRAGMENT_SHADER_RGBA_PACKET, GL_RGBA, GL_UNSIGNED_BYTE },
266  { AV_PIX_FMT_ABGR, &FF_OPENGL_FRAGMENT_SHADER_RGBA_PACKET, GL_RGBA, GL_UNSIGNED_BYTE },
267  { AV_PIX_FMT_BGRA, &FF_OPENGL_FRAGMENT_SHADER_RGBA_PACKET, GL_RGBA, GL_UNSIGNED_BYTE },
268  { AV_PIX_FMT_RGBA64, &FF_OPENGL_FRAGMENT_SHADER_RGBA_PACKET, GL_RGBA, GL_UNSIGNED_SHORT },
269  { AV_PIX_FMT_BGRA64, &FF_OPENGL_FRAGMENT_SHADER_RGBA_PACKET, GL_RGBA, GL_UNSIGNED_SHORT },
276  { AV_PIX_FMT_NONE, NULL }
277 };
278 
280 static int opengl_draw(AVFormatContext *h, void *intput, int repaint, int is_pkt);
281 static av_cold int opengl_init_context(OpenGLContext *opengl);
282 
284 {
285  glDeleteTextures(4, opengl->texture_name);
286  opengl->texture_name[0] = opengl->texture_name[1] =
287  opengl->texture_name[2] = opengl->texture_name[3] = 0;
288  if (opengl->glprocs.glUseProgram)
289  opengl->glprocs.glUseProgram(0);
290  if (opengl->glprocs.glDeleteProgram) {
291  opengl->glprocs.glDeleteProgram(opengl->program);
292  opengl->program = 0;
293  }
294  if (opengl->glprocs.glDeleteShader) {
295  opengl->glprocs.glDeleteShader(opengl->vertex_shader);
296  opengl->glprocs.glDeleteShader(opengl->fragment_shader);
297  opengl->vertex_shader = opengl->fragment_shader = 0;
298  }
299  if (opengl->glprocs.glBindBuffer) {
302  }
303  if (opengl->glprocs.glDeleteBuffers) {
304  opengl->glprocs.glDeleteBuffers(2, &opengl->index_buffer);
305  opengl->vertex_buffer = opengl->index_buffer = 0;
306  }
307 }
308 
309 static int opengl_resize(AVFormatContext *h, int width, int height)
310 {
311  int ret = 0;
312  OpenGLContext *opengl = h->priv_data;
313  opengl->window_width = width;
314  opengl->window_height = height;
315  if (opengl->inited) {
316  if (opengl->no_window &&
318  av_log(opengl, AV_LOG_ERROR, "Application failed to prepare window buffer.\n");
319  goto end;
320  }
321  if ((ret = opengl_prepare_vertex(h)) < 0)
322  goto end;
323  ret = opengl_draw(h, NULL, 1, 0);
324  }
325  end:
326  return ret;
327 }
328 
329 static int opengl_control_message(AVFormatContext *h, int type, void *data, size_t data_size)
330 {
331  OpenGLContext *opengl = h->priv_data;
332  switch(type) {
334  if (data) {
336  return opengl_resize(h, message->width, message->height);
337  }
338  return AVERROR(EINVAL);
340  return opengl_resize(h, opengl->window_width, opengl->window_height);
341  }
342  return AVERROR(ENOSYS);
343 }
344 
345 #if CONFIG_SDL2
346 static int opengl_sdl_process_events(AVFormatContext *h)
347 {
348  OpenGLContext *opengl = h->priv_data;
350  SDL_Event event;
351  SDL_PumpEvents();
352  while (SDL_PeepEvents(&event, 1, SDL_GETEVENT, SDL_FIRSTEVENT, SDL_LASTEVENT) > 0) {
353  switch (event.type) {
354  case SDL_QUIT:
355  return AVERROR(EIO);
356  case SDL_KEYDOWN:
357  switch (event.key.keysym.sym) {
358  case SDLK_ESCAPE:
359  case SDLK_q:
360  return AVERROR(EIO);
361  }
362  return 0;
363  case SDL_WINDOWEVENT:
364  switch(event.window.event) {
365  case SDL_WINDOWEVENT_RESIZED:
366  case SDL_WINDOWEVENT_SIZE_CHANGED:
367  SDL_GL_GetDrawableSize(opengl->window, &message.width, &message.height);
368  return opengl_control_message(h, AV_APP_TO_DEV_WINDOW_SIZE, &message, sizeof(AVDeviceRect));
369  default:
370  break;
371  }
372  }
373  }
374  return 0;
375 }
376 
377 static int av_cold opengl_sdl_create_window(AVFormatContext *h)
378 {
379  OpenGLContext *opengl = h->priv_data;
381  if (SDL_Init(SDL_INIT_VIDEO)) {
382  av_log(opengl, AV_LOG_ERROR, "Unable to initialize SDL: %s\n", SDL_GetError());
383  return AVERROR_EXTERNAL;
384  }
385  opengl->window = SDL_CreateWindow(opengl->window_title,
386  SDL_WINDOWPOS_UNDEFINED,
387  SDL_WINDOWPOS_UNDEFINED,
388  opengl->window_width, opengl->window_height,
389  SDL_WINDOW_RESIZABLE | SDL_WINDOW_OPENGL);
390  if (!opengl->window) {
391  av_log(opengl, AV_LOG_ERROR, "Unable to create default window: %s\n", SDL_GetError());
392  return AVERROR_EXTERNAL;
393  }
394  opengl->glcontext = SDL_GL_CreateContext(opengl->window);
395  if (!opengl->glcontext) {
396  av_log(opengl, AV_LOG_ERROR, "Unable to create OpenGL context on default window: %s\n", SDL_GetError());
397  return AVERROR_EXTERNAL;
398  }
399  SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
400  SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
401  SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
402  SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8);
403  SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
404  av_log(opengl, AV_LOG_INFO, "SDL driver: '%s'.\n", SDL_GetCurrentVideoDriver());
405  SDL_GL_GetDrawableSize(opengl->window, &message.width, &message.height);
406  return opengl_control_message(h, AV_APP_TO_DEV_WINDOW_SIZE, &message, sizeof(AVDeviceRect));
407 }
408 
409 static int av_cold opengl_sdl_load_procedures(OpenGLContext *opengl)
410 {
411  FFOpenGLFunctions *procs = &opengl->glprocs;
412 
413 #define LOAD_OPENGL_FUN(name, type) \
414  procs->name = (type)SDL_GL_GetProcAddress(#name); \
415  if (!procs->name) { \
416  av_log(opengl, AV_LOG_ERROR, "Cannot load OpenGL function: '%s'\n", #name); \
417  return AVERROR(ENOSYS); \
418  }
419 
420  LOAD_OPENGL_FUN(glActiveTexture, FF_PFNGLACTIVETEXTUREPROC)
421  LOAD_OPENGL_FUN(glGenBuffers, FF_PFNGLGENBUFFERSPROC)
422  LOAD_OPENGL_FUN(glDeleteBuffers, FF_PFNGLDELETEBUFFERSPROC)
423  LOAD_OPENGL_FUN(glBufferData, FF_PFNGLBUFFERDATAPROC)
424  LOAD_OPENGL_FUN(glBindBuffer, FF_PFNGLBINDBUFFERPROC)
425  LOAD_OPENGL_FUN(glGetAttribLocation, FF_PFNGLGETATTRIBLOCATIONPROC)
426  LOAD_OPENGL_FUN(glGetUniformLocation, FF_PFNGLGETUNIFORMLOCATIONPROC)
427  LOAD_OPENGL_FUN(glUniform1f, FF_PFNGLUNIFORM1FPROC)
428  LOAD_OPENGL_FUN(glUniform1i, FF_PFNGLUNIFORM1IPROC)
429  LOAD_OPENGL_FUN(glUniformMatrix4fv, FF_PFNGLUNIFORMMATRIX4FVPROC)
430  LOAD_OPENGL_FUN(glCreateProgram, FF_PFNGLCREATEPROGRAMPROC)
431  LOAD_OPENGL_FUN(glDeleteProgram, FF_PFNGLDELETEPROGRAMPROC)
432  LOAD_OPENGL_FUN(glUseProgram, FF_PFNGLUSEPROGRAMPROC)
433  LOAD_OPENGL_FUN(glLinkProgram, FF_PFNGLLINKPROGRAMPROC)
434  LOAD_OPENGL_FUN(glGetProgramiv, FF_PFNGLGETPROGRAMIVPROC)
435  LOAD_OPENGL_FUN(glGetProgramInfoLog, FF_PFNGLGETPROGRAMINFOLOGPROC)
436  LOAD_OPENGL_FUN(glAttachShader, FF_PFNGLATTACHSHADERPROC)
437  LOAD_OPENGL_FUN(glCreateShader, FF_PFNGLCREATESHADERPROC)
438  LOAD_OPENGL_FUN(glDeleteShader, FF_PFNGLDELETESHADERPROC)
439  LOAD_OPENGL_FUN(glCompileShader, FF_PFNGLCOMPILESHADERPROC)
440  LOAD_OPENGL_FUN(glShaderSource, FF_PFNGLSHADERSOURCEPROC)
441  LOAD_OPENGL_FUN(glGetShaderiv, FF_PFNGLGETSHADERIVPROC)
442  LOAD_OPENGL_FUN(glGetShaderInfoLog, FF_PFNGLGETSHADERINFOLOGPROC)
443  LOAD_OPENGL_FUN(glEnableVertexAttribArray, FF_PFNGLENABLEVERTEXATTRIBARRAYPROC)
444  LOAD_OPENGL_FUN(glVertexAttribPointer, FF_PFNGLVERTEXATTRIBPOINTERPROC)
445 
446  return 0;
447 
448 #undef LOAD_OPENGL_FUN
449 }
450 #endif /* CONFIG_SDL2 */
451 
452 #if defined(__APPLE__)
453 static int av_cold opengl_load_procedures(OpenGLContext *opengl)
454 {
455  FFOpenGLFunctions *procs = &opengl->glprocs;
456 
457 #if CONFIG_SDL2
458  if (!opengl->no_window)
459  return opengl_sdl_load_procedures(opengl);
460 #endif
461 
463  procs->glGenBuffers = glGenBuffers;
465  procs->glBufferData = glBufferData;
466  procs->glBindBuffer = glBindBuffer;
469  procs->glUniform1f = glUniform1f;
470  procs->glUniform1i = glUniform1i;
474  procs->glUseProgram = glUseProgram;
475  procs->glLinkProgram = glLinkProgram;
483  procs->glGetShaderiv = glGetShaderiv;
486  procs->glVertexAttribPointer = (FF_PFNGLVERTEXATTRIBPOINTERPROC) glVertexAttribPointer;
487  return 0;
488 }
489 #else
491 {
492  FFOpenGLFunctions *procs = &opengl->glprocs;
493 
494 #if HAVE_GLXGETPROCADDRESS
495 #define SelectedGetProcAddress glXGetProcAddress
496 #elif HAVE_WGLGETPROCADDRESS
497 #define SelectedGetProcAddress wglGetProcAddress
498 #endif
499 
500 #define LOAD_OPENGL_FUN(name, type) \
501  procs->name = (type)SelectedGetProcAddress(#name); \
502  if (!procs->name) { \
503  av_log(opengl, AV_LOG_ERROR, "Cannot load OpenGL function: '%s'\n", #name); \
504  return AVERROR(ENOSYS); \
505  }
506 
507 #if CONFIG_SDL2
508  if (!opengl->no_window)
509  return opengl_sdl_load_procedures(opengl);
510 #endif
511 
512  LOAD_OPENGL_FUN(glActiveTexture, FF_PFNGLACTIVETEXTUREPROC)
513  LOAD_OPENGL_FUN(glGenBuffers, FF_PFNGLGENBUFFERSPROC)
514  LOAD_OPENGL_FUN(glDeleteBuffers, FF_PFNGLDELETEBUFFERSPROC)
515  LOAD_OPENGL_FUN(glBufferData, FF_PFNGLBUFFERDATAPROC)
516  LOAD_OPENGL_FUN(glBindBuffer, FF_PFNGLBINDBUFFERPROC)
517  LOAD_OPENGL_FUN(glGetAttribLocation, FF_PFNGLGETATTRIBLOCATIONPROC)
518  LOAD_OPENGL_FUN(glGetUniformLocation, FF_PFNGLGETUNIFORMLOCATIONPROC)
519  LOAD_OPENGL_FUN(glUniform1f, FF_PFNGLUNIFORM1FPROC)
520  LOAD_OPENGL_FUN(glUniform1i, FF_PFNGLUNIFORM1IPROC)
521  LOAD_OPENGL_FUN(glUniformMatrix4fv, FF_PFNGLUNIFORMMATRIX4FVPROC)
522  LOAD_OPENGL_FUN(glCreateProgram, FF_PFNGLCREATEPROGRAMPROC)
523  LOAD_OPENGL_FUN(glDeleteProgram, FF_PFNGLDELETEPROGRAMPROC)
524  LOAD_OPENGL_FUN(glUseProgram, FF_PFNGLUSEPROGRAMPROC)
525  LOAD_OPENGL_FUN(glLinkProgram, FF_PFNGLLINKPROGRAMPROC)
526  LOAD_OPENGL_FUN(glGetProgramiv, FF_PFNGLGETPROGRAMIVPROC)
527  LOAD_OPENGL_FUN(glGetProgramInfoLog, FF_PFNGLGETPROGRAMINFOLOGPROC)
528  LOAD_OPENGL_FUN(glAttachShader, FF_PFNGLATTACHSHADERPROC)
529  LOAD_OPENGL_FUN(glCreateShader, FF_PFNGLCREATESHADERPROC)
530  LOAD_OPENGL_FUN(glDeleteShader, FF_PFNGLDELETESHADERPROC)
531  LOAD_OPENGL_FUN(glCompileShader, FF_PFNGLCOMPILESHADERPROC)
532  LOAD_OPENGL_FUN(glShaderSource, FF_PFNGLSHADERSOURCEPROC)
533  LOAD_OPENGL_FUN(glGetShaderiv, FF_PFNGLGETSHADERIVPROC)
534  LOAD_OPENGL_FUN(glGetShaderInfoLog, FF_PFNGLGETSHADERINFOLOGPROC)
535  LOAD_OPENGL_FUN(glEnableVertexAttribArray, FF_PFNGLENABLEVERTEXATTRIBARRAYPROC)
536  LOAD_OPENGL_FUN(glVertexAttribPointer, FF_PFNGLVERTEXATTRIBPOINTERPROC)
537 
538  return 0;
539 
540 #undef SelectedGetProcAddress
541 #undef LOAD_OPENGL_FUN
542 }
543 #endif
544 
545 static void opengl_make_identity(float matrix[16])
546 {
547  memset(matrix, 0, 16 * sizeof(float));
548  matrix[0] = matrix[5] = matrix[10] = matrix[15] = 1.0f;
549 }
550 
551 static void opengl_make_ortho(float matrix[16], float left, float right,
552  float bottom, float top, float nearZ, float farZ)
553 {
554  float ral = right + left;
555  float rsl = right - left;
556  float tab = top + bottom;
557  float tsb = top - bottom;
558  float fan = farZ + nearZ;
559  float fsn = farZ - nearZ;
560 
561  memset(matrix, 0, 16 * sizeof(float));
562  matrix[0] = 2.0f / rsl;
563  matrix[5] = 2.0f / tsb;
564  matrix[10] = -2.0f / fsn;
565  matrix[12] = -ral / rsl;
566  matrix[13] = -tab / tsb;
567  matrix[14] = -fan / fsn;
568  matrix[15] = 1.0f;
569 }
570 
572 {
573  static const struct{
574  const char *extension;
575  int major;
576  int minor;
577  } required_extensions[] = {
578  { "GL_ARB_multitexture", 1, 3 },
579  { "GL_ARB_vertex_buffer_object", 1, 5 }, //GLX_ARB_vertex_buffer_object
580  { "GL_ARB_vertex_shader", 2, 0 },
581  { "GL_ARB_fragment_shader", 2, 0 },
582  { "GL_ARB_shader_objects", 2, 0 },
583  { NULL, 0, 0 }
584  };
585  int i, major, minor;
586  const char *extensions, *version;
587 
588  version = glGetString(GL_VERSION);
589  extensions = glGetString(GL_EXTENSIONS);
590 
591  av_log(opengl, AV_LOG_DEBUG, "OpenGL version: %s\n", version);
592  sscanf(version, "%d.%d", &major, &minor);
593 
594  for (i = 0; required_extensions[i].extension; i++) {
595  if (major < required_extensions[i].major &&
596  (major == required_extensions[i].major && minor < required_extensions[i].minor) &&
597  !strstr(extensions, required_extensions[i].extension)) {
598  av_log(opengl, AV_LOG_ERROR, "Required extension %s is not supported.\n",
599  required_extensions[i].extension);
600  av_log(opengl, AV_LOG_DEBUG, "Supported extensions are: %s\n", extensions);
601  return AVERROR(ENOSYS);
602  }
603  }
604  glGetIntegerv(GL_MAX_TEXTURE_SIZE, &opengl->max_texture_size);
605  glGetIntegerv(GL_MAX_VIEWPORT_DIMS, &opengl->max_viewport_width);
606  opengl->non_pow_2_textures = major >= 2 || strstr(extensions, "GL_ARB_texture_non_power_of_two");
607 #if defined(GL_ES_VERSION_2_0)
608  opengl->unpack_subimage = !!strstr(extensions, "GL_EXT_unpack_subimage");
609 #else
610  opengl->unpack_subimage = 1;
611 #endif
612 
613  av_log(opengl, AV_LOG_DEBUG, "Non Power of 2 textures support: %s\n", opengl->non_pow_2_textures ? "Yes" : "No");
614  av_log(opengl, AV_LOG_DEBUG, "Unpack Subimage extension support: %s\n", opengl->unpack_subimage ? "Yes" : "No");
615  av_log(opengl, AV_LOG_DEBUG, "Max texture size: %dx%d\n", opengl->max_texture_size, opengl->max_texture_size);
616  av_log(opengl, AV_LOG_DEBUG, "Max viewport size: %dx%d\n",
617  opengl->max_viewport_width, opengl->max_viewport_height);
618 
619  OPENGL_ERROR_CHECK(opengl);
620  return 0;
621  fail:
622  return AVERROR_EXTERNAL;
623 }
624 
626 {
627  int i;
628  for (i = 0; i < FF_ARRAY_ELEMS(opengl_format_desc); i++) {
629  if (opengl_format_desc[i].fixel_format == format)
631  }
632  return NULL;
633 }
634 
635 static int opengl_type_size(GLenum type)
636 {
637  switch(type) {
638  case GL_UNSIGNED_SHORT:
640  case GL_UNSIGNED_SHORT_5_6_5:
641  return 2;
642  case GL_UNSIGNED_BYTE:
645  default:
646  break;
647  }
648  return 1;
649 }
650 
652 {
653  int i;
654  for (i = 0; i < FF_ARRAY_ELEMS(opengl_format_desc); i++) {
655  if (opengl_format_desc[i].fixel_format == opengl->pix_fmt) {
656  opengl->format = opengl_format_desc[i].format;
657  opengl->type = opengl_format_desc[i].type;
658  break;
659  }
660  }
661 }
662 
664 {
665  AVRational sar, dar; /* sample and display aspect ratios */
666  OpenGLContext *opengl = s->priv_data;
667  AVStream *st = s->streams[0];
668  AVCodecParameters *par = st->codecpar;
669 
670  /* compute overlay width and height from the codec context information */
671  sar = st->sample_aspect_ratio.num ? st->sample_aspect_ratio : (AVRational){ 1, 1 };
672  dar = av_mul_q(sar, (AVRational){ par->width, par->height });
673 
674  /* we suppose the screen has a 1/1 sample aspect ratio */
675  /* fit in the window */
676  if (av_cmp_q(dar, (AVRational){ opengl->window_width, opengl->window_height }) > 0) {
677  /* fit in width */
678  opengl->picture_width = opengl->window_width;
679  opengl->picture_height = av_rescale(opengl->picture_width, dar.den, dar.num);
680  } else {
681  /* fit in height */
682  opengl->picture_height = opengl->window_height;
683  opengl->picture_width = av_rescale(opengl->picture_height, dar.num, dar.den);
684  }
685 }
686 
687 static av_cold void opengl_get_texture_size(OpenGLContext *opengl, int in_width, int in_height,
688  int *out_width, int *out_height)
689 {
690  if (opengl->non_pow_2_textures) {
691  *out_width = in_width;
692  *out_height = in_height;
693  } else {
694  int max = FFMIN(FFMAX(in_width, in_height), opengl->max_texture_size);
695  unsigned power_of_2 = 1;
696  while (power_of_2 < max)
697  power_of_2 *= 2;
698  *out_height = power_of_2;
699  *out_width = power_of_2;
700  av_log(opengl, AV_LOG_DEBUG, "Texture size calculated from %dx%d into %dx%d\n",
701  in_width, in_height, *out_width, *out_height);
702  }
703 }
704 
706 {
707  const AVPixFmtDescriptor *desc;
708  int shift;
709  enum AVPixelFormat pix_fmt = opengl->pix_fmt;
710 
711  /* We need order of components, not exact position, some minor HACKs here */
712  if (pix_fmt == AV_PIX_FMT_RGB565 || pix_fmt == AV_PIX_FMT_BGR555 ||
713  pix_fmt == AV_PIX_FMT_BGR8 || pix_fmt == AV_PIX_FMT_RGB8)
714  pix_fmt = AV_PIX_FMT_RGB24;
715  else if (pix_fmt == AV_PIX_FMT_BGR565 || pix_fmt == AV_PIX_FMT_RGB555)
716  pix_fmt = AV_PIX_FMT_BGR24;
717 
718  desc = av_pix_fmt_desc_get(pix_fmt);
719  if (!(desc->flags & AV_PIX_FMT_FLAG_RGB))
720  return;
721 
722 #define FILL_COMPONENT(i) { \
723  shift = (desc->comp[i].depth - 1) >> 3; \
724  opengl->color_map[(i << 2) + (desc->comp[i].offset >> shift)] = 1.0; \
725  }
726 
727  memset(opengl->color_map, 0, sizeof(opengl->color_map));
728  FILL_COMPONENT(0);
729  FILL_COMPONENT(1);
730  FILL_COMPONENT(2);
731  if (desc->flags & AV_PIX_FMT_FLAG_ALPHA)
732  FILL_COMPONENT(3);
733 
734 #undef FILL_COMPONENT
735 }
736 
737 static av_cold GLuint opengl_load_shader(OpenGLContext *opengl, GLenum type, const char *source)
738 {
739  GLuint shader = opengl->glprocs.glCreateShader(type);
740  GLint result;
741  if (!shader) {
742  av_log(opengl, AV_LOG_ERROR, "glCreateShader() failed\n");
743  return 0;
744  }
745  opengl->glprocs.glShaderSource(shader, 1, &source, NULL);
746  opengl->glprocs.glCompileShader(shader);
747 
748  opengl->glprocs.glGetShaderiv(shader, FF_GL_COMPILE_STATUS, &result);
749  if (!result) {
750  char *log;
751  opengl->glprocs.glGetShaderiv(shader, FF_GL_INFO_LOG_LENGTH, &result);
752  if (result) {
753  if ((log = av_malloc(result))) {
754  opengl->glprocs.glGetShaderInfoLog(shader, result, NULL, log);
755  av_log(opengl, AV_LOG_ERROR, "Compile error: %s\n", log);
756  av_free(log);
757  }
758  }
759  goto fail;
760  }
761  OPENGL_ERROR_CHECK(opengl);
762  return shader;
763  fail:
764  opengl->glprocs.glDeleteShader(shader);
765  return 0;
766 }
767 
769 {
770  GLint result;
771  const char *fragment_shader_code = opengl_get_fragment_shader_code(pix_fmt);
772 
773  if (!fragment_shader_code) {
774  av_log(opengl, AV_LOG_ERROR, "Provided pixel format '%s' is not supported\n",
775  av_get_pix_fmt_name(pix_fmt));
776  return AVERROR(EINVAL);
777  }
778 
781  if (!opengl->vertex_shader) {
782  av_log(opengl, AV_LOG_ERROR, "Vertex shader loading failed.\n");
783  goto fail;
784  }
786  fragment_shader_code);
787  if (!opengl->fragment_shader) {
788  av_log(opengl, AV_LOG_ERROR, "Fragment shader loading failed.\n");
789  goto fail;
790  }
791 
792  opengl->program = opengl->glprocs.glCreateProgram();
793  if (!opengl->program)
794  goto fail;
795 
796  opengl->glprocs.glAttachShader(opengl->program, opengl->vertex_shader);
797  opengl->glprocs.glAttachShader(opengl->program, opengl->fragment_shader);
798  opengl->glprocs.glLinkProgram(opengl->program);
799 
800  opengl->glprocs.glGetProgramiv(opengl->program, FF_GL_LINK_STATUS, &result);
801  if (!result) {
802  char *log;
803  opengl->glprocs.glGetProgramiv(opengl->program, FF_GL_INFO_LOG_LENGTH, &result);
804  if (result) {
805  log = av_malloc(result);
806  if (!log)
807  goto fail;
808  opengl->glprocs.glGetProgramInfoLog(opengl->program, result, NULL, log);
809  av_log(opengl, AV_LOG_ERROR, "Link error: %s\n", log);
810  av_free(log);
811  }
812  goto fail;
813  }
814 
815  opengl->position_attrib = opengl->glprocs.glGetAttribLocation(opengl->program, "a_position");
816  opengl->texture_coords_attrib = opengl->glprocs.glGetAttribLocation(opengl->program, "a_textureCoords");
817  opengl->projection_matrix_location = opengl->glprocs.glGetUniformLocation(opengl->program, "u_projectionMatrix");
818  opengl->model_view_matrix_location = opengl->glprocs.glGetUniformLocation(opengl->program, "u_modelViewMatrix");
819  opengl->color_map_location = opengl->glprocs.glGetUniformLocation(opengl->program, "u_colorMap");
820  opengl->texture_location[0] = opengl->glprocs.glGetUniformLocation(opengl->program, "u_texture0");
821  opengl->texture_location[1] = opengl->glprocs.glGetUniformLocation(opengl->program, "u_texture1");
822  opengl->texture_location[2] = opengl->glprocs.glGetUniformLocation(opengl->program, "u_texture2");
823  opengl->texture_location[3] = opengl->glprocs.glGetUniformLocation(opengl->program, "u_texture3");
824  opengl->chroma_div_w_location = opengl->glprocs.glGetUniformLocation(opengl->program, "u_chroma_div_w");
825  opengl->chroma_div_h_location = opengl->glprocs.glGetUniformLocation(opengl->program, "u_chroma_div_h");
826 
827  OPENGL_ERROR_CHECK(opengl);
828  return 0;
829  fail:
830  opengl->glprocs.glDeleteShader(opengl->vertex_shader);
831  opengl->glprocs.glDeleteShader(opengl->fragment_shader);
832  opengl->glprocs.glDeleteProgram(opengl->program);
833  opengl->fragment_shader = opengl->vertex_shader = opengl->program = 0;
834  return AVERROR_EXTERNAL;
835 }
836 
838  GLsizei width, GLsizei height)
839 {
840  if (texture) {
841  int new_width, new_height;
842  opengl_get_texture_size(opengl, width, height, &new_width, &new_height);
843  glBindTexture(GL_TEXTURE_2D, texture);
844  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
845  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
846  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
847  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
848  glTexImage2D(GL_TEXTURE_2D, 0, opengl->format, new_width, new_height, 0,
849  opengl->format, opengl->type, NULL);
851  }
852  return 0;
853  fail:
854  return AVERROR_EXTERNAL;
855 }
856 
858 {
859  OpenGLContext *opengl = s->priv_data;
860  int tex_w, tex_h;
861 
862  if (opengl->window_width > opengl->max_viewport_width || opengl->window_height > opengl->max_viewport_height) {
863  opengl->window_width = FFMIN(opengl->window_width, opengl->max_viewport_width);
864  opengl->window_height = FFMIN(opengl->window_height, opengl->max_viewport_height);
865  av_log(opengl, AV_LOG_WARNING, "Too big viewport requested, limited to %dx%d", opengl->window_width, opengl->window_height);
866  }
867  glViewport(0, 0, opengl->window_width, opengl->window_height);
869  - (float)opengl->window_width / 2.0f, (float)opengl->window_width / 2.0f,
870  - (float)opengl->window_height / 2.0f, (float)opengl->window_height / 2.0f,
871  1.0f, -1.0f);
873 
875 
876  opengl->vertex[0].z = opengl->vertex[1].z = opengl->vertex[2].z = opengl->vertex[3].z = 0.0f;
877  opengl->vertex[0].x = opengl->vertex[1].x = - (float)opengl->picture_width / 2.0f;
878  opengl->vertex[2].x = opengl->vertex[3].x = (float)opengl->picture_width / 2.0f;
879  opengl->vertex[1].y = opengl->vertex[2].y = - (float)opengl->picture_height / 2.0f;
880  opengl->vertex[0].y = opengl->vertex[3].y = (float)opengl->picture_height / 2.0f;
881 
882  opengl_get_texture_size(opengl, opengl->width, opengl->height, &tex_w, &tex_h);
883 
884  opengl->vertex[0].s0 = 0.0f;
885  opengl->vertex[0].t0 = 0.0f;
886  opengl->vertex[1].s0 = 0.0f;
887  opengl->vertex[1].t0 = (float)opengl->height / (float)tex_h;
888  opengl->vertex[2].s0 = (float)opengl->width / (float)tex_w;
889  opengl->vertex[2].t0 = (float)opengl->height / (float)tex_h;
890  opengl->vertex[3].s0 = (float)opengl->width / (float)tex_w;
891  opengl->vertex[3].t0 = 0.0f;
892 
894  opengl->glprocs.glBufferData(FF_GL_ARRAY_BUFFER, sizeof(opengl->vertex), opengl->vertex, FF_GL_STATIC_DRAW);
896  OPENGL_ERROR_CHECK(opengl);
897  return 0;
898  fail:
899  return AVERROR_EXTERNAL;
900 }
901 
902 static int opengl_prepare(OpenGLContext *opengl)
903 {
904  int i;
905  opengl->glprocs.glUseProgram(opengl->program);
906  opengl->glprocs.glUniformMatrix4fv(opengl->projection_matrix_location, 1, GL_FALSE, opengl->projection_matrix);
907  opengl->glprocs.glUniformMatrix4fv(opengl->model_view_matrix_location, 1, GL_FALSE, opengl->model_view_matrix);
908  for (i = 0; i < 4; i++)
909  if (opengl->texture_location[i] != -1) {
910  opengl->glprocs.glActiveTexture(GL_TEXTURE0 + i);
911  glBindTexture(GL_TEXTURE_2D, opengl->texture_name[i]);
912  opengl->glprocs.glUniform1i(opengl->texture_location[i], i);
913  }
914  if (opengl->color_map_location != -1)
915  opengl->glprocs.glUniformMatrix4fv(opengl->color_map_location, 1, GL_FALSE, opengl->color_map);
916  if (opengl->chroma_div_h_location != -1)
917  opengl->glprocs.glUniform1f(opengl->chroma_div_h_location, opengl->chroma_div_h);
918  if (opengl->chroma_div_w_location != -1)
919  opengl->glprocs.glUniform1f(opengl->chroma_div_w_location, opengl->chroma_div_w);
920 
921  OPENGL_ERROR_CHECK(opengl);
922  return 0;
923  fail:
924  return AVERROR_EXTERNAL;
925 }
926 
928 {
929  OpenGLContext *opengl = h->priv_data;
930  int ret;
931 
932  if (!opengl->no_window) {
933 #if CONFIG_SDL2
934  if ((ret = opengl_sdl_create_window(h)) < 0) {
935  av_log(opengl, AV_LOG_ERROR, "Cannot create default SDL window.\n");
936  return ret;
937  }
938 #else
939  av_log(opengl, AV_LOG_ERROR, "FFmpeg is compiled without SDL. Cannot create default window.\n");
940  return AVERROR(ENOSYS);
941 #endif
942  } else {
944  message.x = message.y = 0;
945  message.width = opengl->window_width;
946  message.height = opengl->window_height;
948  &message , sizeof(message))) < 0) {
949  av_log(opengl, AV_LOG_ERROR, "Application failed to create window buffer.\n");
950  return ret;
951  }
953  av_log(opengl, AV_LOG_ERROR, "Application failed to prepare window buffer.\n");
954  return ret;
955  }
956  }
957  return 0;
958 }
959 
961 {
962  int ret;
963  OpenGLContext *opengl = h->priv_data;
964  if (!opengl->no_window) {
965 #if CONFIG_SDL2
966  SDL_GL_DeleteContext(opengl->glcontext);
967  SDL_DestroyWindow(opengl->window);
968  SDL_Quit();
969 #endif
971  av_log(opengl, AV_LOG_ERROR, "Application failed to release window buffer.\n");
972  return ret;
973  }
974  return 0;
975 }
976 
978 {
979  OpenGLContext *opengl = h->priv_data;
980 
981  if (opengl->no_window &&
983  av_log(opengl, AV_LOG_ERROR, "Application failed to prepare window buffer.\n");
984 
985  opengl_deinit_context(opengl);
987 
988  return 0;
989 }
990 
992 {
993  int i, ret;
994  const AVPixFmtDescriptor *desc;
995 
996  if ((ret = opengl_compile_shaders(opengl, opengl->pix_fmt)) < 0)
997  goto fail;
998 
999  desc = av_pix_fmt_desc_get(opengl->pix_fmt);
1000  av_assert0(desc->nb_components > 0 && desc->nb_components <= 4);
1001  glGenTextures(desc->nb_components, opengl->texture_name);
1002 
1003  opengl->glprocs.glGenBuffers(2, &opengl->index_buffer);
1004  if (!opengl->index_buffer || !opengl->vertex_buffer) {
1005  av_log(opengl, AV_LOG_ERROR, "Buffer generation failed.\n");
1006  ret = AVERROR_EXTERNAL;
1007  goto fail;
1008  }
1009 
1010  opengl_configure_texture(opengl, opengl->texture_name[0], opengl->width, opengl->height);
1011  if (desc->nb_components > 1) {
1012  int has_alpha = desc->flags & AV_PIX_FMT_FLAG_ALPHA;
1013  int num_planes = desc->nb_components - (has_alpha ? 1 : 0);
1014  if (opengl->non_pow_2_textures) {
1015  opengl->chroma_div_w = 1.0f;
1016  opengl->chroma_div_h = 1.0f;
1017  } else {
1018  opengl->chroma_div_w = 1 << desc->log2_chroma_w;
1019  opengl->chroma_div_h = 1 << desc->log2_chroma_h;
1020  }
1021  for (i = 1; i < num_planes; i++)
1022  if (opengl->non_pow_2_textures)
1023  opengl_configure_texture(opengl, opengl->texture_name[i],
1024  AV_CEIL_RSHIFT(opengl->width, desc->log2_chroma_w),
1025  AV_CEIL_RSHIFT(opengl->height, desc->log2_chroma_h));
1026  else
1027  opengl_configure_texture(opengl, opengl->texture_name[i], opengl->width, opengl->height);
1028  if (has_alpha)
1029  opengl_configure_texture(opengl, opengl->texture_name[3], opengl->width, opengl->height);
1030  }
1031 
1035 
1036  glEnable(GL_BLEND);
1037  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1038 
1039  glClearColor((float)opengl->background[0] / 255.0f, (float)opengl->background[1] / 255.0f,
1040  (float)opengl->background[2] / 255.0f, 1.0f);
1041 
1042  ret = AVERROR_EXTERNAL;
1043  OPENGL_ERROR_CHECK(opengl);
1044 
1045  return 0;
1046  fail:
1047  return ret;
1048 }
1049 
1051 {
1052  OpenGLContext *opengl = h->priv_data;
1053  AVStream *st;
1054  int ret;
1055 
1056  if (h->nb_streams != 1 ||
1059  av_log(opengl, AV_LOG_ERROR, "Only a single video stream is supported.\n");
1060  return AVERROR(EINVAL);
1061  }
1062  st = h->streams[0];
1063  opengl->width = st->codecpar->width;
1064  opengl->height = st->codecpar->height;
1065  opengl->pix_fmt = st->codecpar->format;
1066  if (!opengl->window_width)
1067  opengl->window_width = opengl->width;
1068  if (!opengl->window_height)
1069  opengl->window_height = opengl->height;
1070 
1071  if (!opengl->window_title && !opengl->no_window)
1072  opengl->window_title = av_strdup(h->url);
1073 
1074  if ((ret = opengl_create_window(h)))
1075  goto fail;
1076 
1077  if ((ret = opengl_read_limits(opengl)) < 0)
1078  goto fail;
1079 
1080  if (opengl->width > opengl->max_texture_size || opengl->height > opengl->max_texture_size) {
1081  av_log(opengl, AV_LOG_ERROR, "Too big picture %dx%d, max supported size is %dx%d\n",
1082  opengl->width, opengl->height, opengl->max_texture_size, opengl->max_texture_size);
1083  ret = AVERROR(EINVAL);
1084  goto fail;
1085  }
1086 
1087  if ((ret = opengl_load_procedures(opengl)) < 0)
1088  goto fail;
1089 
1090  opengl_fill_color_map(opengl);
1091  opengl_get_texture_params(opengl);
1092 
1093  if ((ret = opengl_init_context(opengl)) < 0)
1094  goto fail;
1095 
1096  if ((ret = opengl_prepare_vertex(h)) < 0)
1097  goto fail;
1098 
1099  glClear(GL_COLOR_BUFFER_BIT);
1100 
1101 #if CONFIG_SDL2
1102  if (!opengl->no_window)
1103  SDL_GL_SwapWindow(opengl->window);
1104 #endif
1105  if (opengl->no_window &&
1107  av_log(opengl, AV_LOG_ERROR, "Application failed to display window buffer.\n");
1108  goto fail;
1109  }
1110 
1111  ret = AVERROR_EXTERNAL;
1112  OPENGL_ERROR_CHECK(opengl);
1113 
1114  opengl->inited = 1;
1115  return 0;
1116 
1117  fail:
1119  return ret;
1120 }
1121 
1122 static uint8_t* opengl_get_plane_pointer(OpenGLContext *opengl, AVPacket *pkt, int comp_index,
1123  const AVPixFmtDescriptor *desc)
1124 {
1125  uint8_t *data = pkt->data;
1126  int wordsize = opengl_type_size(opengl->type);
1127  int width_chroma = AV_CEIL_RSHIFT(opengl->width, desc->log2_chroma_w);
1128  int height_chroma = AV_CEIL_RSHIFT(opengl->height, desc->log2_chroma_h);
1129  int plane = desc->comp[comp_index].plane;
1130 
1131  switch(plane) {
1132  case 0:
1133  break;
1134  case 1:
1135  data += opengl->width * opengl->height * wordsize;
1136  break;
1137  case 2:
1138  data += opengl->width * opengl->height * wordsize;
1139  data += width_chroma * height_chroma * wordsize;
1140  break;
1141  case 3:
1142  data += opengl->width * opengl->height * wordsize;
1143  data += 2 * width_chroma * height_chroma * wordsize;
1144  break;
1145  default:
1146  return NULL;
1147  }
1148  return data;
1149 }
1150 
1151 #define LOAD_TEXTURE_DATA(comp_index, sub) \
1152 { \
1153  int width = sub ? AV_CEIL_RSHIFT(opengl->width, desc->log2_chroma_w) : opengl->width; \
1154  int height = sub ? AV_CEIL_RSHIFT(opengl->height, desc->log2_chroma_h): opengl->height; \
1155  uint8_t *data; \
1156  int plane = desc->comp[comp_index].plane; \
1157  \
1158  glBindTexture(GL_TEXTURE_2D, opengl->texture_name[comp_index]); \
1159  if (!is_pkt) { \
1160  GLint length = ((AVFrame *)input)->linesize[plane]; \
1161  int bytes_per_pixel = opengl_type_size(opengl->type); \
1162  if (!(desc->flags & AV_PIX_FMT_FLAG_PLANAR)) \
1163  bytes_per_pixel *= desc->nb_components; \
1164  data = ((AVFrame *)input)->data[plane]; \
1165  if (!(length % bytes_per_pixel) && \
1166  (opengl->unpack_subimage || ((length / bytes_per_pixel) == width))) { \
1167  length /= bytes_per_pixel; \
1168  if (length != width) \
1169  glPixelStorei(FF_GL_UNPACK_ROW_LENGTH, length); \
1170  glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, \
1171  opengl->format, opengl->type, data); \
1172  if (length != width) \
1173  glPixelStorei(FF_GL_UNPACK_ROW_LENGTH, 0); \
1174  } else { \
1175  int h; \
1176  for (h = 0; h < height; h++) { \
1177  glTexSubImage2D(GL_TEXTURE_2D, 0, 0, h, width, 1, \
1178  opengl->format, opengl->type, data); \
1179  data += length; \
1180  } \
1181  } \
1182  } else { \
1183  data = opengl_get_plane_pointer(opengl, input, comp_index, desc); \
1184  glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, \
1185  opengl->format, opengl->type, data); \
1186  } \
1187 }
1188 
1189 static int opengl_draw(AVFormatContext *h, void *input, int repaint, int is_pkt)
1190 {
1191  OpenGLContext *opengl = h->priv_data;
1192  enum AVPixelFormat pix_fmt = h->streams[0]->codecpar->format;
1193  const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pix_fmt);
1194  int ret;
1195 
1196 #if CONFIG_SDL2
1197  if (!opengl->no_window && (ret = opengl_sdl_process_events(h)) < 0)
1198  goto fail;
1199 #endif
1200  if (opengl->no_window &&
1202  av_log(opengl, AV_LOG_ERROR, "Application failed to prepare window buffer.\n");
1203  goto fail;
1204  }
1205 
1206  glClear(GL_COLOR_BUFFER_BIT);
1207 
1208  if (!repaint) {
1209  if (is_pkt)
1210  glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
1211  LOAD_TEXTURE_DATA(0, 0)
1212  if (desc->flags & AV_PIX_FMT_FLAG_PLANAR) {
1213  LOAD_TEXTURE_DATA(1, 1)
1214  LOAD_TEXTURE_DATA(2, 1)
1215  if (desc->flags & AV_PIX_FMT_FLAG_ALPHA)
1216  LOAD_TEXTURE_DATA(3, 0)
1217  }
1218  }
1219  ret = AVERROR_EXTERNAL;
1220  OPENGL_ERROR_CHECK(opengl);
1221 
1222  if ((ret = opengl_prepare(opengl)) < 0)
1223  goto fail;
1224 
1227  opengl->glprocs.glVertexAttribPointer(opengl->position_attrib, 3, GL_FLOAT, GL_FALSE, sizeof(OpenGLVertexInfo), 0);
1229  opengl->glprocs.glVertexAttribPointer(opengl->texture_coords_attrib, 2, GL_FLOAT, GL_FALSE, sizeof(OpenGLVertexInfo), 12);
1231 
1232  glDrawElements(GL_TRIANGLES, FF_ARRAY_ELEMS(g_index), GL_UNSIGNED_SHORT, 0);
1233 
1234  ret = AVERROR_EXTERNAL;
1235  OPENGL_ERROR_CHECK(opengl);
1236 
1237 #if CONFIG_SDL2
1238  if (!opengl->no_window)
1239  SDL_GL_SwapWindow(opengl->window);
1240 #endif
1241  if (opengl->no_window &&
1243  av_log(opengl, AV_LOG_ERROR, "Application failed to display window buffer.\n");
1244  goto fail;
1245  }
1246 
1247  return 0;
1248  fail:
1249  return ret;
1250 }
1251 
1253 {
1254  return opengl_draw(h, pkt, 0, 1);
1255 }
1256 
1257 static int opengl_write_frame(AVFormatContext *h, int stream_index,
1258  AVFrame **frame, unsigned flags)
1259 {
1260  if ((flags & AV_WRITE_UNCODED_FRAME_QUERY))
1261  return 0;
1262  return opengl_draw(h, *frame, 0, 0);
1263 }
1264 
1265 #define OFFSET(x) offsetof(OpenGLContext, x)
1266 #define ENC AV_OPT_FLAG_ENCODING_PARAM
1267 static const AVOption options[] = {
1268  { "background", "set background color", OFFSET(background), AV_OPT_TYPE_COLOR, {.str = "black"}, CHAR_MIN, CHAR_MAX, ENC },
1269  { "no_window", "disable default window", OFFSET(no_window), AV_OPT_TYPE_INT, {.i64 = 0}, INT_MIN, INT_MAX, ENC },
1270  { "window_title", "set window title", OFFSET(window_title), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, ENC },
1271  { "window_size", "set window size", OFFSET(window_width), AV_OPT_TYPE_IMAGE_SIZE, {.str = NULL}, 0, 0, ENC },
1272  { NULL }
1273 };
1274 
1275 static const AVClass opengl_class = {
1276  .class_name = "opengl outdev",
1277  .item_name = av_default_item_name,
1278  .option = options,
1279  .version = LIBAVUTIL_VERSION_INT,
1281 };
1282 
1284  .name = "opengl",
1285  .long_name = NULL_IF_CONFIG_SMALL("OpenGL output"),
1286  .priv_data_size = sizeof(OpenGLContext),
1287  .audio_codec = AV_CODEC_ID_NONE,
1288  .video_codec = AV_CODEC_ID_RAWVIDEO,
1291  .write_uncoded_frame = opengl_write_frame,
1293  .control_message = opengl_control_message,
1295  .priv_class = &opengl_class,
1296 };
int plane
Definition: avisynth_c.h:384
GLint max_texture_size
Maximum texture size.
Definition: opengl_enc.c:188
Window size change message.
Definition: avdevice.h:134
GLfloat model_view_matrix[16]
Modev view matrix.
Definition: opengl_enc.c:212
static void write_packet(OutputFile *of, AVPacket *pkt, OutputStream *ost, int unqueue)
Definition: ffmpeg.c:689
int plane
Which of the 4 planes contains the component.
Definition: pixdesc.h:35
#define NULL
Definition: coverity.c:32
Repaint request message.
Definition: avdevice.h:144
ptrdiff_t const GLvoid GLenum usage
Definition: opengl_enc.c:100
#define AV_PIX_FMT_YUVA422P16
Definition: pixfmt.h:430
static const GLushort g_index[6]
Definition: opengl_enc.c:167
static const char *const FF_OPENGL_FRAGMENT_SHADER_RGBA_PLANAR
Fragment shader for planar RGBA formats.
#define ENC
Definition: opengl_enc.c:1266
static enum AVPixelFormat pix_fmt
static int shift(int a, int b)
Definition: sonic.c:82
#define FF_GL_FRAGMENT_SHADER
Definition: opengl_enc.c:92
FF_PFNGLDELETESHADERPROC glDeleteShader
Definition: opengl_enc.c:144
static int opengl_prepare(OpenGLContext *opengl)
Definition: opengl_enc.c:902
Prepare window buffer message.
Definition: avdevice.h:229
const AVPixFmtDescriptor * av_pix_fmt_desc_get(enum AVPixelFormat pix_fmt)
Definition: pixdesc.c:2522
float z
Position.
Definition: opengl_enc.c:162
This structure describes decoded (raw) audio or video data.
Definition: frame.h:268
GLfloat chroma_div_h
Chroma subsampling h ratio.
Definition: opengl_enc.c:215
int x
x coordinate of top left corner
Definition: avdevice.h:110
int picture_width
Rendered width.
Definition: opengl_enc.c:223
AVOption.
Definition: opt.h:246
ptrdiff_t const GLvoid * data
Definition: opengl_enc.c:100
const char *const * fragment_shader
Definition: opengl_enc.c:231
FF_PFNGLDELETEPROGRAMPROC glDeleteProgram
Definition: opengl_enc.c:137
planar YUV 4:4:4, 24bpp, (1 Cr & Cb sample per 1x1 Y samples)
Definition: pixfmt.h:71
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition: log.h:182
static int opengl_type_size(GLenum type)
Definition: opengl_enc.c:635
#define LOAD_OPENGL_FUN(name, type)
#define LIBAVUTIL_VERSION_INT
Definition: version.h:85
packed RGB 8:8:8, 24bpp, RGBRGB...
Definition: pixfmt.h:68
const char * desc
Definition: nvenc.c:68
#define FF_GL_LINK_STATUS
Definition: opengl_enc.c:95
#define AV_PIX_FMT_RGBA64
Definition: pixfmt.h:377
GLint model_view_matrix_location
Definition: opengl_enc.c:203
#define APIENTRY
Definition: opengl_enc.c:64
int inited
Set to 1 when write_header was successfully called.
Definition: opengl_enc.c:182
int no_window
0 for create default window
Definition: opengl_enc.c:184
enum AVCodecID codec_id
Specific type of the encoded data (the codec used).
Definition: avcodec.h:3953
planar GBR 4:4:4 24bpp
Definition: pixfmt.h:168
AVRational sample_aspect_ratio
sample aspect ratio (0 if unknown)
Definition: avformat.h:943
int num
Numerator.
Definition: rational.h:59
const char * av_default_item_name(void *ptr)
Return the context name.
Definition: log.c:191
#define AV_PIX_FMT_BGRA64
Definition: pixfmt.h:382
#define OPENGL_ERROR_CHECK(ctx)
Definition: opengl_enc.c:151
AVS_VideoFrame int int int int new_height
Definition: avisynth_c.h:913
GLint GLenum type
Definition: opengl_enc.c:104
static av_cold int opengl_write_trailer(AVFormatContext *h)
Definition: opengl_enc.c:977
static const char *const FF_OPENGL_VERTEX_SHADER
int version
Definition: avisynth_c.h:858
packed BGR 8:8:8, 32bpp, XBGRXBGR... X=unused/undefined
Definition: pixfmt.h:239
GLfloat v0
Definition: opengl_enc.c:106
static AVPacket pkt
FF_PFNGLATTACHSHADERPROC glAttachShader
Definition: opengl_enc.c:142
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFrame structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel sample format(the sample packing is implied by the sample format) and sample rate.The lists are not just lists
GLint texture_location[4]
Definition: opengl_enc.c:207
uint8_t log2_chroma_w
Amount to shift the luma width right to find the chroma width.
Definition: pixdesc.h:92
static void opengl_compute_display_area(AVFormatContext *s)
Definition: opengl_enc.c:663
This struct describes the properties of an encoded stream.
Definition: avcodec.h:3945
FF_PFNGLUSEPROGRAMPROC glUseProgram
Definition: opengl_enc.c:138
Display window buffer message.
Definition: avdevice.h:240
static av_cold int opengl_init_context(OpenGLContext *opengl)
Definition: opengl_enc.c:991
Format I/O context.
Definition: avformat.h:1358
Create window buffer message.
Definition: avdevice.h:218
GLsizei const char ** string
Definition: opengl_enc.c:119
FF_PFNGLCOMPILESHADERPROC glCompileShader
Definition: opengl_enc.c:145
GLint GLenum GLboolean normalized
Definition: opengl_enc.c:104
static int opengl_write_packet(AVFormatContext *h, AVPacket *pkt)
Definition: opengl_enc.c:1252
FF_PFNGLSHADERSOURCEPROC glShaderSource
Definition: opengl_enc.c:146
const char * class_name
The name of the class; usually it is the same name as the context structure type to which the AVClass...
Definition: log.h:72
int avdevice_dev_to_app_control_message(struct AVFormatContext *s, enum AVDevToAppMessageType type, void *data, size_t data_size)
Send control message from device to application.
Definition: avdevice.c:135
int height
Stream height.
Definition: opengl_enc.c:221
#define av_assert0(cond)
assert() equivalent, that is always enabled.
Definition: avassert.h:37
static av_cold void opengl_fill_color_map(OpenGLContext *opengl)
Definition: opengl_enc.c:705
#define FF_GL_ELEMENT_ARRAY_BUFFER
Definition: opengl_enc.c:90
FF_PFNGLUNIFORM1FPROC glUniform1f
Definition: opengl_enc.c:133
planar YUV 4:2:0, 20bpp, (1 Cr & Cb sample per 2x2 Y & A samples)
Definition: pixfmt.h:101
AVComponentDescriptor comp[4]
Parameters that describe how pixels are packed.
Definition: pixdesc.h:117
uint8_t
#define av_cold
Definition: attributes.h:82
#define AV_PIX_FMT_FLAG_ALPHA
The pixel format has an alpha channel.
Definition: pixdesc.h:177
#define av_malloc(s)
#define FF_GL_UNSIGNED_BYTE_3_3_2
Definition: opengl_enc.c:83
int width
Video only.
Definition: avcodec.h:4019
FF_PFNGLGETUNIFORMLOCATIONPROC glGetUniformLocation
Definition: opengl_enc.c:132
packed RGB 8:8:8, 32bpp, RGBXRGBX... X=unused/undefined
Definition: pixfmt.h:238
AVOptions.
GLint position_attrib
Attibutes&#39; locations.
Definition: opengl_enc.c:208
Query whether the feature is possible on this stream.
Definition: internal.h:644
static av_cold int end(AVCodecContext *avctx)
Definition: avrndec.c:90
FF_PFNGLGETSHADERIVPROC glGetShaderiv
Definition: opengl_enc.c:147
FF_PFNGLBINDBUFFERPROC glBindBuffer
Definition: opengl_enc.c:128
GLsizei GLboolean const GLfloat * value
Definition: opengl_enc.c:108
static int opengl_resize(AVFormatContext *h, int width, int height)
Definition: opengl_enc.c:309
AVStream ** streams
A list of all streams in the file.
Definition: avformat.h:1426
packed ABGR 8:8:8:8, 32bpp, ABGRABGR...
Definition: pixfmt.h:94
GLint GLenum GLboolean GLsizei uintptr_t pointer
Definition: opengl_enc.c:104
#define height
uint8_t * data
Definition: avcodec.h:1477
FF_PFNGLENABLEVERTEXATTRIBARRAYPROC glEnableVertexAttribArray
Definition: opengl_enc.c:130
#define AV_PIX_FMT_BGR48
Definition: pixfmt.h:378
GLfloat chroma_div_w
Chroma subsampling w ratio.
Definition: opengl_enc.c:214
#define AV_PIX_FMT_YUV444P16
Definition: pixfmt.h:400
static int opengl_draw(AVFormatContext *h, void *intput, int repaint, int is_pkt)
Definition: opengl_enc.c:1189
static int opengl_control_message(AVFormatContext *h, int type, void *data, size_t data_size)
Definition: opengl_enc.c:329
these buffered frames must be flushed immediately if a new input produces new the filter must not call request_frame to get more It must just process the frame or queue it The task of requesting more frames is left to the filter s request_frame method or the application If a filter has several the filter must be ready for frames arriving randomly on any input any filter with several inputs will most likely require some kind of queuing mechanism It is perfectly acceptable to have a limited queue and to drop frames when the inputs are too unbalanced request_frame For filters that do not use the this method is called when a frame is wanted on an output For a source
ptrdiff_t size
Definition: opengl_enc.c:100
GLuint vertex_buffer
Vertex buffer.
Definition: opengl_enc.c:200
#define AV_PIX_FMT_YUVA420P16
Definition: pixfmt.h:429
#define av_log(a,...)
GLuint fragment_shader
Fragment shader for current pix_pmt.
Definition: opengl_enc.c:197
GLuint texture_name[4]
Textures&#39; IDs.
Definition: opengl_enc.c:198
FF_PFNGLLINKPROGRAMPROC glLinkProgram
Definition: opengl_enc.c:139
GLint texture_coords_attrib
Definition: opengl_enc.c:209
Main libavdevice API header.
FFOpenGLFunctions glprocs
Definition: opengl_enc.c:180
#define FF_GL_VERTEX_SHADER
Definition: opengl_enc.c:93
planar YUV 4:2:2 24bpp, (1 Cr & Cb sample per 2x1 Y & A samples)
Definition: pixfmt.h:176
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:260
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:176
uint8_t log2_chroma_h
Amount to shift the luma height right to find the chroma height.
Definition: pixdesc.h:101
FF_PFNGLDELETEBUFFERSPROC glDeleteBuffers
Definition: opengl_enc.c:126
#define AV_PIX_FMT_FLAG_RGB
The pixel format contains RGB-like data (as opposed to YUV/grayscale).
Definition: pixdesc.h:148
AVOutputFormat ff_opengl_muxer
Definition: opengl_enc.c:1283
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification. ...
Definition: internal.h:186
packed BGRA 8:8:8:8, 32bpp, BGRABGRA...
Definition: pixfmt.h:95
char * url
input or output URL.
Definition: avformat.h:1454
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
Definition: log.h:197
#define s0
Definition: regdef.h:37
#define AV_PIX_FMT_YUVA444P16
Definition: pixfmt.h:431
enum AVMediaType codec_type
General type of the encoded data.
Definition: avcodec.h:3949
GLenum GLint * params
Definition: opengl_enc.c:113
#define AV_PIX_FMT_RGB48
Definition: pixfmt.h:373
simple assert() macros that are a bit more flexible than ISO C assert().
static const char *const FF_OPENGL_FRAGMENT_SHADER_YUVA_PLANAR
Fragment shader for planar YUVA formats.
GLsizei GLsizei * length
Definition: opengl_enc.c:114
int non_pow_2_textures
1 when non power of 2 textures are supported
Definition: opengl_enc.c:191
GLsizei count
Definition: opengl_enc.c:108
#define FFMAX(a, b)
Definition: common.h:94
GLint chroma_div_w_location
Definition: opengl_enc.c:205
static const char *const FF_OPENGL_FRAGMENT_SHADER_RGB_PLANAR
Fragment shader for planar RGB formats.
packed ARGB 8:8:8:8, 32bpp, ARGBARGB...
Definition: pixfmt.h:92
#define fail()
Definition: checkasm.h:120
#define AV_PIX_FMT_GBRAP16
Definition: pixfmt.h:409
packed RGBA 8:8:8:8, 32bpp, RGBARGBA...
Definition: pixfmt.h:93
planar YUV 4:2:2, 16bpp, (1 Cr & Cb sample per 2x1 Y samples)
Definition: pixfmt.h:70
uint64_t flags
Combination of AV_PIX_FMT_FLAG_...
Definition: pixdesc.h:106
unsigned int nb_streams
Number of elements in AVFormatContext.streams.
Definition: avformat.h:1414
uint8_t background[4]
Background color.
Definition: opengl_enc.c:183
static const char *const FF_OPENGL_FRAGMENT_SHADER_RGBA_PACKET
Fragment shader for packet RGBA formats.
static SDL_Window * window
Definition: ffplay.c:367
uint8_t nb_components
The number of components each pixel has, (1-4)
Definition: pixdesc.h:83
#define AV_PIX_FMT_GBRP16
Definition: pixfmt.h:406
#define AV_PIX_FMT_GRAY16
Definition: pixfmt.h:371
int64_t av_rescale(int64_t a, int64_t b, int64_t c)
Rescale a 64-bit integer with rounding to nearest.
Definition: mathematics.c:129
#define FFMIN(a, b)
Definition: common.h:96
static av_cold int opengl_write_header(AVFormatContext *h)
Definition: opengl_enc.c:1050
#define width
static av_cold void opengl_deinit_context(OpenGLContext *opengl)
Definition: opengl_enc.c:283
typedef void(APIENTRY *FF_PFNGLACTIVETEXTUREPROC)(GLenum texture)
static int write_trailer(AVFormatContext *s1)
Definition: v4l2enc.c:94
Undefined Behavior In the C some operations are like signed integer dereferencing freed accessing outside allocated Undefined Behavior must not occur in a C program
Definition: undefined.txt:3
static const char * opengl_get_fragment_shader_code(enum AVPixelFormat format)
Definition: opengl_enc.c:625
enum AVPixelFormat pix_fmt
Stream pixel format.
Definition: opengl_enc.c:222
const char * name
Definition: avformat.h:505
FF_PFNGLCREATEPROGRAMPROC glCreateProgram
Definition: opengl_enc.c:136
static const AVOption options[]
Definition: opengl_enc.c:1267
#define FF_GL_RED_COMPONENT
Definition: opengl_enc.c:79
these buffered frames must be flushed immediately if a new input produces new the filter must not call request_frame to get more It must just process the frame or queue it The task of requesting more frames is left to the filter s request_frame method or the application If a filter has several the filter must be ready for frames arriving randomly on any input any filter with several inputs will most likely require some kind of queuing mechanism It is perfectly acceptable to have a limited queue and to drop frames when the inputs are too unbalanced request_frame For filters that do not use the this method is called when a frame is wanted on an output For a it should directly call filter_frame on the corresponding output For a if there are queued frames already one of these frames should be pushed If the filter should request a frame on one of its repeatedly until at least one frame has been pushed Return or at least make progress towards producing a frame
#define s(width, name)
Definition: cbs_vp9.c:257
int n
Definition: avisynth_c.h:760
static av_cold GLuint opengl_load_shader(OpenGLContext *opengl, GLenum type, const char *source)
Definition: opengl_enc.c:737
packed RGB 8:8:8, 24bpp, BGRBGR...
Definition: pixfmt.h:69
float t0
Texture coords.
Definition: opengl_enc.c:163
OpenGLVertexInfo vertex[4]
VBO.
Definition: opengl_enc.c:201
typedef GLint(APIENTRY *FF_PFNGLGETATTRIBLOCATIONPROC)(GLuint program
FF_PFNGLBUFFERDATAPROC glBufferData
Definition: opengl_enc.c:127
#define FF_ARRAY_ELEMS(a)
Destroy window buffer message.
Definition: avdevice.h:251
#define FF_GL_STATIC_DRAW
Definition: opengl_enc.c:91
#define FILL_COMPONENT(i)
Stream structure.
Definition: avformat.h:881
#define AVFMT_NOTIMESTAMPS
Format does not need / have any timestamps.
Definition: avformat.h:467
#define AV_PIX_FMT_YUV420P16
Definition: pixfmt.h:398
#define AV_PIX_FMT_BGR555
Definition: pixfmt.h:380
GLint chroma_div_h_location
Definition: opengl_enc.c:206
static int opengl_release_window(AVFormatContext *h)
Definition: opengl_enc.c:960
packed RGB 3:3:2, 8bpp, (msb)2B 3G 3R(lsb)
Definition: pixfmt.h:83
GLuint shader
Definition: opengl_enc.c:115
#define AV_LOG_INFO
Standard information.
Definition: log.h:187
FF_PFNGLGETPROGRAMINFOLOGPROC glGetProgramInfoLog
Definition: opengl_enc.c:141
char * av_strdup(const char *s)
Duplicate a string.
Definition: mem.c:251
int height
height
Definition: avdevice.h:113
static const struct OpenGLFormatDesc opengl_format_desc[]
GLfloat projection_matrix[16]
Projection matrix.
Definition: opengl_enc.c:211
planar YUV 4:4:4 32bpp, (1 Cr & Cb sample per 1x1 Y & A samples)
Definition: pixfmt.h:177
GLenum pname
Definition: opengl_enc.c:113
Descriptor that unambiguously describes how the bits of a pixel are stored in the up to 4 data planes...
Definition: pixdesc.h:81
FF_PFNGLUNIFORMMATRIX4FVPROC glUniformMatrix4fv
Definition: opengl_enc.c:135
static av_cold void opengl_get_texture_size(OpenGLContext *opengl, int in_width, int in_height, int *out_width, int *out_height)
Definition: opengl_enc.c:687
static av_cold void opengl_get_texture_params(OpenGLContext *opengl)
Definition: opengl_enc.c:651
static const char *const FF_OPENGL_FRAGMENT_SHADER_GRAY
static int opengl_create_window(AVFormatContext *h)
Definition: opengl_enc.c:927
#define FF_GL_INFO_LOG_LENGTH
Definition: opengl_enc.c:96
static av_cold int opengl_read_limits(OpenGLContext *opengl)
Definition: opengl_enc.c:571
typedef GLuint(APIENTRY *FF_PFNGLCREATEPROGRAMPROC)(void)
Tag MUST be and< 10hcoeff half pel interpolation filter coefficients, hcoeff[0] are the 2 middle coefficients[1] are the next outer ones and so on, resulting in a filter like:...eff[2], hcoeff[1], hcoeff[0], hcoeff[0], hcoeff[1], hcoeff[2]...the sign of the coefficients is not explicitly stored but alternates after each coeff and coeff[0] is positive, so...,+,-,+,-,+,+,-,+,-,+,...hcoeff[0] is not explicitly stored but found by subtracting the sum of all stored coefficients with signs from 32 hcoeff[0]=32-hcoeff[1]-hcoeff[2]-...a good choice for hcoeff and htaps is htaps=6 hcoeff={40,-10, 2}an alternative which requires more computations at both encoder and decoder side and may or may not be better is htaps=8 hcoeff={42,-14, 6,-2}ref_frames minimum of the number of available reference frames and max_ref_frames for example the first frame after a key frame always has ref_frames=1spatial_decomposition_type wavelet type 0 is a 9/7 symmetric compact integer wavelet 1 is a 5/3 symmetric compact integer wavelet others are reserved stored as delta from last, last is reset to 0 if always_reset||keyframeqlog quality(logarithmic quantizer scale) stored as delta from last, last is reset to 0 if always_reset||keyframemv_scale stored as delta from last, last is reset to 0 if always_reset||keyframe FIXME check that everything works fine if this changes between framesqbias dequantization bias stored as delta from last, last is reset to 0 if always_reset||keyframeblock_max_depth maximum depth of the block tree stored as delta from last, last is reset to 0 if always_reset||keyframequant_table quantization tableHighlevel bitstream structure:==============================--------------------------------------------|Header|--------------------------------------------|------------------------------------|||Block0||||split?||||yes no||||.........intra?||||:Block01:yes no||||:Block02:.................||||:Block03::y DC::ref index:||||:Block04::cb DC::motion x:||||.........:cr DC::motion y:||||.................|||------------------------------------||------------------------------------|||Block1|||...|--------------------------------------------|------------------------------------|||Y subbands||Cb subbands||Cr subbands||||------||------||------|||||LL0||HL0||||LL0||HL0||||LL0||HL0|||||------||------||------||||------||------||------|||||LH0||HH0||||LH0||HH0||||LH0||HH0|||||------||------||------||||------||------||------|||||HL1||LH1||||HL1||LH1||||HL1||LH1|||||------||------||------||||------||------||------|||||HH1||HL2||||HH1||HL2||||HH1||HL2|||||...||...||...|||------------------------------------|--------------------------------------------Decoding process:=================------------|||Subbands|------------||||------------|Intra DC||||LL0 subband prediction------------|\Dequantization-------------------\||Reference frames|\IDWT|--------------|Motion\|||Frame 0||Frame 1||Compensation.OBMC v-------|--------------|--------------.\------> Frame n output Frame Frame<----------------------------------/|...|-------------------Range Coder:============Binary Range Coder:-------------------The implemented range coder is an adapted version based upon"Range encoding: an algorithm for removing redundancy from a digitised message."by G.N.N.Martin.The symbols encoded by the Snow range coder are bits(0|1).The associated probabilities are not fix but change depending on the symbol mix seen so far.bit seen|new state---------+-----------------------------------------------0|256-state_transition_table[256-old_state];1|state_transition_table[old_state];state_transition_table={0, 0, 0, 0, 0, 0, 0, 0, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 190, 191, 192, 194, 194, 195, 196, 197, 198, 199, 200, 201, 202, 202, 204, 205, 206, 207, 208, 209, 209, 210, 211, 212, 213, 215, 215, 216, 217, 218, 219, 220, 220, 222, 223, 224, 225, 226, 227, 227, 229, 229, 230, 231, 232, 234, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 248, 0, 0, 0, 0, 0, 0, 0};FIXME Range Coding of integers:-------------------------FIXME Neighboring Blocks:===================left and top are set to the respective blocks unless they are outside of the image in which case they are set to the Null block top-left is set to the top left block unless it is outside of the image in which case it is set to the left block if this block has no larger parent block or it is at the left side of its parent block and the top right block is not outside of the image then the top right block is used for top-right else the top-left block is used Null block y, cb, cr are 128 level, ref, mx and my are 0 Motion Vector Prediction:=========================1.the motion vectors of all the neighboring blocks are scaled to compensate for the difference of reference frames scaled_mv=(mv *(256 *(current_reference+1)/(mv.reference+1))+128)> the median of the scaled left
Definition: snow.txt:206
static const char * window_title
Definition: ffplay.c:312
GLsizei bufSize
Definition: opengl_enc.c:114
planar YUV 4:1:0, 9bpp, (1 Cr & Cb sample per 4x4 Y samples)
Definition: pixfmt.h:72
Describe the class of an AVClass context structure.
Definition: log.h:67
static void opengl_make_ortho(float matrix[16], float left, float right, float bottom, float top, float nearZ, float farZ)
Definition: opengl_enc.c:551
int index
Definition: gxfenc.c:89
Rational number (pair of numerator and denominator).
Definition: rational.h:58
FF_PFNGLGENBUFFERSPROC glGenBuffers
Definition: opengl_enc.c:125
FF_PFNGLGETSHADERINFOLOGPROC glGetShaderInfoLog
Definition: opengl_enc.c:148
#define FF_GL_ARRAY_BUFFER
Definition: opengl_enc.c:89
static av_cold int opengl_prepare_vertex(AVFormatContext *s)
Definition: opengl_enc.c:857
packed BGR 8:8:8, 32bpp, BGRXBGRX... X=unused/undefined
Definition: pixfmt.h:240
GLsizei GLsizei char * infoLog
Definition: opengl_enc.c:114
and forward the test the status of outputs and forward it to the corresponding return FFERROR_NOT_READY If the filters stores internally one or a few frame for some input
GLsizei GLboolean transpose
Definition: opengl_enc.c:108
GLuint vertex_shader
Vertex shader.
Definition: opengl_enc.c:196
FF_PFNGLUNIFORM1IPROC glUniform1i
Definition: opengl_enc.c:134
static int av_cold opengl_load_procedures(OpenGLContext *opengl)
Definition: opengl_enc.c:490
offset must point to two consecutive integers
Definition: opt.h:233
GLint color_map_location
Definition: opengl_enc.c:204
#define FF_GL_UNSIGNED_BYTE_2_3_3_REV
Definition: opengl_enc.c:84
int picture_height
Rendered height.
Definition: opengl_enc.c:224
#define AV_PIX_FMT_BGR565
Definition: pixfmt.h:379
FF_PFNGLGETPROGRAMIVPROC glGetProgramiv
Definition: opengl_enc.c:140
#define flags(name, subs,...)
Definition: cbs_av1.c:561
int width
width
Definition: avdevice.h:112
GLuint program
Shader program.
Definition: opengl_enc.c:195
char * window_title
Title of the window.
Definition: opengl_enc.c:185
#define FF_GL_UNSIGNED_SHORT_1_5_5_5_REV
Definition: opengl_enc.c:85
static int av_cmp_q(AVRational a, AVRational b)
Compare two rationals.
Definition: rational.h:89
int unpack_subimage
1 when GL_EXT_unpack_subimage is available
Definition: opengl_enc.c:192
Main libavformat public API header.
static int opengl_write_frame(AVFormatContext *h, int stream_index, AVFrame **frame, unsigned flags)
Definition: opengl_enc.c:1257
GLint GLenum GLboolean GLsizei stride
Definition: opengl_enc.c:104
FF_PFNGLVERTEXATTRIBPOINTERPROC glVertexAttribPointer
Definition: opengl_enc.c:131
planar YUV 4:2:0, 12bpp, (1 Cr & Cb sample per 2x2 Y samples)
Definition: pixfmt.h:66
Y , 8bpp.
Definition: pixfmt.h:74
static av_cold int opengl_compile_shaders(OpenGLContext *opengl, enum AVPixelFormat pix_fmt)
Definition: opengl_enc.c:768
FF_PFNGLACTIVETEXTUREPROC glActiveTexture
Definition: opengl_enc.c:124
common internal and external API header
#define AVFMT_NOFILE
Demuxer will use avio_open, no opened file should be provided by the caller.
Definition: avformat.h:463
GLuint * buffers
Definition: opengl_enc.c:98
planar GBRA 4:4:4:4 32bpp
Definition: pixfmt.h:215
GLint max_viewport_height
Maximum viewport size.
Definition: opengl_enc.c:190
FF_PFNGLCREATESHADERPROC glCreateShader
Definition: opengl_enc.c:143
GLint max_viewport_width
Maximum viewport size.
Definition: opengl_enc.c:189
packed RGB 3:3:2, 8bpp, (msb)2R 3G 3B(lsb)
Definition: pixfmt.h:86
#define AV_PIX_FMT_RGB555
Definition: pixfmt.h:375
planar YUV 4:1:1, 12bpp, (1 Cr & Cb sample per 4x1 Y samples)
Definition: pixfmt.h:73
#define FF_GL_COMPILE_STATUS
Definition: opengl_enc.c:94
GLfloat color_map[16]
RGBA color map matrix.
Definition: opengl_enc.c:213
int den
Denominator.
Definition: rational.h:60
static const char *const FF_OPENGL_FRAGMENT_SHADER_YUV_PLANAR
Fragment shader for planar YUV formats.
static const AVClass opengl_class
Definition: opengl_enc.c:1275
#define AVFMT_VARIABLE_FPS
Format allows variable fps.
Definition: avformat.h:470
#define av_free(p)
void * priv_data
Format private data.
Definition: avformat.h:1386
GLuint index_buffer
Index buffer.
Definition: opengl_enc.c:199
#define OFFSET(x)
Definition: opengl_enc.c:1265
static void write_header(FFV1Context *f)
Definition: ffv1enc.c:337
static uint8_t * opengl_get_plane_pointer(OpenGLContext *opengl, AVPacket *pkt, int comp_index, const AVPixFmtDescriptor *desc)
Definition: opengl_enc.c:1122
static const char *const FF_OPENGL_FRAGMENT_SHADER_RGB_PACKET
Fragment shader for packet RGB formats.
GLenum format
Definition: opengl_enc.c:218
static const struct twinvq_data tab
#define LOAD_TEXTURE_DATA(comp_index, sub)
Definition: opengl_enc.c:1151
#define AV_PIX_FMT_RGB565
Definition: pixfmt.h:374
static av_cold int opengl_configure_texture(OpenGLContext *opengl, GLuint texture, GLsizei width, GLsizei height)
Definition: opengl_enc.c:837
and forward the result(frame or status change) to the corresponding input.If nothing is possible
AVRational av_mul_q(AVRational b, AVRational c)
Multiply two rationals.
Definition: rational.c:80
planar YUV 4:4:0 (1 Cr & Cb sample per 1x2 Y samples)
Definition: pixfmt.h:99
FF_PFNGLGETATTRIBLOCATIONPROC glGetAttribLocation
Definition: opengl_enc.c:129
AVCodecParameters * codecpar
Codec parameters associated with this stream.
Definition: avformat.h:1028
int y
y coordinate of top left corner
Definition: avdevice.h:111
const char * av_get_pix_fmt_name(enum AVPixelFormat pix_fmt)
Return the short name for a pixel format, NULL in case pix_fmt is unknown.
Definition: pixdesc.c:2438
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFrame structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel sample they are references to shared objects When the negotiation mechanism computes the intersection of the formats supported at each end of a all references to both lists are replaced with a reference to the intersection And when a single format is eventually chosen for a link amongst the remaining all references to the list are updated That means that if a filter requires that its input and output have the same format amongst a supported all it has to do is use a reference to the same list of formats query_formats can leave some formats unset and return AVERROR(EAGAIN) to cause the negotiation mechanism toagain later.That can be used by filters with complex requirements to use the format negotiated on one link to set the formats supported on another.Frame references ownership and permissions
packed RGB 8:8:8, 32bpp, XRGBXRGB... X=unused/undefined
Definition: pixfmt.h:237
int width
Stream width.
Definition: opengl_enc.c:220
static void opengl_make_identity(float matrix[16])
Definition: opengl_enc.c:545
#define AVERROR_EXTERNAL
Generic error in an external library.
Definition: error.h:57
AVPixelFormat
Pixel format.
Definition: pixfmt.h:64
This structure stores compressed data.
Definition: avcodec.h:1454
#define AV_PIX_FMT_FLAG_PLANAR
At least one pixel component is not in the first data plane.
Definition: pixdesc.h:144
#define AV_PIX_FMT_YUV422P16
Definition: pixfmt.h:399
GLuint buffer
Definition: opengl_enc.c:101
#define AV_CEIL_RSHIFT(a, b)
Definition: common.h:58
const char * name
Definition: opengl_enc.c:102
GLint projection_matrix_location
Uniforms&#39; locations.
Definition: opengl_enc.c:202