1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224
|
/*
* This file is part of bino, a 3D video player.
*
* Copyright (C) 2010, 2011, 2012, 2015, 2016
* Martin Lambers <marlam@marlam.de>
* Frédéric Devernay <Frederic.Devernay@inrialpes.fr>
* Joe <cuchac@email.cz>
* Binocle <http://binocle.com> (author: Olivier Letz <oletz@binocle.com>)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef VIDEO_OUTPUT_H
#define VIDEO_OUTPUT_H
#include <vector>
#include <string>
#include <GL/glew.h>
#include "base/blb.h"
#include "media_data.h"
#include "subtitle_renderer.h"
#include "dispatch.h"
class subtitle_updater;
#if HAVE_LIBXNVCTRL
class CNvSDIout;
#endif // HAVE_LIBXNVCTRL
class video_output : public controller
{
private:
bool _initialized;
/* We manage two frames, each with its own set of properties etc.
* The active frame is the one that is displayed, the other frame is the one
* that is prepared for display.
* Each frame contains a left view and may contain a right view. */
int _active_index; // 0 or 1
video_frame _frame[2]; // input frames (active / preparing)
// Step 1: input of video data
video_frame _input_last_frame; // last frame for this step
GLuint _input_pbo; // pixel-buffer object for texture uploading
GLuint _input_fbo; // frame-buffer object for texture clearing
GLuint _input_yuv_y_tex[2]; // for yuv formats: y component
GLuint _input_yuv_u_tex[2]; // for yuv formats: u component
GLuint _input_yuv_v_tex[2]; // for yuv formats: v component
GLuint _input_bgra32_tex[2]; // for bgra32 format
int _input_yuv_chroma_width_divisor; // for yuv formats: chroma subsampling
int _input_yuv_chroma_height_divisor; // for yuv formats: chroma subsampling
subtitle_box _subtitle[2]; // the current subtitle box
GLuint _subtitle_tex[2]; // subtitle texture
bool _subtitle_tex_current[2]; // whether the subtitle tex contains the current subtitle buffer
// Step 2: color space conversion and color correction
parameters _color_last_params[2]; // last params for this step; used for reinitialization check
video_frame _color_last_frame[2]; // last frame for this step; used for reinitialization check
GLuint _color_prg[2]; // color space transformation, color adjustment
GLuint _color_fbo; // framebuffer object to render into the sRGB texture
GLuint _color_tex[2][2]; // output: SRGB8 or linear RGB16 texture
// Step 3: rendering
parameters _render_params; // current parameters for display
parameters _render_last_params; // last params for this step; used for reinitialization check
video_frame _render_last_frame; // last frame for this step; used for reinitialization check
GLuint _render_prg; // reads sRGB texture, renders according to _params[_active_index]
GLuint _render_dummy_tex; // an empty subtitle texture
GLuint _render_mask_tex; // for the masking modes even-odd-{rows,columns}, checkerboard
blob _3d_ready_sync_buf; // for 3-D Ready Sync pixels
// OpenGL viewports and tex coordinates for drawing the two views of the video frame
GLint _full_viewport[4];
GLint _viewport[2][4];
float _tex_coords[2][4][2];
subtitle_updater *_subtitle_updater; // the subtitle updater thread
#if HAVE_LIBXNVCTRL
CNvSDIout *_nv_sdi_output; // access the nvidia quadro sdi output card
int64_t _last_nv_sdi_displayed_frameno;
#endif // HAVE_LIBXNVCTRL
// GL Helper functions
bool xglCheckError(const std::string& where = std::string()) const;
bool xglCheckFBO(const std::string& where = std::string()) const;
GLuint xglCompileShader(const std::string& name, GLenum type, const std::string& src) const;
GLuint xglCreateProgram(GLuint vshader, GLuint fshader) const;
GLuint xglCreateProgram(const std::string& name,
const std::string& vshader_src, const std::string& fshader_src) const;
void xglLinkProgram(const std::string& name, const GLuint prg) const;
void xglDeleteProgram(GLuint prg) const;
bool srgb8_textures_are_color_renderable();
void draw_quad(float x, float y, float w, float h,
const float tex_coords[2][4][2] = NULL,
const float more_tex_coords[4][2] = NULL) const;
// Step 1: initialize/deinitialize, and check if reinitialization is necessary
void input_init(const video_frame &frame);
void input_deinit();
bool input_is_compatible(const video_frame ¤t_frame);
void subtitle_init(int index);
void subtitle_deinit(int index);
// Step 2: initialize/deinitialize, and check if reinitialization is necessary
void color_init(int index, const parameters& params, const video_frame &frame);
void color_deinit(int index);
bool color_is_compatible(int index, const parameters& params, const video_frame ¤t_frame);
// Step 3: initialize/deinitialize, and check if reinitialization is necessary
void render_init();
void render_deinit();
bool render_needs_subtitle(const parameters& params);
bool render_needs_coloradjust(const parameters& params);
bool render_needs_ghostbust(const parameters& params);
bool render_is_compatible();
protected:
subtitle_renderer _subtitle_renderer;
#ifdef GLEW_MX
virtual GLEWContext* glewGetContext() const = 0;
#endif
// Get the total viewport size.
int full_display_width() const;
int full_display_height() const;
// Get size of the viewport area that is used for video. This is overridable for Equalizer.
virtual int video_display_width() const;
virtual int video_display_height() const;
virtual bool context_is_stereo() const = 0; // Is our current OpenGL context a stereo context?
virtual void recreate_context(bool stereo) = 0; // Recreate an OpenGL context and make it current
virtual void trigger_resize(int w, int h) = 0; // Trigger a resize the video area
void clear() const; // Clear the video area
void reshape(int w, int h, const parameters& params = dispatch::parameters()); // Call this when the video area was resized
/* Get screen properties (fixed) */
virtual int screen_width() const = 0; // in pixels
virtual int screen_height() const = 0; // in pixels
virtual float screen_pixel_aspect_ratio() const = 0;// the aspect ratio of a pixel on screen
/* Get current video area properties */
virtual int width() const = 0; // in pixels
virtual int height() const = 0; // in pixels
virtual int pos_x() const = 0; // in pixels
virtual int pos_y() const = 0; // in pixels
/* Display the current frame.
* The first version is used by Equalizer, which needs to set some special properties.
* The second version is used by NVIDIA SDI output.
* The third version is for everyone else.
* TODO: This function needs to handle interlaced frames! */
void display_current_frame(int64_t display_frameno, bool keep_viewport, bool mono_right_instead_of_left,
float x, float y, float w, float h,
const GLint viewport[2][4], const float tex_coords[2][4][2],
int dst_width, int dst_height,
parameters::stereo_mode_t stereo_mode);
void display_current_frame(int64_t display_frameno, int dst_width, int dst_height, parameters::stereo_mode_t stereo_mode)
{
display_current_frame(display_frameno, false, false, -1.0f, -1.0f, 2.0f, 2.0f,
_viewport, _tex_coords, dst_width, dst_height, stereo_mode);
}
void display_current_frame(int64_t display_frameno = 0)
{
display_current_frame(display_frameno, false, false, -1.0f, -1.0f, 2.0f, 2.0f,
_viewport, _tex_coords, full_display_width(), full_display_height(),
dispatch::parameters().stereo_mode());
}
#if HAVE_LIBXNVCTRL
void sdi_output(int64_t display_frameno = 0);
#endif // HAVE_LIBXNVCTRL
public:
/* Constructor, Destructor */
video_output();
virtual ~video_output();
/* Initialize the video output, or throw an exception */
virtual void init();
/* Wait for subtitle renderer initialization to finish. Has to be called
* if the video has subtitles. Returns the number of microseconds that the
* waiting took. */
virtual int64_t wait_for_subtitle_renderer() = 0;
/* Deinitialize the video output */
virtual void deinit();
/* Set a video area size suitable for the given input/output settings */
void set_suitable_size(int w, int h, float ar, parameters::stereo_mode_t stereo_mode);
/* Get capabilities */
virtual bool supports_stereo() const = 0; // Is OpenGL quad buffered stereo available?
/* Center video area on screen */
virtual void center() = 0;
/* Enter/exit fullscreen mode */
virtual void enter_fullscreen() = 0;
virtual void exit_fullscreen() = 0;
/* Process window system events (if applicable) */
virtual void process_events() = 0;
/* Prepare a new frame for display. */
virtual void prepare_next_frame(const video_frame &frame, const subtitle_box &subtitle);
/* Switch to the next frame (make it the current one) */
virtual void activate_next_frame();
/* Get an estimation of when the next frame will appear on screen */
virtual int64_t time_to_next_frame_presentation() const;
};
#endif
|