changeset 33247:a2483e1a3db3

Use xvmc_render struct to hold both xvmc_pix_fmt shared struct and the specific flags needed by MPlayer. These flags were removed from FFmpeg after the version bump.
author iive
date Tue, 26 Apr 2011 23:31:25 +0000
parents 881d0b46bc62
children 747e5068118c
files libvo/vo_xvmc.c
diffstat 1 files changed, 89 insertions(+), 103 deletions(-) [+]
line wrap: on
line diff
--- a/libvo/vo_xvmc.c	Tue Apr 26 18:48:19 2011 +0000
+++ b/libvo/vo_xvmc.c	Tue Apr 26 23:31:25 2011 +0000
@@ -90,21 +90,22 @@
 #define MAX_SURFACES 8
 static int number_of_surfaces=0;
 static XvMCSurface surface_array[MAX_SURFACES];
-static struct render_info {
+struct xvmc_render{
+    struct xvmc_pix_fmt shared;
 #define STATE_DISPLAY_PENDING 1  /**  the surface should be shown, the video driver manipulates this */
 #define STATE_PREDICTION      2  /**  the surface is needed for prediction, the codec manipulates this */
 #define STATE_OSD_SOURCE      4  /**  the surface is needed for subpicture rendering */
     int state;
     void *p_osd_target_surface_render;
     mp_image_t *mpi;
-} surface_render_info[MAX_SURFACES];
-static struct xvmc_pix_fmt *surface_render;
+};
+static struct xvmc_render *surface_render;
 
-static struct xvmc_pix_fmt *p_render_surface_to_show = NULL;
-static struct xvmc_pix_fmt *p_render_surface_visible = NULL;
+static struct xvmc_render *p_render_surface_to_show = NULL;
+static struct xvmc_render *p_render_surface_visible = NULL;
 
 //display queue, kinda render ahead
-static struct xvmc_pix_fmt *show_queue[MAX_SURFACES];
+static struct xvmc_render *show_queue[MAX_SURFACES];
 static int free_element;
 
 
@@ -132,7 +133,7 @@
 static void xvmc_free(void);
 static void xvmc_clean_surfaces(void);
 static int count_free_surfaces(void);
