comparison libvo/vo_vdpau.c @ 29735:8adf928e517a

Try to recover from VDPAU display pre-emptions. Original patch by Uoti.
author cehoyos
date Sat, 17 Oct 2009 15:15:07 +0000
parents 42abcc270fb6
children 593354e0500d
comparison
equal deleted inserted replaced
29734:54145563612e 29735:8adf928e517a
140 static VdpDecoderCreate *vdp_decoder_create; 140 static VdpDecoderCreate *vdp_decoder_create;
141 static VdpDecoderDestroy *vdp_decoder_destroy; 141 static VdpDecoderDestroy *vdp_decoder_destroy;
142 static VdpDecoderRender *vdp_decoder_render; 142 static VdpDecoderRender *vdp_decoder_render;
143 143
144 static VdpGenerateCSCMatrix *vdp_generate_csc_matrix; 144 static VdpGenerateCSCMatrix *vdp_generate_csc_matrix;
145 static VdpPreemptionCallbackRegister *vdp_preemption_callback_register;
145 146
146 static void *vdpau_lib_handle; 147 static void *vdpau_lib_handle;
147 /* output_surfaces[NUM_OUTPUT_SURFACES] is misused for OSD. */ 148 /* output_surfaces[NUM_OUTPUT_SURFACES] is misused for OSD. */
148 #define osd_surface output_surfaces[NUM_OUTPUT_SURFACES] 149 #define osd_surface output_surfaces[NUM_OUTPUT_SURFACES]
149 static VdpOutputSurface output_surfaces[NUM_OUTPUT_SURFACES + 1]; 150 static VdpOutputSurface output_surfaces[NUM_OUTPUT_SURFACES + 1];
175 static int vid_surface_num; 176 static int vid_surface_num;
176 static uint32_t vid_width, vid_height; 177 static uint32_t vid_width, vid_height;
177 static uint32_t image_format; 178 static uint32_t image_format;
178 static VdpChromaType vdp_chroma_type; 179 static VdpChromaType vdp_chroma_type;
179 static VdpYCbCrFormat vdp_pixel_format; 180 static VdpYCbCrFormat vdp_pixel_format;
181
182 static volatile int is_preempted;
180 183
181 /* draw_osd */ 184 /* draw_osd */
182 static unsigned char *index_data; 185 static unsigned char *index_data;
183 static int index_data_size; 186 static int index_data_size;
184 static uint32_t palette[PALETTE_SIZE]; 187 static uint32_t palette[PALETTE_SIZE];
307 } 310 }
308 } 311 }
309 video_to_output_surface(); 312 video_to_output_surface();
310 if (visible_buf) 313 if (visible_buf)
311 flip_page(); 314 flip_page();
315 }
316
317 static void preemption_callback(VdpDevice device, void *context)
318 {
319 mp_msg(MSGT_VO, MSGL_ERR, "[vdpau] Display preemption detected\n");
320 is_preempted = 1;
312 } 321 }
313 322
314 /* Initialize vdp_get_proc_address, called from preinit() */ 323 /* Initialize vdp_get_proc_address, called from preinit() */
315 static int win_x11_init_vdpau_procs(void) 324 static int win_x11_init_vdpau_procs(void)
316 { 325 {
364 {VDP_FUNC_ID_BITMAP_SURFACE_PUT_BITS_NATIVE, 373 {VDP_FUNC_ID_BITMAP_SURFACE_PUT_BITS_NATIVE,
365 &vdp_bitmap_surface_putbits_native}, 374 &vdp_bitmap_surface_putbits_native},
366 {VDP_FUNC_ID_OUTPUT_SURFACE_RENDER_BITMAP_SURFACE, 375 {VDP_FUNC_ID_OUTPUT_SURFACE_RENDER_BITMAP_SURFACE,
367 &vdp_output_surface_render_bitmap_surface}, 376 &vdp_output_surface_render_bitmap_surface},
368 {VDP_FUNC_ID_GENERATE_CSC_MATRIX, &vdp_generate_csc_matrix}, 377 {VDP_FUNC_ID_GENERATE_CSC_MATRIX, &vdp_generate_csc_matrix},
378 {VDP_FUNC_ID_PREEMPTION_CALLBACK_REGISTER,
379 &vdp_preemption_callback_register},
369 {0, NULL} 380 {0, NULL}
370 }; 381 };
371 382
372 vdp_st = vdp_device_create(mDisplay, mScreen, 383 vdp_st = vdp_device_create(mDisplay, mScreen,
373 &vdp_device, &vdp_get_proc_address); 384 &vdp_device, &vdp_get_proc_address);
383 mp_msg(MSGT_VO, MSGL_ERR, "[vdpau] Error when calling vdp_get_proc_address(function id %d): %s\n", 394 mp_msg(MSGT_VO, MSGL_ERR, "[vdpau] Error when calling vdp_get_proc_address(function id %d): %s\n",
384 dsc->id, vdp_get_error_string ? vdp_get_error_string(vdp_st) : "?"); 395 dsc->id, vdp_get_error_string ? vdp_get_error_string(vdp_st) : "?");
385 return -1; 396 return -1;
386 } 397 }
387 } 398 }
399 vdp_st = vdp_preemption_callback_register(vdp_device,
400 preemption_callback, NULL);
401 CHECK_ST_ERROR("Error when calling vdp_preemption_callback_register")
402
388 return 0; 403 return 0;
389 } 404 }
390 405
391 /* Initialize vdpau_flip_queue, called from config() */ 406 /* Initialize vdpau_flip_queue, called from config() */
392 static int win_x11_init_vdpau_flip_queue(void) 407 static int win_x11_init_vdpau_flip_queue(void)
557 } 572 }
558 decoder_max_refs = max_refs; 573 decoder_max_refs = max_refs;
559 return 1; 574 return 1;
560 } 575 }
561 576
577 static void mark_vdpau_objects_uninitialized(void)
578 {
579 int i;
580
581 decoder = VDP_INVALID_HANDLE;
582 for (i = 0; i < MAX_VIDEO_SURFACES; i++)
583 surface_render[i].surface = VDP_INVALID_HANDLE;
584 for (i = 0; i < 3; i++) {
585 deint_surfaces[i] = VDP_INVALID_HANDLE;
586 if (i < 2 && deint_mpi[i])
587 deint_mpi[i]->usage_count--;
588 deint_mpi[i] = NULL;
589 }
590 video_mixer = VDP_INVALID_HANDLE;
591 vdp_flip_queue = VDP_INVALID_HANDLE;
592 vdp_flip_target = VDP_INVALID_HANDLE;
593 for (i = 0; i <= NUM_OUTPUT_SURFACES; i++)
594 output_surfaces[i] = VDP_INVALID_HANDLE;
595 vdp_device = VDP_INVALID_HANDLE;
596 for (i = 0; i < eosd_surface_count; i++)
597 eosd_surfaces[i].surface = VDP_INVALID_HANDLE;
598 output_surface_width = output_surface_height = -1;
599 eosd_render_count = 0;
600 visible_buf = 0;
601 }
602
603 static int handle_preemption(void)
604 {
605 if (!is_preempted)
606 return 0;
607 is_preempted = 0;
608 mp_msg(MSGT_VO, MSGL_INFO, "[vdpau] Attempting to recover from preemption.\n");
609 mark_vdpau_objects_uninitialized();
610 if (win_x11_init_vdpau_procs() < 0 ||
611 win_x11_init_vdpau_flip_queue() < 0 ||
612 create_vdp_mixer(vdp_chroma_type) < 0) {
613 mp_msg(MSGT_VO, MSGL_ERR, "[vdpau] Recovering from preemption failed\n");
614 is_preempted = 1;
615 return -1;
616 }
617 resize();
618 mp_msg(MSGT_VO, MSGL_INFO, "[vdpau] Recovered from display preemption.\n");
619 return 1;
620 }
621
562 /* 622 /*
563 * connect to X server, create and map window, initialize all 623 * connect to X server, create and map window, initialize all
564 * VDPAU objects, create different surfaces etc. 624 * VDPAU objects, create different surfaces etc.
565 */ 625 */
566 static int config(uint32_t width, uint32_t height, uint32_t d_width, 626 static int config(uint32_t width, uint32_t height, uint32_t d_width,
662 } 722 }
663 723
664 static void check_events(void) 724 static void check_events(void)
665 { 725 {
666 int e = vo_x11_check_events(mDisplay); 726 int e = vo_x11_check_events(mDisplay);
727
728 if (handle_preemption() < 0)
729 return;
667 730
668 if (e & VO_EVENT_RESIZE) 731 if (e & VO_EVENT_RESIZE)
669 resize(); 732 resize();
670 733
671 if ((e & VO_EVENT_EXPOSE || e & VO_EVENT_RESIZE) && int_pause) { 734 if ((e & VO_EVENT_EXPOSE || e & VO_EVENT_RESIZE) && int_pause) {
862 925
863 static void draw_osd(void) 926 static void draw_osd(void)
864 { 927 {
865 mp_msg(MSGT_VO, MSGL_DBG2, "DRAW_OSD\n"); 928 mp_msg(MSGT_VO, MSGL_DBG2, "DRAW_OSD\n");
866 929
930 if (handle_preemption() < 0)
931 return;
932
867 vo_draw_text_ext(vo_dwidth, vo_dheight, border_x, border_y, border_x, border_y, 933 vo_draw_text_ext(vo_dwidth, vo_dheight, border_x, border_y, border_x, border_y,
868 vid_width, vid_height, draw_osd_I8A8); 934 vid_width, vid_height, draw_osd_I8A8);
869 } 935 }
870 936
871 static void flip_page(void) 937 static void flip_page(void)
872 { 938 {
873 VdpStatus vdp_st; 939 VdpStatus vdp_st;
874 mp_msg(MSGT_VO, MSGL_DBG2, "\nFLIP_PAGE VID:%u -> OUT:%u\n", 940 mp_msg(MSGT_VO, MSGL_DBG2, "\nFLIP_PAGE VID:%u -> OUT:%u\n",
875 surface_render[vid_surface_num].surface, output_surfaces[surface_num]); 941 surface_render[vid_surface_num].surface, output_surfaces[surface_num]);
942
943 if (handle_preemption() < 0)
944 return;
876 945
877 vdp_st = vdp_presentation_queue_display(vdp_flip_queue, output_surfaces[surface_num], 946 vdp_st = vdp_presentation_queue_display(vdp_flip_queue, output_surfaces[surface_num],
878 vo_dwidth, vo_dheight, 947 vo_dwidth, vo_dheight,
879 0); 948 0);
880 CHECK_ST_WARNING("Error when calling vdp_presentation_queue_display") 949 CHECK_ST_WARNING("Error when calling vdp_presentation_queue_display")
887 int x, int y) 956 int x, int y)
888 { 957 {
889 VdpStatus vdp_st; 958 VdpStatus vdp_st;
890 struct vdpau_render_state *rndr = (struct vdpau_render_state *)image[0]; 959 struct vdpau_render_state *rndr = (struct vdpau_render_state *)image[0];
891 int max_refs = image_format == IMGFMT_VDPAU_H264 ? rndr->info.h264.num_ref_frames : 2; 960 int max_refs = image_format == IMGFMT_VDPAU_H264 ? rndr->info.h264.num_ref_frames : 2;
961
962 if (handle_preemption() < 0)
963 return VO_TRUE;
964
892 if (!IMGFMT_IS_VDPAU(image_format)) 965 if (!IMGFMT_IS_VDPAU(image_format))
893 return VO_FALSE; 966 return VO_FALSE;
894 if ((decoder == VDP_INVALID_HANDLE || decoder_max_refs < max_refs) 967 if ((decoder == VDP_INVALID_HANDLE || decoder_max_refs < max_refs)
895 && !create_vdp_decoder(max_refs)) 968 && !create_vdp_decoder(max_refs))
896 return VO_FALSE; 969 return VO_FALSE;
1201 return update_csc_matrix(); 1274 return update_csc_matrix();
1202 } 1275 }
1203 1276
1204 static int control(uint32_t request, void *data, ...) 1277 static int control(uint32_t request, void *data, ...)
1205 { 1278 {
1279 if (handle_preemption() < 0)
1280 return VO_FALSE;
1281
1206 switch (request) { 1282 switch (request) {
1207 case VOCTRL_GET_DEINTERLACE: 1283 case VOCTRL_GET_DEINTERLACE:
1208 *(int*)data = deint; 1284 *(int*)data = deint;
1209 return VO_TRUE; 1285 return VO_TRUE;
1210 case VOCTRL_SET_DEINTERLACE: 1286 case VOCTRL_SET_DEINTERLACE: