From 2b4da07c4e4c684ecf70969762dc3d2a99410292 Mon Sep 17 00:00:00 2001 From: Marten Richter Date: Sun, 24 Jun 2012 19:49:41 +0200 Subject: [PATCH] Add handling reference frame pointers --- glmocoshader.cc | 50 ++++++- glmocoshader.h | 4 +- videovpeogl.cc | 364 +++++++++++++++++++++++++++++++++++------------- videovpeogl.h | 28 +++- 4 files changed, 336 insertions(+), 110 deletions(-) diff --git a/glmocoshader.cc b/glmocoshader.cc index 23fcc61..a674e0f 100755 --- a/glmocoshader.cc +++ b/glmocoshader.cc @@ -39,6 +39,8 @@ const GLchar moco_vertex_shader[] = "varying vec2 out_block_edge;\n" "varying vec4 out_block_types;\n" + "varying float out_unsupported;\n" + "const float one=1.0;\n" "const float c1024=1024.0;\n" "const float c32=32.0;\n" @@ -91,6 +93,12 @@ const GLchar moco_vertex_shader[] = " out_yblockpos_y-=sign(fmod_cbp_y-one)*c1024;\n" " out_uvblockpos_xy.zw-=sign(fmod_cbp_uv-one)*c1024;\n" + // " if (block_types.y!=0.) {\n" + // " out_unsupported=1.;\n" + // "} else {\n" + // " out_unsupported=0.;\n" + // "}\n" + " out_block_edge=block_edge;\n" " out_block_types=block_types;\n" @@ -105,11 +113,14 @@ const GLchar moco_vertex_shader[] = const GLchar moco_frag_shader[] = "precision mediump float;\n" "uniform sampler2D blocks;\n" + "uniform sampler2D forward_pic;\n" + "uniform sampler2D backward_pic;\n" "varying vec4 out_yblockpos_x;\n" "varying vec4 out_yblockpos_y;\n" "varying vec4 out_uvblockpos_xy;\n" "varying vec2 out_block_edge;\n" - "varying vec4 out_block_types;\n" + "varying vec4 out_block_types;\n" // change this we need so far only the dct type + "varying float out_unsupported;\n" "const float halfst=0.5;\n" "const float ctwo=2.0;\n" @@ -205,6 +216,9 @@ const GLchar moco_frag_shader[] = " ypos_temp2.xy=ypos_temp1.xy;\n" " }\n" " gl_FragColor.b=unpack_short(ypos_temp2.rg);\n" + " if (out_unsupported!=0.) {\n" + " gl_FragColor.rgb=vec3(cone,cone,0.0);\n" + "}\n" //" ypos_temp2=mix(ypos_temp1.rg,ypos_temp1.ba,step(c1over2047,mod(ypos_temp2.x,c1over1023)));\n" //activate this @@ -243,6 +257,8 @@ int GLMocoShader::init() { } loc_pict_scale = glGetUniformLocation(shad_program, "pict_scale"); blocks_loc = glGetUniformLocation(shad_program, "blocks"); + forward_pic_loc = glGetUniformLocation(shad_program, "forward_pic"); + backward_pic_loc = glGetUniformLocation(shad_program, "backward_pic"); // frame_sampler_locY = glGetUniformLocation(shad_program, "textureY"); // Log::getInstance()->log("OSD", Log::WARN, "uniform location %x %x",frame_sampler_locY,glGetError()); @@ -327,18 +343,18 @@ int GLMocoShader::uploadDataBlocks(short* blocks,unsigned int num_blocks, XvMCMa - Log::getInstance()->log("GLMocoShader", Log::WARN, "uploadDataBlocks mark1 glerror %x %d",glGetError(),height); +// Log::getInstance()->log("GLMocoShader", Log::WARN, "uploadDataBlocks mark1 glerror %x %d",glGetError(),height); glTexSubImage2D(GL_TEXTURE_2D,0,0,0, BLOCK_TEXTURE_WIDTH>>1,height, GL_RGBA,GL_UNSIGNED_BYTE, blocks); - Log::getInstance()->log("GLMocoShader", Log::WARN, "uploadDataBlocks mark2 glerror %x",glGetError()); +// Log::getInstance()->log("GLMocoShader", Log::WARN, "uploadDataBlocks mark2 glerror %x",glGetError()); glTexSubImage2D(GL_TEXTURE_2D,0,0,height+1, (num_blocks%BLOCK_PER_ROW)>>1,1, GL_RGBA,GL_UNSIGNED_BYTE, blocks); - Log::getInstance()->log("GLMocoShader", Log::WARN, "uploadDataBlocks mark2 glerror %x",glGetError()); + //Log::getInstance()->log("GLMocoShader", Log::WARN, "uploadDataBlocks mark2 glerror %x",glGetError()); @@ -409,14 +425,14 @@ int GLMocoShader::uploadDataBlocks(short* blocks,unsigned int num_blocks, XvMCMa } -int GLMocoShader::doMoCo(VPEOGLFrame *target) +int GLMocoShader::doMoCo(VPEOGLFrame *target,VPEOGLFrame *forward,VPEOGLFrame *backward) { // Log::getInstance()->log("GLMocoShader", Log::WARN, "doMoCo mark-2 glerror %x %x",glGetError(),frame_buf); //Log::getInstance()->log("GLMocoShader", Log::WARN, "doMoCo mark-1 glerror %x %x",glGetError(),frame_buf); glBindFramebuffer(GL_FRAMEBUFFER, frame_buf); - Log::getInstance()->log("GLMocoShader", Log::WARN, "doMoCo mark1 glerror %x %x %x",glGetError(),target->textures[0],target->textures[1]); + //Log::getInstance()->log("GLMocoShader", Log::WARN, "doMoCo mark1 glerror %x %x %x",glGetError(),target->textures[0],target->textures[1]); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, @@ -482,6 +498,26 @@ int GLMocoShader::doMoCo(VPEOGLFrame *target) glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP_TO_EDGE); + if (forward) { + glActiveTexture(GL_TEXTURE1); + glBindTexture(GL_TEXTURE_2D,forward->textures[0]); + glUniform1i(forward_pic_loc,1); + glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP_TO_EDGE); + } + + if (backward) { + glActiveTexture(GL_TEXTURE2); + glBindTexture(GL_TEXTURE_2D,backward->textures[1]); + glUniform1i(backward_pic_loc,2); + glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP_TO_EDGE); + } + glDrawElements(GL_TRIANGLE_STRIP, valid_macro_blocks*6, GL_UNSIGNED_SHORT, NULL); @@ -501,7 +537,7 @@ int GLMocoShader::doMoCo(VPEOGLFrame *target) //Log::getInstance()->log("GLMocoShader", Log::WARN, "doMoCo mark6 glerror %x",glGetError()); // glDrawElements(GL_TRIANGLE_STRIP,/*valid_macro_blocks*/4,GL_UNSIGNED_SHORT,0); - Log::getInstance()->log("GLMocoShader", Log::WARN, "doMoCo mark7 glerror %x %x",glGetError(),valid_macro_blocks); + //Log::getInstance()->log("GLMocoShader", Log::WARN, "doMoCo mark7 glerror %x %x",glGetError(),valid_macro_blocks); //cleanup glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,0); diff --git a/glmocoshader.h b/glmocoshader.h index b37262b..bb4eba8 100755 --- a/glmocoshader.h +++ b/glmocoshader.h @@ -38,7 +38,7 @@ public: int uploadDataBlocks(short* blocks,unsigned int num_blocks, XvMCMacroBlock *m_blocks,unsigned int num_m_blocks); - int doMoCo(VPEOGLFrame *target); + int doMoCo(VPEOGLFrame *target,VPEOGLFrame *forward,VPEOGLFrame *backward); protected: virtual int BindAttributes(); @@ -48,6 +48,8 @@ protected: GLuint macro_block; GLint loc_pict_scale; GLint blocks_loc; + GLint forward_pic_loc; + GLint backward_pic_loc; unsigned int valid_macro_blocks; diff --git a/videovpeogl.cc b/videovpeogl.cc index 3a8ea28..4715ce9 100755 --- a/videovpeogl.cc +++ b/videovpeogl.cc @@ -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 keep; + list::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::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;ipict_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;ipict_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; } diff --git a/videovpeogl.h b/videovpeogl.h index c098762..3d72ae7 100755 --- a/videovpeogl.h +++ b/videovpeogl.h @@ -80,25 +80,24 @@ extern "C" { } #include "glmocoshader.h" +struct VPEOGLFrame; + struct VPE_FrameBuf { //This is a frame bulibaver, nothing fancy just plain memory void *data[4]; unsigned int size[4]; unsigned int pict_num; + VPEOGLFrame *ogl_ref; }; #endif - - - - - struct VPEOGLFrame { int type; //1 = YUV400, 2 YUV444 GLuint textures[3]; // 0=RGB or Y, 1=U 2=V int width, height; int stride; + unsigned int pict_num; /* #ifdef VPE_OMX_SUPPORT //OMX @@ -107,6 +106,11 @@ struct VPEOGLFrame { #endif*/ }; + + + + + class VideoVPEOGL : public Video, public Thread_TYPE { public: @@ -155,6 +159,7 @@ class VideoVPEOGL : public Video, public Thread_TYPE VPEOGLFrame *getReadyOGLFrame(); void returnOGLFrame(VPEOGLFrame *frame); + void recycleOGLRefFrames(); @@ -263,10 +268,13 @@ class VideoVPEOGL : public Video, public Thread_TYPE AVCodecContext *mpeg2codec_context_libav; vector dec_frame_libav_all; list dec_frame_libav_free; - list dec_frame_libav_upload_pending; + list dec_frame_libav_upload_and_view_pending; + list dec_frame_libav_upload_only_pending; AVFrame* dec_frame_libav_uploading; AVFrame* dec_frame_libav_decoding; + void add_dec_frame_upload_only(struct AVCodecContext *s,const AVFrame* data); + vector all_frame_bufs; list free_frame_bufs; list locked_libav_frame_buf; @@ -299,6 +307,8 @@ class VideoVPEOGL : public Video, public Thread_TYPE static int reget_buffer_libav(struct AVCodecContext *c, AVFrame *pic); static void release_buffer_libav(struct AVCodecContext *c, AVFrame *pic); + static void draw_horiz_band_libav(struct AVCodecContext *s, const AVFrame *src, int offset[4], int y, int type, int height); + bool libav_running; bool libav_hastime; // signals if a pts is now long long libav_time; @@ -311,7 +321,13 @@ class VideoVPEOGL : public Video, public Thread_TYPE vector all_ogl_frames; list free_ogl_frames; + list recycle_ref_ogl_frames; list ready_ogl_frames; + int ogl_forward_ref_frame_num; + int ogl_backward_ref_frame_num; + VPEOGLFrame* ogl_forward_ref_frame; + VPEOGLFrame* ogl_backward_ref_frame; + bool ogl_frame_outside; Mutex ogl_frame_mutex; -- 2.39.2