-static struct xvmc_pix_fmt *find_free_surface(void);
+static struct xvmc_render *find_free_surface(void);
 
 static const vo_info_t info = {
     "XVideo Motion Compensation",
@@ -150,47 +151,33 @@
 #endif
 static XvImage * xvimage;
 
-static struct render_info *get_render_info(struct xvmc_pix_fmt *cur_render)
+static void add_state(struct xvmc_render *cur_render, int flags)
 {
-    int idx;
-    if (!surface_render || !cur_render)
-        return NULL;
-    idx = cur_render - surface_render;
-    if (idx < 0 || idx >= MAX_SURFACES)
-        return NULL;
-    return surface_render_info + idx;
-}
-
-static void add_state(struct xvmc_pix_fmt *cur_render, int flags)
-{
-    struct render_info *info = get_render_info(cur_render);
     int bit;
-    if (info->mpi) {
+    if (cur_render->mpi) {
         for (bit = 1; flags >= bit; bit <<= 1) {
-            if (flags & ~info->state & bit)
-                info->mpi->usage_count++;
+            if (flags & ~cur_render->state & bit)
+                cur_render->mpi->usage_count++;
         }
     }
-    info->state |= flags;
+    cur_render->state |= flags;
 }
 
-static void remove_state(struct xvmc_pix_fmt *cur_render, int flags)
+static void remove_state(struct xvmc_render *cur_render, int flags)
 {
-    struct render_info *info = get_render_info(cur_render);
     int bit;
-    if (info->mpi) {
+    if (cur_render->mpi) {
         for (bit = 1; flags >= bit; bit <<= 1) {
-            if (flags & info->state & bit)
-                info->mpi->usage_count--;
+            if (flags & cur_render->state & bit)
+                cur_render->mpi->usage_count--;
         }
     }
-    info->state &= ~flags;
+    cur_render->state &= ~flags;
 }
 
-static int in_use(struct xvmc_pix_fmt *cur_render)
+static int in_use(struct xvmc_render *cur_render)
 {
-    struct render_info *info = get_render_info(cur_render);
-    return info->state || (info->mpi && info->mpi->usage_count);
+    return cur_render->state || (cur_render->mpi && cur_render->mpi->usage_count);
 }
 
 static void allocate_xvimage(int xvimage_width,int xvimage_height,int xv_format)
@@ -398,15 +385,15 @@
 }
 
 static uint32_t xvmc_draw_image(mp_image_t *mpi){
-    struct xvmc_pix_fmt *rndr;
+    struct xvmc_render *rndr;
 
     assert(mpi!=NULL);
     assert(mpi->flags &MP_IMGFLAG_DIRECT);
 //   assert(mpi->flags &MP_IMGFLAGS_DRAWBACK);
 
-    rndr = (struct xvmc_pix_fmt*)mpi->priv; //there is copy in plane[2]
+    rndr = (struct xvmc_render*)mpi->priv; //there is copy in plane[2]
     assert( rndr != NULL );
-    assert( rndr->xvmc_id == AV_XVMC_ID );
+    assert( rndr->shared.xvmc_id == AV_XVMC_ID );
     mp_msg(MSGT_VO,MSGL_DBG4,"vo_xvmc: draw_image(show rndr=%p)\n",rndr);
 // the surface have passed vf system without been skiped, it will be displayed
     add_state(rndr, STATE_DISPLAY_PENDING);
@@ -555,21 +542,21 @@
     mp_msg(MSGT_VO,MSGL_INFO,"vo_xvmc: mv_blocks allocated\n");
 
     if(surface_render==NULL)
-        surface_render = malloc(MAX_SURFACES * sizeof(struct xvmc_pix_fmt)); //easy mem debug
-    memset(surface_render, 0, MAX_SURFACES * sizeof(struct xvmc_pix_fmt));
+        surface_render = malloc(MAX_SURFACES * sizeof(struct xvmc_render)); //easy mem debug
+    memset(surface_render, 0, MAX_SURFACES * sizeof(struct xvmc_render));
 
     for(i=0; i<MAX_SURFACES; i++){
         rez=XvMCCreateSurface(mDisplay,&ctx,&surface_array[i]);
         if( rez != Success )
             break;
-        surface_render[i].xvmc_id = AV_XVMC_ID;
-        surface_render[i].data_blocks = data_blocks.blocks;
-        surface_render[i].mv_blocks = mv_blocks.macro_blocks;
-        surface_render[i].allocated_mv_blocks = numblocks;
-        surface_render[i].allocated_data_blocks = numblocks*blocks_per_macroblock;
-        surface_render[i].idct = (surface_info.mc_type & XVMC_IDCT) == XVMC_IDCT;
-        surface_render[i].unsigned_intra = (surface_info.flags & XVMC_INTRA_UNSIGNED) == XVMC_INTRA_UNSIGNED;
-        surface_render[i].p_surface = &surface_array[i];
+        surface_render[i].shared.xvmc_id = AV_XVMC_ID;
+        surface_render[i].shared.data_blocks = data_blocks.blocks;
+        surface_render[i].shared.mv_blocks = mv_blocks.macro_blocks;
+        surface_render[i].shared.allocated_mv_blocks = numblocks;
+        surface_render[i].shared.allocated_data_blocks = numblocks*blocks_per_macroblock;
+        surface_render[i].shared.idct = (surface_info.mc_type & XVMC_IDCT) == XVMC_IDCT;
+        surface_render[i].shared.unsigned_intra = (surface_info.flags & XVMC_INTRA_UNSIGNED) == XVMC_INTRA_UNSIGNED;
+        surface_render[i].shared.p_surface = &surface_array[i];
         mp_msg(MSGT_VO,MSGL_DBG4,"vo_xvmc: surface[%d] = %p .rndr=%p\n",
                 i,&surface_array[i], &surface_render[i]);
     }
@@ -866,7 +853,7 @@
 }
 
 static void draw_osd(void){
-    struct xvmc_pix_fmt *osd_rndr;
+    struct xvmc_render *osd_rndr;
     int osd_has_changed;
     int have_osd_to_draw;
     int rez;
@@ -903,7 +890,7 @@
                 return;// no free surface to draw OSD in
 
             rez = XvMCBlendSubpicture2(mDisplay,
-                        p_render_surface_to_show->p_surface, osd_rndr->p_surface,
+                        p_render_surface_to_show->shared.p_surface, osd_rndr->shared.p_surface,
                         &subpicture,
                         0, 0, subpicture.width, subpicture.height,
                         0, 0, image_width, image_height);
@@ -915,13 +902,12 @@
 //       XvMCFlushSurface(mDisplay,osd_rndr->p_surface);//fixme- should I?
 
             //When replaceing the surface with osd one, save the flags too!
-            osd_rndr->picture_structure = p_render_surface_to_show->picture_structure;
+            osd_rndr->shared.picture_structure = p_render_surface_to_show->shared.picture_structure;
 //add more if needed    osd_rndr-> = p_render_surface_to_show->;
 
             add_state(p_render_surface_to_show, STATE_OSD_SOURCE);
             remove_state(p_render_surface_to_show, STATE_DISPLAY_PENDING);
-            info = get_render_info(p_render_surface_to_show);
-            info->p_osd_target_surface_render = osd_rndr;
+            p_render_surface_to_show->p_osd_target_surface_render = osd_rndr;
 
             p_render_surface_to_show = osd_rndr;
             add_state(p_render_surface_to_show, STATE_DISPLAY_PENDING);
@@ -930,7 +916,7 @@
         }//endof if(BLEND)
         if(subpicture_mode == BACKEND_SUBPICTURE){
             rez = XvMCBlendSubpicture(mDisplay,
-                        p_render_surface_to_show->p_surface,
+                        p_render_surface_to_show->shared.p_surface,
                         &subpicture,
                         0, 0, subpicture.width, subpicture.height,
                         0, 0, image_width, image_height);
@@ -961,7 +947,7 @@
     XvMCSyncSurface(mDisplay, srf);
 }
 
-static void put_xvmc_image(struct xvmc_pix_fmt *p_render_surface,
+static void put_xvmc_image(struct xvmc_render *p_render_surface,
                            int draw_ck){
     int rez;
     struct vo_rect src_rect, dst_rect;
@@ -980,7 +966,7 @@
 
     for (i = 1; i <= bob_deinterlace + 1; i++) {
         int field = top_field_first ? i : i ^ 3;
-        rez = XvMCPutSurface(mDisplay, p_render_surface->p_surface,
+        rez = XvMCPutSurface(mDisplay, p_render_surface->shared.p_surface,
                             vo_window,
                             src_rect.left, src_rect.top, src_rect.width, src_rect.height,
                             dst_rect.left, dst_rect.top, dst_rect.width, dst_rect.height,
@@ -999,7 +985,7 @@
     mp_msg(MSGT_VO,MSGL_DBG4,"vo_xvmc: flip_page  show(rndr=%p)\n\n",p_render_surface_to_show);
 
     if(p_render_surface_to_show == NULL) return;
-    assert( p_render_surface_to_show->xvmc_id == AV_XVMC_ID );
+    assert( p_render_surface_to_show->shared.xvmc_id == AV_XVMC_ID );
 //fixme   assert( p_render_surface_to_show != p_render_surface_visible);
 
     if(use_queue){
@@ -1009,7 +995,7 @@
         show_queue[free_element++] = p_render_surface_to_show;
         if(cfs > 3){//well have 3 free surfaces after add queue
             if(free_element > 1)//a little voodoo magic
-                xvmc_sync_surface(show_queue[0]->p_surface);
+                xvmc_sync_surface(show_queue[0]->shared.p_surface);
             return;
         }
         p_render_surface_to_show=show_queue[0];
@@ -1022,7 +1008,7 @@
     }
 
 // make sure the rendering is done
-    xvmc_sync_surface(p_render_surface_to_show->p_surface);
+    xvmc_sync_surface(p_render_surface_to_show->shared.p_surface);
 
 //the visible surface won't be displayed anymore, mark it as free
     if(p_render_surface_visible != NULL)
@@ -1074,13 +1060,13 @@
             XvMCHideSurface(mDisplay,&surface_array[i]);//it doesn't hurt, I hope
             XvMCDestroySurface(mDisplay,&surface_array[i]);
 
-            if( (surface_render_info[i].state != 0) &&
+            if( (surface_render[i].state != 0) &&
                 (p_render_surface_visible != &surface_render[i]) )
                 mp_msg(MSGT_VO,MSGL_INFO,"vo_xvmc::uninit surface_render[%d].status=%d\n",i,
-                        surface_render_info[i].state);
+                        surface_render[i].state);
         }
 
-        memset(surface_render, 0, MAX_SURFACES * sizeof(struct xvmc_pix_fmt)); //for debugging
+        memset(surface_render, 0, MAX_SURFACES * sizeof(struct xvmc_render)); //for debugging
         free(surface_render);surface_render=NULL;
 
         XvMCDestroyContext(mDisplay,&ctx);
@@ -1132,21 +1118,21 @@
 
 static int draw_slice(uint8_t *image[], int stride[],
                            int w, int h, int x, int y){
-    struct xvmc_pix_fmt *rndr;
+    struct xvmc_render *rndr;
     int rez;
 
     mp_msg(MSGT_VO,MSGL_DBG4,"vo_xvmc: draw_slice y=%d\n",y);
 
-    rndr = (struct xvmc_pix_fmt*)image[2]; //this is copy of priv-ate
+    rndr = (struct xvmc_render*)image[2]; //this is copy of priv-ate
     assert( rndr != NULL );
-    assert( rndr->xvmc_id == AV_XVMC_ID );
+    assert( rndr->shared.xvmc_id == AV_XVMC_ID );
 
-    rez = XvMCRenderSurface(mDisplay,&ctx,rndr->picture_structure,
-                            rndr->p_surface,
-                            rndr->p_past_surface,
-                            rndr->p_future_surface,
-                            rndr->flags,
-                            rndr->filled_mv_blocks_num,rndr->start_mv_blocks_num,
+    rez = XvMCRenderSurface(mDisplay,&ctx,rndr->shared.picture_structure,
+                            rndr->shared.p_surface,
+                            rndr->shared.p_past_surface,
+                            rndr->shared.p_future_surface,
+                            rndr->shared.flags,
+                            rndr->shared.filled_mv_blocks_num,rndr->shared.start_mv_blocks_num,
                             &mv_blocks,&data_blocks);
     if(rez != Success)
     {
@@ -1154,12 +1140,12 @@
         mp_msg(MSGT_VO,MSGL_ERR,"vo_xvmc::slice: RenderSirface returned %d\n",rez);
 
         mp_msg(MSGT_VO,MSGL_ERR,"vo_xvmc::slice: pict=%d,flags=%x,start_blocks=%d,num_blocks=%d\n",
-                rndr->picture_structure,rndr->flags,rndr->start_mv_blocks_num,
-                rndr->filled_mv_blocks_num);
+                rndr->shared.picture_structure,rndr->shared.flags,rndr->shared.start_mv_blocks_num,
+                rndr->shared.filled_mv_blocks_num);
         mp_msg(MSGT_VO,MSGL_ERR,"vo_xvmc::slice: this_surf=%p, past_surf=%p, future_surf=%p\n",
-                rndr->p_surface,rndr->p_past_surface,rndr->p_future_surface);
+                rndr->shared.p_surface,rndr->shared.p_past_surface,rndr->shared.p_future_surface);
 
-        for(i=0; i<rndr->filled_mv_blocks_num; i++){
+        for(i=0; i<rndr->shared.filled_mv_blocks_num; i++){
             XvMCMacroBlock* testblock;
             testblock = &mv_blocks.macro_blocks[i];
 
@@ -1175,29 +1161,29 @@
     }
     assert(rez==Success);
     mp_msg(MSGT_VO,MSGL_DBG4,"vo_xvmc: flush surface\n");
-    rez = XvMCFlushSurface(mDisplay, rndr->p_surface);
+    rez = XvMCFlushSurface(mDisplay, rndr->shared.p_surface);
     assert(rez==Success);
 
 //   rndr->start_mv_blocks_num += rndr->filled_mv_blocks_num;
-    rndr->start_mv_blocks_num = 0;
-    rndr->filled_mv_blocks_num = 0;
+    rndr->shared.start_mv_blocks_num = 0;
+    rndr->shared.filled_mv_blocks_num = 0;
 
-    rndr->next_free_data_block_num = 0;
+    rndr->shared.next_free_data_block_num = 0;
 
     return VO_TRUE;
 }
 
 //XvMCHide hides the surface on next retrace, so
 //check if the surface is not still displaying
-static void check_osd_source(struct xvmc_pix_fmt *src_rndr) {
-    struct xvmc_pix_fmt *osd_rndr;
+static void check_osd_source(struct xvmc_render *src_rndr) {
+    struct xvmc_render *osd_rndr;
     int stat;
 
     //If this is source surface, check does the OSD rendering is compleate
-    if(get_render_info(src_rndr)->state & STATE_OSD_SOURCE){
+    if(src_rndr->state & STATE_OSD_SOURCE){
         mp_msg(MSGT_VO,MSGL_DBG4,"vo_xvmc: OSD surface=%p querying\n",src_rndr);
-        osd_rndr = get_render_info(src_rndr)->p_osd_target_surface_render;
-        XvMCGetSurfaceStatus(mDisplay, osd_rndr->p_surface, &stat);
+        osd_rndr = src_rndr->p_osd_target_surface_render;
+        XvMCGetSurfaceStatus(mDisplay, osd_rndr->shared.p_surface, &stat);
         if(!(stat & XVMC_RENDERING))
             remove_state(src_rndr, STATE_OSD_SOURCE);
     }
@@ -1214,17 +1200,17 @@
     return num;
 }
 
-static struct xvmc_pix_fmt *find_free_surface(void) {
+static struct xvmc_render *find_free_surface(void) {
     int i,t;
     int stat;
-    struct xvmc_pix_fmt *visible_rndr;
+    struct xvmc_render *visible_rndr;
 
     visible_rndr = NULL;
     for(i=0; i<number_of_surfaces; i++){
 
         check_osd_source(&surface_render[i]);
         if( !in_use(surface_render + i)){
-            XvMCGetSurfaceStatus(mDisplay, surface_render[i].p_surface,&stat);
+            XvMCGetSurfaceStatus(mDisplay, surface_render[i].shared.p_surface,&stat);
             if( (stat & XVMC_DISPLAYING) == 0 )
                 return &surface_render[i];
             visible_rndr = &surface_render[i];// remember it, use as last resort
@@ -1237,7 +1223,7 @@
         mp_msg(MSGT_VO,MSGL_INFO,"vo_xvmc: waiting retrace\n");
         for(t=0;t<1000;t++){
             usec_sleep(1000);//1ms
-            XvMCGetSurfaceStatus(mDisplay, visible_rndr->p_surface,&stat);
+            XvMCGetSurfaceStatus(mDisplay, visible_rndr->shared.p_surface,&stat);
             if( (stat & XVMC_DISPLAYING) == 0 )
                 return visible_rndr;
         }
@@ -1245,7 +1231,7 @@
 //todo remove when stable
     mp_msg(MSGT_VO,MSGL_WARN,"vo_xvmc: no free surfaces, this should not happen in g1\n");
     for(i=0;i<number_of_surfaces;i++)
-        mp_msg(MSGT_VO,MSGL_WARN,"vo_xvmc: surface[%d].state=%d\n",i,surface_render_info[i].state);
+        mp_msg(MSGT_VO,MSGL_WARN,"vo_xvmc: surface[%d].state=%d\n",i,surface_render[i].state);
     return NULL;
 }
 
@@ -1255,17 +1241,17 @@
     for(i=0; i<number_of_surfaces; i++){
 
         remove_state(surface_render + i, STATE_DISPLAY_PENDING | STATE_OSD_SOURCE);
-        surface_render_info[i].p_osd_target_surface_render=NULL;
-        if(surface_render_info[i].state != 0){
+        surface_render[i].p_osd_target_surface_render=NULL;
+        if(surface_render[i].state != 0){
             mp_msg(MSGT_VO,MSGL_WARN,"vo_xvmc: surface[%d].state=%d\n",
-                                   i,surface_render_info[i].state);
+                                   i,surface_render[i].state);
         }
     }
     free_element=0;//clean up the queue
 }
 
 static uint32_t get_image(mp_image_t *mpi){
-    struct xvmc_pix_fmt *rndr;
+    struct xvmc_render *rndr;
 
     rndr = find_free_surface();
 
@@ -1274,15 +1260,15 @@
         return VO_FALSE;
     }
 
-assert(rndr->start_mv_blocks_num == 0);
-assert(rndr->filled_mv_blocks_num == 0);
-assert(rndr->next_free_data_block_num == 0);
+assert(rndr->shared.start_mv_blocks_num == 0);
+assert(rndr->shared.filled_mv_blocks_num == 0);
+assert(rndr->shared.next_free_data_block_num == 0);
 
     mpi->flags |= MP_IMGFLAG_DIRECT;
 //keep strides 0 to avoid field manipulations
     mpi->stride[0] = 0;
     mpi->stride[1] = 0;
-    mpi->stride[2] = 0;
+    mpi->stride[2] = sizeof(rndr);
 
 // these are shared!! so watch out
 // do call RenderSurface before overwriting
@@ -1291,16 +1277,16 @@
     mpi->priv =
     mpi->planes[2] = (char*)rndr;
 
-    rndr->picture_structure = 0;
-    rndr->flags = 0;
-    get_render_info(rndr)->state = 0;
-    get_render_info(rndr)->mpi = mpi;
-    rndr->start_mv_blocks_num = 0;
-    rndr->filled_mv_blocks_num = 0;
-    rndr->next_free_data_block_num = 0;
+    rndr->shared.picture_structure = 0;
+    rndr->shared.flags = 0;
+    rndr->state = 0;
+    rndr->mpi = mpi;
+    rndr->shared.start_mv_blocks_num = 0;
+    rndr->shared.filled_mv_blocks_num = 0;
+    rndr->shared.next_free_data_block_num = 0;
 
     mp_msg(MSGT_VO,MSGL_DBG4,"vo_xvmc: get_image: rndr=%p (surface=%p) \n",
-                rndr,rndr->p_surface);
+                rndr,rndr->shared.p_surface);
 return VO_TRUE;
 }