[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