]> git.vomp.tv Git - vompclient.git/commitdiff
Add handling reference frame pointers
authorMarten Richter <marten.richter@freenet.de>
Sun, 24 Jun 2012 17:49:41 +0000 (19:49 +0200)
committerMarten Richter <marten.richter@freenet.de>
Sun, 24 Jun 2012 17:49:41 +0000 (19:49 +0200)
glmocoshader.cc
glmocoshader.h
videovpeogl.cc
videovpeogl.h

index 23fcc619792999c5fbe05763dc6577f3929cc50e..a674e0f9d30f497274222ba0b130f9963d0082f8 100755 (executable)
@@ -39,6 +39,8 @@ const GLchar moco_vertex_shader[] =
                "varying vec2 out_block_edge;\n"\r
                "varying vec4 out_block_types;\n"\r
 \r
+               "varying float out_unsupported;\n"\r
+\r
                "const float one=1.0;\n"\r
                "const float c1024=1024.0;\n"\r
                "const float c32=32.0;\n"\r
@@ -91,6 +93,12 @@ const GLchar moco_vertex_shader[] =
                "  out_yblockpos_y-=sign(fmod_cbp_y-one)*c1024;\n"\r
                "  out_uvblockpos_xy.zw-=sign(fmod_cbp_uv-one)*c1024;\n"\r
 \r
+       //      " if (block_types.y!=0.) {\n"\r
+       //      "  out_unsupported=1.;\n"\r
+       //      "} else {\n"\r
+       //      "  out_unsupported=0.;\n"\r
+       //      "}\n"\r
+\r
 \r
                "  out_block_edge=block_edge;\n"\r
                "  out_block_types=block_types;\n"\r
@@ -105,11 +113,14 @@ const GLchar moco_vertex_shader[] =
 const GLchar moco_frag_shader[] =\r
                "precision mediump float;\n"\r
                "uniform sampler2D blocks;\n"\r
+               "uniform sampler2D forward_pic;\n"\r
+               "uniform sampler2D backward_pic;\n"\r
                "varying vec4 out_yblockpos_x;\n"\r
                "varying vec4 out_yblockpos_y;\n"\r
                "varying vec4 out_uvblockpos_xy;\n"\r
                "varying vec2 out_block_edge;\n"\r
-               "varying vec4 out_block_types;\n"\r
+               "varying vec4 out_block_types;\n" // change this we need so far only the dct type\r
+               "varying float out_unsupported;\n"\r
 \r
                "const float halfst=0.5;\n"\r
                "const float ctwo=2.0;\n"\r
@@ -205,6 +216,9 @@ const GLchar moco_frag_shader[] =
                "  ypos_temp2.xy=ypos_temp1.xy;\n"\r
                " }\n"\r
                " gl_FragColor.b=unpack_short(ypos_temp2.rg);\n"\r
+               " if (out_unsupported!=0.) {\n"\r
+               "    gl_FragColor.rgb=vec3(cone,cone,0.0);\n"\r
+               "}\n"\r
 \r
 \r
                //" ypos_temp2=mix(ypos_temp1.rg,ypos_temp1.ba,step(c1over2047,mod(ypos_temp2.x,c1over1023)));\n" //activate this\r
@@ -243,6 +257,8 @@ int GLMocoShader::init() {
        }\r
        loc_pict_scale = glGetUniformLocation(shad_program, "pict_scale");\r
        blocks_loc = glGetUniformLocation(shad_program, "blocks");\r
