UltraGrid
UltraGrid Low-Latency High-Resolution Transmission System
Loading...
Searching...
No Matches
gl_vdpau.cpp
Go to the documentation of this file.
1#ifdef HAVE_CONFIG_H
2#include "config.h"
3#endif // defined HAVE_CONFIG_H
4#include "config_unix.h"
5#include "config_win32.h"
6
7#include <cassert>
8#include "debug.h"
9
10#include "gl_vdpau.hpp"
11
15static void check_mixer(struct state_vdpau *vdp, hw_vdpau_frame *frame){
16 uint32_t frame_w;
17 uint32_t frame_h;
18 VdpChromaType ct;
19
20 VdpStatus st = vdp->funcs.videoSurfaceGetParameters(frame->surface,
21 &ct,
22 &frame_w,
23 &frame_h);
24
25 if(st != VDP_STATUS_OK){
26 log_msg(LOG_LEVEL_ERROR, "Failed to get surface parameters: %s\n", vdp->funcs.getErrorString(st));
27 }
28
29 if(vdp->surf_width != frame_w ||
30 vdp->surf_height != frame_h ||
31 vdp->surf_ct != ct ||
32 !vdp->mixerInitialized)
33 {
34 vdp->initMixer(frame_w, frame_h, ct);
35 }
36}
37
38void state_vdpau::loadFrame(hw_vdpau_frame *frame){
39 assert(initialized);
40
41 glBindTexture(GL_TEXTURE_2D, 0);
42
43 int state = 0;
44 int len = 0;
45 if(vdpgl_surf){
46 glVDPAUGetSurfaceivNV(vdpgl_surf,
47 GL_SURFACE_STATE_NV,
48 1,
49 &len,
50 &state
51 );
52 }
53
54 if(state == GL_SURFACE_MAPPED_NV)
55 glVDPAUUnmapSurfacesNV(1, &vdpgl_surf);
56
57 checkInterop(frame->hwctx.device, frame->hwctx.get_proc_address);
58 check_mixer(this, frame);
59
60 mixerRender(frame->surface);
61
62 glVDPAUMapSurfacesNV(1, &vdpgl_surf);
63
64 glBindTexture(GL_TEXTURE_2D, textures[0]);
65
66 hw_vdpau_frame_unref(&lastFrame);
67 lastFrame = hw_vdpau_frame_copy(frame);
68}
69
73void state_vdpau::uninitMixer(){
74 VdpStatus st;
75
76 if (mixer != VDP_INVALID_HANDLE){
77 st = funcs.videoMixerDestroy(mixer);
78 mixer = VDP_INVALID_HANDLE;
79 if(st != VDP_STATUS_OK){
80 log_msg(LOG_LEVEL_ERROR, "Failed to destroy VdpVideoMixer: %s\n", funcs.getErrorString(st));
81 }
82 }
83
84 if (out_surf != VDP_INVALID_HANDLE){
85 st = funcs.outputSurfaceDestroy(out_surf);
86 if(st != VDP_STATUS_OK){
87 log_msg(LOG_LEVEL_ERROR, "Failed to destroy VdpOutputSurface: %s\n", funcs.getErrorString(st));
88 }
89 out_surf = VDP_INVALID_HANDLE;
90 surf_width = 0;
91 surf_height = 0;
92 surf_ct = 0;
93 }
94
95 glVDPAUUnregisterSurfaceNV(vdpgl_surf);
96 mixerInitialized = false;
97}
98
102void state_vdpau::initMixer(uint32_t w, uint32_t h, VdpChromaType ct){
103 uninitMixer();
104
105 surf_ct = ct;
106 surf_width = w;
107 surf_height = h;
108
109 VdpStatus st;
110
111 VdpRGBAFormat rgbaFormat = VDP_RGBA_FORMAT_B8G8R8A8;
112
113 st = funcs.outputSurfaceCreate(device,
114 rgbaFormat,
115 surf_width,
116 surf_height,
117 &out_surf);
118
119 if(st != VDP_STATUS_OK){
120 log_msg(LOG_LEVEL_ERROR, "Failed to create VdpOutputSurface: %s\n", funcs.getErrorString(st));
121 }
122
123 VdpVideoMixerParameter params[] = {
124 VDP_VIDEO_MIXER_PARAMETER_CHROMA_TYPE,
125 VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_WIDTH,
126 VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_HEIGHT
127 };
128
129 void *param_vals[] = {
130 &surf_ct,
131 &surf_width,
132 &surf_height
133 };
134
135 st = funcs.videoMixerCreate(device,
136 0,
137 NULL,
138 3,
139 params,
140 param_vals,
141 &mixer);
142
143 if(st != VDP_STATUS_OK){
144 log_msg(LOG_LEVEL_ERROR, "Failed to create VdpVideoMixer: %s\n", funcs.getErrorString(st));
145 }
146
147 vdpgl_surf = glVDPAURegisterOutputSurfaceNV(NV_CAST(out_surf),
148 GL_TEXTURE_2D,
149 1,
150 textures);
151
152 glVDPAUSurfaceAccessNV(vdpgl_surf, GL_WRITE_DISCARD_NV);
153
154 mixerInitialized = true;
155}
156
160void state_vdpau::mixerRender(VdpVideoSurface f){
161 VdpStatus st = funcs.videoMixerRender(mixer,
162 VDP_INVALID_HANDLE,
163 NULL,
164 VDP_VIDEO_MIXER_PICTURE_STRUCTURE_FRAME,
165 0,
166 NULL,
167 f,
168 0,
169 NULL,
170 NULL,
171 out_surf,
172 NULL,
173 NULL,
174 0,
175 NULL);
176
177 if(st != VDP_STATUS_OK){
178 log_msg(LOG_LEVEL_ERROR, "Failed to render: %s\n", funcs.getErrorString(st));
179 }
180}
181
186void state_vdpau::checkInterop(VdpDevice device, VdpGetProcAddress *get_proc_address){
187 if(this->device != device || this->get_proc_address != get_proc_address){
188 uninitInterop();
189 initInterop(device, get_proc_address);
190 }
191}
192
196void state_vdpau::initInterop(VdpDevice device, VdpGetProcAddress *get_proc_address){
197 if(interopInitialized)
198 uninitInterop();
199
200 glVDPAUInitNV(NV_CAST(device), (void *) get_proc_address);
201 this->device = device;
202 this->get_proc_address = get_proc_address;
203
204 vdp_funcs_load(&funcs, device, get_proc_address);
205 interopInitialized = true;
206}
207
211void state_vdpau::uninitInterop(){
212 if(!interopInitialized)
213 return;
214
215 glVDPAUFiniNV();
216 device = 0;
217 get_proc_address = nullptr;
218 interopInitialized = false;
219 mixerInitialized = false;
220
221 //VDPAUFiniNV() unmaps and unregisters all surfaces automatically
222 vdpgl_surf = 0;
223}
224
228bool state_vdpau::init(){
229 initialized = true;
230 glGenTextures(4, textures);
231 hw_vdpau_frame_init(&lastFrame);
232
233 return true;
234}
235
239void state_vdpau::uninit(){
240 uninitMixer();
241 uninitInterop();
242 hw_vdpau_frame_unref(&lastFrame);
243 glDeleteTextures(4, textures);
244 for(int i = 0; i < 4; i++){
245 textures[i] = 0;
246 }
247}
void ** state
struct video_frame * frame
int void size_t * len
void log_msg(int level, const char *format,...)
Definition debug.cpp:130
#define LOG_LEVEL_ERROR
general errors
Definition debug.h:59
static void check_mixer(struct state_vdpau *vdp, hw_vdpau_frame *frame)
Checks VdpMixer parameters and reinitializes it if they don't match the video parameters.
Definition gl_vdpau.cpp:15
void hw_vdpau_frame_unref(hw_vdpau_frame *frame)
hw_vdpau_frame hw_vdpau_frame_copy(const hw_vdpau_frame *frame)
void vdp_funcs_load(vdp_funcs *f, VdpDevice device, VdpGetProcAddress *get_proc_address)
void hw_vdpau_frame_init(hw_vdpau_frame *frame)