--- /dev/null
+/*\r
+ Copyright 2012 Marten Richter\r
+\r
+ This file is part of VOMP.\r
+\r
+ VOMP is free software; you can redistribute it and/or modify\r
+ it under the terms of the GNU General Public License as published by\r
+ the Free Software Foundation; either version 2 of the License, or\r
+ (at your option) any later version.\r
+\r
+ VOMP is distributed in the hope that it will be useful,\r
+ but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
+ GNU General Public License for more details.\r
+\r
+ You should have received a copy of the GNU General Public License\r
+ along with VOMP; if not, write to the Free Software\r
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\r
+*/\r
+#include "glmocoshader.h"\r
+#include "videovpeogl.h"\r
+\r
+const GLchar moco_vertex_shader[] =\r
+ "attribute vec4 vec_pos;\n"\r
+ "attribute vec2 tex_coord;\n"\r
+ "varying vec2 out_texCoord;\n"\r
+ "void main()\n"\r
+ "{\n"\r
+ " gl_Position=vec_pos;\n"\r
+ " out_texCoord=tex_coord;\n"\r
+ "}\n";\r
+\r
+const GLchar moco_frag_shader[] =\r
+ "precision mediump float;\n"\r
+ "uniform sampler2D textureU;\n"\r
+ "uniform sampler2D textureV;\n"\r
+ "uniform sampler2D textureY;\n"\r
+ "const float uv_corr=0.5;\n"\r
+ "const float y_corr=0.0625;\n"\r
+ "const mat3 yuvtransform= mat3( 1.164 ,0.0 ,1.596 ,\n"\r
+ " 1.164 ,-0.391,-0.813 ,\n"\r
+ " 1.164,2.018 , 0.0 );\n"\r
+// "const mat3 yuvtransform= mat3( 1. ,1. ,1. ,\n"\r
+// " 0.0 ,-0.3960,2.029 ,\n"\r
+// " 1.140,-0.581 , 0.0 );\n"\r
+// "const mat3 yuvtransform= mat3( 1. ,0 ,0. ,\n"\r
+// " 0.0 ,1.,0. ,\n"\r
+// " 0.,0. , 1.0 );\n"\r
+// "const mat3 yuvtransform= mat3( 1. ,1. ,1. ,\n"\r
+// " 0.0 ,-0.03960,0.2029 ,\n"\r
+// " 0.1140,-0.0581 , 0.0 );\n"\r
+ "varying vec2 out_texCoord;\n"\r
+ "void main()\n"\r
+ "{\n"\r
+ " vec3 help;\n"\r
+ "help.x=texture2D(textureY,out_texCoord).r-y_corr;\n"\r
+ "help.y=texture2D(textureU,out_texCoord).r-uv_corr;\n"\r
+ "help.z=texture2D(textureV,out_texCoord).r-uv_corr;\n" //-uv_corr;\n"\r
+ " gl_FragColor.rgb=help*yuvtransform;\n"\r
+ " gl_FragColor.a=1.;\n"\r
+ "}\n";\r
+\r
+GLMocoShader::GLMocoShader(): GLShader("GLYuv400Shader")\r
+{\r
+\r
+ frame_buf=0;\r
+}\r
+\r
+GLMocoShader::~GLMocoShader()\r
+{\r
+ //parent does everything\r
+}\r
+\r
+int GLMocoShader::init() {\r
+ if (!initShaders(moco_vertex_shader, moco_frag_shader)) {\r
+ return 0;\r
+ }\r
+// frame_sampler_locY = glGetUniformLocation(shad_program, "textureY");\r
+ // Log::getInstance()->log("OSD", Log::WARN, "uniform location %x %x",frame_sampler_locY,glGetError());\r
+// frame_sampler_locU = glGetUniformLocation(shad_program, "textureU");\r
+ //Log::getInstance()->log("OSD", Log::WARN, "uniform location %x %x",frame_sampler_locU,glGetError());\r
+// frame_sampler_locV = glGetUniformLocation(shad_program, "textureV");\r
+ glGenFramebuffers(1, &frame_buf);\r
+ glGenTextures(1, &data_blocks);\r
+ glBindTexture(GL_TEXTURE_2D, data_blocks);\r
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE_ALPHA, 1024, 1024, 0, GL_LUMINANCE_ALPHA,\r
+ GL_UNSIGNED_BYTE, NULL);\r
+\r
+ glGenBuffers(1,¯o_block);\r
+ glBindBuffer(GL_ARRAY_BUFFER,macro_block);\r
+ glBufferData(GL_ARRAY_BUFFER,4096*4*sizeof(XvMCMacroBlock),NULL,GL_DYNAMIC_DRAW);\r
+ valid_macro_blocks=0;\r
+\r
+\r
+ glGenBuffers(1,&triangles);\r
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,triangles);\r
+ GLushort *tri_indices=(GLushort *)malloc(sizeof(GLushort)*4096*6);\r
+ if (!tri_indices) {\r
+ Log::getInstance()->log("GLMocoShader", Log::WARN, "allocating triindices failed");\r
+ return 0;\r
+ }\r
+ GLushort *tri_indices_run=tri_indices;\r
+ for (int i=0;i<4096;i++) {\r
+ *tri_indices_run=i+2*4096; //strip\r
+ tri_indices_run++;\r
+ *tri_indices_run=i+0*4096; //strip\r
+ tri_indices_run++;\r
+ *tri_indices_run=i+3*4096; //strip\r
+ tri_indices_run++;\r
+ *tri_indices_run=i+1*4096; //strip\r
+ tri_indices_run++;\r
+ *tri_indices_run=i+1*4096; //strip\r
+ tri_indices_run++;\r
+ *tri_indices_run=i+1+2*4096; //strip\r
+ tri_indices_run++;\r
+ }\r
+ glBufferData(GL_ELEMENT_ARRAY_BUFFER,4096*6*sizeof(GLushort),tri_indices,GL_STREAM_DRAW);\r
+ free(tri_indices);\r
+\r
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,0);\r
+ glBindBuffer(GL_ARRAY_BUFFER,0);\r
+\r
+\r
+\r
+ return 1;\r
+\r
+}\r
+\r
+int GLMocoShader::deinit()\r
+{\r
+ glDeleteFramebuffers(1, &frame_buf);\r
+ glDeleteTextures(1, &frame_buf);\r
+ return deinitShaders();\r
+}\r
+\r
+int GLMocoShader::uploadDataBlocks(short* blocks,unsigned int num_blocks, XvMCMacroBlock *m_blocks,unsigned int num_m_blocks)\r
+{\r
+ unsigned int height=(num_blocks+127)/128;\r
+\r
+ glBindTexture(GL_TEXTURE_2D, data_blocks);\r
+ glPixelStorei(GL_UNPACK_ALIGNMENT,1);\r
+\r
+ glTexSubImage2D(GL_TEXTURE_2D,0,0,0,\r
+ 1024,height,\r
+ GL_LUMINANCE,GL_UNSIGNED_BYTE,\r
+ blocks);\r
+ //Log::getInstance()->log("GLMocoShader", Log::WARN, "uploadDataBlocks mark2 glerror %x",glGetError());\r
+\r
+ valid_macro_blocks=num_m_blocks;\r
+ glBindBuffer(GL_ARRAY_BUFFER,macro_block);\r
+ XvMCMacroBlock *m_blocks_run=m_blocks;\r
+ XvMCMacroBlock *m_blocks_end=m_blocks+num_m_blocks;\r
+ while (m_blocks_run!=m_blocks_end) {\r
+ m_blocks_run->pad0=0x0000;\r
+ m_blocks_run++;\r
+ }\r
+ glBufferSubData(GL_ARRAY_BUFFER, 0, num_m_blocks * sizeof(XvMCMacroBlock),\r
+ m_blocks);\r
+\r
+ m_blocks_run = m_blocks;\r
+ m_blocks_end = m_blocks + num_m_blocks;\r
+ while (m_blocks_run != m_blocks_end) {\r
+ m_blocks_run->pad0 = 0x00FF;\r
+ m_blocks_run++;\r
+ }\r
+ glBufferSubData(GL_ARRAY_BUFFER, 4096, num_m_blocks * sizeof(XvMCMacroBlock),\r
+ m_blocks);\r
+\r
+ m_blocks_run = m_blocks;\r
+ m_blocks_end = m_blocks + num_m_blocks;\r
+ while (m_blocks_run != m_blocks_end) {\r
+ m_blocks_run->pad0 = 0xFF00;\r
+ m_blocks_run++;\r
+ }\r
+ glBufferSubData(GL_ARRAY_BUFFER, 2 * 4096,\r
+ num_m_blocks * sizeof(XvMCMacroBlock), m_blocks);\r
+\r
+ m_blocks_run = m_blocks;\r
+ m_blocks_end = m_blocks + num_m_blocks;\r
+ while (m_blocks_run != m_blocks_end) {\r
+ m_blocks_run->pad0 = 0xFFFF;\r
+ m_blocks_run++;\r
+ }\r
+ glBufferSubData(GL_ARRAY_BUFFER, 3 * 4096,\r
+ num_m_blocks * sizeof(XvMCMacroBlock), m_blocks);\r
+\r
+\r
+ glBindBuffer(GL_ARRAY_BUFFER,0);\r
+\r
+ return 1;\r
+\r
+\r
+\r
+}\r
+\r
+int GLMocoShader::doMoCo(VPEOGLFrame *target, VPE_FrameBuf* source)\r
+{\r
+\r
+ glBindFramebuffer(GL_FRAMEBUFFER, frame_buf);\r
+ Log::getInstance()->log("GLMocoShader", Log::WARN, "doMoCo mark1 glerror %x",glGetError());\r
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,\r
+ GL_TEXTURE_2D, target->textures[0], 0);\r
+ Log::getInstance()->log("GLMocoShader", Log::WARN, "doMoCo mark2 glerror %x",glGetError());\r
+\r
+ int status = glCheckFramebufferStatus(GL_FRAMEBUFFER);\r
+ if (status == GL_FRAMEBUFFER_COMPLETE) {\r
+ glUseProgram(shad_program);\r
+ Log::getInstance()->log("GLMocoShader", Log::WARN, "doMoCo mark3 glerror %x",glGetError());\r
+\r
+\r
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,0);\r
+ glBindBuffer(GL_ARRAY_BUFFER,0);\r
+ glBindFramebuffer(GL_FRAMEBUFFER, 0);\r
+ } else {\r
+ glBindFramebuffer(GL_FRAMEBUFFER, 0);\r
+ Log::getInstance()->log("GLMocoShader", Log::WARN, "framebuffer not complete");\r
+ return -1;\r
+ }\r
+ return 0;\r
+\r
+\r
+\r
+}\r
+\r
+/*\r
+\r
+int GLMocoShader::PrepareRendering(GLuint y_tex, GLuint u_tex, GLuint v_tex) { // This Function setups the rendering pipeline according to the shaders standards\r
+\r
+ //Log::getInstance()->log("OSD", Log::WARN, "mark1 glerror %x",glGetError());\r
+\r
+\r
+ //Log::getInstance()->log("OSD", Log::WARN, "mark2 glerror %x",glGetError());\r
+\r
+\r
+ glActiveTexture( GL_TEXTURE2);\r
+ glBindTexture(GL_TEXTURE_2D, v_tex);\r
+ glUniform1i(frame_sampler_locV, 2);\r
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);\r
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);\r
+\r
+ glActiveTexture( GL_TEXTURE1);\r
+ glBindTexture(GL_TEXTURE_2D, u_tex);\r
+ glUniform1i(frame_sampler_locU, 1);\r
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);\r
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);\r
+\r
+ glActiveTexture( GL_TEXTURE0);\r
+ glBindTexture(GL_TEXTURE_2D, y_tex);\r
+ glUniform1i(frame_sampler_locY, 0);\r
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);\r
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);\r
+ return 1;\r
+\r
+}*/\r
+\r
+int GLMocoShader::BindAttributes()\r
+{\r
+ glBindAttribLocation(shad_program,0,"vec_pos");\r
+ glBindAttribLocation(shad_program,1,"tex_coord");\r
+ return 1;\r
+}\r
dec_frame_libav_uploading=NULL;
dec_frame_libav_decoding=NULL;
ogl_frame_outside=false;
- decoding_mode=VPE_NO_XVMC;
- //decoding_mode=VPE_XVMC_MOCOMP;
+ //decoding_mode=VPE_NO_XVMC;
+ decoding_mode=VPE_XVMC_MOCOMP;
//decoding_mode=VPE_XVMC_IDCT;
framebuf_framenum=0;
+ moco_shader=NULL;
#endif
#ifdef BENCHMARK_FPS
return 1;
}
-int VideoVPEOGL::AllocateYUVOglTexture(VPEOGLFrame* outframe,int width,int height,int stride)
+int VideoVPEOGL::AllocateYUV400OglTexture(VPEOGLFrame* outframe,int width,int height,int stride)
{
- Log::getInstance()->log("Video", Log::NOTICE, "Allocate ogl texture");
+ Log::getInstance()->log("Video", Log::NOTICE, "Allocate ogl texture 400");
// Y
glGenTextures(1, &outframe->textures[0]);
glBindTexture(GL_TEXTURE_2D, outframe->textures[0]);
outframe->height=height;
outframe->width=width;
outframe->stride=stride;
+ outframe->type=1;
+ return 1;
+}
+
+int VideoVPEOGL::AllocateYUV444OglTexture(VPEOGLFrame* outframe,int width,int height,int stride)
+{
+ Log::getInstance()->log("Video", Log::NOTICE, "Allocate ogl texture 444");
+ // Y
+ glGenTextures(1, &outframe->textures[0]);
+ glBindTexture(GL_TEXTURE_2D, outframe->textures[0]);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, stride, height, 0, GL_RGBA,
+ GL_UNSIGNED_BYTE, NULL);
+ outframe->textures[1]=outframe->textures[2]=0; // no handles here
+
+
+
+
+ outframe->type=2;
+ outframe->height=height;
+ outframe->width=width;
+ outframe->stride=stride;
return 1;
}
glDeleteTextures(1,&out_frame->textures[2]);
out_frame->textures[2]=0;
}
- if (!AllocateYUVOglTexture(out_frame,width,height,dec_frame_libav_uploading->linesize[0])) failed=true;
+
+ if (decoding_mode==VPE_NO_XVMC) {
+ if (!AllocateYUV400OglTexture(out_frame,width,height,dec_frame_libav_uploading->linesize[0])) failed=true;
+ }else {
+ if (!AllocateYUV444OglTexture(out_frame,width,height,dec_frame_libav_uploading->linesize[0])) failed=true; //We use a YUV 444 texture in this case
+ // the shaders are easier to implement
+ }
}
if (!failed) {
//up to now only YUV data, this is for reference only, since the pi is too slow.
- glBindTexture(GL_TEXTURE_2D, out_frame->textures[0]);
- glPixelStorei(GL_UNPACK_ALIGNMENT,1);
-
- glTexSubImage2D(GL_TEXTURE_2D,0,0,0,
- out_frame->stride,out_frame->height,
- GL_LUMINANCE,GL_UNSIGNED_BYTE,
- dec_frame_libav_uploading->data[0]);
-
-
- glBindTexture(GL_TEXTURE_2D, out_frame->textures[1]);
- glPixelStorei(GL_UNPACK_ALIGNMENT,1);
- glTexSubImage2D(GL_TEXTURE_2D,0,0,0,
- out_frame->stride>>1,out_frame->height>>1,
- GL_LUMINANCE,GL_UNSIGNED_BYTE,
- dec_frame_libav_uploading->data[1]);
-
- glBindTexture(GL_TEXTURE_2D, out_frame->textures[2]);
- glPixelStorei(GL_UNPACK_ALIGNMENT,1);
- glTexSubImage2D(GL_TEXTURE_2D,0,0,0,
- out_frame->stride>>1,out_frame->height>>1,
- GL_LUMINANCE,GL_UNSIGNED_BYTE,
- dec_frame_libav_uploading->data[2]);
+ if (decoding_mode==VPE_NO_XVMC) {
+ glBindTexture(GL_TEXTURE_2D, out_frame->textures[0]);
+ glPixelStorei(GL_UNPACK_ALIGNMENT,1);
+ glTexSubImage2D(GL_TEXTURE_2D,0,0,0,
+ out_frame->stride,out_frame->height,
+ GL_LUMINANCE,GL_UNSIGNED_BYTE,
+ dec_frame_libav_uploading->data[0]);
+
+ glBindTexture(GL_TEXTURE_2D, out_frame->textures[1]);
+ glPixelStorei(GL_UNPACK_ALIGNMENT,1);
+ glTexSubImage2D(GL_TEXTURE_2D,0,0,0,
+ out_frame->stride>>1,out_frame->height>>1,
+ GL_LUMINANCE,GL_UNSIGNED_BYTE,
+ dec_frame_libav_uploading->data[1]);
+
+ glBindTexture(GL_TEXTURE_2D, out_frame->textures[2]);
+ glPixelStorei(GL_UNPACK_ALIGNMENT,1);
+ glTexSubImage2D(GL_TEXTURE_2D,0,0,0,
+ out_frame->stride>>1,out_frame->height>>1,
+ GL_LUMINANCE,GL_UNSIGNED_BYTE,
+ dec_frame_libav_uploading->data[2]);
+ } else {
+ //XVMC case
+ xvmc_pix_fmt * pix_fmt=(xvmc_pix_fmt *)dec_frame_libav_uploading->data[2];
+ if (moco_shader && pix_fmt) {
+
+
+ moco_shader->uploadDataBlocks(pix_fmt->data_blocks,pix_fmt->next_free_data_block_num,
+ pix_fmt->mv_blocks , pix_fmt->filled_mv_blocks_num );
+ if (decoding_mode==VPE_XVMC_MOCOMP)
+ {
+ //DCT Blocks upload
+
+ } else {
+ //DCT Blocks upload
+ }
+
+ // Excute motion compensation
+ }
+ }
releaseFrameBufUpload((VPE_FrameBuf*)dec_frame_libav_uploading->base[0]);
ogl_frame_mutex.Unlock();
+ if (decoding_mode==VPE_XVMC_MOCOMP) {
+ OsdOpenGL* osd=(OsdOpenGL*)osd->getInstance();
+ osd->BeginPainting(); // get OpenGl context
+ moco_shader=new GLMocoShader();
+ moco_shader->init();
+ osd->EndPainting();
+ }
+
libav_running=true;
return 1;
glDeleteTextures(1,&del_frame->textures[2]);
del_frame->textures[2]=0;
}
+
free(all_ogl_frames[i]);
}
all_ogl_frames.clear();
vpe_framebuf_mutex.Unlock();
+
+ if (moco_shader) {
+ OsdOpenGL* osd=(OsdOpenGL*)osd->getInstance();
+ osd->BeginPainting(); // get OpenGl context
+ moco_shader->deinit();
+ delete moco_shader;
+ moco_shader=NULL;
+ osd->EndPainting();
+ }
+
+
+
+
+
return 1;
}