]> git.vomp.tv Git - vompclient-marten.git/commitdiff
Prepare libav Buffer handling for XvMc
authorMarten Richter <marten.richter@freenet.de>
Sun, 10 Jun 2012 11:26:53 +0000 (13:26 +0200)
committerMarten Richter <marten.richter@freenet.de>
Sun, 10 Jun 2012 11:26:53 +0000 (13:26 +0200)
defines.h
osdopengl.cc
videovpeogl.cc
videovpeogl.h

index c04928eb3eaca87ab2e793ead90e10e04394a0dd..a46a06ddfd479bc25819434a91f3d327ed9b1168 100755 (executable)
--- a/defines.h
+++ b/defines.h
@@ -104,7 +104,7 @@ long long getTimeMS();
    #define VPE_OMX_VIDEO_DEINTERLACE "OMX.broadcom.image_fx"\r
    #define VPE_OMX_CLOCK "OMX.broadcom.clock"\r
 \r
-   #define  VPE_FFMPEG_SUPPORT\r
+   #define  VPE_LIBAV_SUPPORT\r
 \r
 #endif\r
 #ifdef VOMP_PLATTFORM_MVP\r
index 17b46d34e9934ae60ffa1bf481a2716aa8ab4127..d83557015e754037134908a3027e222645be73cf 100755 (executable)
@@ -297,6 +297,7 @@ int OsdOpenGL::init(void* device)
 \r
 \r
   glClearColor(0.0f,0.0f,0.0f,1.f);\r
+  eglSwapInterval(egl_display, 1 );\r
 \r
   eglMakeCurrent(egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT );\r
 \r
index d5bc781bd25331a50b0dd91ab971185323626e61..77d5bcbb7ce21085ec8b364b331f0cc0930f4ec3 100755 (executable)
@@ -41,12 +41,14 @@ VideoVPEOGL::VideoVPEOGL()
   omx_h264=omx_mpeg2=true;
 #endif
 
-#ifdef VPE_FFMPEG_SUPPORT
-  mpeg2codec_context_ff=NULL;
-  ffmpeg_running=false;
-  dec_frame_ff_uploading=NULL;
-  dec_frame_ff_decoding=NULL;
+#ifdef VPE_LIBAV_SUPPORT
+  mpeg2codec_context_libav=NULL;
+  libav_running=false;
+  dec_frame_libav_uploading=NULL;
+  dec_frame_libav_decoding=NULL;
   ogl_frame_outside=false;
+  decoding_mode=VPE_NO_XVMC;
+  //decoding_mode=VPE_XVMC_MOCOMP;
 #endif
 
 #ifdef BENCHMARK_FPS
@@ -80,7 +82,7 @@ int VideoVPEOGL::init(UCHAR tformat)
 /*  if (format == PAL) setLetterboxBorder("38");
   else setLetterboxBorder("31");*/
 
-  /* new stuff */
+  /* new stulibav */
 
 
 
@@ -142,13 +144,16 @@ int VideoVPEOGL::initUsingOSDObjects()
 
 #endif
 
-#ifdef VPE_FFMPEG_SUPPORT
+#ifdef VPE_LIBAV_SUPPORT
 
        av_register_all();
-       mpeg2codec_ff=avcodec_find_decoder(CODEC_ID_MPEG2VIDEO);
-       //mpeg2codec_ff=avcodec_find_decoder(CODEC_ID_MPEG2VIDEO_XVMC);
-       if (mpeg2codec_ff==NULL) {
-               Log::getInstance()->log("Video", Log::DEBUG, "Find ffmpeg mpeg2 codec failed");
+       if (decoding_mode==VPE_NO_XVMC) {
+               mpeg2codec_libav=avcodec_find_decoder(CODEC_ID_MPEG2VIDEO);
+       } else {
+               mpeg2codec_libav=avcodec_find_decoder(CODEC_ID_MPEG2VIDEO_XVMC);
+       }
+       if (mpeg2codec_libav==NULL) {
+               Log::getInstance()->log("Video", Log::DEBUG, "Find libav mpeg2 codec failed");
                return 0;
        }
 
@@ -230,8 +235,8 @@ int VideoVPEOGL::shutdown()
   DeAllocateCodecsOMX();
   OMX_Deinit();
 #endif
-#ifdef VPE_FFMPEG_SUPPORT
-  DeAllocateCodecsFFMPEG();
+#ifdef VPE_LIBAV_SUPPORT
+  DeAllocateCodecsLibav();
 #endif
   eglDestroyContext(egl_display,egl_context);
 //  close(fdVideo);
@@ -293,15 +298,15 @@ void VideoVPEOGL::threadMethod()
        }
        while (1) {
                bool sleep=true;
-#ifdef VPE_FFMPEG_SUPPORT
-               dec_frame_ff_mutex.Lock();
-               if (dec_frame_ff_upload_pending.size()>0) {
-                       dec_frame_ff_uploading=dec_frame_ff_upload_pending.front();
-                       dec_frame_ff_upload_pending.pop_front();
-                       if (dec_frame_ff_upload_pending.size()>0) sleep=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;
                }
-               dec_frame_ff_mutex.Unlock();
-               if (dec_frame_ff_uploading) {
+               dec_frame_libav_mutex.Unlock();
+               if (dec_frame_libav_uploading) {
                        int width,height,pixfmt;
                         //First get a free ogl image
                        VPEOGLFrame* out_frame=NULL;
@@ -312,9 +317,9 @@ void VideoVPEOGL::threadMethod()
                                }
 
                                if (free_ogl_frames.size()>0) {
-                                       width=ffwidth;
-                                       height=ffheight;
-                                       pixfmt=ffpixfmt;
+                                       width=libavwidth;
+                                       height=libavheight;
+                                       pixfmt=libavpixfmt;
                                        out_frame=free_ogl_frames.front();
                                        free_ogl_frames.pop_front();
                                } else MILLISLEEP(2);
@@ -323,20 +328,20 @@ void VideoVPEOGL::threadMethod()
                        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_ff_uploading->linesize[0]) {
-                                       if (out_frame->textures[0]==0) {
+                                               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) {
+                                       if (out_frame->textures[1]!=0) {
                                                glDeleteTextures(1,&out_frame->textures[1]);
                                                out_frame->textures[1]=0;
                                        }
-                                       if (out_frame->textures[2]==0) {
+                                       if (out_frame->textures[2]!=0) {
                                                glDeleteTextures(1,&out_frame->textures[2]);
                                                out_frame->textures[2]=0;
                                        }
-                                       if (!AllocateYUVOglTexture(out_frame,width,height,dec_frame_ff_uploading->linesize[0])) failed=true;
+                                       if (!AllocateYUVOglTexture(out_frame,width,height,dec_frame_libav_uploading->linesize[0])) failed=true;
                                }
                                if (!failed) {
                                        //up to now only YUV data, this is for reference only, since the pi is too slow.
@@ -346,7 +351,7 @@ void VideoVPEOGL::threadMethod()
                                        glTexSubImage2D(GL_TEXTURE_2D,0,0,0,
                                                        out_frame->stride,out_frame->height,
                                                        GL_LUMINANCE,GL_UNSIGNED_BYTE,
-                                                       dec_frame_ff_uploading->data[0]);
+                                                       dec_frame_libav_uploading->data[0]);
 
 
                                        glBindTexture(GL_TEXTURE_2D, out_frame->textures[1]);
@@ -354,14 +359,19 @@ void VideoVPEOGL::threadMethod()
                                        glTexSubImage2D(GL_TEXTURE_2D,0,0,0,
                                                        out_frame->stride>>1,out_frame->height>>1,
                                                        GL_LUMINANCE,GL_UNSIGNED_BYTE,
-                                                       dec_frame_ff_uploading->data[1]);
+                                                       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_ff_uploading->data[2]);
+                                                       dec_frame_libav_uploading->data[2]);
+
+
+                                       releaseFrameBufUpload((VPE_FrameBuf*)dec_frame_libav_uploading->base[0]);
+
+
                                        ogl_frame_mutex.Lock();
                                        ready_ogl_frames.push_back(out_frame);
                                        ogl_frame_mutex.Unlock();
@@ -369,10 +379,10 @@ void VideoVPEOGL::threadMethod()
 
                                }
 
