[vlc-commits] vdpau: video surface picture copy

Rémi Denis-Courmont git at videolan.org
Sun Jul 7 20:13:41 CEST 2013


vlc | branch: master | Rémi Denis-Courmont <remi at remlab.net> | Tue Jun 25 22:16:01 2013 +0300| [dd638a1a6002a177ec8f492cb87e9ec88aede946] | committer: Rémi Denis-Courmont

vdpau: video surface picture copy

This will be used for deinterlacing.

> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=dd638a1a6002a177ec8f492cb87e9ec88aede946
---

 modules/hw/vdpau/chroma.c    |   13 ++++++----
 modules/hw/vdpau/picture.c   |   56 +++++++++++++++++++++++++++++++++---------
 modules/hw/vdpau/vlc_vdpau.h |   18 +++++++++++---
 3 files changed, 68 insertions(+), 19 deletions(-)

diff --git a/modules/hw/vdpau/chroma.c b/modules/hw/vdpau/chroma.c
index bd7e512..99e9b61 100644
--- a/modules/hw/vdpau/chroma.c
+++ b/modules/hw/vdpau/chroma.c
@@ -125,7 +125,8 @@ error:
 static picture_t *VideoExport(filter_t *filter, picture_t *src, picture_t *dst)
 {
     filter_sys_t *sys = filter->p_sys;
-    vlc_vdp_video_t *psys = src->context;
+    vlc_vdp_video_field_t *field = src->context;
+    vlc_vdp_video_frame_t *psys = field->frame;
     VdpStatus err;
     VdpVideoSurface surface = psys->surface;
     void *planes[3];
@@ -228,14 +229,16 @@ error:
 static picture_t *VideoPassthrough(filter_t *filter, picture_t *src)
 {
     filter_sys_t *sys = filter->p_sys;
-    vlc_vdp_video_t *psys = src->context;
+    vlc_vdp_video_field_t *field = src->context;
 
-    if (unlikely(psys == NULL))
+    if (unlikely(field == NULL))
     {
         msg_Err(filter, "corrupt VDPAU video surface");
         return NULL;
     }
 
+    vlc_vdp_video_frame_t *psys = field->frame;
+
     /* Corner case: different VDPAU instances decoding and rendering */
     if (psys->vdp != sys->vdp)
     {
@@ -258,8 +261,8 @@ static picture_t *VideoPassthrough(filter_t *filter, picture_t *src)
 
 static inline VdpVideoSurface picture_GetVideoSurface(const picture_t *pic)
 {
-    vlc_vdp_video_t *psys = pic->context;
-    return psys->surface;
+    vlc_vdp_video_field_t *field = pic->context;
+    return field->frame->surface;
 }
 
 static picture_t *MixerRender(filter_t *filter, picture_t *src)
diff --git a/modules/hw/vdpau/picture.c b/modules/hw/vdpau/picture.c
index bcd4fd2..37dce53 100644
--- a/modules/hw/vdpau/picture.c
+++ b/modules/hw/vdpau/picture.c
@@ -33,31 +33,65 @@
 
 static void SurfaceDestroy(void *opaque)
 {
-    vlc_vdp_video_t *ctx = opaque;
+    vlc_vdp_video_field_t *field = opaque;
+    vlc_vdp_video_frame_t *frame = field->frame;
     VdpStatus err;
 
-    err = vdp_video_surface_destroy(ctx->vdp, ctx->surface);
+    /* Destroy field-specific infos */
+    free(field);
+
+    if (atomic_fetch_sub(&frame->refs, 1) != 1)
+        return;
+
+    /* Destroy frame (video surface) */
+    err = vdp_video_surface_destroy(frame->vdp, frame->surface);
     if (err != VDP_STATUS_OK)
         fprintf(stderr, "video surface destruction failure: %s\n",
-                vdp_get_error_string(ctx->vdp, err));
-    vdp_release_x11(ctx->vdp);
-    free(ctx);
+                vdp_get_error_string(frame->vdp, err));
+    vdp_release_x11(frame->vdp);
+    free(frame);
 }
 
 VdpStatus vlc_vdp_video_attach(vdp_t *vdp, VdpVideoSurface surface,
                                picture_t *pic)
 {
-    vlc_vdp_video_t *ctx = malloc(sizeof (*ctx));
-    if (unlikely(ctx == NULL))
+    vlc_vdp_video_field_t *field = malloc(sizeof (*field));
+    vlc_vdp_video_frame_t *frame = malloc(sizeof (*frame));
+
+    if (unlikely(field == NULL || frame == NULL))
     {
+        free(frame);
+        free(field);
         vdp_video_surface_destroy(vdp, surface);
         return VDP_STATUS_RESOURCES;
     }
 
-    ctx->destroy = SurfaceDestroy;
-    ctx->surface = surface;
-    ctx->vdp = vdp_hold_x11(vdp, &ctx->device);
     assert(pic->context == NULL);
-    pic->context = ctx;
+    pic->context = field;
+
+    field->destroy = SurfaceDestroy;
+    field->frame = frame;
+
+    atomic_init(&frame->refs, 1);
+    frame->surface = surface;
+    frame->vdp = vdp_hold_x11(vdp, &frame->device);
+    return VDP_STATUS_OK;
+}
+
+VdpStatus vlc_vdp_video_copy(picture_t *restrict dst, picture_t *restrict src)
+{
+    vlc_vdp_video_field_t *fold = src->context;
+    vlc_vdp_video_frame_t *frame = fold->frame;
+    vlc_vdp_video_field_t *fnew = malloc(sizeof (*fnew));
+    if (unlikely(fnew == NULL))
+        return VDP_STATUS_RESOURCES;
+
+    assert(dst->context == NULL);
+    dst->context = fnew;
+
+    fnew->destroy = SurfaceDestroy;
+    fnew->frame = frame;
+
+    atomic_fetch_add(&frame->refs, 1);
     return VDP_STATUS_OK;
 }
diff --git a/modules/hw/vdpau/vlc_vdpau.h b/modules/hw/vdpau/vlc_vdpau.h
index a1499fc..f792298 100644
--- a/modules/hw/vdpau/vlc_vdpau.h
+++ b/modules/hw/vdpau/vlc_vdpau.h
@@ -207,6 +207,7 @@ void vdp_release_x11(vdp_t *);
 # include <stdbool.h>
 # include <vlc_common.h>
 # include <vlc_fourcc.h>
+# include <vlc_atomic.h>
 
 /** Converts VLC YUV format to VDPAU chroma type and YCbCr format */
 static inline
@@ -245,13 +246,19 @@ struct picture_sys_t
     vdp_t *vdp;
 };
 
-typedef struct vlc_vdp_video
+typedef struct vlc_vdp_video_frame
 {
-    void (*destroy)(void *); /* must be first @ref picture_Release() */
     VdpVideoSurface surface;
     VdpDevice device;
     vdp_t *vdp;
-} vlc_vdp_video_t;
+    atomic_uintptr_t refs;
+} vlc_vdp_video_frame_t;
+
+typedef struct vlc_vdp_video_field
+{
+    void (*destroy)(void *); /* must be first @ref picture_Release() */
+    vlc_vdp_video_frame_t *frame;
+} vlc_vdp_video_field_t;
 
 /**
  * Attaches a VDPAU video surface as context of a VLC picture.
@@ -259,4 +266,9 @@ typedef struct vlc_vdp_video
  * it will be destroyed at the same time as the picture it was attached to.
  */
 VdpStatus vlc_vdp_video_attach(vdp_t *, VdpVideoSurface, picture_t *);
+
+/**
+ * Copies the VDPAU video surface from a VLC picture into another VLC picture.
+ */
+VdpStatus vlc_vdp_video_copy(picture_t *dst, picture_t *src);
 #endif



More information about the vlc-commits mailing list