File: video_output.h

package info (click to toggle)
bino 1.6.6-3
  • links: PTS, VCS
  • area: main
  • in suites: bullseye, buster, sid
  • size: 4,636 kB
  • sloc: cpp: 21,288; sh: 4,849; makefile: 314; sed: 16
file content (224 lines) | stat: -rw-r--r-- 10,275 bytes parent folder | download
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 &current_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 &current_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