[vlc-devel] [PATCH 39/42] vdpau: video surface picture copy

Rémi Denis-Courmont remi at remlab.net
Fri Jun 28 20:30:27 CEST 2013


This will be used for deinterlacing.
---
 modules/hw/vdpau/chroma.c    | 13 +++++----
 modules/hw/vdpau/picture.c   | 65 ++++++++++++++++++++++++++++++++++++--------
 modules/hw/vdpau/vlc_vdpau.h | 18 ++++++++++--
 3 files changed, 77 insertions(+), 19 deletions(-)

diff --git a/modules/hw/vdpau/chroma.c b/modules/hw/vdpau/chroma.c
index e7d85d0..7149cb8 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..a0d221b 100644
--- a/modules/hw/vdpau/picture.c
+++ b/modules/hw/vdpau/picture.c
@@ -33,31 +33,74 @@
 
 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;
 }
+
+picture_t *vlc_vdp_video_copy(picture_t *src)
+{
+    picture_t *dst = picture_NewFromFormat(&src->format);
+    if (unlikely(dst == NULL))
+        return NULL;
+    picture_CopyProperties(dst, src);
+
+    vlc_vdp_video_field_t *field = src->context;
+    vlc_vdp_video_frame_t *frame = field->frame;
+
+    field = malloc(sizeof (*field));
+    if (unlikely(field == NULL))
+    {
+        picture_Release(dst);
+        return NULL;
+    }
+
+    assert(dst->context == NULL);
+    dst->context = field;
+
+    field->destroy = SurfaceDestroy;
+    field->frame = frame;
+
+    atomic_fetch_add(&frame->refs, 1);
+    return dst;
+}
diff --git a/modules/hw/vdpau/vlc_vdpau.h b/modules/hw/vdpau/vlc_vdpau.h
index c013b99..b086b7d 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 a VDPAU video surface as VLC picture.
+ */
+picture_t *vlc_vdp_video_copy(picture_t *);
 #endif
-- 
1.8.3.1




More information about the vlc-devel mailing list