-                               dec_frame_ff_mutex.Lock();
-                               dec_frame_ff_free.push_back(dec_frame_ff_uploading);
-                               dec_frame_ff_uploading=NULL;
-                               dec_frame_ff_mutex.Unlock();
+                               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();
 
 
 
@@ -394,8 +404,8 @@ void VideoVPEOGL::threadMethod()
 void VideoVPEOGL::threadPostStopCleanup()
 {
        eglMakeCurrent(egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT );
-#ifdef VPE_FFMPEG_SUPPORT
-       dec_frame_ff_uploading=NULL;
+#ifdef VPE_LIBAV_SUPPORT
+       dec_frame_libav_uploading=NULL;
 #endif
 }
 
@@ -411,7 +421,7 @@ int VideoVPEOGL::setTVsize(UCHAR ttvsize)
   close(fdVideo);
   if ((fdVideo = open("/dev/vdec_dev", O_WRONLY)) < 0) return 0;
   if (!setSource())                  { shutdown(); return 0; }
-  if (!attachFrameBuffer())          { shutdown(); return 0; }
+  if (!attachFramebuffer())          { shutdown(); return 0; }
 
   // Reopening the fd causes the scart aspect line to go back to 4:3
   // Set this again to the same as the tv screen size
@@ -583,7 +593,7 @@ int VideoVPEOGL::play()
          if (AllocateCodecsOMX()) {
                  decoding_backend=VPE_DECODER_OMX;
                  return 1;
-                 // Otherwise fall back to ffmpeg
+                 // Otherwise fall back to libav
          } else {
                  if (h264) {
                          omx_h264=false;
@@ -595,11 +605,11 @@ int VideoVPEOGL::play()
          }
   }
 #endif
