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 + -
显示快捷键?