+       forward_pic_loc = glGetUniformLocation(shad_program, "forward_pic");\r
+       backward_pic_loc = glGetUniformLocation(shad_program, "backward_pic");\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
@@ -327,18 +343,18 @@ int GLMocoShader::uploadDataBlocks(short* blocks,unsigned int num_blocks, XvMCMa
 \r
 \r
 \r
-       Log::getInstance()->log("GLMocoShader", Log::WARN, "uploadDataBlocks mark1 glerror %x %d",glGetError(),height);\r
+//     Log::getInstance()->log("GLMocoShader", Log::WARN, "uploadDataBlocks mark1 glerror %x %d",glGetError(),height);\r
        glTexSubImage2D(GL_TEXTURE_2D,0,0,0,\r
                BLOCK_TEXTURE_WIDTH>>1,height,\r
                GL_RGBA,GL_UNSIGNED_BYTE,\r
                blocks);\r
-       Log::getInstance()->log("GLMocoShader", Log::WARN, "uploadDataBlocks mark2 glerror %x",glGetError());\r
+//     Log::getInstance()->log("GLMocoShader", Log::WARN, "uploadDataBlocks mark2 glerror %x",glGetError());\r
        glTexSubImage2D(GL_TEXTURE_2D,0,0,height+1,\r
                        (num_blocks%BLOCK_PER_ROW)>>1,1,\r
                        GL_RGBA,GL_UNSIGNED_BYTE,\r
                        blocks);\r
 \r
-       Log::getInstance()->log("GLMocoShader", Log::WARN, "uploadDataBlocks mark2 glerror %x",glGetError());\r
+       //Log::getInstance()->log("GLMocoShader", Log::WARN, "uploadDataBlocks mark2 glerror %x",glGetError());\r
 \r
 \r
 \r
@@ -409,14 +425,14 @@ int GLMocoShader::uploadDataBlocks(short* blocks,unsigned int num_blocks, XvMCMa
 \r
 }\r
 \r
-int GLMocoShader::doMoCo(VPEOGLFrame *target)\r
+int GLMocoShader::doMoCo(VPEOGLFrame *target,VPEOGLFrame *forward,VPEOGLFrame *backward)\r
 {\r
 \r
 //     Log::getInstance()->log("GLMocoShader", Log::WARN, "doMoCo mark-2 glerror %x %x",glGetError(),frame_buf);\r
 \r
        //Log::getInstance()->log("GLMocoShader", Log::WARN, "doMoCo mark-1 glerror %x %x",glGetError(),frame_buf);\r
        glBindFramebuffer(GL_FRAMEBUFFER, frame_buf);\r
-       Log::getInstance()->log("GLMocoShader", Log::WARN, "doMoCo mark1 glerror %x %x %x",glGetError(),target->textures[0],target->textures[1]);\r
+       //Log::getInstance()->log("GLMocoShader", Log::WARN, "doMoCo mark1 glerror %x %x %x",glGetError(),target->textures[0],target->textures[1]);\r
 \r
 \r
        glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,\r
@@ -482,6 +498,26 @@ int GLMocoShader::doMoCo(VPEOGLFrame *target)
                glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP_TO_EDGE);\r
                glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP_TO_EDGE);\r
 \r
+               if (forward) {\r
+                       glActiveTexture(GL_TEXTURE1);\r
+                       glBindTexture(GL_TEXTURE_2D,forward->textures[0]);\r
+                       glUniform1i(forward_pic_loc,1);\r
+                       glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);\r
+                       glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);\r
+                       glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP_TO_EDGE);\r
+                       glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP_TO_EDGE);\r
+               }\r
+\r
+               if (backward) {\r
+                       glActiveTexture(GL_TEXTURE2);\r
+                       glBindTexture(GL_TEXTURE_2D,backward->textures[1]);\r
+                       glUniform1i(backward_pic_loc,2);\r
+                       glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);\r
+                       glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);\r
+                       glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP_TO_EDGE);\r
+                       glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP_TO_EDGE);\r
+               }\r
+\r
                glDrawElements(GL_TRIANGLE_STRIP, valid_macro_blocks*6,\r
                        GL_UNSIGNED_SHORT, NULL);\r
 \r
@@ -501,7 +537,7 @@ int GLMocoShader::doMoCo(VPEOGLFrame *target)
                //Log::getInstance()->log("GLMocoShader", Log::WARN, "doMoCo mark6 glerror %x",glGetError());\r
 \r
        //      glDrawElements(GL_TRIANGLE_STRIP,/*valid_macro_blocks*/4,GL_UNSIGNED_SHORT,0);\r
-               Log::getInstance()->log("GLMocoShader", Log::WARN, "doMoCo mark7 glerror %x %x",glGetError(),valid_macro_blocks);\r
+               //Log::getInstance()->log("GLMocoShader", Log::WARN, "doMoCo mark7 glerror %x %x",glGetError(),valid_macro_blocks);\r
                //cleanup\r
 \r
                glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,0);\r
