2 Copyright 2012 Marten Richter
\r
4 This file is part of VOMP.
\r
6 VOMP is free software; you can redistribute it and/or modify
\r
7 it under the terms of the GNU General Public License as published by
\r
8 the Free Software Foundation; either version 2 of the License, or
\r
9 (at your option) any later version.
\r
11 VOMP is distributed in the hope that it will be useful,
\r
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
\r
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
\r
14 GNU General Public License for more details.
\r
16 You should have received a copy of the GNU General Public License
\r
17 along with VOMP; if not, write to the Free Software
\r
18 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
\r
20 #include "glmocoshader.h"
\r
21 #include "videovpeogl.h"
\r
23 #define BLOCK_TEXTURE_WIDTH 2048
\r
24 #define BLOCK_TEXTURE_HEIGHT 1024
\r
25 #define BLOCK_SIZE 64
\r
26 #define BLOCK_PER_ROW (32)
\r
28 // This implementation is for framed coded pictures only!
\r
29 // I did not find any DVB recording with field coded pictures
\r
30 // so I do not think they exist here, anyway I suspect we
\r
31 // need a totally different shader in this case
\r
32 // so first write the frame coded shader
\r
33 // and then later add if necessary field based support.
\r
35 const GLchar moco_vertex_shader[] =
\r
36 "attribute vec4 block_pos;\n"
\r
37 "attribute vec2 block_edge;\n"
\r
38 "attribute vec4 block_types;\n"
\r
39 "attribute vec2 index;\n"
\r
40 "attribute vec4 PMV1;\n"
\r
41 "attribute vec4 PMV2;\n"
\r
42 "attribute float cbp;\n"
\r
43 "uniform vec2 pict_scale;\n"
\r
44 // "attribute vec2 tex_coord;\n"
\r
45 "varying vec4 out_yblockpos_x;\n"
\r
46 "varying vec4 out_yblockpos_y;\n"
\r
47 "varying vec4 out_uvblockpos_xy;\n"
\r
48 "varying vec2 out_block_edge;\n"
\r
49 "varying vec4 out_misc_info;\n"
\r
51 "varying float out_unsupported;\n"
\r
52 "varying vec4 out_moco_pos;\n"
\r
53 "varying vec4 out_moco_forward;\n"
\r
54 "varying vec4 out_moco_backward;\n"
\r
57 "const float one=1.0;\n"
\r
58 "const float czero=0.0;\n"
\r
59 "const float chalf=0.5;\n"
\r
60 "const float c1024=1024.0;\n"
\r
61 "const float c32=32.0;\n"
\r
62 // "const float c1over32=0.03125;\n"
\r
63 "const float c1over32=1./32.;\n"
\r
66 "const float c65536=65536.;\n"
\r
70 "const vec4 y_cbp=vec4(1.0,2.0,4.0,8.0);\n"
\r
71 "const vec3 uv_cbp=vec3(16.0,32.0,64.0);\n"
\r
75 //" vec4 cbp_vec=vec4(cbp,cbp,cbp,cbp);\n"
\r
78 // " vec4 fmod_cbp_y=mod(cbp_vec,y_cbp);\n"
\r
79 // " vec2 fmod_cbp_uv=mod(cbp_vec.xy,uv_cbp.xy);\n"
\r
80 // " fmod_cbp_y.x=0.;\n"
\r
81 // " fmod_cbp_y=sign(vec4(fmod_cbp_y.yzw,fmod_cbp_uv.x)-fmod_cbp_y);\n"
\r
82 // " fmod_cbp_uv=sign(vec2(fmod_cbp_uv.y,cbp)-fmod_cbp_uv);\n"
\r
83 // resulting vector should indicate with block is present
\r
84 // now transform it to a sum (TODO vectorize this)
\r
86 //this code is better but nor really working
\r
87 /* " vec4 fmod_cbp_y=mod(cbp_vec,vec4(uv_cbp.zyx,y_cbp.w));\n"
\r
88 " vec2 fmod_cbp_uv=mod(cbp_vec.xy,y_cbp.zy);\n"
\r
89 " fmod_cbp_y=vec4(lessThanEqual(vec4(uv_cbp.yx,y_cbp.wz),fmod_cbp_y));\n"
\r
90 " fmod_cbp_uv=vec2(lessThanEqual(y_cbp.yx,fmod_cbp_uv));\n"
\r
92 " vec4 fmod_cbp_y2=fmod_cbp_y;\n"
\r
93 " vec2 fmod_cbp_uv2=fmod_cbp_uv;\n"
\r
94 " fmod_cbp_y2.y+=fmod_cbp_y2.x;\n"
\r
95 " fmod_cbp_y2.z+=fmod_cbp_y2.y;\n"
\r
96 " fmod_cbp_y2.w+=fmod_cbp_y2.z;\n"
\r
97 " fmod_cbp_uv2.x+=fmod_cbp_y2.w;\n"
\r
98 " fmod_cbp_uv2.y+=fmod_cbp_uv2.x;\n"*/
\r
101 " float tcbp=cbp;\n"
\r
102 " float tpos=czero;\n"
\r
103 " vec4 fmod_cbp_y=vec4(czero,czero,czero,czero);\n"
\r
104 " vec2 fmod_cbp_uv=vec2(czero,czero);\n"
\r
105 " vec4 fmod_cbp_y2=vec4(czero,czero,czero,czero);\n"
\r
106 " vec2 fmod_cbp_uv2=vec2(czero,czero);\n"
\r
107 " if (tcbp>=uv_cbp.y){\n"
\r
108 " fmod_cbp_y.x=one;\n"
\r
109 " fmod_cbp_y2.x=tpos;\n"
\r
111 " tcbp-=uv_cbp.y;\n"
\r
113 " if (tcbp>=uv_cbp.x){\n"
\r
114 " fmod_cbp_y.y=one;\n"
\r
115 " fmod_cbp_y2.y=tpos;\n"
\r
117 " tcbp-=uv_cbp.x;\n"
\r
119 " if (tcbp>=y_cbp.w){\n"
\r
120 " fmod_cbp_y.z=one;\n"
\r
121 " fmod_cbp_y2.z=tpos;\n"
\r
123 " tcbp-=y_cbp.w;\n"
\r
125 " if (tcbp>=y_cbp.z){\n"
\r
126 " fmod_cbp_y.w=one;\n"
\r
127 " fmod_cbp_y2.w=tpos;\n"
\r
129 " tcbp-=y_cbp.z;\n"
\r
131 " if (tcbp>=y_cbp.y){\n"
\r
132 " fmod_cbp_uv.x=one;\n"
\r
133 " fmod_cbp_uv2.x=tpos;\n"
\r
135 " tcbp-=y_cbp.y;\n"
\r
137 " if (tcbp>=y_cbp.x){\n"
\r
138 " fmod_cbp_uv.y=one;\n"
\r
139 " fmod_cbp_uv2.y=tpos;\n"
\r
141 // " tcbp-=y_cbp.y;\n"
\r
151 // now calculate their position inside the short array
\r
152 " float m_index=index.x/*+index.y*c65536*/;\n" //Not Endian save
\r
153 " fmod_cbp_y2+=m_index;\n" //shift to the blocks
\r
154 " fmod_cbp_uv2+=m_index;\n"
\r
156 " out_yblockpos_y=floor((fmod_cbp_y2)*c1over32);\n"
\r
157 " out_uvblockpos_xy.zw=floor((fmod_cbp_uv2)*c1over32);\n"
\r
158 " out_yblockpos_x=fmod_cbp_y2-c32*out_yblockpos_y;\n"
\r
159 " out_uvblockpos_xy.xy=fmod_cbp_uv2-c32*out_uvblockpos_xy.zw;\n"
\r
163 //Kick out uncoded blocks
\r
164 // " out_yblockpos_y-=sign(fmod_cbp_y-one)*c1024;\n"
\r
165 // " out_uvblockpos_xy.zw-=sign(fmod_cbp_uv-one)*c1024;\n"
\r
167 " out_yblockpos_y=mix(vec4(c1024,c1024,c1024,c1024),out_yblockpos_y,fmod_cbp_y);\n"
\r
168 " out_uvblockpos_xy.zw=mix(vec2(c1024,c1024),out_uvblockpos_xy.zw,fmod_cbp_uv);\n"
\r
171 // set start positions
\r
172 // " vec4 motion_vertical=vec4(block_types.z,block_types.z,block_types.z,block_types.z);\n"
\r
173 // " vec4 mod_motion_vertical=mod(motion_vertical,vec4(y_cbp.yzw,uv_cbp.x));\n"
\r
174 // " mod_motion_vertical=vec4(lessThanEqual(y_cbp,mod_motion_vertical));\n"
\r
176 " out_moco_pos.xy=(block_pos.xy+block_edge.xy)*uv_cbp.x/*16*/+one;"
\r
177 " out_unsupported=czero;\n"
\r
178 " out_moco_pos.zw=vec2(czero,czero);\n"
\r
179 " out_misc_info.y=one;\n" // this is the y step
\r
180 " if (block_types.x<uv_cbp.x /* 16*/) {\n" // not intra coded
\r
181 " float forward_backward=mod(block_types.x,y_cbp.w /* 8*/);\n"
\r
182 " out_moco_pos.zw=vec2(one,czero);\n"
\r
183 " if (forward_backward>y_cbp.z /* 4*/) {\n"
\r
184 " out_moco_pos.zw=vec2(chalf,chalf);\n"
\r
185 //" out_unsupported=2.;\n"
\r
186 " } else if (forward_backward>y_cbp.y /* 2*/ ) {\n" //backward
\r
187 " out_moco_pos.zw=vec2(czero,one);\n"
\r
188 //" out_unsupported=2.;\n"
\r
189 " } else {\n" //forward
\r
190 " out_moco_pos.zw=vec2(one,czero);\n"
\r
192 " if ((out_moco_pos.w+out_moco_pos.z)>y_cbp.x) {"
\r
193 " out_moco_pos.zw*=chalf;\n"
\r
195 " if (block_types.y==y_cbp.y /*2*/) {" //Frame
\r
196 " out_moco_forward=vec4(PMV1.xy,PMV1.xy);\n"
\r
197 " out_moco_backward=vec4(PMV1.zw,PMV1.zw);\n"
\r
198 //" out_unsupported=2.;\n"
\r
199 " } else if (block_types.y==y_cbp.x /*1*/) {" //Field
\r
200 " out_moco_forward=vec4(PMV1.xy,PMV2.xy);\n"
\r
201 " out_moco_backward=vec4(PMV1.zw,PMV2.zw);\n"
\r
203 " float motion_vert=block_types.z;\n"
\r
204 " out_moco_forward.w-=one;\n"
\r
205 " out_moco_backward.w-=one;\n"
\r
206 " if (motion_vert>= y_cbp.w) {\n" //second_backward
\r
207 " motion_vert-=y_cbp.w;\n"
\r
208 " out_moco_backward.w+=one;\n"
\r
210 " if (motion_vert>= y_cbp.z) {\n" //second_forward
\r
211 " motion_vert-=y_cbp.z;\n"
\r
212 " out_moco_forward.w+=one;\n"
\r
214 " if (motion_vert>= y_cbp.y) {\n" //first_backward
\r
215 " motion_vert-=y_cbp.y;\n"
\r
216 " out_moco_backward.y+=one;\n"
\r
218 " if (motion_vert>= y_cbp.x) {\n" //second_forward
\r
219 //" motion_vert-=y_cbp.z;\n"
\r
220 " out_moco_forward.y+=one;\n"
\r
222 /* " out_moco_forward.y+=mod_motion_vertical.x;\n"
\r
223 " out_moco_backward.y+=mod_motion_vertical.y;\n"
\r
224 " out_moco_forward.w-=one-mod_motion_vertical.z;\n"
\r
225 " out_moco_backward.w-=one-mod_motion_vertical.w;\n"*/
\r
226 " out_misc_info.y=one;\n" // step to for field based
\r
227 // " out_unsupported=2.;\n"
\r
229 " out_unsupported=1.;\n"
\r
232 // " if (cbp==63. || cbp==0.) out_unsupported=2.;\n"
\r
233 // " if (fmod_cbp_y.w==1. && mod(cbp,8.)>=4.) out_unsupported=2.;\n"
\r
238 " out_block_edge=block_edge;\n"
\r
239 " out_misc_info.x=block_types.w;\n"
\r
240 " vec4 out_pos=block_pos;\n"
\r
241 " out_pos.xy+=block_edge;\n"
\r
242 " out_pos.xy*=pict_scale;\n"
\r
243 " out_pos.xy-=vec2(one,one);"
\r
244 " out_pos.zw=vec2(one,one);"
\r
245 " gl_Position=out_pos;\n"
\r
248 const GLchar moco_frag_shader[] =
\r
249 "precision mediump float;\n"
\r
250 "uniform sampler2D blocks;\n"
\r
251 "uniform sampler2D forward_pic;\n"
\r
252 "uniform sampler2D backward_pic;\n"
\r
253 "uniform vec2 pict_size;\n"
\r
254 "varying vec4 out_yblockpos_x;\n"
\r
255 "varying vec4 out_yblockpos_y;\n"
\r
256 "varying vec4 out_uvblockpos_xy;\n"
\r
257 "varying vec2 out_block_edge;\n"
\r
258 "varying vec4 out_misc_info;\n"// misc info x= DCT info, y= field based offsets
\r
259 "varying float out_unsupported;\n"
\r
260 "varying vec4 out_moco_forward;\n"
\r
261 "varying vec4 out_moco_backward;\n"
\r
262 "varying vec4 out_moco_pos;\n"
\r
264 "const float halfst=0.5;\n"
\r
265 "const float ctwo=2.0;\n"
\r
266 "const float cone=1.0;\n"
\r
267 "const float czero=0.0;\n"
\r
268 "const float sieben=7.0;\n"
\r
269 "const float acht=8.0;\n"
\r
270 "const float s8=1./8.;\n"
\r
271 "const float s16=1./16.;\n"
\r
272 "const float c1over2048=1./2048.;\n"
\r
273 "const float c1over1024=1./1024.;\n"
\r
274 "const float c255=255.;\n"
\r
275 "const float c65280=65280.;\n"
\r
276 "const float c65536=65536.;\n"
\r
277 "const float cstep=32767.;\n"
\r
279 "float unpack_short(vec2 income) {\n"
\r
280 " float temp=income.y*c65280+income.x*c255;\n"
\r
281 " temp-=step(cstep,temp)*c65536;\n"
\r
282 " return temp/c255;\n"
\r
284 // "uniform sampler2D textureV;\n"
\r
285 // "uniform sampler2D textureY;\n"
\r
286 // "varying vec2 out_texCoord;\n"
\r
289 // first figure out the block num for y, first decide between up and down, fix me field
\r
291 " vec4 ypos_temp1;\n"
\r
292 " vec4 our_fragcol=vec4(czero,czero,czero,cone);\n"
\r
293 " bool upper_half;\n"
\r
294 " float line_step;\n"
\r
295 " if (out_misc_info.x!=0.) {\n" //test the dct type
\r
296 " upper_half=mod(floor(out_block_edge.y*acht),ctwo)==cone;\n"
\r
297 " line_step=cone;\n"
\r
299 " upper_half=halfst<out_block_edge.y;\n"
\r
300 " line_step=ctwo;\n"
\r
302 " if (upper_half) {\n"
\r
303 " ypos_temp1=vec4(out_yblockpos_x.z,out_yblockpos_y.z,out_yblockpos_x.w,out_yblockpos_y.w);\n"
\r
305 " ypos_temp1=vec4(out_yblockpos_x.x,out_yblockpos_y.x,out_yblockpos_x.y,out_yblockpos_y.y);\n"
\r
307 // " vec4 ypos_temp1=mix(vec4(out_yblockpos_x.x,out_yblockpos_y.x,out_yblockpos_x.y,out_yblockpos_y.y),"
\r
308 // " vec4(out_yblockpos_x.z,out_yblockpos_y.z,out_yblockpos_x.w,out_yblockpos_y.w),step(halfst,out_block_edge.y));\n"
\r
310 // " vec4 ypos_temp1=mix(vec4(out_yblockpos_x.x,out_yblockpos_y.x,out_yblockpos_x.y,out_yblockpos_y.y),"
\r
311 // " vec4(out_yblockpos_x.z,out_yblockpos_y.z,out_yblockpos_x.w,out_yblockpos_y.w),step(s16,mod(out_block_edge.y,s8)));\n"
\r
313 //decide between left and right
\r
314 " vec4 ypos_temp2;\n"
\r
315 "if (halfst<out_block_edge.x){\n"
\r
316 " ypos_temp2.xy=ypos_temp1.zw;\n"
\r
318 " ypos_temp2.xy=ypos_temp1.xy;\n"
\r
320 //now get the intra 8x8 Block coordinates
\r
321 " vec2 ypos_temp3=floor(mod(out_block_edge*vec2(ctwo,line_step),cone)*acht);\n"
\r
322 " ypos_temp2.x=(ypos_temp3.x+(ypos_temp3.y+acht*(ypos_temp2.x))*acht);\n"
\r
323 //" bool subsample=(mod(ypos_temp2.x,ctwo)>halfst);\n"
\r
324 " bool subsample=mod(ypos_temp3.x,ctwo)==cone;\n"
\r
325 " ypos_temp2.x*=halfst;\n"
\r
326 " ypos_temp2.xy*=c1over1024;\n"
\r
327 " ypos_temp1=texture2D(blocks,ypos_temp2.xy);\n" // now select the right data
\r
328 "if (subsample){\n"
\r
329 " ypos_temp2.xy=ypos_temp1.zw;\n"
\r
330 //" ypos_temp2=vec2(cone,0.);\n"
\r
332 " ypos_temp2.xy=ypos_temp1.xy;\n"
\r
334 " our_fragcol.r=unpack_short(ypos_temp2.rg);\n"
\r
337 " ypos_temp3=floor(out_block_edge*acht);\n"
\r
338 " ypos_temp2.yw=floor(out_uvblockpos_xy.zw);\n"
\r
339 " ypos_temp2.xz=(ypos_temp3.x+(ypos_temp3.y+acht*(out_uvblockpos_xy.xy))*acht);\n"
\r
340 //" bool subsample=(mod(ypos_temp2.x,ctwo)>halfst);\n"
\r
341 " subsample=mod(ypos_temp3.x,ctwo)==cone;\n"
\r
342 " ypos_temp2.xz*=halfst;\n"
\r
343 " ypos_temp2*=c1over1024;\n"
\r
345 " ypos_temp1=texture2D(blocks,ypos_temp2.xy);\n" // now select the right data
\r
346 " if (subsample){\n"
\r
347 " ypos_temp2.xy=ypos_temp1.zw;\n"
\r
349 " ypos_temp2.xy=ypos_temp1.xy;\n"
\r
351 " our_fragcol.g=unpack_short(ypos_temp2.rg);\n"
\r
353 " ypos_temp1=texture2D(blocks,ypos_temp2.zw);\n" // now select the right data
\r
354 " if (subsample){\n"
\r
355 " ypos_temp2.xy=ypos_temp1.zw;\n"
\r
357 " ypos_temp2.xy=ypos_temp1.xy;\n"
\r
359 " our_fragcol.b=unpack_short(ypos_temp2.rg);\n"
\r
361 // decide if it is top or bottom
\r
362 " vec4 moco_work;\n"
\r
363 " if (mod(floor(out_moco_pos.y),ctwo)!=cone) {\n"
\r
364 " moco_work=vec4(out_moco_forward.xy,out_moco_backward.xy);\n"
\r
366 " moco_work=vec4(out_moco_forward.zw,out_moco_backward.zw);\n"
\r
368 // now we handle the y fetching
\r
369 " vec4 moco_temp;\n"
\r
370 " vec4 subpixel=floor(mod(moco_work,ctwo))*halfst; \n"
\r
371 " moco_temp=floor(moco_work*halfst)+floor(vec4(out_moco_pos.xy,out_moco_pos.xy));\n"
\r
372 " vec4 c00,c01,c10,c11;\n"
\r
374 " c00=texture2D(forward_pic,moco_temp.xy*pict_size);\n"
\r
375 " c01=texture2D(forward_pic,(moco_temp.xy+vec2(czero,out_misc_info.y))*pict_size);\n"
\r
376 " c10=texture2D(forward_pic,(moco_temp.xy+vec2(cone,czero))*pict_size);\n"
\r
377 " c11=texture2D(forward_pic,(moco_temp.xy+vec2(cone,out_misc_info.y))*pict_size);\n"
\r
378 " our_fragcol.r+=mix(mix(c00.r,c10.r,subpixel.x),mix(c01.r,c11.r,subpixel.x),subpixel.y)*out_moco_pos.z;\n"
\r
381 " c00=texture2D(backward_pic,moco_temp.zw*pict_size);\n"//backward
\r
382 " c01=texture2D(backward_pic,(moco_temp.zw+vec2(czero,out_misc_info.y))*pict_size);\n"
\r
383 " c10=texture2D(backward_pic,(moco_temp.zw+vec2(cone,czero))*pict_size);\n"
\r
384 " c11=texture2D(backward_pic,(moco_temp.zw+vec2(cone,out_misc_info.y))*pict_size);\n"
\r
385 " our_fragcol.r+=mix(mix(c00.r,c10.r,subpixel.z),mix(c01.r,c11.r,subpixel.z),subpixel.w)*out_moco_pos.w;\n"
\r
387 " subpixel=floor(mod(moco_work*halfst,ctwo))*halfst; \n"
\r
388 " moco_temp=(floor(moco_work*halfst*halfst)+floor(vec4(out_moco_pos.xy,out_moco_pos.xy)*halfst))*ctwo;\n"
\r
390 " c00=texture2D(forward_pic,moco_temp.xy*pict_size);\n"
\r
391 " c01=texture2D(forward_pic,(moco_temp.xy+vec2(czero,ctwo*out_misc_info.y))*pict_size);\n"
\r
392 " c10=texture2D(forward_pic,(moco_temp.xy+vec2(ctwo,czero))*pict_size);\n"
\r
393 " c11=texture2D(forward_pic,(moco_temp.xy+vec2(ctwo,ctwo*out_misc_info.y))*pict_size);\n"
\r
394 " our_fragcol.gb+=mix(mix(c00.gb,c10.gb,subpixel.x),mix(c01.gb,c11.gb,subpixel.x),subpixel.y)*out_moco_pos.z;\n"
\r
396 " c00=texture2D(backward_pic,moco_temp.zw*pict_size);\n"
\r
397 " c01=texture2D(backward_pic,(moco_temp.zw+vec2(czero,ctwo*out_misc_info.y))*pict_size);\n"
\r
398 " c10=texture2D(backward_pic,(moco_temp.zw+vec2(ctwo,czero))*pict_size);\n"
\r
399 " c11=texture2D(backward_pic,(moco_temp.zw+vec2(ctwo,ctwo*out_misc_info.y))*pict_size);\n"
\r
400 " our_fragcol.gb+=mix(mix(c00.gb,c10.gb,subpixel.z),mix(c01.gb,c11.gb,subpixel.z),subpixel.w)*out_moco_pos.w;\n"
\r
402 " gl_FragColor.rgb=vec3(our_fragcol.r,halfst,halfst);\n"
\r
403 " if (out_unsupported==1.) {\n"
\r
404 " gl_FragColor.gb=vec2(cone,0.0);\n"
\r
405 "}else if (out_unsupported==2.) {\n"
\r
406 " gl_FragColor.gb=vec2(0.0,cone);\n"
\r
410 //" ypos_temp2=mix(ypos_temp1.rg,ypos_temp1.ba,step(c1over2047,mod(ypos_temp2.x,c1over1023)));\n" //activate this
\r
413 //" gl_FragColor.r=subsample/acht;\n" //signed later TODO
\r
414 //" gl_FragColor.g=0.5;\n"
\r
415 //" gl_FragColor.b=0.5;\n"
\r
416 " gl_FragColor.a=1.0;\n"
\r
417 //" vec4 blocks=texture2D(blocks,gl_FragCoord.xy/600.);\n"
\r
418 // "help.x=texture2D(textureY,out_texCoord).r;\n"
\r
419 // "help.y=texture2D(textureU,out_texCoord).r;\n"
\r
420 // "help.z=texture2D(textureV,out_texCoord).r;\n" //-uv_corr;\n"
\r
421 // " gl_FragColor.rgba=blocks;\n"
\r
422 // " gl_FragColor.rgba=vec4(0.7,0.5,0.5,1.0);\n"
\r
423 //" gl_FragColor.a=1.;\n"
\r
426 GLMocoShader::GLMocoShader(): GLShader("GLMocoShader")
\r
433 GLMocoShader::~GLMocoShader()
\r
435 //parent does everything
\r
438 int GLMocoShader::init() {
\r
440 if (!initShaders(moco_vertex_shader, moco_frag_shader)) {
\r
441 Log::getInstance()->log("GLMocoShader", Log::ERR, "init Shaders failed for GLMocoShader");
\r
444 loc_pict_scale = glGetUniformLocation(shad_program, "pict_scale");
\r
445 blocks_loc = glGetUniformLocation(shad_program, "blocks");
\r
446 forward_pic_loc = glGetUniformLocation(shad_program, "forward_pic");
\r
447 backward_pic_loc = glGetUniformLocation(shad_program, "backward_pic");
\r
448 pict_size_loc = glGetUniformLocation(shad_program, "pict_size");
\r
450 // frame_sampler_locY = glGetUniformLocation(shad_program, "textureY");
\r
451 // Log::getInstance()->log("OSD", Log::WARN, "uniform location %x %x",frame_sampler_locY,glGetError());
\r
452 // frame_sampler_locU = glGetUniformLocation(shad_program, "textureU");
\r
453 //Log::getInstance()->log("OSD", Log::WARN, "uniform location %x %x",frame_sampler_locU,glGetError());
\r
454 // frame_sampler_locV = glGetUniformLocation(shad_program, "textureV");
\r
455 glGenFramebuffers(1, &frame_buf);
\r
456 //Log::getInstance()->log("GLMocoShader", Log::WARN, "genframe bufmark1 glerror %x",glGetError());
\r
457 glGenTextures(1, &data_blocks);
\r
458 glBindTexture(GL_TEXTURE_2D, data_blocks);
\r
459 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, BLOCK_TEXTURE_WIDTH >>1, BLOCK_TEXTURE_HEIGHT, 0, GL_RGBA,
\r
460 GL_UNSIGNED_BYTE, NULL);
\r
461 char buffer[BLOCK_TEXTURE_WIDTH*2];
\r
462 memset(buffer,0,BLOCK_TEXTURE_WIDTH*2); // the last line is black, simplifies the shader algorithms
\r
464 glTexSubImage2D(GL_TEXTURE_2D,0,0,BLOCK_TEXTURE_HEIGHT-1,
\r
465 BLOCK_TEXTURE_WIDTH>>1,1,
\r
466 GL_RGBA,GL_UNSIGNED_BYTE,
\r
469 glGenBuffers(1,¯o_block);
\r
470 glBindBuffer(GL_ARRAY_BUFFER,macro_block);
\r
471 glBufferData(GL_ARRAY_BUFFER,4096*4*sizeof(XvMCMacroBlock),NULL,GL_DYNAMIC_DRAW);
\r
472 valid_macro_blocks=0;
\r
475 glGenBuffers(1,&triangles);
\r
476 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,triangles);
\r
477 GLushort *tri_indices=(GLushort *)malloc(sizeof(GLushort)*4096*6);
\r
478 if (!tri_indices) {
\r
479 Log::getInstance()->log("GLMocoShader", Log::WARN, "allocating triindices failed");
\r
482 GLushort *tri_indices_run=tri_indices;
\r
483 for (int i=0;i<4096;i++) {
\r
484 *tri_indices_run=i+0*4096; //strip
\r
486 *tri_indices_run=i+2*4096; //strip
\r
488 *tri_indices_run=i+1*4096; //strip
\r
490 *tri_indices_run=i+3*4096; //strip
\r
492 *tri_indices_run=i+3*4096; //strip
\r
494 *tri_indices_run=i+1+0*4096; //strip
\r
502 glBufferData(GL_ELEMENT_ARRAY_BUFFER,4096*6*sizeof(GLushort),tri_indices,GL_STREAM_DRAW);
\r
505 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,0);
\r
506 glBindBuffer(GL_ARRAY_BUFFER,0);
\r
514 int GLMocoShader::deinit()
\r
516 glDeleteFramebuffers(1, &frame_buf);
\r
517 glDeleteTextures(1, &data_blocks);
\r
518 return deinitShaders();
\r
523 int GLMocoShader::uploadDataBlocks(short* blocks,unsigned int num_blocks, XvMCMacroBlock *m_blocks,unsigned int num_m_blocks)
\r
525 unsigned int height=(num_blocks)/(BLOCK_PER_ROW);
\r
527 glBindTexture(GL_TEXTURE_2D, data_blocks);
\r
528 glPixelStorei(GL_UNPACK_ALIGNMENT,1);
\r
533 Log::getInstance()->log("GLMocoShader", Log::WARN, "uploadDataBlocks mark1 %d %d %d",height,num_blocks,num_m_blocks);
\r
534 glTexSubImage2D(GL_TEXTURE_2D,0,0,0,
\r
535 BLOCK_TEXTURE_WIDTH>>1,height,
\r
536 GL_RGBA,GL_UNSIGNED_BYTE,
\r
538 // Log::getInstance()->log("GLMocoShader", Log::WARN, "uploadDataBlocks mark2 glerror %x",glGetError());
\r
539 glTexSubImage2D(GL_TEXTURE_2D,0,0,height,
\r
540 ((num_blocks%BLOCK_PER_ROW)>>1)*BLOCK_SIZE,1,
\r
541 GL_RGBA,GL_UNSIGNED_BYTE,
\r
542 blocks+height*BLOCK_PER_ROW*BLOCK_SIZE);
\r
544 //Log::getInstance()->log("GLMocoShader", Log::WARN, "uploadDataBlocks mark2 glerror %x",glGetError());
\r
548 glBindTexture(GL_TEXTURE_2D, 0);
\r
550 valid_macro_blocks=num_m_blocks;
\r
551 glBindBuffer(GL_ARRAY_BUFFER,macro_block);
\r
552 XvMCMacroBlock *m_blocks_run=m_blocks;
\r
553 XvMCMacroBlock *m_blocks_end=m_blocks+num_m_blocks;
\r
554 while (m_blocks_run!=m_blocks_end) {
\r
555 m_blocks_run->pad0=0xFF00;
\r
556 // Log::getInstance()->log("GLMocoShader", Log::WARN, "uploadDataBlocks coded block %x %x %d",
\r
557 // m_blocks_run->coded_block_pattern, m_blocks_run->macroblock_type,m_blocks_run->index);
\r
562 /* m_blocks[0].x=0;
\r
564 m_blocks[3]=m_blocks[2]=m_blocks[1]=m_blocks[0];
\r
565 m_blocks[0].pad0=0xFF00;
\r
566 m_blocks[1].pad0=0xFFFF;
\r
567 m_blocks[2].pad0=0x0000;
\r
568 m_blocks[3].pad0=0x00FF;
\r
576 glBufferSubData(GL_ARRAY_BUFFER, 0* sizeof(XvMCMacroBlock), num_m_blocks * sizeof(XvMCMacroBlock),
\r
580 m_blocks_run = m_blocks;
\r
581 m_blocks_end = m_blocks + num_m_blocks;
\r
582 while (m_blocks_run != m_blocks_end) {
\r
583 m_blocks_run->pad0 = 0xFFFF;
\r
586 glBufferSubData(GL_ARRAY_BUFFER, 4096* sizeof(XvMCMacroBlock), num_m_blocks * sizeof(XvMCMacroBlock),
\r
590 m_blocks_run = m_blocks;
\r
591 m_blocks_end = m_blocks + num_m_blocks;
\r
592 while (m_blocks_run != m_blocks_end) {
\r
593 m_blocks_run->pad0 = 0x0000;
\r
596 glBufferSubData(GL_ARRAY_BUFFER, 2 * 4096* sizeof(XvMCMacroBlock),
\r
597 num_m_blocks * sizeof(XvMCMacroBlock), m_blocks);
\r
600 m_blocks_run = m_blocks;
\r
601 m_blocks_end = m_blocks + num_m_blocks;
\r
602 while (m_blocks_run != m_blocks_end) {
\r
603 m_blocks_run->pad0 = 0x00FF;
\r
606 glBufferSubData(GL_ARRAY_BUFFER, 3 * 4096* sizeof(XvMCMacroBlock),
\r
607 num_m_blocks * sizeof(XvMCMacroBlock), m_blocks);
\r
610 glBindBuffer(GL_ARRAY_BUFFER,0);
\r
618 int GLMocoShader::doMoCo(VPEOGLFrame *target,VPEOGLFrame *forward,VPEOGLFrame *backward)
\r
621 // Log::getInstance()->log("GLMocoShader", Log::WARN, "doMoCo mark-2 glerror %x %x",glGetError(),frame_buf);
\r
623 //Log::getInstance()->log("GLMocoShader", Log::WARN, "doMoCo mark-1 glerror %x %x",glGetError(),frame_buf);
\r
624 glBindFramebuffer(GL_FRAMEBUFFER, frame_buf);
\r
625 //Log::getInstance()->log("GLMocoShader", Log::WARN, "doMoCo mark1 glerror %x %x %x",glGetError(),target->textures[0],target->textures[1]);
\r
628 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
\r
629 GL_TEXTURE_2D, target->textures[0], 0);
\r
630 //Log::getInstance()->log("GLMocoShader", Log::WARN, "doMoCo mark1apres glerror %x",glGetError());
\r
636 //Log::getInstance()->log("GLMocoShader", Log::WARN, "doMoCo mark2 glerror %x",glGetError());
\r
638 //Log::getInstance()->log("GLMocoShader", Log::WARN, "doMoCo mark2a glerror %x",glGetError());
\r
640 int status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
\r
641 if (status == GL_FRAMEBUFFER_COMPLETE) {
\r
642 glViewport(0, 0, target->width,target->height);
\r
643 // Log::getInstance()->log("GLMocoShader", Log::WARN, "doMoCo mark2b glerror %x",glGetError());
\r
645 XvMCMacroBlock * helperp=NULL;
\r
647 glClearColor(0.0f,0.5f,0.5f,1.f); //this black
\r
648 glClear(GL_COLOR_BUFFER_BIT);
\r
649 //Log::getInstance()->log("GLMocoShader", Log::WARN, "doMoCo mark2c glerror %x",glGetError());
\r
651 glUseProgram(shad_program);
\r
652 //Log::getInstance()->log("GLMocoShader", Log::WARN, "doMoCo mark3 glerror %x",glGetError());
\r
655 const GLfloat pict_scale[]={ 32./((float)target->width),32./((float)target->height)};
\r
657 glUniform2fv(loc_pict_scale,1,(const GLfloat*)&pict_scale);
\r
660 const GLfloat pict_size[]={ 1./((float)target->width),1./((float)target->height)};
\r
661 glUniform2fv(pict_size_loc,1,(const GLfloat*)&pict_size);
\r
663 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,triangles);
\r
664 //Log::getInstance()->log("GLMocoShader", Log::WARN, "doMoCo mark5 glerror %x",glGetError());
\r
665 glBindBuffer(GL_ARRAY_BUFFER,macro_block);
\r
669 glVertexAttribPointer(0, 2, GL_SHORT, GL_FALSE,
\r
670 sizeof(XvMCMacroBlock), NULL);
\r
672 glEnableVertexAttribArray(0);
\r
674 glVertexAttribPointer(1, 2, GL_UNSIGNED_BYTE, GL_TRUE,sizeof(XvMCMacroBlock), (const void *) &(helperp->pad0));
\r
675 glEnableVertexAttribArray(1);
\r
677 glVertexAttribPointer(2, 4, GL_UNSIGNED_BYTE, GL_FALSE,sizeof(XvMCMacroBlock), (const void *) &(helperp->macroblock_type));
\r
678 glEnableVertexAttribArray(2);
\r
680 glVertexAttribPointer(3, 1, GL_UNSIGNED_SHORT, GL_FALSE,sizeof(XvMCMacroBlock), (const void *) &(helperp->coded_block_pattern));
\r
681 glEnableVertexAttribArray(3);
\r
682 glVertexAttribPointer(4, 2, GL_UNSIGNED_SHORT, GL_FALSE,sizeof(XvMCMacroBlock), (const void *) &(helperp->index));
\r
683 glEnableVertexAttribArray(4);
\r
685 glVertexAttribPointer(5, 4, GL_SHORT, GL_FALSE,sizeof(XvMCMacroBlock), (const void *) &(helperp->PMV[0][0][0]));
\r
686 glEnableVertexAttribArray(5);
\r
688 glVertexAttribPointer(6, 4, GL_SHORT, GL_FALSE,sizeof(XvMCMacroBlock), (const void *) &(helperp->PMV[1][0][0]));
\r
689 glEnableVertexAttribArray(6);
\r
694 glActiveTexture(GL_TEXTURE0);
\r
695 glBindTexture(GL_TEXTURE_2D,data_blocks);
\r
696 glUniform1i(blocks_loc,0);
\r
697 glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
\r
698 glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
\r
699 glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP_TO_EDGE);
\r
700 glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP_TO_EDGE);
\r
705 // Log::getInstance()->log("GLMocoShader", Log::WARN, "doMoCo forward %x",forward->textures[0]);
\r
706 glActiveTexture(GL_TEXTURE1);
\r
707 glBindTexture(GL_TEXTURE_2D,forward->textures[0]);
\r
708 glUniform1i(forward_pic_loc,1);
\r
709 glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
\r
710 glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
\r
711 glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP_TO_EDGE);
\r
712 glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP_TO_EDGE);
\r
717 glActiveTexture(GL_TEXTURE2);
\r
718 // Log::getInstance()->log("GLMocoShader", Log::WARN, "doMoCo backward %x",backward->textures[0]);
\r
719 glBindTexture(GL_TEXTURE_2D,backward->textures[0]);
\r
720 glUniform1i(backward_pic_loc,2);
\r
721 glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
\r
722 glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
\r
723 glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP_TO_EDGE);
\r
724 glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP_TO_EDGE);
\r
730 glDrawElements(GL_TRIANGLE_STRIP, valid_macro_blocks*6,
\r
731 GL_UNSIGNED_SHORT, NULL);
\r
735 glVertexAttribPointer(0, 2, GL_SHORT, GL_FALSE,sizeof(XvMCMacroBlock), 0);
\r
736 //Log::getInstance()->log("GLMocoShader", Log::WARN, "doMoCo mark3 glerror %x",glGetError());
\r
737 glEnableVertexAttribArray(0);
\r
739 glVertexAttribPointer(1, 2, GL_UNSIGNED_BYTE, GL_TRUE,sizeof(XvMCMacroBlock), (const void *) &(helperp->pad0));
\r
740 //Log::getInstance()->log("GLMocoShader", Log::WARN, "doMoCo mark3 glerror %x",glGetError());
\r
741 glEnableVertexAttribArray(1);*/
\r
743 // Log::getInstance()->log("GLMocoShader", Log::WARN, "doMoCo mark4 glerror %x",glGetError());
\r
746 //Log::getInstance()->log("GLMocoShader", Log::WARN, "doMoCo mark6 glerror %x",glGetError());
\r
748 // glDrawElements(GL_TRIANGLE_STRIP,/*valid_macro_blocks*/4,GL_UNSIGNED_SHORT,0);
\r
749 //Log::getInstance()->log("GLMocoShader", Log::WARN, "doMoCo mark7 glerror %x %x",glGetError(),valid_macro_blocks);
\r
752 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,0);
\r
753 //Log::getInstance()->log("GLMocoShader", Log::WARN, "doMoCo mark5 glerror %x",glGetError());
\r
754 glBindBuffer(GL_ARRAY_BUFFER,0);
\r
756 glBindFramebuffer(GL_FRAMEBUFFER, 0);
\r
757 glActiveTexture(GL_TEXTURE0);
\r
758 glBindTexture(GL_TEXTURE_2D, 0);
\r
759 glActiveTexture(GL_TEXTURE1);
\r
760 glBindTexture(GL_TEXTURE_2D, 0);
\r
761 glActiveTexture(GL_TEXTURE2);
\r
762 glBindTexture(GL_TEXTURE_2D, 0);
\r
763 //Log::getInstance()->log("GLMocoShader", Log::WARN, "doMoCo mark8 glerror %x",glGetError());
\r
765 glBindFramebuffer(GL_FRAMEBUFFER, 0);
\r
766 Log::getInstance()->log("GLMocoShader", Log::WARN, "framebuffer not complete %x",status);
\r
770 glFinish(); // since the main rendering is done in a different thread we have to make sure rendering is finished before passing the texture
\r
771 // call this only in the last stage of rendering the moco frame
\r
780 int GLMocoShader::PrepareRendering(GLuint y_tex, GLuint u_tex, GLuint v_tex) { // This Function setups the rendering pipeline according to the shaders standards
\r
782 //Log::getInstance()->log("OSD", Log::WARN, "mark1 glerror %x",glGetError());
\r
785 //Log::getInstance()->log("OSD", Log::WARN, "mark2 glerror %x",glGetError());
\r
788 glActiveTexture( GL_TEXTURE2);
\r
789 glBindTexture(GL_TEXTURE_2D, v_tex);
\r
790 glUniform1i(frame_sampler_locV, 2);
\r
791 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
\r
792 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
\r
794 glActiveTexture( GL_TEXTURE1);
\r
795 glBindTexture(GL_TEXTURE_2D, u_tex);
\r
796 glUniform1i(frame_sampler_locU, 1);
\r
797 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
\r
798 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
\r
800 glActiveTexture( GL_TEXTURE0);
\r
801 glBindTexture(GL_TEXTURE_2D, y_tex);
\r
802 glUniform1i(frame_sampler_locY, 0);
\r
803 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
\r
804 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
\r
809 int GLMocoShader::BindAttributes()
\r
811 glBindAttribLocation(shad_program,0,"block_pos");
\r
812 glBindAttribLocation(shad_program,1,"block_edge");
\r
813 glBindAttribLocation(shad_program,2,"block_types");
\r
814 glBindAttribLocation(shad_program,3,"cbp");
\r
815 glBindAttribLocation(shad_program,4,"index");
\r
816 glBindAttribLocation(shad_program,5,"PMV1");
\r
817 glBindAttribLocation(shad_program,6,"PMV2");
\r
819 //glBindAttribLocation(shad_program,1,"tex_coord");
\r