From ed64450d4c522e6db31c275f111d47601a928e06 Mon Sep 17 00:00:00 2001 From: Marten Richter Date: Sun, 10 Jun 2012 18:44:01 +0200 Subject: [PATCH] Add moco shader object, initial data uploading --- GNUmakefile | 2 +- glmocoshader.cc | 261 ++++++++++++++++++++++++++++++++++++++++++++++++ glmocoshader.h | 55 ++++++++++ videovpeogl.cc | 123 ++++++++++++++++++----- videovpeogl.h | 10 +- 5 files changed, 421 insertions(+), 30 deletions(-) create mode 100755 glmocoshader.cc create mode 100755 glmocoshader.h diff --git a/GNUmakefile b/GNUmakefile index 3508184..99dc70d 100755 --- a/GNUmakefile +++ b/GNUmakefile @@ -58,7 +58,7 @@ $(info Raspberry pi flags) LDFLAGS = -Wall LIBS = -L/opt/vc/lib -lpthread -lrt -lEGL -lGLESv2 -lopenmaxil -lbcm_host -lavcodec -lavformat -lavutil -OBJECTS += main.o threadp.o osdopengl.o surfaceopengl.o ledraspberry.o mtdraspberry.o videovpeogl.o audiovpe.o wjpegsimple.o remotelinux.o glshader.o glosdshader.o glyuv400shader.o +OBJECTS += main.o threadp.o osdopengl.o surfaceopengl.o ledraspberry.o mtdraspberry.o videovpeogl.o audiovpe.o wjpegsimple.o remotelinux.o glshader.o glosdshader.o glyuv400shader.o glmocoshader.o LIBS+= -ljpeg CROSSLIBS = INCLUDES = -DVOMP_PLATTFORM_RASPBERRY -I/opt/vc/include diff --git a/glmocoshader.cc b/glmocoshader.cc new file mode 100755 index 0000000..3f29910 --- /dev/null +++ b/glmocoshader.cc @@ -0,0 +1,261 @@ +/* + Copyright 2012 Marten Richter + + This file is part of VOMP. + + VOMP 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 2 of the License, or + (at your option) any later version. + + VOMP 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 VOMP; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ +#include "glmocoshader.h" +#include "videovpeogl.h" + +const GLchar moco_vertex_shader[] = + "attribute vec4 vec_pos;\n" + "attribute vec2 tex_coord;\n" + "varying vec2 out_texCoord;\n" + "void main()\n" + "{\n" + " gl_Position=vec_pos;\n" + " out_texCoord=tex_coord;\n" + "}\n"; + +const GLchar moco_frag_shader[] = + "precision mediump float;\n" + "uniform sampler2D textureU;\n" + "uniform sampler2D textureV;\n" + "uniform sampler2D textureY;\n" + "const float uv_corr=0.5;\n" + "const float y_corr=0.0625;\n" + "const mat3 yuvtransform= mat3( 1.164 ,0.0 ,1.596 ,\n" + " 1.164 ,-0.391,-0.813 ,\n" + " 1.164,2.018 , 0.0 );\n" +// "const mat3 yuvtransform= mat3( 1. ,1. ,1. ,\n" +// " 0.0 ,-0.3960,2.029 ,\n" +// " 1.140,-0.581 , 0.0 );\n" +// "const mat3 yuvtransform= mat3( 1. ,0 ,0. ,\n" +// " 0.0 ,1.,0. ,\n" +// " 0.,0. , 1.0 );\n" +// "const mat3 yuvtransform= mat3( 1. ,1. ,1. ,\n" +// " 0.0 ,-0.03960,0.2029 ,\n" +// " 0.1140,-0.0581 , 0.0 );\n" + "varying vec2 out_texCoord;\n" + "void main()\n" + "{\n" + " vec3 help;\n" + "help.x=texture2D(textureY,out_texCoord).r-y_corr;\n" + "help.y=texture2D(textureU,out_texCoord).r-uv_corr;\n" + "help.z=texture2D(textureV,out_texCoord).r-uv_corr;\n" //-uv_corr;\n" + " gl_FragColor.rgb=help*yuvtransform;\n" + " gl_FragColor.a=1.;\n" + "}\n"; + +GLMocoShader::GLMocoShader(): GLShader("GLYuv400Shader") +{ + + frame_buf=0; +} + +GLMocoShader::~GLMocoShader() +{ + //parent does everything +} + +int GLMocoShader::init() { + if (!initShaders(moco_vertex_shader, moco_frag_shader)) { + return 0; + } +// frame_sampler_locY = glGetUniformLocation(shad_program, "textureY"); + // Log::getInstance()->log("OSD", Log::WARN, "uniform location %x %x",frame_sampler_locY,glGetError()); +// frame_sampler_locU = glGetUniformLocation(shad_program, "textureU"); + //Log::getInstance()->log("OSD", Log::WARN, "uniform location %x %x",frame_sampler_locU,glGetError()); +// frame_sampler_locV = glGetUniformLocation(shad_program, "textureV"); + glGenFramebuffers(1, &frame_buf); + glGenTextures(1, &data_blocks); + glBindTexture(GL_TEXTURE_2D, data_blocks); + glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE_ALPHA, 1024, 1024, 0, GL_LUMINANCE_ALPHA, + GL_UNSIGNED_BYTE, NULL); + + glGenBuffers(1,¯o_block); + glBindBuffer(GL_ARRAY_BUFFER,macro_block); + glBufferData(GL_ARRAY_BUFFER,4096*4*sizeof(XvMCMacroBlock),NULL,GL_DYNAMIC_DRAW); + valid_macro_blocks=0; + + + glGenBuffers(1,&triangles); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,triangles); + GLushort *tri_indices=(GLushort *)malloc(sizeof(GLushort)*4096*6); + if (!tri_indices) { + Log::getInstance()->log("GLMocoShader", Log::WARN, "allocating triindices failed"); + return 0; + } + GLushort *tri_indices_run=tri_indices; + for (int i=0;i<4096;i++) { + *tri_indices_run=i+2*4096; //strip + tri_indices_run++; + *tri_indices_run=i+0*4096; //strip + tri_indices_run++; + *tri_indices_run=i+3*4096; //strip + tri_indices_run++; + *tri_indices_run=i+1*4096; //strip + tri_indices_run++; + *tri_indices_run=i+1*4096; //strip + tri_indices_run++; + *tri_indices_run=i+1+2*4096; //strip + tri_indices_run++; + } + glBufferData(GL_ELEMENT_ARRAY_BUFFER,4096*6*sizeof(GLushort),tri_indices,GL_STREAM_DRAW); + free(tri_indices); + + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,0); + glBindBuffer(GL_ARRAY_BUFFER,0); + + + + return 1; + +} + +int GLMocoShader::deinit() +{ + glDeleteFramebuffers(1, &frame_buf); + glDeleteTextures(1, &frame_buf); + return deinitShaders(); +} + +int GLMocoShader::uploadDataBlocks(short* blocks,unsigned int num_blocks, XvMCMacroBlock *m_blocks,unsigned int num_m_blocks) +{ + unsigned int height=(num_blocks+127)/128; + + glBindTexture(GL_TEXTURE_2D, data_blocks); + glPixelStorei(GL_UNPACK_ALIGNMENT,1); + + glTexSubImage2D(GL_TEXTURE_2D,0,0,0, + 1024,height, + GL_LUMINANCE,GL_UNSIGNED_BYTE, + blocks); + //Log::getInstance()->log("GLMocoShader", Log::WARN, "uploadDataBlocks mark2 glerror %x",glGetError()); + + valid_macro_blocks=num_m_blocks; + glBindBuffer(GL_ARRAY_BUFFER,macro_block); + XvMCMacroBlock *m_blocks_run=m_blocks; + XvMCMacroBlock *m_blocks_end=m_blocks+num_m_blocks; + while (m_blocks_run!=m_blocks_end) { + m_blocks_run->pad0=0x0000; + m_blocks_run++; + } + glBufferSubData(GL_ARRAY_BUFFER, 0, num_m_blocks * sizeof(XvMCMacroBlock), + m_blocks); + + m_blocks_run = m_blocks; + m_blocks_end = m_blocks + num_m_blocks; + while (m_blocks_run != m_blocks_end) { + m_blocks_run->pad0 = 0x00FF; + m_blocks_run++; + } + glBufferSubData(GL_ARRAY_BUFFER, 4096, num_m_blocks * sizeof(XvMCMacroBlock), + m_blocks); + + m_blocks_run = m_blocks; + m_blocks_end = m_blocks + num_m_blocks; + while (m_blocks_run != m_blocks_end) { + m_blocks_run->pad0 = 0xFF00; + m_blocks_run++; + } + glBufferSubData(GL_ARRAY_BUFFER, 2 * 4096, + num_m_blocks * sizeof(XvMCMacroBlock), m_blocks); + + m_blocks_run = m_blocks; + m_blocks_end = m_blocks + num_m_blocks; + while (m_blocks_run != m_blocks_end) { + m_blocks_run->pad0 = 0xFFFF; + m_blocks_run++; + } + glBufferSubData(GL_ARRAY_BUFFER, 3 * 4096, + num_m_blocks * sizeof(XvMCMacroBlock), m_blocks); + + + glBindBuffer(GL_ARRAY_BUFFER,0); + + return 1; + + + +} + +int GLMocoShader::doMoCo(VPEOGLFrame *target, VPE_FrameBuf* source) +{ + + glBindFramebuffer(GL_FRAMEBUFFER, frame_buf); + Log::getInstance()->log("GLMocoShader", Log::WARN, "doMoCo mark1 glerror %x",glGetError()); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, + GL_TEXTURE_2D, target->textures[0], 0); + Log::getInstance()->log("GLMocoShader", Log::WARN, "doMoCo mark2 glerror %x",glGetError()); + + int status = glCheckFramebufferStatus(GL_FRAMEBUFFER); + if (status == GL_FRAMEBUFFER_COMPLETE) { + glUseProgram(shad_program); + Log::getInstance()->log("GLMocoShader", Log::WARN, "doMoCo mark3 glerror %x",glGetError()); + + + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,0); + glBindBuffer(GL_ARRAY_BUFFER,0); + glBindFramebuffer(GL_FRAMEBUFFER, 0); + } else { + glBindFramebuffer(GL_FRAMEBUFFER, 0); + Log::getInstance()->log("GLMocoShader", Log::WARN, "framebuffer not complete"); + return -1; + } + return 0; + + + +} + +/* + +int GLMocoShader::PrepareRendering(GLuint y_tex, GLuint u_tex, GLuint v_tex) { // This Function setups the rendering pipeline according to the shaders standards + + //Log::getInstance()->log("OSD", Log::WARN, "mark1 glerror %x",glGetError()); + + + //Log::getInstance()->log("OSD", Log::WARN, "mark2 glerror %x",glGetError()); + + + glActiveTexture( GL_TEXTURE2); + glBindTexture(GL_TEXTURE_2D, v_tex); + glUniform1i(frame_sampler_locV, 2); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + + glActiveTexture( GL_TEXTURE1); + glBindTexture(GL_TEXTURE_2D, u_tex); + glUniform1i(frame_sampler_locU, 1); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + + glActiveTexture( GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, y_tex); + glUniform1i(frame_sampler_locY, 0); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + return 1; + +}*/ + +int GLMocoShader::BindAttributes() +{ + glBindAttribLocation(shad_program,0,"vec_pos"); + glBindAttribLocation(shad_program,1,"tex_coord"); + return 1; +} diff --git a/glmocoshader.h b/glmocoshader.h new file mode 100755 index 0000000..51ed2c7 --- /dev/null +++ b/glmocoshader.h @@ -0,0 +1,55 @@ +/* + Copyright 2012 Marten Richter + + This file is part of VOMP. + + VOMP 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 2 of the License, or + (at your option) any later version. + + VOMP 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 VOMP; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#ifndef GL_MOCOSHADER_H +#define GL_MOCOSHADER_H + +#include "glshader.h" +#include + +struct VPEOGLFrame; +struct VPE_FrameBuf; + + +class GLMocoShader: public GLShader { +public: + GLMocoShader(); + virtual ~GLMocoShader(); + + int init(); + int deinit(); + + int uploadDataBlocks(short* blocks,unsigned int num_blocks, XvMCMacroBlock *m_blocks,unsigned int num_m_blocks); + + int doMoCo(VPEOGLFrame *target, VPE_FrameBuf* source); + +protected: + virtual int BindAttributes(); + GLuint frame_buf; + GLuint data_blocks; + GLuint triangles; + GLuint macro_block; + unsigned int valid_macro_blocks; + + +}; + + +#endif diff --git a/videovpeogl.cc b/videovpeogl.cc index 938fea8..8b90009 100755 --- a/videovpeogl.cc +++ b/videovpeogl.cc @@ -47,10 +47,11 @@ VideoVPEOGL::VideoVPEOGL() 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 @@ -245,9 +246,9 @@ int VideoVPEOGL::shutdown() 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]); @@ -266,6 +267,27 @@ int VideoVPEOGL::AllocateYUVOglTexture(VPEOGLFrame* outframe,int width,int heigh 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; } @@ -343,32 +365,56 @@ void VideoVPEOGL::threadMethod() 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]); @@ -1566,6 +1612,14 @@ int VideoVPEOGL::AllocateCodecsLibav() 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; @@ -1618,6 +1672,7 @@ int VideoVPEOGL::DeAllocateCodecsLibav() glDeleteTextures(1,&del_frame->textures[2]); del_frame->textures[2]=0; } + free(all_ogl_frames[i]); } all_ogl_frames.clear(); @@ -1655,6 +1710,20 @@ int VideoVPEOGL::DeAllocateCodecsLibav() 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; } diff --git a/videovpeogl.h b/videovpeogl.h index 4af2bab..95620e8 100755 --- a/videovpeogl.h +++ b/videovpeogl.h @@ -40,6 +40,7 @@ #include "video.h" #include "threadsystem.h" + //#define EGL_EGLEXT_PROTOTYPES #include @@ -74,7 +75,10 @@ extern "C" { #include #include #include + + } +#include "glmocoshader.h" struct VPE_FrameBuf { //This is a frame bulibaver, nothing fancy just plain memory @@ -91,7 +95,7 @@ struct VPE_FrameBuf struct VPEOGLFrame { - int type; //1 = YUV, 2 RGB + int type; //1 = YUV400, 2 YUV444 GLuint textures[3]; // 0=RGB or Y, 1=U 2=V int width, height; int stride; @@ -300,6 +304,7 @@ class VideoVPEOGL : public Video, public Thread_TYPE long long libav_time; int libavwidth,libavheight,libavpixfmt; + GLMocoShader *moco_shader; #endif @@ -310,7 +315,8 @@ class VideoVPEOGL : public Video, public Thread_TYPE bool ogl_frame_outside; Mutex ogl_frame_mutex; - int AllocateYUVOglTexture(VPEOGLFrame* outframe,int width,int height,int stride); + int AllocateYUV400OglTexture(VPEOGLFrame* outframe,int width,int height,int stride); + int AllocateYUV444OglTexture(VPEOGLFrame* outframe,int width,int height,int stride); virtual void threadMethod(); virtual void threadPostStopCleanup(); -- 2.39.5