index b37262b8313291f8fdaff007bb70ce83572df17f..bb4eba83a327ced9b2c0d728958db53763bf01b6 100755 (executable)
@@ -38,7 +38,7 @@ public:
 \r
        int uploadDataBlocks(short* blocks,unsigned int num_blocks, XvMCMacroBlock *m_blocks,unsigned int num_m_blocks);\r
 \r
-       int doMoCo(VPEOGLFrame *target);\r
+       int doMoCo(VPEOGLFrame *target,VPEOGLFrame *forward,VPEOGLFrame *backward);\r
 \r
 protected:\r
        virtual int BindAttributes();\r
@@ -48,6 +48,8 @@ protected:
        GLuint macro_block;\r
        GLint loc_pict_scale;\r
        GLint blocks_loc;\r
+       GLint forward_pic_loc;\r
+       GLint backward_pic_loc;\r
        unsigned int valid_macro_blocks;\r
 \r
 \r
index 3a8ea287069bb0c989b47660576652d004123677..4715ce97eabc7b85be1b3a4621bec45b0de2aba1 100755 (executable)
@@ -54,6 +54,11 @@ VideoVPEOGL::VideoVPEOGL()
   moco_shader=NULL;
 #endif
 
+  ogl_forward_ref_frame_num=0;
+  ogl_backward_ref_frame_num=0;
+  ogl_forward_ref_frame=NULL;
+  ogl_backward_ref_frame=NULL;
+
 #ifdef BENCHMARK_FPS
        time_in_decoder=0;
     num_frames=0;
@@ -309,9 +314,41 @@ void VideoVPEOGL::returnOGLFrame(VPEOGLFrame *frame)
        ogl_frame_mutex.Lock();
        if (frame) {
                ogl_frame_outside=false;
-               free_ogl_frames.push_back(frame);
+               //Log::getInstance()->log("Video", Log::WARN, "returnOGLRFrame mark incoming num: %d",frame->pict_num);
+               if (frame->pict_num==ogl_forward_ref_frame_num ||
+                               frame->pict_num==ogl_backward_ref_frame_num ) {
+                       recycle_ref_ogl_frames.push_back(frame);
+               } else {
+                       free_ogl_frames.push_back(frame);
+               }
+       }
+       ogl_frame_mutex.Unlock();
+}
+
+void VideoVPEOGL::recycleOGLRefFrames()
+{
+       // This function recycles frames formerly used as reference frame
+       ogl_frame_mutex.Lock();
+       list<VPEOGLFrame*> keep;
+       list<VPEOGLFrame*>::iterator itty=recycle_ref_ogl_frames.begin();
+       while (itty!=recycle_ref_ogl_frames.end()) {
+               Log::getInstance()->log("Video", Log::WARN, "recycleOGLRefFrame mark3");
+               if ((*itty)->pict_num==ogl_forward_ref_frame_num
+                               || (*itty)->pict_num==ogl_backward_ref_frame_num)
+               {
+                       // ok we have to keep this
+                       keep.push_back(*itty);
+               } else {
+                       free_ogl_frames.push_back(*itty);
+               }
+               itty++;
        }
+       recycle_ref_ogl_frames.clear();
+       recycle_ref_ogl_frames=keep;
+
        ogl_frame_mutex.Unlock();
+
+
 }
 
 void VideoVPEOGL::threadMethod()
