summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/libvdpau/dpb.c31
-rw-r--r--src/libvdpau/vdpau_h264.c22
-rw-r--r--src/video_out/video_out_vdpau.c42
-rw-r--r--src/xine-engine/accel_vdpau.h4
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