-#ifdef VPE_FFMPEG_SUPPORT
-  if (AllocateCodecsFFMPEG()) {
-         decoding_backend=VPE_DECODER_FFMPEG;
+#ifdef VPE_LIBAV_SUPPORT
+  if (AllocateCodecsLibav()) {
+         decoding_backend=VPE_DECODER_libav;
          return 1;
-                 // Otherwise fall back to ffmpeg
+                 // Otherwise fall back to libav
   }
 #endif
   return 0;
@@ -1113,11 +1123,11 @@ int VideoVPEOGL::PrepareInputBufsOMX()
        input_bufs_omx_mutex.Lock();
        for (unsigned int i=0; i< port_def_type.nBufferCountActual;i++) {
 
-       //      unsigned char* new_buffer_data=(unsigned char*)malloc(port_def_type.nBufferSize);
+       //      unsigned char* new_buffer_data=(unsigned char*)malloc(port_def_type.nbufferSize);
                OMX_BUFFERHEADERTYPE *buf_head=NULL;
-       /*      error=OMX_UseBuffer(omx_vid_dec,&buf_head,omx_codec_input_port,NULL,port_def_type.nBufferSize,new_buffer_data);
+       /*      error=OMX_Usebuffer(omx_vid_dec,&buf_head,omx_codec_input_port,NULL,port_def_type.nbufferSize,new_buffer_data);
                if (error!=OMX_ErrorNone){
-                       Log::getInstance()->log("Video", Log::DEBUG, "Use OMX_UseBuffer failed %x", error);
+                       Log::getInstance()->log("Video", Log::DEBUG, "Use OMX_Usebuffer failed %x", error);
                        input_bufs_omx_mutex.Unlock();
                        return 0;
                }*/
@@ -1330,37 +1340,182 @@ int VideoVPEOGL::DeAllocateCodecsOMX()
 #endif
 
 
-#ifdef VPE_FFMPEG_SUPPORT
+#ifdef VPE_LIBAV_SUPPORT
+
+enum PixelFormat VideoVPEOGL::get_format_libav(struct AVCodecContext *s, const enum PixelFormat *fmt)
+{
+       int dec_mode=((VideoVPEOGL*)getInstance())->getlibavDecodingMode();
+       enum PixelFormat ret_pix=PIX_FMT_NONE;
+       if (dec_mode==VPE_NO_XVMC) return PIX_FMT_NONE;
+       while (*fmt!=PIX_FMT_NONE) {
+               if (*fmt== PIX_FMT_XVMC_MPEG2_IDCT && dec_mode==VPE_XVMC_IDCT) {
+                       ret_pix=PIX_FMT_XVMC_MPEG2_IDCT;
+               } else if (*fmt== PIX_FMT_XVMC_MPEG2_MC && dec_mode==VPE_XVMC_MOCOMP) {
+                       ret_pix=PIX_FMT_XVMC_MPEG2_MC;
+               }
+               fmt++;
+       }
+       return ret_pix;
+}
 
-int VideoVPEOGL::AllocateCodecsFFMPEG()
+int VideoVPEOGL::reget_buffer_libav(struct AVCodecContext *c, AVFrame *pic)
 {
-       ffmpeg_hastime=false;
-       Log::getInstance()->log("Video", Log::NOTICE, "AllocateCodecsFFmpeg");
-       mpeg2codec_context_ff=avcodec_alloc_context();
-       if (mpeg2codec_context_ff==NULL) {
-               Log::getInstance()->log("Video", Log::DEBUG, "Creating ffmpeg codec context failed");
+       Log::getInstance()->log("Video", Log::ERR, "Buffer reusing! Should not happen!Not Implemented!");
+       return -1;
+}
+
+int VideoVPEOGL::get_buffer_libav(struct AVCodecContext *c, AVFrame *pic)
+{
+       unsigned int want_sizes[4]={0,0,0,0};
+       AVPicture pict;
+       bool normal_pixs=false;
+       int s_a[4];
+       //reget logic from mplayer
+       if (pic->opaque && pic->data[0] && (!pic->buffer_hints ||pic->buffer_hints & FF_BUFFER_HINTS_REUSABLE )){
+               Log::getInstance()->log("Video", Log::ERR, "Buffer reusing! Should not happen!");
                return 0;
        }
-       if(avcodec_open(mpeg2codec_context_ff, mpeg2codec_ff)<0) {
-               Log::getInstance()->log("Video", Log::DEBUG, "Opening ffmpeg codec  failed");
+
+
+       if (c->pix_fmt!=PIX_FMT_XVMC_MPEG2_IDCT &&c->pix_fmt!=PIX_FMT_XVMC_MPEG2_MC) {
+               normal_pixs=true;
+               // standard pixel format
+               // this is written using much inspiration from libav util.c, so portions from there
+               int width,height;
+
+               width=c->width;
+               height=c->height;
+
+               avcodec_align_dimensions2(c, &width, &height, s_a);
+               if ((c->flags & CODEC_FLAG_EMU_EDGE)==0) {
+                       width+=2*16;
+                       height+=2*16;
+               }
+               // Now we have to determine alignment size
+               bool unaligned=true;
+               while (unaligned) {
+                       av_image_fill_linesizes(pict.linesize, c->pix_fmt, width); //linesizes are derived
+                       width+=width & ~(width-1); //trick from libav, now determine, if the alignment is ok
+                       unaligned=false;
+                       for (int i=0;i<4;i++) {
+                               if ((pict.linesize[i]%s_a[i])!=0) {
+                                       unaligned=true;
+                                       break;
+                               }
+                       }
+               }
+               int tot_size=av_image_fill_pointers(pict.data, c->pix_fmt, height, NULL, pict.linesize); //get sizes
+               for (int i=0;i<4 ;i++) {
+                       if (i<3 && pict.data[i+1]) {
+                               want_sizes[i]=pict.data[i+1]-pict.data[i];
+                               want_sizes[i]+=16;
+                       } else {
+                               want_sizes[i]=(tot_size-(pict.data[i]-pict.data[0]));
+                               want_sizes[i]+=16;
+                               break;
+                       }
+               }
+
+       } else {
+               //TODE set linesizes!
+               Log::getInstance()->log("Video", Log::ERR, "Not implemented");
+               return -1;
+
+       }
+
+       VPE_FrameBuf *frame_buf=((VideoVPEOGL*)Video::getInstance())->getFrameBuf(want_sizes);
+       //Log::getInstance()->log("Video", Log::NOTICE, "get buffer %x",frame_buf);
+       if (!frame_buf) {
+               Log::getInstance()->log("Video", Log::ERR, "Getting buffer libav failed");
+               return -1;
+       }
+       //populate pict
+       pic->type=FF_BUFFER_TYPE_USER; // we are controlling the buffers
+       int hchr_shift,vchr_shift;
+       avcodec_get_chroma_sub_sample(c->pix_fmt,&hchr_shift,&vchr_shift);
+       const int pixel_size = av_pix_fmt_descriptors[c->pix_fmt].comp[0].step_minus1+1;
+       for (int i=0;i<4;i++) {
+               pic->data[i]=(uint8_t*)frame_buf->data[i];
+               pic->linesize[i]=pict.linesize[i];
+               if (normal_pixs) {
+
+                       int edge_width=16;
+                       int edge_height=16;
+                       if (i!=0) {
+                               edge_width>>=hchr_shift;
+                               edge_height>>=vchr_shift;
+                       }
+                       pic->data[i]+=FFALIGN((pic->linesize[i]*16) + (pixel_size*edge_width), s_a[i]);
+               }
+       }
+
+       pic->base[0]=(uint8_t*)frame_buf; // our structure
+       //pic->extended_data=pic->data;
+       if(c->pkt) pic->pkt_pts=c->pkt->pts;
+       else pic->pkt_pts=AV_NOPTS_VALUE;
+       pic->width=c->width;
+       pic->height=c->height;
+       pic->format=c->pix_fmt;
+       pic->sample_aspect_ratio=c->sample_aspect_ratio;
+       pic->reordered_opaque= c->reordered_opaque;
+       pic->age=INT_MAX;
+
+       return 0;
+
+}
+
+void VideoVPEOGL::release_buffer_libav(struct AVCodecContext *c, AVFrame *pic)
+{
+//     Log::getInstance()->log("Video", Log::NOTICE, "release buffer %x",pic->base[0]);
+       ((VideoVPEOGL*)Video::getInstance())->releaseFrameBufLibav((VPE_FrameBuf*) pic->base[0]);
+       pic->base[0]=NULL;
+       pic->data[0]=pic->data[1]=pic->data[2]=pic->data[3]=NULL;
+
+
+}
+
+int VideoVPEOGL::AllocateCodecsLibav()
+{
+       libav_hastime=false;
+       Log::getInstance()->log("Video", Log::NOTICE, "AllocateCodecslibav");
+       mpeg2codec_context_libav=avcodec_alloc_context();
+       if (mpeg2codec_context_libav==NULL) {
+               Log::getInstance()->log("Video", Log::DEBUG, "Creating libav codec context failed");
                return 0;
        }
-       memset(&incom_packet_ff,0,sizeof(incom_packet_ff));
-       incom_packet_ff_size=200000;
-       incom_packet_ff.data=(uint8_t*)av_malloc(incom_packet_ff_size+FF_INPUT_BUFFER_PADDING_SIZE);
+       if (decoding_mode!=VPE_NO_XVMC) {
+               mpeg2codec_context_libav->slice_flags=SLICE_FLAG_CODED_ORDER|SLICE_FLAG_ALLOW_FIELD;
+               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->get_buffer=get_buffer_libav;
+       mpeg2codec_context_libav->reget_buffer=reget_buffer_libav;
+       mpeg2codec_context_libav->release_buffer=release_buffer_libav;
 
-       dec_frame_ff_mutex.Lock();
+
+       int avc_ret=avcodec_open(mpeg2codec_context_libav, mpeg2codec_libav);
+       if (avc_ret<0) {
+               Log::getInstance()->log("Video", Log::DEBUG, "Opening libav codec  failed ");
+               return 0;
+       }
+       memset(&incom_packet_libav,0,sizeof(incom_packet_libav));
+       incom_packet_libav_size=200000;
+       incom_packet_libav.data=(uint8_t*)av_malloc(incom_packet_libav_size+FF_INPUT_BUFFER_PADDING_SIZE);
+
+       dec_frame_libav_mutex.Lock();
        for (int i=0;i<3;i++) {
-                       AVFrame *dec_frame_ff=avcodec_alloc_frame(); // may be we need multiple frames, if we want to use async texture upload
-                       if (!dec_frame_ff) {
+                       AVFrame *dec_frame_libav=avcodec_alloc_frame(); // may be we need multiple frames, if we want to use async texture upload
+                       if (!dec_frame_libav) {
                                Log::getInstance()->log("Video", Log::DEBUG, "Allocating dec_frame  failed");
                                return 0;
                        }
-                       dec_frame_ff_all.push_back(dec_frame_ff);
-                       dec_frame_ff_free.push_back(dec_frame_ff);
+                       dec_frame_libav_all.push_back(dec_frame_libav);
+                       dec_frame_libav_free.push_back(dec_frame_libav);
        }
-       dec_frame_ff_decoding=NULL;
-       dec_frame_ff_mutex.Unlock();
+       dec_frame_libav_decoding=NULL;
+       dec_frame_libav_mutex.Unlock();
 
        ogl_frame_mutex.Lock();
        //Allocate texture structs, since we do not know the sizes, we do not allocate the textures yet
@@ -1379,37 +1534,37 @@ int VideoVPEOGL::AllocateCodecsFFMPEG()
 
        ogl_frame_mutex.Unlock();
 
-       ffmpeg_running=true;
+       libav_running=true;
 
        return 1;
 
 }
 
-int VideoVPEOGL::DeAllocateCodecsFFMPEG()
+int VideoVPEOGL::DeAllocateCodecsLibav()
 {
-       ffmpeg_running=false;
-       Log::getInstance()->log("Video", Log::NOTICE, "DeAllocateCodecsFFmpeg");
-       dec_frame_ff_mutex.Lock();
-       dec_frame_ff_upload_pending.clear();
-       dec_frame_ff_free.clear();
-       dec_frame_ff_mutex.Unlock();
-       while (dec_frame_ff_uploading) {
+       libav_running=false;
+       Log::getInstance()->log("Video", Log::NOTICE, "DeAllocateCodecslibav");
+       dec_frame_libav_mutex.Lock();
+       dec_frame_libav_upload_pending.clear();
+       dec_frame_libav_free.clear();
+       dec_frame_libav_mutex.Unlock();
+       while (dec_frame_libav_uploading) {
                Log::getInstance()->log("Video", Log::NOTICE, "Wait for uploading to finish");
                MILLISLEEP(20);
        }
-       dec_frame_ff_mutex.Lock();
-       for (int i=0; i< dec_frame_ff_all.size();i++) {
-               av_free(dec_frame_ff_all[i]);
+       dec_frame_libav_mutex.Lock();
+       for (int i=0; i< dec_frame_libav_all.size();i++) {
+               av_free(dec_frame_libav_all[i]);
        }
 
-       dec_frame_ff_all.clear();
+       dec_frame_libav_all.clear();
 
-       av_free(incom_packet_ff.data);
-       incom_packet_ff.data=NULL;
-       incom_packet_ff_size=0;
+       av_free(incom_packet_libav.data);
+       incom_packet_libav.data=NULL;
+       incom_packet_libav_size=0;
 
-       dec_frame_ff_mutex.Unlock();
-       dec_frame_ff_decoding=NULL;
+       dec_frame_libav_mutex.Unlock();
+       dec_frame_libav_decoding=NULL;
        while (ogl_frame_outside) {
                Log::getInstance()->log("Video", Log::NOTICE, "Wait for ogl frame from outside");
                MILLISLEEP(20);
@@ -1417,7 +1572,7 @@ int VideoVPEOGL::DeAllocateCodecsFFMPEG()
 
        ((OsdOpenGL*)Osd::getInstance())->BeginPainting(); // get osd's context
        ogl_frame_mutex.Lock();
-       for (int i=0; i< dec_frame_ff_all.size();i++) {
+       for (int i=0; i< dec_frame_libav_all.size();i++) {
                VPEOGLFrame * del_frame=all_ogl_frames[i];
                if (del_frame->textures[0]==0) {
                        glDeleteTextures(1,&del_frame->textures[0]);
@@ -1440,19 +1595,129 @@ int VideoVPEOGL::DeAllocateCodecsFFMPEG()
        ((OsdOpenGL*)Osd::getInstance())->EndPainting();
 
 
-       if (mpeg2codec_context_ff) {
-               avcodec_close(mpeg2codec_context_ff);
-               av_free(mpeg2codec_context_ff);
-               mpeg2codec_context_ff=NULL;
+       if (mpeg2codec_context_libav) {
+               avcodec_close(mpeg2codec_context_libav);
+               av_free(mpeg2codec_context_libav);
+               mpeg2codec_context_libav=NULL;
+
+       }
 
+
+
+       vpe_framebuf_mutex.Lock();
+
+       for (int i=0;i<all_frame_bufs.size();i++) {
+               VPE_FrameBuf* current=all_frame_bufs[i];
+               for (int x=0;x<4;x++) {
+                       if (current->data[x]) {
+                               av_free(current->data[x]);
+                       }
+               }
+               free(current);
        }
+       all_frame_bufs.clear();
+       free_frame_bufs.clear();
+       locked_libav_frame_buf.clear();
+       locked_uploading_frame_buf.clear();
 
+       vpe_framebuf_mutex.Unlock();
 
 
        return 1;
 }
 
 
+VPE_FrameBuf *VideoVPEOGL::getFrameBuf(unsigned int *size)
+{ //for libav
+       VPE_FrameBuf* current=NULL;
+       vpe_framebuf_mutex.Lock();
+       if (free_frame_bufs.size()>0) {
+               current=free_frame_bufs.front();
+               free_frame_bufs.pop_front();
+       } else if (all_frame_bufs.size()<6) {
+               current=(VPE_FrameBuf*)malloc(sizeof(VPE_FrameBuf));
+               memset(current,0,sizeof(VPE_FrameBuf));
+       } else {
+               Log::getInstance()->log("Video", Log::NOTICE, "Framebuffer underrun!");
+               vpe_framebuf_mutex.Unlock();
+               return NULL; // We do not have a frame buffer
+       }
+       locked_libav_frame_buf.push_back(current);
+       vpe_framebuf_mutex.Unlock();
+       //check if we need reallocation
+       for (int x=0;x<4;x++) {
+               if (current->size[x]!=size[x]) {
+                       current->data[x]=av_realloc(current->data[x],size[x]);
+                       current->size[x]=size[x];
+               }
+       }
+       return current;
+
+}
+
+void VideoVPEOGL::lockFrameBufUpload(VPE_FrameBuf* buf)
+{
+       // first find frame_buf memory
+
+       //Log::getInstance()->log("Video", Log::NOTICE, "lock buffer upload %x",buf);
+       VPE_FrameBuf* current=buf;
+       vpe_framebuf_mutex.Lock();
+       if (current) locked_uploading_frame_buf.push_back(current); //locked
+       vpe_framebuf_mutex.Unlock();
+
+}
+
+
+void VideoVPEOGL::releaseFrameBufLibav(VPE_FrameBuf* buf)
+{
+       // first find frame_buf memory
+       //Log::getInstance()->log("Video", Log::NOTICE, "release buffer libav %x",buf);
+       VPE_FrameBuf* current=buf;
+       vpe_framebuf_mutex.Lock();
+       if (current) {
+               locked_libav_frame_buf.remove(current); //unlocked
+               list<VPE_FrameBuf*>::iterator itty=locked_uploading_frame_buf.begin();
+               bool inlist=false;
+               while (itty!=locked_uploading_frame_buf.end()) {
+                       if (*itty==current) {
+                               inlist=true;
+                               break;
+                       }
+                       itty++;
+               }
+               if (!inlist) {
+                       free_frame_bufs.push_back(current);
+               }
+       }
+       vpe_framebuf_mutex.Unlock();
+}
+
+void VideoVPEOGL::releaseFrameBufUpload(VPE_FrameBuf* buf)
+{
+       // first find frame_buf memory
+       VPE_FrameBuf* current=buf;
+       //Log::getInstance()->log("Video", Log::NOTICE, "release buffer upload %x",buf);
+       vpe_framebuf_mutex.Lock();
+       if (current) {
+               locked_uploading_frame_buf.remove(current); //unlocked
+               list<VPE_FrameBuf*>::iterator itty=locked_libav_frame_buf.begin();
+               bool inlist=false;
+               while (itty!=locked_libav_frame_buf.end()) {
+                       if (*itty==current) {
+                               inlist=true;
+                               break;
+                       }
+                       itty++;
+               }
+               if (!inlist) {
+                       free_frame_bufs.push_back(current);
+               }
+       }
+       vpe_framebuf_mutex.Unlock();
+}
+
+
+
 
 
 
@@ -1463,7 +1728,7 @@ int VideoVPEOGL::stop()
   if (!initted) return 0;
 
 #ifdef VPE_OMX_SUPPORT
-  //Check if ffmpeg mode
+  //Check if libav mode
   if (decoding_backend==VPE_DECODER_OMX) DeAllocateCodecsOMX();
   decoding_backend=0;
 
@@ -1502,7 +1767,7 @@ int VideoVPEOGL::fastForward()
 {
   if (!initted) return 0;
 
-//  if (ioctl(fdVideo, AV_SET_VID_FFWD, 1) != 0) return 0;
+//  if (ioctl(fdVideo, AV_SET_VID_libavWD, 1) != 0) return 0;
   return 1;
 }
 
@@ -1607,8 +1872,8 @@ UINT VideoVPEOGL::DeliverMediaPacket(MediaPacket packet,
 #ifdef VPE_OMX_SUPPORT
        case VPE_DECODER_OMX: return DeliverMediaPacketOMX(packet,buffer,samplepos);
 #endif
-#ifdef VPE_FFMPEG_SUPPORT
-       case VPE_DECODER_FFMPEG: return DeliverMediaPacketFFMPEG(packet,buffer,samplepos);
+#ifdef VPE_LIBAV_SUPPORT
+       case VPE_DECODER_libav: return DeliverMediaPacketlibav(packet,buffer,samplepos);
 #endif
        }
 }
@@ -1620,7 +1885,7 @@ UINT VideoVPEOGL::DeliverMediaPacketOMX(MediaPacket packet,
 {
 
 
-       //Later add fail back code for ffmpeg
+       //Later add fail back code for libav
        /*if (!videoon) {
                *samplepos+=packet.length;
                return packet.length;
@@ -1780,11 +2045,11 @@ UINT VideoVPEOGL::DeliverMediaPacketOMX(MediaPacket packet,
 #endif
 
 
-#ifdef VPE_FFMPEG_SUPPORT
-int VideoVPEOGL::DecodePacketFFMPEG()
+#ifdef VPE_LIBAV_SUPPORT
+int VideoVPEOGL::DecodePacketlibav()
 {
-       unsigned int haveToCopy=incom_packet_ff.size;
-       if (incom_packet_ff.size==0) return 1; // we are already empty
+       unsigned int haveToCopy=incom_packet_libav.size;
+       if (incom_packet_libav.size==0) return 1; // we are already empty
        while (haveToCopy>0) {
                int dec_bytes=0;
                int frame_ready=0;
@@ -1794,9 +2059,8 @@ int VideoVPEOGL::DecodePacketFFMPEG()
 #ifdef BENCHMARK_FPS
            int cur_time=getTimeMS();
 #endif
-
-               dec_bytes=avcodec_decode_video2(mpeg2codec_context_ff, dec_frame_ff_decoding,
-                               &frame_ready, &incom_packet_ff);
+               dec_bytes=avcodec_decode_video2(mpeg2codec_context_libav, dec_frame_libav_decoding,
+                               &frame_ready, &incom_packet_libav);
 #ifdef BENCHMARK_FPS
                time_in_decoder+=getTimeMS()-cur_time;
                if (frame_ready) num_frames++;
@@ -1814,24 +2078,26 @@ int VideoVPEOGL::DecodePacketFFMPEG()
                if (frame_ready) {
                //      Log::getInstance()->log("Video", Log::DEBUG, "We have a frame push it to osd");
 
-                       dec_frame_ff_mutex.Lock();
-                       ffwidth=mpeg2codec_context_ff->width;
-                       ffheight=mpeg2codec_context_ff->height;
-                       ffpixfmt=mpeg2codec_context_ff->pix_fmt;
-               //      Log::getInstance()->log("Video", Log::DEBUG, "Frame info %d %d %d",ffwidth,ffheight,ffpixfmt);
-
-                       dec_frame_ff_upload_pending.push_back(dec_frame_ff_decoding);
-                       dec_frame_ff_decoding=NULL;
-                       if (dec_frame_ff_free.size()>0) {
-                               dec_frame_ff_decoding=dec_frame_ff_free.front();
-                               dec_frame_ff_free.pop_front();
-                               dec_frame_ff_mutex.Unlock();
+                       lockFrameBufUpload((VPE_FrameBuf*)dec_frame_libav_decoding->base[0]); //lock for upload, so that ffmpeg does not reuse
+                       dec_frame_libav_mutex.Lock();
+                       libavwidth=mpeg2codec_context_libav->width;
+                       libavheight=mpeg2codec_context_libav->height;
+                       libavpixfmt=mpeg2codec_context_libav->pix_fmt;
+               //      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_decoding=NULL;
+                       if (dec_frame_libav_free.size()>0) {
+                               dec_frame_libav_decoding=dec_frame_libav_free.front();
+                               dec_frame_libav_free.pop_front();
+                               dec_frame_libav_mutex.Unlock();
                                threadSignal();
-                               ffmpeg_hastime=false;
+                               libav_hastime=false;
                        } else {
-                               ffmpeg_hastime=false;
-                               dec_frame_ff_mutex.Unlock();
-                               // No free Buffers
+                               libav_hastime=false;
+                               dec_frame_libav_mutex.Unlock();
+                               // No free buffers
                                return 0;
                        }
 
@@ -1839,23 +2105,23 @@ int VideoVPEOGL::DecodePacketFFMPEG()
                }
 
        }
-       incom_packet_ff.size=0;
+       incom_packet_libav.size=0;
        return 1;
 
 }
 
 
-UINT VideoVPEOGL::DeliverMediaPacketFFMPEG(MediaPacket packet,
+UINT VideoVPEOGL::DeliverMediaPacketlibav(MediaPacket packet,
                const UCHAR* buffer,
                UINT *samplepos)
 {
-       //Later add fail back code for ffmpeg
+       //Later add fail back code for libav
        /*if (!videoon) {
                *samplepos+=packet.length;
                return packet.length;
        }*/
 
-       if (!ffmpeg_running) return 0; // if we are not runnig do not do this
+       if (!libav_running) return 0; // if we are not runnig do not do this
 
 
        if (iframemode) {
@@ -1867,20 +2133,20 @@ UINT VideoVPEOGL::DeliverMediaPacketFFMPEG(MediaPacket packet,
        UINT headerstrip=0;
        if (packet.disconti) {
                firstsynched=false;
-               if (!DecodePacketFFMPEG()) return 0;
+               if (!DecodePacketlibav()) return 0;
        }
 
        /*Inspect PES-Header */
-       if (!dec_frame_ff_decoding) {
-               dec_frame_ff_mutex.Lock();
-               if (dec_frame_ff_free.size()>0) {
-                       dec_frame_ff_decoding=dec_frame_ff_free.front();
-                       dec_frame_ff_free.pop_front();
-                       dec_frame_ff_mutex.Unlock();
+       if (!dec_frame_libav_decoding) {
+               dec_frame_libav_mutex.Lock();
+               if (dec_frame_libav_free.size()>0) {
+                       dec_frame_libav_decoding=dec_frame_libav_free.front();
+                       dec_frame_libav_free.pop_front();
+                       dec_frame_libav_mutex.Unlock();
                } else {
                        Log::getInstance()->log("Video", Log::DEBUG, "We have no free buffers");
-                       dec_frame_ff_mutex.Unlock();
-                       // No free Buffers
+                       dec_frame_libav_mutex.Unlock();
+                       // No free buffers
                        return 0;
                }
        }
@@ -1892,10 +2158,10 @@ UINT VideoVPEOGL::DeliverMediaPacketFFMPEG(MediaPacket packet,
                *samplepos+=headerstrip;
                if ( packet.synched ) {
 
-                       if (!DecodePacketFFMPEG()) return 0; // WriteOut old Data
+                       if (!DecodePacketlibav()) return 0; // WriteOut old Data
 
-                       ffmpeg_time=packet.presentation_time;
-                       ffmpeg_hastime=true;
+                       libav_time=packet.presentation_time;
+                       libav_hastime=true;
                //      reftime1=packet.presentation_time;
                //      reftime2=reftime1+1;
                        firstsynched=true;
@@ -1938,14 +2204,14 @@ UINT VideoVPEOGL::DeliverMediaPacketFFMPEG(MediaPacket packet,
        }*/
        unsigned int haveToCopy=packet.length-*samplepos;
 
-       if  ((incom_packet_ff_size-incom_packet_ff.size)< haveToCopy) {
+       if  ((incom_packet_libav_size-incom_packet_libav.size)< haveToCopy) {
                // if the buffer is to small reallocate
-               incom_packet_ff_size+=haveToCopy;
-               incom_packet_ff.data=(uint8_t*)av_realloc(incom_packet_ff.data,incom_packet_ff_size+FF_INPUT_BUFFER_PADDING_SIZE);
-               Log::getInstance()->log("Video", Log::DEBUG, "Reallocate avpacket buffer to %d", incom_packet_ff_size);
+               incom_packet_libav_size+=haveToCopy;
+               incom_packet_libav.data=(uint8_t*)av_realloc(incom_packet_libav.data,incom_packet_libav_size+FF_INPUT_BUFFER_PADDING_SIZE);
+               Log::getInstance()->log("Video", Log::DEBUG, "Reallocate avpacket buffer to %d", incom_packet_libav_size);
        }
-       memcpy(incom_packet_ff.data,buffer+packet.pos_buffer+*samplepos,haveToCopy);
-       incom_packet_ff.size+=haveToCopy;
+       memcpy(incom_packet_libav.data+incom_packet_libav.size,buffer+packet.pos_buffer+*samplepos,haveToCopy);
+       incom_packet_libav.size+=haveToCopy;
 
        *samplepos+=haveToCopy;
 
index c127a33b2d90878c75b8e642e0d0aa3d69e9980a..ef737243fdae78f7bcf4877e6532e68f628c7d9f 100755 (executable)
@@ -65,14 +65,22 @@ struct VPE_OMX_EVENT {
 \r
 #endif\r
 \r
-#ifdef VPE_FFMPEG_SUPPORT\r
+#ifdef VPE_LIBAV_SUPPORT\r
 \r
 #include <stdint.h>\r
 extern "C" {\r
 \r
 #include <libavcodec/avcodec.h>\r
 #include <libavformat/avformat.h>\r
+#include <libavutil/imgutils.h>\r
 }\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
+};\r
+\r
 #endif\r
 \r
 \r
@@ -124,18 +132,18 @@ class VideoVPEOGL : public Video, public Thread_TYPE
     int attachFrameBuffer(); // What does this do?\r
     ULONG timecodeToFrameNumber(ULLONG timecode);\r
     ULLONG getCurrentTimestamp();\r
-    bool displayIFrame(const UCHAR* buffer, UINT length);\r
+    bool displayIFrame(const UCHAR* bulibaver, UINT length);\r
 \r
     // Writing Data to Videodevice\r
     virtual void PrepareMediaSample(const MediaPacketList&, UINT samplepos);\r
-    virtual UINT DeliverMediaSample(UCHAR* buffer, UINT* samplepos);\r
+    virtual UINT DeliverMediaSample(UCHAR* bulibaver, UINT* samplepos);\r
     virtual long long SetStartOffset(long long curreftime, bool *rsync)\r
     { *rsync=false; return 0; };\r
     virtual void ResetTimeOffsets();\r
 \r
        virtual bool supportsh264(){return true;};\r
 \r
-       int WriteOutTS(const unsigned char *buffer,int length, int type);\r
+       int WriteOutTS(const unsigned char *bulibaver,int length, int type);\r
        void WriteOutPATPMT();\r
 \r
 \r
@@ -154,33 +162,39 @@ class VideoVPEOGL : public Video, public Thread_TYPE
     int initUsingOSDObjects();\r
     int shutdownUsingOSDObjects() {return shutdown();};\r
 \r
+#ifdef VPE_LIBAV_SUPPORT\r
+    int getlibavDecodingMode() {return decoding_mode;};\r
+\r
+\r
+#endif\r
+\r
   private:\r
           int EnterIframePlayback();\r
           bool iframemode;\r
 \r
           UINT DeliverMediaPacket(MediaPacket packet,\r
-                                            const UCHAR* buffer,\r
+                                            const UCHAR* bulibaver,\r
                                             UINT *samplepos);\r
-          int decoding_backend; //1 omx, 2 ffmpeg\r
+          int decoding_backend; //1 omx, 2 libav\r
 #define VPE_DECODER_OMX 1\r
-#define VPE_DECODER_FFMPEG 2\r
+#define VPE_DECODER_libav 2\r
 \r
 #ifdef VPE_OMX_SUPPORT\r
           static OMX_ERRORTYPE EventHandler_OMX(OMX_IN OMX_HANDLETYPE handle,OMX_IN OMX_PTR appdata,\r
           OMX_IN OMX_EVENTTYPE event_type,OMX_IN OMX_U32 data1,\r
           OMX_IN OMX_U32 data2,OMX_IN OMX_PTR event_data);\r
-          static OMX_ERRORTYPE EmptyBufferDone_OMX(OMX_IN OMX_HANDLETYPE hcomp,OMX_IN OMX_PTR appdata,OMX_IN OMX_BUFFERHEADERTYPE* buffer);\r
-          static OMX_ERRORTYPE FillBufferDone_OMX(OMX_IN OMX_HANDLETYPE hcomp, OMX_IN OMX_PTR appdata,OMX_IN OMX_BUFFERHEADERTYPE* buffer);\r
+          static OMX_ERRORTYPE EmptyBufferDone_OMX(OMX_IN OMX_HANDLETYPE hcomp,OMX_IN OMX_PTR appdata,OMX_IN OMX_BUFFERHEADERTYPE* bulibaver);\r
+          static OMX_ERRORTYPE FillBufferDone_OMX(OMX_IN OMX_HANDLETYPE hcomp, OMX_IN OMX_PTR appdata,OMX_IN OMX_BUFFERHEADERTYPE* bulibaver);\r
 \r
           UINT DeliverMediaPacketOMX(MediaPacket packet,\r
-                                                    const UCHAR* buffer,\r
+                                                    const UCHAR* bulibaver,\r
                                                     UINT *samplepos);\r
 \r
           int PrepareInputBufsOMX();\r
           int DestroyInputBufsOMX();\r
 \r
           void AddOmxEvent(VPE_OMX_EVENT  new_event);\r
-          void ReturnEmptyOMXBuffer(OMX_BUFFERHEADERTYPE* buffer);\r
+          void ReturnEmptyOMXBuffer(OMX_BUFFERHEADERTYPE* bulibaver);\r
 \r
           int ChangeComponentState(OMX_HANDLETYPE handle,OMX_STATETYPE type);\r
           int CommandFinished(OMX_HANDLETYPE handle,OMX_U32 command,OMX_U32 data2);\r
@@ -231,30 +245,57 @@ class VideoVPEOGL : public Video, public Thread_TYPE
 \r
 #endif\r
 \r
-#ifdef VPE_FFMPEG_SUPPORT\r
-       AVCodec *mpeg2codec_ff;\r
-       AVCodecContext *mpeg2codec_context_ff;\r
-       vector<AVFrame*> dec_frame_ff_all;\r
-       list<AVFrame*> dec_frame_ff_free;\r
-       list<AVFrame*> dec_frame_ff_upload_pending;\r
-       AVFrame* dec_frame_ff_uploading;\r
-       AVFrame* dec_frame_ff_decoding;\r
+#ifdef VPE_LIBAV_SUPPORT\r
+\r
+       const static int VPE_NO_XVMC=0;\r
+       const static int VPE_XVMC_MOCOMP=1;\r
+       const static int VPE_XVMC_IDCT=2;\r
+\r
+       int decoding_mode;\r
+\r
+       AVCodec *mpeg2codec_libav;\r
+       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
+       AVFrame* dec_frame_libav_uploading;\r
+       AVFrame* dec_frame_libav_decoding;\r
+\r
+       vector<VPE_FrameBuf*> all_frame_bufs;\r
+       list<VPE_FrameBuf*> free_frame_bufs;\r
+       list<VPE_FrameBuf*> locked_libav_frame_buf;\r
+       list<VPE_FrameBuf*> locked_uploading_frame_buf;\r
+\r
+       VPE_FrameBuf *getFrameBuf(unsigned int *size); //for libav\r
+       void releaseFrameBufLibav(VPE_FrameBuf*data);\r
+       void lockFrameBufUpload(VPE_FrameBuf* data);\r
+       void releaseFrameBufUpload(VPE_FrameBuf* data);\r
+\r
+       Mutex vpe_framebuf_mutex;\r
+\r
+\r
+\r
+       AVPacket incom_packet_libav;\r
+       int incom_packet_libav_size;\r
+       Mutex dec_frame_libav_mutex;\r
+\r
 \r
-       AVPacket incom_packet_ff;\r
-       int incom_packet_ff_size;\r
-       Mutex dec_frame_ff_mutex;\r
 \r
+       UINT DeliverMediaPacketlibav(MediaPacket packet,const UCHAR* bulibaver,UINT *samplepos);\r
+       int AllocateCodecsLibav();\r
+       int DeAllocateCodecsLibav();\r
+       int DecodePacketlibav();\r
 \r
+       static enum PixelFormat get_format_libav(struct AVCodecContext *s, const enum PixelFormat *fmt);\r
+       static int get_buffer_libav(struct AVCodecContext *c, AVFrame *pic);\r
+       static int reget_buffer_libav(struct AVCodecContext *c, AVFrame *pic);\r
+       static void release_buffer_libav(struct AVCodecContext *c, AVFrame *pic);\r
 \r
-       UINT DeliverMediaPacketFFMPEG(MediaPacket packet,const UCHAR* buffer,UINT *samplepos);\r
-       int AllocateCodecsFFMPEG();\r
-       int DeAllocateCodecsFFMPEG();\r
-       int DecodePacketFFMPEG();\r
-       bool ffmpeg_running;\r
-       bool ffmpeg_hastime; // signals if a pts is now\r
-       long long ffmpeg_time;\r
+       bool libav_running;\r
+       bool libav_hastime; // signals if a pts is now\r
+       long long libav_time;\r
 \r
-       int ffwidth,ffheight,ffpixfmt;\r
+       int libavwidth,libavheight,libavpixfmt;\r
 \r
        \r
 #endif\r