@@ -322,129 +359,232 @@ void VideoVPEOGL::threadMethod()
        }
        while (1) {
                bool sleep=true;
+               bool upload=false;
+               bool view=false;
 #ifdef VPE_LIBAV_SUPPORT
                dec_frame_libav_mutex.Lock();
-               if (dec_frame_libav_upload_pending.size()>0) {
-                       dec_frame_libav_uploading=dec_frame_libav_upload_pending.front();
-                       dec_frame_libav_upload_pending.pop_front();
-                       if (dec_frame_libav_upload_pending.size()>0) sleep=false;
+
+
+               if (dec_frame_libav_upload_and_view_pending.size()>0  ) {
+                       bool blocked=false;
+                       dec_frame_libav_uploading=dec_frame_libav_upload_and_view_pending.front();
+               //      Log::getInstance()->log("Video", Log::WARN, "threadMethod u and view %d",((VPE_FrameBuf*)dec_frame_libav_uploading->base[0])->pict_num);
+               //      if (dec_frame_libav_upload_only_pending.size()>0) Log::getInstance()->log("Video", Log::WARN, "threadMethod u and view %d",
+               //                      ((VPE_FrameBuf*)dec_frame_libav_upload_only_pending.front()->base[0])->pict_num);
+                       list<AVFrame*>::iterator itty=dec_frame_libav_upload_only_pending.begin();
+                       while (itty!=dec_frame_libav_upload_only_pending.end())
+                       {
+                               if (*itty==dec_frame_libav_uploading) {
+                                       blocked=true;
+                                       break;
+                               }
+                               itty++;
+                       }
+                       if (!blocked) { // this assures that no frame without an upload is pushed out to rendering
+                               dec_frame_libav_upload_and_view_pending.pop_front();
+                               upload=view=true;
+                               if (decoding_mode!=VPE_NO_XVMC) upload=false;
+                       } else {
+                               dec_frame_libav_uploading=NULL;
+                       }
+               }
+
+               if (!view && dec_frame_libav_upload_only_pending.size()>0) {
+
+                       dec_frame_libav_uploading=dec_frame_libav_upload_only_pending.front();
+                       //Log::getInstance()->log("Video", Log::WARN, "threadMethod u  %d",((VPE_FrameBuf*)dec_frame_libav_uploading->base[0])->pict_num);
+                       dec_frame_libav_upload_only_pending.pop_front();
+                       view=false;
+                       upload=true;
                }
+
+
+               if (dec_frame_libav_upload_and_view_pending.size()>0
+                       ||dec_frame_libav_upload_only_pending.size()>0) sleep=false;
+
                dec_frame_libav_mutex.Unlock();
+
+
                if (dec_frame_libav_uploading) {
-                       int width,height,pixfmt;
-                        //First get a free ogl image
-                       VPEOGLFrame* out_frame=NULL;
-                       while (!out_frame) {
-                               ogl_frame_mutex.Lock();
-                               if (all_ogl_frames.size()==0) {
-                                       ogl_frame_mutex.Unlock(); break;
-                               }
 
-                               if (free_ogl_frames.size()>0) {
-                                       width=libavwidth;
-                                       height=libavheight;
-                                       pixfmt=libavpixfmt;
-                                       out_frame=free_ogl_frames.front();
-                                       free_ogl_frames.pop_front();
-                               } else MILLISLEEP(2);
-                               ogl_frame_mutex.Unlock();
-                       }
-                       bool failed=false;
-                       if (out_frame) {
-                               if (out_frame->textures[0]==0 || out_frame->width!=width ||
-                                               out_frame->height!=height || out_frame->stride!=dec_frame_libav_uploading->linesize[0]) {
-                                       if (out_frame->textures[0]!=0) {
-                                               glDeleteTextures(1,&out_frame->textures[0]);
-                                               out_frame->textures[0]=0;
-                                       }
-                                       if (out_frame->textures[1]!=0) {
-                                               glDeleteTextures(1,&out_frame->textures[1]);
-                                               out_frame->textures[1]=0;
-                                       }
-                                       if (out_frame->textures[2]!=0) {
-                                               glDeleteTextures(1,&out_frame->textures[2]);
-                                               out_frame->textures[2]=0;
+                       if (upload) {
+                               int width,height,pixfmt;
+                               //First get a free ogl image
+                               VPEOGLFrame* out_frame=NULL;
+                               while (!out_frame) {
+                                       ogl_frame_mutex.Lock();
+                               //      Log::getInstance()->log("Video", Log::WARN, "threadMethod mark upload 1a %d %d %d %d %d",all_ogl_frames.size(),free_ogl_frames.size(),
+                                       //                                                              recycle_ref_ogl_frames.size(),ready_ogl_frames.size(),ogl_frame_outside);
+                                       if (all_ogl_frames.size()==0) {
+                                               ogl_frame_mutex.Unlock(); break;
                                        }
 
-                                       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)) failed=true; //We use a YUV 444 texture in this case
-                                               // the shaders are easier to implement
-                                       }
+                                       if (free_ogl_frames.size()>0) {
+                                               width=libavwidth;
+                                               height=libavheight;
+                                               pixfmt=libavpixfmt;
+                                               out_frame=free_ogl_frames.front();
+                                               free_ogl_frames.pop_front();
+                                       } else MILLISLEEP(2);
+                                       ogl_frame_mutex.Unlock();
                                }
-                               if (!failed) {
-                                       //up to now only YUV data, this is for reference only, since the pi is too slow.
-                                       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
-                                                       }
-                                                       moco_shader->doMoCo(out_frame);
+                               bool failed=false;
+                               if (out_frame) {
+                                       if (out_frame->textures[0]==0 || out_frame->width!=width ||
+                                                       out_frame->height!=height || out_frame->stride!=dec_frame_libav_uploading->linesize[0]) {
+                                               if (out_frame->textures[0]!=0) {
+                                                       glDeleteTextures(1,&out_frame->textures[0]);
+                                                       out_frame->textures[0]=0;
+                                               }
+                                               if (out_frame->textures[1]!=0) {
+                                                       glDeleteTextures(1,&out_frame->textures[1]);
+                                                       out_frame->textures[1]=0;
+                                               }
+                                               if (out_frame->textures[2]!=0) {
+                                                       glDeleteTextures(1,&out_frame->textures[2]);
+                                                       out_frame->textures[2]=0;
+                                               }
 
-                                               // Excute motion compensation
+                                               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)) failed=true; //We use a YUV 444 texture in this case
+                                                       // the shaders are easier to implement
                                                }
                                        }
+                                       ((VPE_FrameBuf*)dec_frame_libav_uploading->base[0])->ogl_ref=out_frame;
+                                       if (!failed) {
+                                               //up to now only YUV data, this is for reference only, since the pi is too slow.
+                                               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 );
+                                                               Log::getInstance()->log("Video", Log::WARN, "Pictnum %d Forward %d Backward %d pict_type%d",pix_fmt->p_surface,
+                                                                                                                       pix_fmt->p_past_surface,pix_fmt->p_future_surface,dec_frame_libav_uploading->pict_type);
+
+                                                               if (((int)pix_fmt->p_future_surface)!=0 && ogl_forward_ref_frame_num!=((int)pix_fmt->p_future_surface))
+                                                               {
+                                                                       //Now determine the frame, that fits
+                                                                       ogl_frame_mutex.Lock();
+                                                                       for (int i=0;i<all_ogl_frames.size();i++) {
+                                                                               if (all_ogl_frames[i]->pict_num==((int)pix_fmt->p_future_surface))
+                                                                               {
+                                                                                       ogl_backward_ref_frame=ogl_forward_ref_frame; //mpeg life time axioms
+                                                                                       ogl_backward_ref_frame_num=ogl_forward_ref_frame_num;
+                                                                                       ogl_forward_ref_frame=all_ogl_frames[i];
+                                                                                       ogl_forward_ref_frame_num=(int)pix_fmt->p_future_surface;
+                                                                                       break;
+                                                                               }
+                                                                       }
+
+                                                                       ogl_frame_mutex.Unlock();
+                                                                       recycleOGLRefFrames(); //needed for recycling of reference frames
+                                                               }
+
+
+                                                               if (((int)pix_fmt->p_past_surface)!=0 && ogl_backward_ref_frame_num!=((int)pix_fmt->p_past_surface))
+                                                               {
+                                                                       //Now determine the frame, that fits
+                                                                       ogl_frame_mutex.Lock();
+                                                                       for (int i=0;i<all_ogl_frames.size();i++) {
+                                                                               if (all_ogl_frames[i]->pict_num==((int)pix_fmt->p_past_surface))
+                                                                               {
+                                                                                       ogl_backward_ref_frame=all_ogl_frames[i];
+                                                                                       ogl_backward_ref_frame_num=(int)pix_fmt->p_past_surface; // This should not happen, or for DMV, who knows
+                                                                                       break;
+                                                                               }
+                                                                       }
+
+                                                                       ogl_frame_mutex.Unlock();
+                                                                       recycleOGLRefFrames(); //needed for recycling of reference frames
+
+                                                               }
+
+                                                               if (decoding_mode==VPE_XVMC_MOCOMP)
+                                                               {
+                                                                       //DCT Blocks upload
+
+                                                               } else {
+                                                                       //DCT Blocks upload
+                                                               }
+                                                               out_frame->pict_num=((VPE_FrameBuf*)dec_frame_libav_uploading->base[0])->pict_num;
+
+                                                               moco_shader->doMoCo(out_frame,ogl_forward_ref_frame,ogl_backward_ref_frame);
+
+                                                               // Excute motion compensation
+                                                       }
+                                               }
 
 
-                                       releaseFrameBufUpload((VPE_FrameBuf*)dec_frame_libav_uploading->base[0]);
 
