vo_xvmc.c

来自「君正早期ucos系统(只有早期的才不没有打包成库),MPLAYER,文件系统,图」· C语言 代码 · 共 1,427 行 · 第 1/3 页

C
1,427
字号
         p_render_surface_to_show = osd_rndr;         p_render_surface_to_show->state = MP_XVMC_STATE_DISPLAY_PENDING;         if( mp_msg_test(MSGT_VO,MSGL_DBG4) )            printf("vo_xvmc:draw_osd: surface_to_show changed to %p\n",osd_rndr);      }//endof if(BLEND)      if(subpicture_mode == BACKEND_SUBPICTURE){         rez = XvMCBlendSubpicture(mDisplay,                       p_render_surface_to_show->p_surface,                       &subpicture,                       0, 0, subpicture.width, subpicture.height,                       0, 0, image_width, image_height);      }      }//if(BLEND||BACKEND)}static void xvmc_sync_surface(XvMCSurface * srf){int status,rez;   rez = XvMCGetSurfaceStatus(mDisplay,srf,&status);   assert(rez==Success);   if((status & XVMC_RENDERING) == 0)      return;//surface is already complete   if(use_sleep){      rez = XvMCFlushSurface(mDisplay, srf);      assert(rez==Success);      do{         usec_sleep(1000);//1ms (may be 20ms on linux)         XvMCGetSurfaceStatus(mDisplay,srf,&status);      } while (status & XVMC_RENDERING);      return;//done   }          XvMCSyncSurface(mDisplay, srf);}static void put_xvmc_image(xvmc_render_state_t * p_render_surface, int draw_ck){int rez;int clipX,clipY,clipW,clipH;int i;   if(p_render_surface == NULL)      return;   clipX = drwX-(vo_panscan_x>>1);   clipY = drwY-(vo_panscan_y>>1);    clipW = vo_dwidth+vo_panscan_x;   clipH = vo_dheight+vo_panscan_y;      if(draw_ck)      vo_xv_draw_colorkey(clipX,clipY,clipW,clipH);   if(benchmark)      return;   for (i = 1; i <= bob_deinterlace + 1; i++) {   int field = top_field_first ? i : i ^ 3;   rez = XvMCPutSurface(mDisplay, p_render_surface->p_surface,                         vo_window,                        0, 0, image_width, image_height,                        clipX, clipY, clipW, clipH,                        bob_deinterlace ? field : 3);                        //p_render_surface_to_show->display_flags);   if(rez != Success){      printf("vo_xvmc: PutSurface failer, critical error %d!\n",rez);      assert(0);   }   }   XFlush(mDisplay);}static void flip_page(void){int i,cfs;   if( mp_msg_test(MSGT_VO,MSGL_DBG4) )      printf("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->magic == MP_XVMC_RENDER_MAGIC );//fixme   assert( p_render_surface_to_show != p_render_surface_visible);   if(use_queue){      // fill the queue until only n free surfaces remain      // after that start displaying      cfs = count_free_surfaces();      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);         return;       }      p_render_surface_to_show=show_queue[0];      if( mp_msg_test(MSGT_VO,MSGL_DBG5) )         printf("vo_xvmc: flip_queue free_element=%d\n",free_element);      free_element--;      for(i=0; i<free_element; i++){         show_queue[i] = show_queue[i+1];      }      show_queue[free_element] = NULL;   }// make sure the rendering is done   xvmc_sync_surface(p_render_surface_to_show->p_surface);//the visible surface won't be displayed anymore, mark it as free   if(p_render_surface_visible != NULL)      p_render_surface_visible->state &= ~MP_XVMC_STATE_DISPLAY_PENDING;//!!fixme   assert(p_render_surface_to_show->state & MP_XVMC_STATE_DISPLAY_PENDING);   //show it, displaying is always vsynced, so skip it for benchmark   put_xvmc_image(p_render_surface_to_show,first_frame);   first_frame=0;//make sure we won't draw it anymore   p_render_surface_visible = p_render_surface_to_show;   p_render_surface_to_show = NULL;}static void check_events(void){Window mRoot;uint32_t drwBorderWidth,drwDepth;int e=vo_x11_check_events(mDisplay);   if(e&VO_EVENT_RESIZE)   {      e |= VO_EVENT_EXPOSE;      XGetGeometry( mDisplay,vo_window,&mRoot,&drwX,&drwY,&vo_dwidth,&vo_dheight,                   &drwBorderWidth,&drwDepth );      mp_msg(MSGT_VO,MSGL_V, "[xvmc] dx: %d dy: %d dw: %d dh: %d\n",drwX,drwY,              vo_dwidth,vo_dheight );      calc_drwXY(&drwX, &drwY);   }   if ( e & VO_EVENT_EXPOSE )   {      put_xvmc_image(p_render_surface_visible,1);   }}static void xvmc_free(void){int i;   if( subpicture_alloc ){      XvMCDestroySubpicture(mDisplay,&subpicture);      deallocate_xvimage();      subpicture_alloc = 0;      if( mp_msg_test(MSGT_VO,MSGL_DBG4) )         printf("vo_xvmc: subpicture destroyed\n");   }   if( number_of_surfaces ){      XvMCDestroyMacroBlocks(mDisplay,&mv_blocks);      XvMCDestroyBlocks(mDisplay,&data_blocks);      for(i=0; i<number_of_surfaces; i++)      {         XvMCHideSurface(mDisplay,&surface_array[i]);//it doesn't hurt, I hope         XvMCDestroySurface(mDisplay,&surface_array[i]);         if( (surface_render[i].state != 0) &&              (p_render_surface_visible != &surface_render[i]) )            printf("vo_xvmc::uninit surface_render[%d].status=%d\n",i,                    surface_render[i].state);       }      memset(surface_render,0,MAX_SURFACES*sizeof(xvmc_render_state_t));//for debuging      free(surface_render);surface_render=NULL;      XvMCDestroyContext(mDisplay,&ctx);      number_of_surfaces = 0;      if( mp_msg_test(MSGT_VO,MSGL_DBG4) ) {         printf("vo_xvmc: Context sucessfuly freed\n"); }   }   if( xv_port !=0 ){      XvUngrabPort(mDisplay,xv_port,CurrentTime);      xv_port = 0;      if( mp_msg_test(MSGT_VO,MSGL_DBG4) ) {         printf("vo_xvmc: xv_port sucessfuly ungrabed\n"); }   }}static void uninit(void){   if( mp_msg_test(MSGT_VO,MSGL_DBG4) ) {      printf("vo_xvmc: uninit called\n"); }   xvmc_free(); //from vo_xv#ifdef HAVE_XF86VM   vo_vm_close(mDisplay);#endif   vo_x11_uninit();}static int query_format(uint32_t format){uint32_t flags;XvMCSurfaceInfo qsurface_info;int mode_id;   if( mp_msg_test(MSGT_VO,MSGL_DBG4) )      printf("vo_xvmc: query_format=%X\n",format);   if(!IMGFMT_IS_XVMC(format)) return 0;// no caps supported   mode_id = xvmc_find_surface_by_format(format, 16, 16, &qsurface_info, 1);//true=1 - quering   if( mode_id == 0 ) return 0;   flags = VFCAP_CSP_SUPPORTED |           VFCAP_CSP_SUPPORTED_BY_HW |	   VFCAP_ACCEPT_STRIDE;   if( (qsurface_info.subpicture_max_width  != 0) &&       (qsurface_info.subpicture_max_height != 0) )      flags|=VFCAP_OSD;   return flags;}static int draw_slice(uint8_t *image[], int stride[],			   int w, int h, int x, int y){xvmc_render_state_t * rndr;int rez;   if( mp_msg_test(MSGT_VO,MSGL_DBG4) )      printf("vo_xvmc: draw_slice y=%d\n",y);   rndr = (xvmc_render_state_t*)image[2];//this is copy of priv-ate   assert( rndr != NULL );   assert( rndr->magic == MP_XVMC_RENDER_MAGIC );   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,                           &mv_blocks,&data_blocks);#if 1   if(rez != Success)   {   int i;      printf("vo_xvmc::slice: RenderSirface returned %d\n",rez);      printf("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);      printf("vo_xvmc::slice: this_surf=%p, past_surf=%p, future_surf=%p\n",             rndr->p_surface,rndr->p_past_surface,rndr->p_future_surface);      for(i=0; i<rndr->filled_mv_blocks_num; i++){       XvMCMacroBlock* testblock;         testblock = &mv_blocks.macro_blocks[i];	 printf("vo_xvmc::slice: mv_block - x=%d,y=%d,mb_type=0x%x,mv_type=0x%x,mv_field_select=%d\n",	        testblock->x,testblock->y,testblock->macroblock_type,	        testblock->motion_type,testblock->motion_vertical_field_select);         printf("vo_xvmc::slice: dct_type=%d,data_index=0x%x,cbp=%d,pad0=%d\n",	         testblock->dct_type,testblock->index,testblock->coded_block_pattern,	         testblock->pad0);         printf("vo_xvmc::slice: PMV[0][0][0/1]=(%d,%d)\n",	         testblock->PMV[0][0][0],testblock->PMV[0][0][1]);       }   }#endif   assert(rez==Success);   if( mp_msg_test(MSGT_VO,MSGL_DBG4) ) printf("vo_xvmc: flush surface\n");   rez = XvMCFlushSurface(mDisplay, rndr->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->next_free_data_block_num = 0;   return VO_TRUE;}//XvMCHide hides the surface on next retrace, so//check if the surface is not still displayingstatic void check_osd_source(xvmc_render_state_t * src_rndr){xvmc_render_state_t * osd_rndr;int stat;      //If this is source surface, check does the OSD rendering is compleate      if(src_rndr->state & MP_XVMC_STATE_OSD_SOURCE){         if( mp_msg_test(MSGT_VO,MSGL_DBG4) )            printf("vo_xvmc: OSD surface=%p quering\n",src_rndr);         osd_rndr = src_rndr->p_osd_target_surface_render;         XvMCGetSurfaceStatus(mDisplay, osd_rndr->p_surface, &stat);         if(!(stat & XVMC_RENDERING))            src_rndr->state &= ~MP_XVMC_STATE_OSD_SOURCE;      }}static int count_free_surfaces(){int i,num;   num=0;   for(i=0; i<number_of_surfaces; i++){      check_osd_source(&surface_render[i]);      if(surface_render[i].state == 0)        num++;   }   return num;}static xvmc_render_state_t * find_free_surface(){int i,t;int stat;xvmc_render_state_t * visible_rndr;   visible_rndr = NULL;   for(i=0; i<number_of_surfaces; i++){      check_osd_source(&surface_render[i]);      if( surface_render[i].state == 0){         XvMCGetSurfaceStatus(mDisplay, surface_render[i].p_surface,&stat);         if( (stat & XVMC_DISPLAYING) == 0 )             return &surface_render[i];         visible_rndr = &surface_render[i];// remember it, use as last resort      }   }   //all surfaces are busy, but there is one that will be free   //on next monitor retrace, we just have to wait   if(visible_rndr != NULL){             printf("vo_xvmc: waiting retrace\n");      for(t=0;t<1000;t++){          usec_sleep(1000);//1ms         XvMCGetSurfaceStatus(mDisplay, visible_rndr->p_surface,&stat);         if( (stat & XVMC_DISPLAYING) == 0 )             return visible_rndr;      }   }//todo remove when stable   printf("vo_xvmc: no free surfaces, this should not happen in g1\n");   for(i=0;i<number_of_surfaces;i++)      printf("vo_xvmc: surface[%d].state=%d\n",i,surface_render[i].state);   return NULL;}static void xvmc_clean_surfaces(void){int i;  for(i=0; i<number_of_surfaces; i++){      surface_render[i].state&=!( MP_XVMC_STATE_DISPLAY_PENDING |                                  MP_XVMC_STATE_OSD_SOURCE |                                  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[i].state);      }   }   free_element=0;//clean up the queue}static uint32_t get_image(mp_image_t *mpi){xvmc_render_state_t * rndr;   rndr = find_free_surface();   if(rndr == NULL){      printf("vo_xvmc: get_image failed\n");      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);   mpi->flags |= MP_IMGFLAG_DIRECT;//keep strides 0 to avoid field manipulations   mpi->stride[0] = 0;   mpi->stride[1] = 0;   mpi->stride[2] = 0;// these are shared!! so watch out// do call RenderSurface before overwriting   mpi->planes[0] = (char*)data_blocks.blocks;      mpi->planes[1] = (char*)mv_blocks.macro_blocks;   mpi->priv =   mpi->planes[2] = (char*)rndr;   rndr->picture_structure = 0;   rndr->flags = 0;   rndr->state = 0;   rndr->start_mv_blocks_num = 0;   rndr->filled_mv_blocks_num = 0;   rndr->next_free_data_block_num = 0;   if( mp_msg_test(MSGT_VO,MSGL_DBG4) )      printf("vo_xvmc: get_image: rndr=%p (surface=%p) \n",             rndr,rndr->p_surface);return VO_TRUE;   }static int control(uint32_t request, void *data, ... ){   switch (request){      case VOCTRL_GET_DEINTERLACE:        *(int*)data = bob_deinterlace;        return VO_TRUE;      case VOCTRL_SET_DEINTERLACE:        bob_deinterlace = *(int*)data;        return VO_TRUE;      case VOCTRL_QUERY_FORMAT:         return query_format(*((uint32_t*)data));      case VOCTRL_DRAW_IMAGE:         return xvmc_draw_image((mp_image_t *)data);      case VOCTRL_GET_IMAGE:	 return get_image((mp_image_t *)data);      //vo_xv      case VOCTRL_GUISUPPORT:         return VO_TRUE;      case VOCTRL_ONTOP:         vo_x11_ontop();	 return VO_TRUE;      case VOCTRL_FULLSCREEN:         vo_x11_fullscreen();      // indended, fallthrough to update panscan on fullscreen/windowed switch      case VOCTRL_SET_PANSCAN:         if ( ( vo_fs && ( vo_panscan != vo_panscan_amount ) ) || ( !vo_fs && vo_panscan_amount ) )         {            int old_y = vo_panscan_y;            panscan_calc();            if(old_y != vo_panscan_y)            {	       //this also draws the colorkey               put_xvmc_image(p_render_surface_visible,1);            }         }         return VO_TRUE;      case VOCTRL_GET_PANSCAN:         if ( !vo_config_count || !vo_fs ) return VO_FALSE;         return VO_TRUE;      case VOCTRL_SET_EQUALIZER:      {      va_list ap;      int value;         va_start(ap, data);         value = va_arg(ap, int);         va_end(ap);         return(vo_xv_set_eq(xv_port, data, value));      }      case VOCTRL_GET_EQUALIZER:      {      va_list ap;      int *value;         va_start(ap, data);         value = va_arg(ap, int*);         va_end(ap);         return(vo_xv_get_eq(xv_port, data, value));      }      case VOCTRL_UPDATE_SCREENINFO:         update_xinerama_info();         return VO_TRUE;   }return VO_NOTIMPL;}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?