summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/libvdpau/h264_parser.c2
-rw-r--r--src/libvdpau/vdpau_h264.c58
-rw-r--r--src/libvdpau/vdpau_mpeg12.c14
-rw-r--r--src/video_out/video_out_vdpau.c105
-rw-r--r--src/xine-engine/accel_vdpau.h3
5 files changed, 162 insertions, 20 deletions
diff --git a/src/libvdpau/h264_parser.c b/src/libvdpau/h264_parser.c
index fcec0b92e..dff73f235 100644
--- a/src/libvdpau/h264_parser.c
+++ b/src/libvdpau/h264_parser.c
@@ -1139,7 +1139,7 @@ int parse_frame(struct nal_parser *parser, uint8_t *inbuf, int inbuf_len,
parser->last_nal_res = parse_nal(prebuf+3, parser->prebuf_len-3, parser);
if (parser->last_nal_res == 1 && parser->buf_len > 0) {
- //printf("Frame complete: %d bytes\n", parser->buf_len);
+ printf("Frame complete: %d bytes\n", parser->buf_len);
*ret_buf = malloc(parser->buf_len);
xine_fast_memcpy(*ret_buf, parser->buf, parser->buf_len);
*ret_len = parser->buf_len;
diff --git a/src/libvdpau/vdpau_h264.c b/src/libvdpau/vdpau_h264.c
index 0f6639125..ca9407063 100644
--- a/src/libvdpau/vdpau_h264.c
+++ b/src/libvdpau/vdpau_h264.c
@@ -82,6 +82,8 @@ typedef struct vdpau_h264_decoder_s {
vo_frame_t *last_img;
vo_frame_t *dangling_img;
+ int vdp_runtime_nr;
+
} vdpau_h264_decoder_t;
/**************************************************************************
@@ -186,7 +188,6 @@ static void vdpau_h264_decode_data (video_decoder_t *this_gen,
this->video_step = buf->decoder_info[0];
_x_stream_info_set(this->stream, XINE_STREAM_INFO_FRAME_DURATION, this->video_step);
}
-
if (buf->decoder_flags & BUF_FLAG_STDHEADER) { /* need to initialize */
xine_bmiheader *bih = (xine_bmiheader*)buf->content;
this->width = bih->biWidth;
@@ -196,14 +197,17 @@ static void vdpau_h264_decode_data (video_decoder_t *this_gen,
/* parse the first nal packages to retrieve profile type */
int len = 0;
+ int write_start_seq = 0;
uint32_t slice_count;
if(buf->pts != 0)
this->next_pts = buf->pts;
- while(len < buf->size) {
- len += parse_frame(this->nal_parser, buf->content + len, buf->size - len,
- (void*)&vdp_buffer.bitstream, &vdp_buffer.bitstream_bytes, &slice_count);
+ while(len < buf->size || write_start_seq == 1) {
+ if(!write_start_seq) {
+ len += parse_frame(this->nal_parser, buf->content + len, buf->size - len,
+ (void*)&vdp_buffer.bitstream, &vdp_buffer.bitstream_bytes, &slice_count);
+ }
if(!this->decoder_initialized &&
this->nal_parser->current_nal != NULL &&
@@ -340,18 +344,19 @@ static void vdpau_h264_decode_data (video_decoder_t *this_gen,
/*VdpBool is_supported;
uint32_t max_level, max_references, max_width, max_height;*/
- xprintf(this->xine, XINE_VERBOSITY_LOG,
- "Create decoder: vdp_device: %d, profile: %d, res: %dx%d\n",
- this->vdpau_accel->vdp_device, this->profile, this->width, this->height);
-
- VdpStatus status = this->vdpau_accel->vdp_decoder_create(this->vdpau_accel->vdp_device,
- this->profile, this->width, this->height, 16, &this->decoder);
-
- if(status != VDP_STATUS_OK)
- xprintf(this->xine, XINE_VERBOSITY_LOG, "vdpau_h264: ERROR: VdpDecoderCreate returned status != OK (%s)\n", this->vdpau_accel->vdp_get_error_string(status));
- else
- this->decoder_initialized = 1;
-
+ if(this->vdpau_accel->vdp_runtime_nr > 0) {
+ xprintf(this->xine, XINE_VERBOSITY_LOG,
+ "Create decoder: vdp_device: %d, profile: %d, res: %dx%d\n",
+ this->vdpau_accel->vdp_device, this->profile, this->width, this->height);
+
+ VdpStatus status = this->vdpau_accel->vdp_decoder_create(this->vdpau_accel->vdp_device,
+ this->profile, this->width, this->height, 16, &this->decoder);
+
+ if(status != VDP_STATUS_OK)
+ xprintf(this->xine, XINE_VERBOSITY_LOG, "vdpau_h264: ERROR: VdpDecoderCreate returned status != OK (%s)\n", this->vdpau_accel->vdp_get_error_string(status));
+ else
+ this->decoder_initialized = 1;
+ }
img->free(img);
img = NULL;
}
@@ -361,7 +366,6 @@ static void vdpau_h264_decode_data (video_decoder_t *this_gen,
this->nal_parser->current_nal->slc != NULL &&
this->nal_parser->current_nal->sps != NULL &&
this->nal_parser->current_nal->pps != NULL) {
-
struct pic_parameter_set_rbsp *pps = this->nal_parser->current_nal->pps;
struct seq_parameter_set_rbsp *sps = this->nal_parser->current_nal->sps;
struct slice_header *slc = this->nal_parser->current_nal->slc;
@@ -452,6 +456,23 @@ static void vdpau_h264_decode_data (video_decoder_t *this_gen,
this->dangling_img = img;
}
+ if(this->vdp_runtime_nr != *(this->vdpau_accel->current_vdp_runtime_nr)) {
+ printf("VDPAU was preempted. Reinitialise the decoder.\n");
+ this->decoder_initialized = 0;
+ this->decoder_started = 0;
+ this->vdp_runtime_nr = this->vdpau_accel->vdp_runtime_nr;
+ this->last_img = NULL;
+ this->last_ref_pic = NULL;
+ dpb_free_all(&this->nal_parser->dpb);
+ free_parser(this->nal_parser);
+ this->nal_parser = init_parser();
+ if(img) {
+ img->free(img);
+ img = NULL;
+ }
+ continue;
+ }
+
VdpVideoSurface surface = this->vdpau_accel->surface;
//printf("Decode: NUM: %d, REF: %d, BYTES: %d, PTS: %lld\n", pic.frame_num, pic.is_reference, vdp_buffer.bitstream_bytes, this->curr_pts);
@@ -543,6 +564,7 @@ static void vdpau_h264_decode_data (video_decoder_t *this_gen,
}
}
}
+
}
}
@@ -649,6 +671,8 @@ static video_decoder_t *open_plugin (video_decoder_class_t *class_gen, xine_stre
this->xine = stream->xine;
this->class = (vdpau_h264_class_t *) class_gen;
+ this->vdp_runtime_nr = 1;
+
this->nal_parser = init_parser();
(this->stream->video_out->open) (this->stream->video_out, this->stream);
diff --git a/src/libvdpau/vdpau_mpeg12.c b/src/libvdpau/vdpau_mpeg12.c
index 7978a7682..819796d0f 100644
--- a/src/libvdpau/vdpau_mpeg12.c
+++ b/src/libvdpau/vdpau_mpeg12.c
@@ -143,6 +143,8 @@ typedef struct {
vdpau_accel_t *accel_vdpau;
+ int vdp_runtime_nr;
+
} sequence_t;
@@ -578,6 +580,7 @@ static void decode_render( vdpau_mpeg12_decoder_t *vd, vdpau_accel_t *accel )
vd->decoder_profile = seq->profile;
vd->decoder_width = seq->coded_width;
vd->decoder_height = seq->coded_height;
+ seq->vdp_runtime_nr = accel->vdp_runtime_nr;
}
}
@@ -671,6 +674,16 @@ static void decode_picture( vdpau_mpeg12_decoder_t *vd )
if ( !seq->accel_vdpau )
seq->accel_vdpau = accel;
+ if( seq->vdp_runtime_nr != *(seq->accel_vdpau->current_vdp_runtime_nr) ) {
+ seq->accel_vdpau = accel;
+ if ( seq->forward_ref )
+ seq->forward_ref->free( seq->forward_ref );
+ seq->forward_ref = NULL;
+ if ( seq->backward_ref )
+ seq->backward_ref->free( seq->backward_ref );
+ seq->backward_ref = NULL;
+ vd->decoder = VDP_INVALID_HANDLE;
+ }
img->drawn = 0;
//printf("vdpau_mpeg12: .. got image %d\n", img);
@@ -870,6 +883,7 @@ static video_decoder_t *open_plugin (video_decoder_class_t *class_gen, xine_stre
this->sequence.buf = (uint8_t*)malloc(this->sequence.bufsize);
this->sequence.forward_ref = 0;
this->sequence.backward_ref = 0;
+ this->sequence.vdp_runtime_nr = 1;
reset_sequence( &this->sequence );
init_picture( &this->sequence.picture );
diff --git a/src/video_out/video_out_vdpau.c b/src/video_out/video_out_vdpau.c
index c7a7f3299..de305d05e 100644
--- a/src/video_out/video_out_vdpau.c
+++ b/src/video_out/video_out_vdpau.c
@@ -120,7 +120,9 @@ VdpDecoderCreate *vdp_decoder_create;
VdpDecoderDestroy *vdp_decoder_destroy;
VdpDecoderRender *vdp_decoder_render;
-
+VdpPreemptionCallbackRegister *vdp_preemption_callback_register;
+static void vdp_preemption_callback( VdpDevice device, void *context );
+static void vdpau_reinit( vo_driver_t *this_gen );
static VdpVideoSurfaceCreate *orig_vdp_video_surface_create;
static VdpVideoSurfaceDestroy *orig_vdp_video_surface_destroy;
@@ -199,6 +201,7 @@ typedef struct {
typedef struct {
+
vo_driver_t vo_driver;
vo_scale_t sc;
@@ -265,6 +268,9 @@ typedef struct {
int enable_inverse_telecine;
int honor_progressive;
+ int vdp_runtime_nr;
+ int reinit_needed;
+
int allocated_surfaces;
} vdpau_driver_t;
@@ -661,6 +667,8 @@ static vo_frame_t *vdpau_alloc_frame (vo_driver_t *this_gen)
frame->vdpau_accel_data.vdp_decoder_destroy = vdp_decoder_destroy;
frame->vdpau_accel_data.vdp_decoder_render = vdp_decoder_render;
frame->vdpau_accel_data.vdp_get_error_string = vdp_get_error_string;
+ frame->vdpau_accel_data.vdp_runtime_nr = this->vdp_runtime_nr;
+ frame->vdpau_accel_data.current_vdp_runtime_nr = &this->vdp_runtime_nr;
return (vo_frame_t *) frame;
}
@@ -796,7 +804,8 @@ static void vdpau_update_frame_format (vo_driver_t *this_gen, vo_frame_t *frame_
VdpChromaType chroma = (flags & VO_CHROMA_422) ? VDP_CHROMA_TYPE_422 : VDP_CHROMA_TYPE_420;
/* Check frame size and format and reallocate if necessary */
- if ( (frame->width != width) || (frame->height != height) || (frame->format != format) || (frame->format==XINE_IMGFMT_VDPAU && frame->vdpau_accel_data.chroma!=chroma) ) {
+ if ( (frame->width != width) || (frame->height != height) || (frame->format != format) || (frame->format==XINE_IMGFMT_VDPAU && frame->vdpau_accel_data.chroma!=chroma) ||
+ (frame->vdpau_accel_data.vdp_runtime_nr != this->vdp_runtime_nr)) {
//printf("vo_vdpau: updating frame to %d x %d (ratio=%g, format=%08X)\n", width, height, ratio, format);
/* (re-) allocate render space */
@@ -833,6 +842,12 @@ static void vdpau_update_frame_format (vo_driver_t *this_gen, vo_frame_t *frame_
}
}
+ if ( frame->vdpau_accel_data.vdp_runtime_nr != this->vdp_runtime_nr ) {
+ frame->vdpau_accel_data.surface = VDP_INVALID_HANDLE;
+ frame->vdpau_accel_data.vdp_runtime_nr = this->vdp_runtime_nr;
+ frame->vdpau_accel_data.vdp_device = vdp_device;
+ }
+
if ( (format == XINE_IMGFMT_VDPAU) && (frame->vdpau_accel_data.surface == VDP_INVALID_HANDLE) ) {
VdpStatus st = vdp_video_surface_create( vdp_device, chroma, width, height, &frame->vdpau_accel_data.surface );
if ( st!=VDP_STATUS_OK )
@@ -1063,6 +1078,9 @@ static void vdpau_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen)
VdpTime stream_speed;
+ if(this->reinit_needed)
+ vdpau_reinit(this_gen);
+
if ( (frame->width != this->sc.delivered_width) || (frame->height != this->sc.delivered_height) || (frame->ratio != this->sc.delivered_ratio) ) {
this->sc.force_redraw = 1; /* trigger re-calc of output size */
}
@@ -1507,7 +1525,81 @@ static int vdpau_init_error( VdpStatus st, const char *msg, vo_driver_t *driver,
return 0;
}
+static void vdpau_reinit( vo_driver_t *this_gen )
+{
+ printf("VDPAU was pre-empted. Reinit.\n");
+ vdpau_driver_t *this = (vdpau_driver_t *)this_gen;
+
+ XLockDisplay(guarded_display);
+ vdpau_release_back_frames(this_gen);
+ VdpStatus st = vdp_device_create_x11( this->display, this->screen, &vdp_device, &vdp_get_proc_address );
+
+ if ( st != VDP_STATUS_OK ) {
+ printf( "vo_vdpau: Can't create vdp device : " );
+ if ( st == VDP_STATUS_NO_IMPLEMENTATION )
+ printf( "No vdpau implementation.\n" );
+ else
+ printf( "unsupported GPU?\n" );
+ vdpau_dispose( &this->vo_driver );
+ return;
+ }
+
+ st = vdp_queue_target_create_x11( vdp_device, this->drawable, &vdp_queue_target );
+ if ( vdpau_init_error( st, "Can't create presentation queue target !!", &this->vo_driver, 1 ) )
+ return;
+ st = vdp_queue_create( vdp_device, vdp_queue_target, &vdp_queue );
+ if ( vdpau_init_error( st, "Can't create presentation queue !!", &this->vo_driver, 1 ) )
+ return;
+
+
+ VdpChromaType chroma = VDP_CHROMA_TYPE_420;
+ st = orig_vdp_video_surface_create( vdp_device, chroma, this->soft_surface_width, this->soft_surface_height, &this->soft_surface );
+ if ( vdpau_init_error( st, "Can't create video surface !!", &this->vo_driver, 1 ) )
+ return;
+
+ this->current_output_surface = 0;
+ this->init_queue = 0;
+ st = vdp_output_surface_create( vdp_device, VDP_RGBA_FORMAT_B8G8R8A8, this->output_surface_width[0], this->output_surface_height[0], &this->output_surface[0] );
+ if ( vdpau_init_error( st, "Can't create first output surface !!", &this->vo_driver, 1 ) ) {
+ orig_vdp_video_surface_destroy( this->soft_surface );
+ return;
+ }
+ st = vdp_output_surface_create( vdp_device, VDP_RGBA_FORMAT_B8G8R8A8, this->output_surface_width[0], this->output_surface_height[0], &this->output_surface[1] );
+ if ( vdpau_init_error( st, "Can't create second output surface !!", &this->vo_driver, 1 ) ) {
+ orig_vdp_video_surface_destroy( this->soft_surface );
+ vdp_output_surface_destroy( this->output_surface[0] );
+ return;
+ }
+
+ this->video_mixer_chroma = chroma;
+ VdpVideoMixerFeature features[] = { VDP_VIDEO_MIXER_FEATURE_NOISE_REDUCTION, VDP_VIDEO_MIXER_FEATURE_SHARPNESS,
+ VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL, VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL_SPATIAL };
+ VdpVideoMixerParameter params[] = { VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_WIDTH, VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_HEIGHT, VDP_VIDEO_MIXER_PARAMETER_CHROMA_TYPE, VDP_VIDEO_MIXER_PARAMETER_LAYERS };
+ int num_layers = 3;
+ void const *param_values[] = { &this->video_mixer_width, &this->video_mixer_height, &chroma, &num_layers };
+ st = vdp_video_mixer_create( vdp_device, 4, features, 4, params, param_values, &this->video_mixer );
+ if ( vdpau_init_error( st, "Can't create video mixer !!", &this->vo_driver, 1 ) ) {
+ orig_vdp_video_surface_destroy( this->soft_surface );
+ vdp_output_surface_destroy( this->output_surface[0] );
+ vdp_output_surface_destroy( this->output_surface[1] );
+ return;
+ }
+
+ vdp_preemption_callback_register(vdp_device, &vdp_preemption_callback, (void*)this);
+
+ XUnlockDisplay(guarded_display);
+ printf("Reinit done.\n");
+ this->vdp_runtime_nr++;
+ this->reinit_needed = 0;
+}
+
+static void vdp_preemption_callback(VdpDevice device, void *context)
+{
+ printf("VDPAU preemption callback\n");
+ vdpau_driver_t *this = (vdpau_driver_t *)context;
+ this->reinit_needed = 1;
+}
static vo_driver_t *vdpau_open_plugin (video_driver_class_t *class_gen, const void *visual_gen)
{
@@ -1707,6 +1799,13 @@ static vo_driver_t *vdpau_open_plugin (video_driver_class_t *class_gen, const vo
st = vdp_get_proc_address( vdp_device, VDP_FUNC_ID_BITMAP_SURFACE_PUT_BITS_NATIVE , (void*)&vdp_bitmap_put_bits );
if ( vdpau_init_error( st, "Can't get BITMAP_SURFACE_PUT_BITS_NATIVE proc address !!", &this->vo_driver, 1 ) )
return NULL;
+ st = vdp_get_proc_address( vdp_device, VDP_FUNC_ID_PREEMPTION_CALLBACK_REGISTER, (void*)&vdp_preemption_callback_register );
+ if ( vdpau_init_error( st, "Can't get PREEMPTION_CALLBACK_REGISTER proc address !!", &this->vo_driver, 1 ) )
+ return NULL;
+
+ st = vdp_preemption_callback_register(vdp_device, &vdp_preemption_callback, (void*)this);
+ if ( vdpau_init_error( st, "Can't register preemption callback !!", &this->vo_driver, 1 ) )
+ return NULL;
st = vdp_queue_target_create_x11( vdp_device, this->drawable, &vdp_queue_target );
if ( vdpau_init_error( st, "Can't create presentation queue target !!", &this->vo_driver, 1 ) )
@@ -1816,6 +1915,8 @@ static vo_driver_t *vdpau_open_plugin (video_driver_class_t *class_gen, const vo
this->allocated_surfaces = 0;
+ this->vdp_runtime_nr = 1;
+
return &this->vo_driver;
}
diff --git a/src/xine-engine/accel_vdpau.h b/src/xine-engine/accel_vdpau.h
index e489408c5..99cea4568 100644
--- a/src/xine-engine/accel_vdpau.h
+++ b/src/xine-engine/accel_vdpau.h
@@ -49,6 +49,9 @@ typedef struct {
VdpVideoSurface surface;
VdpChromaType chroma;
+ int vdp_runtime_nr; /* this is used to keep in sync on preemptions */
+ int *current_vdp_runtime_nr;
+
} vdpau_accel_t;
#ifdef __cplusplus