+                                       }
+                               }
 
-                                       ogl_frame_mutex.Lock();
-                                       ready_ogl_frames.push_back(out_frame);
-                                       ogl_frame_mutex.Unlock();
-                                       ((OsdOpenGL*)Osd::getInstance())->AdviseAboutNewFrame(); //Tell him, that we have a frame waiting
+                       }
 
-                               }
+
+
+                       if (view) {
+
+                               //Log::getInstance()->log("Video", Log::WARN, "threadMethod mark view");
+                               VPEOGLFrame* out_frame=((VPE_FrameBuf*)dec_frame_libav_uploading->base[0])->ogl_ref;
+                               xvmc_pix_fmt * pix_fmt=(xvmc_pix_fmt *)dec_frame_libav_uploading->data[2];
+                               Log::getInstance()->log("Video", Log::WARN, "View Pictnum %d Forward %d Backward %d pict_type%d",pix_fmt->p_surface,
+                                                                                                                       pix_fmt->p_past_surface,pix_fmt->p_future_surface,dec_frame_libav_uploading->pict_type);
+
+                               releaseFrameBufUpload((VPE_FrameBuf*)dec_frame_libav_uploading->base[0]);
+                               ogl_frame_mutex.Lock();
+                               ready_ogl_frames.push_back(out_frame);
+                               ogl_frame_mutex.Unlock();
+                               ((OsdOpenGL*)Osd::getInstance())->AdviseAboutNewFrame(); //Tell him, that we have a frame waiting
 
                                dec_frame_libav_mutex.Lock();
                                dec_frame_libav_free.push_back(dec_frame_libav_uploading);
-                               dec_frame_libav_uploading=NULL;
                                dec_frame_libav_mutex.Unlock();
+                       }
 
 
+                       dec_frame_libav_mutex.Lock();
+                       dec_frame_libav_uploading=NULL;
 
+                       if (dec_frame_libav_upload_and_view_pending.size()>0
+                                       ||dec_frame_libav_upload_only_pending.size()>0) sleep=false;
 
-                       }
-
+                       dec_frame_libav_mutex.Unlock();
 
 
 
                }
 #endif
 
-               if (sleep) threadWaitForSignal();
+               if (sleep) {
+                       threadWaitForSignal();
+                       Log::getInstance()->log("Video", Log::WARN, "threadMethod signalled");
+               }
                threadCheckExit();
        }
 
@@ -1407,6 +1547,16 @@ enum PixelFormat VideoVPEOGL::get_format_libav(struct AVCodecContext *s, const e
        return ret_pix;
 }
 
+// we use this function to push the data to ogl out before hand, this is only useful for xvmc
+void VideoVPEOGL::draw_horiz_band_libav(struct AVCodecContext *s, const AVFrame *src, int offset[4], int y, int type, int height)
+{
+       if ((y+height)==src->height) {
+               //Log::getInstance()->log("Video", Log::NOTICE, "draw_horiz_band %d %d %d %d!",y,type,height,((xvmc_pix_fmt *)src->data[2])->p_surface);
+               ((VideoVPEOGL*)Video::getInstance())->add_dec_frame_upload_only(s,src);
+       }
+
+}
+
 int VideoVPEOGL::reget_buffer_libav(struct AVCodecContext *c, AVFrame *pic)
 {
        Log::getInstance()->log("Video", Log::ERR, "Buffer reusing! Should not happen!Not Implemented!");
@@ -1567,6 +1717,7 @@ int VideoVPEOGL::AllocateCodecsLibav()
                if (decoding_mode==VPE_XVMC_MOCOMP) mpeg2codec_context_libav->pix_fmt=PIX_FMT_XVMC_MPEG2_MC;
                else mpeg2codec_context_libav->pix_fmt=PIX_FMT_XVMC_MPEG2_IDCT;
                mpeg2codec_context_libav->get_format=get_format_libav;
+               mpeg2codec_context_libav->draw_horiz_band=draw_horiz_band_libav;
 
        }
        mpeg2codec_context_libav->get_buffer=get_buffer_libav;
