diff options
-rw-r--r-- | src/libvdpau/dpb.c | 31 | ||||
-rw-r--r-- | src/libvdpau/vdpau_h264.c | 22 | ||||
-rw-r--r-- | src/video_out/video_out_vdpau.c | 42 | ||||
-rw-r--r-- | src/xine-engine/accel_vdpau.h | 4 |
4 files changed, 91 insertions, 8 deletions
diff --git a/src/libvdpau/dpb.c b/src/libvdpau/dpb.c index 9aa2f4298..01f147639 100644 --- a/src/libvdpau/dpb.c +++ b/src/libvdpau/dpb.c @@ -240,6 +240,31 @@ int dpb_remove_picture(struct dpb *dpb, struct decoded_picture *rempic) return -1; } +static int dpb_remove_picture_by_img(struct dpb *dpb, vo_frame_t *remimg) +{ + struct decoded_picture *pic = dpb->pictures; + struct decoded_picture *last_pic = NULL; + + if (pic != NULL) + do { + if (pic->img == remimg) { + // FIXME: free the picture.... + + if (last_pic != NULL) + last_pic->next = pic->next; + else + dpb->pictures = pic->next; + free_decoded_picture(pic); + dpb->used--; + return 0; + } + + last_pic = pic; + } while ((pic = pic->next) != NULL); + + return -1; +} + int dpb_remove_picture_by_picnum(struct dpb *dpb, uint32_t picnum) { struct decoded_picture *pic = dpb->pictures; @@ -259,6 +284,12 @@ int dpb_remove_picture_by_picnum(struct dpb *dpb, uint32_t picnum) int dpb_add_picture(struct dpb *dpb, struct decoded_picture *pic, uint32_t num_ref_frames) { + pic->img->lock(pic->img); + if (0 == dpb_remove_picture_by_img(dpb, pic->img)) + fprintf(stderr, "broken stream: current img was already in dpb -- freed it\n"); + else + pic->img->free(pic->img); + int i = 0; struct decoded_picture *last_pic = dpb->pictures; diff --git a/src/libvdpau/vdpau_h264.c b/src/libvdpau/vdpau_h264.c index a8d4093d9..90dc15d67 100644 --- a/src/libvdpau/vdpau_h264.c +++ b/src/libvdpau/vdpau_h264.c @@ -353,6 +353,13 @@ static int vdpau_decoder_init(video_decoder_t *this_gen) img->duration = this->video_step; img->pts = this->curr_pts; + if (this->dangling_img) { + fprintf(stderr, "broken stream: current img wasn't processed -- freeing it\n!"); + this->dangling_img->free(this->dangling_img); + } + this->dangling_img = img; + this->last_img = img; + this->vdpau_accel = (vdpau_accel_t*)img->accel_data; /*VdpBool is_supported; @@ -370,9 +377,6 @@ static int vdpau_decoder_init(video_decoder_t *this_gen) return 0; } } - this->last_img = img; - this->dangling_img = img; - return 1; } @@ -438,6 +442,10 @@ static int vdpau_decoder_render(video_decoder_t *this_gen, VdpBitstreamBuffer *v img->duration = this->video_step; img->pts = this->curr_pts; + if (this->dangling_img) { + fprintf(stderr, "broken stream: current img wasn't processed -- freeing it\n!"); + this->dangling_img->free(this->dangling_img); + } this->dangling_img = img; } @@ -446,8 +454,6 @@ static int vdpau_decoder_render(video_decoder_t *this_gen, VdpBitstreamBuffer *v this->decoder = VDP_INVALID_HANDLE; vdpau_h264_reset(this_gen); this->vdp_runtime_nr = this->vdpau_accel->vdp_runtime_nr; - img->free(img); - img = this->last_img = NULL; return 0; } @@ -471,7 +477,8 @@ static int vdpau_decoder_render(video_decoder_t *this_gen, VdpBitstreamBuffer *v if(status != VDP_STATUS_OK) { xprintf(this->xine, XINE_VERBOSITY_LOG, "vdpau_h264: Decoder failure: %s\n", this->vdpau_accel->vdp_get_error_string(status)); - img->free(img); + if (this->dangling_img) + this->dangling_img->free(this->dangling_img); img = this->last_img = this->dangling_img = NULL; } else { @@ -700,6 +707,8 @@ static void vdpau_h264_reset (video_decoder_t *this_gen) { this->dangling_img->free(this->dangling_img); this->dangling_img = NULL; } + + this->last_img = NULL; } /* @@ -725,7 +734,6 @@ static void vdpau_h264_dispose (video_decoder_t *this_gen) { this->dangling_img = NULL; } - dpb_free_all( &(this->nal_parser->dpb) ); if (this->decoder != VDP_INVALID_HANDLE) { diff --git a/src/video_out/video_out_vdpau.c b/src/video_out/video_out_vdpau.c index 6b25b28c3..af7c33c3b 100644 --- a/src/video_out/video_out_vdpau.c +++ b/src/video_out/video_out_vdpau.c @@ -754,6 +754,7 @@ static vo_frame_t *vdpau_alloc_frame (vo_driver_t *this_gen) frame->vo_frame.dispose = vdpau_frame_dispose; frame->vo_frame.driver = this_gen; + frame->vdpau_accel_data.vo_frame = &frame->vo_frame; frame->vdpau_accel_data.vdp_device = vdp_device; frame->vdpau_accel_data.surface = VDP_INVALID_HANDLE; frame->vdpau_accel_data.chroma = VDP_CHROMA_TYPE_420; @@ -901,10 +902,19 @@ static void vdpau_update_frame_format (vo_driver_t *this_gen, vo_frame_t *frame_ uint32_t width, uint32_t height, double ratio, int format, int flags) { vdpau_driver_t *this = (vdpau_driver_t *) this_gen; - vdpau_frame_t *frame = (vdpau_frame_t *) frame_gen; + vdpau_frame_t *frame = VDPAU_FRAME(frame_gen); VdpChromaType chroma = (flags & VO_CHROMA_422) ? VDP_CHROMA_TYPE_422 : VDP_CHROMA_TYPE_420; + vo_frame_t orig_frame_content; + if (format == XINE_IMGFMT_VDPAU) { + if (frame_gen != &frame->vo_frame) { + /* this is an intercepted frame, so we need to detect and propagate any + * changes on the original vo_frame to all the intercepted frames */ + xine_fast_memcpy(&orig_frame_content, &frame->vo_frame, sizeof (vo_frame_t)); + } + } + /* 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) || (frame->vdpau_accel_data.vdp_runtime_nr != this->vdp_runtime_nr)) { @@ -974,6 +984,36 @@ static void vdpau_update_frame_format (vo_driver_t *this_gen, vo_frame_t *frame_ frame->vdpau_accel_data.color_standard = VDP_COLOR_STANDARD_ITUR_BT_601; frame->ratio = ratio; frame->vo_frame.future_frame = NULL; + + if (format == XINE_IMGFMT_VDPAU) { + if (frame_gen != &frame->vo_frame) { + /* this is an intercepted frame, so we need to detect and propagate any + * changes on the original vo_frame to all the intercepted frames */ + unsigned char *p0 = (unsigned char *)&orig_frame_content; + unsigned char *p1 = (unsigned char *)&frame->vo_frame; + int i; + for (i = 0; i < sizeof (vo_frame_t); i++) { + if (*p0 != *p1) { + /* propagate the change */ + vo_frame_t *f = frame_gen; + while (f->next) { + /* serveral restrictions apply when intercepting VDPAU frames. So let's check + * the intercepted frames before modifing them and fail otherwise. */ + unsigned char *p = (unsigned char *)f + i; + if (*p != *p0) { + xprintf(this->xine, XINE_VERBOSITY_DEBUG, "vdpau_update_frame_format: a post plugin violates the restrictions on intercepting VDPAU frames\n"); + _x_abort(); + } + + *p = *p1; + f = f->next; + } + } + p0++; + p1++; + } + } + } } diff --git a/src/xine-engine/accel_vdpau.h b/src/xine-engine/accel_vdpau.h index 92a46e46f..7ddc5e21f 100644 --- a/src/xine-engine/accel_vdpau.h +++ b/src/xine-engine/accel_vdpau.h @@ -38,6 +38,7 @@ extern "C" { typedef struct { + vo_frame_t *vo_frame; VdpDevice vdp_device; @@ -56,6 +57,9 @@ typedef struct { } vdpau_accel_t; +#define VDPAU_DATA(frame_gen) ((frame_gen) ? (vdpau_accel_t *)(frame_gen)->accel_data : (vdpau_accel_t *)0) +#define VDPAU_FRAME(frame_gen) ((frame_gen) ? (vdpau_accel_t *)VDPAU_DATA(frame_gen)->vo_frame : (vdpau_frame_t *)0) + #ifdef __cplusplus } #endif |