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 <unistd.h>
29 #include <stddef.h>
30 
31 #include "config.h"
32 
33 #if HAVE_WINDOWS_H
34 #define WIN32_LEAN_AND_MEAN
35 #include <windows.h>
36 #endif
37 #if HAVE_OPENGL_GL3_H
38 #include <OpenGL/gl3.h>
39 #elif HAVE_ES2_GL_H
40 #include <ES2/gl.h>
41 #else
42 #include <GL/gl.h>
43 #include <GL/glext.h>
44 #endif
45 #if HAVE_GLXGETPROCADDRESS
46 #include <GL/glx.h>
47 #endif
48 
49 #if CONFIG_SDL2
50 #include <SDL.h>
51 #endif
52 
53 #include "libavutil/common.h"
54 #include "libavutil/pixdesc.h"
55 #include "libavutil/log.h"
56 #include "libavutil/opt.h"
57 #include "libavutil/avassert.h"
58 #include "libavutil/avstring.h"
59 #include "libavformat/avformat.h"
60 #include "libavformat/internal.h"
61 #include "libavdevice/avdevice.h"
62 #include "opengl_enc_shaders.h"
63 
64 #ifndef APIENTRY
65 #define APIENTRY
66 #endif
67 
68 /* FF_GL_RED_COMPONENT is used for planar pixel types.
69  * Only red component is sampled in shaders.
70  * On some platforms GL_RED is not available and GL_LUMINANCE have to be used,
71  * but since OpenGL 3.0 GL_LUMINANCE is deprecated.
72  * GL_RED produces RGBA = value, 0, 0, 1.
73  * GL_LUMINANCE produces RGBA = value, value, value, 1.
74  * Note: GL_INTENSITY may also be used which produce RGBA = value, value, value, value. */
75 #if defined(GL_RED)
76 #define FF_GL_RED_COMPONENT GL_RED
77 #elif defined(GL_LUMINANCE)
78 #define FF_GL_RED_COMPONENT GL_LUMINANCE
79 #else
80 #define FF_GL_RED_COMPONENT 0x1903; //GL_RED
81 #endif
82 
83 /* Constants not defined for iOS */
84 #define FF_GL_UNSIGNED_BYTE_3_3_2 0x8032
85 #define FF_GL_UNSIGNED_BYTE_2_3_3_REV 0x8362
86 #define FF_GL_UNSIGNED_SHORT_1_5_5_5_REV 0x8366
87 #define FF_GL_UNPACK_ROW_LENGTH 0x0CF2
88 
89 /* MinGW exposes only OpenGL 1.1 API */
90 #define FF_GL_ARRAY_BUFFER 0x8892
91 #define FF_GL_ELEMENT_ARRAY_BUFFER 0x8893
92 #define FF_GL_STATIC_DRAW 0x88E4
93 #define FF_GL_FRAGMENT_SHADER 0x8B30
94 #define FF_GL_VERTEX_SHADER 0x8B31
95 #define FF_GL_COMPILE_STATUS 0x8B81
96 #define FF_GL_LINK_STATUS 0x8B82
97 #define FF_GL_INFO_LOG_LENGTH 0x8B84
98 typedef void (APIENTRY *FF_PFNGLACTIVETEXTUREPROC) (GLenum texture);
99 typedef void (APIENTRY *FF_PFNGLGENBUFFERSPROC) (GLsizei n, GLuint *buffers);
100 typedef void (APIENTRY *FF_PFNGLDELETEBUFFERSPROC) (GLsizei n, const GLuint *buffers);
101 typedef void (APIENTRY *FF_PFNGLBUFFERDATAPROC) (GLenum target, ptrdiff_t size, const GLvoid *data, GLenum usage);
102 typedef void (APIENTRY *FF_PFNGLBINDBUFFERPROC) (GLenum target, GLuint buffer);
103 typedef GLint (APIENTRY *FF_PFNGLGETATTRIBLOCATIONPROC) (GLuint program, const char *name);
104 typedef void (APIENTRY *FF_PFNGLENABLEVERTEXATTRIBARRAYPROC) (GLuint index);
105 typedef void (APIENTRY *FF_PFNGLVERTEXATTRIBPOINTERPROC) (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, uintptr_t pointer);
106 typedef GLint (APIENTRY *FF_PFNGLGETUNIFORMLOCATIONPROC) (GLuint program, const char *name);
107 typedef void (APIENTRY *FF_PFNGLUNIFORM1FPROC) (GLint location, GLfloat v0);
108 typedef void (APIENTRY *FF_PFNGLUNIFORM1IPROC) (GLint location, GLint v0);
109 typedef void (APIENTRY *FF_PFNGLUNIFORMMATRIX4FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
110 typedef GLuint (APIENTRY *FF_PFNGLCREATEPROGRAMPROC) (void);
111 typedef void (APIENTRY *FF_PFNGLDELETEPROGRAMPROC) (GLuint program);
112 typedef void (APIENTRY *FF_PFNGLUSEPROGRAMPROC) (GLuint program);
113 typedef void (APIENTRY *FF_PFNGLLINKPROGRAMPROC) (GLuint program);
114 typedef void (APIENTRY *FF_PFNGLGETPROGRAMIVPROC) (GLuint program, GLenum pname, GLint *params);
115 typedef void (APIENTRY *FF_PFNGLGETPROGRAMINFOLOGPROC) (GLuint program, GLsizei bufSize, GLsizei *length, char *infoLog);
116 typedef void (APIENTRY *FF_PFNGLATTACHSHADERPROC) (GLuint program, GLuint shader);
117 typedef GLuint (APIENTRY *FF_PFNGLCREATESHADERPROC) (GLenum type);
118 typedef void (APIENTRY *FF_PFNGLDELETESHADERPROC) (GLuint shader);
119 typedef void (APIENTRY *FF_PFNGLCOMPILESHADERPROC) (GLuint shader);
120 typedef void (APIENTRY *FF_PFNGLSHADERSOURCEPROC) (GLuint shader, GLsizei count, const char* *string, const GLint *length);
121 typedef void (APIENTRY *FF_PFNGLGETSHADERIVPROC) (GLuint shader, GLenum pname, GLint *params);
122 typedef void (APIENTRY *FF_PFNGLGETSHADERINFOLOGPROC) (GLuint shader, GLsizei bufSize, GLsizei *length, char *infoLog);
123 
124 typedef struct FFOpenGLFunctions {
125  FF_PFNGLACTIVETEXTUREPROC glActiveTexture; //Require GL ARB multitexture
126  FF_PFNGLGENBUFFERSPROC glGenBuffers; //Require GL_ARB_vertex_buffer_object
127  FF_PFNGLDELETEBUFFERSPROC glDeleteBuffers; //Require GL_ARB_vertex_buffer_object
128  FF_PFNGLBUFFERDATAPROC glBufferData; //Require GL_ARB_vertex_buffer_object
129  FF_PFNGLBINDBUFFERPROC glBindBuffer; //Require GL_ARB_vertex_buffer_object
130  FF_PFNGLGETATTRIBLOCATIONPROC glGetAttribLocation; //Require GL_ARB_vertex_shader
131  FF_PFNGLENABLEVERTEXATTRIBARRAYPROC glEnableVertexAttribArray; //Require GL_ARB_vertex_shader
132  FF_PFNGLVERTEXATTRIBPOINTERPROC glVertexAttribPointer; //Require GL_ARB_vertex_shader
133  FF_PFNGLGETUNIFORMLOCATIONPROC glGetUniformLocation; //Require GL_ARB_shader_objects
134  FF_PFNGLUNIFORM1FPROC glUniform1f; //Require GL_ARB_shader_objects
135  FF_PFNGLUNIFORM1IPROC glUniform1i; //Require GL_ARB_shader_objects
136  FF_PFNGLUNIFORMMATRIX4FVPROC glUniformMatrix4fv; //Require GL_ARB_shader_objects
137  FF_PFNGLCREATEPROGRAMPROC glCreateProgram; //Require GL_ARB_shader_objects
138  FF_PFNGLDELETEPROGRAMPROC glDeleteProgram; //Require GL_ARB_shader_objects
139  FF_PFNGLUSEPROGRAMPROC glUseProgram; //Require GL_ARB_shader_objects
140  FF_PFNGLLINKPROGRAMPROC glLinkProgram; //Require GL_ARB_shader_objects
141  FF_PFNGLGETPROGRAMIVPROC glGetProgramiv; //Require GL_ARB_shader_objects
142  FF_PFNGLGETPROGRAMINFOLOGPROC glGetProgramInfoLog; //Require GL_ARB_shader_objects
143  FF_PFNGLATTACHSHADERPROC glAttachShader; //Require GL_ARB_shader_objects
144  FF_PFNGLCREATESHADERPROC glCreateShader; //Require GL_ARB_shader_objects
145  FF_PFNGLDELETESHADERPROC glDeleteShader; //Require GL_ARB_shader_objects
146  FF_PFNGLCOMPILESHADERPROC glCompileShader; //Require GL_ARB_shader_objects
147  FF_PFNGLSHADERSOURCEPROC glShaderSource; //Require GL_ARB_shader_objects
148  FF_PFNGLGETSHADERIVPROC glGetShaderiv; //Require GL_ARB_shader_objects
149  FF_PFNGLGETSHADERINFOLOGPROC glGetShaderInfoLog; //Require GL_ARB_shader_objects
151 
152 #define OPENGL_ERROR_CHECK(ctx) \
153 {\
154  GLenum err_code; \
155  if ((err_code = glGetError()) != GL_NO_ERROR) { \
156  av_log(ctx, AV_LOG_ERROR, "OpenGL error occurred in '%s', line %d: %d\n", __FUNCTION__, __LINE__, err_code); \
157  goto fail; \
158  } \
159 }\
160 
161 typedef struct OpenGLVertexInfo
162 {
163  float x, y, z; ///<Position
164  float s0, t0; ///<Texture coords
166 
167 /* defines 2 triangles to display */
168 static const GLushort g_index[6] =
169 {
170  0, 1, 2,
171  0, 3, 2,
172 };
173 
174 typedef struct OpenGLContext {
175  AVClass *class; ///< class for private options
176 
177 #if CONFIG_SDL2
178  SDL_Window *window;
179  SDL_GLContext glcontext;
180 #endif
182 
183  int inited; ///< Set to 1 when write_header was successfully called.
184  uint8_t background[4]; ///< Background color
185  int no_window; ///< 0 for create default window
186  char *window_title; ///< Title of the window
187 
188  /* OpenGL implementation limits */
189  GLint max_texture_size; ///< Maximum texture size
190  GLint max_viewport_width; ///< Maximum viewport size
191  GLint max_viewport_height; ///< Maximum viewport size
192  int non_pow_2_textures; ///< 1 when non power of 2 textures are supported
193  int unpack_subimage; ///< 1 when GL_EXT_unpack_subimage is available
194 
195  /* Current OpenGL configuration */
196  GLuint program; ///< Shader program
197  GLuint vertex_shader; ///< Vertex shader
198  GLuint fragment_shader; ///< Fragment shader for current pix_pmt
199  GLuint texture_name[4]; ///< Textures' IDs
200  GLuint index_buffer; ///< Index buffer
201  GLuint vertex_buffer; ///< Vertex buffer
202  OpenGLVertexInfo vertex[4]; ///< VBO
203  GLint projection_matrix_location; ///< Uniforms' locations
208  GLint texture_location[4];
209  GLint position_attrib; ///< Attibutes' locations
211 
212  GLfloat projection_matrix[16]; ///< Projection matrix
213  GLfloat model_view_matrix[16]; ///< Modev view matrix
214  GLfloat color_map[16]; ///< RGBA color map matrix
215  GLfloat chroma_div_w; ///< Chroma subsampling w ratio
216  GLfloat chroma_div_h; ///< Chroma subsampling h ratio
217 
218  /* Stream information */
219  GLenum format;
220  GLenum type;
221  int width; ///< Stream width
222  int height; ///< Stream height
223  enum AVPixelFormat pix_fmt; ///< Stream pixel format
224  int picture_width; ///< Rendered width
225  int picture_height; ///< Rendered height
228 } OpenGLContext;
229 
230 static const struct OpenGLFormatDesc {
231  enum AVPixelFormat fixel_format;
232  const char * const * fragment_shader;
233  GLenum format;
234  GLenum type;
235 } opengl_format_desc[] = {
251  { AV_PIX_FMT_RGB24, &FF_OPENGL_FRAGMENT_SHADER_RGB_PACKET, GL_RGB, GL_UNSIGNED_BYTE },
252  { AV_PIX_FMT_BGR24, &FF_OPENGL_FRAGMENT_SHADER_RGB_PACKET, GL_RGB, GL_UNSIGNED_BYTE },
253  { AV_PIX_FMT_0RGB, &FF_OPENGL_FRAGMENT_SHADER_RGB_PACKET, GL_RGBA, GL_UNSIGNED_BYTE },
254  { AV_PIX_FMT_RGB0, &FF_OPENGL_FRAGMENT_SHADER_RGB_PACKET, GL_RGBA, GL_UNSIGNED_BYTE },
255  { AV_PIX_FMT_0BGR, &FF_OPENGL_FRAGMENT_SHADER_RGB_PACKET, GL_RGBA, GL_UNSIGNED_BYTE },
256  { AV_PIX_FMT_BGR0, &FF_OPENGL_FRAGMENT_SHADER_RGB_PACKET, GL_RGBA, GL_UNSIGNED_BYTE },
257  { AV_PIX_FMT_RGB565, &FF_OPENGL_FRAGMENT_SHADER_RGB_PACKET, GL_RGB, GL_UNSIGNED_SHORT_5_6_5 },
258  { AV_PIX_FMT_BGR565, &FF_OPENGL_FRAGMENT_SHADER_RGB_PACKET, GL_RGB, GL_UNSIGNED_SHORT_5_6_5 },
260  { AV_PIX_FMT_BGR555, &FF_OPENGL_FRAGMENT_SHADER_RGB_PACKET, GL_RGBA, FF_GL_UNSIGNED_SHORT_1_5_5_5_REV },
263  { AV_PIX_FMT_RGB48, &FF_OPENGL_FRAGMENT_SHADER_RGB_PACKET, GL_RGB, GL_UNSIGNED_SHORT },
264  { AV_PIX_FMT_BGR48, &FF_OPENGL_FRAGMENT_SHADER_RGB_PACKET, GL_RGB, GL_UNSIGNED_SHORT },
265  { AV_PIX_FMT_ARGB, &FF_OPENGL_FRAGMENT_SHADER_RGBA_PACKET, GL_RGBA, GL_UNSIGNED_BYTE },
266  { AV_PIX_FMT_RGBA, &FF_OPENGL_FRAGMENT_SHADER_RGBA_PACKET, GL_RGBA, GL_UNSIGNED_BYTE },
267  { AV_PIX_FMT_ABGR, &FF_OPENGL_FRAGMENT_SHADER_RGBA_PACKET, GL_RGBA, GL_UNSIGNED_BYTE },
268  { AV_PIX_FMT_BGRA, &FF_OPENGL_FRAGMENT_SHADER_RGBA_PACKET, GL_RGBA, GL_UNSIGNED_BYTE },
269  { AV_PIX_FMT_RGBA64, &FF_OPENGL_FRAGMENT_SHADER_RGBA_PACKET, GL_RGBA, GL_UNSIGNED_SHORT },
270  { AV_PIX_FMT_BGRA64, &FF_OPENGL_FRAGMENT_SHADER_RGBA_PACKET, GL_RGBA, GL_UNSIGNED_SHORT },
277  { AV_PIX_FMT_NONE, NULL }
278 };
279 
281 static int opengl_draw(AVFormatContext *h, void *intput, int repaint, int is_pkt);
282 static av_cold int opengl_init_context(OpenGLContext *opengl);
283 
285 {
286  glDeleteTextures(4, opengl->texture_name);
287  opengl->texture_name[0] = opengl->texture_name[1] =
288  opengl->texture_name[2] = opengl->texture_name[3] = 0;
289  if (opengl->glprocs.glUseProgram)
290  opengl->glprocs.glUseProgram(0);
291  if (opengl->glprocs.glDeleteProgram) {
292  opengl->glprocs.glDeleteProgram(opengl->program);
293  opengl->program = 0;
294  }
295  if (opengl->glprocs.glDeleteShader) {
296  opengl->glprocs.glDeleteShader(opengl->vertex_shader);
297  opengl->glprocs.glDeleteShader(opengl->fragment_shader);
298  opengl->vertex_shader = opengl->fragment_shader = 0;
299  }
300  if (opengl->glprocs.glBindBuffer) {
303  }
304  if (opengl->glprocs.glDeleteBuffers) {
305  opengl->glprocs.glDeleteBuffers(2, &opengl->index_buffer);
306  opengl->vertex_buffer = opengl->index_buffer = 0;
307  }
308 }
309 
310 static int opengl_resize(AVFormatContext *h, int width, int height)
311 {
312  int ret = 0;
313  OpenGLContext *opengl = h->priv_data;
314  opengl->window_width = width;
315  opengl->window_height = height;
316  if (opengl->inited) {
317  if (opengl->no_window &&
319  av_log(opengl, AV_LOG_ERROR, "Application failed to prepare window buffer.\n");
320  goto end;
321  }
322  if ((ret = opengl_prepare_vertex(h)) < 0)
323  goto end;
324  ret = opengl_draw(h, NULL, 1, 0);
325  }
326  end:
327  return ret;
328 }
329 
330 static int opengl_control_message(AVFormatContext *h, int type, void *data, size_t data_size)
331 {
332  OpenGLContext *opengl = h->priv_data;
333  switch(type) {
335  if (data) {
337  return opengl_resize(h, message->width, message->height);
338  }
339  return AVERROR(EINVAL);
341  return opengl_resize(h, opengl->window_width, opengl->window_height);
342  }
343  return AVERROR(ENOSYS);
344 }
345 
346 #if CONFIG_SDL2
347 static int opengl_sdl_process_events(AVFormatContext *h)
348 {
349  OpenGLContext *opengl = h->priv_data;
351  SDL_Event event;
352  SDL_PumpEvents();
353  while (SDL_PeepEvents(&event, 1, SDL_GETEVENT, SDL_FIRSTEVENT, SDL_LASTEVENT) > 0) {
354  switch (event.type) {
355  case SDL_QUIT:
356  return AVERROR(EIO);
357  case SDL_KEYDOWN:
358  switch (event.key.keysym.sym) {
359  case SDLK_ESCAPE:
360  case SDLK_q:
361  return AVERROR(EIO);
362  }
363  return 0;
364  case SDL_WINDOWEVENT:
365  switch(event.window.event) {
366  case SDL_WINDOWEVENT_RESIZED:
367  case SDL_WINDOWEVENT_SIZE_CHANGED:
368  SDL_GL_GetDrawableSize(opengl->window, &message.width, &message.height);
369  return opengl_control_message(h, AV_APP_TO_DEV_WINDOW_SIZE, &message, sizeof(AVDeviceRect));
370  default:
371  break;
372  }
373  }
374  }
375  return 0;
376 }
377 
378 static int av_cold opengl_sdl_create_window(AVFormatContext *h)
379 {
380  OpenGLContext *opengl = h->priv_data;
382  if (SDL_Init(SDL_INIT_VIDEO)) {
383  av_log(opengl, AV_LOG_ERROR, "Unable to initialize SDL: %s\n", SDL_GetError());
384  return AVERROR_EXTERNAL;
385  }
386  opengl->window = SDL_CreateWindow(opengl->window_title,
387  SDL_WINDOWPOS_UNDEFINED,
388  SDL_WINDOWPOS_UNDEFINED,
389  opengl->window_width, opengl->window_height,
390  SDL_WINDOW_RESIZABLE | SDL_WINDOW_OPENGL);
391  if (!opengl->window) {
392  av_log(opengl, AV_LOG_ERROR, "Unable to create default window: %s\n", SDL_GetError());
393  return AVERROR_EXTERNAL;
394  }
395  opengl->glcontext = SDL_GL_CreateContext(opengl->window);
396  if (!opengl->glcontext) {
397  av_log(opengl, AV_LOG_ERROR, "Unable to create OpenGL context on default window: %s\n", SDL_GetError());
398  return AVERROR_EXTERNAL;
399  }
400  SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
401  SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
402  SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
403  SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8);
404  SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
405  av_log(opengl, AV_LOG_INFO, "SDL driver: '%s'.\n", SDL_GetCurrentVideoDriver());
406  SDL_GL_GetDrawableSize(opengl->window, &message.width, &message.height);
407  return opengl_control_message(h, AV_APP_TO_DEV_WINDOW_SIZE, &message, sizeof(AVDeviceRect));
408 }
409 
410 static int av_cold opengl_sdl_load_procedures(OpenGLContext *opengl)
411 {
412  FFOpenGLFunctions *procs = &opengl->glprocs;
413 
414 #define LOAD_OPENGL_FUN(name, type) \
415  procs->name = (type)SDL_GL_GetProcAddress(#name); \
416  if (!procs->name) { \
417  av_log(opengl, AV_LOG_ERROR, "Cannot load OpenGL function: '%s'\n", #name); \
418  return AVERROR(ENOSYS); \
419  }
420 
421  LOAD_OPENGL_FUN(glActiveTexture, FF_PFNGLACTIVETEXTUREPROC)
422  LOAD_OPENGL_FUN(glGenBuffers, FF_PFNGLGENBUFFERSPROC)
423  LOAD_OPENGL_FUN(glDeleteBuffers, FF_PFNGLDELETEBUFFERSPROC)
424  LOAD_OPENGL_FUN(glBufferData, FF_PFNGLBUFFERDATAPROC)
425  LOAD_OPENGL_FUN(glBindBuffer, FF_PFNGLBINDBUFFERPROC)
426  LOAD_OPENGL_FUN(glGetAttribLocation, FF_PFNGLGETATTRIBLOCATIONPROC)
427  LOAD_OPENGL_FUN(glGetUniformLocation, FF_PFNGLGETUNIFORMLOCATIONPROC)
428  LOAD_OPENGL_FUN(glUniform1f, FF_PFNGLUNIFORM1FPROC)
429  LOAD_OPENGL_FUN(glUniform1i, FF_PFNGLUNIFORM1IPROC)
430  LOAD_OPENGL_FUN(glUniformMatrix4fv, FF_PFNGLUNIFORMMATRIX4FVPROC)
431  LOAD_OPENGL_FUN(glCreateProgram, FF_PFNGLCREATEPROGRAMPROC)
432  LOAD_OPENGL_FUN(glDeleteProgram, FF_PFNGLDELETEPROGRAMPROC)
433  LOAD_OPENGL_FUN(glUseProgram, FF_PFNGLUSEPROGRAMPROC)
434  LOAD_OPENGL_FUN(glLinkProgram, FF_PFNGLLINKPROGRAMPROC)
435  LOAD_OPENGL_FUN(glGetProgramiv, FF_PFNGLGETPROGRAMIVPROC)
436  LOAD_OPENGL_FUN(glGetProgramInfoLog, FF_PFNGLGETPROGRAMINFOLOGPROC)
437  LOAD_OPENGL_FUN(glAttachShader, FF_PFNGLATTACHSHADERPROC)
438  LOAD_OPENGL_FUN(glCreateShader, FF_PFNGLCREATESHADERPROC)
439  LOAD_OPENGL_FUN(glDeleteShader, FF_PFNGLDELETESHADERPROC)
440  LOAD_OPENGL_FUN(glCompileShader, FF_PFNGLCOMPILESHADERPROC)
441  LOAD_OPENGL_FUN(glShaderSource, FF_PFNGLSHADERSOURCEPROC)
442  LOAD_OPENGL_FUN(glGetShaderiv, FF_PFNGLGETSHADERIVPROC)
443  LOAD_OPENGL_FUN(glGetShaderInfoLog, FF_PFNGLGETSHADERINFOLOGPROC)
444  LOAD_OPENGL_FUN(glEnableVertexAttribArray, FF_PFNGLENABLEVERTEXATTRIBARRAYPROC)
445  LOAD_OPENGL_FUN(glVertexAttribPointer, FF_PFNGLVERTEXATTRIBPOINTERPROC)
446 
447  return 0;
448 
449 #undef LOAD_OPENGL_FUN
450 }
451 #endif /* CONFIG_SDL2 */
452 
453 #if defined(__APPLE__)
454 static int av_cold opengl_load_procedures(OpenGLContext *opengl)
455 {
456  FFOpenGLFunctions *procs = &opengl->glprocs;
457 
458 #if CONFIG_SDL2
459  if (!opengl->no_window)
460  return opengl_sdl_load_procedures(opengl);
461 #endif
462 
464  procs->glGenBuffers = glGenBuffers;
466  procs->glBufferData = glBufferData;
467  procs->glBindBuffer = glBindBuffer;
470  procs->glUniform1f = glUniform1f;
471  procs->glUniform1i = glUniform1i;
475  procs->glUseProgram = glUseProgram;
476  procs->glLinkProgram = glLinkProgram;
484  procs->glGetShaderiv = glGetShaderiv;
487  procs->glVertexAttribPointer = (FF_PFNGLVERTEXATTRIBPOINTERPROC) glVertexAttribPointer;
488  return 0;
489 }
490 #else
492 {
493  FFOpenGLFunctions *procs = &opengl->glprocs;
494 
495 #if HAVE_GLXGETPROCADDRESS
496 #define SelectedGetProcAddress glXGetProcAddress
497 #elif HAVE_WGLGETPROCADDRESS
498 #define SelectedGetProcAddress wglGetProcAddress
499 #endif
500 
501 #define LOAD_OPENGL_FUN(name, type) \
502  procs->name = (type)SelectedGetProcAddress(#name); \
503  if (!procs->name) { \
504  av_log(opengl, AV_LOG_ERROR, "Cannot load OpenGL function: '%s'\n", #name); \
505  return AVERROR(ENOSYS); \
506  }
507 
508 #if CONFIG_SDL2
509  if (!opengl->no_window)
510  return opengl_sdl_load_procedures(opengl);
511 #endif
512 
513  LOAD_OPENGL_FUN(glActiveTexture, FF_PFNGLACTIVETEXTUREPROC)
514  LOAD_OPENGL_FUN(glGenBuffers, FF_PFNGLGENBUFFERSPROC)
515  LOAD_OPENGL_FUN(glDeleteBuffers, FF_PFNGLDELETEBUFFERSPROC)
516  LOAD_OPENGL_FUN(glBufferData, FF_PFNGLBUFFERDATAPROC)
517  LOAD_OPENGL_FUN(glBindBuffer, FF_PFNGLBINDBUFFERPROC)
518  LOAD_OPENGL_FUN(glGetAttribLocation, FF_PFNGLGETATTRIBLOCATIONPROC)
519  LOAD_OPENGL_FUN(glGetUniformLocation, FF_PFNGLGETUNIFORMLOCATIONPROC)
520  LOAD_OPENGL_FUN(glUniform1f, FF_PFNGLUNIFORM1FPROC)
521  LOAD_OPENGL_FUN(glUniform1i, FF_PFNGLUNIFORM1IPROC)
522  LOAD_OPENGL_FUN(glUniformMatrix4fv, FF_PFNGLUNIFORMMATRIX4FVPROC)
523  LOAD_OPENGL_FUN(glCreateProgram, FF_PFNGLCREATEPROGRAMPROC)
524  LOAD_OPENGL_FUN(glDeleteProgram, FF_PFNGLDELETEPROGRAMPROC)
525  LOAD_OPENGL_FUN(glUseProgram, FF_PFNGLUSEPROGRAMPROC)
526  LOAD_OPENGL_FUN(glLinkProgram, FF_PFNGLLINKPROGRAMPROC)
527  LOAD_OPENGL_FUN(glGetProgramiv, FF_PFNGLGETPROGRAMIVPROC)
528  LOAD_OPENGL_FUN(glGetProgramInfoLog, FF_PFNGLGETPROGRAMINFOLOGPROC)
529  LOAD_OPENGL_FUN(glAttachShader, FF_PFNGLATTACHSHADERPROC)
530  LOAD_OPENGL_FUN(glCreateShader, FF_PFNGLCREATESHADERPROC)
531  LOAD_OPENGL_FUN(glDeleteShader, FF_PFNGLDELETESHADERPROC)
532  LOAD_OPENGL_FUN(glCompileShader, FF_PFNGLCOMPILESHADERPROC)
533  LOAD_OPENGL_FUN(glShaderSource, FF_PFNGLSHADERSOURCEPROC)
534  LOAD_OPENGL_FUN(glGetShaderiv, FF_PFNGLGETSHADERIVPROC)
535  LOAD_OPENGL_FUN(glGetShaderInfoLog, FF_PFNGLGETSHADERINFOLOGPROC)
536  LOAD_OPENGL_FUN(glEnableVertexAttribArray, FF_PFNGLENABLEVERTEXATTRIBARRAYPROC)
537  LOAD_OPENGL_FUN(glVertexAttribPointer, FF_PFNGLVERTEXATTRIBPOINTERPROC)
538 
539  return 0;
540 
541 #undef SelectedGetProcAddress
542 #undef LOAD_OPENGL_FUN
543 }
544 #endif
545 
546 static void opengl_make_identity(float matrix[16])
547 {
548  memset(matrix, 0, 16 * sizeof(float));
549  matrix[0] = matrix[5] = matrix[10] = matrix[15] = 1.0f;
550 }
551 
552 static void opengl_make_ortho(float matrix[16], float left, float right,
553  float bottom, float top, float nearZ, float farZ)
554 {
555  float ral = right + left;
556  float rsl = right - left;
557  float tab = top + bottom;
558  float tsb = top - bottom;
559  float fan = farZ + nearZ;
560  float fsn = farZ - nearZ;
561 
562  memset(matrix, 0, 16 * sizeof(float));
563  matrix[0] = 2.0f / rsl;
564  matrix[5] = 2.0f / tsb;
565  matrix[10] = -2.0f / fsn;
566  matrix[12] = -ral / rsl;
567  matrix[13] = -tab / tsb;
568  matrix[14] = -fan / fsn;
569  matrix[15] = 1.0f;
570 }
571 
573 {
574  static const struct{
575  const char *extension;
576  int major;
577  int minor;
578  } required_extensions[] = {
579  { "GL_ARB_multitexture", 1, 3 },
580  { "GL_ARB_vertex_buffer_object", 1, 5 }, //GLX_ARB_vertex_buffer_object
581  { "GL_ARB_vertex_shader", 2, 0 },
582  { "GL_ARB_fragment_shader", 2, 0 },
583  { "GL_ARB_shader_objects", 2, 0 },
584  { NULL, 0, 0 }
585  };
586  int i, major, minor;
587  const char *extensions, *version;
588 
589  version = glGetString(GL_VERSION);
590  extensions = glGetString(GL_EXTENSIONS);
591 
592  av_log(opengl, AV_LOG_DEBUG, "OpenGL version: %s\n", version);
593  sscanf(version, "%d.%d", &major, &minor);
594 
595  for (i = 0; required_extensions[i].extension; i++) {
596  if (major < required_extensions[i].major &&
597  (major == required_extensions[i].major && minor < required_extensions[i].minor) &&
598  !strstr(extensions, required_extensions[i].extension)) {
599  av_log(opengl, AV_LOG_ERROR, "Required extension %s is not supported.\n",
600  required_extensions[i].extension);
601  av_log(opengl, AV_LOG_DEBUG, "Supported extensions are: %s\n", extensions);
602  return AVERROR(ENOSYS);
603  }
604  }
605  glGetIntegerv(GL_MAX_TEXTURE_SIZE, &opengl->max_texture_size);
606  glGetIntegerv(GL_MAX_VIEWPORT_DIMS, &opengl->max_viewport_width);
607  opengl->non_pow_2_textures = major >= 2 || strstr(extensions, "GL_ARB_texture_non_power_of_two");
608 #if defined(GL_ES_VERSION_2_0)
609  opengl->unpack_subimage = !!strstr(extensions, "GL_EXT_unpack_subimage");
610 #else
611  opengl->unpack_subimage = 1;
612 #endif
613 
614  av_log(opengl, AV_LOG_DEBUG, "Non Power of 2 textures support: %s\n", opengl->non_pow_2_textures ? "Yes" : "No");
615  av_log(opengl, AV_LOG_DEBUG, "Unpack Subimage extension support: %s\n", opengl->unpack_subimage ? "Yes" : "No");
616  av_log(opengl, AV_LOG_DEBUG, "Max texture size: %dx%d\n", opengl->max_texture_size, opengl->max_texture_size);
617  av_log(opengl, AV_LOG_DEBUG, "Max viewport size: %dx%d\n",
618  opengl->max_viewport_width, opengl->max_viewport_height);
619 
620  OPENGL_ERROR_CHECK(opengl);
621  return 0;
622  fail:
623  return AVERROR_EXTERNAL;
624 }
625 
627 {
628  int i;
629  for (i = 0; i < FF_ARRAY_ELEMS(opengl_format_desc); i++) {
630  if (opengl_format_desc[i].fixel_format == format)
632  }
633  return NULL;
634 }
635 
636 static int opengl_type_size(GLenum type)
637 {
638  switch(type) {
639  case GL_UNSIGNED_SHORT:
641  case GL_UNSIGNED_SHORT_5_6_5:
642  return 2;
643  case GL_UNSIGNED_BYTE:
646  default:
647  break;
648  }
649  return 1;
650 }
651 
653 {
654  int i;
655  for (i = 0; i < FF_ARRAY_ELEMS(opengl_format_desc); i++) {
656  if (opengl_format_desc[i].fixel_format == opengl->pix_fmt) {
657  opengl->format = opengl_format_desc[i].format;
658  opengl->type = opengl_format_desc[i].type;
659  break;
660  }
661  }
662 }
663 
665 {
666  AVRational sar, dar; /* sample and display aspect ratios */
667  OpenGLContext *opengl = s->priv_data;
668  AVStream *st = s->streams[0];
669  AVCodecParameters *par = st->codecpar;
670 
671  /* compute overlay width and height from the codec context information */
672  sar = st->sample_aspect_ratio.num ? st->sample_aspect_ratio : (AVRational){ 1, 1 };
673  dar = av_mul_q(sar, (AVRational){ par->width, par->height });
674 
675  /* we suppose the screen has a 1/1 sample aspect ratio */
676  /* fit in the window */
677  if (av_cmp_q(dar, (AVRational){ opengl->window_width, opengl->window_height }) > 0) {
678  /* fit in width */
679  opengl->picture_width = opengl->window_width;
680  opengl->picture_height = av_rescale(opengl->picture_width, dar.den, dar.num);
681  } else {
682  /* fit in height */
683  opengl->picture_height = opengl->window_height;
684  opengl->picture_width = av_rescale(opengl->picture_height, dar.num, dar.den);
685  }
686 }
687 
688 static av_cold void opengl_get_texture_size(OpenGLContext *opengl, int in_width, int in_height,
689  int *out_width, int *out_height)
690 {
691  if (opengl->non_pow_2_textures) {
692  *out_width = in_width;
693  *out_height = in_height;
694  } else {
695  int max = FFMIN(FFMAX(in_width, in_height), opengl->max_texture_size);
696  unsigned power_of_2 = 1;
697  while (power_of_2 < max)
698  power_of_2 *= 2;
699  *out_height = power_of_2;
700  *out_width = power_of_2;
701  av_log(opengl, AV_LOG_DEBUG, "Texture size calculated from %dx%d into %dx%d\n",
702  in_width, in_height, *out_width, *out_height);
703  }
704 }
705 
707 {
708  const AVPixFmtDescriptor *desc;
709  int shift;
710  enum AVPixelFormat pix_fmt = opengl->pix_fmt;
711 
712  /* We need order of components, not exact position, some minor HACKs here */
713  if (pix_fmt == AV_PIX_FMT_RGB565 || pix_fmt == AV_PIX_FMT_BGR555 ||
714  pix_fmt == AV_PIX_FMT_BGR8 || pix_fmt == AV_PIX_FMT_RGB8)
715  pix_fmt = AV_PIX_FMT_RGB24;
716  else if (pix_fmt == AV_PIX_FMT_BGR565 || pix_fmt == AV_PIX_FMT_RGB555)
717  pix_fmt = AV_PIX_FMT_BGR24;
718 
719  desc = av_pix_fmt_desc_get(pix_fmt);
720  if (!(desc->flags & AV_PIX_FMT_FLAG_RGB))
721  return;
722 
723 #define FILL_COMPONENT(i) { \
724  shift = (desc->comp[i].depth - 1) >> 3; \
725  opengl->color_map[(i << 2) + (desc->comp[i].offset >> shift)] = 1.0; \
726  }
727 
728  memset(opengl->color_map, 0, sizeof(opengl->color_map));
729  FILL_COMPONENT(0);
730  FILL_COMPONENT(1);
731  FILL_COMPONENT(2);
732  if (desc->flags & AV_PIX_FMT_FLAG_ALPHA)
733  FILL_COMPONENT(3);
734 
735 #undef FILL_COMPONENT
736 }
737 
738 static av_cold GLuint opengl_load_shader(OpenGLContext *opengl, GLenum type, const char *source)
739 {
740  GLuint shader = opengl->glprocs.glCreateShader(type);
741  GLint result;
742  if (!shader) {
743  av_log(opengl, AV_LOG_ERROR, "glCreateShader() failed\n");
744  return 0;
745  }
746  opengl->glprocs.glShaderSource(shader, 1, &source, NULL);
747  opengl->glprocs.glCompileShader(shader);
748 
749  opengl->glprocs.glGetShaderiv(shader, FF_GL_COMPILE_STATUS, &result);
750  if (!result) {
751  char *log;
752  opengl->glprocs.glGetShaderiv(shader, FF_GL_INFO_LOG_LENGTH, &result);
753  if (result) {
754  if ((log = av_malloc(result))) {
755  opengl->glprocs.glGetShaderInfoLog(shader, result, NULL, log);
756  av_log(opengl, AV_LOG_ERROR, "Compile error: %s\n", log);
757  av_free(log);
758  }
759  }
760  goto fail;
761  }
762  OPENGL_ERROR_CHECK(opengl);
763  return shader;
764  fail:
765  opengl->glprocs.glDeleteShader(shader);
766  return 0;
767 }
768 
770 {
771  GLint result;
772  const char *fragment_shader_code = opengl_get_fragment_shader_code(pix_fmt);
773 
774  if (!fragment_shader_code) {
775  av_log(opengl, AV_LOG_ERROR, "Provided pixel format '%s' is not supported\n",
776  av_get_pix_fmt_name(pix_fmt));
777  return AVERROR(EINVAL);
778  }
779 
782  if (!opengl->vertex_shader) {
783  av_log(opengl, AV_LOG_ERROR, "Vertex shader loading failed.\n");
784  goto fail;
785  }
787  fragment_shader_code);
788  if (!opengl->fragment_shader) {
789  av_log(opengl, AV_LOG_ERROR, "Fragment shader loading failed.\n");
790  goto fail;
791  }
792 
793  opengl->program = opengl->glprocs.glCreateProgram();
794  if (!opengl->program)
795  goto fail;
796 
797  opengl->glprocs.glAttachShader(opengl->program, opengl->vertex_shader);
798  opengl->glprocs.glAttachShader(opengl->program, opengl->fragment_shader);
799  opengl->glprocs.glLinkProgram(opengl->program);
800 
801  opengl->glprocs.glGetProgramiv(opengl->program, FF_GL_LINK_STATUS, &result);
802  if (!result) {
803  char *log;
804  opengl->glprocs.glGetProgramiv(opengl->program, FF_GL_INFO_LOG_LENGTH, &result);
805  if (result) {
806  log = av_malloc(result);
807  if (!log)
808  goto fail;
809  opengl->glprocs.glGetProgramInfoLog(opengl->program, result, NULL, log);
810  av_log(opengl, AV_LOG_ERROR, "Link error: %s\n", log);
811  av_free(log);
812  }
813  goto fail;
814  }
815 
816  opengl->position_attrib = opengl->glprocs.glGetAttribLocation(opengl->program, "a_position");
817  opengl->texture_coords_attrib = opengl->glprocs.glGetAttribLocation(opengl->program, "a_textureCoords");
818  opengl->projection_matrix_location = opengl->glprocs.glGetUniformLocation(opengl->program, "u_projectionMatrix");
819  opengl->model_view_matrix_location = opengl->glprocs.glGetUniformLocation(opengl->program, "u_modelViewMatrix");
820  opengl->color_map_location = opengl->glprocs.glGetUniformLocation(opengl->program, "u_colorMap");
821  opengl->texture_location[0] = opengl->glprocs.glGetUniformLocation(opengl->program, "u_texture0");
822  opengl->texture_location[1] = opengl->glprocs.glGetUniformLocation(opengl->program, "u_texture1");
823  opengl->texture_location[2] = opengl->glprocs.glGetUniformLocation(opengl->program, "u_texture2");
824  opengl->texture_location[3] = opengl->glprocs.glGetUniformLocation(opengl->program, "u_texture3");
825  opengl->chroma_div_w_location = opengl->glprocs.glGetUniformLocation(opengl->program, "u_chroma_div_w");
826  opengl->chroma_div_h_location = opengl->glprocs.glGetUniformLocation(opengl->program, "u_chroma_div_h");
827 
828  OPENGL_ERROR_CHECK(opengl);
829  return 0;
830  fail:
831  opengl->glprocs.glDeleteShader(opengl->vertex_shader);
832  opengl->glprocs.glDeleteShader(opengl->fragment_shader);
833  opengl->glprocs.glDeleteProgram(opengl->program);
834  opengl->fragment_shader = opengl->vertex_shader = opengl->program = 0;
835  return AVERROR_EXTERNAL;
836 }
837 
839  GLsizei width, GLsizei height)
840 {
841  if (texture) {
842  int new_width, new_height;
843  opengl_get_texture_size(opengl, width, height, &new_width, &new_height);
844  glBindTexture(GL_TEXTURE_2D, texture);
845  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
846  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
847  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
848  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
849  glTexImage2D(GL_TEXTURE_2D, 0, opengl->format, new_width, new_height, 0,
850  opengl->format, opengl->type, NULL);
852  }
853  return 0;
854  fail:
855  return AVERROR_EXTERNAL;
856 }
857 
859 {
860  OpenGLContext *opengl = s->priv_data;
861  int tex_w, tex_h;
862 
863  if (opengl->window_width > opengl->max_viewport_width || opengl->window_height > opengl->max_viewport_height) {
864  opengl->window_width = FFMIN(opengl->window_width, opengl->max_viewport_width);
865  opengl->window_height = FFMIN(opengl->window_height, opengl->max_viewport_height);
866  av_log(opengl, AV_LOG_WARNING, "Too big viewport requested, limited to %dx%d", opengl->window_width, opengl->window_height);
867  }
868  glViewport(0, 0, opengl->window_width, opengl->window_height);
870  - (float)opengl->window_width / 2.0f, (float)opengl->window_width / 2.0f,
871  - (float)opengl->window_height / 2.0f, (float)opengl->window_height / 2.0f,
872  1.0f, -1.0f);
874 
876 
877  opengl->vertex[0].z = opengl->vertex[1].z = opengl->vertex[2].z = opengl->vertex[3].z = 0.0f;
878  opengl->vertex[0].x = opengl->vertex[1].x = - (float)opengl->picture_width / 2.0f;
879  opengl->vertex[2].x = opengl->vertex[3].x = (float)opengl->picture_width / 2.0f;
880  opengl->vertex[1].y = opengl->vertex[2].y = - (float)opengl->picture_height / 2.0f;
881  opengl->vertex[0].y = opengl->vertex[3].y = (float)opengl->picture_height / 2.0f;
882 
883  opengl_get_texture_size(opengl, opengl->width, opengl->height, &tex_w, &tex_h);
884 
885  opengl->vertex[0].s0 = 0.0f;
886  opengl->vertex[0].t0 = 0.0f;
887  opengl->vertex[1].s0 = 0.0f;
888  opengl->vertex[1].t0 = (float)opengl->height / (float)tex_h;
889  opengl->vertex[2].s0 = (float)opengl->width / (float)tex_w;
890  opengl->vertex[2].t0 = (float)opengl->height / (float)tex_h;
891  opengl->vertex[3].s0 = (float)opengl->width / (float)tex_w;
892  opengl->vertex[3].t0 = 0.0f;
893 
895  opengl->glprocs.glBufferData(FF_GL_ARRAY_BUFFER, sizeof(opengl->vertex), opengl->vertex, FF_GL_STATIC_DRAW);
897  OPENGL_ERROR_CHECK(opengl);
898  return 0;
899  fail:
900  return AVERROR_EXTERNAL;
901 }
902 
903 static int opengl_prepare(OpenGLContext *opengl)
904 {
905  int i;
906  opengl->glprocs.glUseProgram(opengl->program);
907  opengl->glprocs.glUniformMatrix4fv(opengl->projection_matrix_location, 1, GL_FALSE, opengl->projection_matrix);
908  opengl->glprocs.glUniformMatrix4fv(opengl->model_view_matrix_location, 1, GL_FALSE, opengl->model_view_matrix);
909  for (i = 0; i < 4; i++)
910  if (opengl->texture_location[i] != -1) {
911  opengl->glprocs.glActiveTexture(GL_TEXTURE0 + i);
912  glBindTexture(GL_TEXTURE_2D, opengl->texture_name[i]);
913  opengl->glprocs.glUniform1i(opengl->texture_location[i], i);
914  }
915  if (opengl->color_map_location != -1)
916  opengl->glprocs.glUniformMatrix4fv(opengl->color_map_location, 1, GL_FALSE, opengl->color_map);
917  if (opengl->chroma_div_h_location != -1)
918  opengl->glprocs.glUniform1f(opengl->chroma_div_h_location, opengl->chroma_div_h);
919  if (opengl->chroma_div_w_location != -1)
920  opengl->glprocs.glUniform1f(opengl->chroma_div_w_location, opengl->chroma_div_w);
921 
922  OPENGL_ERROR_CHECK(opengl);
923  return 0;
924  fail:
925  return AVERROR_EXTERNAL;
926 }
927 
929 {
930  OpenGLContext *opengl = h->priv_data;
931  int ret;
932 
933  if (!opengl->no_window) {
934 #if CONFIG_SDL2
935  if ((ret = opengl_sdl_create_window(h)) < 0) {
936  av_log(opengl, AV_LOG_ERROR, "Cannot create default SDL window.\n");
937  return ret;
938  }
939 #else
940  av_log(opengl, AV_LOG_ERROR, "FFmpeg is compiled without SDL. Cannot create default window.\n");
941  return AVERROR(ENOSYS);
942 #endif
943  } else {
945  message.x = message.y = 0;
946  message.width = opengl->window_width;
947  message.height = opengl->window_height;
949  &message , sizeof(message))) < 0) {
950  av_log(opengl, AV_LOG_ERROR, "Application failed to create window buffer.\n");
951  return ret;
952  }
954  av_log(opengl, AV_LOG_ERROR, "Application failed to prepare window buffer.\n");
955  return ret;
956  }
957  }
958  return 0;
959 }
960 
962 {
963  int ret;
964  OpenGLContext *opengl = h->priv_data;
965  if (!opengl->no_window) {
966 #if CONFIG_SDL2
967  SDL_GL_DeleteContext(opengl->glcontext);
968  SDL_DestroyWindow(opengl->window);
969  SDL_Quit();
970 #endif
972  av_log(opengl, AV_LOG_ERROR, "Application failed to release window buffer.\n");
973  return ret;
974  }
975  return 0;
976 }
977 
979 {
980  OpenGLContext *opengl = h->priv_data;
981 
982  if (opengl->no_window &&
984  av_log(opengl, AV_LOG_ERROR, "Application failed to prepare window buffer.\n");
985 
986  opengl_deinit_context(opengl);
988 
989  return 0;
990 }
991 
993 {
994  int i, ret;
995  const AVPixFmtDescriptor *desc;
996 
997  if ((ret = opengl_compile_shaders(opengl, opengl->pix_fmt)) < 0)
998  goto fail;
999 
1000  desc = av_pix_fmt_desc_get(opengl->pix_fmt);
1001  av_assert0(desc->nb_components > 0 && desc->nb_components <= 4);
1002  glGenTextures(desc->nb_components, opengl->texture_name);
1003 
1004  opengl->glprocs.glGenBuffers(2, &opengl->index_buffer);
1005  if (!opengl->index_buffer || !opengl->vertex_buffer) {
1006  av_log(opengl, AV_LOG_ERROR, "Buffer generation failed.\n");
1007  ret = AVERROR_EXTERNAL;
1008  goto fail;
1009  }
1010 
1011  opengl_configure_texture(opengl, opengl->texture_name[0], opengl->width, opengl->height);
1012  if (desc->nb_components > 1) {
1013  int has_alpha = desc->flags & AV_PIX_FMT_FLAG_ALPHA;
1014  int num_planes = desc->nb_components - (has_alpha ? 1 : 0);
1015  if (opengl->non_pow_2_textures) {
1016  opengl->chroma_div_w = 1.0f;
1017  opengl->chroma_div_h = 1.0f;
1018  } else {
1019  opengl->chroma_div_w = 1 << desc->log2_chroma_w;
1020  opengl->chroma_div_h = 1 << desc->log2_chroma_h;
1021  }
1022  for (i = 1; i < num_planes; i++)
1023  if (opengl->non_pow_2_textures)
1024  opengl_configure_texture(opengl, opengl->texture_name[i],
1025  AV_CEIL_RSHIFT(opengl->width, desc->log2_chroma_w),
1026  AV_CEIL_RSHIFT(opengl->height, desc->log2_chroma_h));
1027  else
1028  opengl_configure_texture(opengl, opengl->texture_name[i], opengl->width, opengl->height);
1029  if (has_alpha)
1030  opengl_configure_texture(opengl, opengl->texture_name[3], opengl->width, opengl->height);
1031  }
1032 
1036 
1037  glEnable(GL_BLEND);
1038  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1039 
1040  glClearColor((float)opengl->background[0] / 255.0f, (float)opengl->background[1] / 255.0f,
1041  (float)opengl->background[2] / 255.0f, 1.0f);
1042 
1043  ret = AVERROR_EXTERNAL;
1044  OPENGL_ERROR_CHECK(opengl);
1045 
1046  return 0;
1047  fail:
1048  return ret;
1049 }
1050 
1052 {
1053  OpenGLContext *opengl = h->priv_data;
1054  AVStream *st;
1055  int ret;
1056 
1057  if (h->nb_streams != 1 ||
1060  av_log(opengl, AV_LOG_ERROR, "Only a single video stream is supported.\n");
1061  return AVERROR(EINVAL);
1062  }
1063  st = h->streams[0];
1064  opengl->width = st->codecpar->width;
1065  opengl->height = st->codecpar->height;
1066  opengl->pix_fmt = st->codecpar->format;
1067  if (!opengl->window_width)
1068  opengl->window_width = opengl->width;
1069  if (!opengl->window_height)
1070  opengl->window_height = opengl->height;
1071 
1072  if (!opengl->window_title && !opengl->no_window)
1073  opengl->window_title = av_strdup(h->url);
1074 
1075  if ((ret = opengl_create_window(h)))
1076  goto fail;
1077 
1078  if ((ret = opengl_read_limits(opengl)) < 0)
1079  goto fail;
1080 
1081  if (opengl->width > opengl->max_texture_size || opengl->height > opengl->max_texture_size) {
1082  av_log(opengl, AV_LOG_ERROR, "Too big picture %dx%d, max supported size is %dx%d\n",
1083  opengl->width, opengl->height, opengl->max_texture_size, opengl->max_texture_size);
1084  ret = AVERROR(EINVAL);
1085  goto fail;
1086  }
1087 
1088  if ((ret = opengl_load_procedures(opengl)) < 0)
1089  goto fail;
1090 
1091  opengl_fill_color_map(opengl);
1092  opengl_get_texture_params(opengl);
1093 
1094  if ((ret = opengl_init_context(opengl)) < 0)
1095  goto fail;
1096 
1097  if ((ret = opengl_prepare_vertex(h)) < 0)
1098  goto fail;
1099 
1100  glClear(GL_COLOR_BUFFER_BIT);
1101 
1102 #if CONFIG_SDL2
1103  if (!opengl->no_window)
1104  SDL_GL_SwapWindow(opengl->window);
1105 #endif
1106  if (opengl->no_window &&
1108  av_log(opengl, AV_LOG_ERROR, "Application failed to display window buffer.\n");
1109  goto fail;
1110  }
1111 
1112  ret = AVERROR_EXTERNAL;
1113  OPENGL_ERROR_CHECK(opengl);
1114 
1115  opengl->inited = 1;
1116  return 0;
1117 
1118  fail:
1120  return ret;
1121 }
1122 
1123 static uint8_t* opengl_get_plane_pointer(OpenGLContext *opengl, AVPacket *pkt, int comp_index,
1124  const AVPixFmtDescriptor *desc)
1125 {
1126  uint8_t *data = pkt->data;
1127  int wordsize = opengl_type_size(opengl->type);
1128  int width_chroma = AV_CEIL_RSHIFT(opengl->width, desc->log2_chroma_w);
1129  int height_chroma = AV_CEIL_RSHIFT(opengl->height, desc->log2_chroma_h);
1130  int plane = desc->comp[comp_index].plane;
1131 
1132  switch(plane) {
1133  case 0:
1134  break;
1135  case 1:
1136  data += opengl->width * opengl->height * wordsize;
1137  break;
1138  case 2:
1139  data += opengl->width * opengl->height * wordsize;
1140  data += width_chroma * height_chroma * wordsize;
1141  break;
1142  case 3:
1143  data += opengl->width * opengl->height * wordsize;
1144  data += 2 * width_chroma * height_chroma * wordsize;
1145  break;
1146  default:
1147  return NULL;
1148  }
1149  return data;
1150 }
1151 
1152 #define LOAD_TEXTURE_DATA(comp_index, sub) \
1153 { \
1154  int width = sub ? AV_CEIL_RSHIFT(opengl->width, desc->log2_chroma_w) : opengl->width; \
1155  int height = sub ? AV_CEIL_RSHIFT(opengl->height, desc->log2_chroma_h): opengl->height; \
1156  uint8_t *data; \
1157  int plane = desc->comp[comp_index].plane; \
1158  \
1159  glBindTexture(GL_TEXTURE_2D, opengl->texture_name[comp_index]); \
1160  if (!is_pkt) { \
1161  GLint length = ((AVFrame *)input)->linesize[plane]; \
1162  int bytes_per_pixel = opengl_type_size(opengl->type); \
1163  if (!(desc->flags & AV_PIX_FMT_FLAG_PLANAR)) \
1164  bytes_per_pixel *= desc->nb_components; \
1165  data = ((AVFrame *)input)->data[plane]; \
1166  if (!(length % bytes_per_pixel) && \
1167  (opengl->unpack_subimage || ((length / bytes_per_pixel) == width))) { \
1168  length /= bytes_per_pixel; \
1169  if (length != width) \
1170  glPixelStorei(FF_GL_UNPACK_ROW_LENGTH, length); \
1171  glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, \
1172  opengl->format, opengl->type, data); \
1173  if (length != width) \
1174  glPixelStorei(FF_GL_UNPACK_ROW_LENGTH, 0); \
1175  } else { \
1176  int h; \
1177  for (h = 0; h < height; h++) { \
1178  glTexSubImage2D(GL_TEXTURE_2D, 0, 0, h, width, 1, \
1179  opengl->format, opengl->type, data); \
1180  data += length; \
1181  } \
1182  } \
1183  } else { \
1184  data = opengl_get_plane_pointer(opengl, input, comp_index, desc); \
1185  glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, \
1186  opengl->format, opengl->type, data); \
1187  } \
1188 }
1189 
1190 static int opengl_draw(AVFormatContext *h, void *input, int repaint, int is_pkt)
1191 {
1192  OpenGLContext *opengl = h->priv_data;
1193  enum AVPixelFormat pix_fmt = h->streams[0]->codecpar->format;
1194  const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pix_fmt);
1195  int ret;
1196 
1197 #if CONFIG_SDL2
1198  if (!opengl->no_window && (ret = opengl_sdl_process_events(h)) < 0)
1199  goto fail;
1200 #endif
1201  if (opengl->no_window &&
1203  av_log(opengl, AV_LOG_ERROR, "Application failed to prepare window buffer.\n");
1204  goto fail;
1205  }
1206 
1207  glClear(GL_COLOR_BUFFER_BIT);
1208 
1209  if (!repaint) {
1210  if (is_pkt)
1211  glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
1212  LOAD_TEXTURE_DATA(0, 0)
1213  if (desc->flags & AV_PIX_FMT_FLAG_PLANAR) {
1214  LOAD_TEXTURE_DATA(1, 1)
1215  LOAD_TEXTURE_DATA(2, 1)
1216  if (desc->flags & AV_PIX_FMT_FLAG_ALPHA)
1217  LOAD_TEXTURE_DATA(3, 0)
1218  }
1219  }
1220  ret = AVERROR_EXTERNAL;
1221  OPENGL_ERROR_CHECK(opengl);
1222 
1223  if ((ret = opengl_prepare(opengl)) < 0)
1224  goto fail;
1225 
1228  opengl->glprocs.glVertexAttribPointer(opengl->position_attrib, 3, GL_FLOAT, GL_FALSE, sizeof(OpenGLVertexInfo), 0);
1230  opengl->glprocs.glVertexAttribPointer(opengl->texture_coords_attrib, 2, GL_FLOAT, GL_FALSE, sizeof(OpenGLVertexInfo), 12);
1232 
1233  glDrawElements(GL_TRIANGLES, FF_ARRAY_ELEMS(g_index), GL_UNSIGNED_SHORT, 0);
1234 
1235  ret = AVERROR_EXTERNAL;
1236  OPENGL_ERROR_CHECK(opengl);
1237 
1238 #if CONFIG_SDL2
1239  if (!opengl->no_window)
1240  SDL_GL_SwapWindow(opengl->window);
1241 #endif
1242  if (opengl->no_window &&
1244  av_log(opengl, AV_LOG_ERROR, "Application failed to display window buffer.\n");
1245  goto fail;
1246  }
1247 
1248  return 0;
1249  fail:
1250  return ret;
1251 }
1252 
1254 {
1255  return opengl_draw(h, pkt, 0, 1);
1256 }
1257 
1258 static int opengl_write_frame(AVFormatContext *h, int stream_index,
1259  AVFrame **frame, unsigned flags)
1260 {
1261  if ((flags & AV_WRITE_UNCODED_FRAME_QUERY))
1262  return 0;
1263  return opengl_draw(h, *frame, 0, 0);
1264 }
1265 
1266 #define OFFSET(x) offsetof(OpenGLContext, x)
1267 #define ENC AV_OPT_FLAG_ENCODING_PARAM
1268 static const AVOption options[] = {
1269  { "background", "set background color", OFFSET(background), AV_OPT_TYPE_COLOR, {.str = "black"}, CHAR_MIN, CHAR_MAX, ENC },
1270  { "no_window", "disable default window", OFFSET(no_window), AV_OPT_TYPE_INT, {.i64 = 0}, INT_MIN, INT_MAX, ENC },
1271  { "window_title", "set window title", OFFSET(window_title), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, ENC },
1272  { "window_size", "set window size", OFFSET(window_width), AV_OPT_TYPE_IMAGE_SIZE, {.str = NULL}, 0, 0, ENC },
1273  { NULL }
1274 };
1275 
1276 static const AVClass opengl_class = {
1277  .class_name = "opengl outdev",
1278  .item_name = av_default_item_name,
1279  .option = options,
1280  .version = LIBAVUTIL_VERSION_INT,
1282 };
1283 
1285  .name = "opengl",
1286  .long_name = NULL_IF_CONFIG_SMALL("OpenGL output"),
1287  .priv_data_size = sizeof(OpenGLContext),
1288  .audio_codec = AV_CODEC_ID_NONE,
1289  .video_codec = AV_CODEC_ID_RAWVIDEO,
1292  .write_uncoded_frame = opengl_write_frame,
1294  .control_message = opengl_control_message,
1296  .priv_class = &opengl_class,
1297 };
int plane
Definition: avisynth_c.h:422
GLint max_texture_size
Maximum texture size.
Definition: opengl_enc.c:189
Window size change message.
Definition: avdevice.h:134
GLfloat model_view_matrix[16]
Modev view matrix.
Definition: opengl_enc.c:213
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:101
#define AV_PIX_FMT_YUVA422P16
Definition: pixfmt.h:427
static const GLushort g_index[6]
Definition: opengl_enc.c:168
static const char *const FF_OPENGL_FRAGMENT_SHADER_RGBA_PLANAR
Fragment shader for planar RGBA formats.
#define ENC
Definition: opengl_enc.c:1267
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:93
FF_PFNGLDELETESHADERPROC glDeleteShader
Definition: opengl_enc.c:145
static int opengl_prepare(OpenGLContext *opengl)
Definition: opengl_enc.c:903
Prepare window buffer message.
Definition: avdevice.h:229
const AVPixFmtDescriptor * av_pix_fmt_desc_get(enum AVPixelFormat pix_fmt)
Definition: pixdesc.c:2498
float z
Position.
Definition: opengl_enc.c:163
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:216
int x
x coordinate of top left corner
Definition: avdevice.h:110
int picture_width
Rendered width.
Definition: opengl_enc.c:224
AVOption.
Definition: opt.h:246
ptrdiff_t const GLvoid * data
Definition: opengl_enc.c:101
const char *const * fragment_shader
Definition: opengl_enc.c:232
FF_PFNGLDELETEPROGRAMPROC glDeleteProgram
Definition: opengl_enc.c:138
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:636
#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:96
#define AV_PIX_FMT_RGBA64
Definition: pixfmt.h:374
GLint model_view_matrix_location
Definition: opengl_enc.c:204
#define APIENTRY
Definition: opengl_enc.c:65
int inited
Set to 1 when write_header was successfully called.
Definition: opengl_enc.c:183
int no_window
0 for create default window
Definition: opengl_enc.c:185
enum AVCodecID codec_id
Specific type of the encoded data (the codec used).
Definition: avcodec.h:3944
planar GBR 4:4:4 24bpp
Definition: pixfmt.h:168
AVRational sample_aspect_ratio
sample aspect ratio (0 if unknown)
Definition: avformat.h:945
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:379
#define OPENGL_ERROR_CHECK(ctx)
Definition: opengl_enc.c:152
AVS_VideoFrame int int int int new_height
Definition: avisynth_c.h:818
GLint GLenum type
Definition: opengl_enc.c:105
static av_cold int opengl_write_trailer(AVFormatContext *h)
Definition: opengl_enc.c:978
static const char *const FF_OPENGL_VERTEX_SHADER
int version
Definition: avisynth_c.h:766
packed BGR 8:8:8, 32bpp, XBGRXBGR... X=unused/undefined
Definition: pixfmt.h:239
GLfloat v0
Definition: opengl_enc.c:107
static AVPacket pkt
FF_PFNGLATTACHSHADERPROC glAttachShader
Definition: opengl_enc.c:143
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:208
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:664
This struct describes the properties of an encoded stream.
Definition: avcodec.h:3936
FF_PFNGLUSEPROGRAMPROC glUseProgram
Definition: opengl_enc.c:139
Display window buffer message.
Definition: avdevice.h:240
static av_cold int opengl_init_context(OpenGLContext *opengl)
Definition: opengl_enc.c:992
Format I/O context.
Definition: avformat.h:1360
Create window buffer message.
Definition: avdevice.h:218
GLsizei const char ** string
Definition: opengl_enc.c:120
FF_PFNGLCOMPILESHADERPROC glCompileShader
Definition: opengl_enc.c:146
GLint GLenum GLboolean normalized
Definition: opengl_enc.c:105
static int opengl_write_packet(AVFormatContext *h, AVPacket *pkt)
Definition: opengl_enc.c:1253
FF_PFNGLSHADERSOURCEPROC glShaderSource
Definition: opengl_enc.c:147
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:222
#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:706
#define FF_GL_ELEMENT_ARRAY_BUFFER
Definition: opengl_enc.c:91
FF_PFNGLUNIFORM1FPROC glUniform1f
Definition: opengl_enc.c:134
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:84
int width
Video only.
Definition: avcodec.h:4010
FF_PFNGLGETUNIFORMLOCATIONPROC glGetUniformLocation
Definition: opengl_enc.c:133
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:209
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:148
FF_PFNGLBINDBUFFERPROC glBindBuffer
Definition: opengl_enc.c:129
GLsizei GLboolean const GLfloat * value
Definition: opengl_enc.c:109
static int opengl_resize(AVFormatContext *h, int width, int height)
Definition: opengl_enc.c:310
AVStream ** streams
A list of all streams in the file.
Definition: avformat.h:1428
packed ABGR 8:8:8:8, 32bpp, ABGRABGR...
Definition: pixfmt.h:94
GLint GLenum GLboolean GLsizei uintptr_t pointer
Definition: opengl_enc.c:105
#define height
uint8_t * data
Definition: avcodec.h:1468
FF_PFNGLENABLEVERTEXATTRIBARRAYPROC glEnableVertexAttribArray
Definition: opengl_enc.c:131
#define AV_PIX_FMT_BGR48
Definition: pixfmt.h:375
GLfloat chroma_div_w
Chroma subsampling w ratio.
Definition: opengl_enc.c:215
#define AV_PIX_FMT_YUV444P16
Definition: pixfmt.h:397
static int opengl_draw(AVFormatContext *h, void *intput, int repaint, int is_pkt)
Definition: opengl_enc.c:1190
static int opengl_control_message(AVFormatContext *h, int type, void *data, size_t data_size)
Definition: opengl_enc.c:330
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:101
GLuint vertex_buffer
Vertex buffer.
Definition: opengl_enc.c:201
#define AV_PIX_FMT_YUVA420P16
Definition: pixfmt.h:426
#define av_log(a,...)
GLuint fragment_shader
Fragment shader for current pix_pmt.
Definition: opengl_enc.c:198
GLuint texture_name[4]
Textures&#39; IDs.
Definition: opengl_enc.c:199
FF_PFNGLLINKPROGRAMPROC glLinkProgram
Definition: opengl_enc.c:140
GLint texture_coords_attrib
Definition: opengl_enc.c:210
Main libavdevice API header.
FFOpenGLFunctions glprocs
Definition: opengl_enc.c:181
#define FF_GL_VERTEX_SHADER
Definition: opengl_enc.c:94
planar YUV 4:2:2 24bpp, (1 Cr & Cb sample per 2x1 Y & A samples)
Definition: pixfmt.h:176
#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:127
#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:1284
#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:1456
#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:428
enum AVMediaType codec_type
General type of the encoded data.
Definition: avcodec.h:3940
GLenum GLint * params
Definition: opengl_enc.c:114
#define AV_PIX_FMT_RGB48
Definition: pixfmt.h:370
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:115
int non_pow_2_textures
1 when non power of 2 textures are supported
Definition: opengl_enc.c:192
GLsizei count
Definition: opengl_enc.c:109
#define FFMAX(a, b)
Definition: common.h:94
GLint chroma_div_w_location
Definition: opengl_enc.c:206
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:118
#define AV_PIX_FMT_GBRAP16
Definition: pixfmt.h:406
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:1416
uint8_t background[4]
Background color.
Definition: opengl_enc.c:184
static const char *const FF_OPENGL_FRAGMENT_SHADER_RGBA_PACKET
Fragment shader for packet RGBA formats.
static SDL_Window * window
Definition: ffplay.c:366
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:403
#define AV_PIX_FMT_GRAY16
Definition: pixfmt.h:368
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:1051
#define width
static av_cold void opengl_deinit_context(OpenGLContext *opengl)
Definition: opengl_enc.c:284
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:626
enum AVPixelFormat pix_fmt
Stream pixel format.
Definition: opengl_enc.c:223
const char * name
Definition: avformat.h:507
FF_PFNGLCREATEPROGRAMPROC glCreateProgram
Definition: opengl_enc.c:137
static const AVOption options[]
Definition: opengl_enc.c:1268
#define FF_GL_RED_COMPONENT
Definition: opengl_enc.c:80
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:684
static av_cold GLuint opengl_load_shader(OpenGLContext *opengl, GLenum type, const char *source)
Definition: opengl_enc.c:738
packed RGB 8:8:8, 24bpp, BGRBGR...
Definition: pixfmt.h:69
float t0
Texture coords.
Definition: opengl_enc.c:164
OpenGLVertexInfo vertex[4]
VBO.
Definition: opengl_enc.c:202
typedef GLint(APIENTRY *FF_PFNGLGETATTRIBLOCATIONPROC)(GLuint program
FF_PFNGLBUFFERDATAPROC glBufferData
Definition: opengl_enc.c:128
#define FF_ARRAY_ELEMS(a)
Destroy window buffer message.
Definition: avdevice.h:251
#define FF_GL_STATIC_DRAW
Definition: opengl_enc.c:92
#define FILL_COMPONENT(i)
Stream structure.
Definition: avformat.h:883
#define AVFMT_NOTIMESTAMPS
Format does not need / have any timestamps.
Definition: avformat.h:469
#define AV_PIX_FMT_YUV420P16
Definition: pixfmt.h:395
#define AV_PIX_FMT_BGR555
Definition: pixfmt.h:377
GLint chroma_div_h_location
Definition: opengl_enc.c:207
static int opengl_release_window(AVFormatContext *h)
Definition: opengl_enc.c:961
packed RGB 3:3:2, 8bpp, (msb)2B 3G 3R(lsb)
Definition: pixfmt.h:83
GLuint shader
Definition: opengl_enc.c:116
#define AV_LOG_INFO
Standard information.
Definition: log.h:187
FF_PFNGLGETPROGRAMINFOLOGPROC glGetProgramInfoLog
Definition: opengl_enc.c:142
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:212
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:114
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:136
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:688
static av_cold void opengl_get_texture_params(OpenGLContext *opengl)
Definition: opengl_enc.c:652
static const char *const FF_OPENGL_FRAGMENT_SHADER_GRAY
static int opengl_create_window(AVFormatContext *h)
Definition: opengl_enc.c:928
#define FF_GL_INFO_LOG_LENGTH
Definition: opengl_enc.c:97
static av_cold int opengl_read_limits(OpenGLContext *opengl)
Definition: opengl_enc.c:572
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:115
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:552
int index
Definition: gxfenc.c:89
Rational number (pair of numerator and denominator).
Definition: rational.h:58
FF_PFNGLGENBUFFERSPROC glGenBuffers
Definition: opengl_enc.c:126
FF_PFNGLGETSHADERINFOLOGPROC glGetShaderInfoLog
Definition: opengl_enc.c:149
#define FF_GL_ARRAY_BUFFER
Definition: opengl_enc.c:90
static av_cold int opengl_prepare_vertex(AVFormatContext *s)
Definition: opengl_enc.c:858
packed BGR 8:8:8, 32bpp, BGRXBGRX... X=unused/undefined
Definition: pixfmt.h:240
GLsizei GLsizei char * infoLog
Definition: opengl_enc.c:115
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:109
GLuint vertex_shader
Vertex shader.
Definition: opengl_enc.c:197
FF_PFNGLUNIFORM1IPROC glUniform1i
Definition: opengl_enc.c:135
static int av_cold opengl_load_procedures(OpenGLContext *opengl)
Definition: opengl_enc.c:491
offset must point to two consecutive integers
Definition: opt.h:233
GLint color_map_location
Definition: opengl_enc.c:205
#define FF_GL_UNSIGNED_BYTE_2_3_3_REV
Definition: opengl_enc.c:85
int picture_height
Rendered height.
Definition: opengl_enc.c:225
#define AV_PIX_FMT_BGR565
Definition: pixfmt.h:376
FF_PFNGLGETPROGRAMIVPROC glGetProgramiv
Definition: opengl_enc.c:141
#define flags(name, subs,...)
Definition: cbs_av1.c:606
int width
width
Definition: avdevice.h:112
GLuint program
Shader program.
Definition: opengl_enc.c:196
char * window_title
Title of the window.
Definition: opengl_enc.c:186
#define FF_GL_UNSIGNED_SHORT_1_5_5_5_REV
Definition: opengl_enc.c:86
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:193
Main libavformat public API header.
static int opengl_write_frame(AVFormatContext *h, int stream_index, AVFrame **frame, unsigned flags)
Definition: opengl_enc.c:1258
GLint GLenum GLboolean GLsizei stride
Definition: opengl_enc.c:105
FF_PFNGLVERTEXATTRIBPOINTERPROC glVertexAttribPointer
Definition: opengl_enc.c:132
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:769
FF_PFNGLACTIVETEXTUREPROC glActiveTexture
Definition: opengl_enc.c:125
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:465
GLuint * buffers
Definition: opengl_enc.c:99
planar GBRA 4:4:4:4 32bpp
Definition: pixfmt.h:215
GLint max_viewport_height
Maximum viewport size.
Definition: opengl_enc.c:191
FF_PFNGLCREATESHADERPROC glCreateShader
Definition: opengl_enc.c:144
GLint max_viewport_width
Maximum viewport size.
Definition: opengl_enc.c:190
packed RGB 3:3:2, 8bpp, (msb)2R 3G 3B(lsb)
Definition: pixfmt.h:86
#define AV_PIX_FMT_RGB555
Definition: pixfmt.h:372
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:95
GLfloat color_map[16]
RGBA color map matrix.
Definition: opengl_enc.c:214
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:1276
#define AVFMT_VARIABLE_FPS
Format allows variable fps.
Definition: avformat.h:472
#define av_free(p)
void * priv_data
Format private data.
Definition: avformat.h:1388
GLuint index_buffer
Index buffer.
Definition: opengl_enc.c:200
#define OFFSET(x)
Definition: opengl_enc.c:1266
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:1123
static const char *const FF_OPENGL_FRAGMENT_SHADER_RGB_PACKET
Fragment shader for packet RGB formats.
GLenum format
Definition: opengl_enc.c:219
static const struct twinvq_data tab
#define LOAD_TEXTURE_DATA(comp_index, sub)
Definition: opengl_enc.c:1152
#define AV_PIX_FMT_RGB565
Definition: pixfmt.h:371
static av_cold int opengl_configure_texture(OpenGLContext *opengl, GLuint texture, GLsizei width, GLsizei height)
Definition: opengl_enc.c:838
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:130
AVCodecParameters * codecpar
Codec parameters associated with this stream.
Definition: avformat.h:1030
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:2414
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:221
static void opengl_make_identity(float matrix[16])
Definition: opengl_enc.c:546
#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:1445
#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:396
GLuint buffer
Definition: opengl_enc.c:102
#define AV_CEIL_RSHIFT(a, b)
Definition: common.h:58
const char * name
Definition: opengl_enc.c:103
GLint projection_matrix_location
Uniforms&#39; locations.
Definition: opengl_enc.c:203