@@ -1574,6 +1725,7 @@ int VideoVPEOGL::AllocateCodecsLibav()
        mpeg2codec_context_libav->release_buffer=release_buffer_libav;
 
 
+
        int avc_ret=avcodec_open(mpeg2codec_context_libav, mpeg2codec_libav);
        if (avc_ret<0) {
                Log::getInstance()->log("Video", Log::DEBUG, "Opening libav codec  failed ");
@@ -1598,7 +1750,7 @@ int VideoVPEOGL::AllocateCodecsLibav()
 
        ogl_frame_mutex.Lock();
        //Allocate texture structs, since we do not know the sizes, we do not allocate the textures yet
-       for (int i=0;i<3;i++) {
+       for (int i=0;i<5;i++) {
                VPEOGLFrame *new_frame=(VPEOGLFrame *)malloc(sizeof(VPEOGLFrame));
                new_frame->type=1; //1 = YUV, 2 RGB
                new_frame->textures[0]=0;
@@ -1632,7 +1784,8 @@ int VideoVPEOGL::DeAllocateCodecsLibav()
        libav_running=false;
        Log::getInstance()->log("Video", Log::NOTICE, "DeAllocateCodecslibav");
        dec_frame_libav_mutex.Lock();
-       dec_frame_libav_upload_pending.clear();
+       dec_frame_libav_upload_and_view_pending.clear();
+       dec_frame_libav_upload_only_pending.clear();
        dec_frame_libav_free.clear();
        dec_frame_libav_mutex.Unlock();
        while (dec_frame_libav_uploading) {
@@ -1679,6 +1832,12 @@ int VideoVPEOGL::DeAllocateCodecsLibav()
        all_ogl_frames.clear();
        free_ogl_frames.clear();
        ready_ogl_frames.clear();
+       recycle_ref_ogl_frames.clear();
+       ogl_forward_ref_frame_num=0;
+       ogl_backward_ref_frame_num=0;
+       ogl_forward_ref_frame=NULL;
+       ogl_backward_ref_frame=NULL;
+
        ogl_frame_mutex.Unlock();
        ((OsdOpenGL*)Osd::getInstance())->EndPainting();
 
@@ -1820,6 +1979,18 @@ void VideoVPEOGL::releaseFrameBufUpload(VPE_FrameBuf* buf)
        vpe_framebuf_mutex.Unlock();
 }
 
+void VideoVPEOGL::add_dec_frame_upload_only(struct AVCodecContext *s,const AVFrame* data)
+{
+       dec_frame_libav_mutex.Lock();
+       libavwidth=s->width;
+       libavheight=s->height;
+       libavpixfmt=s->pix_fmt;
+       Log::getInstance()->log("Video", Log::DEBUG, "add_dec Frame info %d %d %d %d",libavwidth,libavheight,libavpixfmt,((VPE_FrameBuf*)data->base[0])->pict_num);
+
+       dec_frame_libav_upload_only_pending.push_back((AVFrame*)data); // we are only uploading
+       dec_frame_libav_mutex.Unlock();
+       threadSignal();
+}
 
 
 
@@ -2190,7 +2361,7 @@ int VideoVPEOGL::DecodePacketlibav()
                //      Log::getInstance()->log("Video", Log::DEBUG, "Frame info %d %d %d",libavwidth,libavheight,libavpixfmt);
 
 
-                       dec_frame_libav_upload_pending.push_back(dec_frame_libav_decoding);
+                       dec_frame_libav_upload_and_view_pending.push_back(dec_frame_libav_decoding);
                        dec_frame_libav_decoding=NULL;
                        if (dec_frame_libav_free.size()>0) {
                                dec_frame_libav_decoding=dec_frame_libav_free.front();
@@ -2201,6 +2372,7 @@ int VideoVPEOGL::DecodePacketlibav()
                        } else {
                                libav_hastime=false;
                                dec_frame_libav_mutex.Unlock();
+                               threadSignal();
                                // No free buffers
                                return 0;
                        }
index c09876221caf62b4ba4a7f68a30cdf47b67f2b9b..3d72ae75696ce71bbc92901f5f441c759fd58644 100755 (executable)
@@ -80,25 +80,24 @@ extern "C" {
 }\r
 #include "glmocoshader.h"\r
 \r
+struct VPEOGLFrame;\r
+\r
 struct VPE_FrameBuf\r
 { //This is a frame bulibaver, nothing fancy just plain memory\r
        void *data[4];\r
        unsigned int size[4];\r
        unsigned int pict_num;\r
+       VPEOGLFrame *ogl_ref;\r
 };\r
 \r
 #endif\r
 \r
-\r
-\r
-\r
-\r
-\r
 struct VPEOGLFrame {\r
        int type; //1 = YUV400, 2 YUV444\r
        GLuint textures[3]; // 0=RGB or Y, 1=U 2=V\r
        int width, height;\r
        int stride;\r
+       unsigned int pict_num;\r
 /*\r
 #ifdef VPE_OMX_SUPPORT\r
        //OMX\r
@@ -107,6 +106,11 @@ struct VPEOGLFrame {
 #endif*/\r
 };\r
 \r
+\r
+\r
+\r
+\r
+\r
 class VideoVPEOGL : public Video, public Thread_TYPE\r
 {\r
   public:\r
@@ -155,6 +159,7 @@ class VideoVPEOGL : public Video, public Thread_TYPE
 \r
        VPEOGLFrame *getReadyOGLFrame();\r
        void returnOGLFrame(VPEOGLFrame *frame);\r
+       void recycleOGLRefFrames();\r
 \r
 \r
 \r
@@ -263,10 +268,13 @@ class VideoVPEOGL : public Video, public Thread_TYPE
        AVCodecContext *mpeg2codec_context_libav;\r
        vector<AVFrame*> dec_frame_libav_all;\r
        list<AVFrame*> dec_frame_libav_free;\r
-       list<AVFrame*> dec_frame_libav_upload_pending;\r
+       list<AVFrame*> dec_frame_libav_upload_and_view_pending;\r
+       list<AVFrame*> dec_frame_libav_upload_only_pending;\r
        AVFrame* dec_frame_libav_uploading;\r
        AVFrame* dec_frame_libav_decoding;\r
 \r
+       void add_dec_frame_upload_only(struct AVCodecContext *s,const AVFrame* data);\r
+\r
        vector<VPE_FrameBuf*> all_frame_bufs;\r
        list<VPE_FrameBuf*> free_frame_bufs;\r
        list<VPE_FrameBuf*> locked_libav_frame_buf;\r
@@ -299,6 +307,8 @@ class VideoVPEOGL : public Video, public Thread_TYPE
        static int reget_buffer_libav(struct AVCodecContext *c, AVFrame *pic);\r
        static void release_buffer_libav(struct AVCodecContext *c, AVFrame *pic);\r
 \r
+       static void draw_horiz_band_libav(struct AVCodecContext *s, const AVFrame *src, int offset[4], int y, int type, int height);\r
+\r
        bool libav_running;\r
        bool libav_hastime; // signals if a pts is now\r
        long long libav_time;\r
@@ -311,7 +321,13 @@ class VideoVPEOGL : public Video, public Thread_TYPE
 \r
        vector<VPEOGLFrame*> all_ogl_frames;\r
        list<VPEOGLFrame*> free_ogl_frames;\r
+       list<VPEOGLFrame*> recycle_ref_ogl_frames;\r
        list<VPEOGLFrame*> ready_ogl_frames;\r
+       int ogl_forward_ref_frame_num;\r
+       int ogl_backward_ref_frame_num;\r
+       VPEOGLFrame* ogl_forward_ref_frame;\r
+       VPEOGLFrame* ogl_backward_ref_frame;\r
+\r
        bool ogl_frame_outside;\r
        Mutex ogl_frame_mutex;\r
 \r